@lucaismyname/create-l1-stack 0.0.18 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +78 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucaismyname/create-l1-stack",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/index.js CHANGED
@@ -77,6 +77,39 @@ const THEME_PRESETS = {
77
77
  },
78
78
  }
79
79
 
80
+ const ICON_SETS = {
81
+ lucide: {
82
+ dependency: { name: 'lucide-react', version: '^0.563.0' },
83
+ tsx: `import * as React from "react"\nimport {\n Check,\n ChevronDown,\n ChevronUp,\n Database,\n NotebookPen,\n Rocket,\n Server,\n} from "lucide-react"\n\ntype IconProps = React.SVGProps<SVGSVGElement>\n\nexport const Icons = {\n Check: (props: IconProps) => <Check {...props} />,\n ChevronDown: (props: IconProps) => <ChevronDown {...props} />,\n ChevronUp: (props: IconProps) => <ChevronUp {...props} />,\n Database: (props: IconProps) => <Database {...props} />,\n NotebookPen: (props: IconProps) => <NotebookPen {...props} />,\n Rocket: (props: IconProps) => <Rocket {...props} />,\n Server: (props: IconProps) => <Server {...props} />,\n}\n`,
84
+ jsx: `import {\n Check,\n ChevronDown,\n ChevronUp,\n Database,\n NotebookPen,\n Rocket,\n Server,\n} from "lucide-react"\n\nexport const Icons = {\n Check: (props) => <Check {...props} />,\n ChevronDown: (props) => <ChevronDown {...props} />,\n ChevronUp: (props) => <ChevronUp {...props} />,\n Database: (props) => <Database {...props} />,\n NotebookPen: (props) => <NotebookPen {...props} />,\n Rocket: (props) => <Rocket {...props} />,\n Server: (props) => <Server {...props} />,\n}\n`,
85
+ },
86
+ heroicons: {
87
+ dependency: { name: '@heroicons/react', version: '^2.2.0' },
88
+ tsx: `import * as React from "react"\nimport {\n CheckIcon,\n ChevronDownIcon,\n ChevronUpIcon,\n CircleStackIcon,\n PencilSquareIcon,\n RocketLaunchIcon,\n ServerIcon,\n} from "@heroicons/react/24/outline"\n\ntype IconProps = React.SVGProps<SVGSVGElement>\n\nexport const Icons = {\n Check: (props: IconProps) => <CheckIcon {...props} />,\n ChevronDown: (props: IconProps) => <ChevronDownIcon {...props} />,\n ChevronUp: (props: IconProps) => <ChevronUpIcon {...props} />,\n Database: (props: IconProps) => <CircleStackIcon {...props} />,\n NotebookPen: (props: IconProps) => <PencilSquareIcon {...props} />,\n Rocket: (props: IconProps) => <RocketLaunchIcon {...props} />,\n Server: (props: IconProps) => <ServerIcon {...props} />,\n}\n`,
89
+ jsx: `import {\n CheckIcon,\n ChevronDownIcon,\n ChevronUpIcon,\n CircleStackIcon,\n PencilSquareIcon,\n RocketLaunchIcon,\n ServerIcon,\n} from "@heroicons/react/24/outline"\n\nexport const Icons = {\n Check: (props) => <CheckIcon {...props} />,\n ChevronDown: (props) => <ChevronDownIcon {...props} />,\n ChevronUp: (props) => <ChevronUpIcon {...props} />,\n Database: (props) => <CircleStackIcon {...props} />,\n NotebookPen: (props) => <PencilSquareIcon {...props} />,\n Rocket: (props) => <RocketLaunchIcon {...props} />,\n Server: (props) => <ServerIcon {...props} />,\n}\n`,
90
+ },
91
+ tabler: {
92
+ dependency: { name: '@tabler/icons-react', version: '^3.31.0' },
93
+ tsx: `import * as React from "react"\nimport {\n IconCheck,\n IconChevronDown,\n IconChevronUp,\n IconDatabase,\n IconNotebook,\n IconRocket,\n IconServer,\n} from "@tabler/icons-react"\n\ntype IconProps = React.SVGProps<SVGSVGElement>\n\nexport const Icons = {\n Check: (props: IconProps) => <IconCheck {...props} />,\n ChevronDown: (props: IconProps) => <IconChevronDown {...props} />,\n ChevronUp: (props: IconProps) => <IconChevronUp {...props} />,\n Database: (props: IconProps) => <IconDatabase {...props} />,\n NotebookPen: (props: IconProps) => <IconNotebook {...props} />,\n Rocket: (props: IconProps) => <IconRocket {...props} />,\n Server: (props: IconProps) => <IconServer {...props} />,\n}\n`,
94
+ jsx: `import {\n IconCheck,\n IconChevronDown,\n IconChevronUp,\n IconDatabase,\n IconNotebook,\n IconRocket,\n IconServer,\n} from "@tabler/icons-react"\n\nexport const Icons = {\n Check: (props) => <IconCheck {...props} />,\n ChevronDown: (props) => <IconChevronDown {...props} />,\n ChevronUp: (props) => <IconChevronUp {...props} />,\n Database: (props) => <IconDatabase {...props} />,\n NotebookPen: (props) => <IconNotebook {...props} />,\n Rocket: (props) => <IconRocket {...props} />,\n Server: (props) => <IconServer {...props} />,\n}\n`,
95
+ },
96
+ radix: {
97
+ dependency: { name: '@radix-ui/react-icons', version: '^1.3.2' },
98
+ tsx: `import * as React from "react"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "@radix-ui/react-icons"\n\ntype IconProps = React.SVGProps<SVGSVGElement>\n\nconst FallbackIcon = (props: IconProps) => (\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>\n <path d="M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7l3-7z" />\n </svg>\n)\n\nexport const Icons = {\n Check: (props: IconProps) => <CheckIcon {...props} />,\n ChevronDown: (props: IconProps) => <ChevronDownIcon {...props} />,\n ChevronUp: (props: IconProps) => <ChevronUpIcon {...props} />,\n Database: (props: IconProps) => <FallbackIcon {...props} />,\n NotebookPen: (props: IconProps) => <FallbackIcon {...props} />,\n Rocket: (props: IconProps) => <FallbackIcon {...props} />,\n Server: (props: IconProps) => <FallbackIcon {...props} />,\n}\n`,
99
+ jsx: `import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "@radix-ui/react-icons"\n\nconst FallbackIcon = (props) => (\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>\n <path d="M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7l3-7z" />\n </svg>\n)\n\nexport const Icons = {\n Check: (props) => <CheckIcon {...props} />,\n ChevronDown: (props) => <ChevronDownIcon {...props} />,\n ChevronUp: (props) => <ChevronUpIcon {...props} />,\n Database: (props) => <FallbackIcon {...props} />,\n NotebookPen: (props) => <FallbackIcon {...props} />,\n Rocket: (props) => <FallbackIcon {...props} />,\n Server: (props) => <FallbackIcon {...props} />,\n}\n`,
100
+ },
101
+ feather: {
102
+ dependency: { name: 'react-feather', version: '^2.0.10' },
103
+ tsx: `import * as React from "react"\nimport { Check, ChevronDown, ChevronUp, Database, Edit3, Send, Server } from "react-feather"\n\ntype IconProps = React.SVGProps<SVGSVGElement>\n\nexport const Icons = {\n Check: (props: IconProps) => <Check {...props} />,\n ChevronDown: (props: IconProps) => <ChevronDown {...props} />,\n ChevronUp: (props: IconProps) => <ChevronUp {...props} />,\n Database: (props: IconProps) => <Database {...props} />,\n NotebookPen: (props: IconProps) => <Edit3 {...props} />,\n Rocket: (props: IconProps) => <Send {...props} />,\n Server: (props: IconProps) => <Server {...props} />,\n}\n`,
104
+ jsx: `import { Check, ChevronDown, ChevronUp, Database, Edit3, Send, Server } from "react-feather"\n\nexport const Icons = {\n Check: (props) => <Check {...props} />,\n ChevronDown: (props) => <ChevronDown {...props} />,\n ChevronUp: (props) => <ChevronUp {...props} />,\n Database: (props) => <Database {...props} />,\n NotebookPen: (props) => <Edit3 {...props} />,\n Rocket: (props) => <Send {...props} />,\n Server: (props) => <Server {...props} />,\n}\n`,
105
+ },
106
+ materialSymbols: {
107
+ dependency: { name: 'react-material-symbols', version: '^4.1.0' },
108
+ tsx: `import * as React from "react"\nimport { MaterialSymbol } from "react-material-symbols"\n\ntype IconProps = React.SVGProps<SVGSVGElement>\n\ntype MaterialProps = IconProps & { icon: string }\n\nconst MS = ({ icon, className }: MaterialProps) => (\n <MaterialSymbol icon={icon} className={className} size={24} fill={0} grade={0} opticalSize={24} />\n)\n\nexport const Icons = {\n Check: (props: IconProps) => <MS icon="check" {...props} />,\n ChevronDown: (props: IconProps) => <MS icon="keyboard_arrow_down" {...props} />,\n ChevronUp: (props: IconProps) => <MS icon="keyboard_arrow_up" {...props} />,\n Database: (props: IconProps) => <MS icon="database" {...props} />,\n NotebookPen: (props: IconProps) => <MS icon="edit_note" {...props} />,\n Rocket: (props: IconProps) => <MS icon="rocket_launch" {...props} />,\n Server: (props: IconProps) => <MS icon="dns" {...props} />,\n}\n`,
109
+ jsx: `import { MaterialSymbol } from "react-material-symbols"\n\nconst MS = ({ icon, className }) => (\n <MaterialSymbol icon={icon} className={className} size={24} fill={0} grade={0} opticalSize={24} />\n)\n\nexport const Icons = {\n Check: (props) => <MS icon="check" {...props} />,\n ChevronDown: (props) => <MS icon="keyboard_arrow_down" {...props} />,\n ChevronUp: (props) => <MS icon="keyboard_arrow_up" {...props} />,\n Database: (props) => <MS icon="database" {...props} />,\n NotebookPen: (props) => <MS icon="edit_note" {...props} />,\n Rocket: (props) => <MS icon="rocket_launch" {...props} />,\n Server: (props) => <MS icon="dns" {...props} />,\n}\n`,
110
+ },
111
+ }
112
+
80
113
  function updateCssVarInBlock(css, blockSelector, varName, value) {
81
114
  const blockRe = new RegExp(`(${blockSelector}\\s*\\{)([\\s\\S]*?)(\\})`, 'm')
82
115
  const match = css.match(blockRe)
@@ -112,6 +145,33 @@ async function applyPrimaryTheme(targetDir, preset) {
112
145
  }
113
146
  }
