aeon-ui-engine 1.0.3 → 1.2.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 +34 -0
- package/CONSUMER.md +82 -40
- package/README.md +47 -16
- package/package.json +9 -2
- package/packages/cli/README.md +17 -0
- package/packages/cli/dist/bin.d.ts +1 -0
- package/packages/cli/dist/bin.js +35 -0
- package/packages/cli/dist/chunk-IW5NT2Z2.js +103 -0
- package/packages/cli/dist/index.d.ts +10 -0
- package/packages/cli/dist/index.js +6 -0
- package/packages/cli/node_modules/.bin/esbuild +21 -0
- package/packages/cli/node_modules/.bin/jiti +21 -0
- package/packages/cli/node_modules/.bin/tsc +21 -0
- package/packages/cli/node_modules/.bin/tsserver +21 -0
- package/packages/cli/node_modules/.bin/tsup +21 -0
- package/packages/cli/node_modules/.bin/tsup-node +21 -0
- package/packages/cli/node_modules/.bin/tsx +21 -0
- package/packages/cli/node_modules/.bin/vite +21 -0
- package/packages/cli/node_modules/.bin/vitest +21 -0
- package/packages/cli/package.json +50 -0
- package/packages/cli/src/bin.ts +34 -0
- package/packages/cli/src/index.ts +1 -0
- package/packages/cli/src/init.ts +107 -0
- package/packages/cli/tsconfig.json +10 -0
- package/packages/core/README.md +7 -1
- package/packages/core/dist/index.d.ts +255 -7
- package/packages/core/dist/index.js +372 -2
- package/packages/core/node_modules/.bin/esbuild +4 -4
- package/packages/core/node_modules/.bin/vite +4 -4
- package/packages/core/node_modules/.bin/vitest +2 -2
- package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/packages/core/package.json +17 -5
- package/packages/core/src/anatomy.ts +234 -5
- package/packages/core/src/brand-theme.ts +172 -0
- package/packages/core/src/index.ts +1 -0
- package/packages/core/src/machine.test.ts +62 -1
- package/packages/core/src/machine.ts +93 -0
- package/packages/core/src/theme.ts +105 -0
- package/packages/panda/aeon.css +8 -0
- package/packages/panda/package.json +1 -1
- package/packages/panda/panda.config.ts +58 -1
- package/packages/panda/src/recipes/app-shell.ts +137 -0
- package/packages/panda/src/recipes/avatar.ts +131 -0
- package/packages/panda/src/recipes/bar.ts +206 -0
- package/packages/panda/src/recipes/button-group.ts +12 -4
- package/packages/panda/src/recipes/button.ts +1 -0
- package/packages/panda/src/recipes/combobox.ts +2 -1
- package/packages/panda/src/recipes/composer.ts +81 -0
- package/packages/panda/src/recipes/content.ts +104 -0
- package/packages/panda/src/recipes/conversation.ts +106 -0
- package/packages/panda/src/recipes/entry.ts +217 -0
- package/packages/panda/src/recipes/field.ts +12 -2
- package/packages/panda/src/recipes/floating.ts +26 -13
- package/packages/panda/src/recipes/identity.ts +73 -0
- package/packages/panda/src/recipes/index.ts +15 -0
- package/packages/panda/src/recipes/list-row.ts +109 -0
- package/packages/panda/src/recipes/metric-strip.ts +80 -0
- package/packages/panda/src/recipes/nav.ts +155 -0
- package/packages/panda/src/recipes/panel.ts +156 -0
- package/packages/panda/src/recipes/pin-input.ts +3 -2
- package/packages/panda/src/recipes/profile-header.ts +120 -0
- package/packages/panda/src/recipes/select.ts +2 -1
- package/packages/panda/src/recipes/slider.ts +6 -4
- package/packages/panda/src/recipes/theme-switcher.ts +110 -0
- package/packages/panda/src/recipes/thread.ts +88 -0
- package/packages/panda/src/theme/catalog-types.ts +2 -0
- package/packages/panda/src/theme/catalog.ts +23 -0
- package/packages/panda/src/theme/chrome.css +2 -1
- package/packages/panda/src/theme/consumer-shell.css +129 -0
- package/packages/panda/src/theme/electron.css +30 -0
- package/packages/panda/src/theme/global-theme-css.ts +9 -0
- package/packages/panda/src/theme/omarchy.themes.ts +607 -0
- package/packages/panda/src/theme/palette.ts +3 -0
- package/packages/panda/src/theme/scrollbars.css +58 -21
- package/packages/panda/src/theme/themes.config.ts +39 -1
- package/packages/panda/styled-system/css/conditions.mjs +1 -1
- package/packages/panda/styled-system/css/css.mjs +1 -1
- package/packages/panda/styled-system/css/sva.mjs +9 -4
- package/packages/panda/styled-system/helpers.mjs +11 -22
- package/packages/panda/styled-system/jsx/create-style-context.d.ts +54 -0
- package/packages/panda/styled-system/jsx/create-style-context.mjs +121 -0
- package/packages/panda/styled-system/jsx/factory.mjs +14 -5
- package/packages/panda/styled-system/jsx/index.d.ts +1 -0
- package/packages/panda/styled-system/jsx/index.mjs +1 -0
- package/packages/panda/styled-system/jsx/is-valid-prop.mjs +2 -2
- package/packages/panda/styled-system/patterns/aspect-ratio.d.ts +0 -1
- package/packages/panda/styled-system/patterns/bleed.d.ts +0 -1
- package/packages/panda/styled-system/patterns/box.d.ts +0 -1
- package/packages/panda/styled-system/patterns/center.d.ts +0 -1
- package/packages/panda/styled-system/patterns/circle.d.ts +0 -1
- package/packages/panda/styled-system/patterns/container.d.ts +0 -1
- package/packages/panda/styled-system/patterns/cq.d.ts +0 -1
- package/packages/panda/styled-system/patterns/divider.d.ts +0 -1
- package/packages/panda/styled-system/patterns/flex.d.ts +0 -1
- package/packages/panda/styled-system/patterns/float.d.ts +0 -1
- package/packages/panda/styled-system/patterns/grid-item.d.ts +0 -1
- package/packages/panda/styled-system/patterns/grid.d.ts +0 -1
- package/packages/panda/styled-system/patterns/grid.mjs +1 -1
- package/packages/panda/styled-system/patterns/hstack.d.ts +0 -1
- package/packages/panda/styled-system/patterns/hstack.mjs +1 -1
- package/packages/panda/styled-system/patterns/link-overlay.d.ts +0 -1
- package/packages/panda/styled-system/patterns/spacer.d.ts +0 -1
- package/packages/panda/styled-system/patterns/spacer.mjs +6 -2
- package/packages/panda/styled-system/patterns/square.d.ts +0 -1
- package/packages/panda/styled-system/patterns/stack.d.ts +0 -1
- package/packages/panda/styled-system/patterns/stack.mjs +1 -1
- package/packages/panda/styled-system/patterns/visually-hidden.d.ts +0 -1
- package/packages/panda/styled-system/patterns/vstack.d.ts +0 -1
- package/packages/panda/styled-system/patterns/vstack.mjs +1 -1
- package/packages/panda/styled-system/patterns/wrap.d.ts +0 -1
- package/packages/panda/styled-system/patterns/wrap.mjs +1 -1
- package/packages/panda/styled-system/recipes/aeon-accordion.d.ts +4 -3
- package/packages/panda/styled-system/recipes/aeon-accordion.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-app-shell.d.ts +34 -0
- package/packages/panda/styled-system/recipes/aeon-app-shell.mjs +70 -0
- package/packages/panda/styled-system/recipes/aeon-async.d.ts +4 -3
- package/packages/panda/styled-system/recipes/aeon-async.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-avatar.d.ts +36 -0
- package/packages/panda/styled-system/recipes/aeon-avatar.mjs +57 -0
- package/packages/panda/styled-system/recipes/aeon-badge.d.ts +3 -0
- package/packages/panda/styled-system/recipes/aeon-bar.d.ts +40 -0
- package/packages/panda/styled-system/recipes/aeon-bar.mjs +77 -0
- package/packages/panda/styled-system/recipes/aeon-button-group.d.ts +3 -2
- package/packages/panda/styled-system/recipes/aeon-button.d.ts +3 -2
- package/packages/panda/styled-system/recipes/aeon-checkbox.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-checkbox.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-combobox.d.ts +4 -3
- package/packages/panda/styled-system/recipes/aeon-combobox.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-composer.d.ts +31 -0
- package/packages/panda/styled-system/recipes/aeon-composer.mjs +45 -0
- package/packages/panda/styled-system/recipes/aeon-content.d.ts +34 -0
- package/packages/panda/styled-system/recipes/aeon-content.mjs +70 -0
- package/packages/panda/styled-system/recipes/aeon-conversation.d.ts +31 -0
- package/packages/panda/styled-system/recipes/aeon-conversation.mjs +61 -0
- package/packages/panda/styled-system/recipes/aeon-dialog.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-dialog.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-entry.d.ts +38 -0
- package/packages/panda/styled-system/recipes/aeon-entry.mjs +100 -0
- package/packages/panda/styled-system/recipes/aeon-field.d.ts +4 -3
- package/packages/panda/styled-system/recipes/aeon-field.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-identity.d.ts +36 -0
- package/packages/panda/styled-system/recipes/aeon-identity.mjs +63 -0
- package/packages/panda/styled-system/recipes/aeon-list-row.d.ts +33 -0
- package/packages/panda/styled-system/recipes/aeon-list-row.mjs +49 -0
- package/packages/panda/styled-system/recipes/aeon-menu.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-menu.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-metric-strip.d.ts +36 -0
- package/packages/panda/styled-system/recipes/aeon-metric-strip.mjs +54 -0
- package/packages/panda/styled-system/recipes/aeon-nav.d.ts +38 -0
- package/packages/panda/styled-system/recipes/aeon-nav.mjs +69 -0
- package/packages/panda/styled-system/recipes/aeon-panel.d.ts +34 -0
- package/packages/panda/styled-system/recipes/aeon-panel.mjs +58 -0
- package/packages/panda/styled-system/recipes/aeon-pin-input.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-pin-input.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-popover.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-popover.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-profile-header.d.ts +36 -0
- package/packages/panda/styled-system/recipes/aeon-profile-header.mjs +62 -0
- package/packages/panda/styled-system/recipes/aeon-progress.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-progress.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-radio-group.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-radio-group.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-scroll.d.ts +4 -3
- package/packages/panda/styled-system/recipes/aeon-scroll.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-select.d.ts +4 -3
- package/packages/panda/styled-system/recipes/aeon-select.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-separator.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-separator.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-slider.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-slider.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-switch.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-switch.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-tabs.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-tabs.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-theme-switcher.d.ts +34 -0
- package/packages/panda/styled-system/recipes/aeon-theme-switcher.mjs +59 -0
- package/packages/panda/styled-system/recipes/aeon-thread.d.ts +31 -0
- package/packages/panda/styled-system/recipes/aeon-thread.mjs +53 -0
- package/packages/panda/styled-system/recipes/aeon-toast.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-toast.mjs +1 -0
- package/packages/panda/styled-system/recipes/aeon-tooltip.d.ts +4 -1
- package/packages/panda/styled-system/recipes/aeon-tooltip.mjs +1 -0
- package/packages/panda/styled-system/recipes/index.d.ts +16 -1
- package/packages/panda/styled-system/recipes/index.mjs +16 -1
- package/packages/panda/styled-system/styles.css +2317 -450
- package/packages/panda/styled-system/tokens/index.mjs +43 -7
- package/packages/panda/styled-system/tokens/tokens.d.ts +5 -5
- package/packages/panda/styled-system/types/composition.d.ts +86 -23
- package/packages/panda/styled-system/types/conditions.d.ts +34 -10
- package/packages/panda/styled-system/types/csstype.d.ts +6405 -5133
- package/packages/panda/styled-system/types/jsx.d.ts +27 -10
- package/packages/panda/styled-system/types/pattern.d.ts +4 -4
- package/packages/panda/styled-system/types/prop-type.d.ts +11 -1
- package/packages/panda/styled-system/types/style-props.d.ts +2763 -2165
- package/packages/panda/styled-system/types/system-types.d.ts +38 -80
- package/packages/panda/theme-runtime.css +945 -0
- package/packages/primitives/dist/chunk-4NOKRUSG.js +81 -0
- package/packages/primitives/dist/chunk-R25CUHNF.js +46 -0
- package/packages/primitives/dist/chunk-RO2DMFN5.js +89 -0
- package/packages/primitives/dist/chunk-V5D7LS4J.js +61 -0
- package/packages/primitives/dist/chunk-YBPNI2LI.js +70 -0
- package/packages/primitives/dist/index.d.ts +5 -0
- package/packages/primitives/dist/index.js +46 -14
- package/packages/primitives/dist/machines/app-nav.d.ts +96 -0
- package/packages/primitives/dist/machines/app-nav.js +12 -0
- package/packages/primitives/dist/machines/app-shell.d.ts +57 -0
- package/packages/primitives/dist/machines/app-shell.js +8 -0
- package/packages/primitives/dist/machines/async.d.ts +4 -4
- package/packages/primitives/dist/machines/content-region.d.ts +72 -0
- package/packages/primitives/dist/machines/content-region.js +8 -0
- package/packages/primitives/dist/machines/panel.d.ts +50 -0
- package/packages/primitives/dist/machines/panel.js +6 -0
- package/packages/primitives/dist/machines/sticky-bar.d.ts +62 -0
- package/packages/primitives/dist/machines/sticky-bar.js +8 -0
- package/packages/primitives/node_modules/.bin/esbuild +21 -0
- package/packages/primitives/node_modules/.bin/vite +21 -0
- package/packages/primitives/node_modules/.bin/vitest +2 -2
- package/packages/primitives/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/packages/primitives/package.json +15 -5
- package/packages/primitives/scripts/xstate-introspect.mjs +35 -0
- package/packages/primitives/src/__tests__/app-nav.test.ts +30 -0
- package/packages/primitives/src/index.ts +5 -0
- package/packages/primitives/src/machines/app-nav.ts +107 -0
- package/packages/primitives/src/machines/app-shell.ts +63 -0
- package/packages/primitives/src/machines/content-region.ts +107 -0
- package/packages/primitives/src/machines/panel.ts +71 -0
- package/packages/primitives/src/machines/sticky-bar.ts +89 -0
- package/packages/react/dist/index.d.ts +536 -17
- package/packages/react/dist/index.js +2163 -479
- package/packages/react/node_modules/.bin/esbuild +21 -0
- package/packages/react/node_modules/.bin/vite +21 -0
- package/packages/react/node_modules/.bin/vitest +2 -2
- package/packages/react/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/packages/react/package.json +18 -7
- package/packages/react/src/app-nav/index.tsx +249 -0
- package/packages/react/src/app-shell/index.tsx +154 -0
- package/packages/react/src/async/index.tsx +6 -1
- package/packages/react/src/async/map-content-state.ts +18 -0
- package/packages/react/src/avatar/index.tsx +23 -1
- package/packages/react/src/bar/index.tsx +101 -0
- package/packages/react/src/button/index.tsx +4 -2
- package/packages/react/src/composer/index.tsx +75 -0
- package/packages/react/src/content/index.tsx +149 -0
- package/packages/react/src/conversation/index.tsx +78 -0
- package/packages/react/src/entry/index.tsx +85 -0
- package/packages/react/src/field/index.tsx +31 -18
- package/packages/react/src/hooks/use-fit-text.ts +59 -0
- package/packages/react/src/identity/index.tsx +110 -0
- package/packages/react/src/index.ts +19 -0
- package/packages/react/src/list-row/index.tsx +80 -0
- package/packages/react/src/metric-strip/index.tsx +88 -0
- package/packages/react/src/nav/index.tsx +155 -0
- package/packages/react/src/panel/index.tsx +267 -0
- package/packages/react/src/profile-header/index.tsx +91 -0
- package/packages/react/src/prompt/index.tsx +161 -0
- package/packages/react/src/radio-group/index.tsx +19 -7
- package/packages/react/src/slider/index.tsx +3 -1
- package/packages/react/src/status-banner/index.tsx +84 -0
- package/packages/react/src/sticky-bar/index.tsx +135 -0
- package/packages/react/src/switch/index.tsx +7 -1
- package/packages/react/src/theme-switcher/index.tsx +227 -0
- package/packages/react/src/thread/index.tsx +95 -0
- package/packages/react/src/toast/primitives.tsx +2 -2
- package/packages/react/src/tooltip/tooltip.test.tsx +9 -1
- package/packages/react/tsconfig.json +2 -1
- package/packages/schemas/README.md +52 -0
- package/packages/schemas/dist/index.d.ts +287 -0
- package/packages/schemas/dist/index.js +701 -0
- package/packages/schemas/json/accordion.json +132 -0
- package/packages/schemas/json/async.json +161 -0
- package/packages/schemas/json/button.json +170 -0
- package/packages/schemas/json/catalog.json +2299 -0
- package/packages/schemas/json/checkbox.json +136 -0
- package/packages/schemas/json/combobox.json +130 -0
- package/packages/schemas/json/dialog.json +154 -0
- package/packages/schemas/json/field.json +171 -0
- package/packages/schemas/json/menu.json +138 -0
- package/packages/schemas/json/popover.json +133 -0
- package/packages/schemas/json/progress.json +137 -0
- package/packages/schemas/json/scroll.json +129 -0
- package/packages/schemas/json/select.json +140 -0
- package/packages/schemas/json/switch.json +136 -0
- package/packages/schemas/json/tabs.json +135 -0
- package/packages/schemas/json/toast.json +141 -0
- package/packages/schemas/json/tooltip.json +123 -0
- package/packages/schemas/node_modules/.bin/esbuild +21 -0
- package/packages/schemas/node_modules/.bin/jiti +21 -0
- package/packages/schemas/node_modules/.bin/tsc +21 -0
- package/packages/schemas/node_modules/.bin/tsserver +21 -0
- package/packages/schemas/node_modules/.bin/tsup +21 -0
- package/packages/schemas/node_modules/.bin/tsup-node +21 -0
- package/packages/schemas/node_modules/.bin/tsx +21 -0
- package/packages/schemas/node_modules/.bin/vite +21 -0
- package/packages/schemas/node_modules/.bin/vitest +21 -0
- package/packages/schemas/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/schemas/package.json +56 -0
- package/packages/schemas/prompts/cursorrules.md +64 -0
- package/packages/schemas/prompts/statecharts.md +31 -0
- package/packages/schemas/prompts/system.md +30 -0
- package/packages/schemas/registry/catalog.json +54 -0
- package/packages/schemas/registry/components/accordion.json +132 -0
- package/packages/schemas/registry/components/async.json +161 -0
- package/packages/schemas/registry/components/button.json +170 -0
- package/packages/schemas/registry/components/checkbox.json +136 -0
- package/packages/schemas/registry/components/combobox.json +130 -0
- package/packages/schemas/registry/components/dialog.json +154 -0
- package/packages/schemas/registry/components/field.json +171 -0
- package/packages/schemas/registry/components/menu.json +138 -0
- package/packages/schemas/registry/components/popover.json +133 -0
- package/packages/schemas/registry/components/progress.json +137 -0
- package/packages/schemas/registry/components/scroll.json +129 -0
- package/packages/schemas/registry/components/select.json +140 -0
- package/packages/schemas/registry/components/switch.json +136 -0
- package/packages/schemas/registry/components/tabs.json +135 -0
- package/packages/schemas/registry/components/toast.json +141 -0
- package/packages/schemas/registry/components/tooltip.json +123 -0
- package/packages/schemas/registry/machines/async.json +219 -0
- package/packages/schemas/registry/machines/buttonLifecycle.json +224 -0
- package/packages/schemas/registry/machines/dialog.json +143 -0
- package/packages/schemas/registry/machines/field.json +275 -0
- package/packages/schemas/scripts/emit.ts +61 -0
- package/packages/schemas/src/aeon-to-schema.test.ts +70 -0
- package/packages/schemas/src/aeon-to-schema.ts +206 -0
- package/packages/schemas/src/agent-bridge.ts +82 -0
- package/packages/schemas/src/components.ts +307 -0
- package/packages/schemas/src/index.test.ts +25 -0
- package/packages/schemas/src/index.ts +25 -0
- package/packages/schemas/src/prompts.ts +121 -0
- package/packages/schemas/src/registry.ts +73 -0
- package/packages/schemas/src/schema-builder.ts +87 -0
- package/packages/schemas/tsconfig.json +9 -0
- package/packages/solid/package.json +2 -2
- package/packages/svelte/node_modules/.bin/esbuild +21 -0
- package/packages/svelte/node_modules/.bin/vite +4 -4
- package/packages/svelte/package.json +15 -5
- package/packages/ui/README.md +19 -6
- package/packages/ui/dist/index.d.ts +254 -9
- package/packages/ui/dist/index.js +690 -139
- package/packages/ui/src/app-nav.tsx +2 -0
- package/packages/ui/src/app-shell.tsx +44 -0
- package/packages/ui/src/async.tsx +2 -1
- package/packages/ui/src/avatar.tsx +35 -0
- package/packages/ui/src/bar.tsx +34 -0
- package/packages/ui/src/composer.tsx +27 -0
- package/packages/ui/src/content.tsx +43 -0
- package/packages/ui/src/conversation.tsx +43 -0
- package/packages/ui/src/entry.tsx +76 -0
- package/packages/ui/src/field.tsx +5 -0
- package/packages/ui/src/identity.tsx +35 -0
- package/packages/ui/src/index.ts +20 -0
- package/packages/ui/src/list-row.tsx +30 -0
- package/packages/ui/src/metric-strip.tsx +29 -0
- package/packages/ui/src/nav.tsx +46 -0
- package/packages/ui/src/panel.tsx +39 -0
- package/packages/ui/src/profile-header.tsx +35 -0
- package/packages/ui/src/prompt.tsx +29 -0
- package/packages/ui/src/status-banner.tsx +1 -0
- package/packages/ui/src/sticky-bar.tsx +42 -0
- package/packages/ui/src/switch.tsx +17 -4
- package/packages/ui/src/theme-switcher.tsx +41 -0
- package/packages/ui/src/thread.tsx +35 -0
- package/packages/vue/package.json +3 -3
- package/scripts/vite-aliases.mjs +65 -3
- package/scripts/xstate-introspect.mjs +68 -0
- package/packages/react/src/async/legacy-region.tsx +0 -38
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
// src/schema-builder.ts
|
|
2
|
+
function componentSchema(opts) {
|
|
3
|
+
const props = opts.props ?? {};
|
|
4
|
+
return {
|
|
5
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
6
|
+
$id: opts.id,
|
|
7
|
+
title: opts.title,
|
|
8
|
+
description: opts.description,
|
|
9
|
+
type: "object",
|
|
10
|
+
additionalProperties: false,
|
|
11
|
+
required: ["component", "scope"],
|
|
12
|
+
properties: {
|
|
13
|
+
component: { const: opts.title.replace(/\s+/g, "") },
|
|
14
|
+
scope: { const: opts.scope },
|
|
15
|
+
parts: {
|
|
16
|
+
type: "array",
|
|
17
|
+
description: "Anatomy part keys \u2014 map to data-aeon-part",
|
|
18
|
+
items: { type: "string", enum: [...opts.parts] },
|
|
19
|
+
uniqueItems: true
|
|
20
|
+
},
|
|
21
|
+
states: {
|
|
22
|
+
type: "array",
|
|
23
|
+
description: "Allowed data-aeon-state values (stable states only)",
|
|
24
|
+
items: { type: "string", enum: [...opts.states] },
|
|
25
|
+
uniqueItems: true
|
|
26
|
+
},
|
|
27
|
+
props: {
|
|
28
|
+
type: "object",
|
|
29
|
+
additionalProperties: false,
|
|
30
|
+
properties: props
|
|
31
|
+
},
|
|
32
|
+
slots: {
|
|
33
|
+
type: "object",
|
|
34
|
+
description: "Named composition slots / compound parts",
|
|
35
|
+
additionalProperties: { type: "string" },
|
|
36
|
+
properties: Object.fromEntries(
|
|
37
|
+
Object.entries(opts.slots ?? {}).map(([k, v]) => [k, { const: v, description: v }])
|
|
38
|
+
)
|
|
39
|
+
},
|
|
40
|
+
machine: {
|
|
41
|
+
type: ["string", "null"],
|
|
42
|
+
description: "XState machine export from @aeon-ui/primitives, or null if prop/React driven",
|
|
43
|
+
const: opts.machine ?? null
|
|
44
|
+
},
|
|
45
|
+
runtime: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: "How headless state is driven at runtime",
|
|
48
|
+
const: opts.runtime ?? "useAeonMachine"
|
|
49
|
+
},
|
|
50
|
+
events: {
|
|
51
|
+
type: "array",
|
|
52
|
+
items: { type: "string", enum: [...opts.events ?? []] }
|
|
53
|
+
},
|
|
54
|
+
examples: {
|
|
55
|
+
type: "array",
|
|
56
|
+
items: { type: "string" },
|
|
57
|
+
default: opts.examples ?? []
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"x-aeon": {
|
|
61
|
+
scope: opts.scope,
|
|
62
|
+
parts: [...opts.parts],
|
|
63
|
+
states: [...opts.states],
|
|
64
|
+
machine: opts.machine ?? null,
|
|
65
|
+
runtime: opts.runtime ?? "useAeonMachine",
|
|
66
|
+
events: [...opts.events ?? []],
|
|
67
|
+
slots: opts.slots ?? {},
|
|
68
|
+
examples: [...opts.examples ?? []]
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/components.ts
|
|
74
|
+
var componentSchemas = {
|
|
75
|
+
button: componentSchema({
|
|
76
|
+
id: "https://aeon-ui.com/schemas/button.json",
|
|
77
|
+
title: "Button",
|
|
78
|
+
description: "Action control. status is a prop projection (not an in-tree machine). Never invent parallel useState for lifecycle.",
|
|
79
|
+
scope: "button",
|
|
80
|
+
parts: ["root", "group", "label", "icon"],
|
|
81
|
+
states: ["idle", "pending", "success", "failure", "disabled"],
|
|
82
|
+
machine: "buttonLifecycleMachine",
|
|
83
|
+
runtime: "status prop",
|
|
84
|
+
props: {
|
|
85
|
+
status: {
|
|
86
|
+
type: "string",
|
|
87
|
+
enum: ["idle", "pending", "success", "failure", "disabled"],
|
|
88
|
+
default: "idle"
|
|
89
|
+
},
|
|
90
|
+
variant: { type: "string", enum: ["solid", "outline", "ghost", "link"] },
|
|
91
|
+
size: { type: "string", enum: ["sm", "md", "lg"] },
|
|
92
|
+
disabled: { type: "boolean" }
|
|
93
|
+
},
|
|
94
|
+
slots: { Root: "button.root", Group: "button.group", Label: "button.label", Icon: "button.icon" },
|
|
95
|
+
examples: [
|
|
96
|
+
'<Button.Root status="pending" aria-busy>Saving\u2026</Button.Root>',
|
|
97
|
+
"const [snap, send] = useAeonMachine(buttonLifecycleMachine)\n<Button.Root status={snap.value as ButtonStatus} onClick={() => send({ type: 'PRESS' })} />"
|
|
98
|
+
]
|
|
99
|
+
}),
|
|
100
|
+
async: componentSchema({
|
|
101
|
+
id: "https://aeon-ui.com/schemas/async.json",
|
|
102
|
+
title: "Async",
|
|
103
|
+
description: "Fetch region with full lifecycle totality: idle \u2192 loading \u2192 success|empty|failure. Always render every stable state in demos.",
|
|
104
|
+
scope: "async",
|
|
105
|
+
parts: ["root", "track", "segment", "readout", "readoutRail", "readoutBody", "actions"],
|
|
106
|
+
states: ["idle", "loading", "success", "empty", "failure"],
|
|
107
|
+
machine: "createAsyncMachine",
|
|
108
|
+
runtime: "useAeonMachine",
|
|
109
|
+
events: ["FETCH", "RESOLVE", "REJECT", "RESET", "STALE", "REFRESH"],
|
|
110
|
+
slots: {
|
|
111
|
+
Root: "async.root",
|
|
112
|
+
Track: "async.track",
|
|
113
|
+
Segment: "async.segment",
|
|
114
|
+
Readout: "async.readout",
|
|
115
|
+
Actions: "async.actions"
|
|
116
|
+
},
|
|
117
|
+
examples: [
|
|
118
|
+
"<Async.Root>\n {/* Content faces via asyncStatusToContentState \u2014 not Track */}\n <Async.Actions />\n</Async.Root>"
|
|
119
|
+
]
|
|
120
|
+
}),
|
|
121
|
+
field: componentSchema({
|
|
122
|
+
id: "https://aeon-ui.com/schemas/field.json",
|
|
123
|
+
title: "Field",
|
|
124
|
+
description: "Parallel regions: interaction \xD7 validation \xD7 submission. Do not collapse into a single error boolean.",
|
|
125
|
+
scope: "field",
|
|
126
|
+
parts: ["root", "label", "control", "textarea", "message", "hint"],
|
|
127
|
+
states: [
|
|
128
|
+
"pristine",
|
|
129
|
+
"dirty",
|
|
130
|
+
"valid",
|
|
131
|
+
"invalid",
|
|
132
|
+
"idle",
|
|
133
|
+
"pending",
|
|
134
|
+
"interaction.pristine",
|
|
135
|
+
"interaction.dirty",
|
|
136
|
+
"validation.valid",
|
|
137
|
+
"validation.invalid",
|
|
138
|
+
"submission.idle",
|
|
139
|
+
"submission.pending"
|
|
140
|
+
],
|
|
141
|
+
machine: "fieldMachine",
|
|
142
|
+
runtime: "useAeonMachine",
|
|
143
|
+
events: ["INPUT", "BLUR", "VALIDATE", "SUBMIT", "SUBMIT_DONE", "SUBMIT_FAIL", "RESET"],
|
|
144
|
+
slots: {
|
|
145
|
+
Root: "field.root",
|
|
146
|
+
Label: "field.label",
|
|
147
|
+
Control: "field.control",
|
|
148
|
+
Message: "field.message",
|
|
149
|
+
Hint: "field.hint"
|
|
150
|
+
}
|
|
151
|
+
}),
|
|
152
|
+
dialog: componentSchema({
|
|
153
|
+
id: "https://aeon-ui.com/schemas/dialog.json",
|
|
154
|
+
title: "Dialog",
|
|
155
|
+
description: "Modal open/closed via dialogMachine. Dismissal is a transition, not ad hoc flags.",
|
|
156
|
+
scope: "dialog",
|
|
157
|
+
parts: [
|
|
158
|
+
"root",
|
|
159
|
+
"trigger",
|
|
160
|
+
"portal",
|
|
161
|
+
"backdrop",
|
|
162
|
+
"positioner",
|
|
163
|
+
"content",
|
|
164
|
+
"title",
|
|
165
|
+
"description",
|
|
166
|
+
"closeTrigger"
|
|
167
|
+
],
|
|
168
|
+
states: ["open", "closed"],
|
|
169
|
+
machine: "dialogMachine",
|
|
170
|
+
runtime: "useAeonMachine",
|
|
171
|
+
events: ["OPEN", "CLOSE", "TOGGLE"],
|
|
172
|
+
slots: {
|
|
173
|
+
Root: "dialog.root",
|
|
174
|
+
Trigger: "dialog.trigger",
|
|
175
|
+
Content: "dialog.content",
|
|
176
|
+
Title: "dialog.title",
|
|
177
|
+
Description: "dialog.description",
|
|
178
|
+
CloseTrigger: "dialog.closeTrigger"
|
|
179
|
+
}
|
|
180
|
+
}),
|
|
181
|
+
switch: componentSchema({
|
|
182
|
+
id: "https://aeon-ui.com/schemas/switch.json",
|
|
183
|
+
title: "Switch",
|
|
184
|
+
description: "Binary toggle via toggleMachine.",
|
|
185
|
+
scope: "switch",
|
|
186
|
+
parts: ["root", "control", "thumb", "label", "hiddenInput"],
|
|
187
|
+
states: ["checked", "unchecked"],
|
|
188
|
+
machine: "toggleMachine",
|
|
189
|
+
runtime: "useAeonMachine",
|
|
190
|
+
events: ["TOGGLE", "CHECK", "UNCHECK"],
|
|
191
|
+
slots: { Root: "switch.root", Control: "switch.control", Thumb: "switch.thumb", Label: "switch.label" }
|
|
192
|
+
}),
|
|
193
|
+
checkbox: componentSchema({
|
|
194
|
+
id: "https://aeon-ui.com/schemas/checkbox.json",
|
|
195
|
+
title: "Checkbox",
|
|
196
|
+
description: "Binary toggle via toggleMachine (same chart family as Switch).",
|
|
197
|
+
scope: "checkbox",
|
|
198
|
+
parts: ["root", "control", "indicator", "label", "hiddenInput"],
|
|
199
|
+
states: ["checked", "unchecked"],
|
|
200
|
+
machine: "toggleMachine",
|
|
201
|
+
runtime: "useAeonMachine",
|
|
202
|
+
events: ["TOGGLE", "CHECK", "UNCHECK"],
|
|
203
|
+
slots: {
|
|
204
|
+
Root: "checkbox.root",
|
|
205
|
+
Control: "checkbox.control",
|
|
206
|
+
Indicator: "checkbox.indicator",
|
|
207
|
+
Label: "checkbox.label"
|
|
208
|
+
}
|
|
209
|
+
}),
|
|
210
|
+
tabs: componentSchema({
|
|
211
|
+
id: "https://aeon-ui.com/schemas/tabs.json",
|
|
212
|
+
title: "Tabs",
|
|
213
|
+
description: "Selected tab value from tabsMachine.",
|
|
214
|
+
scope: "tabs",
|
|
215
|
+
parts: ["root", "list", "trigger", "content", "indicator"],
|
|
216
|
+
states: ["selected"],
|
|
217
|
+
machine: "tabsMachine",
|
|
218
|
+
runtime: "useAeonMachine",
|
|
219
|
+
events: ["SELECT"],
|
|
220
|
+
props: {
|
|
221
|
+
value: { type: "string", description: "Selected tab id \u2014 becomes data-aeon-state" }
|
|
222
|
+
},
|
|
223
|
+
slots: { Root: "tabs.root", List: "tabs.list", Trigger: "tabs.trigger", Content: "tabs.content" }
|
|
224
|
+
}),
|
|
225
|
+
accordion: componentSchema({
|
|
226
|
+
id: "https://aeon-ui.com/schemas/accordion.json",
|
|
227
|
+
title: "Accordion",
|
|
228
|
+
description: "Per-item open state via accordionMachine.",
|
|
229
|
+
scope: "accordion",
|
|
230
|
+
parts: ["root", "item", "itemTrigger", "itemContent", "itemIndicator"],
|
|
231
|
+
states: ["open", "closed"],
|
|
232
|
+
machine: "accordionMachine",
|
|
233
|
+
runtime: "useAeonMachine",
|
|
234
|
+
events: ["TOGGLE"],
|
|
235
|
+
slots: {
|
|
236
|
+
Root: "accordion.root",
|
|
237
|
+
Item: "accordion.item",
|
|
238
|
+
ItemTrigger: "accordion.itemTrigger",
|
|
239
|
+
ItemContent: "accordion.itemContent"
|
|
240
|
+
}
|
|
241
|
+
}),
|
|
242
|
+
popover: componentSchema({
|
|
243
|
+
id: "https://aeon-ui.com/schemas/popover.json",
|
|
244
|
+
title: "Popover",
|
|
245
|
+
description: "Floating surface \u2014 shares popoverMachine. Do not fork a duplicate open/closed chart.",
|
|
246
|
+
scope: "popover",
|
|
247
|
+
parts: ["root", "trigger", "positioner", "content", "arrow", "closeTrigger"],
|
|
248
|
+
states: ["open", "closed"],
|
|
249
|
+
machine: "popoverMachine",
|
|
250
|
+
runtime: "useAeonMachine",
|
|
251
|
+
events: ["OPEN", "CLOSE", "TOGGLE"],
|
|
252
|
+
slots: { Root: "popover.root", Trigger: "popover.trigger", Content: "popover.content" }
|
|
253
|
+
}),
|
|
254
|
+
menu: componentSchema({
|
|
255
|
+
id: "https://aeon-ui.com/schemas/menu.json",
|
|
256
|
+
title: "Menu",
|
|
257
|
+
description: "Shares popoverMachine with Popover/Select open state.",
|
|
258
|
+
scope: "menu",
|
|
259
|
+
parts: ["root", "trigger", "positioner", "content", "item", "separator"],
|
|
260
|
+
states: ["open", "closed"],
|
|
261
|
+
machine: "popoverMachine",
|
|
262
|
+
runtime: "useAeonMachine",
|
|
263
|
+
events: ["OPEN", "CLOSE", "TOGGLE"],
|
|
264
|
+
slots: { Root: "menu.root", Trigger: "menu.trigger", Content: "menu.content", Item: "menu.item" }
|
|
265
|
+
}),
|
|
266
|
+
select: componentSchema({
|
|
267
|
+
id: "https://aeon-ui.com/schemas/select.json",
|
|
268
|
+
title: "Select",
|
|
269
|
+
description: "Open/closed via popoverMachine; highlight may be React-local. Do not invent a new open machine.",
|
|
270
|
+
scope: "select",
|
|
271
|
+
parts: ["root", "trigger", "value", "icon", "positioner", "content", "item"],
|
|
272
|
+
states: ["open", "closed"],
|
|
273
|
+
machine: "popoverMachine",
|
|
274
|
+
runtime: "useAeonMachine",
|
|
275
|
+
events: ["OPEN", "CLOSE", "TOGGLE"],
|
|
276
|
+
slots: { Root: "select.root", Trigger: "select.trigger", Content: "select.content", Item: "select.item" }
|
|
277
|
+
}),
|
|
278
|
+
combobox: componentSchema({
|
|
279
|
+
id: "https://aeon-ui.com/schemas/combobox.json",
|
|
280
|
+
title: "Combobox",
|
|
281
|
+
description: "Typeahead \u2014 React useState for open/query/highlight today. Do not add a duplicate floating machine without COMPONENT_CHECKLIST.",
|
|
282
|
+
scope: "combobox",
|
|
283
|
+
parts: ["root", "input", "icon", "content", "item", "empty"],
|
|
284
|
+
states: ["open", "closed"],
|
|
285
|
+
machine: null,
|
|
286
|
+
runtime: "useState",
|
|
287
|
+
slots: { Root: "combobox.root", Input: "combobox.input", Content: "combobox.content", Item: "combobox.item" }
|
|
288
|
+
}),
|
|
289
|
+
tooltip: componentSchema({
|
|
290
|
+
id: "https://aeon-ui.com/schemas/tooltip.json",
|
|
291
|
+
title: "Tooltip",
|
|
292
|
+
description: "Open via React useState. Touch tap toggles.",
|
|
293
|
+
scope: "tooltip",
|
|
294
|
+
parts: ["root", "trigger", "positioner", "content", "arrow"],
|
|
295
|
+
states: ["open", "closed"],
|
|
296
|
+
machine: null,
|
|
297
|
+
runtime: "useState",
|
|
298
|
+
slots: { Root: "tooltip.root", Trigger: "tooltip.trigger", Content: "tooltip.content" }
|
|
299
|
+
}),
|
|
300
|
+
toast: componentSchema({
|
|
301
|
+
id: "https://aeon-ui.com/schemas/toast.json",
|
|
302
|
+
title: "Toast",
|
|
303
|
+
description: "Per-item visibility via toastMachine.",
|
|
304
|
+
scope: "toast",
|
|
305
|
+
parts: ["viewport", "root", "title", "description", "closeTrigger"],
|
|
306
|
+
states: ["visible", "hidden"],
|
|
307
|
+
machine: "toastMachine",
|
|
308
|
+
runtime: "useAeonMachine",
|
|
309
|
+
events: ["SHOW", "HIDE", "DISMISS"],
|
|
310
|
+
slots: {
|
|
311
|
+
Provider: "toast.provider",
|
|
312
|
+
Viewport: "toast.viewport",
|
|
313
|
+
Root: "toast.root",
|
|
314
|
+
Title: "toast.title",
|
|
315
|
+
Description: "toast.description"
|
|
316
|
+
}
|
|
317
|
+
}),
|
|
318
|
+
scroll: componentSchema({
|
|
319
|
+
id: "https://aeon-ui.com/schemas/scroll.json",
|
|
320
|
+
title: "Scroll",
|
|
321
|
+
description: "Derived overflow/edge snapshot via getScrollSnapshot() \u2014 no XState machine.",
|
|
322
|
+
scope: "scroll",
|
|
323
|
+
parts: ["root", "viewport", "content"],
|
|
324
|
+
states: ["idle", "start", "middle", "end", "overflow-x", "overflow-y", "overflow-both"],
|
|
325
|
+
machine: null,
|
|
326
|
+
runtime: "getScrollSnapshot",
|
|
327
|
+
slots: { Root: "scroll.root", Viewport: "scroll.viewport", Content: "scroll.content" }
|
|
328
|
+
}),
|
|
329
|
+
progress: componentSchema({
|
|
330
|
+
id: "https://aeon-ui.com/schemas/progress.json",
|
|
331
|
+
title: "Progress",
|
|
332
|
+
description: "Prop-driven progress: value + indeterminate \u2192 idle | loading | complete.",
|
|
333
|
+
scope: "progress",
|
|
334
|
+
parts: ["root", "track", "range", "label"],
|
|
335
|
+
states: ["idle", "loading", "complete"],
|
|
336
|
+
machine: null,
|
|
337
|
+
runtime: "props",
|
|
338
|
+
props: {
|
|
339
|
+
value: { type: "number", minimum: 0, maximum: 100 },
|
|
340
|
+
indeterminate: { type: "boolean" }
|
|
341
|
+
},
|
|
342
|
+
slots: { Root: "progress.root", Track: "progress.track", Range: "progress.range", Label: "progress.label" }
|
|
343
|
+
})
|
|
344
|
+
};
|
|
345
|
+
var catalog = {
|
|
346
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
347
|
+
$id: "https://aeon-ui.com/schemas/catalog.json",
|
|
348
|
+
title: "Aeon UI Component Catalog",
|
|
349
|
+
description: "Machine-legible index of Aeon UI components. Prefer these schemas over inventing props, states, or boolean UI flags.",
|
|
350
|
+
version: "0.1.0",
|
|
351
|
+
principle: "UI = f(state)",
|
|
352
|
+
attributes: ["data-aeon-scope", "data-aeon-part", "data-aeon-state"],
|
|
353
|
+
components: Object.keys(componentSchemas),
|
|
354
|
+
schemas: componentSchemas
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
// src/prompts.ts
|
|
358
|
+
var AEON_SYSTEM_PROMPT = `# Aeon UI \u2014 agent system prompt
|
|
359
|
+
|
|
360
|
+
You are building UI with **Aeon UI**, a React component library powered by finite statecharts.
|
|
361
|
+
|
|
362
|
+
## Order of work (mandatory)
|
|
363
|
+
1. **Build the state machines first** \u2014 name every lifecycle the UX needs (states + events). Prefer machines from \`@aeon-ui/primitives\` (or documented prop projections such as Button \`status\`).
|
|
364
|
+
2. **Then project UI from those machines** \u2014 compound parts, copy, and layout exist only to reflect the chart. Never invent UI for states that are not in a machine.
|
|
365
|
+
3. **UI = f(state)** \u2014 the DOM exposes \`data-aeon-scope\`, \`data-aeon-part\`, \`data-aeon-state\`. Style targets those attributes. Do not drive the same concern with parallel React \`useState\` flags.
|
|
366
|
+
|
|
367
|
+
## Non-negotiable rules
|
|
368
|
+
1. Do not duplicate open/checked/lifecycle in \`useState\` when a machine exists in \`@aeon-ui/primitives\`.
|
|
369
|
+
2. **Button \`status\` is a prop** (\`idle|pending|success|failure|disabled\`). Optional: drive it from \`buttonLifecycleMachine\` via \`useAeonMachine\` in app code.
|
|
370
|
+
3. **Select / Menu / Popover** share \`popoverMachine\` \u2014 never fork another open/closed chart.
|
|
371
|
+
4. **Combobox** and **Tooltip** use React state today \u2014 do not add floating machines without the component checklist.
|
|
372
|
+
5. **Scroll** uses \`getScrollSnapshot()\` \u2014 no XState machine.
|
|
373
|
+
6. If a machine lists N stable states, the UI must represent all N (totality).
|
|
374
|
+
7. Prefer \`@aeon-ui/react\` (headless) or \`@aeon-ui/ui\` (styled). Relative TS imports use \`.js\` extensions inside the Aeon monorepo only.
|
|
375
|
+
8. Primitives stay **universal** \u2014 never invent niche components (dating, colour-blind test, pong). Compose from generic parts.
|
|
376
|
+
|
|
377
|
+
## DOM contract
|
|
378
|
+
Every interactive surface sets anatomy via \`partAttrs\` from \`@aeon-ui/core\`:
|
|
379
|
+
- \`data-aeon-scope\` \u2014 family (\`button\`, \`async\`, \`field\`, \u2026)
|
|
380
|
+
- \`data-aeon-part\` \u2014 anatomy key (\`root\`, \`trigger\`, \u2026)
|
|
381
|
+
- \`data-aeon-state\` \u2014 allowed snapshot / prop state only
|
|
382
|
+
|
|
383
|
+
## Before writing JSX
|
|
384
|
+
1. Enumerate machines (or documented status props) for the flow \u2014 states and events.
|
|
385
|
+
2. Read the component JSON Schema from \`@aeon-ui/schemas\` (or pasted catalog) and match parts to those charts.
|
|
386
|
+
3. Compose with documented compound parts (\`Dialog.Root\`, \`Field.Control\`, \u2026).
|
|
387
|
+
4. Wire events to machine events or documented props \u2014 never invent \`isLoading && !isError && hasData\` spaghetti when a named state exists.
|
|
388
|
+
`;
|
|
389
|
+
var STATECHART_PROMPTS = {
|
|
390
|
+
async: `## Async region statechart
|
|
391
|
+
States: idle \u2192 loading \u2192 (success | empty | failure); REFRESH from success/empty/failure; STALE flag while success.
|
|
392
|
+
Events: FETCH, RESOLVE{data}, REJECT{error}, RESET, STALE, REFRESH.
|
|
393
|
+
Rule: Render track segments for idle, loading, success, empty, failure. Never hide empty/failure behind a generic spinner.`,
|
|
394
|
+
field: `## Field parallel statechart
|
|
395
|
+
Regions:
|
|
396
|
+
- interaction: pristine | dirty
|
|
397
|
+
- validation: valid | invalid
|
|
398
|
+
- submission: idle | pending
|
|
399
|
+
Events: INPUT, BLUR, VALIDATE{valid}, SUBMIT, SUBMIT_DONE, SUBMIT_FAIL, RESET.
|
|
400
|
+
Rule: Do not collapse validation + submission into one \`error\` boolean. Message UI follows validation region; pending follows submission.`,
|
|
401
|
+
button: `## Button lifecycle
|
|
402
|
+
Preferred headless API: \`status\` prop \u2208 idle | pending | success | failure | disabled.
|
|
403
|
+
Optional machine: buttonLifecycleMachine with PRESS / RESOLVE / REJECT / RESET.
|
|
404
|
+
Rule: Pending must set aria-busy. Do not use disabled alone to mean "saving".`,
|
|
405
|
+
dialog: `## Dialog statechart
|
|
406
|
+
States: open | closed. Events: OPEN, CLOSE, TOGGLE.
|
|
407
|
+
Rule: Backdrop click and Escape are CLOSE transitions. Title/Description are required for a11y when open.`,
|
|
408
|
+
popoverFamily: `## Popover family (Popover, Menu, Select open state)
|
|
409
|
+
Machine: popoverMachine \u2014 states open | closed.
|
|
410
|
+
Rule: Reuse this chart. Never create selectOpenMachine / menuOpenMachine forks.`,
|
|
411
|
+
toggle: `## Switch / Checkbox
|
|
412
|
+
Machine: toggleMachine \u2014 checked | unchecked. Events: TOGGLE, CHECK, UNCHECK.
|
|
413
|
+
Rule: Hidden input stays in sync with snapshot for forms.`
|
|
414
|
+
};
|
|
415
|
+
var GENERATIVE_UI_EXAMPLE = {
|
|
416
|
+
prompt: "Create a multi-step checkout form with error handling.",
|
|
417
|
+
schemaOutput: {
|
|
418
|
+
component: "CheckoutFlow",
|
|
419
|
+
steps: [
|
|
420
|
+
{
|
|
421
|
+
id: "shipping",
|
|
422
|
+
fields: [
|
|
423
|
+
{ component: "Field", name: "email", states: ["interaction", "validation", "submission"] },
|
|
424
|
+
{ component: "Field", name: "address", states: ["interaction", "validation", "submission"] }
|
|
425
|
+
]
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
id: "payment",
|
|
429
|
+
fields: [{ component: "Field", name: "card", states: ["interaction", "validation", "submission"] }]
|
|
430
|
+
}
|
|
431
|
+
],
|
|
432
|
+
submit: {
|
|
433
|
+
component: "Button",
|
|
434
|
+
statusMachine: "buttonLifecycleMachine",
|
|
435
|
+
allowedStatuses: ["idle", "pending", "success", "failure"]
|
|
436
|
+
},
|
|
437
|
+
asyncRegion: {
|
|
438
|
+
component: "Async",
|
|
439
|
+
allowedStates: ["idle", "loading", "success", "empty", "failure"],
|
|
440
|
+
onFailure: "show Field.message + Button status=failure"
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
renderedHint: "Aeon maps each step to Field (parallel regions) + Button status + Async lifecycle \u2014 named states throughout."
|
|
444
|
+
};
|
|
445
|
+
var CURSOR_RULES_SNIPPET = `${AEON_SYSTEM_PROMPT}
|
|
446
|
+
|
|
447
|
+
## Schemas
|
|
448
|
+
When generating Aeon UI, constrain props/parts/states to @aeon-ui/schemas catalog.
|
|
449
|
+
Import headless from @aeon-ui/react or styled from @aeon-ui/ui.
|
|
450
|
+
Install: npm install aeon-ui-engine react react-dom xstate @xstate/react
|
|
451
|
+
CSS: import 'aeon-ui-engine/aeon.css'
|
|
452
|
+
Vite: aeonUiVitePlugin() from aeon-ui-engine/vite
|
|
453
|
+
|
|
454
|
+
${STATECHART_PROMPTS.async}
|
|
455
|
+
|
|
456
|
+
${STATECHART_PROMPTS.field}
|
|
457
|
+
|
|
458
|
+
${STATECHART_PROMPTS.button}
|
|
459
|
+
|
|
460
|
+
${STATECHART_PROMPTS.dialog}
|
|
461
|
+
|
|
462
|
+
${STATECHART_PROMPTS.popoverFamily}
|
|
463
|
+
`;
|
|
464
|
+
|
|
465
|
+
// src/aeon-to-schema.ts
|
|
466
|
+
import {
|
|
467
|
+
createActor,
|
|
468
|
+
getNextTransitions,
|
|
469
|
+
getStateNodes,
|
|
470
|
+
__unsafe_getAllOwnEventDescriptors
|
|
471
|
+
} from "xstate";
|
|
472
|
+
function isPublicEvent(event) {
|
|
473
|
+
return !event.startsWith("xstate.");
|
|
474
|
+
}
|
|
475
|
+
function filterPublicEvents(events) {
|
|
476
|
+
return events.filter(isPublicEvent);
|
|
477
|
+
}
|
|
478
|
+
function walkNode(node) {
|
|
479
|
+
const on = node.config.on ?? {};
|
|
480
|
+
const transitionEntries = Object.entries(on).filter(([event]) => isPublicEvent(event)).map(([event, def]) => {
|
|
481
|
+
const targets = [];
|
|
482
|
+
const list = Array.isArray(def) ? def : [def];
|
|
483
|
+
let guarded = false;
|
|
484
|
+
for (const item of list) {
|
|
485
|
+
if (item == null) continue;
|
|
486
|
+
if (typeof item === "string") {
|
|
487
|
+
targets.push(item);
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
if (typeof item === "object") {
|
|
491
|
+
const row = item;
|
|
492
|
+
if (row.guard != null) guarded = true;
|
|
493
|
+
if (typeof row.target === "string") targets.push(row.target);
|
|
494
|
+
else if (Array.isArray(row.target)) targets.push(...row.target);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return { event, target: targets, guarded };
|
|
498
|
+
});
|
|
499
|
+
return {
|
|
500
|
+
key: node.key,
|
|
501
|
+
id: node.id,
|
|
502
|
+
type: node.type,
|
|
503
|
+
events: filterPublicEvents([...node.events ?? []]),
|
|
504
|
+
transitions: transitionEntries,
|
|
505
|
+
children: Object.values(node.states ?? {}).map(walkNode)
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function flattenNodes(node, out) {
|
|
509
|
+
out[node.id] = {
|
|
510
|
+
events: filterPublicEvents([...node.events ?? []]),
|
|
511
|
+
type: node.type
|
|
512
|
+
};
|
|
513
|
+
for (const child of Object.values(node.states ?? {})) {
|
|
514
|
+
flattenNodes(child, out);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
function aeonToSchema(machine) {
|
|
518
|
+
const tree = walkNode(machine.root);
|
|
519
|
+
const flat = {};
|
|
520
|
+
flattenNodes(machine.root, flat);
|
|
521
|
+
const initial = typeof machine.config.initial === "string" ? machine.config.initial : void 0;
|
|
522
|
+
return {
|
|
523
|
+
id: machine.id,
|
|
524
|
+
initial,
|
|
525
|
+
events: filterPublicEvents([...machine.events ?? []]),
|
|
526
|
+
tree,
|
|
527
|
+
states: flat
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function aeonSnapshotSchema(machine, snapshot) {
|
|
531
|
+
const active = getStateNodes(machine.root, snapshot.value);
|
|
532
|
+
const next = getNextTransitions(snapshot);
|
|
533
|
+
return {
|
|
534
|
+
machineId: machine.id,
|
|
535
|
+
value: snapshot.value,
|
|
536
|
+
validEvents: [...__unsafe_getAllOwnEventDescriptors(snapshot)].filter(
|
|
537
|
+
(e) => !e.startsWith("xstate.")
|
|
538
|
+
),
|
|
539
|
+
nextTransitions: next.filter((t) => !t.eventType.startsWith("xstate.")).map((t) => ({
|
|
540
|
+
event: t.eventType,
|
|
541
|
+
target: (t.target ?? []).map((n) => n.id),
|
|
542
|
+
guarded: Boolean(t.guard)
|
|
543
|
+
})),
|
|
544
|
+
activeStateIds: active.map((n) => n.id)
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function aeonToPrompt(machine, snapshot) {
|
|
548
|
+
const schema = aeonToSchema(machine);
|
|
549
|
+
const lines = [
|
|
550
|
+
`## Aeon statechart: ${schema.id}`,
|
|
551
|
+
`Initial: ${schema.initial ?? "(none)"}`,
|
|
552
|
+
`All events: ${schema.events.join(", ") || "(none)"}`,
|
|
553
|
+
"",
|
|
554
|
+
"### State tree (JSON)",
|
|
555
|
+
"```json",
|
|
556
|
+
JSON.stringify(schema.tree, null, 2),
|
|
557
|
+
"```",
|
|
558
|
+
"",
|
|
559
|
+
"Rules for agents:",
|
|
560
|
+
"- Only send event types listed under the *active* configuration.",
|
|
561
|
+
"- Never invent events or targets not present in this tree.",
|
|
562
|
+
"- Prefer events with guarded:false unless you can satisfy the guard payload."
|
|
563
|
+
];
|
|
564
|
+
if (snapshot) {
|
|
565
|
+
const live = aeonSnapshotSchema(machine, snapshot);
|
|
566
|
+
lines.push(
|
|
567
|
+
"",
|
|
568
|
+
"### Live snapshot",
|
|
569
|
+
`- value: ${JSON.stringify(live.value)}`,
|
|
570
|
+
`- validEvents now: ${live.validEvents.join(", ") || "(none)"}`,
|
|
571
|
+
`- nextTransitions: ${JSON.stringify(live.nextTransitions)}`
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
return lines.join("\n");
|
|
575
|
+
}
|
|
576
|
+
function aeonInitialAgentContext(machine) {
|
|
577
|
+
const actor = createActor(machine);
|
|
578
|
+
actor.start();
|
|
579
|
+
const snap = actor.getSnapshot();
|
|
580
|
+
actor.stop();
|
|
581
|
+
return {
|
|
582
|
+
schema: aeonToSchema(machine),
|
|
583
|
+
snapshot: aeonSnapshotSchema(machine, snap),
|
|
584
|
+
prompt: aeonToPrompt(machine, snap)
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// src/agent-bridge.ts
|
|
589
|
+
function createAgentEventBridge(actor, options) {
|
|
590
|
+
const { map, accept, onIllegal } = options;
|
|
591
|
+
const resolve = (incoming) => {
|
|
592
|
+
if (accept && !accept(incoming)) return null;
|
|
593
|
+
const binding = map[incoming.type];
|
|
594
|
+
if (binding == null) return null;
|
|
595
|
+
if (typeof binding === "function") return binding(incoming);
|
|
596
|
+
return { type: binding };
|
|
597
|
+
};
|
|
598
|
+
const push = (incoming) => {
|
|
599
|
+
const event = resolve(incoming);
|
|
600
|
+
if (!event) return false;
|
|
601
|
+
const snap = typeof actor.getSnapshot === "function" ? actor.getSnapshot() : void 0;
|
|
602
|
+
if (snap && !snap.can(event)) {
|
|
603
|
+
onIllegal?.(event, `Event ${event.type} is not valid in the current configuration`);
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
actor.send(event);
|
|
607
|
+
return true;
|
|
608
|
+
};
|
|
609
|
+
return {
|
|
610
|
+
/** Push one agent/stream event through the map into `machine.send`. */
|
|
611
|
+
push,
|
|
612
|
+
/** Map of known agent → machine bindings (for prompts / docs). */
|
|
613
|
+
map,
|
|
614
|
+
/** Describe the bridge for system prompts. */
|
|
615
|
+
toPrompt() {
|
|
616
|
+
const rows = Object.entries(map).map(([from, to]) => {
|
|
617
|
+
const dest = typeof to === "string" ? to : "(transform)";
|
|
618
|
+
return `- ${from} \u2192 ${dest}`;
|
|
619
|
+
});
|
|
620
|
+
return [
|
|
621
|
+
"## Agent event bridge",
|
|
622
|
+
"Inbound stream events map to machine events:",
|
|
623
|
+
...rows,
|
|
624
|
+
"Illegal events (rejected by snapshot.can) are dropped."
|
|
625
|
+
].join("\n");
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// src/registry.ts
|
|
631
|
+
var REGISTRY_BASE = "https://aeon-ui.com/registry";
|
|
632
|
+
var registryCatalog = {
|
|
633
|
+
$id: `${REGISTRY_BASE}/catalog.json`,
|
|
634
|
+
version: "0.1.0",
|
|
635
|
+
principle: "UI = f(state)",
|
|
636
|
+
description: "Lightweight runtime registry \u2014 fetch Aeon component schemas and state-tree JSON on demand instead of bundling every primitive.",
|
|
637
|
+
endpoints: {
|
|
638
|
+
catalog: `${REGISTRY_BASE}/catalog.json`,
|
|
639
|
+
component: `${REGISTRY_BASE}/components/{id}.json`,
|
|
640
|
+
machine: `${REGISTRY_BASE}/machines/{id}.json`
|
|
641
|
+
},
|
|
642
|
+
components: [
|
|
643
|
+
{
|
|
644
|
+
id: "button",
|
|
645
|
+
title: "Button",
|
|
646
|
+
scope: "button",
|
|
647
|
+
schemaUrl: `${REGISTRY_BASE}/components/button.json`,
|
|
648
|
+
machineUrl: `${REGISTRY_BASE}/machines/buttonLifecycle.json`,
|
|
649
|
+
runtime: "status prop",
|
|
650
|
+
description: "Action control with idle|pending|success|failure|disabled"
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
id: "async",
|
|
654
|
+
title: "Async",
|
|
655
|
+
scope: "async",
|
|
656
|
+
schemaUrl: `${REGISTRY_BASE}/components/async.json`,
|
|
657
|
+
machineUrl: `${REGISTRY_BASE}/machines/async.json`,
|
|
658
|
+
runtime: "useAeonMachine",
|
|
659
|
+
description: "Fetch lifecycle region with full totality"
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
id: "field",
|
|
663
|
+
title: "Field",
|
|
664
|
+
scope: "field",
|
|
665
|
+
schemaUrl: `${REGISTRY_BASE}/components/field.json`,
|
|
666
|
+
machineUrl: `${REGISTRY_BASE}/machines/field.json`,
|
|
667
|
+
runtime: "useAeonMachine",
|
|
668
|
+
description: "Parallel interaction \xD7 validation \xD7 submission"
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
id: "dialog",
|
|
672
|
+
title: "Dialog",
|
|
673
|
+
scope: "dialog",
|
|
674
|
+
schemaUrl: `${REGISTRY_BASE}/components/dialog.json`,
|
|
675
|
+
machineUrl: `${REGISTRY_BASE}/machines/dialog.json`,
|
|
676
|
+
runtime: "useAeonMachine",
|
|
677
|
+
description: "Modal open/closed"
|
|
678
|
+
}
|
|
679
|
+
],
|
|
680
|
+
client: {
|
|
681
|
+
fetchCatalog: `fetch('${REGISTRY_BASE}/catalog.json').then(r => r.json())`,
|
|
682
|
+
fetchComponent: `id => fetch(\`${REGISTRY_BASE}/components/\${id}.json\`).then(r => r.json())`,
|
|
683
|
+
fetchMachine: `id => fetch(\`${REGISTRY_BASE}/machines/\${id}.json\`).then(r => r.json())`
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
export {
|
|
687
|
+
AEON_SYSTEM_PROMPT,
|
|
688
|
+
CURSOR_RULES_SNIPPET,
|
|
689
|
+
GENERATIVE_UI_EXAMPLE,
|
|
690
|
+
REGISTRY_BASE,
|
|
691
|
+
STATECHART_PROMPTS,
|
|
692
|
+
aeonInitialAgentContext,
|
|
693
|
+
aeonSnapshotSchema,
|
|
694
|
+
aeonToPrompt,
|
|
695
|
+
aeonToSchema,
|
|
696
|
+
catalog,
|
|
697
|
+
componentSchema,
|
|
698
|
+
componentSchemas,
|
|
699
|
+
createAgentEventBridge,
|
|
700
|
+
registryCatalog
|
|
701
|
+
};
|