@bloomneo/uikit 1.5.0
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.
- package/CHANGELOG.md +222 -0
- package/LICENSE +21 -0
- package/README.md +513 -0
- package/bin/commands/build.js +232 -0
- package/bin/commands/bundle.js +587 -0
- package/bin/commands/create.js +768 -0
- package/bin/commands/deploy.js +533 -0
- package/bin/commands/generate.js +673 -0
- package/bin/commands/optimize.js +198 -0
- package/bin/commands/prerender.js +306 -0
- package/bin/commands/serve.js +216 -0
- package/bin/templates/fbca/README.md.template +130 -0
- package/bin/templates/fbca/docs/QUICKSTART_FBCA.md +368 -0
- package/bin/templates/fbca/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/fbca/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/fbca/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/fbca/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/fbca/package.json.template +41 -0
- package/bin/templates/fbca/public/favicon.svg +10 -0
- package/bin/templates/fbca/public/hero_fbca.svg +1 -0
- package/bin/templates/fbca/src/utils/asset.ts +6 -0
- package/bin/templates/fbca/src/web/App.tsx.template +20 -0
- package/bin/templates/fbca/src/web/features/auth/pages/index.tsx.template +157 -0
- package/bin/templates/fbca/src/web/features/docs/pages/[...slug].tsx.template +83 -0
- package/bin/templates/fbca/src/web/features/gallery/hooks/useGallery.ts.template +74 -0
- package/bin/templates/fbca/src/web/features/gallery/pages/index.tsx.template +136 -0
- package/bin/templates/fbca/src/web/features/main/components/CTASection.tsx.template +43 -0
- package/bin/templates/fbca/src/web/features/main/pages/About.tsx.template +374 -0
- package/bin/templates/fbca/src/web/features/main/pages/index.tsx.template +214 -0
- package/bin/templates/fbca/src/web/index.html.template +15 -0
- package/bin/templates/fbca/src/web/lib/page-router.tsx.template +134 -0
- package/bin/templates/fbca/src/web/main.tsx.template +14 -0
- package/bin/templates/fbca/src/web/shared/components/Footer.tsx.template +57 -0
- package/bin/templates/fbca/src/web/shared/components/Header.tsx.template +91 -0
- package/bin/templates/fbca/src/web/shared/components/SEO.tsx.template +24 -0
- package/bin/templates/fbca/src/web/shared/components/index.ts.template +3 -0
- package/bin/templates/fbca/src/web/shared/hooks/useSEO.ts.template +85 -0
- package/bin/templates/fbca/src/web/shared/utils/asset.ts +6 -0
- package/bin/templates/fbca/src/web/styles/index.css.template +8 -0
- package/bin/templates/fbca/src/web/utils/asset.ts +6 -0
- package/bin/templates/fbca/tsconfig.json.template +32 -0
- package/bin/templates/fbca/tsconfig.node.json.template +10 -0
- package/bin/templates/fbca/vite.config.ts.template +38 -0
- package/bin/templates/generate/component/component.tsx.template +79 -0
- package/bin/templates/generate/component/index.ts.template +2 -0
- package/bin/templates/generate/component/types.ts.template +58 -0
- package/bin/templates/generate/feature/index.ts.template +14 -0
- package/bin/templates/generate/feature/list-page.tsx.template +34 -0
- package/bin/templates/generate/feature/main-component.tsx.template +37 -0
- package/bin/templates/generate/feature/main-page.tsx.template +30 -0
- package/bin/templates/generate/feature/types.ts.template +34 -0
- package/bin/templates/generate/hook/hook.ts.template +35 -0
- package/bin/templates/generate/index.css.template +10 -0
- package/bin/templates/generate/main.tsx.template +10 -0
- package/bin/templates/generate/page/index.ts.template +2 -0
- package/bin/templates/generate/page/page.tsx.template +86 -0
- package/bin/templates/generate/theme/README.md +31 -0
- package/bin/templates/generate/theme/theme.js.template +155 -0
- package/bin/templates/multi/README.md.template +120 -0
- package/bin/templates/multi/docs/QUICKSTART_MULTI.md +334 -0
- package/bin/templates/multi/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/multi/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/multi/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/multi/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/multi/index.html.template +58 -0
- package/bin/templates/multi/package.json.template +35 -0
- package/bin/templates/multi/public/favicon.svg +10 -0
- package/bin/templates/multi/public/hero_multi.svg +1 -0
- package/bin/templates/multi/src/App.tsx.template +92 -0
- package/bin/templates/multi/src/components/Footer.tsx.template +58 -0
- package/bin/templates/multi/src/components/Header.tsx.template +103 -0
- package/bin/templates/multi/src/components/SEO.tsx.template +19 -0
- package/bin/templates/multi/src/components/index.ts.template +3 -0
- package/bin/templates/multi/src/hooks/useSEO.ts.template +38 -0
- package/bin/templates/multi/src/index.css.template +7 -0
- package/bin/templates/multi/src/main.tsx.template +14 -0
- package/bin/templates/multi/src/pages/About.tsx.template +276 -0
- package/bin/templates/multi/src/pages/Components.tsx.template +288 -0
- package/bin/templates/multi/src/pages/Contact.tsx.template +348 -0
- package/bin/templates/multi/src/pages/Dashboard.tsx.template +306 -0
- package/bin/templates/multi/src/pages/ErrorPage.tsx.template +37 -0
- package/bin/templates/multi/src/pages/Home.tsx.template +201 -0
- package/bin/templates/multi/src/pages/Login.tsx.template +148 -0
- package/bin/templates/multi/src/pages/Themes.tsx.template +207 -0
- package/bin/templates/multi/src/router.tsx.template +34 -0
- package/bin/templates/multi/src/utils/asset.ts +6 -0
- package/bin/templates/multi/tsconfig.json.template +30 -0
- package/bin/templates/multi/tsconfig.node.json +22 -0
- package/bin/templates/multi/vite.config.ts.template +36 -0
- package/bin/templates/single/README.md.template +131 -0
- package/bin/templates/single/docs/QUICKSTART_SINGLE.md +259 -0
- package/bin/templates/single/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/single/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/single/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/single/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/single/index.html.template +37 -0
- package/bin/templates/single/package.json.template +34 -0
- package/bin/templates/single/public/favicon.svg +10 -0
- package/bin/templates/single/public/hero.svg +1 -0
- package/bin/templates/single/src/App.tsx.template +233 -0
- package/bin/templates/single/src/index.css.template +7 -0
- package/bin/templates/single/src/main.tsx.template +14 -0
- package/bin/templates/single/src/styles/fonts.css +99 -0
- package/bin/templates/single/src/utils/asset.ts +6 -0
- package/bin/templates/single/tsconfig.json +31 -0
- package/bin/templates/single/tsconfig.node.json +22 -0
- package/bin/templates/single/vite.config.ts.template +36 -0
- package/bin/templates/spa/README.md.template +105 -0
- package/bin/templates/spa/components/SEO.tsx.template +19 -0
- package/bin/templates/spa/docs/QUICKSTART_SPA.md +300 -0
- package/bin/templates/spa/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/spa/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/spa/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/spa/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/spa/hooks/useSEO.ts.template +38 -0
- package/bin/templates/spa/index.html.template +58 -0
- package/bin/templates/spa/package.json.template +35 -0
- package/bin/templates/spa/public/favicon.svg +15 -0
- package/bin/templates/spa/public/hero_spa.svg +1 -0
- package/bin/templates/spa/src/App.tsx.template +659 -0
- package/bin/templates/spa/src/index.css.template +7 -0
- package/bin/templates/spa/src/main.tsx.template +14 -0
- package/bin/templates/spa/src/utils/asset.ts +6 -0
- package/bin/templates/spa/tsconfig.json.template +30 -0
- package/bin/templates/spa/tsconfig.node.json +22 -0
- package/bin/templates/spa/vite.config.ts.template +36 -0
- package/bin/uikit.js +133 -0
- package/cookbook/README.md +20 -0
- package/cookbook/crud-page.tsx +99 -0
- package/cookbook/dashboard.tsx +89 -0
- package/cookbook/delete-flow.tsx +59 -0
- package/cookbook/login.tsx +85 -0
- package/cookbook/settings.tsx +113 -0
- package/dist/Combination-C0DFrmJW.js +674 -0
- package/dist/Combination-C0DFrmJW.js.map +1 -0
- package/dist/accordion.js +284 -0
- package/dist/accordion.js.map +1 -0
- package/dist/admin.js +429 -0
- package/dist/admin.js.map +1 -0
- package/dist/alert.js +67 -0
- package/dist/alert.js.map +1 -0
- package/dist/auth.js +178 -0
- package/dist/auth.js.map +1 -0
- package/dist/avatar.js +249 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.js +40 -0
- package/dist/badge.js.map +1 -0
- package/dist/blank.js +80 -0
- package/dist/blank.js.map +1 -0
- package/dist/breadcrumb.js +104 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/button.js +50 -0
- package/dist/button.js.map +1 -0
- package/dist/calendar.js +2785 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card.js +91 -0
- package/dist/card.js.map +1 -0
- package/dist/check-DXouwtzp.js +12 -0
- package/dist/check-DXouwtzp.js.map +1 -0
- package/dist/checkbox.js +268 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chevron-down-BORJtX8F.js +14 -0
- package/dist/chevron-down-BORJtX8F.js.map +1 -0
- package/dist/chevron-left-C1pkx4AF.js +14 -0
- package/dist/chevron-left-C1pkx4AF.js.map +1 -0
- package/dist/chevron-right-pz9eCjj-.js +14 -0
- package/dist/chevron-right-pz9eCjj-.js.map +1 -0
- package/dist/circle-DHOdTDQh.js +14 -0
- package/dist/circle-DHOdTDQh.js.map +1 -0
- package/dist/collapsible.js +35 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/command.js +481 -0
- package/dist/command.js.map +1 -0
- package/dist/confirm-dialog.js +129 -0
- package/dist/confirm-dialog.js.map +1 -0
- package/dist/container.js +334 -0
- package/dist/container.js.map +1 -0
- package/dist/createLucideIcon-B45kRl5r.js +80 -0
- package/dist/createLucideIcon-B45kRl5r.js.map +1 -0
- package/dist/data-table.js +574 -0
- package/dist/data-table.js.map +1 -0
- package/dist/detail-page.js +454 -0
- package/dist/detail-page.js.map +1 -0
- package/dist/dialog.js +137 -0
- package/dist/dialog.js.map +1 -0
- package/dist/dropdown-menu.js +424 -0
- package/dist/dropdown-menu.js.map +1 -0
- package/dist/ellipsis-BhAoKPVk.js +16 -0
- package/dist/ellipsis-BhAoKPVk.js.map +1 -0
- package/dist/empty-state.js +54 -0
- package/dist/empty-state.js.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/errors.js.map +1 -0
- package/dist/eye-DDKoW0KS.js +46 -0
- package/dist/eye-DDKoW0KS.js.map +1 -0
- package/dist/fonts/caveat-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-cyrillic-700-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-700-normal.woff2 +0 -0
- package/dist/fonts/caveat-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-cyrillic-ext-700-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-400-normal.woff +0 -0
- package/dist/fonts/caveat-latin-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-700-normal.woff +0 -0
- package/dist/fonts/caveat-latin-700-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/caveat-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/caveat-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-400-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-400-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-600-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-600-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-700-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-700-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/crimson-text-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-vietnamese-600-normal.woff +0 -0
- package/dist/fonts/crimson-text-vietnamese-600-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-vietnamese-700-normal.woff +0 -0
- package/dist/fonts/crimson-text-vietnamese-700-normal.woff2 +0 -0
- package/dist/fonts/dm-serif-display-latin-400-normal.woff +0 -0
- package/dist/fonts/dm-serif-display-latin-400-normal.woff2 +0 -0
- package/dist/fonts/dm-serif-display-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/dm-serif-display-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-400-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-400-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-700-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-700-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-500-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-600-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-500-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-600-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-400-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-500-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-600-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/montserrat-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-vietnamese-500-normal.woff +0 -0
- package/dist/fonts/montserrat-vietnamese-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-vietnamese-600-normal.woff +0 -0
- package/dist/fonts/montserrat-vietnamese-600-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-cyrillic-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-cyrillic-500-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-500-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-vietnamese-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-vietnamese-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-devanagari-400-normal.woff +0 -0
- package/dist/fonts/poppins-devanagari-400-normal.woff2 +0 -0
- package/dist/fonts/poppins-devanagari-500-normal.woff +0 -0
- package/dist/fonts/poppins-devanagari-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-devanagari-600-normal.woff +0 -0
- package/dist/fonts/poppins-devanagari-600-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-400-normal.woff +0 -0
- package/dist/fonts/poppins-latin-400-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-500-normal.woff +0 -0
- package/dist/fonts/poppins-latin-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-600-normal.woff +0 -0
- package/dist/fonts/poppins-latin-600-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/poppins-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/poppins-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/poppins-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/rubik-arabic-400-normal.woff +0 -0
- package/dist/fonts/rubik-arabic-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-arabic-500-normal.woff +0 -0
- package/dist/fonts/rubik-arabic-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-500-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-ext-500-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-ext-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-hebrew-400-normal.woff +0 -0
- package/dist/fonts/rubik-hebrew-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-hebrew-500-normal.woff +0 -0
- package/dist/fonts/rubik-hebrew-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-400-normal.woff +0 -0
- package/dist/fonts/rubik-latin-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-500-normal.woff +0 -0
- package/dist/fonts/rubik-latin-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/rubik-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/rubik-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-greek-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-greek-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-latin-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-latin-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-400-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-600-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-700-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/space-grotesk-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-vietnamese-600-normal.woff +0 -0
- package/dist/fonts/space-grotesk-vietnamese-600-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-vietnamese-700-normal.woff +0 -0
- package/dist/fonts/space-grotesk-vietnamese-700-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-400-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-400-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-500-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-500-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/work-sans-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/work-sans-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/work-sans-vietnamese-500-normal.woff +0 -0
- package/dist/fonts/work-sans-vietnamese-500-normal.woff2 +0 -0
- package/dist/footer.js +308 -0
- package/dist/footer.js.map +1 -0
- package/dist/form-field.js +69 -0
- package/dist/form-field.js.map +1 -0
- package/dist/form.js +732 -0
- package/dist/form.js.map +1 -0
- package/dist/format.js +112 -0
- package/dist/format.js.map +1 -0
- package/dist/fouc.js +28 -0
- package/dist/fouc.js.map +1 -0
- package/dist/header.js +289 -0
- package/dist/header.js.map +1 -0
- package/dist/hooks.js +13 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hover-card.js +210 -0
- package/dist/hover-card.js.map +1 -0
- package/dist/index-0ioNhtNM.js +11 -0
- package/dist/index-0ioNhtNM.js.map +1 -0
- package/dist/index-1QHKgw6D.js +55 -0
- package/dist/index-1QHKgw6D.js.map +1 -0
- package/dist/index-B6sSWi7l.js +747 -0
- package/dist/index-B6sSWi7l.js.map +1 -0
- package/dist/index-BCjJQGh8.js +71 -0
- package/dist/index-BCjJQGh8.js.map +1 -0
- package/dist/index-BGQepRFJ.js +28 -0
- package/dist/index-BGQepRFJ.js.map +1 -0
- package/dist/index-BVRIAMfe.js +37 -0
- package/dist/index-BVRIAMfe.js.map +1 -0
- package/dist/index-BY7PeRJA.js +145 -0
- package/dist/index-BY7PeRJA.js.map +1 -0
- package/dist/index-BZPx6jYI.js +9 -0
- package/dist/index-BZPx6jYI.js.map +1 -0
- package/dist/index-Ba4eHUBD.js +243 -0
- package/dist/index-Ba4eHUBD.js.map +1 -0
- package/dist/index-Bke1qZdk.js +35 -0
- package/dist/index-Bke1qZdk.js.map +1 -0
- package/dist/index-C0UREtMP.js +60 -0
- package/dist/index-C0UREtMP.js.map +1 -0
- package/dist/index-CCKe-Mpx.js +7 -0
- package/dist/index-CCKe-Mpx.js.map +1 -0
- package/dist/index-DFZozV_h.js +69 -0
- package/dist/index-DFZozV_h.js.map +1 -0
- package/dist/index-DFi6WydO.js +180 -0
- package/dist/index-DFi6WydO.js.map +1 -0
- package/dist/index-DQH6odE9.js +83 -0
- package/dist/index-DQH6odE9.js.map +1 -0
- package/dist/index-EO5flKM3.js +119 -0
- package/dist/index-EO5flKM3.js.map +1 -0
- package/dist/index-Lf7yDOXW.js +615 -0
- package/dist/index-Lf7yDOXW.js.map +1 -0
- package/dist/index-dhIqEbxW.js +1541 -0
- package/dist/index-dhIqEbxW.js.map +1 -0
- package/dist/index-pWhlqjff.js +32 -0
- package/dist/index-pWhlqjff.js.map +1 -0
- package/dist/index-rKs9bXHr.js +7 -0
- package/dist/index-rKs9bXHr.js.map +1 -0
- package/dist/index-xqkGMOJ8.js +14 -0
- package/dist/index-xqkGMOJ8.js.map +1 -0
- package/dist/index.js +247 -0
- package/dist/index.js.map +1 -0
- package/dist/input.js +22 -0
- package/dist/input.js.map +1 -0
- package/dist/label.js +36 -0
- package/dist/label.js.map +1 -0
- package/dist/layout-wrapper.js +208 -0
- package/dist/layout-wrapper.js.map +1 -0
- package/dist/llms.txt +1140 -0
- package/dist/menu-DBhEanGo.js +16 -0
- package/dist/menu-DBhEanGo.js.map +1 -0
- package/dist/menubar.js +565 -0
- package/dist/menubar.js.map +1 -0
- package/dist/mobile.js +183 -0
- package/dist/mobile.js.map +1 -0
- package/dist/motion.js +119 -0
- package/dist/motion.js.map +1 -0
- package/dist/page-header.js +47 -0
- package/dist/page-header.js.map +1 -0
- package/dist/page.js +214 -0
- package/dist/page.js.map +1 -0
- package/dist/pagination.js +121 -0
- package/dist/pagination.js.map +1 -0
- package/dist/platform.js +194 -0
- package/dist/platform.js.map +1 -0
- package/dist/popover.js +263 -0
- package/dist/popover.js.map +1 -0
- package/dist/popup.js +335 -0
- package/dist/popup.js.map +1 -0
- package/dist/progress.js +108 -0
- package/dist/progress.js.map +1 -0
- package/dist/radio-group.js +272 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/safe-area.js +42 -0
- package/dist/safe-area.js.map +1 -0
- package/dist/search-CpUwRnG-.js +15 -0
- package/dist/search-CpUwRnG-.js.map +1 -0
- package/dist/select.js +985 -0
- package/dist/select.js.map +1 -0
- package/dist/separator.js +45 -0
- package/dist/separator.js.map +1 -0
- package/dist/sheet.js +127 -0
- package/dist/sheet.js.map +1 -0
- package/dist/skeleton.js +16 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/slider.js +485 -0
- package/dist/slider.js.map +1 -0
- package/dist/sonner.js +52 -0
- package/dist/sonner.js.map +1 -0
- package/dist/styles/fonts.css +253 -0
- package/dist/styles.css +2 -0
- package/dist/switch.js +155 -0
- package/dist/switch.js.map +1 -0
- package/dist/tab-bar.js +110 -0
- package/dist/tab-bar.js.map +1 -0
- package/dist/table.js +115 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.js +218 -0
- package/dist/tabs.js.map +1 -0
- package/dist/textarea.js +19 -0
- package/dist/textarea.js.map +1 -0
- package/dist/theme-provider.js +154 -0
- package/dist/theme-provider.js.map +1 -0
- package/dist/themes.js +873 -0
- package/dist/themes.js.map +1 -0
- package/dist/toast.js +63 -0
- package/dist/toast.js.map +1 -0
- package/dist/toggle.js +70 -0
- package/dist/toggle.js.map +1 -0
- package/dist/tooltip.js +375 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/types/App.d.ts +3 -0
- package/dist/types/App.d.ts.map +1 -0
- package/dist/types/components/layouts/admin.d.ts +117 -0
- package/dist/types/components/layouts/admin.d.ts.map +1 -0
- package/dist/types/components/layouts/auth.d.ts +17 -0
- package/dist/types/components/layouts/auth.d.ts.map +1 -0
- package/dist/types/components/layouts/blank.d.ts +63 -0
- package/dist/types/components/layouts/blank.d.ts.map +1 -0
- package/dist/types/components/layouts/layout-wrapper.d.ts +130 -0
- package/dist/types/components/layouts/layout-wrapper.d.ts.map +1 -0
- package/dist/types/components/layouts/mobile.d.ts +91 -0
- package/dist/types/components/layouts/mobile.d.ts.map +1 -0
- package/dist/types/components/layouts/page.d.ts +181 -0
- package/dist/types/components/layouts/page.d.ts.map +1 -0
- package/dist/types/components/layouts/popup.d.ts +100 -0
- package/dist/types/components/layouts/popup.d.ts.map +1 -0
- package/dist/types/components/sections/container.d.ts +79 -0
- package/dist/types/components/sections/container.d.ts.map +1 -0
- package/dist/types/components/sections/footer.d.ts +128 -0
- package/dist/types/components/sections/footer.d.ts.map +1 -0
- package/dist/types/components/sections/header.d.ts +72 -0
- package/dist/types/components/sections/header.d.ts.map +1 -0
- package/dist/types/components/sections/safe-area.d.ts +46 -0
- package/dist/types/components/sections/safe-area.d.ts.map +1 -0
- package/dist/types/components/sections/tab-bar.d.ts +61 -0
- package/dist/types/components/sections/tab-bar.d.ts.map +1 -0
- package/dist/types/components/ui/accordion.d.ts +8 -0
- package/dist/types/components/ui/accordion.d.ts.map +1 -0
- package/dist/types/components/ui/alert.d.ts +10 -0
- package/dist/types/components/ui/alert.d.ts.map +1 -0
- package/dist/types/components/ui/avatar.d.ts +7 -0
- package/dist/types/components/ui/avatar.d.ts.map +1 -0
- package/dist/types/components/ui/badge.d.ts +10 -0
- package/dist/types/components/ui/badge.d.ts.map +1 -0
- package/dist/types/components/ui/breadcrumb.d.ts +12 -0
- package/dist/types/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/types/components/ui/button.d.ts +11 -0
- package/dist/types/components/ui/button.d.ts.map +1 -0
- package/dist/types/components/ui/calendar.d.ts +9 -0
- package/dist/types/components/ui/calendar.d.ts.map +1 -0
- package/dist/types/components/ui/card.d.ts +10 -0
- package/dist/types/components/ui/card.d.ts.map +1 -0
- package/dist/types/components/ui/checkbox.d.ts +5 -0
- package/dist/types/components/ui/checkbox.d.ts.map +1 -0
- package/dist/types/components/ui/collapsible.d.ts +6 -0
- package/dist/types/components/ui/collapsible.d.ts.map +1 -0
- package/dist/types/components/ui/command.d.ts +19 -0
- package/dist/types/components/ui/command.d.ts.map +1 -0
- package/dist/types/components/ui/confirm-dialog.d.ts +72 -0
- package/dist/types/components/ui/confirm-dialog.d.ts.map +1 -0
- package/dist/types/components/ui/data-table.d.ts +211 -0
- package/dist/types/components/ui/data-table.d.ts.map +1 -0
- package/dist/types/components/ui/detail-page.d.ts +119 -0
- package/dist/types/components/ui/detail-page.d.ts.map +1 -0
- package/dist/types/components/ui/dialog.d.ts +16 -0
- package/dist/types/components/ui/dialog.d.ts.map +1 -0
- package/dist/types/components/ui/dropdown-menu.d.ts +26 -0
- package/dist/types/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/types/components/ui/empty-state.d.ts +30 -0
- package/dist/types/components/ui/empty-state.d.ts.map +1 -0
- package/dist/types/components/ui/form-field.d.ts +57 -0
- package/dist/types/components/ui/form-field.d.ts.map +1 -0
- package/dist/types/components/ui/form.d.ts +185 -0
- package/dist/types/components/ui/form.d.ts.map +1 -0
- package/dist/types/components/ui/hover-card.d.ts +7 -0
- package/dist/types/components/ui/hover-card.d.ts.map +1 -0
- package/dist/types/components/ui/input.d.ts +4 -0
- package/dist/types/components/ui/input.d.ts.map +1 -0
- package/dist/types/components/ui/label.d.ts +5 -0
- package/dist/types/components/ui/label.d.ts.map +1 -0
- package/dist/types/components/ui/menubar.d.ts +27 -0
- package/dist/types/components/ui/menubar.d.ts.map +1 -0
- package/dist/types/components/ui/motion.d.ts +130 -0
- package/dist/types/components/ui/motion.d.ts.map +1 -0
- package/dist/types/components/ui/page-header.d.ts +45 -0
- package/dist/types/components/ui/page-header.d.ts.map +1 -0
- package/dist/types/components/ui/pagination.d.ts +14 -0
- package/dist/types/components/ui/pagination.d.ts.map +1 -0
- package/dist/types/components/ui/popover.d.ts +8 -0
- package/dist/types/components/ui/popover.d.ts.map +1 -0
- package/dist/types/components/ui/progress.d.ts +5 -0
- package/dist/types/components/ui/progress.d.ts.map +1 -0
- package/dist/types/components/ui/radio-group.d.ts +6 -0
- package/dist/types/components/ui/radio-group.d.ts.map +1 -0
- package/dist/types/components/ui/select.d.ts +16 -0
- package/dist/types/components/ui/select.d.ts.map +1 -0
- package/dist/types/components/ui/separator.d.ts +5 -0
- package/dist/types/components/ui/separator.d.ts.map +1 -0
- package/dist/types/components/ui/sheet.d.ts +14 -0
- package/dist/types/components/ui/sheet.d.ts.map +1 -0
- package/dist/types/components/ui/skeleton.d.ts +3 -0
- package/dist/types/components/ui/skeleton.d.ts.map +1 -0
- package/dist/types/components/ui/slider.d.ts +5 -0
- package/dist/types/components/ui/slider.d.ts.map +1 -0
- package/dist/types/components/ui/sonner.d.ts +4 -0
- package/dist/types/components/ui/sonner.d.ts.map +1 -0
- package/dist/types/components/ui/switch.d.ts +5 -0
- package/dist/types/components/ui/switch.d.ts.map +1 -0
- package/dist/types/components/ui/table.d.ts +11 -0
- package/dist/types/components/ui/table.d.ts.map +1 -0
- package/dist/types/components/ui/tabs.d.ts +8 -0
- package/dist/types/components/ui/tabs.d.ts.map +1 -0
- package/dist/types/components/ui/textarea.d.ts +4 -0
- package/dist/types/components/ui/textarea.d.ts.map +1 -0
- package/dist/types/components/ui/toast.d.ts +70 -0
- package/dist/types/components/ui/toast.d.ts.map +1 -0
- package/dist/types/components/ui/toggle.d.ts +10 -0
- package/dist/types/components/ui/toggle.d.ts.map +1 -0
- package/dist/types/components/ui/tooltip.d.ts +8 -0
- package/dist/types/components/ui/tooltip.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +14 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useApi.d.ts +38 -0
- package/dist/types/hooks/useApi.d.ts.map +1 -0
- package/dist/types/hooks/useBreakpoint.d.ts +35 -0
- package/dist/types/hooks/useBreakpoint.d.ts.map +1 -0
- package/dist/types/hooks/useDataTable.d.ts +59 -0
- package/dist/types/hooks/useDataTable.d.ts.map +1 -0
- package/dist/types/hooks/useMediaQuery.d.ts +12 -0
- package/dist/types/hooks/useMediaQuery.d.ts.map +1 -0
- package/dist/types/hooks/useStorage.d.ts +35 -0
- package/dist/types/hooks/useStorage.d.ts.map +1 -0
- package/dist/types/index.d.ts +75 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/lib/errors.d.ts +37 -0
- package/dist/types/lib/errors.d.ts.map +1 -0
- package/dist/types/lib/format.d.ts +80 -0
- package/dist/types/lib/format.d.ts.map +1 -0
- package/dist/types/lib/fouc.d.ts +64 -0
- package/dist/types/lib/fouc.d.ts.map +1 -0
- package/dist/types/lib/platform.d.ts +156 -0
- package/dist/types/lib/platform.d.ts.map +1 -0
- package/dist/types/lib/utils.d.ts +14 -0
- package/dist/types/lib/utils.d.ts.map +1 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/main.d.ts.map +1 -0
- package/dist/types/themes/index.d.ts +499 -0
- package/dist/types/themes/index.d.ts.map +1 -0
- package/dist/types/themes/presets/base.d.ts +108 -0
- package/dist/types/themes/presets/base.d.ts.map +1 -0
- package/dist/types/themes/presets/elegant.d.ts +108 -0
- package/dist/types/themes/presets/elegant.d.ts.map +1 -0
- package/dist/types/themes/presets/metro.d.ts +114 -0
- package/dist/types/themes/presets/metro.d.ts.map +1 -0
- package/dist/types/themes/presets/studio.d.ts +115 -0
- package/dist/types/themes/presets/studio.d.ts.map +1 -0
- package/dist/types/themes/presets/vivid.d.ts +115 -0
- package/dist/types/themes/presets/vivid.d.ts.map +1 -0
- package/dist/types/themes/theme-provider.d.ts +122 -0
- package/dist/types/themes/theme-provider.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +813 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/uikit.css +1 -0
- package/dist/useDataTable-CPiBpEg-.js +254 -0
- package/dist/useDataTable-CPiBpEg-.js.map +1 -0
- package/dist/utils-CwJPJKOE.js +2278 -0
- package/dist/utils-CwJPJKOE.js.map +1 -0
- package/dist/utils.js +5 -0
- package/dist/utils.js.map +1 -0
- package/dist/wrapper.js +13 -0
- package/dist/wrapper.js.map +1 -0
- package/dist/x-BxwubQiM.js +15 -0
- package/dist/x-BxwubQiM.js.map +1 -0
- package/examples/README.md +18 -0
- package/examples/button.tsx +16 -0
- package/examples/confirm-dialog.tsx +44 -0
- package/examples/data-table.tsx +35 -0
- package/examples/dialog.tsx +34 -0
- package/examples/empty-state.tsx +13 -0
- package/examples/form-field.tsx +22 -0
- package/examples/format.tsx +19 -0
- package/examples/page-header.tsx +17 -0
- package/examples/skeleton.tsx +12 -0
- package/examples/theme-provider.tsx +33 -0
- package/examples/toast.tsx +32 -0
- package/examples/use-breakpoint.tsx +17 -0
- package/llms.txt +1140 -0
- package/package.json +430 -0
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview UIKit Generate Command - Frontend feature scaffolding
|
|
3
|
+
* @description Generates new frontend features using FBCA pattern with UIKit components
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate a new frontend feature using TypeScript templates
|
|
15
|
+
*/
|
|
16
|
+
export async function generateFeature(type, name, options) {
|
|
17
|
+
const theme = options && options.theme || 'base';
|
|
18
|
+
console.log(`šØ Generating ${type}: "${name}" with ${theme} theme...\n`);
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Handle theme generation separately (doesn't need features directory)
|
|
22
|
+
if (type === 'theme') {
|
|
23
|
+
await generateThemeFeature(name, options);
|
|
24
|
+
console.log(`ā
Generated ${type} "${name}" successfully!`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Validate feature name (allow forward slashes for nested paths)
|
|
29
|
+
if (!name || !/^[a-zA-Z0-9-_/]+$/.test(name)) {
|
|
30
|
+
console.error('ā Invalid feature name. Use only letters, numbers, hyphens, underscores, and forward slashes.');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check if we're in a project directory
|
|
35
|
+
const currentDir = process.cwd();
|
|
36
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
40
|
+
if (!packageJson.dependencies || !packageJson.dependencies['@bloomneo/uikit']) {
|
|
41
|
+
console.error('ā Not in a UIKit project directory. Run this from project root.');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
console.error('ā No package.json found. Run this from project root.');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check if we're in FBCA structure (src/web/features or src/features)
|
|
50
|
+
let featuresPath = path.join(currentDir, 'src/web/features');
|
|
51
|
+
let isFBCA = true;
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
await fs.access(featuresPath);
|
|
55
|
+
} catch {
|
|
56
|
+
// Try alternative path
|
|
57
|
+
featuresPath = path.join(currentDir, 'src/features');
|
|
58
|
+
try {
|
|
59
|
+
await fs.access(featuresPath);
|
|
60
|
+
} catch {
|
|
61
|
+
// Create features directory in preferred location
|
|
62
|
+
featuresPath = path.join(currentDir, 'src/web/features');
|
|
63
|
+
await fs.mkdir(featuresPath, { recursive: true });
|
|
64
|
+
console.log(`š Created features directory: ${featuresPath}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check if feature already exists
|
|
69
|
+
const featurePath = path.join(featuresPath, name);
|
|
70
|
+
try {
|
|
71
|
+
await fs.access(featurePath);
|
|
72
|
+
console.error(`ā Feature "${name}" already exists.`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
} catch {
|
|
75
|
+
// Feature doesn't exist, good to proceed
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Generate feature based on type
|
|
79
|
+
if (type === 'page') {
|
|
80
|
+
await generatePageFeature(featuresPath, name, options);
|
|
81
|
+
} else if (type === 'component') {
|
|
82
|
+
await generateComponentFeature(featuresPath, name, options);
|
|
83
|
+
} else if (type === 'hook') {
|
|
84
|
+
await generateHookFeature(featuresPath, name, options);
|
|
85
|
+
} else if (type === 'feature') {
|
|
86
|
+
await generateFullFeature(featuresPath, name, options);
|
|
87
|
+
} else {
|
|
88
|
+
console.error(`ā Unknown type "${type}". Use: page, component, hook, feature, or theme`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`ā
Generated ${type} "${name}" successfully!`);
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('ā Failed to generate feature:', error.message);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Generate a page component following FBCA convention with nested path support
|
|
102
|
+
*/
|
|
103
|
+
async function generatePageFeature(featuresPath, name, options) {
|
|
104
|
+
// Parse feature name and nested path
|
|
105
|
+
// Examples: "dashboard" ā feature: dashboard, path: index.tsx
|
|
106
|
+
// "dashboard/new" ā feature: dashboard, path: new.tsx
|
|
107
|
+
// "dashboard/new/apple" ā feature: dashboard, path: new/apple.tsx
|
|
108
|
+
|
|
109
|
+
const pathParts = name.split('/');
|
|
110
|
+
const featureName = pathParts[0];
|
|
111
|
+
const nestedPath = pathParts.slice(1);
|
|
112
|
+
|
|
113
|
+
let targetDir;
|
|
114
|
+
|
|
115
|
+
if (nestedPath.length === 0) {
|
|
116
|
+
// Simple page goes to main feature - don't create the original feature directory
|
|
117
|
+
targetDir = path.join(featuresPath, 'main', 'pages');
|
|
118
|
+
} else {
|
|
119
|
+
// Nested path creates its own feature
|
|
120
|
+
const featurePath = path.join(featuresPath, featureName);
|
|
121
|
+
const pagesPath = path.join(featurePath, 'pages');
|
|
122
|
+
|
|
123
|
+
// Create the full nested directory structure
|
|
124
|
+
targetDir = pagesPath;
|
|
125
|
+
if (nestedPath.length > 1) {
|
|
126
|
+
// Create nested directories for deep paths like "new/apple"
|
|
127
|
+
const nestedDirs = nestedPath.slice(0, -1).join('/');
|
|
128
|
+
targetDir = path.join(pagesPath, nestedDirs);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
133
|
+
|
|
134
|
+
const templatesPath = path.join(__dirname, '../templates/generate/page');
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
// Determine the page file name
|
|
138
|
+
let pageFileName;
|
|
139
|
+
if (nestedPath.length === 0) {
|
|
140
|
+
// Simple feature name like "dashboard" ā goes to main/pages/dashboard.tsx
|
|
141
|
+
pageFileName = `${featureName}.tsx`;
|
|
142
|
+
} else {
|
|
143
|
+
// Nested path like "dashboard/new" ā new.tsx or "dashboard/new/apple" ā apple.tsx
|
|
144
|
+
pageFileName = `${nestedPath[nestedPath.length - 1]}.tsx`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Generate the page component
|
|
148
|
+
await generateFromTemplate(templatesPath, 'page.tsx.template', targetDir, pageFileName, featureName, options);
|
|
149
|
+
|
|
150
|
+
const relativePath = nestedPath.length === 0
|
|
151
|
+
? `main/pages/${featureName}.tsx`
|
|
152
|
+
: `${featureName}/pages/${nestedPath.join('/')}.tsx`;
|
|
153
|
+
|
|
154
|
+
console.log(`š Created: src/web/features/${relativePath}`);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error(`ā Failed to generate page: ${error.message}`);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Generate a reusable component with shared/feature logic
|
|
163
|
+
*/
|
|
164
|
+
async function generateComponentFeature(featuresPath, name, options) {
|
|
165
|
+
// Parse component name and feature path
|
|
166
|
+
// Examples: "button" ā shared/components/Button.tsx
|
|
167
|
+
// "blog/post-card" ā blog/components/PostCard.tsx
|
|
168
|
+
|
|
169
|
+
const pathParts = name.split('/');
|
|
170
|
+
const isFeatureSpecific = pathParts.length > 1;
|
|
171
|
+
|
|
172
|
+
let targetDir;
|
|
173
|
+
let componentName;
|
|
174
|
+
let relativePath;
|
|
175
|
+
|
|
176
|
+
if (isFeatureSpecific) {
|
|
177
|
+
// Feature-specific component like "blog/post-card"
|
|
178
|
+
const featureName = pathParts[0];
|
|
179
|
+
const componentBaseName = pathParts[pathParts.length - 1];
|
|
180
|
+
componentName = componentBaseName.split('-').map(part =>
|
|
181
|
+
part.charAt(0).toUpperCase() + part.slice(1)
|
|
182
|
+
).join('');
|
|
183
|
+
|
|
184
|
+
const featurePath = path.join(featuresPath, featureName);
|
|
185
|
+
targetDir = path.join(featurePath, 'components');
|
|
186
|
+
relativePath = `${featureName}/components/${componentName}.tsx`;
|
|
187
|
+
} else {
|
|
188
|
+
// Shared component like "button"
|
|
189
|
+
componentName = name.split('-').map(part =>
|
|
190
|
+
part.charAt(0).toUpperCase() + part.slice(1)
|
|
191
|
+
).join('');
|
|
192
|
+
|
|
193
|
+
// Go up from features to web, then to shared/components
|
|
194
|
+
const webPath = path.dirname(featuresPath);
|
|
195
|
+
targetDir = path.join(webPath, 'shared', 'components');
|
|
196
|
+
relativePath = `shared/components/${componentName}.tsx`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
200
|
+
|
|
201
|
+
const templatesPath = path.join(__dirname, '../templates/generate/component');
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
// Generate component only - pass componentName as the feature name for template replacement
|
|
205
|
+
const templateOptions = { ...options, componentName: componentName };
|
|
206
|
+
await generateComponentFromTemplate(templatesPath, 'component.tsx.template', targetDir, `${componentName}.tsx`, componentName, templateOptions);
|
|
207
|
+
|
|
208
|
+
const displayPath = isFeatureSpecific
|
|
209
|
+
? `src/web/features/${relativePath}`
|
|
210
|
+
: `src/web/${relativePath}`;
|
|
211
|
+
|
|
212
|
+
console.log(`š Created: ${displayPath}`);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
console.error(`ā Failed to generate component: ${error.message}`);
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Generate a custom hook with shared/feature logic
|
|
221
|
+
*/
|
|
222
|
+
async function generateHookFeature(featuresPath, name, options) {
|
|
223
|
+
// Parse hook name and feature path
|
|
224
|
+
// Examples: "sample" ā shared/hooks/useSharedSample.ts
|
|
225
|
+
// "greeting/welcome" ā greeting/hooks/useWelcome.ts
|
|
226
|
+
|
|
227
|
+
const pathParts = name.split('/');
|
|
228
|
+
const isFeatureSpecific = pathParts.length > 1;
|
|
229
|
+
|
|
230
|
+
let targetDir;
|
|
231
|
+
let hookName;
|
|
232
|
+
let relativePath;
|
|
233
|
+
|
|
234
|
+
if (isFeatureSpecific) {
|
|
235
|
+
// Feature-specific hook like "greeting/welcome"
|
|
236
|
+
const featureName = pathParts[0];
|
|
237
|
+
const hookBaseName = pathParts[pathParts.length - 1];
|
|
238
|
+
hookName = 'use' + hookBaseName.split('-').map(part =>
|
|
239
|
+
part.charAt(0).toUpperCase() + part.slice(1)
|
|
240
|
+
).join('');
|
|
241
|
+
|
|
242
|
+
const featurePath = path.join(featuresPath, featureName);
|
|
243
|
+
targetDir = path.join(featurePath, 'hooks');
|
|
244
|
+
relativePath = `${featureName}/hooks/${hookName}.ts`;
|
|
245
|
+
} else {
|
|
246
|
+
// Shared hook like "sample"
|
|
247
|
+
hookName = 'useShared' + name.split('-').map(part =>
|
|
248
|
+
part.charAt(0).toUpperCase() + part.slice(1)
|
|
249
|
+
).join('');
|
|
250
|
+
|
|
251
|
+
// Go up from features to web, then to shared/hooks
|
|
252
|
+
const webPath = path.dirname(featuresPath);
|
|
253
|
+
targetDir = path.join(webPath, 'shared', 'hooks');
|
|
254
|
+
relativePath = `shared/hooks/${hookName}.ts`;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
258
|
+
|
|
259
|
+
const templatesPath = path.join(__dirname, '../templates/generate/hook');
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
// Generate hook only - pass hookName for template replacement
|
|
263
|
+
const templateOptions = { ...options, hookName: hookName };
|
|
264
|
+
await generateHookFromTemplate(templatesPath, 'hook.ts.template', targetDir, `${hookName}.ts`, hookName, templateOptions);
|
|
265
|
+
|
|
266
|
+
const displayPath = isFeatureSpecific
|
|
267
|
+
? `src/web/features/${relativePath}`
|
|
268
|
+
: `src/web/${relativePath}`;
|
|
269
|
+
|
|
270
|
+
console.log(`š Created: ${displayPath}`);
|
|
271
|
+
} catch (error) {
|
|
272
|
+
console.error(`ā Failed to generate hook: ${error.message}`);
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Generate a complete feature with hook, component, and page
|
|
279
|
+
*/
|
|
280
|
+
async function generateFullFeature(featuresPath, name, options) {
|
|
281
|
+
const featurePath = path.join(featuresPath, name);
|
|
282
|
+
await fs.mkdir(featurePath, { recursive: true });
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
// Create directory structure
|
|
286
|
+
const pagesPath = path.join(featurePath, 'pages');
|
|
287
|
+
const componentsPath = path.join(featurePath, 'components');
|
|
288
|
+
const hooksPath = path.join(featurePath, 'hooks');
|
|
289
|
+
|
|
290
|
+
await fs.mkdir(pagesPath, { recursive: true });
|
|
291
|
+
await fs.mkdir(componentsPath, { recursive: true });
|
|
292
|
+
await fs.mkdir(hooksPath, { recursive: true });
|
|
293
|
+
|
|
294
|
+
// Component and hook names
|
|
295
|
+
const componentName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
296
|
+
const hookName = `use${componentName}`;
|
|
297
|
+
|
|
298
|
+
// Generate hook
|
|
299
|
+
const hookTemplatesPath = path.join(__dirname, '../templates/generate/hook');
|
|
300
|
+
const hookOptions = { ...options, hookName: hookName };
|
|
301
|
+
await generateHookFromTemplate(hookTemplatesPath, 'hook.ts.template', hooksPath, `${hookName}.ts`, hookName, hookOptions);
|
|
302
|
+
|
|
303
|
+
// Generate component
|
|
304
|
+
const componentTemplatesPath = path.join(__dirname, '../templates/generate/component');
|
|
305
|
+
const componentOptions = { ...options, componentName: componentName };
|
|
306
|
+
await generateComponentFromTemplate(componentTemplatesPath, 'component.tsx.template', componentsPath, `${componentName}.tsx`, componentName, componentOptions);
|
|
307
|
+
|
|
308
|
+
// Generate page (index page for the feature)
|
|
309
|
+
const pageTemplatesPath = path.join(__dirname, '../templates/generate/page');
|
|
310
|
+
await generateFromTemplate(pageTemplatesPath, 'page.tsx.template', pagesPath, 'index.tsx', name, options);
|
|
311
|
+
|
|
312
|
+
console.log(`š Created: src/web/features/${name}/hooks/${hookName}.ts`);
|
|
313
|
+
console.log(`š Created: src/web/features/${name}/components/${componentName}.tsx`);
|
|
314
|
+
console.log(`š Created: src/web/features/${name}/pages/index.tsx`);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error(`ā Failed to generate feature: ${error.message}`);
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Generate component file from template with proper variable replacement
|
|
323
|
+
*/
|
|
324
|
+
async function generateComponentFromTemplate(templatesPath, templateFile, outputPath, outputFile, componentName, options) {
|
|
325
|
+
try {
|
|
326
|
+
// Read template file
|
|
327
|
+
const templatePath = path.join(templatesPath, templateFile);
|
|
328
|
+
const templateContent = await fs.readFile(templatePath, 'utf8');
|
|
329
|
+
|
|
330
|
+
// Get project name from package.json
|
|
331
|
+
const currentDir = process.cwd();
|
|
332
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
333
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
334
|
+
const projectName = packageJson.name || 'my-uikit-project';
|
|
335
|
+
|
|
336
|
+
// Determine theme
|
|
337
|
+
const theme = options && options.theme || 'base';
|
|
338
|
+
|
|
339
|
+
// Convert component name for different cases
|
|
340
|
+
const componentBaseName = componentName.toLowerCase().replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
341
|
+
|
|
342
|
+
// Replace template variables
|
|
343
|
+
const processedContent = templateContent
|
|
344
|
+
.replace(/\{\{componentName\}\}/g, componentBaseName)
|
|
345
|
+
.replace(/\{\{ComponentName\}\}/g, componentName)
|
|
346
|
+
.replace(/\{\{projectName\}\}/g, projectName)
|
|
347
|
+
.replace(/\{\{theme\}\}/g, theme);
|
|
348
|
+
|
|
349
|
+
// Write output file
|
|
350
|
+
const outputFilePath = path.join(outputPath, outputFile);
|
|
351
|
+
await fs.writeFile(outputFilePath, processedContent, 'utf8');
|
|
352
|
+
} catch (error) {
|
|
353
|
+
console.error(`ā Failed to generate ${outputFile} from template ${templateFile}:`, error.message);
|
|
354
|
+
throw error;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Generate hook file from template with proper variable replacement
|
|
360
|
+
*/
|
|
361
|
+
async function generateHookFromTemplate(templatesPath, templateFile, outputPath, outputFile, hookName, options) {
|
|
362
|
+
try {
|
|
363
|
+
// Read template file
|
|
364
|
+
const templatePath = path.join(templatesPath, templateFile);
|
|
365
|
+
const templateContent = await fs.readFile(templatePath, 'utf8');
|
|
366
|
+
|
|
367
|
+
// Get project name from package.json
|
|
368
|
+
const currentDir = process.cwd();
|
|
369
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
370
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
371
|
+
const projectName = packageJson.name || 'my-uikit-project';
|
|
372
|
+
|
|
373
|
+
// Determine theme
|
|
374
|
+
const theme = options && options.theme || 'base';
|
|
375
|
+
|
|
376
|
+
// Replace template variables
|
|
377
|
+
const processedContent = templateContent
|
|
378
|
+
.replace(/\{\{hookName\}\}/g, hookName)
|
|
379
|
+
.replace(/\{\{projectName\}\}/g, projectName)
|
|
380
|
+
.replace(/\{\{theme\}\}/g, theme);
|
|
381
|
+
|
|
382
|
+
// Write output file
|
|
383
|
+
const outputFilePath = path.join(outputPath, outputFile);
|
|
384
|
+
await fs.writeFile(outputFilePath, processedContent, 'utf8');
|
|
385
|
+
} catch (error) {
|
|
386
|
+
console.error(`ā Failed to generate ${outputFile} from template ${templateFile}:`, error.message);
|
|
387
|
+
throw error;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Generate file from template with variable replacement
|
|
393
|
+
*/
|
|
394
|
+
async function generateFromTemplate(templatesPath, templateFile, outputPath, outputFile, featureName, options) {
|
|
395
|
+
try {
|
|
396
|
+
// Read template file
|
|
397
|
+
const templatePath = path.join(templatesPath, templateFile);
|
|
398
|
+
const templateContent = await fs.readFile(templatePath, 'utf8');
|
|
399
|
+
|
|
400
|
+
// Get project name from package.json
|
|
401
|
+
const currentDir = process.cwd();
|
|
402
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
403
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
404
|
+
const projectName = packageJson.name || 'my-uikit-project';
|
|
405
|
+
|
|
406
|
+
// Determine theme
|
|
407
|
+
const theme = options && options.theme || 'base';
|
|
408
|
+
|
|
409
|
+
// Replace template variables
|
|
410
|
+
const processedContent = templateContent
|
|
411
|
+
.replace(/\{\{featureName\}\}/g, featureName)
|
|
412
|
+
.replace(/\{\{FeatureName\}\}/g, featureName.charAt(0).toUpperCase() + featureName.slice(1))
|
|
413
|
+
.replace(/\{\{FEATURE_NAME\}\}/g, featureName.toUpperCase())
|
|
414
|
+
.replace(/\{\{componentName\}\}/g, featureName)
|
|
415
|
+
.replace(/\{\{ComponentName\}\}/g, featureName.charAt(0).toUpperCase() + featureName.slice(1))
|
|
416
|
+
.replace(/\{\{projectName\}\}/g, projectName)
|
|
417
|
+
.replace(/\{\{theme\}\}/g, theme);
|
|
418
|
+
|
|
419
|
+
// Write output file
|
|
420
|
+
const outputFilePath = path.join(outputPath, outputFile);
|
|
421
|
+
await fs.writeFile(outputFilePath, processedContent, 'utf8');
|
|
422
|
+
} catch (error) {
|
|
423
|
+
console.error(`ā Failed to generate ${outputFile} from template ${templateFile}:`, error.message);
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Generate a custom theme file
|
|
429
|
+
*/
|
|
430
|
+
async function generateThemeFeature(name, options) {
|
|
431
|
+
// Validate theme name
|
|
432
|
+
if (!name || !/^[a-zA-Z0-9-_]+$/.test(name)) {
|
|
433
|
+
console.error('ā Invalid theme name. Use only letters, numbers, hyphens, and underscores.');
|
|
434
|
+
process.exit(1);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Check if we're in a project directory
|
|
438
|
+
const currentDir = process.cwd();
|
|
439
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
440
|
+
|
|
441
|
+
try {
|
|
442
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
443
|
+
if (!packageJson.dependencies || !packageJson.dependencies['@bloomneo/uikit']) {
|
|
444
|
+
console.error('ā Not in a UIKit project directory. Run this from project root.');
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
} catch {
|
|
448
|
+
console.error('ā No package.json found. Run this from project root.');
|
|
449
|
+
process.exit(1);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Determine theme directory based on project structure
|
|
453
|
+
let themesPath;
|
|
454
|
+
const isWebStructure = await fs.access(path.join(currentDir, 'src/web')).then(() => true).catch(() => false);
|
|
455
|
+
|
|
456
|
+
if (isWebStructure) {
|
|
457
|
+
// FBCA structure - check for existing themes in web directory
|
|
458
|
+
const possiblePaths = [
|
|
459
|
+
'src/web/themes/presets',
|
|
460
|
+
'src/web/assets/themes/presets',
|
|
461
|
+
];
|
|
462
|
+
|
|
463
|
+
// Try to find existing themes directory
|
|
464
|
+
for (const possiblePath of possiblePaths) {
|
|
465
|
+
const fullPath = path.join(currentDir, possiblePath);
|
|
466
|
+
try {
|
|
467
|
+
await fs.access(fullPath);
|
|
468
|
+
themesPath = fullPath;
|
|
469
|
+
break;
|
|
470
|
+
} catch {
|
|
471
|
+
// Directory doesn't exist, continue searching
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// If no existing themes directory, create the preferred one for FBCA
|
|
476
|
+
if (!themesPath) {
|
|
477
|
+
themesPath = path.join(currentDir, 'src/web/themes/presets');
|
|
478
|
+
await fs.mkdir(themesPath, { recursive: true });
|
|
479
|
+
console.log(`š Created themes directory: ${themesPath}`);
|
|
480
|
+
}
|
|
481
|
+
} else {
|
|
482
|
+
// SPA/Multi structure - check for existing themes in src directory
|
|
483
|
+
const possiblePaths = [
|
|
484
|
+
'src/themes/presets',
|
|
485
|
+
'themes/presets',
|
|
486
|
+
];
|
|
487
|
+
|
|
488
|
+
// Try to find existing themes directory
|
|
489
|
+
for (const possiblePath of possiblePaths) {
|
|
490
|
+
const fullPath = path.join(currentDir, possiblePath);
|
|
491
|
+
try {
|
|
492
|
+
await fs.access(fullPath);
|
|
493
|
+
themesPath = fullPath;
|
|
494
|
+
break;
|
|
495
|
+
} catch {
|
|
496
|
+
// Directory doesn't exist, continue searching
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// If no existing themes directory, create the preferred one for SPA/Multi
|
|
501
|
+
if (!themesPath) {
|
|
502
|
+
themesPath = path.join(currentDir, 'src/themes/presets');
|
|
503
|
+
await fs.mkdir(themesPath, { recursive: true });
|
|
504
|
+
console.log(`š Created themes directory: ${themesPath}`);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Check if theme already exists
|
|
509
|
+
const themeFileName = `theme-${name}.js`;
|
|
510
|
+
const themeFilePath = path.join(themesPath, themeFileName);
|
|
511
|
+
|
|
512
|
+
try {
|
|
513
|
+
await fs.access(themeFilePath);
|
|
514
|
+
console.error(`ā Theme "${name}" already exists at ${themeFilePath}`);
|
|
515
|
+
process.exit(1);
|
|
516
|
+
} catch {
|
|
517
|
+
// Theme doesn't exist, good to proceed
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
try {
|
|
521
|
+
// Generate theme from template
|
|
522
|
+
const templatesPath = path.join(__dirname, '../templates/generate/theme');
|
|
523
|
+
await generateThemeFromTemplate(templatesPath, 'theme.js.template', themesPath, themeFileName, name, options);
|
|
524
|
+
|
|
525
|
+
// Get relative path for display
|
|
526
|
+
const relativePath = path.relative(currentDir, themeFilePath);
|
|
527
|
+
console.log(`š Created: ${relativePath}`);
|
|
528
|
+
|
|
529
|
+
// Auto-update main.tsx with CSS import and theme setting
|
|
530
|
+
// Use the same project structure detection from above
|
|
531
|
+
let stylesGlobalPath, mainTsxPath;
|
|
532
|
+
|
|
533
|
+
if (isWebStructure) {
|
|
534
|
+
// FBCA structure
|
|
535
|
+
stylesGlobalPath = path.join(currentDir, 'src/web/styles/globals.css');
|
|
536
|
+
mainTsxPath = path.join(currentDir, 'src/web/main.tsx');
|
|
537
|
+
} else {
|
|
538
|
+
// SPA/Multi structure
|
|
539
|
+
stylesGlobalPath = path.join(currentDir, 'src/styles/globals.css');
|
|
540
|
+
mainTsxPath = path.join(currentDir, 'src/main.tsx');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
const hasStylesGlobal = await fs.access(stylesGlobalPath).then(() => true).catch(() => false);
|
|
544
|
+
|
|
545
|
+
try {
|
|
546
|
+
// Read main.tsx
|
|
547
|
+
let mainContent = await fs.readFile(mainTsxPath, 'utf8');
|
|
548
|
+
let updated = false;
|
|
549
|
+
|
|
550
|
+
// Add CSS import for globals.css (will be created by bundle command)
|
|
551
|
+
const cssImportPath = './styles/globals.css';
|
|
552
|
+
if (!mainContent.includes(cssImportPath)) {
|
|
553
|
+
// Simple approach: find the index.css import line and add globals.css after it
|
|
554
|
+
const indexCssImport = "import './styles/index.css';";
|
|
555
|
+
if (mainContent.includes(indexCssImport)) {
|
|
556
|
+
mainContent = mainContent.replace(
|
|
557
|
+
indexCssImport,
|
|
558
|
+
`${indexCssImport}\nimport '${cssImportPath}';`
|
|
559
|
+
);
|
|
560
|
+
console.log(`ā
Added import '${cssImportPath}' to main.tsx`);
|
|
561
|
+
updated = true;
|
|
562
|
+
} else {
|
|
563
|
+
// Fallback: add after any CSS import
|
|
564
|
+
const cssImportRegex = /(import\s+['"'][^'"]*\.css['"];)/;
|
|
565
|
+
if (cssImportRegex.test(mainContent)) {
|
|
566
|
+
mainContent = mainContent.replace(
|
|
567
|
+
cssImportRegex,
|
|
568
|
+
`$1\nimport '${cssImportPath}';`
|
|
569
|
+
);
|
|
570
|
+
console.log(`ā
Added import '${cssImportPath}' to main.tsx`);
|
|
571
|
+
updated = true;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Update theme in ThemeProvider if it exists
|
|
577
|
+
if (mainContent.includes('ThemeProvider')) {
|
|
578
|
+
const oldThemeMatch = mainContent.match(/theme="([^"]+)"/);
|
|
579
|
+
if (oldThemeMatch) {
|
|
580
|
+
const oldTheme = oldThemeMatch[1];
|
|
581
|
+
|
|
582
|
+
// Update theme
|
|
583
|
+
mainContent = mainContent.replace(
|
|
584
|
+
/theme="[^"]+"/,
|
|
585
|
+
`theme="${name}"`
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
// Add forceConfig if not present
|
|
589
|
+
if (!mainContent.includes('forceConfig')) {
|
|
590
|
+
mainContent = mainContent.replace(
|
|
591
|
+
/<ThemeProvider([^>]+)>/,
|
|
592
|
+
`<ThemeProvider$1 forceConfig={true}>`
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
console.log(`ā
Updated theme from "${oldTheme}" to "${name}" in main.tsx`);
|
|
597
|
+
updated = true;
|
|
598
|
+
}
|
|
599
|
+
} else {
|
|
600
|
+
// Add ThemeProvider if it doesn't exist
|
|
601
|
+
if (!mainContent.includes('ThemeProvider')) {
|
|
602
|
+
// Add import
|
|
603
|
+
mainContent = mainContent.replace(
|
|
604
|
+
/(import.*from.*;\n)$/m,
|
|
605
|
+
`$1import { ThemeProvider } from '@bloomneo/uikit/theme-provider';\n`
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
// Wrap App with ThemeProvider (with forceConfig to override storage)
|
|
609
|
+
mainContent = mainContent.replace(
|
|
610
|
+
/(<React\.StrictMode>\s*<App[^>]*\/>\s*<\/React\.StrictMode>)/,
|
|
611
|
+
`<React.StrictMode>\n <ThemeProvider theme="${name}" mode="light" forceConfig={true}>\n <App />\n </ThemeProvider>\n </React.StrictMode>`
|
|
612
|
+
);
|
|
613
|
+
console.log(`ā
Added ThemeProvider with theme "${name}" to main.tsx`);
|
|
614
|
+
updated = true;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Write updated content if changes were made
|
|
619
|
+
if (updated) {
|
|
620
|
+
await fs.writeFile(mainTsxPath, mainContent);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
} catch (error) {
|
|
624
|
+
console.log(`ā ļø Could not auto-update main.tsx: ${error.message}`);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
console.log(`\nšØ Next steps:`);
|
|
628
|
+
console.log(` 1. Customize colors in ${relativePath}`);
|
|
629
|
+
console.log(` 2. Run "npx uikit bundle" to generate CSS`);
|
|
630
|
+
console.log(`\nš Theme "${name}" is now active!`);
|
|
631
|
+
|
|
632
|
+
} catch (error) {
|
|
633
|
+
console.error(`ā Failed to generate theme: ${error.message}`);
|
|
634
|
+
throw error;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Generate theme file from template with proper variable replacement
|
|
640
|
+
*/
|
|
641
|
+
async function generateThemeFromTemplate(templatesPath, templateFile, outputPath, outputFile, themeName, options) {
|
|
642
|
+
try {
|
|
643
|
+
// Read template file
|
|
644
|
+
const templatePath = path.join(templatesPath, templateFile);
|
|
645
|
+
const templateContent = await fs.readFile(templatePath, 'utf8');
|
|
646
|
+
|
|
647
|
+
// Get project name from package.json
|
|
648
|
+
const currentDir = process.cwd();
|
|
649
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
650
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
651
|
+
const projectName = packageJson.name || 'my-uikit-project';
|
|
652
|
+
|
|
653
|
+
// Determine theme
|
|
654
|
+
const theme = options && options.theme || 'base';
|
|
655
|
+
|
|
656
|
+
// Create theme name variations
|
|
657
|
+
const ThemeName = themeName.charAt(0).toUpperCase() + themeName.slice(1);
|
|
658
|
+
|
|
659
|
+
// Replace template variables
|
|
660
|
+
const processedContent = templateContent
|
|
661
|
+
.replace(/\{\{themeName\}\}/g, themeName)
|
|
662
|
+
.replace(/\{\{ThemeName\}\}/g, ThemeName)
|
|
663
|
+
.replace(/\{\{projectName\}\}/g, projectName)
|
|
664
|
+
.replace(/\{\{theme\}\}/g, theme);
|
|
665
|
+
|
|
666
|
+
// Write output file
|
|
667
|
+
const outputFilePath = path.join(outputPath, outputFile);
|
|
668
|
+
await fs.writeFile(outputFilePath, processedContent, 'utf8');
|
|
669
|
+
} catch (error) {
|
|
670
|
+
console.error(`ā Failed to generate ${outputFile} from template ${templateFile}:`, error.message);
|
|
671
|
+
throw error;
|
|
672
|
+
}
|
|
673
|
+
}
|