@sabrenski/spire-ui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/dist/index.d.ts +4981 -0
  4. package/dist/spire-ui.css +1 -0
  5. package/dist/spire-ui.es.js +18403 -0
  6. package/dist/spire-ui.umd.js +45 -0
  7. package/package.json +83 -0
  8. package/src/components/Accordion/Accordion.test.ts +218 -0
  9. package/src/components/Accordion/AccordionContent.vue +112 -0
  10. package/src/components/Accordion/AccordionItem.vue +87 -0
  11. package/src/components/Accordion/AccordionRoot.vue +111 -0
  12. package/src/components/Accordion/AccordionTrigger.vue +125 -0
  13. package/src/components/Accordion/index.ts +11 -0
  14. package/src/components/Accordion/keys.ts +23 -0
  15. package/src/components/Avatar/Avatar.test.ts +181 -0
  16. package/src/components/Avatar/Avatar.vue +150 -0
  17. package/src/components/Avatar/index.ts +2 -0
  18. package/src/components/Badge/Badge.test.ts +141 -0
  19. package/src/components/Badge/Badge.vue +133 -0
  20. package/src/components/Badge/index.ts +2 -0
  21. package/src/components/BadgeContainer/BadgeContainer.test.ts +150 -0
  22. package/src/components/BadgeContainer/BadgeContainer.vue +90 -0
  23. package/src/components/BadgeContainer/index.ts +2 -0
  24. package/src/components/Breadcrumb/Breadcrumb.test.ts +342 -0
  25. package/src/components/Breadcrumb/BreadcrumbEllipsis.vue +96 -0
  26. package/src/components/Breadcrumb/BreadcrumbItem.vue +16 -0
  27. package/src/components/Breadcrumb/BreadcrumbLink.vue +67 -0
  28. package/src/components/Breadcrumb/BreadcrumbList.vue +20 -0
  29. package/src/components/Breadcrumb/BreadcrumbPage.vue +25 -0
  30. package/src/components/Breadcrumb/BreadcrumbRoot.vue +41 -0
  31. package/src/components/Breadcrumb/BreadcrumbSeparator.vue +63 -0
  32. package/src/components/Breadcrumb/index.ts +13 -0
  33. package/src/components/Breadcrumb/keys.ts +7 -0
  34. package/src/components/Button/Button.test.ts +231 -0
  35. package/src/components/Button/Button.vue +349 -0
  36. package/src/components/Button/index.ts +2 -0
  37. package/src/components/Callout/Callout.test.ts +260 -0
  38. package/src/components/Callout/Callout.vue +341 -0
  39. package/src/components/Callout/index.ts +2 -0
  40. package/src/components/Card/Card.test.ts +565 -0
  41. package/src/components/Card/Card.vue +209 -0
  42. package/src/components/Card/CardContent.vue +57 -0
  43. package/src/components/Card/CardFooter.vue +72 -0
  44. package/src/components/Card/CardHeader.vue +111 -0
  45. package/src/components/Card/CardImage.vue +124 -0
  46. package/src/components/Card/index.ts +14 -0
  47. package/src/components/Chart/BarChart.vue +208 -0
  48. package/src/components/Chart/BaseChart.vue +444 -0
  49. package/src/components/Chart/Chart.test.ts +359 -0
  50. package/src/components/Chart/DonutChart.vue +283 -0
  51. package/src/components/Chart/LineChart.vue +211 -0
  52. package/src/components/Chart/index.ts +20 -0
  53. package/src/components/Chart/useChartTheme.ts +192 -0
  54. package/src/components/Checkbox/Checkbox.test.ts +209 -0
  55. package/src/components/Checkbox/Checkbox.vue +285 -0
  56. package/src/components/Checkbox/index.ts +2 -0
  57. package/src/components/ChoiceChip/ChoiceChip.test.ts +142 -0
  58. package/src/components/ChoiceChip/ChoiceChip.vue +218 -0
  59. package/src/components/ChoiceChip/index.ts +2 -0
  60. package/src/components/ChoiceChipGroup/ChoiceChipGroup.test.ts +151 -0
  61. package/src/components/ChoiceChipGroup/ChoiceChipGroup.vue +70 -0
  62. package/src/components/ChoiceChipGroup/index.ts +2 -0
  63. package/src/components/ColorPicker/ColorArea.vue +159 -0
  64. package/src/components/ColorPicker/ColorPicker.test.ts +250 -0
  65. package/src/components/ColorPicker/ColorPicker.vue +339 -0
  66. package/src/components/ColorPicker/ColorSlider.vue +191 -0
  67. package/src/components/ColorPicker/index.ts +7 -0
  68. package/src/components/Combobox/Combobox.test.ts +891 -0
  69. package/src/components/Combobox/Combobox.vue +934 -0
  70. package/src/components/Combobox/index.ts +2 -0
  71. package/src/components/DataTable/DataTable.test.ts +1221 -0
  72. package/src/components/DataTable/DataTable.vue +1415 -0
  73. package/src/components/DataTable/index.ts +10 -0
  74. package/src/components/DatePicker/DatePicker.test.ts +625 -0
  75. package/src/components/DatePicker/DatePicker.vue +1586 -0
  76. package/src/components/DatePicker/index.ts +2 -0
  77. package/src/components/Drawer/Drawer.test.ts +336 -0
  78. package/src/components/Drawer/Drawer.vue +466 -0
  79. package/src/components/Drawer/index.ts +2 -0
  80. package/src/components/Dropdown/Dropdown.test.ts +607 -0
  81. package/src/components/Dropdown/Dropdown.vue +807 -0
  82. package/src/components/Dropdown/DropdownItem.vue +227 -0
  83. package/src/components/Dropdown/DropdownSeparator.vue +14 -0
  84. package/src/components/Dropdown/DropdownSub.vue +104 -0
  85. package/src/components/Dropdown/DropdownSubContent.vue +187 -0
  86. package/src/components/Dropdown/DropdownSubTrigger.vue +151 -0
  87. package/src/components/Dropdown/index.ts +14 -0
  88. package/src/components/EmptyState/EmptyState.test.ts +180 -0
  89. package/src/components/EmptyState/EmptyState.vue +137 -0
  90. package/src/components/EmptyState/index.ts +2 -0
  91. package/src/components/FileUpload/FileUpload.test.ts +1151 -0
  92. package/src/components/FileUpload/FileUpload.vue +1042 -0
  93. package/src/components/FileUpload/index.ts +2 -0
  94. package/src/components/Heading/Heading.test.ts +107 -0
  95. package/src/components/Heading/Heading.vue +67 -0
  96. package/src/components/Heading/index.ts +2 -0
  97. package/src/components/Icon/Icon.test.ts +157 -0
  98. package/src/components/Icon/Icon.vue +86 -0
  99. package/src/components/Icon/index.ts +2 -0
  100. package/src/components/Input/Input.test.ts +273 -0
  101. package/src/components/Input/Input.vue +388 -0
  102. package/src/components/Input/index.ts +2 -0
  103. package/src/components/Layout/Container.vue +67 -0
  104. package/src/components/Layout/Grid.vue +159 -0
  105. package/src/components/Layout/GridItem.vue +154 -0
  106. package/src/components/Layout/Layout.test.ts +202 -0
  107. package/src/components/Layout/Stack.vue +128 -0
  108. package/src/components/Layout/index.ts +9 -0
  109. package/src/components/Layout/keys.ts +7 -0
  110. package/src/components/Modal/Modal.test.ts +311 -0
  111. package/src/components/Modal/Modal.vue +336 -0
  112. package/src/components/Modal/index.ts +2 -0
  113. package/src/components/Pagination/Pagination.test.ts +303 -0
  114. package/src/components/Pagination/Pagination.vue +212 -0
  115. package/src/components/Pagination/index.ts +3 -0
  116. package/src/components/Pagination/utils.ts +86 -0
  117. package/src/components/Popover/Popover.test.ts +285 -0
  118. package/src/components/Popover/Popover.vue +441 -0
  119. package/src/components/Popover/index.ts +2 -0
  120. package/src/components/Progress/Progress.test.ts +361 -0
  121. package/src/components/Progress/Progress.vue +363 -0
  122. package/src/components/Progress/index.ts +7 -0
  123. package/src/components/Radio/Radio.test.ts +216 -0
  124. package/src/components/Radio/Radio.vue +214 -0
  125. package/src/components/Radio/index.ts +2 -0
  126. package/src/components/Rating/Rating.test.ts +319 -0
  127. package/src/components/Rating/Rating.vue +247 -0
  128. package/src/components/Rating/index.ts +2 -0
  129. package/src/components/SegmentedControl/SegmentedControl.test.ts +292 -0
  130. package/src/components/SegmentedControl/SegmentedControl.vue +288 -0
  131. package/src/components/SegmentedControl/index.ts +2 -0
  132. package/src/components/Select/Select.test.ts +589 -0
  133. package/src/components/Select/Select.vue +666 -0
  134. package/src/components/Select/index.ts +2 -0
  135. package/src/components/Sidebar/Sidebar.test.ts +301 -0
  136. package/src/components/Sidebar/SidebarGroup.vue +103 -0
  137. package/src/components/Sidebar/SidebarItem.vue +196 -0
  138. package/src/components/Sidebar/SidebarLayout.vue +42 -0
  139. package/src/components/Sidebar/SidebarRoot.vue +122 -0
  140. package/src/components/Sidebar/index.ts +11 -0
  141. package/src/components/Sidebar/keys.ts +14 -0
  142. package/src/components/Skeleton/Skeleton.test.ts +130 -0
  143. package/src/components/Skeleton/Skeleton.vue +104 -0
  144. package/src/components/Skeleton/index.ts +2 -0
  145. package/src/components/Slider/Slider.test.ts +416 -0
  146. package/src/components/Slider/Slider.vue +435 -0
  147. package/src/components/Slider/index.ts +2 -0
  148. package/src/components/Slider/utils.ts +91 -0
  149. package/src/components/Spinner/Spinner.test.ts +79 -0
  150. package/src/components/Spinner/Spinner.vue +159 -0
  151. package/src/components/Spinner/index.ts +2 -0
  152. package/src/components/SpireProvider/SpireProvider.vue +71 -0
  153. package/src/components/SpireProvider/index.ts +11 -0
  154. package/src/components/Stepper/Stepper.test.ts +221 -0
  155. package/src/components/Stepper/StepperContent.vue +51 -0
  156. package/src/components/Stepper/StepperItem.vue +89 -0
  157. package/src/components/Stepper/StepperRoot.vue +101 -0
  158. package/src/components/Stepper/StepperSeparator.vue +52 -0
  159. package/src/components/Stepper/StepperTrigger.vue +144 -0
  160. package/src/components/Stepper/index.ts +11 -0
  161. package/src/components/Stepper/keys.ts +27 -0
  162. package/src/components/Switch/Switch.test.ts +214 -0
  163. package/src/components/Switch/Switch.vue +235 -0
  164. package/src/components/Switch/index.ts +2 -0
  165. package/src/components/Tabs/Tabs.test.ts +363 -0
  166. package/src/components/Tabs/Tabs.vue +318 -0
  167. package/src/components/Tabs/index.ts +2 -0
  168. package/src/components/Text/Text.test.ts +154 -0
  169. package/src/components/Text/Text.vue +100 -0
  170. package/src/components/Text/index.ts +2 -0
  171. package/src/components/Textarea/Textarea.test.ts +432 -0
  172. package/src/components/Textarea/Textarea.vue +411 -0
  173. package/src/components/Textarea/index.ts +2 -0
  174. package/src/components/TimePicker/TimePicker.test.ts +352 -0
  175. package/src/components/TimePicker/TimePicker.vue +569 -0
  176. package/src/components/TimePicker/index.ts +2 -0
  177. package/src/components/Timeline/Timeline.test.ts +193 -0
  178. package/src/components/Timeline/Timeline.vue +111 -0
  179. package/src/components/Timeline/TimelineItem.vue +167 -0
  180. package/src/components/Timeline/index.ts +13 -0
  181. package/src/components/Timeline/keys.ts +21 -0
  182. package/src/components/Toast/ToastItem.test.ts +289 -0
  183. package/src/components/Toast/ToastItem.vue +370 -0
  184. package/src/components/Toast/ToastProvider.test.ts +158 -0
  185. package/src/components/Toast/ToastProvider.vue +181 -0
  186. package/src/components/Toast/index.ts +83 -0
  187. package/src/components/Toast/toastState.test.ts +165 -0
  188. package/src/components/Toast/toastState.ts +161 -0
  189. package/src/components/ToggleButton/ToggleButton.test.ts +166 -0
  190. package/src/components/ToggleButton/ToggleButton.vue +197 -0
  191. package/src/components/ToggleButton/index.ts +2 -0
  192. package/src/components/ToggleGroup/ToggleGroup.test.ts +181 -0
  193. package/src/components/ToggleGroup/ToggleGroup.vue +130 -0
  194. package/src/components/ToggleGroup/index.ts +2 -0
  195. package/src/components/Tooltip/Tooltip.test.ts +238 -0
  196. package/src/components/Tooltip/Tooltip.vue +217 -0
  197. package/src/components/Tooltip/index.ts +2 -0
  198. package/src/components/TreeView/TreeView.test.ts +357 -0
  199. package/src/components/TreeView/TreeView.vue +251 -0
  200. package/src/components/TreeView/TreeViewItem.vue +288 -0
  201. package/src/components/TreeView/index.ts +11 -0
  202. package/src/components/TreeView/keys.ts +35 -0
  203. package/src/composables/index.ts +12 -0
  204. package/src/composables/useClickOutside.ts +36 -0
  205. package/src/composables/useClipboard.ts +35 -0
  206. package/src/composables/useEventListener.ts +48 -0
  207. package/src/composables/useFocusTrap.ts +58 -0
  208. package/src/composables/useHoverReveal.ts +98 -0
  209. package/src/composables/useId.ts +10 -0
  210. package/src/composables/useMagnetic.ts +171 -0
  211. package/src/composables/useRelativePosition.ts +127 -0
  212. package/src/composables/useRipple.ts +146 -0
  213. package/src/composables/useScrollLock.ts +25 -0
  214. package/src/composables/useSpireConfig.ts +27 -0
  215. package/src/composables/useStagger.ts +224 -0
  216. package/src/config/icons.test.ts +115 -0
  217. package/src/config/icons.ts +170 -0
  218. package/src/index.ts +361 -0
  219. package/src/styles/depth.css +129 -0
  220. package/src/styles/effects.css +169 -0
  221. package/src/styles/fallback.css +152 -0
  222. package/src/styles/main.css +25 -0
  223. package/src/styles/mood.css +211 -0
  224. package/src/styles/motion.css +159 -0
  225. package/src/styles/reset.css +97 -0
  226. package/src/styles/theme.css +708 -0
  227. package/src/styles/tokens.css +183 -0
  228. package/src/utils/.gitkeep +0 -0
  229. package/src/utils/color.ts +277 -0
  230. package/src/utils/date.test.ts +522 -0
  231. package/src/utils/date.ts +380 -0
  232. package/src/utils/index.ts +23 -0
  233. package/src/utils/object.test.ts +80 -0
  234. package/src/utils/object.ts +25 -0
  235. package/src/utils/string.test.ts +64 -0
  236. package/src/utils/string.ts +32 -0
  237. package/src/utils/time.ts +156 -0
