aeon-ui-engine 1.0.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/.changeset/README.md +23 -0
- package/.changeset/combobox-and-changesets.md +9 -0
- package/.changeset/config.json +30 -0
- package/.changeset/framework-adapters.md +12 -0
- package/.changeset/scene-3d.md +6 -0
- package/.changeset/scene-plane.md +8 -0
- package/.changeset/site-og.md +5 -0
- package/.cursor/rules/aeon-ui.mdc +22 -0
- package/ACCESSIBILITY.md +32 -0
- package/AGENTS.md +226 -0
- package/COMPONENTS.md +36 -0
- package/FRAMEWORKS.md +57 -0
- package/INTEGRATION.md +89 -0
- package/LICENSE +21 -0
- package/PHILOSOPHY.md +71 -0
- package/PUBLISHING.md +85 -0
- package/README.md +154 -0
- package/SCENE.md +113 -0
- package/STATES.md +243 -0
- package/apps/demo/index.html +31 -0
- package/apps/demo/og.config.mjs +15 -0
- package/apps/demo/package.json +41 -0
- package/apps/demo/public/favicon.svg +16 -0
- package/apps/demo/public/og.png +0 -0
- package/apps/demo/public/og.svg +35 -0
- package/apps/demo/scripts/generate-og-png.mjs +60 -0
- package/apps/demo/src/App.tsx +31 -0
- package/apps/demo/src/aeonDiagrams.ts +100 -0
- package/apps/demo/src/app.css +16 -0
- package/apps/demo/src/components/ActionCluster.tsx +20 -0
- package/apps/demo/src/components/AsyncMachineDemo.tsx +97 -0
- package/apps/demo/src/components/ButtonLifecycleDemo.tsx +63 -0
- package/apps/demo/src/components/CodeExample.tsx +7 -0
- package/apps/demo/src/components/ComboboxDemo.tsx +30 -0
- package/apps/demo/src/components/DiagramsSection.tsx +38 -0
- package/apps/demo/src/components/FieldStateDemo.tsx +51 -0
- package/apps/demo/src/components/GridMesh.tsx +8 -0
- package/apps/demo/src/components/HeroInstall.tsx +10 -0
- package/apps/demo/src/components/LandingFaq.tsx +29 -0
- package/apps/demo/src/components/LandingFooter.tsx +22 -0
- package/apps/demo/src/components/LandingHeader.tsx +60 -0
- package/apps/demo/src/components/LandingHero.tsx +55 -0
- package/apps/demo/src/components/LayersSection.tsx +51 -0
- package/apps/demo/src/components/MermaidDiagram.tsx +84 -0
- package/apps/demo/src/components/PhilosophySection.tsx +33 -0
- package/apps/demo/src/components/PlaygroundBlock.tsx +23 -0
- package/apps/demo/src/components/PlaygroundSection.tsx +204 -0
- package/apps/demo/src/components/SceneSection.tsx +157 -0
- package/apps/demo/src/components/ScrollRegionDemo.tsx +74 -0
- package/apps/demo/src/components/ThemeSwitcher.tsx +76 -0
- package/apps/demo/src/demo-layout.css +264 -0
- package/apps/demo/src/landing.css +1094 -0
- package/apps/demo/src/main.tsx +14 -0
- package/apps/demo/src/nav.ts +9 -0
- package/apps/demo/src/site.ts +347 -0
- package/apps/demo/tsconfig.json +17 -0
- package/apps/demo/vite-plugins/og-meta.ts +30 -0
- package/apps/demo/vite.config.ts +69 -0
- package/docs/API_PATTERNS.md +234 -0
- package/docs/ARCHITECTURE.md +125 -0
- package/docs/COMPONENT_CHECKLIST.md +103 -0
- package/docs/FILE_MAP.md +122 -0
- package/docs/GLOSSARY.md +125 -0
- package/docs/INDEX.md +53 -0
- package/docs/LAYOUT_COORDINATES.md +178 -0
- package/docs/MACHINES.md +166 -0
- package/docs/MIGRATION_FROM_ARK.md +295 -0
- package/docs/VITE_CONSUMER.md +114 -0
- package/package.json +25 -0
- package/packages/core/README.md +69 -0
- package/packages/core/package.json +37 -0
- package/packages/core/src/anatomy.ts +144 -0
- package/packages/core/src/attrs.ts +47 -0
- package/packages/core/src/index.ts +8 -0
- package/packages/core/src/layout.ts +176 -0
- package/packages/core/src/machine.test.ts +18 -0
- package/packages/core/src/machine.ts +15 -0
- package/packages/core/src/philosophy.ts +10 -0
- package/packages/core/src/scroll.ts +72 -0
- package/packages/core/src/theme.test.ts +14 -0
- package/packages/core/src/theme.ts +53 -0
- package/packages/core/src/types.ts +25 -0
- package/packages/core/theme-transition.css +58 -0
- package/packages/core/tsconfig.json +8 -0
- package/packages/core/vitest.config.ts +8 -0
- package/packages/geometry/README.md +7 -0
- package/packages/geometry/package.json +35 -0
- package/packages/geometry/src/index.ts +3 -0
- package/packages/geometry/src/patterns.ts +55 -0
- package/packages/geometry/src/scene-attrs.ts +11 -0
- package/packages/geometry/src/svg.ts +60 -0
- package/packages/geometry/tsconfig.json +8 -0
- package/packages/panda/README.md +66 -0
- package/packages/panda/package.json +40 -0
- package/packages/panda/panda.config.ts +229 -0
- package/packages/panda/scripts/emit-theme-runtime.ts +37 -0
- package/packages/panda/src/recipes/accordion.ts +95 -0
- package/packages/panda/src/recipes/async.ts +76 -0
- package/packages/panda/src/recipes/badge.ts +44 -0
- package/packages/panda/src/recipes/button-group.ts +33 -0
- package/packages/panda/src/recipes/button.ts +91 -0
- package/packages/panda/src/recipes/checkbox.ts +41 -0
- package/packages/panda/src/recipes/combobox.ts +121 -0
- package/packages/panda/src/recipes/dialog.ts +96 -0
- package/packages/panda/src/recipes/field-shared.ts +29 -0
- package/packages/panda/src/recipes/field.ts +72 -0
- package/packages/panda/src/recipes/floating.ts +170 -0
- package/packages/panda/src/recipes/index.ts +14 -0
- package/packages/panda/src/recipes/scroll-region.ts +55 -0
- package/packages/panda/src/recipes/select.ts +111 -0
- package/packages/panda/src/recipes/switch.ts +51 -0
- package/packages/panda/src/recipes/tabs.ts +50 -0
- package/packages/panda/src/theme/catalog-types.ts +24 -0
- package/packages/panda/src/theme/catalog.ts +73 -0
- package/packages/panda/src/theme/chrome.css +75 -0
- package/packages/panda/src/theme/global-theme-css.ts +42 -0
- package/packages/panda/src/theme/index.ts +5 -0
- package/packages/panda/src/theme/palette.ts +65 -0
- package/packages/panda/src/theme/scrollbars.css +96 -0
- package/packages/panda/src/theme/semantic-tokens.ts +17 -0
- package/packages/panda/src/theme/themes.config.ts +516 -0
- package/packages/panda/src/theme/tokens.ts +51 -0
- package/packages/panda/styled-system/css/conditions.mjs +36 -0
- package/packages/panda/styled-system/css/css.d.ts +22 -0
- package/packages/panda/styled-system/css/css.mjs +45 -0
- package/packages/panda/styled-system/css/cva.d.ts +6 -0
- package/packages/panda/styled-system/css/cva.mjs +87 -0
- package/packages/panda/styled-system/css/cx.d.ts +5 -0
- package/packages/panda/styled-system/css/cx.mjs +15 -0
- package/packages/panda/styled-system/css/index.d.ts +5 -0
- package/packages/panda/styled-system/css/index.mjs +4 -0
- package/packages/panda/styled-system/css/sva.d.ts +4 -0
- package/packages/panda/styled-system/css/sva.mjs +41 -0
- package/packages/panda/styled-system/helpers.mjs +339 -0
- package/packages/panda/styled-system/jsx/aspect-ratio.d.ts +10 -0
- package/packages/panda/styled-system/jsx/aspect-ratio.mjs +14 -0
- package/packages/panda/styled-system/jsx/bleed.d.ts +10 -0
- package/packages/panda/styled-system/jsx/bleed.mjs +14 -0
- package/packages/panda/styled-system/jsx/box.d.ts +10 -0
- package/packages/panda/styled-system/jsx/box.mjs +14 -0
- package/packages/panda/styled-system/jsx/center.d.ts +10 -0
- package/packages/panda/styled-system/jsx/center.mjs +14 -0
- package/packages/panda/styled-system/jsx/circle.d.ts +10 -0
- package/packages/panda/styled-system/jsx/circle.mjs +14 -0
- package/packages/panda/styled-system/jsx/container.d.ts +10 -0
- package/packages/panda/styled-system/jsx/container.mjs +14 -0
- package/packages/panda/styled-system/jsx/cq.d.ts +10 -0
- package/packages/panda/styled-system/jsx/cq.mjs +14 -0
- package/packages/panda/styled-system/jsx/divider.d.ts +10 -0
- package/packages/panda/styled-system/jsx/divider.mjs +14 -0
- package/packages/panda/styled-system/jsx/factory-helper.mjs +22 -0
- package/packages/panda/styled-system/jsx/factory.d.ts +3 -0
- package/packages/panda/styled-system/jsx/factory.mjs +80 -0
- package/packages/panda/styled-system/jsx/flex.d.ts +10 -0
- package/packages/panda/styled-system/jsx/flex.mjs +14 -0
- package/packages/panda/styled-system/jsx/float.d.ts +10 -0
- package/packages/panda/styled-system/jsx/float.mjs +14 -0
- package/packages/panda/styled-system/jsx/grid-item.d.ts +10 -0
- package/packages/panda/styled-system/jsx/grid-item.mjs +14 -0
- package/packages/panda/styled-system/jsx/grid.d.ts +10 -0
- package/packages/panda/styled-system/jsx/grid.mjs +14 -0
- package/packages/panda/styled-system/jsx/hstack.d.ts +10 -0
- package/packages/panda/styled-system/jsx/hstack.mjs +14 -0
- package/packages/panda/styled-system/jsx/index.d.ts +24 -0
- package/packages/panda/styled-system/jsx/index.mjs +22 -0
- package/packages/panda/styled-system/jsx/is-valid-prop.d.ts +11 -0
- package/packages/panda/styled-system/jsx/is-valid-prop.mjs +17 -0
- package/packages/panda/styled-system/jsx/link-overlay.d.ts +10 -0
- package/packages/panda/styled-system/jsx/link-overlay.mjs +14 -0
- package/packages/panda/styled-system/jsx/spacer.d.ts +10 -0
- package/packages/panda/styled-system/jsx/spacer.mjs +14 -0
- package/packages/panda/styled-system/jsx/square.d.ts +10 -0
- package/packages/panda/styled-system/jsx/square.mjs +14 -0
- package/packages/panda/styled-system/jsx/stack.d.ts +10 -0
- package/packages/panda/styled-system/jsx/stack.mjs +14 -0
- package/packages/panda/styled-system/jsx/visually-hidden.d.ts +10 -0
- package/packages/panda/styled-system/jsx/visually-hidden.mjs +14 -0
- package/packages/panda/styled-system/jsx/vstack.d.ts +10 -0
- package/packages/panda/styled-system/jsx/vstack.mjs +14 -0
- package/packages/panda/styled-system/jsx/wrap.d.ts +10 -0
- package/packages/panda/styled-system/jsx/wrap.mjs +14 -0
- package/packages/panda/styled-system/patterns/aspect-ratio.d.ts +21 -0
- package/packages/panda/styled-system/patterns/aspect-ratio.mjs +38 -0
- package/packages/panda/styled-system/patterns/bleed.d.ts +22 -0
- package/packages/panda/styled-system/patterns/bleed.mjs +24 -0
- package/packages/panda/styled-system/patterns/box.d.ts +21 -0
- package/packages/panda/styled-system/patterns/box.mjs +15 -0
- package/packages/panda/styled-system/patterns/center.d.ts +21 -0
- package/packages/panda/styled-system/patterns/center.mjs +21 -0
- package/packages/panda/styled-system/patterns/circle.d.ts +21 -0
- package/packages/panda/styled-system/patterns/circle.mjs +25 -0
- package/packages/panda/styled-system/patterns/container.d.ts +21 -0
- package/packages/panda/styled-system/patterns/container.mjs +21 -0
- package/packages/panda/styled-system/patterns/cq.d.ts +22 -0
- package/packages/panda/styled-system/patterns/cq.mjs +21 -0
- package/packages/panda/styled-system/patterns/divider.d.ts +23 -0
- package/packages/panda/styled-system/patterns/divider.mjs +25 -0
- package/packages/panda/styled-system/patterns/flex.d.ts +27 -0
- package/packages/panda/styled-system/patterns/flex.mjs +26 -0
- package/packages/panda/styled-system/patterns/float.d.ts +24 -0
- package/packages/panda/styled-system/patterns/float.mjs +52 -0
- package/packages/panda/styled-system/patterns/grid-item.d.ts +26 -0
- package/packages/panda/styled-system/patterns/grid-item.mjs +25 -0
- package/packages/panda/styled-system/patterns/grid.d.ts +25 -0
- package/packages/panda/styled-system/patterns/grid.mjs +27 -0
- package/packages/panda/styled-system/patterns/hstack.d.ts +22 -0
- package/packages/panda/styled-system/patterns/hstack.mjs +24 -0
- package/packages/panda/styled-system/patterns/index.d.ts +21 -0
- package/packages/panda/styled-system/patterns/index.mjs +20 -0
- package/packages/panda/styled-system/patterns/link-overlay.d.ts +21 -0
- package/packages/panda/styled-system/patterns/link-overlay.mjs +24 -0
- package/packages/panda/styled-system/patterns/spacer.d.ts +21 -0
- package/packages/panda/styled-system/patterns/spacer.mjs +21 -0
- package/packages/panda/styled-system/patterns/square.d.ts +21 -0
- package/packages/panda/styled-system/patterns/square.mjs +24 -0
- package/packages/panda/styled-system/patterns/stack.d.ts +24 -0
- package/packages/panda/styled-system/patterns/stack.mjs +24 -0
- package/packages/panda/styled-system/patterns/visually-hidden.d.ts +21 -0
- package/packages/panda/styled-system/patterns/visually-hidden.mjs +18 -0
- package/packages/panda/styled-system/patterns/vstack.d.ts +22 -0
- package/packages/panda/styled-system/patterns/vstack.mjs +24 -0
- package/packages/panda/styled-system/patterns/wrap.d.ts +25 -0
- package/packages/panda/styled-system/patterns/wrap.mjs +25 -0
- package/packages/panda/styled-system/recipes/aeon-accordion.d.ts +32 -0
- package/packages/panda/styled-system/recipes/aeon-accordion.mjs +48 -0
- package/packages/panda/styled-system/recipes/aeon-async.d.ts +32 -0
- package/packages/panda/styled-system/recipes/aeon-async.mjs +56 -0
- package/packages/panda/styled-system/recipes/aeon-badge.d.ts +31 -0
- package/packages/panda/styled-system/recipes/aeon-badge.mjs +32 -0
- package/packages/panda/styled-system/recipes/aeon-button-group.d.ts +39 -0
- package/packages/panda/styled-system/recipes/aeon-button-group.mjs +37 -0
- package/packages/panda/styled-system/recipes/aeon-button.d.ts +39 -0
- package/packages/panda/styled-system/recipes/aeon-button.mjs +39 -0
- package/packages/panda/styled-system/recipes/aeon-checkbox.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-checkbox.mjs +48 -0
- package/packages/panda/styled-system/recipes/aeon-combobox.d.ts +32 -0
- package/packages/panda/styled-system/recipes/aeon-combobox.mjs +52 -0
- package/packages/panda/styled-system/recipes/aeon-dialog.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-dialog.mjs +60 -0
- package/packages/panda/styled-system/recipes/aeon-field.d.ts +32 -0
- package/packages/panda/styled-system/recipes/aeon-field.mjs +52 -0
- package/packages/panda/styled-system/recipes/aeon-menu.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-menu.mjs +52 -0
- package/packages/panda/styled-system/recipes/aeon-popover.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-popover.mjs +52 -0
- package/packages/panda/styled-system/recipes/aeon-scroll.d.ts +43 -0
- package/packages/panda/styled-system/recipes/aeon-scroll.mjs +63 -0
- package/packages/panda/styled-system/recipes/aeon-select.d.ts +32 -0
- package/packages/panda/styled-system/recipes/aeon-select.mjs +56 -0
- package/packages/panda/styled-system/recipes/aeon-switch.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-switch.mjs +48 -0
- package/packages/panda/styled-system/recipes/aeon-tabs.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-tabs.mjs +48 -0
- package/packages/panda/styled-system/recipes/aeon-toast.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-toast.mjs +48 -0
- package/packages/panda/styled-system/recipes/aeon-tooltip.d.ts +28 -0
- package/packages/panda/styled-system/recipes/aeon-tooltip.mjs +48 -0
- package/packages/panda/styled-system/recipes/create-recipe.mjs +82 -0
- package/packages/panda/styled-system/recipes/index.d.ts +18 -0
- package/packages/panda/styled-system/recipes/index.mjs +17 -0
- package/packages/panda/styled-system/styles.css +2157 -0
- package/packages/panda/styled-system/tokens/index.d.ts +9 -0
- package/packages/panda/styled-system/tokens/index.mjs +2156 -0
- package/packages/panda/styled-system/tokens/tokens.d.ts +60 -0
- package/packages/panda/styled-system/types/composition.d.ts +164 -0
- package/packages/panda/styled-system/types/conditions.d.ts +322 -0
- package/packages/panda/styled-system/types/csstype.d.ts +21298 -0
- package/packages/panda/styled-system/types/global.d.ts +20 -0
- package/packages/panda/styled-system/types/index.d.ts +8 -0
- package/packages/panda/styled-system/types/jsx.d.ts +52 -0
- package/packages/panda/styled-system/types/parts.d.ts +8 -0
- package/packages/panda/styled-system/types/pattern.d.ts +78 -0
- package/packages/panda/styled-system/types/prop-type.d.ts +240 -0
- package/packages/panda/styled-system/types/recipe.d.ts +181 -0
- package/packages/panda/styled-system/types/selectors.d.ts +59 -0
- package/packages/panda/styled-system/types/static-css.d.ts +56 -0
- package/packages/panda/styled-system/types/style-props.d.ts +7491 -0
- package/packages/panda/styled-system/types/system-types.d.ts +193 -0
- package/packages/panda/theme-runtime.css +842 -0
- package/packages/panda/tsconfig.json +8 -0
- package/packages/primitives/README.md +54 -0
- package/packages/primitives/package.json +41 -0
- package/packages/primitives/src/__tests__/floating-surface.test.ts +29 -0
- package/packages/primitives/src/index.ts +9 -0
- package/packages/primitives/src/machines/accordion.ts +56 -0
- package/packages/primitives/src/machines/async.ts +108 -0
- package/packages/primitives/src/machines/button.ts +66 -0
- package/packages/primitives/src/machines/dialog.ts +61 -0
- package/packages/primitives/src/machines/field.ts +85 -0
- package/packages/primitives/src/machines/popover.ts +52 -0
- package/packages/primitives/src/machines/tabs.ts +46 -0
- package/packages/primitives/src/machines/toast.ts +48 -0
- package/packages/primitives/src/machines/toggle.ts +61 -0
- package/packages/primitives/tsconfig.json +8 -0
- package/packages/primitives/vitest.config.ts +8 -0
- package/packages/react/README.md +65 -0
- package/packages/react/package.json +52 -0
- package/packages/react/src/accordion/index.tsx +179 -0
- package/packages/react/src/async/actions.tsx +22 -0
- package/packages/react/src/async/context.tsx +54 -0
- package/packages/react/src/async/index.tsx +21 -0
- package/packages/react/src/async/legacy-region.tsx +38 -0
- package/packages/react/src/async/readout.tsx +34 -0
- package/packages/react/src/async/root.tsx +39 -0
- package/packages/react/src/async/track.tsx +59 -0
- package/packages/react/src/avatar/avatar.test.tsx +27 -0
- package/packages/react/src/avatar/index.tsx +122 -0
- package/packages/react/src/button/index.tsx +70 -0
- package/packages/react/src/checkbox/index.tsx +180 -0
- package/packages/react/src/combobox/index.tsx +430 -0
- package/packages/react/src/dialog/dialog.test.tsx +50 -0
- package/packages/react/src/dialog/index.tsx +275 -0
- package/packages/react/src/field/index.tsx +172 -0
- package/packages/react/src/hooks/use-aeon-machine.ts +10 -0
- package/packages/react/src/hooks/use-anchor-position.ts +33 -0
- package/packages/react/src/hooks/use-focus-trap.ts +51 -0
- package/packages/react/src/hooks/use-layout-mode.ts +22 -0
- package/packages/react/src/hooks/use-outside-click.ts +19 -0
- package/packages/react/src/hooks/use-portalled.ts +16 -0
- package/packages/react/src/hooks/use-scroll-lock.ts +13 -0
- package/packages/react/src/index.ts +18 -0
- package/packages/react/src/menu/index.tsx +195 -0
- package/packages/react/src/popover/index.tsx +191 -0
- package/packages/react/src/scroll/index.tsx +98 -0
- package/packages/react/src/scroll/use-scroll-state.ts +30 -0
- package/packages/react/src/select/index.tsx +372 -0
- package/packages/react/src/select/select.test.tsx +60 -0
- package/packages/react/src/switch/index.tsx +215 -0
- package/packages/react/src/tabs/index.tsx +140 -0
- package/packages/react/src/toast/context.tsx +28 -0
- package/packages/react/src/toast/index.tsx +20 -0
- package/packages/react/src/toast/primitives.tsx +129 -0
- package/packages/react/src/toast/provider.tsx +111 -0
- package/packages/react/src/toast/toast-item.tsx +32 -0
- package/packages/react/src/tooltip/index.tsx +191 -0
- package/packages/react/src/utils/merge-props.ts +24 -0
- package/packages/react/tsconfig.json +8 -0
- package/packages/react/vitest.config.ts +9 -0
- package/packages/react/vitest.setup.ts +5 -0
- package/packages/react-scene/README.md +11 -0
- package/packages/react-scene/package.json +47 -0
- package/packages/react-scene/scene-3d.css +37 -0
- package/packages/react-scene/scene-room.css +95 -0
- package/packages/react-scene/src/index.ts +20 -0
- package/packages/react-scene/src/procedural-grid.tsx +35 -0
- package/packages/react-scene/src/scene-layer.tsx +38 -0
- package/packages/react-scene/src/scene-plane.tsx +69 -0
- package/packages/react-scene/src/scene-room.tsx +81 -0
- package/packages/react-scene/src/scene-root.tsx +49 -0
- package/packages/react-scene/src/scene-slot.tsx +41 -0
- package/packages/react-scene/src/scene-stage.tsx +37 -0
- package/packages/react-scene/src/scene-surface.tsx +20 -0
- package/packages/react-scene/src/signal-bars.tsx +57 -0
- package/packages/react-scene/src/use-signal-visualizer.ts +103 -0
- package/packages/react-scene/tsconfig.json +8 -0
- package/packages/scene/README.md +5 -0
- package/packages/scene/package.json +32 -0
- package/packages/scene/src/index.ts +2 -0
- package/packages/scene/src/room.ts +40 -0
- package/packages/scene/src/transform.ts +60 -0
- package/packages/scene/tsconfig.json +8 -0
- package/packages/signal/README.md +9 -0
- package/packages/signal/package.json +32 -0
- package/packages/signal/src/analyser.ts +113 -0
- package/packages/signal/src/bands.ts +33 -0
- package/packages/signal/src/index.ts +3 -0
- package/packages/signal/src/motion.ts +80 -0
- package/packages/signal/tsconfig.json +8 -0
- package/packages/site/README.md +19 -0
- package/packages/site/package.json +32 -0
- package/packages/site/src/index.ts +8 -0
- package/packages/site/src/open-graph.ts +90 -0
- package/packages/site/tsconfig.json +8 -0
- package/packages/solid/README.md +30 -0
- package/packages/solid/package.json +42 -0
- package/packages/solid/src/hooks/use-aeon-machine.ts +10 -0
- package/packages/solid/src/index.ts +2 -0
- package/packages/solid/src/switch/index.tsx +191 -0
- package/packages/solid/src/utils/merge-props.ts +3 -0
- package/packages/solid/tsconfig.json +10 -0
- package/packages/surface/README.md +10 -0
- package/packages/surface/package.json +33 -0
- package/packages/surface/src/index.ts +1 -0
- package/packages/surface/src/materials.ts +14 -0
- package/packages/surface/surface.css +113 -0
- package/packages/surface/tsconfig.json +8 -0
- package/packages/svelte/README.md +45 -0
- package/packages/svelte/package.json +49 -0
- package/packages/svelte/src/Switch.svelte +86 -0
- package/packages/svelte/src/SwitchControl.svelte +45 -0
- package/packages/svelte/src/SwitchHiddenInput.svelte +12 -0
- package/packages/svelte/src/SwitchLabel.svelte +9 -0
- package/packages/svelte/src/SwitchThumb.svelte +16 -0
- package/packages/svelte/src/hooks/use-aeon-machine.ts +23 -0
- package/packages/svelte/src/index.ts +2 -0
- package/packages/svelte/src/switch-context.ts +13 -0
- package/packages/svelte/tsconfig.json +8 -0
- package/packages/ui/README.md +63 -0
- package/packages/ui/package.json +45 -0
- package/packages/ui/src/accordion.tsx +27 -0
- package/packages/ui/src/async.tsx +43 -0
- package/packages/ui/src/badge.tsx +18 -0
- package/packages/ui/src/button.tsx +38 -0
- package/packages/ui/src/checkbox.tsx +24 -0
- package/packages/ui/src/cn.ts +1 -0
- package/packages/ui/src/combobox.tsx +29 -0
- package/packages/ui/src/dialog.tsx +32 -0
- package/packages/ui/src/field.tsx +33 -0
- package/packages/ui/src/index.ts +17 -0
- package/packages/ui/src/menu.tsx +25 -0
- package/packages/ui/src/popover.tsx +22 -0
- package/packages/ui/src/scroll.tsx +51 -0
- package/packages/ui/src/select.tsx +33 -0
- package/packages/ui/src/styles.css +2 -0
- package/packages/ui/src/switch.tsx +22 -0
- package/packages/ui/src/tabs.tsx +22 -0
- package/packages/ui/src/toast.tsx +36 -0
- package/packages/ui/src/tooltip.tsx +19 -0
- package/packages/ui/tsconfig.json +12 -0
- package/packages/vue/README.md +40 -0
- package/packages/vue/package.json +42 -0
- package/packages/vue/src/hooks/use-aeon-machine.ts +10 -0
- package/packages/vue/src/index.ts +2 -0
- package/packages/vue/src/switch/index.ts +208 -0
- package/packages/vue/src/utils/part-props.ts +8 -0
- package/packages/vue/tsconfig.json +8 -0
- package/pnpm-workspace.yaml +3 -0
- package/scripts/ensure-headless-built.mjs +25 -0
- package/tsconfig.base.json +21 -0
- package/vercel.json +12 -0
package/docs/INDEX.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Aeon UI documentation index
|
|
2
|
+
|
|
3
|
+
Use this map to pick the right doc. **Agents should start at [AGENTS.md](../AGENTS.md).**
|
|
4
|
+
|
|
5
|
+
## For coding agents (LLMs)
|
|
6
|
+
|
|
7
|
+
| Document | Use when |
|
|
8
|
+
|----------|----------|
|
|
9
|
+
| [AGENTS.md](../AGENTS.md) | **Start here** — rules, workflows, naming |
|
|
10
|
+
| [MACHINES.md](./MACHINES.md) | Machine vs prop vs `useState`; events |
|
|
11
|
+
| [ARCHITECTURE.md](./ARCHITECTURE.md) | Monorepo layout, layers, dependencies |
|
|
12
|
+
| [COMPONENT_CHECKLIST.md](./COMPONENT_CHECKLIST.md) | Add or change a component (ordered steps) |
|
|
13
|
+
| [FILE_MAP.md](./FILE_MAP.md) | Where to find every artifact |
|
|
14
|
+
| [GLOSSARY.md](./GLOSSARY.md) | Terms (anatomy, snapshot, totality, …) |
|
|
15
|
+
| [LAYOUT_COORDINATES.md](./LAYOUT_COORDINATES.md) | Normalized plane, split/stack/overlay, game layouts |
|
|
16
|
+
| [API_PATTERNS.md](./API_PATTERNS.md) | Copy-paste snippets by layer |
|
|
17
|
+
|
|
18
|
+
## Philosophy & contracts
|
|
19
|
+
|
|
20
|
+
| Document | Use when |
|
|
21
|
+
|----------|----------|
|
|
22
|
+
| [PHILOSOPHY.md](../PHILOSOPHY.md) | Why statecharts; north star |
|
|
23
|
+
| [STATES.md](../STATES.md) | `data-aeon-*`; async, button, field, scroll |
|
|
24
|
+
| [COMPONENTS.md](../COMPONENTS.md) | What ships vs planned |
|
|
25
|
+
|
|
26
|
+
## Integration & shipping
|
|
27
|
+
|
|
28
|
+
| Document | Use when |
|
|
29
|
+
|----------|----------|
|
|
30
|
+
| [INTEGRATION.md](../INTEGRATION.md) | Headless vs Panda vs `@aeon-ui/ui` |
|
|
31
|
+
| [MIGRATION_FROM_ARK.md](./MIGRATION_FROM_ARK.md) | Replace `@ark-ui/react` with `@aeon-ui/react` (Vite, Next.js) |
|
|
32
|
+
| [VITE_CONSUMER.md](./VITE_CONSUMER.md) | Vite aliases + local clone |
|
|
33
|
+
| [FRAMEWORKS.md](../FRAMEWORKS.md) | Vue / Solid / Svelte adapters |
|
|
34
|
+
| [ACCESSIBILITY.md](../ACCESSIBILITY.md) | Roles, focus, keyboard |
|
|
35
|
+
| [PUBLISHING.md](../PUBLISHING.md) | Changesets, npm release |
|
|
36
|
+
| [SCENE.md](../SCENE.md) | Scene plane (signal, geometry, surface) |
|
|
37
|
+
|
|
38
|
+
## Package READMEs
|
|
39
|
+
|
|
40
|
+
| Package | README |
|
|
41
|
+
|---------|--------|
|
|
42
|
+
| `@aeon-ui/core` | [packages/core/README.md](../packages/core/README.md) |
|
|
43
|
+
| `@aeon-ui/primitives` | [packages/primitives/README.md](../packages/primitives/README.md) |
|
|
44
|
+
| `@aeon-ui/react` | [packages/react/README.md](../packages/react/README.md) |
|
|
45
|
+
| `@aeon-ui/panda` | [packages/panda/README.md](../packages/panda/README.md) |
|
|
46
|
+
| `@aeon-ui/ui` | [packages/ui/README.md](../packages/ui/README.md) |
|
|
47
|
+
| Scene / adapters | `packages/signal`, `geometry`, `surface`, `scene`, `react-scene`, `vue`, `solid`, `svelte` |
|
|
48
|
+
|
|
49
|
+
## Live reference
|
|
50
|
+
|
|
51
|
+
- Demo app: `apps/demo` — run `pnpm dev`
|
|
52
|
+
- Diagrams: `apps/demo/src/aeonDiagrams.ts` (Mermaid ↔ machines)
|
|
53
|
+
- Ground truth config: `packages/panda/panda.config.ts`
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Layout coordinates (responsive play surfaces)
|
|
2
|
+
|
|
3
|
+
**Problem:** Games and rich apps need the same **logical** interaction space on desktop (split columns) and mobile (stacked lanes or overlays). CSS alone does not give you stable pointer math when regions move.
|
|
4
|
+
|
|
5
|
+
**Aeon answer:** Separate three concerns — same pattern as `UI = f(state)`:
|
|
6
|
+
|
|
7
|
+
| Layer | Owns | Package |
|
|
8
|
+
|-------|------|---------|
|
|
9
|
+
| **Behavior** | Statecharts, rounds, bets | `@aeon-ui/primitives` + app |
|
|
10
|
+
| **Composition** | *Where* regions sit (split / stack / overlay) | CSS + `ResponsiveLayoutSpec` |
|
|
11
|
+
| **Coordinates** | *Where* the user points inside a region | `@aeon-ui/core` `layout` module |
|
|
12
|
+
|
|
13
|
+
Pointer logic uses a **normalized plane** (0–100 per axis) inside a measured `DOMRect`, not raw pixels.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## North star
|
|
18
|
+
|
|
19
|
+
**Layout mode is explicit. Coordinates are normalized. CSS projects mode to pixels.**
|
|
20
|
+
|
|
21
|
+
- `data-aeon-layout-mode="compact" | "wide"`
|
|
22
|
+
- `data-aeon-layout-composition="split" | "stack" | "overlay"`
|
|
23
|
+
- Anatomy: `playSurfaceAnatomy` → `mat`, `table`, `dice`, `bank`
|
|
24
|
+
|
|
25
|
+
Agents: [AGENTS.md](../AGENTS.md) · API: `packages/core/src/layout.ts`
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Normalized plane
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import {
|
|
33
|
+
normFromClient,
|
|
34
|
+
clientFromNorm,
|
|
35
|
+
clampNorm,
|
|
36
|
+
NORM_PLANE,
|
|
37
|
+
} from '@aeon-ui/core'
|
|
38
|
+
|
|
39
|
+
const rect = bowlEl.getBoundingClientRect()
|
|
40
|
+
const aim = normFromClient(rect, e.clientX, e.clientY, {
|
|
41
|
+
origin: NORM_PLANE.bottomLeft, // y up — throws, dice
|
|
42
|
+
bounds: { xMin: 10, xMax: 90, yMin: 26, yMax: 74 },
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| Origin | Y direction | Use |
|
|
47
|
+
|--------|-------------|-----|
|
|
48
|
+
| `bottom-left` | Up | Dice throw, spatial games, scene aim |
|
|
49
|
+
| `top-left` | Down | HUD-aligned hit targets (optional) |
|
|
50
|
+
|
|
51
|
+
**Rule:** Pick one origin per region and keep it in the spec. Do not mix origins in one gesture pipeline.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Responsive layout spec
|
|
56
|
+
|
|
57
|
+
Declare **composition per mode**, not ad hoc media queries in TS:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import type { ResponsiveLayoutSpec } from '@aeon-ui/core'
|
|
61
|
+
|
|
62
|
+
export const ceeLoPlayLayout: ResponsiveLayoutSpec = {
|
|
63
|
+
compactMq: '(max-width: 39.99rem)',
|
|
64
|
+
modes: {
|
|
65
|
+
wide: {
|
|
66
|
+
id: 'ceelo-wide',
|
|
67
|
+
composition: 'split',
|
|
68
|
+
regions: [
|
|
69
|
+
{ region: 'dice', slot: 'bowl', zIndex: 1 },
|
|
70
|
+
{ region: 'table', slot: 'felt', zIndex: 1 },
|
|
71
|
+
],
|
|
72
|
+
bounds: {
|
|
73
|
+
dice: { xMin: 8, xMax: 40, yMin: 8, yMax: 92 },
|
|
74
|
+
table: { xMin: 0, xMax: 100, yMin: 0, yMax: 100 },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
compact: {
|
|
78
|
+
id: 'ceelo-compact',
|
|
79
|
+
composition: 'stack',
|
|
80
|
+
regions: [
|
|
81
|
+
{ region: 'table', slot: 'felt', zIndex: 2 },
|
|
82
|
+
{ region: 'dice', slot: 'dice', zIndex: 4 },
|
|
83
|
+
],
|
|
84
|
+
bounds: {
|
|
85
|
+
dice: { xMin: 10, xMax: 90, yMin: 26, yMax: 74 },
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| Composition | Meaning | CSS strategy |
|
|
93
|
+
|-------------|---------|--------------|
|
|
94
|
+
| `split` | Regions side by side | `grid-template-columns: col + 1fr` |
|
|
95
|
+
| `stack` | Regions in rows | `grid-template-rows: auto + lane` |
|
|
96
|
+
| `overlay` | Same cell, z-index | Single `mat` area + absolute children |
|
|
97
|
+
|
|
98
|
+
**Do not** encode `overlay` until stack/split is stable — Casino-games reverted overlay for this reason.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## React
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { useLayoutMode } from '@aeon-ui/react'
|
|
106
|
+
import { layoutModeAttrs, regionBoundsForMode } from '@aeon-ui/core'
|
|
107
|
+
|
|
108
|
+
const { mode, composition } = useLayoutMode(ceeLoPlayLayout)
|
|
109
|
+
const diceBounds = regionBoundsForMode(ceeLoPlayLayout, mode, 'dice')
|
|
110
|
+
|
|
111
|
+
<div
|
|
112
|
+
data-aeon-scope="play"
|
|
113
|
+
data-aeon-part="mat"
|
|
114
|
+
{...layoutModeAttrs(mode, composition.composition)}
|
|
115
|
+
>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Measure the **dice region** element for `normFromClient`, not the full mat, when bounds are defined per region.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { measureElement, resolveRegionRect, normFromClient } from '@aeon-ui/core'
|
|
122
|
+
|
|
123
|
+
const diceRect = resolveRegionRect(
|
|
124
|
+
measureElement(bowlRef.current),
|
|
125
|
+
measureElement(matRef.current),
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## CSS contract
|
|
132
|
+
|
|
133
|
+
1. Map `composition.regions[].slot` → `grid-template-areas` per `data-aeon-layout-mode`.
|
|
134
|
+
2. Never drive throw math from `grid-template-columns` percentages — measure DOM.
|
|
135
|
+
3. Optional Panda conditions:
|
|
136
|
+
|
|
137
|
+
```css
|
|
138
|
+
[data-aeon-scope='play'][data-aeon-layout-mode='compact'][data-aeon-layout-composition='stack'] {
|
|
139
|
+
/* stack rules */
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Checklist (new game surface)
|
|
146
|
+
|
|
147
|
+
- [ ] List logical regions (`table`, `dice`, `bank`, …).
|
|
148
|
+
- [ ] Add `ResponsiveLayoutSpec` with `wide` + `compact` compositions.
|
|
149
|
+
- [ ] Add per-mode `bounds` for any region that receives drag/aim.
|
|
150
|
+
- [ ] CSS: two layouts keyed on `data-aeon-layout-mode` (no overlay until tested).
|
|
151
|
+
- [ ] TS: `useLayoutMode` + `normFromClient` on measured region rects.
|
|
152
|
+
- [ ] Demo or story: resize across breakpoint; aim stays inside bounds.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Relation to scene plane
|
|
157
|
+
|
|
158
|
+
| Package | Role |
|
|
159
|
+
|---------|------|
|
|
160
|
+
| `@aeon-ui/core` `layout` | App/play surface, pointer norm, breakpoints |
|
|
161
|
+
| `@aeon-ui/geometry` | Decorative scene grids, SVG, `sceneAttrs` |
|
|
162
|
+
| `@aeon-ui/scene` | CSS 3D presentation |
|
|
163
|
+
|
|
164
|
+
Scene coordinates are visual; **layout coordinates** are for input and game logic.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Reference implementation
|
|
169
|
+
|
|
170
|
+
[Casino-games](https://github.com/GenericCPU/Casino-games) `shared/game/dicePlayLayout.ts` and `diceAim.ts` already use this model informally (`AimBounds` = `NormRect`). Migrating to `@aeon-ui/core` keeps one API across products.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## See also
|
|
175
|
+
|
|
176
|
+
- [STATES.md](../STATES.md) — scroll snapshot (derived spatial state, same idea)
|
|
177
|
+
- [docs/ARCHITECTURE.md](./ARCHITECTURE.md)
|
|
178
|
+
- [packages/core/README.md](../packages/core/README.md)
|
package/docs/MACHINES.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Machines truth table
|
|
2
|
+
|
|
3
|
+
**Purpose:** Prevent agents from wiring the wrong state layer. This table reflects **current implementation**, not aspirational catalog rows.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Summary table
|
|
8
|
+
|
|
9
|
+
| Component | `@aeon-ui/primitives` machine | Headless runtime | `data-aeon-state` source |
|
|
10
|
+
|-----------|------------------------------|------------------|--------------------------|
|
|
11
|
+
| **Async** | `createAsyncMachine()` | `useAeonMachine` in `Async` context | Snapshot value (+ `stale` flag on readout) |
|
|
12
|
+
| **Field** | `fieldMachine` (parallel) | `useAeonMachine` | `stateToAttr(snapshot.value)` |
|
|
13
|
+
| **Button** | `buttonLifecycleMachine` | **`status` prop** on `Button.Root` | Prop string, not machine by default |
|
|
14
|
+
| **Switch** | `toggleMachine` | `useAeonMachine` | Snapshot |
|
|
15
|
+
| **Checkbox** | `toggleMachine` | `useAeonMachine` | Snapshot |
|
|
16
|
+
| **Dialog** | `dialogMachine` | `useAeonMachine` | `open` / `closed` |
|
|
17
|
+
| **Tabs** | `tabsMachine` | `useAeonMachine` | Selected tab value |
|
|
18
|
+
| **Accordion** | `accordionMachine` | `useAeonMachine` | Per-item open |
|
|
19
|
+
| **Menu** | `popoverMachine` | `useAeonMachine` | `open` / `closed` |
|
|
20
|
+
| **Popover** | `popoverMachine` | `useAeonMachine` | `open` / `closed` |
|
|
21
|
+
| **Toast** (item) | `toastMachine` | `useAeonMachine` | visible / hidden |
|
|
22
|
+
| **Select** | `popoverMachine` | `useAeonMachine` | `open` / `closed`; highlight in React |
|
|
23
|
+
| **Combobox** | — | **`useState`** (open, query, highlight) | `open` / `closed` + highlight attrs |
|
|
24
|
+
| **Tooltip** | — | **`useState(open)`** | `open` / `closed` |
|
|
25
|
+
| **Scroll** | — | **`getScrollSnapshot()`** | Derived overflow/edge tokens |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Button: prop vs machine (critical)
|
|
30
|
+
|
|
31
|
+
Two valid patterns — **do not conflate them**:
|
|
32
|
+
|
|
33
|
+
### Pattern A — Headless / styled (default)
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<Button.Root status="pending" aria-busy>
|
|
37
|
+
Saving…
|
|
38
|
+
</Button.Root>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- File: `packages/react/src/button/index.tsx`
|
|
42
|
+
- `status` ∈ `idle` | `pending` | `success` | `failure` | `disabled`
|
|
43
|
+
- Sets `data-aeon-state` via `partAttrs`
|
|
44
|
+
- **No** `useAeonMachine` inside Button
|
|
45
|
+
|
|
46
|
+
### Pattern B — Chart-driven (app / demo)
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
const [snapshot, send] = useAeonMachine(buttonLifecycleMachine)
|
|
50
|
+
const status = snapshot.value as ButtonStatus
|
|
51
|
+
<Button.Root status={status} onClick={() => send({ type: 'PRESS' })} />
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- Machine: `packages/primitives/src/machines/button.ts`
|
|
55
|
+
- Demo: playground **Button lifecycle**
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Async events
|
|
60
|
+
|
|
61
|
+
Machine: `packages/primitives/src/machines/async.ts`
|
|
62
|
+
Factory: `createAsyncMachine<T>()` — use per-region instance in context.
|
|
63
|
+
|
|
64
|
+
| Event | Effect |
|
|
65
|
+
|-------|--------|
|
|
66
|
+
| `FETCH` | → `loading` |
|
|
67
|
+
| `RESOLVE` `{ data }` | → `success` or `empty` if `isEmptyAsyncData(data)` |
|
|
68
|
+
| `REJECT` `{ error }` | → `failure` |
|
|
69
|
+
| `RESET` | → `idle`, clear context |
|
|
70
|
+
| `STALE` | Context flag while staying in `success` |
|
|
71
|
+
| `REFRESH` | Re-fetch from success/empty/failure |
|
|
72
|
+
|
|
73
|
+
Constants: `ASYNC_LIFECYCLE_STATES`, `isEmptyAsyncData()`.
|
|
74
|
+
|
|
75
|
+
React: `Async.Root` provides context; children call `send` via `useAsyncContext()`.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Field events (orthogonal)
|
|
80
|
+
|
|
81
|
+
Machine: `packages/primitives/src/machines/field.ts` — **parallel** regions.
|
|
82
|
+
|
|
83
|
+
| Region | States |
|
|
84
|
+
|--------|--------|
|
|
85
|
+
| `interaction` | `pristine` · `dirty` |
|
|
86
|
+
| `validation` | `valid` · `invalid` |
|
|
87
|
+
| `submission` | `idle` · `pending` |
|
|
88
|
+
|
|
89
|
+
| Event | Typical use |
|
|
90
|
+
|-------|-------------|
|
|
91
|
+
| `INPUT` | User typed |
|
|
92
|
+
| `BLUR` | Left control |
|
|
93
|
+
| `VALIDATE` `{ valid: boolean }` | After rule run |
|
|
94
|
+
| `SUBMIT` | Form submit started |
|
|
95
|
+
| `SUBMIT_DONE` / `SUBMIT_FAIL` | End pending |
|
|
96
|
+
| `RESET` | Clear field |
|
|
97
|
+
|
|
98
|
+
Flatten for DOM:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { stateToAttr } from '@aeon-ui/core'
|
|
102
|
+
stateToAttr(snapshot.value) // "interaction:dirty validation:invalid submission:idle"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Button lifecycle events
|
|
108
|
+
|
|
109
|
+
Machine: `buttonLifecycleMachine` in `packages/primitives/src/machines/button.ts`
|
|
110
|
+
|
|
111
|
+
| Event | From → To (simplified) |
|
|
112
|
+
|-------|------------------------|
|
|
113
|
+
| `PRESS` | idle → pending |
|
|
114
|
+
| `SUCCEED` | pending → success |
|
|
115
|
+
| `FAIL` | pending → failure |
|
|
116
|
+
| `DISABLE` / `ENABLE` | ↔ disabled |
|
|
117
|
+
| `RESET` | → idle |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Dialog / toggle / tabs / accordion
|
|
122
|
+
|
|
123
|
+
| Machine | File | Notes |
|
|
124
|
+
|---------|------|-------|
|
|
125
|
+
| `dialogMachine` | `machines/dialog.ts` | open/closed; Escape handled in React |
|
|
126
|
+
| `toggleMachine` | `machines/toggle.ts` | Switch + Checkbox |
|
|
127
|
+
| `tabsMachine` | `machines/tabs.ts` | Single active value |
|
|
128
|
+
| `accordionMachine` | `machines/accordion.ts` | Multiple items |
|
|
129
|
+
| `popoverMachine` | `machines/popover.ts` | Menu, Popover, Select |
|
|
130
|
+
| `toastMachine` | `machines/toast.ts` | Auto-dismiss input |
|
|
131
|
+
|
|
132
|
+
Inspect each file for full transition tables. Diagrams: `apps/demo/src/aeonDiagrams.ts`.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Combobox / Tooltip
|
|
137
|
+
|
|
138
|
+
**No primitives machine.** Open/query/highlight live in:
|
|
139
|
+
|
|
140
|
+
- `packages/react/src/combobox/index.tsx` (item registry for filtering)
|
|
141
|
+
- `packages/react/src/tooltip/index.tsx`
|
|
142
|
+
|
|
143
|
+
**Select** reuses `popoverMachine` for open/closed; option order comes from DOM (`role="option"` ids), not a registry.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Scroll
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { getScrollSnapshot } from '@aeon-ui/core'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Hook: `packages/react/src/scroll/use-scroll-state.ts` — listens to scroll/resize on viewport.
|
|
154
|
+
|
|
155
|
+
States: `idle`, `overflow-y`, `overflow-x`, `overflow-both`, `at-start-y`, `between-y`, `at-end-y`, … (see [STATES.md](../STATES.md) §5).
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Diagram sync
|
|
160
|
+
|
|
161
|
+
When you change transitions in `packages/primitives/src/machines/`:
|
|
162
|
+
|
|
163
|
+
1. Update matching diagram string in `apps/demo/src/aeonDiagrams.ts`
|
|
164
|
+
2. Mention in PR / commit that diagrams were synced
|
|
165
|
+
|
|
166
|
+
No automated test enforces sync yet — **manual discipline required**.
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Migrating from Ark UI to Aeon UI
|
|
2
|
+
|
|
3
|
+
Step-by-step guide for apps that use **`@ark-ui/react`** headless primitives with your own CSS (Tailwind, CSS modules, etc.). Chakra-wrapped Ark recipes are out of scope here—migrate the headless boundary first, then revisit styling.
|
|
4
|
+
|
|
5
|
+
**Reference consumers**
|
|
6
|
+
|
|
7
|
+
| App | Stack | Notes |
|
|
8
|
+
|-----|-------|--------|
|
|
9
|
+
| [spidercorp.xyz](https://github.com/GenericCPU/spydercorp.xyz) | Vite + React | Field, Select, Dialog, Toast |
|
|
10
|
+
| [soundbase.click](https://github.com/GenericCPU/soundbase) | Next.js + React | Avatar (Chakra remains for other widgets) |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. Inventory Ark usage
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
rg "@ark-ui" --glob '*.{ts,tsx}' .
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Group imports by component (`dialog`, `select`, `field`, `avatar`, `toast`, `portal`, `collection`, …). Migrate in this order when possible:
|
|
21
|
+
|
|
22
|
+
1. **Leaf primitives** with a direct Aeon equivalent (Avatar, Switch, Checkbox).
|
|
23
|
+
2. **Forms** — Field, Select, Combobox.
|
|
24
|
+
3. **Overlays** — Dialog, Menu, Popover, Tooltip.
|
|
25
|
+
4. **Toasts** — replace `createToaster` with `Toast.Provider` + `useToast()`.
|
|
26
|
+
|
|
27
|
+
Components with **no** Aeon headless yet (Slider, Number Input, Steps, …): keep Ark for that file until Aeon ships them, or replace with a minimal local implementation.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. Install Aeon runtime deps
|
|
32
|
+
|
|
33
|
+
Aeon headless peers:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @xstate/react xstate
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
When `@aeon-ui/*` is on npm:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @aeon-ui/react @aeon-ui/core @aeon-ui/primitives
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Until publish, point the bundler at a built clone (sections 3–4).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 3. Build Aeon once
|
|
50
|
+
|
|
51
|
+
From the Aeon UI repo:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm run build:headless
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
In the consumer `package.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"scripts": {
|
|
62
|
+
"aeon:ensure": "node <path-to-AeonUI>/scripts/ensure-headless-built.mjs",
|
|
63
|
+
"prebuild": "npm run aeon:ensure"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
CI: set `AEON_UI_ROOT` to the checkout path.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 4. Wire the bundler
|
|
73
|
+
|
|
74
|
+
### Vite
|
|
75
|
+
|
|
76
|
+
See [VITE_CONSUMER.md](./VITE_CONSUMER.md) for full `resolve.alias`, `optimizeDeps.include`, and TypeScript `paths`.
|
|
77
|
+
|
|
78
|
+
### Next.js (recommended: `file:` links)
|
|
79
|
+
|
|
80
|
+
Turbopack often **cannot** import files outside the app root via `resolveAlias`. Link the built packages into `node_modules` instead:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"@aeon-ui/core": "file:../../../AeonUI/packages/core",
|
|
86
|
+
"@aeon-ui/primitives": "file:../../../AeonUI/packages/primitives",
|
|
87
|
+
"@aeon-ui/react": "file:../../../AeonUI/packages/react",
|
|
88
|
+
"@xstate/react": "^5.0.3",
|
|
89
|
+
"xstate": "^5.19.2"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Run `npm install` after `pnpm run build:headless` in Aeon UI (or `npm run aeon:ensure` in the consumer).
|
|
95
|
+
|
|
96
|
+
`next.config.mjs`:
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
export default {
|
|
100
|
+
transpilePackages: ['@aeon-ui/react', '@aeon-ui/core', '@aeon-ui/primitives'],
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Optional: `next build --webpack` if you hit Turbopack edge cases.
|
|
105
|
+
|
|
106
|
+
`tsconfig.json` paths (optional; `file:` installs usually typecheck via package `types`):
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"compilerOptions": {
|
|
111
|
+
"paths": {
|
|
112
|
+
"@aeon-ui/core": ["../../../AeonUI/packages/core/dist/index.d.ts"],
|
|
113
|
+
"@aeon-ui/primitives": ["../../../AeonUI/packages/primitives/dist/index.d.ts"],
|
|
114
|
+
"@aeon-ui/react": ["../../../AeonUI/packages/react/dist/index.d.ts"]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Mark client boundaries: `'use client'` on files that import `@aeon-ui/react`.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 5. API mapping (Ark → Aeon)
|
|
125
|
+
|
|
126
|
+
| Ark | Aeon |
|
|
127
|
+
|-----|------|
|
|
128
|
+
| `data-scope` / `data-part` | `data-aeon-scope` / `data-aeon-part` |
|
|
129
|
+
| `data-state` | `data-aeon-state` |
|
|
130
|
+
| `Field.Input` | `Field.Control` |
|
|
131
|
+
| `Field.Textarea` | `Field.Textarea` |
|
|
132
|
+
| `createListCollection` + `Select.*` | `Select.Root` → `Trigger` + `ValueText` → `Positioner` → `Content` → `Item` |
|
|
133
|
+
| `Portal` + `Dialog.*` | `Dialog.Portal` wraps `Backdrop`, `Positioner`, `Content` |
|
|
134
|
+
| `Avatar.Root` / `Image` / `Fallback` | Same part names under `@aeon-ui/react` |
|
|
135
|
+
| `createToaster` + `Toaster` | `Toast.Provider`, `Toast.Viewport`, `useToast().publish()` |
|
|
136
|
+
|
|
137
|
+
### Select (required structure)
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { Select } from '@aeon-ui/react'
|
|
141
|
+
|
|
142
|
+
<Select.Root value={value} onValueChange={setValue}>
|
|
143
|
+
<Select.Trigger>
|
|
144
|
+
<Select.ValueText>{label}</Select.ValueText>
|
|
145
|
+
</Select.Trigger>
|
|
146
|
+
<Select.Positioner>
|
|
147
|
+
<Select.Content>
|
|
148
|
+
<Select.Item value="a">Option A</Select.Item>
|
|
149
|
+
</Select.Content>
|
|
150
|
+
</Select.Positioner>
|
|
151
|
+
</Select.Root>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Use `portalled={false}` in tests or fixed-height containers.
|
|
155
|
+
|
|
156
|
+
### Dialog
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
<Dialog.Root open={open} onOpenChange={setOpen}>
|
|
160
|
+
<Dialog.Trigger>Open</Dialog.Trigger>
|
|
161
|
+
<Dialog.Portal>
|
|
162
|
+
<Dialog.Backdrop />
|
|
163
|
+
<Dialog.Positioner>
|
|
164
|
+
<Dialog.Content>
|
|
165
|
+
<Dialog.Title>Title</Dialog.Title>
|
|
166
|
+
<Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
|
|
167
|
+
</Dialog.Content>
|
|
168
|
+
</Dialog.Positioner>
|
|
169
|
+
</Dialog.Portal>
|
|
170
|
+
</Dialog.Root>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Avatar (shadcn-style wrapper)
|
|
174
|
+
|
|
175
|
+
Keep your `components/ui/avatar.tsx` as a thin Tailwind wrapper over Aeon parts so call sites stay unchanged:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { Avatar as AeonAvatar } from '@aeon-ui/react'
|
|
179
|
+
|
|
180
|
+
function Avatar({ className, ...props }) {
|
|
181
|
+
return <AeonAvatar.Root className={cn('relative flex size-8 ...', className)} {...props} />
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Aeon does not force width/height recipes—Tailwind `size-*` on `Root` works.
|
|
186
|
+
|
|
187
|
+
### Toasts
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
// layout.tsx
|
|
191
|
+
import { Toast } from '@aeon-ui/react'
|
|
192
|
+
|
|
193
|
+
<Toast.Provider>
|
|
194
|
+
{children}
|
|
195
|
+
<Toast.Viewport placement="bottom-end" />
|
|
196
|
+
</Toast.Provider>
|
|
197
|
+
|
|
198
|
+
// anywhere
|
|
199
|
+
const { publish } = useToast()
|
|
200
|
+
publish({ title: 'Saved' })
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 6. Restyle with `data-aeon-*`
|
|
206
|
+
|
|
207
|
+
Ark CSS often targets `[data-part=trigger]`. Rename selectors:
|
|
208
|
+
|
|
209
|
+
```css
|
|
210
|
+
/* was: [data-scope='select'][data-part='content'] */
|
|
211
|
+
[data-aeon-scope='select'][data-aeon-part='content'] {
|
|
212
|
+
/* ... */
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
State:
|
|
217
|
+
|
|
218
|
+
```css
|
|
219
|
+
[data-aeon-scope='select'][data-aeon-part='item'][data-aeon-state='highlighted'] {
|
|
220
|
+
background: var(--accent);
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
See [STATES.md](../STATES.md) and [INTEGRATION.md](../INTEGRATION.md).
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 7. Remove Ark
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm uninstall @ark-ui/react
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Re-run build and grep for stragglers:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
rg "@ark-ui" .
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 8. Verify
|
|
243
|
+
|
|
244
|
+
| Check | Command / action |
|
|
245
|
+
|-------|------------------|
|
|
246
|
+
| Aeon tests | `cd AeonUI && pnpm test:headless` |
|
|
247
|
+
| Consumer build | `npm run build` / `vite build` |
|
|
248
|
+
| Select | Open list, keyboard, pick option, Escape |
|
|
249
|
+
| Dialog | Open, focus trap, Escape, scroll lock |
|
|
250
|
+
| Avatar | Image load, fallback when missing/broken |
|
|
251
|
+
| Toasts | `publish` after provider mount |
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 9. Chakra + Ark stacks
|
|
256
|
+
|
|
257
|
+
Many HandCash templates use **Chakra v3 recipes** built on Ark. Migrating “off Ark” does not require removing Chakra in one pass:
|
|
258
|
+
|
|
259
|
+
1. Replace **direct** `@ark-ui/react` imports (e.g. `components/ui/avatar.tsx`).
|
|
260
|
+
2. Later, swap Chakra widgets for `@aeon-ui/react` or `@aeon-ui/ui` per component.
|
|
261
|
+
|
|
262
|
+
soundbase.click keeps Chakra for Button, Dialog, Select, etc.; only Avatar uses Aeon headless today.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Light / dark transitions (Tailwind + next-themes)
|
|
267
|
+
|
|
268
|
+
Import Aeon’s transition stylesheet and bridge `data-aeon-mode` to your existing theme toggle:
|
|
269
|
+
|
|
270
|
+
```css
|
|
271
|
+
/* globals.css */
|
|
272
|
+
@import '@aeon-ui/core/theme-transition.css';
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { AeonThemeBridge } from '@/components/aeon-theme-bridge' // syncs next-themes → data-aeon-mode
|
|
277
|
+
import { runAeonThemeTransition } from '@aeon-ui/core'
|
|
278
|
+
|
|
279
|
+
// layout: inside <ThemeProvider>
|
|
280
|
+
<AeonThemeBridge />
|
|
281
|
+
|
|
282
|
+
// theme menu
|
|
283
|
+
runAeonThemeTransition(() => setTheme('dark'))
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Reference: **soundbase.click** (`components/aeon-theme-bridge.tsx`).
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Related docs
|
|
291
|
+
|
|
292
|
+
- [VITE_CONSUMER.md](./VITE_CONSUMER.md) — Vite-specific aliases
|
|
293
|
+
- [MACHINES.md](./MACHINES.md) — which components use XState
|
|
294
|
+
- [ACCESSIBILITY.md](../ACCESSIBILITY.md) — roles and keyboard
|
|
295
|
+
- [API_PATTERNS.md](./API_PATTERNS.md) — copy-paste snippets
|