@getdom/studio 0.1.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.
Files changed (213) hide show
  1. package/LICENSE.md +109 -0
  2. package/README.md +44 -0
  3. package/SKILL.md +83 -0
  4. package/package.json +73 -0
  5. package/public/llms.txt +57 -0
  6. package/public/skills.sh +11 -0
  7. package/src/pages/_layout/componentCatalog.generated.js +4514 -0
  8. package/src/pages/_layout/componentInspector.js +60 -0
  9. package/src/pages/_layout/componentManager.js +192 -0
  10. package/src/pages/_layout/componentRuntimeRecords.js +49 -0
  11. package/src/pages/_layout/inspector/componentRegistry.js +639 -0
  12. package/src/pages/_layout/inspector/serialize.js +134 -0
  13. package/src/pages/_layout/inspector/useInspector.js +293 -0
  14. package/src/pages/components/accordion/DomAccordion.vue +39 -0
  15. package/src/pages/components/breadcrumbs/DomBreadcrumbs.vue +347 -0
  16. package/src/pages/components/button/DomButton.vue +132 -0
  17. package/src/pages/components/command-palette/DomCommandPalette.vue +482 -0
  18. package/src/pages/components/context-menu/DomContextMenu.vue +178 -0
  19. package/src/pages/components/dialog/DomDialog.vue +271 -0
  20. package/src/pages/components/dialog/DomDialogSchemaForm.vue +72 -0
  21. package/src/pages/components/dialog/DomDialogStack.vue +289 -0
  22. package/src/pages/components/dialog/useDialogs.js +253 -0
  23. package/src/pages/components/drawer/DomDrawer.vue +159 -0
  24. package/src/pages/components/dropdown/DomDropdown.vue +261 -0
  25. package/src/pages/components/icon-button/DomIconButton.vue +155 -0
  26. package/src/pages/components/lightbox/DomLightbox.vue +1561 -0
  27. package/src/pages/components/menu/DomMenu.vue +359 -0
  28. package/src/pages/components/menu/DomMenuItem.vue +233 -0
  29. package/src/pages/components/menu/DomMenuLabel.vue +19 -0
  30. package/src/pages/components/menu/DomMenuSeparator.vue +14 -0
  31. package/src/pages/components/menu/menuContext.js +11 -0
  32. package/src/pages/components/menu/menuPlacement.js +26 -0
  33. package/src/pages/components/menu/submenu.js +58 -0
  34. package/src/pages/components/pagination/DomPagination.vue +265 -0
  35. package/src/pages/components/playground/DomRenderer.vue +48 -0
  36. package/src/pages/components/popover/DomPopover.vue +244 -0
  37. package/src/pages/components/profile-menu/DomProfileMenu.vue +408 -0
  38. package/src/pages/components/profile-menu/DomProfileMenuItemContent.vue +45 -0
  39. package/src/pages/components/scroll-menu/DomScrollMenu.vue +430 -0
  40. package/src/pages/components/scroll-menu/DomScrollMenuItem.vue +212 -0
  41. package/src/pages/components/scroll-menu/scrollMenuContext.js +22 -0
  42. package/src/pages/components/splitter-panel/DomSplitterPanel.vue +283 -0
  43. package/src/pages/components/stepper/DomStepper.vue +386 -0
  44. package/src/pages/components/tabs/DomTabs.vue +149 -0
  45. package/src/pages/components/theme-switcher/DomThemeSwitcher.vue +226 -0
  46. package/src/pages/components/toast/DomToastItem.vue +52 -0
  47. package/src/pages/components/toast/DomToastStack.vue +768 -0
  48. package/src/pages/components/toast/useToasts.js +237 -0
  49. package/src/pages/components/toolbar/DomToolbar.vue +158 -0
  50. package/src/pages/components/tooltip/DomTooltip.vue +69 -0
  51. package/src/pages/components/tooltip/vDomTooltip.js +106 -0
  52. package/src/pages/components/tree-view/DomTreeView.vue +961 -0
  53. package/src/pages/components/tree-view/treeSchemas.js +129 -0
  54. package/src/pages/components/tree-view/treeUtils.js +228 -0
  55. package/src/pages/data/_shared/calculateVirtualWindow.js +101 -0
  56. package/src/pages/data/_shared/resourceRecord.js +29 -0
  57. package/src/pages/data/activity-timeline/DomActivityTimeline.vue +417 -0
  58. package/src/pages/data/agent-chat/DomAgentChatShell.vue +565 -0
  59. package/src/pages/data/agent-chat/DomAgentConversation.vue +737 -0
  60. package/src/pages/data/agent-chat/DomAgentConversationList.vue +319 -0
  61. package/src/pages/data/agent-chat/examples/agentChatMockApi.js +620 -0
  62. package/src/pages/data/agent-chat/examples/useAgentChatDemoStore.js +730 -0
  63. package/src/pages/data/data-grid/DataGridVirtualRows.vue +220 -0
  64. package/src/pages/data/data-grid/DomDataGrid.vue +1643 -0
  65. package/src/pages/data/document-editor/DomDocumentEditor.vue +3030 -0
  66. package/src/pages/data/document-editor/documentEditorCodeBlock.js +282 -0
  67. package/src/pages/data/document-editor/examples/documentEditorMockApi.js +272 -0
  68. package/src/pages/data/document-editor/examples/useDocumentEditorDemoStore.js +284 -0
  69. package/src/pages/data/filter-bar/DomFilterBar.vue +533 -0
  70. package/src/pages/data/kanban/DomKanban.vue +1703 -0
  71. package/src/pages/data/kanban/kanbanApi.js +80 -0
  72. package/src/pages/data/media-browser/DomMediaBrowser.vue +2344 -0
  73. package/src/pages/data/media-browser/examples/mediaBrowserMockApi.js +653 -0
  74. package/src/pages/data/media-browser/examples/useMediaBrowserDemoStore.js +1157 -0
  75. package/src/pages/data/month-calendar/DomMonthCalendar.vue +1718 -0
  76. package/src/pages/data/week-planner/DomWeekPlanner.vue +2308 -0
  77. package/src/pages/dev/code-block/DomCodeBlock.vue +263 -0
  78. package/src/pages/dev/json-viewer/DomJsonViewer.vue +962 -0
  79. package/src/pages/forms/_shared/DomFieldLoadingSpinner.vue +12 -0
  80. package/src/pages/forms/_shared/options.js +61 -0
  81. package/src/pages/forms/_shared/useOptionMenu.js +59 -0
  82. package/src/pages/forms/autocomplete/DomAutocomplete.vue +180 -0
  83. package/src/pages/forms/calendar/DomCalendar.vue +442 -0
  84. package/src/pages/forms/checkbox/DomCheckbox.vue +69 -0
  85. package/src/pages/forms/class-toggle-input/DomClassToggleInput.vue +316 -0
  86. package/src/pages/forms/code-input/DomCodeInput.vue +202 -0
  87. package/src/pages/forms/color-input/DomColorInput.vue +118 -0
  88. package/src/pages/forms/combobox/DomCombobox.vue +237 -0
  89. package/src/pages/forms/confirmation-code-input/DomConfirmationCodeInput.vue +345 -0
  90. package/src/pages/forms/date-picker/DomDatePicker.vue +299 -0
  91. package/src/pages/forms/date-time-picker/DomDateTimePicker.vue +630 -0
  92. package/src/pages/forms/email-input/DomEmailInput.vue +55 -0
  93. package/src/pages/forms/field/DomField.vue +267 -0
  94. package/src/pages/forms/field/fieldLayout.js +1 -0
  95. package/src/pages/forms/field/fieldProps.js +114 -0
  96. package/src/pages/forms/field/layouts/DomGridFieldLayout.vue +38 -0
  97. package/src/pages/forms/field/useField.js +343 -0
  98. package/src/pages/forms/field/validators.js +364 -0
  99. package/src/pages/forms/file-upload/DomFileUpload.vue +361 -0
  100. package/src/pages/forms/form/DomForm.vue +985 -0
  101. package/src/pages/forms/form/adapters/fieldBuilder.js +45 -0
  102. package/src/pages/forms/form/adapters/jsonSchema.js +264 -0
  103. package/src/pages/forms/form/adapters/shared.js +53 -0
  104. package/src/pages/forms/form/adapters/zod.js +235 -0
  105. package/src/pages/forms/form/formApi.js +38 -0
  106. package/src/pages/forms/form/formDefinition.js +392 -0
  107. package/src/pages/forms/form/schemaAdapter.js +54 -0
  108. package/src/pages/forms/icon-selector/DomIconSelector.vue +460 -0
  109. package/src/pages/forms/icon-selector/iconSelectorItems.js +490 -0
  110. package/src/pages/forms/input-group/DomInputGroup.vue +232 -0
  111. package/src/pages/forms/json-input/DomJsonInput.vue +227 -0
  112. package/src/pages/forms/json-list-input/DomJsonListInput.vue +206 -0
  113. package/src/pages/forms/listbox/DomListbox.vue +105 -0
  114. package/src/pages/forms/money-input/DomMoneyInput.vue +147 -0
  115. package/src/pages/forms/native-select/DomNativeSelect.vue +67 -0
  116. package/src/pages/forms/number-input/DomNumberInput.vue +47 -0
  117. package/src/pages/forms/password-input/DomPasswordInput.vue +218 -0
  118. package/src/pages/forms/password-input/pwnedPasswords.js +47 -0
  119. package/src/pages/forms/password-strength/DomPasswordStrength.vue +128 -0
  120. package/src/pages/forms/password-strength/passwordStrength.js +92 -0
  121. package/src/pages/forms/position-input/DomPositionInput.vue +83 -0
  122. package/src/pages/forms/radio-group/DomRadioGroup.vue +102 -0
  123. package/src/pages/forms/range-input/DomRangeInput.vue +296 -0
  124. package/src/pages/forms/select/DomSelect.vue +479 -0
  125. package/src/pages/forms/select-input/DomSelectInput.vue +155 -0
  126. package/src/pages/forms/tag-combobox/DomTagCombobox.vue +358 -0
  127. package/src/pages/forms/text-input/DomTextInput.vue +48 -0
  128. package/src/pages/forms/textarea-composer/DomTextareaComposer.vue +234 -0
  129. package/src/pages/forms/textarea-input/DomTextareaInput.vue +86 -0
  130. package/src/pages/forms/textarea-input/useTextareaAutosize.js +147 -0
  131. package/src/pages/forms/time-selector/DomTimeSelector.vue +389 -0
  132. package/src/pages/forms/time-selector/timeUtils.js +194 -0
  133. package/src/pages/forms/toggle/DomToggle.vue +158 -0
  134. package/src/pages/forms/toggle-button/DomToggleButton.vue +88 -0
  135. package/src/pages/forms/toggle-button-group/DomToggleButtonGroup.vue +340 -0
  136. package/src/pages/forms/url-input/DomUrlInput.vue +55 -0
  137. package/src/pages/forms/wysiwyg/DomWysiwyg.vue +204 -0
  138. package/src/pages/lib/css/color.js +245 -0
  139. package/src/pages/lib/headless/accordion.d.ts +7 -0
  140. package/src/pages/lib/headless/accordion.js +246 -0
  141. package/src/pages/lib/headless/autocomplete.d.ts +4 -0
  142. package/src/pages/lib/headless/autocomplete.js +33 -0
  143. package/src/pages/lib/headless/base.d.ts +25 -0
  144. package/src/pages/lib/headless/base.js +127 -0
  145. package/src/pages/lib/headless/checkbox.d.ts +19 -0
  146. package/src/pages/lib/headless/checkbox.js +99 -0
  147. package/src/pages/lib/headless/combobox.d.ts +7 -0
  148. package/src/pages/lib/headless/combobox.js +488 -0
  149. package/src/pages/lib/headless/dialog.d.ts +23 -0
  150. package/src/pages/lib/headless/dialog.js +384 -0
  151. package/src/pages/lib/headless/drawer.d.ts +21 -0
  152. package/src/pages/lib/headless/drawer.js +682 -0
  153. package/src/pages/lib/headless/dropdown.d.ts +19 -0
  154. package/src/pages/lib/headless/dropdown.js +412 -0
  155. package/src/pages/lib/headless/floating-effect.js +118 -0
  156. package/src/pages/lib/headless/floating.d.ts +34 -0
  157. package/src/pages/lib/headless/floating.js +382 -0
  158. package/src/pages/lib/headless/index.d.ts +19 -0
  159. package/src/pages/lib/headless/index.js +19 -0
  160. package/src/pages/lib/headless/listbox.d.ts +19 -0
  161. package/src/pages/lib/headless/listbox.js +126 -0
  162. package/src/pages/lib/headless/menu.d.ts +18 -0
  163. package/src/pages/lib/headless/menu.js +117 -0
  164. package/src/pages/lib/headless/popover-panel.d.ts +18 -0
  165. package/src/pages/lib/headless/popover-panel.js +309 -0
  166. package/src/pages/lib/headless/popover.d.ts +19 -0
  167. package/src/pages/lib/headless/popover.js +391 -0
  168. package/src/pages/lib/headless/radio-group.d.ts +19 -0
  169. package/src/pages/lib/headless/radio-group.js +100 -0
  170. package/src/pages/lib/headless/tabs.d.ts +18 -0
  171. package/src/pages/lib/headless/tabs.js +119 -0
  172. package/src/pages/lib/headless/toast.d.ts +13 -0
  173. package/src/pages/lib/headless/toast.js +65 -0
  174. package/src/pages/lib/headless/toggle.d.ts +19 -0
  175. package/src/pages/lib/headless/toggle.js +162 -0
  176. package/src/pages/lib/headless/tooltip-controller.d.ts +22 -0
  177. package/src/pages/lib/headless/tooltip-controller.js +549 -0
  178. package/src/pages/lib/headless/tooltip.d.ts +19 -0
  179. package/src/pages/lib/headless/tooltip.js +153 -0
  180. package/src/pages/lib/headless/transitions.d.ts +5 -0
  181. package/src/pages/lib/headless/transitions.js +89 -0
  182. package/src/pages/lib/vue/_internal/DomLiquidGlassSurface.vue +310 -0
  183. package/src/pages/lib/vue/_internal/liquidGlass.js +112 -0
  184. package/src/pages/lib/vue/_internal/liquidGlassConfig.js +10 -0
  185. package/src/pages/lib/vue/codeHighlighter.js +132 -0
  186. package/src/pages/lib/vue/floatingTeleportTarget.js +23 -0
  187. package/src/pages/lib/vue/index.d.ts +6806 -0
  188. package/src/pages/lib/vue/index.js +218 -0
  189. package/src/pages/lib/vue/useTheme.js +116 -0
  190. package/src/pages/mobile/action-sheet/DomActionSheet.vue +186 -0
  191. package/src/pages/mobile/bottom-nav/DomAppBottomNav.vue +94 -0
  192. package/src/pages/mobile/list-item/DomAppListItem.vue +90 -0
  193. package/src/pages/mobile/safe-area/DomSafeArea.vue +39 -0
  194. package/src/pages/mobile/shell/DomAppShell.vue +51 -0
  195. package/src/pages/mobile/stack/AppStackScreen.vue +63 -0
  196. package/src/pages/mobile/stack/DomAppStack.vue +711 -0
  197. package/src/pages/mobile/top-bar/DomAppTopBar.vue +67 -0
  198. package/src/pages/visual/alert/DomAlert.vue +363 -0
  199. package/src/pages/visual/avatar/DomAvatar.vue +110 -0
  200. package/src/pages/visual/avatar-stack/DomAvatarStack.vue +89 -0
  201. package/src/pages/visual/badge/DomBadge.vue +105 -0
  202. package/src/pages/visual/card/DomCard.vue +65 -0
  203. package/src/pages/visual/card-rail/DomCardRail.vue +99 -0
  204. package/src/pages/visual/empty-state/DomEmptyState.vue +88 -0
  205. package/src/pages/visual/progress/DomProgress.vue +212 -0
  206. package/src/pages/visual/progress/DomRadialProgress.vue +186 -0
  207. package/src/pages/visual/progress/DomSegmentedProgress.vue +350 -0
  208. package/src/pages/visual/skeleton/DomSkeleton.vue +174 -0
  209. package/src/pages/visual/spinner/DomSpinner.vue +122 -0
  210. package/src/pages/visual/status-pill/DomStatusPill.vue +75 -0
  211. package/src/pages/visual/text-diff/DomTextDiff.vue +577 -0
  212. package/src/pages/visual/text-diff/textDiff.js +300 -0
  213. package/src/style.css +446 -0