@@ -0,0 +1,115 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest'
2
+ import { h, type FunctionalComponent } from 'vue'
3
+ import {
4
+ configureIcons,
5
+ resetIcons,
6
+ useInternalIcon,
7
+ getIconRegistry
8
+ } from './icons'
9
+
10
+ const MockIcon: FunctionalComponent = () => h('svg', { class: 'mock-icon' })
11
+
12
+ describe('Icon Registry', () => {
13
+ beforeEach(() => {
14
+ resetIcons()
15
+ })
16
+
17
+ describe('useInternalIcon', () => {
18
+ it('returns default icon for sortAsc', () => {
19
+ const icon = useInternalIcon('sortAsc')
20
+ expect(icon).toBeDefined()
21
+ expect(typeof icon).toBe('function')
22
+ })
23
+
24
+ it('returns default icon for all semantic keys', () => {
25
+ const keys = [
26
+ 'sortAsc', 'sortDesc', 'sortNeutral',
27
+ 'expand', 'collapse', 'close', 'search', 'check',
28
+ 'info', 'success', 'warning', 'error',
29
+ 'emptyData', 'emptySearch'
30
+ ] as const
31
+
32
+ keys.forEach(key => {
33
+ const icon = useInternalIcon(key)
34
+ expect(icon).toBeDefined()
35
+ })
36
+ })
37
+ })
38
+
39
+ describe('configureIcons', () => {
40
+ it('overrides a single icon', () => {
41
+ configureIcons({ sortAsc: MockIcon })
42
+ const icon = useInternalIcon('sortAsc')
43
+ expect(icon).toBe(MockIcon)
44
+ })
45
+
46
+ it('overrides multiple icons', () => {
47
+ configureIcons({
48
+ sortAsc: MockIcon,
49
+ sortDesc: MockIcon,
50
+ close: MockIcon
51
+ })
52
+
53
+ expect(useInternalIcon('sortAsc')).toBe(MockIcon)
54
+ expect(useInternalIcon('sortDesc')).toBe(MockIcon)
55
+ expect(useInternalIcon('close')).toBe(MockIcon)
56
+ })
57
+
58
+ it('preserves non-overridden icons', () => {
59
+ const originalExpand = useInternalIcon('expand')
60
+ configureIcons({ sortAsc: MockIcon })
61
+ expect(useInternalIcon('expand')).toBe(originalExpand)
62
+ })
63
+
64
+ it('allows partial updates', () => {
65
+ configureIcons({ sortAsc: MockIcon })
66
+ const originalSortDesc = useInternalIcon('sortDesc')
67
+
68
+ const AnotherMockIcon: FunctionalComponent = () => h('svg', { class: 'another-mock' })
69
+ configureIcons({ sortDesc: AnotherMockIcon })
70
+
71
+ expect(useInternalIcon('sortAsc')).toBe(MockIcon)
72
+ expect(useInternalIcon('sortDesc')).toBe(AnotherMockIcon)
73
+ })
74
+ })
75
+
76
+ describe('resetIcons', () => {
77
+ it('resets all icons to defaults', () => {
78
+ const originalSortAsc = useInternalIcon('sortAsc')
79
+ configureIcons({ sortAsc: MockIcon })
80
+ expect(useInternalIcon('sortAsc')).toBe(MockIcon)
81
+
82
+ resetIcons()
83
+ expect(useInternalIcon('sortAsc')).not.toBe(MockIcon)
84
+ expect(typeof useInternalIcon('sortAsc')).toBe('function')
85
+ })
86
+ })
87
+
88
+ describe('getIconRegistry', () => {
89
+ it('returns all icons', () => {
90
+ const registry = getIconRegistry()
91
+ expect(registry.sortAsc).toBeDefined()
92
+ expect(registry.sortDesc).toBeDefined()
93
+ expect(registry.emptyData).toBeDefined()
94
+ })
95
+
96
+ it('reflects configuration changes', () => {
97
+ configureIcons({ sortAsc: MockIcon })
98
+ const registry = getIconRegistry()
99
+ expect(registry.sortAsc).toBe(MockIcon)
100
+ })
101
+ })
102
+
103
+ describe('Default Icons', () => {
104
+ it('default icons are functional components', () => {
105
+ const icon = useInternalIcon('sortAsc')
106
+ expect(typeof icon).toBe('function')
107
+ })
108
+
109
+ it('default icons render SVG elements', () => {
110
+ const icon = useInternalIcon('emptyData')
111
+ const vnode = (icon as FunctionalComponent)({}, { attrs: {}, slots: {}, emit: () => {} })
112
+ expect(vnode.type).toBe('svg')
113
+ })
114
+ })
115
+ })
@@ -0,0 +1,170 @@
1
+ import { shallowRef, h, type Component, type FunctionalComponent } from 'vue'
2
+
3
+ /**
4
+ * Semantic icon keys used internally by Spire UI components.
5
+ * Components request icons by function, not by name.
6
+ */
7
+ export interface IconMap {
8
+ sortAsc: Component
9
+ sortDesc: Component
10
+ sortNeutral: Component
11
+ expand: Component
12
+ collapse: Component
13
+ close: Component
14
+ search: Component
15
+ check: Component
16
+ info: Component
17
+ success: Component
18
+ warning: Component
19
+ error: Component
20
+ emptyData: Component
21
+ emptySearch: Component
22
+ calendar: Component
23
+ chevronLeft: Component
24
+ chevronRight: Component
25
+ star: Component
26
+ starFilled: Component
27
+ }
28
+
29
+ type SVGProps = { class?: string }
30
+
31
+ function createSvgIcon(paths: string[], viewBox = '0 0 24 24'): FunctionalComponent<SVGProps> {
32
+ return (props) => h('svg', {
33
+ xmlns: 'http://www.w3.org/2000/svg',
34
+ viewBox,
35
+ fill: 'none',
36
+ stroke: 'currentColor',
37
+ 'stroke-width': '1.5',
38
+ 'stroke-linecap': 'round',
39
+ 'stroke-linejoin': 'round',
40
+ class: props.class
41
+ }, paths.map(d => h('path', { d })))
42
+ }
43
+
44
+ function createFilledSvgIcon(paths: string[], viewBox = '0 0 24 24'): FunctionalComponent<SVGProps> {
45
+ return (props) => h('svg', {
46
+ xmlns: 'http://www.w3.org/2000/svg',
47
+ viewBox,
48
+ fill: 'currentColor',
49
+ class: props.class
50
+ }, paths.map(d => h('path', { d })))
51
+ }
52
+
53
+ const defaultIcons: IconMap = {
54
+ sortAsc: createSvgIcon(['M4 10l4-4 4 4'], '0 0 16 16'),
55
+
56
+ sortDesc: createSvgIcon(['M4 6l4 4 4-4'], '0 0 16 16'),
57
+
58
+ sortNeutral: createSvgIcon([
59
+ 'M4 6l4-3 4 3',
60
+ 'M4 10l4 3 4-3'
61
+ ], '0 0 16 16'),
62
+
63
+ expand: createSvgIcon(['M6 9l6 6 6-6']),
64
+
65
+ collapse: createSvgIcon(['M18 15l-6-6-6 6']),
66
+
67
+ close: createSvgIcon(['M18 6L6 18', 'M6 6l12 12']),
68
+
69
+ search: createSvgIcon([
70
+ 'M11 19a8 8 0 100-16 8 8 0 000 16z',
71
+ 'M21 21l-4.35-4.35'
72
+ ]),
73
+
74
+ check: createSvgIcon(['M20 6L9 17l-5-5']),
75
+
76
+ info: createSvgIcon([
77
+ 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z',
78
+ 'M12 16v-4',
79
+ 'M12 8h.01'
80
+ ]),
81
+
82
+ success: createSvgIcon([
83
+ 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z',
84
+ 'M9 12l2 2 4-4'
85
+ ]),
86
+
87
+ warning: createSvgIcon([
88
+ 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z',
89
+ 'M12 8v4',
90
+ 'M12 16h.01'
91
+ ]),
92
+
93
+ error: createSvgIcon([
94
+ 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z',
95
+ 'M15 9l-6 6',
96
+ 'M9 9l6 6'
97
+ ]),
98
+
99
+ emptyData: createSvgIcon([
100
+ 'M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4'
101
+ ]),
102
+
103
+ emptySearch: createSvgIcon([
104
+ 'M11 19a8 8 0 100-16 8 8 0 000 16z',
105
+ 'M21 21l-4.35-4.35'
106
+ ]),
107
+
108
+ calendar: createSvgIcon([
109
+ 'M8 2v4',
110
+ 'M16 2v4',
111
+ 'M3 10h18',
112
+ 'M5 4h14a2 2 0 012 2v14a2 2 0 01-2 2H5a2 2 0 01-2-2V6a2 2 0 012-2z'
113
+ ]),
114
+
115
+ chevronLeft: createSvgIcon(['M15 18l-6-6 6-6']),
116
+
117
+ chevronRight: createSvgIcon(['M9 18l6-6-6-6']),
118
+
119
+ star: createSvgIcon([
120
+ 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'
121
+ ]),
122
+
123
+ starFilled: createFilledSvgIcon([
124
+ 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'
125
+ ])
126
+ }
127
+
128
+ const iconRegistry = shallowRef<IconMap>({ ...defaultIcons })
129
+
130
+ /**
131
+ * Configure internal icons used by Spire UI components.
132
+ * Call this before mounting your app to customize icons globally.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * import { configureIcons } from 'spire-ui'
137
+ * import { ArrowUp, ArrowDown, X } from 'lucide-vue-next'
138
+ *
139
+ * configureIcons({
140
+ * sortAsc: ArrowUp,
141
+ * sortDesc: ArrowDown,
142
+ * close: X
143
+ * })
144
+ * ```
145
+ */
146
+ export function configureIcons(userIcons: Partial<IconMap>): void {
147
+ iconRegistry.value = { ...iconRegistry.value, ...userIcons }
148
+ }
149
+
150
+ /**
151
+ * Reset icons to defaults. Useful for testing.
152
+ */
153
+ export function resetIcons(): void {
154
+ iconRegistry.value = { ...defaultIcons }
155
+ }
156
+
157
+ /**
158
+ * Get an internal icon by semantic key.
159
+ * Used internally by Spire UI components.
160
+ */
161
+ export function useInternalIcon(key: keyof IconMap): Component {
162
+ return iconRegistry.value[key]
163
+ }
164
+
165
+ /**
166
+ * Get all currently configured icons.
167
+ */
168
+ export function getIconRegistry(): Readonly<IconMap> {
169
+ return iconRegistry.value
170
+ }
package/src/index.ts ADDED
@@ -0,0 +1,361 @@
1
+ // Styles - Must be imported by consumer
2
+ import './styles/main.css'
3
+
4
+ // Components
5
+ export {
6
+ AccordionRoot,
7
+ AccordionItem,
8
+ AccordionTrigger,
9
+ AccordionContent
10
+ } from './components/Accordion'
11
+ export type {
12
+ AccordionRootProps,
13
+ AccordionItemProps,
14
+ AccordionTriggerProps
15
+ } from './components/Accordion'
16
+
17
+ export { Avatar } from './components/Avatar'
18
+ export type { AvatarProps } from './components/Avatar'
19
+
20
+ export { Badge } from './components/Badge'
21
+ export type { BadgeProps } from './components/Badge'
22
+
23
+ export { BadgeContainer } from './components/BadgeContainer'
24
+ export type { BadgeContainerProps } from './components/BadgeContainer'
25
+
26
+ export {
27
+ BreadcrumbRoot,
28
+ BreadcrumbList,
29
+ BreadcrumbItem,
30
+ BreadcrumbLink,
31
+ BreadcrumbPage,
32
+ BreadcrumbSeparator,
33
+ BreadcrumbEllipsis
34
+ } from './components/Breadcrumb'
35
+ export type {
36
+ BreadcrumbRootProps,
37
+ BreadcrumbLinkProps,
38
+ BreadcrumbEllipsisProps,
39
+ BreadcrumbEllipsisItem,
40
+ BreadcrumbContext
41
+ } from './components/Breadcrumb'
42
+
43
+ export { Button } from './components/Button'
44
+ export type { ButtonProps } from './components/Button'
45
+
46
+ export { Callout } from './components/Callout'
47
+ export type { CalloutProps, CalloutVariant } from './components/Callout'
48
+
49
+ export { Card, CardHeader, CardContent, CardFooter, CardImage } from './components/Card'
50
+ export type {
51
+ CardProps,
52
+ CardVariant,
53
+ CardPadding,
54
+ CardHeaderProps,
55
+ CardContentProps,
56
+ CardFooterProps,
57
+ CardImageProps,
58
+ CardImagePosition,
59
+ CardImageAspectRatio,
60
+ CardImageFit
61
+ } from './components/Card'
62
+
63
+ export { Checkbox } from './components/Checkbox'
64
+ export type { CheckboxProps } from './components/Checkbox'
65
+
66
+ export { ColorPicker, ColorArea, ColorSlider } from './components/ColorPicker'
67
+ export type { ColorPickerProps, ColorFormat, ColorAreaProps, ColorSliderProps } from './components/ColorPicker'
68
+
69
+ export {
70
+ BaseChart,
71
+ LineChart,
72
+ BarChart,
73
+ DonutChart,
74
+ useChartTheme
75
+ } from './components/Chart'
76
+ export type {
77
+ BaseChartProps,
78
+ ChartDataset,
79
+ TooltipData,
80
+ LegendItem,
81
+ LineChartProps,
82
+ LineChartSeries,
83
+ BarChartProps,
84
+ BarChartSeries,
85
+ DonutChartProps,
86
+ DonutChartSegment,
87
+ ChartTheme,
88
+ ChartThemeColors
89
+ } from './components/Chart'
90
+
91
+ export { DataTable } from './components/DataTable'
92
+ export type {
93
+ DataTableProps,
94
+ DataTableColumn,
95
+ SortState,
96
+ SortDirection,
97
+ ColumnAlign,
98
+ PaginationConfig,
99
+ FilterFn
100
+ } from './components/DataTable'
101
+
102
+ export { Pagination } from './components/Pagination'
103
+ export type { PaginationProps } from './components/Pagination'
104
+ export { generatePageRange, type PageItem } from './components/Pagination'
105
+
106
+ export { DatePicker } from './components/DatePicker'
107
+ export type { DatePickerProps, ViewMode as DatePickerViewMode } from './components/DatePicker'
108
+
109
+ export { Drawer } from './components/Drawer'
110
+ export type {
111
+ DrawerProps,
112
+ DrawerPlacement,
113
+ DrawerVariant,
114
+ DrawerSize
115
+ } from './components/Drawer'
116
+
117
+ export {
118
+ Dropdown,
119
+ DropdownItem,
120
+ DropdownSeparator,
121
+ DropdownSub,
122
+ DropdownSubTrigger,
123
+ DropdownSubContent
124
+ } from './components/Dropdown'
125
+ export type {
126
+ DropdownProps,
127
+ DropdownPlacement,
128
+ DropdownContext,
129
+ DropdownItemProps,
130
+ DropdownSubContext,
131
+ DropdownSubTriggerProps
132
+ } from './components/Dropdown'
133
+
134
+ export { EmptyState } from './components/EmptyState'
135
+ export type { EmptyStateProps, EmptyStateVariant } from './components/EmptyState'
136
+
137
+ export { Combobox } from './components/Combobox'
138
+ export type { ComboboxProps, ComboboxOption } from './components/Combobox'
139
+
140
+ export { ChoiceChip } from './components/ChoiceChip'
141
+ export type { ChoiceChipProps } from './components/ChoiceChip'
142
+
143
+ export { ChoiceChipGroup } from './components/ChoiceChipGroup'
144
+ export type { ChoiceChipGroupProps } from './components/ChoiceChipGroup'
145
+
146
+ export { FileUpload } from './components/FileUpload'
147
+ export type { FileUploadProps, UploadFile } from './components/FileUpload'
148
+
149
+ export { Heading } from './components/Heading'
150
+ export type { HeadingProps } from './components/Heading'
151
+
152
+ export { Icon } from './components/Icon'
153
+ export type { IconProps, IconInput } from './components/Icon'
154
+
155
+ export { Input } from './components/Input'
156
+ export type { InputProps } from './components/Input'
157
+
158
+ export { Modal } from './components/Modal'
159
+ export type { ModalProps, ModalSize } from './components/Modal'
160
+
161
+ export { Popover } from './components/Popover'
162
+ export type { PopoverProps, PopoverPlacement } from './components/Popover'
163
+
164
+ export { Progress } from './components/Progress'
165
+ export type {
166
+ ProgressProps,
167
+ ProgressVariant,
168
+ ProgressSize,
169
+ ProgressColor
170
+ } from './components/Progress'
171
+
172
+ export { Radio } from './components/Radio'
173
+ export type { RadioProps } from './components/Radio'
174
+
175
+ export { Rating } from './components/Rating'
176
+ export type { RatingProps } from './components/Rating'
177
+
178
+ export { SegmentedControl } from './components/SegmentedControl'
179
+ export type { SegmentedControlProps, SegmentedOption } from './components/SegmentedControl'
180
+
181
+ export { Select } from './components/Select'
182
+ export type { SelectProps, SelectOption } from './components/Select'
183
+
184
+ export { Slider } from './components/Slider'
185
+ export type { SliderProps } from './components/Slider'
186
+
187
+ export {
188
+ SidebarLayout,
189
+ SidebarRoot,
190
+ SidebarItem,
191
+ SidebarGroup
192
+ } from './components/Sidebar'
193
+ export type {
194
+ SidebarLayoutProps,
195
+ SidebarRootProps,
196
+ SidebarItemProps,
197
+ SidebarGroupProps,
198
+ SidebarContext,
199
+ SidebarGroupContext
200
+ } from './components/Sidebar'
201
+ export { SidebarKey, SidebarGroupKey } from './components/Sidebar'
202
+
203
+ export { Skeleton } from './components/Skeleton'
204
+ export type { SkeletonProps, SkeletonVariant } from './components/Skeleton'
205
+
206
+ export { SpireProvider, spireConfigKey } from './components/SpireProvider'
207
+ export type {
208
+ Theme,
209
+ Mood,
210
+ Depth,
211
+ Motion,
212
+ Texture,
213
+ SpireConfig,
214
+ SpireProviderProps
215
+ } from './components/SpireProvider'
216
+
217
+ export { Spinner } from './components/Spinner'
218
+ export type { SpinnerProps } from './components/Spinner'
219
+
220
+ export {
221
+ StepperRoot,
222
+ StepperItem,
223
+ StepperTrigger,
224
+ StepperContent,
225
+ StepperSeparator
226
+ } from './components/Stepper'
227
+ export type {
228
+ StepperRootProps,
229
+ StepperItemProps,
230
+ StepperTriggerProps,
231
+ StepperContext,
232
+ StepperItemContext,
233
+ StepState,
234
+ StepperOrientation
235
+ } from './components/Stepper'
236
+ export { StepperKey, StepperItemKey } from './components/Stepper'
237
+
238
+ export { Switch } from './components/Switch'
239
+ export type { SwitchProps } from './components/Switch'
240
+
241
+ export { Tabs } from './components/Tabs'
242
+ export type { TabsProps, TabItem } from './components/Tabs'
243
+
244
+ export { Textarea } from './components/Textarea'
245
+ export type { TextareaProps } from './components/Textarea'
246
+
247
+ export { Text } from './components/Text'
248
+ export type { TextProps } from './components/Text'
249
+
250
+ export { Timeline, TimelineItem } from './components/Timeline'
251
+ export type {
252
+ TimelineProps,
253
+ TimelineItemProps,
254
+ TimelineContext,
255
+ TimelineAlign,
256
+ TimelineLineStyle,
257
+ TimelineDotColor
258
+ } from './components/Timeline'
259
+ export { TimelineKey } from './components/Timeline'
260
+
261
+ export { TimePicker } from './components/TimePicker'
262
+ export type { TimePickerProps } from './components/TimePicker'
263
+
264
+ export { ToggleButton } from './components/ToggleButton'
265
+ export type { ToggleButtonProps } from './components/ToggleButton'
266
+
267
+ export { ToggleGroup } from './components/ToggleGroup'
268
+ export type { ToggleGroupProps } from './components/ToggleGroup'
269
+
270
+ export { ToastProvider, ToastItem, useToast } from './components/Toast'
271
+ export type { ToastProviderProps, ToastItemProps, Toast, ToastOptions, ToastVariant, ToastAction } from './components/Toast'
272
+
273
+ export { Tooltip } from './components/Tooltip'
274
+ export type { TooltipProps } from './components/Tooltip'
275
+
276
+ export { TreeView, TreeViewItem } from './components/TreeView'
277
+ export type {
278
+ TreeViewProps,
279
+ TreeViewItemProps,
280
+ TreeNode,
281
+ TreeViewContext,
282
+ TreeViewItemContext
283
+ } from './components/TreeView'
284
+ export { TreeViewKey, TreeViewItemKey } from './components/TreeView'
285
+
286
+ export { Container, Stack, Grid, GridItem } from './components/Layout'
287
+ export type {
288
+ ContainerProps,
289
+ StackProps,
290
+ SpacingToken,
291
+ GridProps,
292
+ ColumnCount,
293
+ ResponsiveColumns,
294
+ GridItemProps,
295
+ SpanCount,
296
+ ResponsiveSpan
297
+ } from './components/Layout'
298
+
299
+ // Composables
300
+ export { useClickOutside } from './composables'
301
+ export { useClipboard } from './composables'
302
+ export { useEventListener } from './composables'
303
+ export { useFocusTrap } from './composables'
304
+ export { useHoverReveal, type UseHoverRevealOptions } from './composables'
305
+ export { useId } from './composables'
306
+ export { useMagnetic, type UseMagneticOptions, type UseMagneticReturn } from './composables'
307
+ export { useRelativePosition, type Placement } from './composables'
308
+ export { useRipple, type UseRippleOptions } from './composables'
309
+ export { useScrollLock } from './composables'
310
+ export { useStagger, getStaggerStyle, type UseStaggerOptions, type UseStaggerReturn } from './composables'
311
+
312
+ // Utilities
313
+ export { getInitials, getNestedValue } from './utils'
314
+ export {
315
+ generateCalendarGrid,
316
+ getDaysInMonth,
317
+ formatDate,
318
+ parseDate,
319
+ isSameDate,
320
+ isDateBefore,
321
+ isDateAfter,
322
+ getMonthName,
323
+ getMonthNamesShort,
324
+ getWeekdayNames,
325
+ isDateInRange,
326
+ isDateBetween,
327
+ getRangeClass,
328
+ normalizeRange,
329
+ generateYearGrid,
330
+ getPresetRange
331
+ } from './utils'
332
+ export type { CalendarDay, RangeState, RangeClass } from './utils'
333
+ export {
334
+ hexToRgb,
335
+ rgbToHex,
336
+ rgbToHsv,
337
+ hsvToRgb,
338
+ hexToHsv,
339
+ hsvToHex,
340
+ oklchToRgb,
341
+ rgbToOklch,
342
+ hsvToOklch,
343
+ oklchToHsv,
344
+ formatRgb,
345
+ formatOklch,
346
+ parseColorString,
347
+ formatColor
348
+ } from './utils/color'
349
+ export type { RGB, HSV, OKLCH, RGBA, HSVA } from './utils/color'
350
+ export {
351
+ parseTime,
352
+ formatTime,
353
+ generateRange,
354
+ to12Hour,
355
+ to24Hour,
356
+ isValidTimeString
357
+ } from './utils/time'
358
+ export type { ParsedTime, TimeFormat } from './utils/time'
359
+
360
+ // Configuration
361
+ export { configureIcons, resetIcons, type IconMap } from './config/icons'