Skip to content
17 changes: 17 additions & 0 deletions packages/create-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import gradient from 'gradient-string';
import path from 'path';
import pc from 'picocolors';
import { fileURLToPath } from 'url';
import { setupTailwind } from './tailwind-setup.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
Expand All @@ -30,6 +31,7 @@ interface AppConfig {
name: string;
platforms: string[];
directory: string;
useTailwind: boolean;
}

function toPascalCase(str: string): string {
Expand Down Expand Up @@ -300,10 +302,20 @@ async function gatherProjectInfo(
platforms = platformsResult as string[];
}

const tailwindResult = await p.confirm({
message: 'Do you want to use Tailwind CSS?',
initialValue: false,
});

if (p.isCancel(tailwindResult)) {
throw new Error('cancelled');
}

return {
name: name as string,
platforms: platforms as string[],
directory: options?.directory || process.cwd(),
useTailwind: tailwindResult,
};
}

Expand Down Expand Up @@ -338,6 +350,11 @@ async function scaffoldProject(config: AppConfig): Promise<void> {

await cleanupUnselectedPlatforms(targetPath, config.platforms);

if (config.useTailwind) {
spinner.message('Setting up Tailwind CSS...');
await setupTailwind(targetPath);
}

spinner.stop('Project created successfully!');
}

Expand Down
158 changes: 158 additions & 0 deletions packages/create-app/src/tailwind-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import fs from 'fs-extra';
import path from 'path';

export async function setupTailwind(targetPath: string): Promise<void> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we delete the comments, function names are pretty self-explanatory already

// Update package.json with Tailwind dependencies
await updatePackageJsonForTailwind(targetPath);

// Create postcss.config.js
await createPostCSSConfig(targetPath);

// Create tailwind.config.ts
await createTailwindConfig(targetPath);

// Update App.css with Tailwind directives
await updateAppCSSForTailwind(targetPath);

// Update App.tsx with Tailwind classes
await updateAppTSXForTailwind(targetPath);
}

async function updatePackageJsonForTailwind(targetPath: string): Promise<void> {
const packageJsonPath = path.join(targetPath, 'package.json');
const packageJson = await fs.readJson(packageJsonPath);

// Add Tailwind CSS dependencies
packageJson.devDependencies = {
...packageJson.devDependencies,
tailwindcss: '^3',
'@lynx-js/tailwind-preset': 'latest',
};

await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
}

async function createPostCSSConfig(targetPath: string): Promise<void> {
const postCSSConfig = `export default {
plugins: {
tailwindcss: {},
},
};
`;

const configPath = path.join(targetPath, 'postcss.config.js');
await fs.writeFile(configPath, postCSSConfig, 'utf8');
}

async function createTailwindConfig(targetPath: string): Promise<void> {
const tailwindConfig = `import lynxPreset from '@lynx-js/tailwind-preset';

export default {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
presets: [lynxPreset],
};
`;

const configPath = path.join(targetPath, 'tailwind.config.ts');
await fs.writeFile(configPath, tailwindConfig, 'utf8');
}

async function updateAppCSSForTailwind(targetPath: string): Promise<void> {
const appCSSContent = `@tailwind base;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's leave a comment or let's open an issue to properly implement templates where each template which be used based on the option because it's much harder to maintain this kind flow that is added here.

@tailwind components;
@tailwind utilities;
:root {
background-color: #000;
--color-text: #fff;
}
.Background {
position: fixed;
background: radial-gradient(
71.43% 62.3% at 46.43% 36.43%,
rgba(18, 229, 229, 0) 15%,
rgba(239, 155, 255, 0.3) 56.35%,
#ff6448 100%
);
box-shadow: 0px 12.93px 28.74px 0px #ffd28db2 inset;
border-radius: 50%;
width: 200vw;
height: 200vw;
top: -60vw;
left: -14.27vw;
transform: rotate(15.25deg);
}

`;

const appCSSPath = path.join(targetPath, 'src', 'App.css');
await fs.writeFile(appCSSPath, appCSSContent, 'utf8');
}

async function updateAppTSXForTailwind(targetPath: string): Promise<void> {
const appTSXContent = `
import { useCallback, useEffect, useState } from '@lynx-js/react';
Comment thread
HimanshuKumarDutt094 marked this conversation as resolved.
Outdated

import './App.css';
import arrow from './assets/arrow.png';
import lynxLogo from './assets/lynx-logo.png';
import reactLynxLogo from './assets/react-logo.png';

export function App(props: { onRender?: () => void }) {
const [alterLogo, setAlterLogo] = useState(false);

useEffect(() => {
console.info('Hello, ReactLynx');
}, []);
props.onRender?.();

const onTap = useCallback(() => {
'background only';
setAlterLogo((prevAlterLogo) => !prevAlterLogo);
}, []);

return (
<view>
<view className="fixed Background rounded-full w-[200vw] h-[200vw] -top-[60vw] -left-[14.27vw] rotate-[15.25deg]" />
<view className="relative min-h-screen flex flex-col items-center justify-center">
<view className="flex-[5] flex flex-col items-center justify-center z-[100]">
<view
className="flex flex-col items-center justify-center mb-2"
bindtap={onTap}
>
{alterLogo ? (
<image
src={reactLynxLogo}
className="w-[100px] h-[100px] animate-spin duration-[20s]"
/>
) : (
<image
src={lynxLogo}
className="w-[100px] h-[100px] animate-pulse duration-500"
/>
)}
</view>
<text className="text-[36px] font-bold text-white">React</text>
<text className="italic text-[22px] font-semibold mb-2 text-white">
on Lynx
</text>
</view>
<view className="flex flex-col items-center justify-center">
<image src={arrow} className="w-6 h-6" />
<text className="text-[20px] text-white/85 my-[15px]">
Tap the logo and have fun!
</text>
<text className="text-xs my-[5px] text-white/65">
Edit
<text className="italic text-white/85">{' src/App.tsx '}</text>
to see updates!
</text>
</view>
<view className="flex-1" />
</view>
</view>
);
} `;

const appTSXPath = path.join(targetPath, 'src', 'App.tsx');
await fs.writeFile(appTSXPath, appTSXContent, 'utf8');
}