114
147
 
148
+ async function applyIconSet(targetDir, language, iconSetKey) {
149
+ const iconSet = ICON_SETS[iconSetKey] ?? ICON_SETS.lucide
150
+
151
+ const pkgJsonPath = path.join(targetDir, 'package.json')
152
+ const pkg = await fse.readJson(pkgJsonPath)
153
+ pkg.dependencies ??= {}
154
+
155
+ for (const key of Object.keys(ICON_SETS)) {
156
+ const depName = ICON_SETS[key]?.dependency?.name
157
+ if (depName && pkg.dependencies[depName]) {
158
+ delete pkg.dependencies[depName]
159
+ }
160
+ }
161
+
162
+ pkg.dependencies[iconSet.dependency.name] = iconSet.dependency.version
163
+ await fse.writeJson(pkgJsonPath, pkg, { spaces: 2 })
164
+
165
+ const iconFile = path.join(
166
+ targetDir,
167
+ 'src',
168
+ 'components',
169
+ language === 'ts' ? 'icons.tsx' : 'icons.jsx'
170
+ )
171
+ await fs.mkdir(path.dirname(iconFile), { recursive: true })
172
+ await fs.writeFile(iconFile, language === 'ts' ? iconSet.tsx : iconSet.jsx, 'utf8')
173
+ }
174
+
115
175
  function toKebabCaseName(input) {
116
176
  return input
117
177
  .trim()
@@ -257,6 +317,23 @@ async function main() {
257
317
  process.exit(0)
258
318
  }
259
319
 
320
+ const iconSet = await select({
321
+ message: 'Icon set',
322
+ options: [
323
+ { value: 'lucide', label: 'Lucide (default)' },
324
+ { value: 'heroicons', label: 'HeroIcons' },
325
+ { value: 'materialSymbols', label: 'Material Symbols' },
326
+ { value: 'tabler', label: 'Tabler Icons' },
327
+ { value: 'radix', label: 'Radix Icons' },
328
+ { value: 'feather', label: 'Feather Icons' },
329
+ ],
330
+ initialValue: 'lucide',
331
+ })
332
+ if (isCancel(iconSet)) {
333
+ cancel('Cancelled')
334
+ process.exit(0)
335
+ }
336
+
260
337
  const targetDir = path.resolve(process.cwd(), projectName)
261
338
  // NOTE: npm downloads the CLI package before prompts run.
262
339
  // To avoid downloading both templates, we fetch only the chosen template from npm.
@@ -309,6 +386,7 @@ async function main() {
309
386
  }
310
387
 
311
388
  await applyPrimaryTheme(targetDir, THEME_PRESETS[primaryColor] ?? THEME_PRESETS.slate)
389
+ await applyIconSet(targetDir, language, iconSet)
312
390
 
313
391
  // Update package name
314
392
  const pkgJsonPath = path.join(targetDir, 'package.json')