@@ -0,0 +1,218 @@
1
+ export { default as DomButton } from '../../components/button/DomButton.vue';
2
+ export { default as DomIconButton } from '../../components/icon-button/DomIconButton.vue';
3
+ export { default as DomToolbar } from '../../components/toolbar/DomToolbar.vue';
4
+ export { default as DomDropdown } from '../../components/dropdown/DomDropdown.vue';
5
+ export { default as DomProfileMenu } from '../../components/profile-menu/DomProfileMenu.vue';
6
+ export { default as DomThemeSwitcher } from '../../components/theme-switcher/DomThemeSwitcher.vue';
7
+ export { default as DomDialog } from '../../components/dialog/DomDialog.vue';
8
+ export { default as DomDialogStack } from '../../components/dialog/DomDialogStack.vue';
9
+ export { default as DomDialogSchemaForm } from '../../components/dialog/DomDialogSchemaForm.vue';
10
+ export { default as DomLightbox } from '../../components/lightbox/DomLightbox.vue';
11
+ export { default as DomTabs } from '../../components/tabs/DomTabs.vue';
12
+ export { default as DomTooltip } from '../../components/tooltip/DomTooltip.vue';
13
+ export { vDomTooltip } from '../../components/tooltip/vDomTooltip.js';
14
+ export { default as DomAccordion } from '../../components/accordion/DomAccordion.vue';
15
+ export { default as DomMenu } from '../../components/menu/DomMenu.vue';
16
+ export { default as DomMenuItem } from '../../components/menu/DomMenuItem.vue';
17
+ export { default as MenuItem } from '../../components/menu/DomMenuItem.vue';
18
+ export { default as DomMenuSeparator } from '../../components/menu/DomMenuSeparator.vue';
19
+ export { default as MenuSeparator } from '../../components/menu/DomMenuSeparator.vue';
20
+ export { default as DomMenuLabel } from '../../components/menu/DomMenuLabel.vue';
21
+ export { default as MenuLabel } from '../../components/menu/DomMenuLabel.vue';
22
+ export { default as DomScrollMenu } from '../../components/scroll-menu/DomScrollMenu.vue';
23
+ export { default as DomScrollMenuItem } from '../../components/scroll-menu/DomScrollMenuItem.vue';
24
+ export { default as DomTreeView } from '../../components/tree-view/DomTreeView.vue';
25
+ export { default as DomSplitterPanel } from '../../components/splitter-panel/DomSplitterPanel.vue';
26
+ export { default as DomStepper } from '../../components/stepper/DomStepper.vue';
27
+ export { default as DomBreadcrumbs } from '../../components/breadcrumbs/DomBreadcrumbs.vue';
28
+ export {
29
+ cloneTreeItems,
30
+ flattenTreeItems,
31
+ indexTreeItems,
32
+ isSameOrDescendantPath,
33
+ moveTreeItem,
34
+ seedTreeOpenValues,
35
+ treeItemCanAcceptChildren,
36
+ treeItemChildren,
37
+ treeItemHasChildren,
38
+ treeItemLabel,
39
+ treeItemValue,
40
+ visitTreeItems,
41
+ } from '../../components/tree-view/treeUtils.js';
42
+ export { default as DomPopover } from '../../components/popover/DomPopover.vue';
43
+ export { default as DomDrawer } from '../../components/drawer/DomDrawer.vue';
44
+ export { default as DomToastStack } from '../../components/toast/DomToastStack.vue';
45
+ export { default as DomToastItem } from '../../components/toast/DomToastItem.vue';
46
+ export { default as DomCommandPalette } from '../../components/command-palette/DomCommandPalette.vue';
47
+ export { default as DomContextMenu } from '../../components/context-menu/DomContextMenu.vue';
48
+ export { default as DomDataGrid } from '../../data/data-grid/DomDataGrid.vue';
49
+ export { default as DomFilterBar } from '../../data/filter-bar/DomFilterBar.vue';
50
+ export { default as DomActivityTimeline } from '../../data/activity-timeline/DomActivityTimeline.vue';
51
+ export { default as DomKanban } from '../../data/kanban/DomKanban.vue';
52
+ export { default as DomMonthCalendar } from '../../data/month-calendar/DomMonthCalendar.vue';
53
+ export { default as DomWeekPlanner } from '../../data/week-planner/DomWeekPlanner.vue';
54
+ export { default as DomMediaBrowser } from '../../data/media-browser/DomMediaBrowser.vue';
55
+ export { default as DomDocumentEditor } from '../../data/document-editor/DomDocumentEditor.vue';
56
+ export { default as DomJsonViewer } from '../../dev/json-viewer/DomJsonViewer.vue';
57
+ export { default as DomAgentChatShell } from '../../data/agent-chat/DomAgentChatShell.vue';
58
+ export { default as DomAgentConversation } from '../../data/agent-chat/DomAgentConversation.vue';
59
+ export { default as DomAgentConversationList } from '../../data/agent-chat/DomAgentConversationList.vue';
60
+ export { default as DomPagination } from '../../components/pagination/DomPagination.vue';
61
+ export { agentChatShellProps } from '../../data/agent-chat/DomAgentChatShell.vue';
62
+ export { agentConversationProps } from '../../data/agent-chat/DomAgentConversation.vue';
63
+ export { agentConversationListProps } from '../../data/agent-chat/DomAgentConversationList.vue';
64
+ export { documentEditorProps, createDefaultDocumentContent } from '../../data/document-editor/DomDocumentEditor.vue';
65
+ export { mediaBrowserProps } from '../../data/media-browser/DomMediaBrowser.vue';
66
+ export { filterBarProps } from '../../data/filter-bar/DomFilterBar.vue';
67
+ export { createAgentChatRestApi, defineAgentChatStore } from '../../data/agent-chat/examples/useAgentChatDemoStore.js';
68
+ export { createDocumentEditorRestApi, defineDocumentEditorStore } from '../../data/document-editor/examples/useDocumentEditorDemoStore.js';
69
+ export { createMediaBrowserRestApi, defineMediaBrowserStore } from '../../data/media-browser/examples/useMediaBrowserDemoStore.js';
70
+ export { activityTimelineProps } from '../../data/activity-timeline/DomActivityTimeline.vue';
71
+ export { stepperProps } from '../../components/stepper/DomStepper.vue';
72
+ export { breadcrumbsProps } from '../../components/breadcrumbs/DomBreadcrumbs.vue';
73
+ export { kanbanProps } from '../../data/kanban/DomKanban.vue';
74
+ export { applyKanbanCardMove, applyKanbanColumnMove, resolveKanbanRowKey } from '../../data/kanban/kanbanApi.js';
75
+ export { monthCalendarProps } from '../../data/month-calendar/DomMonthCalendar.vue';
76
+ export { weekPlannerProps } from '../../data/week-planner/DomWeekPlanner.vue';
77
+ export { popoverProps } from '../../components/popover/DomPopover.vue';
78
+ export { useToasts } from '../../components/toast/useToasts.js';
79
+ export { useDialogs } from '../../components/dialog/useDialogs.js';
80
+ export {
81
+ THEME_MODE_STORAGE_KEY,
82
+ applyThemeMode,
83
+ cycleThemeMode,
84
+ initTheme,
85
+ normalizeThemeMode,
86
+ readThemeMode,
87
+ resolveThemeMode,
88
+ resolvedTheme,
89
+ setThemeMode,
90
+ themeModeValues,
91
+ useTheme,
92
+ } from './useTheme.js';
93
+
94
+ // Visual primitives
95
+ export { default as DomCard } from '../../visual/card/DomCard.vue';
96
+ export { default as DomCardRail } from '../../visual/card-rail/DomCardRail.vue';
97
+ export { default as DomBadge } from '../../visual/badge/DomBadge.vue';
98
+ export { default as DomStatusPill } from '../../visual/status-pill/DomStatusPill.vue';
99
+ export { default as DomAvatar } from '../../visual/avatar/DomAvatar.vue';
100
+ export { default as DomAvatarStack } from '../../visual/avatar-stack/DomAvatarStack.vue';
101
+ export { default as DomEmptyState } from '../../visual/empty-state/DomEmptyState.vue';
102
+ export { default as DomAlert } from '../../visual/alert/DomAlert.vue';
103
+ export { default as DomSkeleton } from '../../visual/skeleton/DomSkeleton.vue';
104
+ export { default as DomProgress } from '../../visual/progress/DomProgress.vue';
105
+ export { default as DomSegmentedProgress } from '../../visual/progress/DomSegmentedProgress.vue';
106
+ export { default as DomRadialProgress } from '../../visual/progress/DomRadialProgress.vue';
107
+ export { default as DomSpinner } from '../../visual/spinner/DomSpinner.vue';
108
+ export { default as DomTextDiff } from '../../visual/text-diff/DomTextDiff.vue';
109
+ export { default as DomCodeBlock } from '../../dev/code-block/DomCodeBlock.vue';
110
+
111
+ // Form primitives
112
+ export { default as DomToggle } from '../../forms/toggle/DomToggle.vue';
113
+ export { default as DomToggleButton } from '../../forms/toggle-button/DomToggleButton.vue';
114
+ export { default as DomToggleButtonGroup } from '../../forms/toggle-button-group/DomToggleButtonGroup.vue';
115
+ export { default as DomCheckbox } from '../../forms/checkbox/DomCheckbox.vue';
116
+ export { default as DomRadioGroup } from '../../forms/radio-group/DomRadioGroup.vue';
117
+ export { default as DomListbox } from '../../forms/listbox/DomListbox.vue';
118
+ export { default as DomSelect } from '../../forms/select/DomSelect.vue';
119
+ export { default as DomCombobox } from '../../forms/combobox/DomCombobox.vue';
120
+ export { default as DomAutocomplete } from '../../forms/autocomplete/DomAutocomplete.vue';
121
+ export { default as DomTagCombobox } from '../../forms/tag-combobox/DomTagCombobox.vue';
122
+ export { default as DomIconSelector } from '../../forms/icon-selector/DomIconSelector.vue';
123
+ export { default as DomClassToggleInput } from '../../forms/class-toggle-input/DomClassToggleInput.vue';
124
+ export { default as DomField } from '../../forms/field/DomField.vue';
125
+ export { default as DomGridFieldLayout } from '../../forms/field/layouts/DomGridFieldLayout.vue';
126
+ export { default as DomInputGroup } from '../../forms/input-group/DomInputGroup.vue';
127
+ export { default as DomForm } from '../../forms/form/DomForm.vue';
128
+ export { default as DomTextInput } from '../../forms/text-input/DomTextInput.vue';
129
+ export { default as DomEmailInput } from '../../forms/email-input/DomEmailInput.vue';
130
+ export { default as DomUrlInput } from '../../forms/url-input/DomUrlInput.vue';
131
+ export { default as DomTextareaInput } from '../../forms/textarea-input/DomTextareaInput.vue';
132
+ export { default as DomTextareaComposer } from '../../forms/textarea-composer/DomTextareaComposer.vue';
133
+ export { default as DomWysiwyg } from '../../forms/wysiwyg/DomWysiwyg.vue';
134
+ export { default as DomNumberInput } from '../../forms/number-input/DomNumberInput.vue';
135
+ export { default as DomMoneyInput } from '../../forms/money-input/DomMoneyInput.vue';
136
+ export { default as DomFileUpload } from '../../forms/file-upload/DomFileUpload.vue';
137
+ export { default as DomRangeInput } from '../../forms/range-input/DomRangeInput.vue';
138
+ export { default as DomPositionInput } from '../../forms/position-input/DomPositionInput.vue';
139
+ export { default as DomSelectInput } from '../../forms/select-input/DomSelectInput.vue';
140
+ export { default as DomNativeSelect } from '../../forms/native-select/DomNativeSelect.vue';
141
+ export { default as DomPasswordInput } from '../../forms/password-input/DomPasswordInput.vue';
142
+ export { default as DomPasswordStrength } from '../../forms/password-strength/DomPasswordStrength.vue';
143
+ export { checkCompromisedPassword, sha1PasswordHash } from '../../forms/password-input/pwnedPasswords.js';
144
+ export { default as DomCalendar } from '../../forms/calendar/DomCalendar.vue';
145
+ export { calendarProps } from '../../forms/calendar/DomCalendar.vue';
146
+ export { default as DomDatePicker } from '../../forms/date-picker/DomDatePicker.vue';
147
+ export { default as DomTimeSelector } from '../../forms/time-selector/DomTimeSelector.vue';
148
+ export { timeSelectorProps } from '../../forms/time-selector/DomTimeSelector.vue';
149
+ export { default as DomDateTimePicker } from '../../forms/date-time-picker/DomDateTimePicker.vue';
150
+ export { dateTimePickerProps } from '../../forms/date-time-picker/DomDateTimePicker.vue';
151
+ export { default as DomBooleanInput } from '../../forms/toggle/DomToggle.vue';
152
+ export { default as DomColorInput } from '../../forms/color-input/DomColorInput.vue';
153
+ export { default as DomConfirmationCodeInput } from '../../forms/confirmation-code-input/DomConfirmationCodeInput.vue';
154
+ export { default as DomJsonListInput } from '../../forms/json-list-input/DomJsonListInput.vue';
155
+ export { default as DomCodeInput } from '../../forms/code-input/DomCodeInput.vue';
156
+ export { default as DomJsonInput } from '../../forms/json-input/DomJsonInput.vue';
157
+ export { fieldProps } from '../../forms/field/fieldProps.js';
158
+ export { wysiwygProps } from '../../forms/wysiwyg/DomWysiwyg.vue';
159
+ export { fieldLayoutProviderKey } from '../../forms/field/fieldLayout.js';
160
+ export { fieldDisplayProviderKey, formFieldProviderKey, normalizeErrors, useField } from '../../forms/field/useField.js';
161
+ export {
162
+ betweenValidator,
163
+ compileValidator,
164
+ compileValidators,
165
+ createValidator,
166
+ defineValidator,
167
+ emailValidator,
168
+ getValidator,
169
+ integerValidator,
170
+ lengthValidator,
171
+ listValidators,
172
+ maxLengthValidator,
173
+ maxValidator,
174
+ minLengthValidator,
175
+ minValidator,
176
+ normalizeValidatorResult,
177
+ numberValidator,
178
+ oneOfValidator,
179
+ patternValidator,
180
+ requiredValidator,
181
+ urlValidator,
182
+ } from '../../forms/field/validators.js';
183
+ export { createFormRegistry, forms, getPathValue, setPathValue } from '../../forms/form/formApi.js';
184
+ export {
185
+ FORM_NODE_RESERVED_KEYS,
186
+ defaultComponentByType,
187
+ formDefinitionToJsonSchema,
188
+ formNodeDefaultValue,
189
+ formNodeToJsonSchema,
190
+ getFormType,
191
+ normalizeFormChildren,
192
+ normalizeFormNode,
193
+ registerFormType,
194
+ typeByComponent,
195
+ } from '../../forms/form/formDefinition.js';
196
+ export {
197
+ builtInSchemaAdapters,
198
+ isJsonSchema,
199
+ isZodLikeSchema,
200
+ jsonSchemaAdapter,
201
+ jsonSchemaToChildren,
202
+ schemaToChildren,
203
+ zodSchemaAdapter,
204
+ zodSchemaToChildren,
205
+ } from '../../forms/form/schemaAdapter.js';
206
+
207
+ // Mobile primitives
208
+ export { default as DomAppBottomNav } from '../../mobile/bottom-nav/DomAppBottomNav.vue';
209
+ export { default as DomAppListItem } from '../../mobile/list-item/DomAppListItem.vue';
210
+ export { default as DomAppShell } from '../../mobile/shell/DomAppShell.vue';
211
+ export { default as DomAppTopBar } from '../../mobile/top-bar/DomAppTopBar.vue';
212
+ export { default as DomActionSheet } from '../../mobile/action-sheet/DomActionSheet.vue';
213
+ export { default as DomSafeArea } from '../../mobile/safe-area/DomSafeArea.vue';
214
+ export { default as DomAppStack } from '../../mobile/stack/DomAppStack.vue';
215
+ export { default as DomAppStackScreen } from '../../mobile/stack/AppStackScreen.vue';
216
+
217
+ // Rehydration
218
+ export { default as DomRenderer } from '../../components/playground/DomRenderer.vue';
@@ -0,0 +1,116 @@
1
+ import { computed, ref } from 'vue';
2
+
3
+ export const THEME_MODE_STORAGE_KEY = 'theme-mode';
4
+ export const themeModeValues = ['light', 'dark', 'system'];
5
+
6
+ const mode = ref('system');
7
+ const systemDark = ref(false);
8
+ let mediaQueryList = null;
9
+ let mediaListener = null;
10
+
11
+ export const resolvedTheme = computed(() => resolveThemeMode(mode.value, systemDark.value));
12
+
13
+ export function normalizeThemeMode(value) {
14
+ return themeModeValues.includes(value) ? value : 'system';
15
+ }
16
+
17
+ export function resolveThemeMode(value = mode.value, prefersDark = systemDark.value) {
18
+ const normalized = normalizeThemeMode(value);
19
+ if (normalized === 'system') return prefersDark ? 'dark' : 'light';
20
+ return normalized;
21
+ }
22
+
23
+ export function readThemeMode() {
24
+ try {
25
+ return normalizeThemeMode(storage()?.getItem(THEME_MODE_STORAGE_KEY));
26
+ } catch {
27
+ return 'system';
28
+ }
29
+ }
30
+
31
+ export function initTheme() {
32
+ if (typeof window !== 'undefined') {
33
+ mode.value = readThemeMode();
34
+ installSystemThemeListener();
35
+ }
36
+ return applyThemeMode();
37
+ }
38
+
39
+ export function setThemeMode(value) {
40
+ const next = normalizeThemeMode(value);
41
+ mode.value = next;
42
+ writeThemeMode(next);
43
+ if (typeof window !== 'undefined' && !mediaQueryList) installSystemThemeListener();
44
+ return applyThemeMode();
45
+ }
46
+
47
+ export function cycleThemeMode() {
48
+ const next = ({ light: 'dark', dark: 'system', system: 'light' })[mode.value] || 'light';
49
+ return setThemeMode(next);
50
+ }
51
+
52
+ export function applyThemeMode(value = mode.value) {
53
+ const next = resolveThemeMode(value, systemDark.value);
54
+ if (typeof document !== 'undefined') document.documentElement.dataset.theme = next;
55
+ return next;
56
+ }
57
+
58
+ export function useTheme() {
59
+ return {
60
+ mode,
61
+ resolvedTheme,
62
+ setMode: setThemeMode,
63
+ cycleMode: cycleThemeMode,
64
+ initTheme,
65
+ currentTheme: resolvedTheme,
66
+ toggleTheme: cycleThemeMode,
67
+ };
68
+ }
69
+
70
+ function installSystemThemeListener() {
71
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return;
72
+
73
+ const nextMediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
74
+ systemDark.value = nextMediaQueryList.matches;
75
+ if (mediaQueryList && mediaListener) removeMediaListener(mediaQueryList, mediaListener);
76
+
77
+ mediaQueryList = nextMediaQueryList;
78
+ mediaListener = (event) => {
79
+ systemDark.value = event.matches;
80
+ applyThemeMode();
81
+ };
82
+ addMediaListener(mediaQueryList, mediaListener);
83
+ }
84
+
85
+ function storage() {
86
+ if (typeof window === 'undefined') return null;
87
+ try {
88
+ return window.localStorage;
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+
94
+ function writeThemeMode(value) {
95
+ try {
96
+ storage()?.setItem(THEME_MODE_STORAGE_KEY, value);
97
+ } catch {
98
+ // Ignore storage failures; the active document theme still updates.
99
+ }
100
+ }
101
+
102
+ function addMediaListener(queryList, listener) {
103
+ if (typeof queryList.addEventListener === 'function') {
104
+ queryList.addEventListener('change', listener);
105
+ return;
106
+ }
107
+ queryList.addListener?.(listener);
108
+ }
109
+
110
+ function removeMediaListener(queryList, listener) {
111
+ if (typeof queryList.removeEventListener === 'function') {
112
+ queryList.removeEventListener('change', listener);
113
+ return;
114
+ }
115
+ queryList.removeListener?.(listener);
116
+ }
@@ -0,0 +1,186 @@
1
+ <script setup>
2
+ import { computed, onMounted, ref, useId, watch } from 'vue';
3
+
4
+ defineOptions({
5
+ __doc: {
6
+ name: 'Action sheet',
7
+ tag: '<DomActionSheet>',
8
+ description: 'A bottom action sheet for app choices, destructive actions, and quick commands.',
9
+ events: [
10
+ { name: 'update:modelValue', payload: 'boolean', description: 'Fired when the sheet opens or closes.' },
11
+ { name: 'select', payload: 'object', description: 'Fired with the selected action.' },
12
+ ],
13
+ playground: {
14
+ mobileSlot: 'overlay',
15
+ initial: {
16
+ modelValue: true,
17
+ title: 'Project actions',
18
+ description: 'Use for app commands that should stay near the thumb.',
19
+ actions: [
20
+ { label: 'Share project', description: 'Open the native share sheet', value: 'share' },
21
+ { label: 'Duplicate screen', value: 'duplicate' },
22
+ { label: 'Delete draft', value: 'delete', variant: 'danger' },
23
+ ],
24
+ },
25
+ },
26
+ },
27
+ });
28
+
29
+ const props = defineProps({
30
+ modelValue: {
31
+ type: Boolean,
32
+ default: false,
33
+ _edit: { description: 'Whether the action sheet is open.' },
34
+ },
35
+ title: {
36
+ type: String,
37
+ default: '',
38
+ _edit: { description: 'Optional action sheet title.' },
39
+ },
40
+ description: {
41
+ type: String,
42
+ default: '',
43
+ _edit: { description: 'Optional supporting text below the title.' },
44
+ },
45
+ actions: {
46
+ type: Array,
47
+ default: () => [],
48
+ _edit: {
49
+ component: 'DomJsonListInput',
50
+ props: {
51
+ addLabel: '+ Add action',
52
+ compact: true,
53
+ schema: {
54
+ type: 'array',
55
+ items: {
56
+ type: 'DomForm',
57
+ properties: {
58
+ label: {
59
+ type: 'string',
60
+ label: 'Label',
61
+ placeholder: 'Share project',
62
+ },
63
+ description: {
64
+ type: 'string',
65
+ label: 'Description',
66
+ placeholder: 'Open the native share sheet',
67
+ },
68
+ value: {
69
+ type: 'string',
70
+ label: 'Value',
71
+ placeholder: 'share',
72
+ },
73
+ variant: {
74
+ type: 'string',
75
+ component: 'DomSelectInput',
76
+ label: 'Variant',
77
+ options: [
78
+ { label: 'Default', value: '' },
79
+ { label: 'Danger', value: 'danger' },
80
+ ],
81
+ },
82
+ },
83
+ },
84
+ },
85
+ },
86
+ description: 'Action rows: { label, description, value, variant }.',
87
+ },
88
+ },
89
+ cancelLabel: {
90
+ type: String,
91
+ default: 'Cancel',
92
+ _edit: { description: 'Dismiss button label.' },
93
+ },
94
+ });
95
+ const emit = defineEmits(['update:modelValue', 'select']);
96
+
97
+ const drawer = ref(null);
98
+ const uniqueId = useId();
99
+ const titleId = computed(() => (props.title ? `dom-action-sheet-${uniqueId}-title` : ''));
100
+
101
+ function close() {
102
+ emit('update:modelValue', false);
103
+ }
104
+
105
+ function selectAction(action) {
106
+ emit('select', action);
107
+ close();
108
+ }
109
+
110
+ function setOpen(value) {
111
+ if (drawer.value) drawer.value.open = value;
112
+ }
113
+
114
+ onMounted(async () => {
115
+ await import('../../lib/headless/drawer.js');
116
+ drawer.value?.addEventListener('dom:open', () => {
117
+ emit('update:modelValue', true);
118
+ });
119
+ drawer.value?.addEventListener('dom:close', () => {
120
+ emit('update:modelValue', false);
121
+ });
122
+ if (props.modelValue) setOpen(true);
123
+ });
124
+
125
+ watch(() => props.modelValue, setOpen);
126
+ </script>
127
+
128
+ <template>
129
+ <dom-drawer
130
+ ref="drawer"
131
+ side="bottom"
132
+ class="absolute inset-0 z-30 block pointer-events-none data-[state=open]:pointer-events-auto"
133
+ :aria-labelledby="titleId || null"
134
+ >
135
+ <div
136
+ data-overlay
137
+ data-no-defaults
138
+ class="absolute inset-0 pointer-events-none data-[state=open]:pointer-events-auto"
139
+ >
140
+ <div
141
+ data-backdrop
142
+ data-no-defaults
143
+ class="absolute inset-0 bg-black/40 opacity-0 backdrop-blur-sm transition-opacity duration-300 data-[state=open]:opacity-100"
144
+ ></div>
145
+ <section
146
+ data-panel
147
+ data-no-defaults
148
+ class="absolute inset-x-3 bottom-3 translate-y-full outline-none transition-transform duration-300 ease-out data-[state=open]:translate-y-0"
149
+ :class="'pb-[env(safe-area-inset-bottom,0px)]'"
150
+ >
151
+ <button
152
+ data-drag-handle
153
+ type="button"
154
+ class="group mx-auto mb-1 flex h-8 w-full items-center justify-center"
155
+ aria-label="Drag to close action sheet"
156
+ >
157
+ <span class="block h-1.5 w-12 rounded-full bg-white/70 shadow-sm transition group-hover:bg-white"></span>
158
+ </button>
159
+ <div class="skin-overlay overflow-hidden rounded-[1.75rem]">
160
+ <div v-if="title || description" class="border-b border-border px-5 py-4 text-center">
161
+ <h2 v-if="title" :id="titleId" class="text-sm font-semibold text-canvas-fg">{{ title }}</h2>
162
+ <p v-if="description" class="mt-1 text-xs leading-5 text-muted-fg">{{ description }}</p>
163
+ </div>
164
+ <div>
165
+ <button
166
+ v-for="action in actions"
167
+ :key="action.value || action.label"
168
+ type="button"
169
+ class="block min-h-14 w-full border-b border-border px-5 py-3 text-center transition last:border-b-0 hover:bg-secondary/70 active:bg-secondary"
170
+ :class="action.variant === 'danger' ? 'text-destructive' : 'text-canvas-fg'"
171
+ @click="selectAction(action)"
172
+ >
173
+ <span class="block text-sm font-medium">{{ action.label }}</span>
174
+ <span v-if="action.description" class="mt-0.5 block text-xs text-muted-fg">{{ action.description }}</span>
175
+ </button>
176
+ </div>
177
+ </div>
178
+ <button
179
+ data-close
180
+ type="button"
181
+ class="skin-control mt-2 min-h-14 w-full rounded-[1.5rem] px-5 text-sm font-semibold transition hover:brightness-[0.98] active:brightness-[0.96]"
182
+ >{{ cancelLabel }}</button>
183
+ </section>
184
+ </div>
185
+ </dom-drawer>
186
+ </template>
@@ -0,0 +1,94 @@
1
+ <script setup>
2
+ import { computed } from 'vue';
3
+
4
+ defineOptions({
5
+ __doc: {
6
+ name: 'App bottom nav',
7
+ tag: '<DomAppBottomNav>',
8
+ description: 'A thumb-friendly bottom navigation bar for primary app destinations.',
9
+ events: [
10
+ { name: 'update:modelValue', payload: 'string', description: 'Fired when a tab is selected.' },
11
+ { name: 'change', payload: 'object', description: 'Fired with the selected tab item.' },
12
+ ],
13
+ playground: {
14
+ mobileSlot: 'bottom',
15
+ initial: {
16
+ modelValue: 'home',
17
+ items: [
18
+ { value: 'home', label: 'Home' },
19
+ { value: 'inbox', label: 'Inbox', badge: '3' },
20
+ { value: 'settings', label: 'Settings' },
21
+ ],
22
+ },
23
+ },
24
+ },
25
+ });
26
+
27
+ const props = defineProps({
28
+ modelValue: {
29
+ type: String,
30
+ default: '',
31
+ _edit: { description: 'Currently selected navigation item value.' },
32
+ },
33
+ items: {
34
+ type: Array,
35
+ default: () => [],
36
+ _edit: {
37
+ component: 'DomJsonListInput',
38
+ description: 'Navigation items: { value, label, icon, iconPath, badge }.',
39
+ },
40
+ },
41
+ });
42
+ const emit = defineEmits(['update:modelValue', 'change']);
43
+
44
+ const activeValue = computed(() => props.modelValue || props.items[0]?.value || '');
45
+
46
+ /**
47
+ * Selects a primary app destination and reports the full item to consumers.
48
+ *
49
+ * @param {{ value: string }} item Navigation destination selected by the user.
50
+ * @returns {void}
51
+ */
52
+ function selectItem(item) {
53
+ emit('update:modelValue', item.value);
54
+ emit('change', item);
55
+ }
56
+ </script>
57
+
58
+ <template>
59
+ <nav class="skin-card px-2 py-2" aria-label="Primary">
60
+ <div class="grid auto-cols-fr grid-flow-col gap-1">
61
+ <button
62
+ v-for="item in items"
63
+ :key="item.value"
64
+ type="button"
65
+ class="relative flex min-h-14 min-w-0 flex-col items-center justify-center gap-1 rounded-2xl px-2 text-xs font-medium text-muted-fg transition active:scale-95"
66
+ :class="item.value === activeValue && 'bg-secondary text-canvas-fg'"
67
+ :aria-current="item.value === activeValue ? 'page' : undefined"
68
+ @click="selectItem(item)"
69
+ >
70
+ <svg
71
+ v-if="item.iconPath"
72
+ class="size-5"
73
+ viewBox="0 0 24 24"
74
+ fill="none"
75
+ aria-hidden="true"
76
+ >
77
+ <path
78
+ :d="item.iconPath"
79
+ stroke="currentColor"
80
+ stroke-width="1.8"
81
+ stroke-linecap="round"
82
+ stroke-linejoin="round"
83
+ />
84
+ </svg>
85
+ <span v-else-if="item.icon" class="grid size-5 place-items-center" v-html="item.icon"></span>
86
+ <span class="max-w-full truncate">{{ item.label }}</span>
87
+ <span
88
+ v-if="item.badge"
89
+ class="absolute right-4 top-2 min-w-4 rounded-full bg-primary px-1 text-[10px] leading-4 text-primary-fg"
90
+ >{{ item.badge }}</span>
91
+ </button>
92
+ </div>
93
+ </nav>
94
+ </template>