@lucasvu/scope-ui 0.1.0 → 0.1.2
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 +308 -45
- package/README.md +84 -10
- package/bin/copy-theme-assets.mjs +29 -0
- package/bin/scope-ui-init.mjs +300 -178
- 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 +180 -3
- package/dist/index.d.cts +2 -855
- package/dist/index.d.ts +2 -855
- package/dist/index.js +4 -872
- 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
|
@@ -333,6 +333,9 @@ Usage:
|
|
|
333
333
|
npx scope-ui-init --theme sunset
|
|
334
334
|
Fast path when you already know the preset you want.
|
|
335
335
|
|
|
336
|
+
npx scope-ui-init --theme sunset --agents-file agents/dev.md
|
|
337
|
+
Optional: write the generated agent definition straight into a tool-specific agent path.
|
|
338
|
+
|
|
336
339
|
npx scope-ui-init --list-themes
|
|
337
340
|
Optional: inspect approved presets before choosing one.
|
|
338
341
|
|
|
@@ -341,7 +344,7 @@ Usage:
|
|
|
341
344
|
|
|
342
345
|
Options:
|
|
343
346
|
--force overwrite existing files
|
|
344
|
-
--agents-file target path for the generated
|
|
347
|
+
--agents-file target path for the generated agent markdown file
|
|
345
348
|
--theme-file target path for the generated theme override file
|
|
346
349
|
--layout-file target path for the generated layout preset file
|
|
347
350
|
--theme theme preset id (${Object.keys(THEME_PRESETS).join(', ')})
|
|
@@ -383,186 +386,283 @@ function renderTokenBlock(tokens) {
|
|
|
383
386
|
.join('\n')
|
|
384
387
|
}
|
|
385
388
|
|
|
386
|
-
function
|
|
387
|
-
return
|
|
389
|
+
function quoteYaml(value) {
|
|
390
|
+
return JSON.stringify(value)
|
|
388
391
|
}
|
|
389
392
|
|
|
390
|
-
function
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
This repo is locked to the \`${themePreset.label}\` theme preset (\`${themePreset.id}\`).
|
|
395
|
-
This repo uses the \`${layoutPreset.label}\` shell preset (\`${layoutPreset.id}\`) as the shared layout baseline.
|
|
396
|
-
|
|
397
|
-
Primary references:
|
|
398
|
-
- \`node_modules/${PACKAGE_NAME}/README.md\`
|
|
399
|
-
- \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`
|
|
400
|
-
- \`uiScreenBlueprint\` and \`uiAiManifest\` from \`${PACKAGE_NAME}\`
|
|
401
|
-
- \`${themeFile}\`
|
|
402
|
-
- \`${layoutFile}\`
|
|
403
|
-
|
|
404
|
-
Theme preset summary:
|
|
405
|
-
- ${themePreset.description}
|
|
406
|
-
- Recommended for: ${themePreset.recommendedFor.join(', ')}
|
|
407
|
-
|
|
408
|
-
Layout preset summary:
|
|
409
|
-
${renderMarkdownList(layoutPreset.shellRecipe)}
|
|
410
|
-
|
|
411
|
-
## Required Flow
|
|
412
|
-
|
|
413
|
-
When asked to build or edit a screen, follow these steps in order:
|
|
414
|
-
|
|
415
|
-
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.
|
|
416
|
-
2. 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.
|
|
417
|
-
3. Verify the app entry imports \`${PACKAGE_NAME}/styles.css\` first and the project theme file right after it.
|
|
418
|
-
4. 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.
|
|
419
|
-
5. Identify the page kind (\`list | form | detail | dashboard\`), then map each block to canonical components from \`uiAiManifest\` before writing JSX.
|
|
420
|
-
6. Build the shell in this exact order: \`Sidebar\` -> workspace topbar -> intro card (\`Breadcrumb\` + \`PageTitle\`) -> optional segmented tabs -> toolbar card -> page body cards/grids.
|
|
421
|
-
7. 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.
|
|
422
|
-
8. 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.
|
|
423
|
-
9. 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.
|
|
424
|
-
10. Before finishing, run the output checklist in this file.
|
|
425
|
-
|
|
426
|
-
## Ask For Missing Input
|
|
427
|
-
|
|
428
|
-
If any of these are missing, ask the user directly before writing JSX:
|
|
429
|
-
|
|
430
|
-
${renderMarkdownList(layoutPreset.askBeforeCoding)}
|
|
431
|
-
|
|
432
|
-
## Shell Brief
|
|
433
|
-
|
|
434
|
-
Complete this shell brief before writing JSX:
|
|
435
|
-
|
|
436
|
-
\`\`\`yaml
|
|
437
|
-
layoutPreset: ${layoutPreset.id}
|
|
438
|
-
workspaceLabel:
|
|
439
|
-
timezoneLabel:
|
|
440
|
-
userBadgeLabel:
|
|
441
|
-
pageTabs:
|
|
442
|
-
- value:
|
|
443
|
-
label:
|
|
444
|
-
activePageTab:
|
|
445
|
-
searchPlaceholder:
|
|
446
|
-
toolbarNote:
|
|
447
|
-
\`\`\`
|
|
448
|
-
|
|
449
|
-
## Screen Brief
|
|
393
|
+
function renderYamlList(items, indent = 2) {
|
|
394
|
+
const prefix = ' '.repeat(indent)
|
|
395
|
+
return items.map((item) => `${prefix}- ${quoteYaml(item)}`).join('\n')
|
|
396
|
+
}
|
|
450
397
|
|
|
451
|
-
|
|
398
|
+
function createAgentsTemplate({ themeFile, layoutFile, themePreset, layoutPreset }) {
|
|
399
|
+
const importOrder = [
|
|
400
|
+
`${PACKAGE_NAME}/styles.css`,
|
|
401
|
+
`${PACKAGE_NAME}/themes/*`,
|
|
402
|
+
themeFile,
|
|
403
|
+
]
|
|
404
|
+
const activationInstructions = [
|
|
405
|
+
'ONLY load dependency files when user selects them for execution via command or request of a task',
|
|
406
|
+
'The agent.customization field ALWAYS takes precedence over any conflicting instructions',
|
|
407
|
+
'When listing commands or presenting options during conversations, always show as numbered options list, allowing the user to type a number to select or execute',
|
|
408
|
+
'STAY IN CHARACTER!',
|
|
409
|
+
`Read \`${themeFile}\`, \`${layoutFile}\`, \`node_modules/${PACKAGE_NAME}/README.md\`, and \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\` before generating UI`,
|
|
410
|
+
`Lock all UI work to the \`${themePreset.label}\` theme preset (\`${themePreset.id}\`) and the \`${layoutPreset.label}\` shell preset (\`${layoutPreset.id}\`) unless the user explicitly asks to change them`,
|
|
411
|
+
`Keep stylesheet import order as \`${PACKAGE_NAME}/styles.css\` -> optional \`${PACKAGE_NAME}/themes/*\` -> \`${themeFile}\``,
|
|
412
|
+
'If a bundled theme layer is client-theme-scoped, use `applyDocumentClientTheme(...)` after importing it',
|
|
413
|
+
]
|
|
414
|
+
const corePrinciples = [
|
|
415
|
+
`CRITICAL: \`${themeFile}\` is the only source of truth for palette, radius, surface, and shadow decisions for this project`,
|
|
416
|
+
`CRITICAL: \`${layoutFile}\` is the source of truth for the shared shell and page frame`,
|
|
417
|
+
'CRITICAL: Follow the build-screen command when the user asks to implement or update a screen',
|
|
418
|
+
`CRITICAL: Use root exports from \`${PACKAGE_NAME}\` and avoid \`MainFe\` unless the task explicitly targets legacy screens`,
|
|
419
|
+
'CRITICAL: Keep the host app responsible for sidebar, topbar, remote mount, theme mode, and bundled theme layer activation',
|
|
420
|
+
'CRITICAL: Ask for missing required brief values before writing JSX unless the user explicitly asks for a scaffold with TODOs',
|
|
421
|
+
'Numbered Options - Always use numbered lists when presenting choices to the user',
|
|
422
|
+
]
|
|
423
|
+
const runtimeContracts = [
|
|
424
|
+
`${PACKAGE_NAME}/core -> uiAiManifest`,
|
|
425
|
+
`${PACKAGE_NAME}/core -> uiScreenBlueprint`,
|
|
426
|
+
`${PACKAGE_NAME}/core -> uiThemeContract`,
|
|
427
|
+
`${PACKAGE_NAME}/core -> uiThemeLayerAssets`,
|
|
428
|
+
`${PACKAGE_NAME}/core -> uiThemePresets`,
|
|
429
|
+
]
|
|
430
|
+
const pageKinds = ['list', 'form', 'detail', 'dashboard']
|
|
431
|
+
const pageFrameRecipes = {
|
|
432
|
+
list: [
|
|
433
|
+
'dark Sidebar',
|
|
434
|
+
'workspace topbar',
|
|
435
|
+
'intro card',
|
|
436
|
+
'optional segmented tabs',
|
|
437
|
+
'toolbar Card',
|
|
438
|
+
'DataTable Card',
|
|
439
|
+
],
|
|
440
|
+
form: [
|
|
441
|
+
'dark Sidebar',
|
|
442
|
+
'workspace topbar',
|
|
443
|
+
'intro card',
|
|
444
|
+
'optional segmented tabs',
|
|
445
|
+
'top actions',
|
|
446
|
+
'sectioned form Card blocks',
|
|
447
|
+
'bottom action row',
|
|
448
|
+
],
|
|
449
|
+
detail: [
|
|
450
|
+
'dark Sidebar',
|
|
451
|
+
'workspace topbar',
|
|
452
|
+
'intro card',
|
|
453
|
+
'optional segmented tabs',
|
|
454
|
+
'status/actions',
|
|
455
|
+
'summary metadata Card',
|
|
456
|
+
'detail Card blocks',
|
|
457
|
+
'related DataTable',
|
|
458
|
+
],
|
|
459
|
+
dashboard: [
|
|
460
|
+
'dark Sidebar',
|
|
461
|
+
'workspace topbar',
|
|
462
|
+
'intro card',
|
|
463
|
+
'optional segmented tabs',
|
|
464
|
+
'toolbar Card',
|
|
465
|
+
'Stat row',
|
|
466
|
+
'insight Card blocks and DataTable',
|
|
467
|
+
],
|
|
468
|
+
}
|
|
469
|
+
const hardRules = [
|
|
470
|
+
`import \`${PACKAGE_NAME}/styles.css\` once at the app entry`,
|
|
471
|
+
`import a bundled theme layer from \`${PACKAGE_NAME}/themes/*\` after the package stylesheet when the repo chooses one`,
|
|
472
|
+
'import the project theme override file after the bundled theme layer',
|
|
473
|
+
'use `applyDocumentClientTheme` when the chosen bundled theme layer is client-theme-scoped',
|
|
474
|
+
`use root exports from \`${PACKAGE_NAME}\` for React components`,
|
|
475
|
+
`use \`${PACKAGE_NAME}/core\` for theme/runtime utilities in non-React or mixed-framework setup`,
|
|
476
|
+
`use \`${themeFile}\` as the only source of truth for colors, radius, surfaces, and shadows`,
|
|
477
|
+
`use \`${layoutFile}\` as the source of truth for the shell layout and shared page frame`,
|
|
478
|
+
'keep the host shell responsible for sidebar, topbar, remote mount, and theme mode',
|
|
479
|
+
'keep remotes focused on feature routes and page business content',
|
|
480
|
+
'read `uiAiManifest` before choosing components',
|
|
481
|
+
'read `uiThemeLayerAssets` before choosing a bundled theme layer',
|
|
482
|
+
'read `uiThemeContract` before changing colors, surfaces, borders, radius, or shadows',
|
|
483
|
+
'keep UI token-driven and theme-driven',
|
|
484
|
+
]
|
|
485
|
+
const doNotRules = [
|
|
486
|
+
'import from `MainFe` unless the task explicitly targets a legacy screen',
|
|
487
|
+
`invent a second palette or one-off brand colors outside \`${themeFile}\``,
|
|
488
|
+
'replace the shared dark-sidebar + gradient-topbar shell with a flat blank layout unless the user explicitly requests it',
|
|
489
|
+
'restyle individual pages if the preset tokens can solve it globally',
|
|
490
|
+
'create duplicate Button/Input/Select wrappers unless a project-specific behavior is required',
|
|
491
|
+
'let each remote define a different shell or a different palette',
|
|
492
|
+
]
|
|
493
|
+
const componentChoices = [
|
|
494
|
+
'Input for short text',
|
|
495
|
+
'Textarea for multiline text',
|
|
496
|
+
'Select for small fixed options',
|
|
497
|
+
'SearchableSelect for larger local option sets',
|
|
498
|
+
'Combobox for type-and-pick',
|
|
499
|
+
'AsyncCombobox for remote search',
|
|
500
|
+
'MultiSelect for multi-pick',
|
|
501
|
+
'Field only for custom controls or grouped content',
|
|
502
|
+
'DataTable for tabular records',
|
|
503
|
+
]
|
|
504
|
+
const outputCheck = [
|
|
505
|
+
'The shell brief and screen brief are complete',
|
|
506
|
+
'Any missing required input was explicitly asked for before coding',
|
|
507
|
+
`The shell matches \`${layoutPreset.id}\` with a dark sidebar, gradient topbar, intro card, and card-based body structure`,
|
|
508
|
+
'The chosen components match the page kind and the brief',
|
|
509
|
+
'No `MainFe` imports were used',
|
|
510
|
+
'No hardcoded brand colors were added in page components',
|
|
511
|
+
`Theme decisions live in \`${themeFile}\`, not in ad hoc JSX styling`,
|
|
512
|
+
'The app entry import order is package stylesheet -> bundled theme layer if present -> project theme override',
|
|
513
|
+
'The shell still lives in the host app and remotes only own business screens',
|
|
514
|
+
'Spacing, card structure, and actions are consistent with the shared preset',
|
|
515
|
+
'The layout shell stayed stable even if the page body changed',
|
|
516
|
+
]
|
|
517
|
+
|
|
518
|
+
return `# dev
|
|
519
|
+
|
|
520
|
+
CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:
|
|
452
521
|
|
|
453
522
|
\`\`\`yaml
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
523
|
+
activation-instructions:
|
|
524
|
+
${renderYamlList(activationInstructions, 2)}
|
|
525
|
+
agent:
|
|
526
|
+
name: James
|
|
527
|
+
id: dev
|
|
528
|
+
title: Theme-Locked Full Stack Developer
|
|
529
|
+
icon: 💻
|
|
530
|
+
whenToUse: ${quoteYaml(`Use for UI implementation, shell alignment, theme-safe refactors, and development best practices with ${PACKAGE_NAME}`)}
|
|
531
|
+
customization:
|
|
532
|
+
package_name: ${quoteYaml(PACKAGE_NAME)}
|
|
533
|
+
package_core: ${quoteYaml(`${PACKAGE_NAME}/core`)}
|
|
534
|
+
theme_preset_id: ${quoteYaml(themePreset.id)}
|
|
535
|
+
theme_preset_label: ${quoteYaml(themePreset.label)}
|
|
536
|
+
theme_preset_description: ${quoteYaml(themePreset.description)}
|
|
537
|
+
theme_file: ${quoteYaml(themeFile)}
|
|
538
|
+
layout_preset_id: ${quoteYaml(layoutPreset.id)}
|
|
539
|
+
layout_preset_label: ${quoteYaml(layoutPreset.label)}
|
|
540
|
+
layout_preset_description: ${quoteYaml(layoutPreset.description)}
|
|
541
|
+
layout_file: ${quoteYaml(layoutFile)}
|
|
542
|
+
import_order:
|
|
543
|
+
${renderYamlList(importOrder, 6)}
|
|
544
|
+
recommended_for:
|
|
545
|
+
${renderYamlList(themePreset.recommendedFor, 6)}
|
|
546
|
+
shell_recipe:
|
|
547
|
+
${renderYamlList(layoutPreset.shellRecipe, 6)}
|
|
548
|
+
persona:
|
|
549
|
+
role: ${quoteYaml('Expert Senior UI Engineer & Implementation Specialist')}
|
|
550
|
+
style: ${quoteYaml('Extremely concise, pragmatic, detail-oriented, solution-focused')}
|
|
551
|
+
identity: ${quoteYaml(`Expert who implements screens by locking to the selected theme preset, the shared shell contract, and canonical ${PACKAGE_NAME} components`)}
|
|
552
|
+
focus: ${quoteYaml('Executing UI tasks with precision, keeping shell and theme stable, and avoiding ad hoc palette drift')}
|
|
553
|
+
core_principles:
|
|
554
|
+
${renderYamlList(corePrinciples, 2)}
|
|
555
|
+
commands:
|
|
556
|
+
- help: ${quoteYaml('Show numbered list of available commands, selected theme preset, and shared layout preset')}
|
|
557
|
+
- build-screen:
|
|
558
|
+
- order-of-execution: ${quoteYaml('Read theme and layout source -> fill shell brief + screen brief -> verify stylesheet import order -> map blocks to canonical components -> implement shell/body -> run tests/validations -> summarize changes')}
|
|
559
|
+
- required-inputs:
|
|
560
|
+
${renderYamlList(layoutPreset.requiredFields, 10)}
|
|
561
|
+
- ask-before-coding:
|
|
562
|
+
${renderYamlList(layoutPreset.askBeforeCoding, 10)}
|
|
563
|
+
- page-kinds:
|
|
564
|
+
${renderYamlList(pageKinds, 10)}
|
|
565
|
+
- shell-lock:
|
|
566
|
+
${renderYamlList(layoutPreset.shellRecipe, 10)}
|
|
567
|
+
- blocking: ${quoteYaml('HALT for: Missing required brief values | conflicting theme instructions | unknown bundled theme activation | failing regression | requests to mix multiple palettes')}
|
|
568
|
+
- ready-for-review: ${quoteYaml('Shell matches the shared preset + Theme stays token-driven + Canonical components are used + Validations pass')}
|
|
569
|
+
- completion: ${quoteYaml('Shell brief complete -> Screen brief complete -> Import order correct -> No MainFe drift -> Tests/validations pass -> Summarize changes')}
|
|
570
|
+
- review-theme: ${quoteYaml('Audit or update theme usage without inventing a second palette')}
|
|
571
|
+
- run-tests: ${quoteYaml('Execute the package build and any relevant validations for the touched files')}
|
|
572
|
+
- explain: ${quoteYaml('Teach me what and why you did whatever you just did in detail so I can learn')}
|
|
573
|
+
- exit: ${quoteYaml('Say goodbye as the Developer, and then abandon inhabiting this persona')}
|
|
574
|
+
dependencies:
|
|
575
|
+
docs:
|
|
576
|
+
${renderYamlList(['README.md', 'AI_SETUP.md'], 4)}
|
|
577
|
+
project-files:
|
|
578
|
+
${renderYamlList([themeFile, layoutFile], 4)}
|
|
579
|
+
runtime-contracts:
|
|
580
|
+
${renderYamlList(runtimeContracts, 4)}
|
|
581
|
+
brief_templates:
|
|
582
|
+
shell:
|
|
583
|
+
layoutPreset: ${quoteYaml(layoutPreset.id)}
|
|
584
|
+
workspaceLabel:
|
|
585
|
+
timezoneLabel:
|
|
586
|
+
userBadgeLabel:
|
|
587
|
+
pageTabs:
|
|
588
|
+
- value:
|
|
589
|
+
label:
|
|
590
|
+
activePageTab:
|
|
591
|
+
searchPlaceholder:
|
|
592
|
+
toolbarNote:
|
|
593
|
+
screen:
|
|
594
|
+
pageKind: ${quoteYaml('list | form | detail | dashboard')}
|
|
595
|
+
routeUrl:
|
|
596
|
+
sidebarItems:
|
|
597
|
+
- id:
|
|
598
|
+
title:
|
|
599
|
+
href:
|
|
600
|
+
icon:
|
|
601
|
+
activeSidebarItemId:
|
|
602
|
+
breadcrumbs:
|
|
603
|
+
- label:
|
|
604
|
+
href:
|
|
605
|
+
current:
|
|
606
|
+
pageTitle:
|
|
607
|
+
pageSubtitle:
|
|
608
|
+
primaryAction:
|
|
609
|
+
label:
|
|
610
|
+
href:
|
|
611
|
+
secondaryActions:
|
|
612
|
+
- label:
|
|
613
|
+
href:
|
|
614
|
+
summaryStats:
|
|
615
|
+
- label:
|
|
616
|
+
value:
|
|
617
|
+
delta:
|
|
618
|
+
trend:
|
|
619
|
+
filters:
|
|
620
|
+
- type:
|
|
621
|
+
label:
|
|
622
|
+
key:
|
|
623
|
+
tableColumns:
|
|
624
|
+
- key:
|
|
625
|
+
title:
|
|
626
|
+
type:
|
|
627
|
+
rowActions:
|
|
628
|
+
- label:
|
|
629
|
+
key:
|
|
630
|
+
formSections:
|
|
631
|
+
- title:
|
|
632
|
+
fields: []
|
|
633
|
+
fields:
|
|
634
|
+
- name:
|
|
635
|
+
type:
|
|
636
|
+
label:
|
|
637
|
+
required:
|
|
638
|
+
helperText:
|
|
639
|
+
detailSections:
|
|
640
|
+
- title:
|
|
641
|
+
type:
|
|
642
|
+
emptyState:
|
|
643
|
+
title:
|
|
644
|
+
description:
|
|
645
|
+
actionLabel:
|
|
646
|
+
permissions: []
|
|
647
|
+
page_frame_recipes:
|
|
648
|
+
list:
|
|
649
|
+
${renderYamlList(pageFrameRecipes.list, 4)}
|
|
650
|
+
form:
|
|
651
|
+
${renderYamlList(pageFrameRecipes.form, 4)}
|
|
652
|
+
detail:
|
|
653
|
+
${renderYamlList(pageFrameRecipes.detail, 4)}
|
|
654
|
+
dashboard:
|
|
655
|
+
${renderYamlList(pageFrameRecipes.dashboard, 4)}
|
|
656
|
+
implementation_rules:
|
|
657
|
+
hard-rules:
|
|
658
|
+
${renderYamlList(hardRules, 4)}
|
|
659
|
+
do-not:
|
|
660
|
+
${renderYamlList(doNotRules, 4)}
|
|
661
|
+
component-choice:
|
|
662
|
+
${renderYamlList(componentChoices, 4)}
|
|
663
|
+
output_check:
|
|
664
|
+
${renderYamlList(outputCheck, 2)}
|
|
507
665
|
\`\`\`
|
|
508
|
-
|
|
509
|
-
## Shell Lock
|
|
510
|
-
|
|
511
|
-
Keep the layout aligned with \`${layoutPreset.id}\`:
|
|
512
|
-
|
|
513
|
-
${renderMarkdownList(layoutPreset.shellRecipe)}
|
|
514
|
-
|
|
515
|
-
## Page Frame Recipes
|
|
516
|
-
|
|
517
|
-
- \`list\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> toolbar \`Card\` -> \`DataTable\` \`Card\`
|
|
518
|
-
- \`form\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> top actions -> sectioned form \`Card\` blocks -> bottom action row
|
|
519
|
-
- \`detail\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> status/actions -> summary metadata \`Card\` -> detail \`Card\` blocks -> related \`DataTable\`
|
|
520
|
-
- \`dashboard\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> toolbar \`Card\` -> \`Stat\` row -> insight \`Card\` blocks and \`DataTable\`
|
|
521
|
-
|
|
522
|
-
## Hard Rules
|
|
523
|
-
|
|
524
|
-
- import \`${PACKAGE_NAME}/styles.css\` once at the app entry
|
|
525
|
-
- import the project theme override file after the package stylesheet
|
|
526
|
-
- use root exports from \`${PACKAGE_NAME}\`
|
|
527
|
-
- use \`${themeFile}\` as the only source of truth for colors, radius, surfaces, and shadows
|
|
528
|
-
- use \`${layoutFile}\` as the source of truth for the shell layout and shared page frame
|
|
529
|
-
- keep layouts and component choices aligned with the shared preset-driven UI used across projects
|
|
530
|
-
- read \`uiAiManifest\` before choosing components
|
|
531
|
-
- read \`uiThemeContract\` before changing colors, surfaces, borders, radius, or shadows
|
|
532
|
-
- keep UI token-driven and theme-driven
|
|
533
|
-
|
|
534
|
-
Do not:
|
|
535
|
-
- import from \`MainFe\` unless the task explicitly targets a legacy screen
|
|
536
|
-
- invent a second palette or one-off brand colors outside \`${themeFile}\`
|
|
537
|
-
- replace the shared dark-sidebar + gradient-topbar shell with a flat blank layout unless the user explicitly requests it
|
|
538
|
-
- restyle individual pages if the preset tokens can solve it globally
|
|
539
|
-
- create duplicate Button/Input/Select wrappers unless a project-specific behavior is required
|
|
540
|
-
|
|
541
|
-
## Component Choice
|
|
542
|
-
|
|
543
|
-
- \`Input\` for short text
|
|
544
|
-
- \`Textarea\` for multiline text
|
|
545
|
-
- \`Select\` for small fixed options
|
|
546
|
-
- \`SearchableSelect\` for larger local option sets
|
|
547
|
-
- \`Combobox\` for type-and-pick
|
|
548
|
-
- \`AsyncCombobox\` for remote search
|
|
549
|
-
- \`MultiSelect\` for multi-pick
|
|
550
|
-
- \`Field\` only for custom controls or grouped content
|
|
551
|
-
- \`DataTable\` for tabular records
|
|
552
|
-
|
|
553
|
-
## Output Check
|
|
554
|
-
|
|
555
|
-
Before finishing, confirm all of these are true:
|
|
556
|
-
|
|
557
|
-
- The shell brief and screen brief are complete.
|
|
558
|
-
- Any missing required input was explicitly asked for before coding.
|
|
559
|
-
- The shell matches \`${layoutPreset.id}\` with a dark sidebar, gradient topbar, intro card, and card-based body structure.
|
|
560
|
-
- The chosen components match the page kind and the brief.
|
|
561
|
-
- No \`MainFe\` imports were used.
|
|
562
|
-
- No hardcoded brand colors were added in page components.
|
|
563
|
-
- Theme decisions live in \`${themeFile}\`, not in ad hoc JSX styling.
|
|
564
|
-
- Spacing, card structure, and actions are consistent with the shared preset.
|
|
565
|
-
- The layout shell stayed stable even if the page body changed.
|
|
566
666
|
`
|
|
567
667
|
}
|
|
568
668
|
|
|
@@ -605,6 +705,24 @@ ${layoutPreset.requiredFields.map((item) => ` '${item}',`).join('\n')}
|
|
|
605
705
|
askBeforeCoding: [
|
|
606
706
|
${layoutPreset.askBeforeCoding.map((item) => ` '${item}',`).join('\n')}
|
|
607
707
|
],
|
|
708
|
+
workspaceStructure: {
|
|
709
|
+
packageUi: ['components', 'theme contracts', 'bundled theme layers', 'color-mode runtime'],
|
|
710
|
+
shellApp: ['src/app', 'src/layouts', 'src/routes', 'src/remotes', 'src/styles/ui-theme.css'],
|
|
711
|
+
remoteApp: ['src/features', 'src/pages', 'src/routes', 'src/services', 'src/styles/index.css'],
|
|
712
|
+
},
|
|
713
|
+
themeLayers: [
|
|
714
|
+
'${PACKAGE_NAME}/styles.css',
|
|
715
|
+
'${PACKAGE_NAME}/themes/theme-ui-new-main-fe.css (optional bundled package layer)',
|
|
716
|
+
'${themeFile}',
|
|
717
|
+
],
|
|
718
|
+
setupSteps: [
|
|
719
|
+
'Import the package stylesheet once at the host app entry.',
|
|
720
|
+
'If the app wants a bundled package theme layer, import it after the package stylesheet.',
|
|
721
|
+
'Import the project themeSource after the bundled theme layer.',
|
|
722
|
+
'If the chosen theme layer is client-theme-scoped, set data-client-theme at the document root.',
|
|
723
|
+
'Initialize color mode at the host app entry and let the host own shell/theme concerns.',
|
|
724
|
+
'Keep remotes focused on feature routes and business screens instead of rebuilding the global shell.',
|
|
725
|
+
],
|
|
608
726
|
shell: {
|
|
609
727
|
sidebar: {
|
|
610
728
|
tone: 'dark',
|
|
@@ -641,6 +759,8 @@ ${layoutPreset.askBeforeCoding.map((item) => ` '${item}',`).join('\n')}
|
|
|
641
759
|
'Keep the dark sidebar and gradient topbar shell stable across screens.',
|
|
642
760
|
'Do not replace the intro card with a bare page title row.',
|
|
643
761
|
'Use the shared theme tokens from the themeSource file for color, border, surface, and shadow decisions.',
|
|
762
|
+
'Import theme layers in this order: package stylesheet, bundled package theme layer when present, then themeSource.',
|
|
763
|
+
'Keep the host app responsible for the global shell and keep remotes page-scoped.',
|
|
644
764
|
'Only omit tabs or toolbar sections when the brief explicitly leaves them out.',
|
|
645
765
|
'Ask for missing required fields before generating JSX instead of guessing from the screenshot.',
|
|
646
766
|
],
|
|
@@ -720,6 +840,8 @@ console.log(`- ${layoutResult.path}: ${layoutResult.status}`)
|
|
|
720
840
|
console.log('')
|
|
721
841
|
console.log('Next steps:')
|
|
722
842
|
console.log(`1. Import \`${PACKAGE_NAME}/styles.css\` once at your app entry.`)
|
|
723
|
-
console.log(`2.
|
|
724
|
-
console.log(`3.
|
|
725
|
-
console.log(`4.
|
|
843
|
+
console.log(`2. If you want a bundled package theme layer, import one from \`${PACKAGE_NAME}/themes/*\` right after the package stylesheet.`)
|
|
844
|
+
console.log(`3. Import \`${options.themeFile}\` after the bundled theme layer.`)
|
|
845
|
+
console.log(`4. Let your agent read \`${options.agentsFile}\` and \`${options.layoutFile}\` before generating UI.`)
|
|
846
|
+
console.log('5. Keep the host app responsible for the global shell and keep remotes page-scoped.')
|
|
847
|
+
console.log(`6. Re-run this command with \`--theme <preset> --force\` if you want another approved preset.`)
|