@lucasvu/scope-ui 0.0.8 → 0.1.1
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/AI_SETUP.md +313 -43
- package/README.md +89 -14
- package/bin/copy-theme-assets.mjs +29 -0
- package/bin/scope-ui-init.mjs +275 -24
- package/dist/chunk-CL3F2TWE.js +1039 -0
- package/dist/core/index.cjs +1052 -0
- package/dist/core/index.d.cts +963 -0
- package/dist/core/index.d.ts +963 -0
- package/dist/core/index.js +1 -0
- package/dist/index.cjs +247 -15
- package/dist/index.d.cts +2 -771
- package/dist/index.d.ts +2 -771
- package/dist/index.js +4 -817
- package/dist/themes/theme-default.css +343 -0
- package/dist/themes/theme-ui-citrus-ink.css +364 -0
- package/dist/themes/theme-ui-custom-crisp.css +969 -0
- package/dist/themes/theme-ui-facebook-blue.css +381 -0
- package/dist/themes/theme-ui-neo-slate.css +962 -0
- package/dist/themes/theme-ui-new-main-fe-sunset.css +1316 -0
- package/dist/themes/theme-ui-new-main-fe.css +343 -0
- package/dist/themes/theme-ui-pure-white.css +377 -0
- package/dist/themes/theme-ui-siraya-vii-light.css +603 -0
- package/dist/themes/theme-ui-solstice-pop.css +1020 -0
- package/dist/themes/theme-ui-uat-aurora.css +962 -0
- package/package.json +20 -4
package/bin/scope-ui-init.mjs
CHANGED
|
@@ -6,6 +6,44 @@ import process from 'node:process'
|
|
|
6
6
|
|
|
7
7
|
const PACKAGE_NAME = '@lucasvu/scope-ui'
|
|
8
8
|
const DEFAULT_THEME_PRESET = 'ocean'
|
|
9
|
+
const DEFAULT_LAYOUT_FILE = 'src/layout-presets/workspace-admin-v1.ts'
|
|
10
|
+
|
|
11
|
+
const LAYOUT_PRESET = {
|
|
12
|
+
id: 'workspace-admin-v1',
|
|
13
|
+
label: 'Workspace Admin v1',
|
|
14
|
+
description:
|
|
15
|
+
'Shared admin shell with a dark sidebar, gradient topbar, soft intro card, optional segmented tabs, and card-based content blocks inspired by the Campaigns screen.',
|
|
16
|
+
recommendedFor: [
|
|
17
|
+
'Admin workspaces',
|
|
18
|
+
'Operations dashboards',
|
|
19
|
+
'CRUD-heavy backoffice screens that should share one shell',
|
|
20
|
+
],
|
|
21
|
+
shellRecipe: [
|
|
22
|
+
'Dark left sidebar with icon + label navigation and one active item',
|
|
23
|
+
'Gradient workspace topbar with workspace label on the left and timezone/user slots on the right',
|
|
24
|
+
'Large page intro card with breadcrumb, title, and optional subtitle',
|
|
25
|
+
'Optional segmented tabs row directly under the intro card',
|
|
26
|
+
'Toolbar card with search/filters on the left and actions on the right',
|
|
27
|
+
'Main body rendered as one or more content cards instead of a flat page',
|
|
28
|
+
],
|
|
29
|
+
requiredFields: [
|
|
30
|
+
'layoutPreset',
|
|
31
|
+
'workspaceLabel',
|
|
32
|
+
'pageKind',
|
|
33
|
+
'routeUrl',
|
|
34
|
+
'sidebarItems',
|
|
35
|
+
'activeSidebarItemId',
|
|
36
|
+
'pageTitle',
|
|
37
|
+
],
|
|
38
|
+
askBeforeCoding: [
|
|
39
|
+
'What workspace label should appear in the topbar?',
|
|
40
|
+
'What timezone or top-right meta label should appear beside the user badge?',
|
|
41
|
+
'What sidebar items exist and which one is active on this screen?',
|
|
42
|
+
'Does this screen need segmented tabs? If yes, what are the tab labels and which tab is active?',
|
|
43
|
+
'What search placeholder, filters, and primary action belong in the toolbar card?',
|
|
44
|
+
'What columns, fields, or summary blocks should be rendered in the page body?',
|
|
45
|
+
],
|
|
46
|
+
}
|
|
9
47
|
|
|
10
48
|
const THEME_PRESETS = {
|
|
11
49
|
ocean: {
|
|
@@ -216,6 +254,7 @@ function parseArgs(argv) {
|
|
|
216
254
|
force: false,
|
|
217
255
|
agentsFile: 'AGENTS.md',
|
|
218
256
|
themeFile: 'src/styles/ui-theme.css',
|
|
257
|
+
layoutFile: DEFAULT_LAYOUT_FILE,
|
|
219
258
|
theme: DEFAULT_THEME_PRESET,
|
|
220
259
|
listThemes: false,
|
|
221
260
|
}
|
|
@@ -248,6 +287,16 @@ function parseArgs(argv) {
|
|
|
248
287
|
continue
|
|
249
288
|
}
|
|
250
289
|
|
|
290
|
+
if (arg === '--layout-file') {
|
|
291
|
+
const value = argv[index + 1]
|
|
292
|
+
if (!value || value.startsWith('--')) {
|
|
293
|
+
exitWithMissingValue('--layout-file')
|
|
294
|
+
}
|
|
295
|
+
args.layoutFile = value
|
|
296
|
+
index += 1
|
|
297
|
+
continue
|
|
298
|
+
}
|
|
299
|
+
|
|
251
300
|
if (arg === '--theme') {
|
|
252
301
|
const value = argv[index + 1]
|
|
253
302
|
if (!value || value.startsWith('--')) {
|
|
@@ -288,12 +337,13 @@ Usage:
|
|
|
288
337
|
Optional: inspect approved presets before choosing one.
|
|
289
338
|
|
|
290
339
|
npx scope-ui-init --theme forest --force
|
|
291
|
-
npx scope-ui-init --agents-file AGENTS.md --theme-file src/styles/ui-theme.css
|
|
340
|
+
npx scope-ui-init --agents-file AGENTS.md --theme-file src/styles/ui-theme.css --layout-file ${DEFAULT_LAYOUT_FILE}
|
|
292
341
|
|
|
293
342
|
Options:
|
|
294
343
|
--force overwrite existing files
|
|
295
344
|
--agents-file target path for the generated AGENTS.md file
|
|
296
345
|
--theme-file target path for the generated theme override file
|
|
346
|
+
--layout-file target path for the generated layout preset file
|
|
297
347
|
--theme theme preset id (${Object.keys(THEME_PRESETS).join(', ')})
|
|
298
348
|
--list-themes show the approved preset list
|
|
299
349
|
--help, -h show this help
|
|
@@ -333,38 +383,100 @@ function renderTokenBlock(tokens) {
|
|
|
333
383
|
.join('\n')
|
|
334
384
|
}
|
|
335
385
|
|
|
336
|
-
function
|
|
386
|
+
function renderMarkdownList(items) {
|
|
387
|
+
return items.map((item) => `- ${item}`).join('\n')
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function createAgentsTemplate({ themeFile, layoutFile, themePreset, layoutPreset }) {
|
|
337
391
|
return `# Agent Rules
|
|
338
392
|
|
|
339
393
|
This repo uses \`${PACKAGE_NAME}\` as the default UI library.
|
|
394
|
+
Use \`${PACKAGE_NAME}\` for React components and \`${PACKAGE_NAME}/core\` for framework-agnostic theme/runtime contracts.
|
|
340
395
|
This repo is locked to the \`${themePreset.label}\` theme preset (\`${themePreset.id}\`).
|
|
396
|
+
This repo uses the \`${layoutPreset.label}\` shell preset (\`${layoutPreset.id}\`) as the shared layout baseline.
|
|
341
397
|
|
|
342
398
|
Primary references:
|
|
343
399
|
- \`node_modules/${PACKAGE_NAME}/README.md\`
|
|
344
400
|
- \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`
|
|
345
|
-
- \`uiScreenBlueprint\` and \`
|
|
401
|
+
- \`uiScreenBlueprint\`, \`uiAiManifest\`, and \`uiThemeLayerAssets\` from \`${PACKAGE_NAME}/core\`
|
|
346
402
|
- \`${themeFile}\`
|
|
403
|
+
- \`${layoutFile}\`
|
|
347
404
|
|
|
348
405
|
Theme preset summary:
|
|
349
406
|
- ${themePreset.description}
|
|
350
407
|
- Recommended for: ${themePreset.recommendedFor.join(', ')}
|
|
351
408
|
|
|
409
|
+
Layout preset summary:
|
|
410
|
+
${renderMarkdownList(layoutPreset.shellRecipe)}
|
|
411
|
+
|
|
412
|
+
## Workspace Base
|
|
413
|
+
|
|
414
|
+
For Vite + micro frontend repos, keep this structure stable:
|
|
415
|
+
|
|
416
|
+
- \`${PACKAGE_NAME}\` owns the React component surface
|
|
417
|
+
- \`${PACKAGE_NAME}/core\` owns theme contracts, bundled theme layers, color-mode runtime, and framework-agnostic contracts
|
|
418
|
+
- \`apps/shell\` owns the shared app shell, top-level routing, remote mounts, and theme imports
|
|
419
|
+
- \`apps/*-mfe\` owns page-level business screens and feature routes
|
|
420
|
+
|
|
421
|
+
If the repo still has a \`packages/shared\` folder, keep it for business utils or internal loaders, not for the primary theme runtime.
|
|
422
|
+
|
|
423
|
+
Recommended folders:
|
|
424
|
+
|
|
425
|
+
- shell: \`src/app\`, \`src/layouts\`, \`src/routes\`, \`src/remotes\`, \`src/styles/ui-theme.css\`
|
|
426
|
+
- remote: \`src/features\`, \`src/pages\`, \`src/routes\`, \`src/services\`, \`src/styles/index.css\`
|
|
427
|
+
|
|
428
|
+
Theme layers:
|
|
429
|
+
|
|
430
|
+
1. Import \`${PACKAGE_NAME}/styles.css\` first.
|
|
431
|
+
2. If the repo wants a bundled shell/theme layer, import one from \`${PACKAGE_NAME}/themes/*\` next.
|
|
432
|
+
3. Import \`${themeFile}\` after the bundled theme layer.
|
|
433
|
+
4. Keep app-specific overrides thin and token-based.
|
|
434
|
+
|
|
435
|
+
If the bundled theme layer is client-theme-scoped, set \`data-client-theme\` with \`applyDocumentClientTheme(...)\`.
|
|
436
|
+
|
|
352
437
|
## Required Flow
|
|
353
438
|
|
|
354
439
|
When asked to build or edit a screen, follow these steps in order:
|
|
355
440
|
|
|
356
|
-
1. Read \`${themeFile}\`, \`node_modules/${PACKAGE_NAME}/README.md\`, \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`, and the exported \`uiScreenBlueprint\` contract before generating UI.
|
|
357
|
-
2.
|
|
358
|
-
3.
|
|
359
|
-
4.
|
|
360
|
-
5.
|
|
361
|
-
6.
|
|
362
|
-
7.
|
|
363
|
-
8.
|
|
441
|
+
1. Read \`${themeFile}\`, \`${layoutFile}\`, \`node_modules/${PACKAGE_NAME}/README.md\`, \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`, and the exported \`uiScreenBlueprint\` contract before generating UI.
|
|
442
|
+
2. If the task touches app bootstrap, shell setup, or micro frontend structure, scaffold the repo around the workspace base above before writing page JSX.
|
|
443
|
+
3. Fill the shell brief and screen brief first. If a required field is missing, stop and ask for that exact value before writing JSX. Only leave TODO placeholders when the user explicitly asks for an incomplete scaffold.
|
|
444
|
+
4. Verify the app entry imports \`${PACKAGE_NAME}/styles.css\` first, then any bundled theme layer from \`${PACKAGE_NAME}/themes/*\`, then \`${themeFile}\`.
|
|
445
|
+
5. Treat \`${layoutFile}\` as the source of truth for the app shell. Keep the dark sidebar, gradient topbar, intro card, and card-based body structure aligned with that preset unless the user explicitly asks for a different shell.
|
|
446
|
+
6. Keep the shell in the host app. Do not let a remote rebuild its own global shell unless the task explicitly asks for a standalone shell.
|
|
447
|
+
7. Identify the page kind (\`list | form | detail | dashboard\`), then map each block to canonical components from \`uiAiManifest\` before writing JSX.
|
|
448
|
+
8. Build the shell in this exact order: \`Sidebar\` -> workspace topbar -> intro card (\`Breadcrumb\` + \`PageTitle\`) -> optional segmented tabs -> toolbar card -> page body cards/grids.
|
|
449
|
+
9. For list pages, build the toolbar card first and then the \`DataTable\`. For form pages, keep the same shell and swap the body into section cards and a bottom action row. For detail pages, keep the shell and render summary/detail cards plus related tables. For dashboard pages, keep the shell and render stat cards plus supporting cards/tables.
|
|
450
|
+
10. If \`${layoutFile}\` says a slot is optional, omit it cleanly when the brief does not request it. Do not invent tabs, workspace labels, filters, or toolbar actions.
|
|
451
|
+
11. Keep all colors, radius, surface, and shadow decisions inside \`${themeFile}\`. If the preset is insufficient, update tokens there instead of styling one page ad hoc.
|
|
452
|
+
12. Before finishing, run the output checklist in this file.
|
|
453
|
+
|
|
454
|
+
## Ask For Missing Input
|
|
455
|
+
|
|
456
|
+
If any of these are missing, ask the user directly before writing JSX:
|
|
457
|
+
|
|
458
|
+
${renderMarkdownList(layoutPreset.askBeforeCoding)}
|
|
459
|
+
|
|
460
|
+
## Shell Brief
|
|
461
|
+
|
|
462
|
+
Complete this shell brief before writing JSX:
|
|
463
|
+
|
|
464
|
+
\`\`\`yaml
|
|
465
|
+
layoutPreset: ${layoutPreset.id}
|
|
466
|
+
workspaceLabel:
|
|
467
|
+
timezoneLabel:
|
|
468
|
+
userBadgeLabel:
|
|
469
|
+
pageTabs:
|
|
470
|
+
- value:
|
|
471
|
+
label:
|
|
472
|
+
activePageTab:
|
|
473
|
+
searchPlaceholder:
|
|
474
|
+
toolbarNote:
|
|
475
|
+
\`\`\`
|
|
364
476
|
|
|
365
477
|
## Screen Brief
|
|
366
478
|
|
|
367
|
-
Complete this brief before writing JSX:
|
|
479
|
+
Complete this screen brief before writing JSX:
|
|
368
480
|
|
|
369
481
|
\`\`\`yaml
|
|
370
482
|
pageKind: list | form | detail | dashboard
|
|
@@ -373,6 +485,7 @@ sidebarItems:
|
|
|
373
485
|
- id:
|
|
374
486
|
title:
|
|
375
487
|
href:
|
|
488
|
+
icon:
|
|
376
489
|
activeSidebarItemId:
|
|
377
490
|
breadcrumbs:
|
|
378
491
|
- label:
|
|
@@ -421,29 +534,44 @@ emptyState:
|
|
|
421
534
|
permissions: []
|
|
422
535
|
\`\`\`
|
|
423
536
|
|
|
537
|
+
## Shell Lock
|
|
538
|
+
|
|
539
|
+
Keep the layout aligned with \`${layoutPreset.id}\`:
|
|
540
|
+
|
|
541
|
+
${renderMarkdownList(layoutPreset.shellRecipe)}
|
|
542
|
+
|
|
424
543
|
## Page Frame Recipes
|
|
425
544
|
|
|
426
|
-
- \`list\`: \`Sidebar\` ->
|
|
427
|
-
- \`form\`: \`Sidebar\` ->
|
|
428
|
-
- \`detail\`: \`Sidebar\` ->
|
|
429
|
-
- \`dashboard\`: \`Sidebar\` ->
|
|
545
|
+
- \`list\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> toolbar \`Card\` -> \`DataTable\` \`Card\`
|
|
546
|
+
- \`form\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> top actions -> sectioned form \`Card\` blocks -> bottom action row
|
|
547
|
+
- \`detail\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> status/actions -> summary metadata \`Card\` -> detail \`Card\` blocks -> related \`DataTable\`
|
|
548
|
+
- \`dashboard\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> toolbar \`Card\` -> \`Stat\` row -> insight \`Card\` blocks and \`DataTable\`
|
|
430
549
|
|
|
431
550
|
## Hard Rules
|
|
432
551
|
|
|
433
552
|
- import \`${PACKAGE_NAME}/styles.css\` once at the app entry
|
|
434
|
-
- import
|
|
435
|
-
-
|
|
553
|
+
- import a bundled theme layer from \`${PACKAGE_NAME}/themes/*\` after the package stylesheet when the repo chooses one
|
|
554
|
+
- import the project theme override file after the bundled theme layer
|
|
555
|
+
- use \`applyDocumentClientTheme\` when the chosen bundled theme layer is client-theme-scoped
|
|
556
|
+
- use root exports from \`${PACKAGE_NAME}\` for React components
|
|
557
|
+
- use \`${PACKAGE_NAME}/core\` for theme/runtime utilities in non-React or mixed-framework setup
|
|
436
558
|
- use \`${themeFile}\` as the only source of truth for colors, radius, surfaces, and shadows
|
|
559
|
+
- use \`${layoutFile}\` as the source of truth for the shell layout and shared page frame
|
|
437
560
|
- keep layouts and component choices aligned with the shared preset-driven UI used across projects
|
|
561
|
+
- keep the host shell responsible for sidebar, topbar, remote mount, and theme mode
|
|
562
|
+
- keep remotes focused on feature routes and page business content
|
|
438
563
|
- read \`uiAiManifest\` before choosing components
|
|
564
|
+
- read \`uiThemeLayerAssets\` before choosing a bundled theme layer
|
|
439
565
|
- read \`uiThemeContract\` before changing colors, surfaces, borders, radius, or shadows
|
|
440
566
|
- keep UI token-driven and theme-driven
|
|
441
567
|
|
|
442
568
|
Do not:
|
|
443
569
|
- import from \`MainFe\` unless the task explicitly targets a legacy screen
|
|
444
570
|
- invent a second palette or one-off brand colors outside \`${themeFile}\`
|
|
571
|
+
- replace the shared dark-sidebar + gradient-topbar shell with a flat blank layout unless the user explicitly requests it
|
|
445
572
|
- restyle individual pages if the preset tokens can solve it globally
|
|
446
573
|
- create duplicate Button/Input/Select wrappers unless a project-specific behavior is required
|
|
574
|
+
- let each remote define a different shell or a different palette
|
|
447
575
|
|
|
448
576
|
## Component Choice
|
|
449
577
|
|
|
@@ -461,13 +589,17 @@ Do not:
|
|
|
461
589
|
|
|
462
590
|
Before finishing, confirm all of these are true:
|
|
463
591
|
|
|
464
|
-
- The
|
|
465
|
-
-
|
|
592
|
+
- The shell brief and screen brief are complete.
|
|
593
|
+
- Any missing required input was explicitly asked for before coding.
|
|
594
|
+
- The shell matches \`${layoutPreset.id}\` with a dark sidebar, gradient topbar, intro card, and card-based body structure.
|
|
466
595
|
- The chosen components match the page kind and the brief.
|
|
467
596
|
- No \`MainFe\` imports were used.
|
|
468
597
|
- No hardcoded brand colors were added in page components.
|
|
469
598
|
- Theme decisions live in \`${themeFile}\`, not in ad hoc JSX styling.
|
|
599
|
+
- The app entry import order is package stylesheet -> bundled theme layer if present -> project theme override.
|
|
600
|
+
- The shell still lives in the host app and remotes only own business screens.
|
|
470
601
|
- Spacing, card structure, and actions are consistent with the shared preset.
|
|
602
|
+
- The layout shell stayed stable even if the page body changed.
|
|
471
603
|
`
|
|
472
604
|
}
|
|
473
605
|
|
|
@@ -487,6 +619,110 @@ ${renderTokenBlock(themePreset.tokens.dark)}
|
|
|
487
619
|
`
|
|
488
620
|
}
|
|
489
621
|
|
|
622
|
+
function createLayoutTemplate({ themeFile, layoutPreset }) {
|
|
623
|
+
return `/* Generated by scope-ui-init. */
|
|
624
|
+
/* Layout preset: ${layoutPreset.label} (${layoutPreset.id}) */
|
|
625
|
+
/* Use this file as the shared app-shell source of truth for AI/codegen. */
|
|
626
|
+
|
|
627
|
+
export const uiLayoutPreset = {
|
|
628
|
+
id: '${layoutPreset.id}',
|
|
629
|
+
label: '${layoutPreset.label}',
|
|
630
|
+
description:
|
|
631
|
+
'${layoutPreset.description}',
|
|
632
|
+
themeSource: '${themeFile}',
|
|
633
|
+
recommendedFor: [
|
|
634
|
+
${layoutPreset.recommendedFor.map((item) => ` '${item}',`).join('\n')}
|
|
635
|
+
],
|
|
636
|
+
shellRecipe: [
|
|
637
|
+
${layoutPreset.shellRecipe.map((item) => ` '${item}',`).join('\n')}
|
|
638
|
+
],
|
|
639
|
+
requiredFields: [
|
|
640
|
+
${layoutPreset.requiredFields.map((item) => ` '${item}',`).join('\n')}
|
|
641
|
+
],
|
|
642
|
+
askBeforeCoding: [
|
|
643
|
+
${layoutPreset.askBeforeCoding.map((item) => ` '${item}',`).join('\n')}
|
|
644
|
+
],
|
|
645
|
+
workspaceStructure: {
|
|
646
|
+
packageUi: ['components', 'theme contracts', 'bundled theme layers', 'color-mode runtime'],
|
|
647
|
+
shellApp: ['src/app', 'src/layouts', 'src/routes', 'src/remotes', 'src/styles/ui-theme.css'],
|
|
648
|
+
remoteApp: ['src/features', 'src/pages', 'src/routes', 'src/services', 'src/styles/index.css'],
|
|
649
|
+
},
|
|
650
|
+
themeLayers: [
|
|
651
|
+
'${PACKAGE_NAME}/styles.css',
|
|
652
|
+
'${PACKAGE_NAME}/themes/theme-ui-new-main-fe.css (optional bundled package layer)',
|
|
653
|
+
'${themeFile}',
|
|
654
|
+
],
|
|
655
|
+
setupSteps: [
|
|
656
|
+
'Import the package stylesheet once at the host app entry.',
|
|
657
|
+
'If the app wants a bundled package theme layer, import it after the package stylesheet.',
|
|
658
|
+
'Import the project themeSource after the bundled theme layer.',
|
|
659
|
+
'If the chosen theme layer is client-theme-scoped, set data-client-theme at the document root.',
|
|
660
|
+
'Initialize color mode at the host app entry and let the host own shell/theme concerns.',
|
|
661
|
+
'Keep remotes focused on feature routes and business screens instead of rebuilding the global shell.',
|
|
662
|
+
],
|
|
663
|
+
shell: {
|
|
664
|
+
sidebar: {
|
|
665
|
+
tone: 'dark',
|
|
666
|
+
width: '240px',
|
|
667
|
+
content: ['workspace badge', 'icon + label navigation', 'active state'],
|
|
668
|
+
},
|
|
669
|
+
topbar: {
|
|
670
|
+
background: 'theme gradient from --primary-grad-from to --primary-grad-to',
|
|
671
|
+
leftSlot: 'workspaceLabel',
|
|
672
|
+
rightSlots: ['timezoneLabel', 'userBadgeLabel'],
|
|
673
|
+
},
|
|
674
|
+
introCard: {
|
|
675
|
+
content: ['breadcrumbs', 'pageTitle', 'pageSubtitle'],
|
|
676
|
+
surface: 'soft elevated card',
|
|
677
|
+
},
|
|
678
|
+
pageTabs: {
|
|
679
|
+
optional: true,
|
|
680
|
+
style: 'segmented pills',
|
|
681
|
+
fields: ['pageTabs', 'activePageTab'],
|
|
682
|
+
},
|
|
683
|
+
toolbarCard: {
|
|
684
|
+
optional: true,
|
|
685
|
+
leftSlots: ['searchPlaceholder', 'filters'],
|
|
686
|
+
rightSlots: ['secondaryActions', 'primaryAction'],
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
pageBodies: {
|
|
690
|
+
list: ['toolbar card', 'DataTable card', 'rowActions', 'emptyState'],
|
|
691
|
+
form: ['sectioned form cards', 'fields', 'bottom action row'],
|
|
692
|
+
detail: ['summary metadata card', 'detailSections', 'related tables'],
|
|
693
|
+
dashboard: ['summaryStats', 'filters', 'insight cards', 'DataTable'],
|
|
694
|
+
},
|
|
695
|
+
hardRules: [
|
|
696
|
+
'Keep the dark sidebar and gradient topbar shell stable across screens.',
|
|
697
|
+
'Do not replace the intro card with a bare page title row.',
|
|
698
|
+
'Use the shared theme tokens from the themeSource file for color, border, surface, and shadow decisions.',
|
|
699
|
+
'Import theme layers in this order: package stylesheet, bundled package theme layer when present, then themeSource.',
|
|
700
|
+
'Keep the host app responsible for the global shell and keep remotes page-scoped.',
|
|
701
|
+
'Only omit tabs or toolbar sections when the brief explicitly leaves them out.',
|
|
702
|
+
'Ask for missing required fields before generating JSX instead of guessing from the screenshot.',
|
|
703
|
+
],
|
|
704
|
+
exampleBrief: {
|
|
705
|
+
layoutPreset: '${layoutPreset.id}',
|
|
706
|
+
workspaceLabel: 'Workspace',
|
|
707
|
+
timezoneLabel: 'UTC+07:00',
|
|
708
|
+
userBadgeLabel: 'L',
|
|
709
|
+
pageKind: 'list',
|
|
710
|
+
routeUrl: '/campaigns/new',
|
|
711
|
+
activeSidebarItemId: 'campaigns',
|
|
712
|
+
pageTabs: [
|
|
713
|
+
{ value: 'overview', label: 'Overview' },
|
|
714
|
+
{ value: 'coupons', label: 'Coupons' },
|
|
715
|
+
{ value: 'redemption', label: 'Redemption' },
|
|
716
|
+
],
|
|
717
|
+
activePageTab: 'coupons',
|
|
718
|
+
searchPlaceholder: 'Search by coupon code',
|
|
719
|
+
},
|
|
720
|
+
} as const
|
|
721
|
+
|
|
722
|
+
export type UiLayoutPreset = typeof uiLayoutPreset
|
|
723
|
+
`
|
|
724
|
+
}
|
|
725
|
+
|
|
490
726
|
function writeFile(targetPath, content, force) {
|
|
491
727
|
const absolutePath = resolve(process.cwd(), targetPath)
|
|
492
728
|
const alreadyExists = existsSync(absolutePath)
|
|
@@ -511,7 +747,12 @@ const themePreset = resolveThemePreset(options.theme)
|
|
|
511
747
|
|
|
512
748
|
const agentsResult = writeFile(
|
|
513
749
|
options.agentsFile,
|
|
514
|
-
createAgentsTemplate({
|
|
750
|
+
createAgentsTemplate({
|
|
751
|
+
themeFile: options.themeFile,
|
|
752
|
+
layoutFile: options.layoutFile,
|
|
753
|
+
themePreset,
|
|
754
|
+
layoutPreset: LAYOUT_PRESET,
|
|
755
|
+
}),
|
|
515
756
|
options.force,
|
|
516
757
|
)
|
|
517
758
|
|
|
@@ -521,13 +762,23 @@ const themeResult = writeFile(
|
|
|
521
762
|
options.force,
|
|
522
763
|
)
|
|
523
764
|
|
|
765
|
+
const layoutResult = writeFile(
|
|
766
|
+
options.layoutFile,
|
|
767
|
+
createLayoutTemplate({ themeFile: options.themeFile, layoutPreset: LAYOUT_PRESET }),
|
|
768
|
+
options.force,
|
|
769
|
+
)
|
|
770
|
+
|
|
524
771
|
console.log(`Initialized ${PACKAGE_NAME}`)
|
|
525
772
|
console.log(`- theme preset: ${themePreset.label} (${themePreset.id})`)
|
|
773
|
+
console.log(`- layout preset: ${LAYOUT_PRESET.label} (${LAYOUT_PRESET.id})`)
|
|
526
774
|
console.log(`- ${agentsResult.path}: ${agentsResult.status}`)
|
|
527
775
|
console.log(`- ${themeResult.path}: ${themeResult.status}`)
|
|
776
|
+
console.log(`- ${layoutResult.path}: ${layoutResult.status}`)
|
|
528
777
|
console.log('')
|
|
529
778
|
console.log('Next steps:')
|
|
530
779
|
console.log(`1. Import \`${PACKAGE_NAME}/styles.css\` once at your app entry.`)
|
|
531
|
-
console.log(`2.
|
|
532
|
-
console.log(`3.
|
|
533
|
-
console.log(`4.
|
|
780
|
+
console.log(`2. If you want a bundled package theme layer, import one from \`${PACKAGE_NAME}/themes/*\` right after the package stylesheet.`)
|
|
781
|
+
console.log(`3. Import \`${options.themeFile}\` after the bundled theme layer.`)
|
|
782
|
+
console.log(`4. Let your agent read \`${options.agentsFile}\` and \`${options.layoutFile}\` before generating UI.`)
|
|
783
|
+
console.log('5. Keep the host app responsible for the global shell and keep remotes page-scoped.')
|
|
784
|
+
console.log(`6. Re-run this command with \`--theme <preset> --force\` if you want another approved preset.`)
|