@duro-app/ui 5.10.0 → 5.12.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 (179) hide show
  1. package/dist/{Table-gRiLI243.js → Table-ColfpgKV.js} +8 -4
  2. package/dist/Table-ColfpgKV.js.map +1 -0
  3. package/dist/compiler-runtime-BuugS4D0.js.map +1 -1
  4. package/dist/components/Alert/Alert.d.ts.map +1 -1
  5. package/dist/components/Button/Button.d.ts +2 -1
  6. package/dist/components/Button/Button.d.ts.map +1 -1
  7. package/dist/components/Button/styles.css.d.ts +1 -0
  8. package/dist/components/Button/styles.css.d.ts.map +1 -1
  9. package/dist/components/Callout/Callout.d.ts.map +1 -1
  10. package/dist/components/Callout/styles.css.d.ts +3 -0
  11. package/dist/components/Callout/styles.css.d.ts.map +1 -1
  12. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  13. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -1
  14. package/dist/components/DetailPanel/DetailPanel.d.ts.map +1 -1
  15. package/dist/components/Dialog/Dialog.d.ts +2 -17
  16. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  17. package/dist/components/Dialog/Dialog.stories.d.ts +4 -0
  18. package/dist/components/Dialog/Dialog.stories.d.ts.map +1 -1
  19. package/dist/components/Dialog/native.css.d.ts +82 -0
  20. package/dist/components/Dialog/native.css.d.ts.map +1 -0
  21. package/dist/components/Dialog/parts.css.d.ts +82 -0
  22. package/dist/components/Dialog/parts.css.d.ts.map +1 -0
  23. package/dist/components/Dialog/parts.d.ts +35 -0
  24. package/dist/components/Dialog/parts.d.ts.map +1 -0
  25. package/dist/components/Dialog/styles.css.d.ts +1 -74
  26. package/dist/components/Dialog/styles.css.d.ts.map +1 -1
  27. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  28. package/dist/components/Drawer/styles.css.d.ts +2 -0
  29. package/dist/components/Drawer/styles.css.d.ts.map +1 -1
  30. package/dist/components/FileTrigger/FileTrigger.d.ts +23 -0
  31. package/dist/components/FileTrigger/FileTrigger.d.ts.map +1 -0
  32. package/dist/components/FileTrigger/FileTrigger.meta.d.ts +3 -0
  33. package/dist/components/FileTrigger/FileTrigger.meta.d.ts.map +1 -0
  34. package/dist/components/FileTrigger/FileTrigger.stories.d.ts +9 -0
  35. package/dist/components/FileTrigger/FileTrigger.stories.d.ts.map +1 -0
  36. package/dist/components/FileTrigger/index.d.ts +3 -0
  37. package/dist/components/FileTrigger/index.d.ts.map +1 -0
  38. package/dist/components/FileTrigger/pick.d.ts +14 -0
  39. package/dist/components/FileTrigger/pick.d.ts.map +1 -0
  40. package/dist/components/Grid/styles.css.d.ts +1 -0
  41. package/dist/components/Grid/styles.css.d.ts.map +1 -1
  42. package/dist/components/Icon/Icon.d.ts +3 -9
  43. package/dist/components/Icon/Icon.d.ts.map +1 -1
  44. package/dist/components/Icon/Icon.stories.d.ts.map +1 -1
  45. package/dist/components/Icon/geometry.d.ts +60 -0
  46. package/dist/components/Icon/geometry.d.ts.map +1 -0
  47. package/dist/components/Icon/types.d.ts +15 -0
  48. package/dist/components/Icon/types.d.ts.map +1 -0
  49. package/dist/components/Input/Input.d.ts +5 -1
  50. package/dist/components/Input/Input.d.ts.map +1 -1
  51. package/dist/components/Input/styles.css.d.ts +1 -0
  52. package/dist/components/Input/styles.css.d.ts.map +1 -1
  53. package/dist/components/LinkButton/styles.css.d.ts +1 -0
  54. package/dist/components/LinkButton/styles.css.d.ts.map +1 -1
  55. package/dist/components/Meter/styles.css.d.ts +1 -0
  56. package/dist/components/Meter/styles.css.d.ts.map +1 -1
  57. package/dist/components/PageShell/styles.css.d.ts +2 -0
  58. package/dist/components/PageShell/styles.css.d.ts.map +1 -1
  59. package/dist/components/RadioGroup/RadioGroup.d.ts +1 -17
  60. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  61. package/dist/components/RadioGroup/RadioGroup.stories.d.ts +3 -0
  62. package/dist/components/RadioGroup/RadioGroup.stories.d.ts.map +1 -1
  63. package/dist/components/RadioGroup/group.d.ts +31 -0
  64. package/dist/components/RadioGroup/group.d.ts.map +1 -0
  65. package/dist/components/RadioGroup/styles.css.d.ts +10 -0
  66. package/dist/components/RadioGroup/styles.css.d.ts.map +1 -1
  67. package/dist/components/ScrollArea/styles.css.d.ts +1 -0
  68. package/dist/components/ScrollArea/styles.css.d.ts.map +1 -1
  69. package/dist/components/Spinner/Spinner.d.ts +2 -6
  70. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  71. package/dist/components/Spinner/Spinner.types.d.ts +6 -0
  72. package/dist/components/Spinner/Spinner.types.d.ts.map +1 -0
  73. package/dist/components/Spinner/ring.css.d.ts +39 -0
  74. package/dist/components/Spinner/ring.css.d.ts.map +1 -0
  75. package/dist/components/Spinner/styles.css.d.ts +1 -28
  76. package/dist/components/Spinner/styles.css.d.ts.map +1 -1
  77. package/dist/components/StatusIcon/StatusIcon.d.ts.map +1 -1
  78. package/dist/components/StatusIcon/styles.css.d.ts +3 -0
  79. package/dist/components/StatusIcon/styles.css.d.ts.map +1 -1
  80. package/dist/components/Switch/Switch.d.ts +2 -18
  81. package/dist/components/Switch/Switch.d.ts.map +1 -1
  82. package/dist/components/Switch/Switch.types.d.ts +18 -0
  83. package/dist/components/Switch/Switch.types.d.ts.map +1 -0
  84. package/dist/components/TableOfContents/styles.css.d.ts +1 -0
  85. package/dist/components/TableOfContents/styles.css.d.ts.map +1 -1
  86. package/dist/components/Textarea/styles.css.d.ts +1 -0
  87. package/dist/components/Textarea/styles.css.d.ts.map +1 -1
  88. package/dist/components/Toggle/Toggle.d.ts.map +1 -1
  89. package/dist/components/Toggle/styles.css.d.ts +11 -2
  90. package/dist/components/Toggle/styles.css.d.ts.map +1 -1
  91. package/dist/components/VirtualTable/styles.css.d.ts +6 -0
  92. package/dist/components/VirtualTable/styles.css.d.ts.map +1 -1
  93. package/dist/index.css +1 -1
  94. package/dist/index.d.ts +1 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +4589 -3788
  97. package/dist/index.js.map +1 -1
  98. package/dist/shared/portal/hostRegistry.d.ts +33 -0
  99. package/dist/shared/portal/hostRegistry.d.ts.map +1 -0
  100. package/dist/shared/useOverlayOpenState.d.ts +40 -0
  101. package/dist/shared/useOverlayOpenState.d.ts.map +1 -0
  102. package/dist/table.js +141 -135
  103. package/dist/table.js.map +1 -1
  104. package/package.json +34 -4
  105. package/src/components/Alert/Alert.tsx +14 -2
  106. package/src/components/Button/Button.tsx +3 -2
  107. package/src/components/Button/styles.css.ts +2 -0
  108. package/src/components/Callout/Callout.tsx +17 -3
  109. package/src/components/Callout/styles.css.ts +5 -0
  110. package/src/components/Checkbox/Checkbox.native.tsx +67 -0
  111. package/src/components/Checkbox/Checkbox.tsx +1 -50
  112. package/src/components/ConfirmDialog/ConfirmDialog.tsx +3 -0
  113. package/src/components/DetailPanel/DetailPanel.tsx +9 -45
  114. package/src/components/Dialog/Dialog.native.tsx +296 -0
  115. package/src/components/Dialog/Dialog.stories.tsx +71 -0
  116. package/src/components/Dialog/Dialog.tsx +41 -130
  117. package/src/components/Dialog/native.css.ts +78 -0
  118. package/src/components/Dialog/parts.css.ts +101 -0
  119. package/src/components/Dialog/parts.tsx +61 -0
  120. package/src/components/Dialog/styles.css.ts +2 -89
  121. package/src/components/Drawer/Drawer.tsx +20 -49
  122. package/src/components/Drawer/styles.css.ts +4 -0
  123. package/src/components/FileTrigger/FileTrigger.meta.ts +24 -0
  124. package/src/components/FileTrigger/FileTrigger.stories.tsx +36 -0
  125. package/src/components/FileTrigger/FileTrigger.tsx +80 -0
  126. package/src/components/FileTrigger/index.ts +2 -0
  127. package/src/components/FileTrigger/pick.ts +21 -0
  128. package/src/components/Grid/styles.css.ts +2 -0
  129. package/src/components/Icon/Icon.native.tsx +54 -0
  130. package/src/components/Icon/Icon.stories.tsx +1 -0
  131. package/src/components/Icon/Icon.tsx +19 -400
  132. package/src/components/Icon/geometry.ts +456 -0
  133. package/src/components/Icon/types.ts +74 -0
  134. package/src/components/Input/Input.tsx +8 -0
  135. package/src/components/Input/styles.css.ts +2 -0
  136. package/src/components/LinkButton/styles.css.ts +2 -0
  137. package/src/components/Meter/styles.css.ts +2 -0
  138. package/src/components/PageShell/styles.css.ts +4 -0
  139. package/src/components/RadioGroup/RadioGroup.meta.ts +1 -1
  140. package/src/components/RadioGroup/RadioGroup.native.tsx +48 -0
  141. package/src/components/RadioGroup/RadioGroup.stories.tsx +64 -1
  142. package/src/components/RadioGroup/RadioGroup.tsx +8 -83
  143. package/src/components/RadioGroup/group.tsx +85 -0
  144. package/src/components/RadioGroup/styles.css.ts +13 -0
  145. package/src/components/ScrollArea/styles.css.ts +2 -0
  146. package/src/components/Spinner/Spinner.native.tsx +37 -0
  147. package/src/components/Spinner/Spinner.tsx +6 -15
  148. package/src/components/Spinner/Spinner.types.ts +6 -0
  149. package/src/components/Spinner/ring.css.ts +45 -0
  150. package/src/components/Spinner/styles.css.ts +2 -32
  151. package/src/components/StatusIcon/StatusIcon.tsx +13 -2
  152. package/src/components/StatusIcon/styles.css.ts +5 -0
  153. package/src/components/Switch/Switch.native.tsx +45 -0
  154. package/src/components/Switch/Switch.tsx +22 -44
  155. package/src/components/Switch/Switch.types.ts +18 -0
  156. package/src/components/TableOfContents/styles.css.ts +2 -0
  157. package/src/components/Textarea/styles.css.ts +2 -0
  158. package/src/components/ThemeProvider/ThemeProvider.native.tsx +70 -10
  159. package/src/components/Toggle/Toggle.tsx +2 -0
  160. package/src/components/Toggle/styles.css.ts +14 -2
  161. package/src/components/VirtualTable/styles.css.ts +12 -0
  162. package/src/index.native.ts +28 -1
  163. package/src/index.ts +5 -0
  164. package/src/native-guard/globals.d.ts +10 -0
  165. package/src/native-guard/react-dom.d.ts +3 -0
  166. package/src/shared/accessibilityFocus.native.ts +23 -0
  167. package/src/shared/portal/OverlayModal.native.tsx +51 -0
  168. package/src/shared/portal/PortalHost.native.tsx +102 -0
  169. package/src/shared/portal/hostRegistry.ts +76 -0
  170. package/src/shared/portal/themeScope.native.ts +18 -0
  171. package/src/shared/safeArea.native.ts +22 -0
  172. package/src/shared/useOverlayOpenState.ts +128 -0
  173. package/dist/Table-gRiLI243.js.map +0 -1
  174. package/dist/components/ThemeProvider/ThemeProvider.native.d.ts +0 -10
  175. package/dist/components/ThemeProvider/ThemeProvider.native.d.ts.map +0 -1
  176. package/dist/index.native.d.ts +0 -33
  177. package/dist/index.native.d.ts.map +0 -1
  178. package/dist/platform.native.d.ts +0 -2
  179. package/dist/platform.native.d.ts.map +0 -1
@@ -1,409 +1,27 @@
1
- import type {ReactNode} from 'react'
2
- import {ICON_SIZES, type IconSize} from '@duro-app/tokens/keys'
1
+ import {createElement} from 'react'
2
+ import {ICON_SIZES} from '@duro-app/tokens/keys'
3
+ import {colors} from '@duro-app/tokens/tokens/colors.css'
3
4
 
4
- export type {IconSize}
5
+ import {GLYPHS, type Shape} from './geometry'
6
+ import type {IconProps} from './types'
5
7
 
6
- export type IconName =
7
- | 'x-circle'
8
- | 'check-circle'
9
- | 'check-done'
10
- | 'clock'
11
- | 'forbidden'
12
- | 'info-circle'
13
- | 'alert-triangle'
14
- | 'shield'
15
- | 'lock'
16
- | 'key'
17
- // Navigation / wayfinding glyphs
18
- | 'map'
19
- | 'layers'
20
- | 'repeat'
21
- | 'database'
22
- | 'shield-check'
23
- | 'route'
24
- | 'git-branch'
25
- | 'menu'
26
- | 'pin'
27
- // Infrastructure / inventory glyphs
28
- | 'server'
29
- | 'hard-drive'
30
- | 'box'
31
- | 'image'
32
- | 'tag'
33
- | 'pie-chart'
34
- // People / access / admin glyphs
35
- | 'users'
36
- | 'user-plus'
37
- | 'mail'
38
- | 'file-text'
39
- | 'plug'
40
- // Input / action glyphs
41
- | 'search'
42
- | 'mic'
43
- // Color-mode glyphs
44
- | 'sun'
45
- | 'moon'
46
- | 'monitor'
47
- | 'contrast'
48
- // Device status glyphs
49
- | 'signal'
50
- | 'battery'
51
- // Filled variants (solid shape with cutout symbol)
52
- | 'info-circle-filled'
53
- | 'alert-triangle-filled'
54
- | 'check-circle-filled'
55
- | 'x-circle-filled'
56
- | 'shield-filled'
57
- | 'lock-filled'
8
+ export type {IconName, IconProps, IconSize} from './types'
58
9
 
59
- /** Stroke-based icons (Feather/Lucide style) */
60
- const strokeIcons: Partial<Record<IconName, ReactNode>> = {
61
- 'x-circle': (
62
- <>
63
- <circle cx="12" cy="12" r="10" />
64
- <line x1="15" y1="9" x2="9" y2="15" />
65
- <line x1="9" y1="9" x2="15" y2="15" />
66
- </>
67
- ),
68
- 'check-circle': (
69
- <>
70
- <circle cx="12" cy="12" r="10" />
71
- <polyline points="16 10 11 15 8 12" />
72
- </>
73
- ),
74
- 'check-done': (
75
- <>
76
- <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
77
- <polyline points="22 4 12 14.01 9 11.01" />
78
- </>
79
- ),
80
- clock: (
81
- <>
82
- <circle cx="12" cy="12" r="10" />
83
- <polyline points="12 6 12 12 16 14" />
84
- </>
85
- ),
86
- forbidden: (
87
- <>
88
- <circle cx="12" cy="12" r="10" />
89
- <line x1="4.93" y1="4.93" x2="19.07" y2="19.07" />
90
- </>
91
- ),
92
- 'info-circle': (
93
- <>
94
- <circle cx="12" cy="12" r="10" />
95
- <line x1="12" y1="16" x2="12" y2="12" />
96
- <line x1="12" y1="8" x2="12.01" y2="8" />
97
- </>
98
- ),
99
- 'alert-triangle': (
100
- <>
101
- <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
102
- <line x1="12" y1="9" x2="12" y2="13" />
103
- <line x1="12" y1="17" x2="12.01" y2="17" />
104
- </>
105
- ),
106
- shield: <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />,
107
- lock: (
108
- <>
109
- <rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
110
- <path d="M7 11V7a5 5 0 0 1 10 0v4" />
111
- </>
112
- ),
113
- key: (
114
- <>
115
- <path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" />
116
- </>
117
- ),
118
- // ---- navigation / wayfinding ----
119
- map: (
120
- <>
121
- <polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6" />
122
- <line x1="8" y1="2" x2="8" y2="18" />
123
- <line x1="16" y1="6" x2="16" y2="22" />
124
- </>
125
- ),
126
- layers: (
127
- <>
128
- <polygon points="12 2 2 7 12 12 22 7 12 2" />
129
- <polyline points="2 17 12 22 22 17" />
130
- <polyline points="2 12 12 17 22 12" />
131
- </>
132
- ),
133
- // Two crossing arrows — exchange / interface flows.
134
- repeat: (
135
- <>
136
- <polyline points="17 1 21 5 17 9" />
137
- <path d="M3 11V9a4 4 0 0 1 4-4h14" />
138
- <polyline points="7 23 3 19 7 15" />
139
- <path d="M21 13v2a4 4 0 0 1-4 4H3" />
140
- </>
141
- ),
142
- database: (
143
- <>
144
- <ellipse cx="12" cy="5" rx="9" ry="3" />
145
- <path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
146
- <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
147
- </>
148
- ),
149
- 'shield-check': (
150
- <>
151
- <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
152
- <polyline points="9 12 11 14 15 10" />
153
- </>
154
- ),
155
- // Milestone path — roadmap / itinerary.
156
- route: (
157
- <>
158
- <circle cx="6" cy="19" r="3" />
159
- <path d="M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15" />
160
- <circle cx="18" cy="5" r="3" />
161
- </>
162
- ),
163
- 'git-branch': (
164
- <>
165
- <line x1="6" y1="3" x2="6" y2="15" />
166
- <circle cx="18" cy="6" r="3" />
167
- <circle cx="6" cy="18" r="3" />
168
- <path d="M18 9a9 9 0 0 1-9 9" />
169
- </>
170
- ),
171
- menu: (
172
- <>
173
- <line x1="3" y1="6" x2="21" y2="6" />
174
- <line x1="3" y1="12" x2="21" y2="12" />
175
- <line x1="3" y1="18" x2="21" y2="18" />
176
- </>
177
- ),
178
- // ---- infrastructure / inventory ----
179
- // Two stacked rack units — hosts, nodes, machines.
180
- server: (
181
- <>
182
- <rect x="2" y="2" width="20" height="8" rx="2" ry="2" />
183
- <rect x="2" y="14" width="20" height="8" rx="2" ry="2" />
184
- <line x1="6" y1="6" x2="6.01" y2="6" />
185
- <line x1="6" y1="18" x2="6.01" y2="18" />
186
- </>
187
- ),
188
- // Disk enclosure — volumes, persistent storage.
189
- 'hard-drive': (
190
- <>
191
- <line x1="22" y1="12" x2="2" y2="12" />
192
- <path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />
193
- <line x1="6" y1="16" x2="6.01" y2="16" />
194
- <line x1="10" y1="16" x2="10.01" y2="16" />
195
- </>
196
- ),
197
- // Isometric crate — a deployable unit of work.
198
- box: (
199
- <>
200
- <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
201
- <polyline points="3.27 6.96 12 12.01 20.73 6.96" />
202
- <line x1="12" y1="22.08" x2="12" y2="12" />
203
- </>
204
- ),
205
- // Picture frame — container images, artefacts.
206
- image: (
207
- <>
208
- <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
209
- <circle cx="8.5" cy="8.5" r="1.5" />
210
- <polyline points="21 15 16 10 5 21" />
211
- </>
212
- ),
213
- // Luggage tag — labels, annotations, metadata.
214
- tag: (
215
- <>
216
- <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z" />
217
- <line x1="7" y1="7" x2="7.01" y2="7" />
218
- </>
219
- ),
220
- // Share of a whole — quotas, budgets, utilisation.
221
- 'pie-chart': (
222
- <>
223
- <path d="M21.21 15.89A10 10 0 1 1 8 2.83" />
224
- <path d="M22 12A10 10 0 0 0 12 2v10z" />
225
- </>
226
- ),
227
- // ---- people / access / admin ----
228
- users: (
229
- <>
230
- <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
231
- <circle cx="9" cy="7" r="4" />
232
- <path d="M23 21v-2a4 4 0 0 0-3-3.87" />
233
- <path d="M16 3.13a4 4 0 0 1 0 7.75" />
234
- </>
235
- ),
236
- 'user-plus': (
237
- <>
238
- <path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
239
- <circle cx="8.5" cy="7" r="4" />
240
- <line x1="20" y1="8" x2="20" y2="14" />
241
- <line x1="23" y1="11" x2="17" y2="11" />
242
- </>
243
- ),
244
- mail: (
245
- <>
246
- <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" />
247
- <polyline points="22,6 12,13 2,6" />
248
- </>
249
- ),
250
- 'file-text': (
251
- <>
252
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
253
- <polyline points="14 2 14 8 20 8" />
254
- <line x1="16" y1="13" x2="8" y2="13" />
255
- <line x1="16" y1="17" x2="8" y2="17" />
256
- <polyline points="10 9 9 9 8 9" />
257
- </>
258
- ),
259
- plug: (
260
- <>
261
- <path d="M12 22v-5" />
262
- <path d="M9 8V2" />
263
- <path d="M15 8V2" />
264
- <path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z" />
265
- </>
266
- ),
267
- pin: (
268
- <>
269
- <line x1="12" y1="17" x2="12" y2="22" />
270
- <path d="M9 10.76V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v6.76a2 2 0 0 0 .55 1.38l1.68 1.78A1 1 0 0 1 16.5 16h-9a1 1 0 0 1-.73-1.68l1.68-1.78A2 2 0 0 0 9 10.76z" />
271
- </>
272
- ),
273
- // ---- input / action ----
274
- // Magnifying glass — search fields, find actions.
275
- search: (
276
- <>
277
- <circle cx="11" cy="11" r="8" />
278
- <line x1="21" y1="21" x2="16.65" y2="16.65" />
279
- </>
280
- ),
281
- // Microphone — voice input, dictation.
282
- mic: (
283
- <>
284
- <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
285
- <path d="M19 10v2a7 7 0 0 1-14 0v-2" />
286
- <line x1="12" y1="19" x2="12" y2="23" />
287
- <line x1="8" y1="23" x2="16" y2="23" />
288
- </>
289
- ),
290
- // ---- color mode ----
291
- sun: (
292
- <>
293
- <circle cx="12" cy="12" r="5" />
294
- <line x1="12" y1="1" x2="12" y2="3" />
295
- <line x1="12" y1="21" x2="12" y2="23" />
296
- <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
297
- <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
298
- <line x1="1" y1="12" x2="3" y2="12" />
299
- <line x1="21" y1="12" x2="23" y2="12" />
300
- <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
301
- <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
302
- </>
303
- ),
304
- moon: <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />,
305
- monitor: (
306
- <>
307
- <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
308
- <line x1="8" y1="21" x2="16" y2="21" />
309
- <line x1="12" y1="17" x2="12" y2="21" />
310
- </>
311
- ),
312
- // Circle, half solid — high-contrast / mode indicator.
313
- contrast: (
314
- <>
315
- <circle cx="12" cy="12" r="10" />
316
- <path d="M12 2a10 10 0 0 1 0 20z" fill="currentColor" stroke="none" />
317
- </>
318
- ),
319
- // ---- device status ----
320
- // Four ascending bars — cellular signal strength.
321
- signal: (
322
- <>
323
- <line x1="4" y1="20" x2="4" y2="16" />
324
- <line x1="9" y1="20" x2="9" y2="12" />
325
- <line x1="14" y1="20" x2="14" y2="8" />
326
- <line x1="19" y1="20" x2="19" y2="4" />
327
- </>
328
- ),
329
- // Horizontal battery outline with a terminal nub — charge level.
330
- battery: (
331
- <>
332
- <rect x="2" y="7" width="17" height="10" rx="2" />
333
- <line x1="22" y1="11" x2="22" y2="13" />
334
- </>
335
- ),
10
+ /** One geometry shape as the SVG element it was drawn as before 5.12. */
11
+ function svgShape(shape: Shape, key: number) {
12
+ const {tag, ...attrs} = shape
13
+ return createElement(tag, {key, ...attrs})
336
14
  }
337
15
 
338
- /**
339
- * Filled icons — solid shape with evenodd cutout for the inner symbol.
340
- * The cutout reveals the background color, so they work on any theme.
341
- * Uses fill="currentColor" only, no stroke.
342
- */
343
- const filledIcons: Partial<Record<IconName, ReactNode>> = {
344
- // Filled circle with "i" cutout (dot + line)
345
- 'info-circle-filled': (
346
- <path
347
- fillRule="evenodd"
348
- d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm-.75 6a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0zM11 11a1 1 0 1 1 2 0v5a1 1 0 1 1-2 0v-5z"
349
- />
350
- ),
351
- // Filled triangle with "!" cutout
352
- 'alert-triangle-filled': (
353
- <path
354
- fillRule="evenodd"
355
- d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0zM11 10a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0v-3zm.25 6a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0z"
356
- />
357
- ),
358
- // Filled circle with checkmark cutout
359
- 'check-circle-filled': (
360
- <path
361
- fillRule="evenodd"
362
- d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm4.707 8.707a1 1 0 0 0-1.414-1.414L11 13.586l-2.293-2.293a1 1 0 0 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l5-5z"
363
- />
364
- ),
365
- // Filled circle with X cutout
366
- 'x-circle-filled': (
367
- <path
368
- fillRule="evenodd"
369
- d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zM9.707 8.293a1 1 0 0 0-1.414 1.414L10.586 12l-2.293 2.293a1 1 0 1 0 1.414 1.414L12 13.414l2.293 2.293a1 1 0 0 0 1.414-1.414L13.414 12l2.293-2.293a1 1 0 0 0-1.414-1.414L12 10.586 9.707 8.293z"
370
- />
371
- ),
372
- // Filled shield with checkmark cutout
373
- 'shield-filled': (
374
- <path
375
- fillRule="evenodd"
376
- d="M12 1L3 5v7c0 6.5 8.5 10.5 9 10.73.5-.23 9-4.23 9-10.73V5l-9-4zm3.707 8.707a1 1 0 0 0-1.414-1.414L11 11.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4z"
377
- />
378
- ),
379
- // Filled lock body with stroke shackle
380
- 'lock-filled': (
381
- <>
382
- <path
383
- d="M7 11V7a5 5 0 0 1 10 0v4"
384
- fill="none"
385
- stroke="currentColor"
386
- strokeWidth="2"
387
- strokeLinecap="round"
388
- />
389
- <rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
390
- </>
391
- ),
392
- }
393
-
394
- interface IconProps {
395
- name: IconName
396
- /** Token from the icon size scale: sm 16, md 18, lg 24, xl 36, xxl 48. */
397
- size?: IconSize
398
- }
399
-
400
- export function Icon({name, size: sizeToken = 'lg'}: IconProps) {
16
+ export function Icon({name, size: sizeToken = 'lg', color}: IconProps) {
401
17
  const size = ICON_SIZES[sizeToken]
402
- const filled = filledIcons[name]
403
- if (filled) {
18
+ const glyph = GLYPHS[name]
19
+ const shapes = glyph.shapes.map(svgShape)
20
+ const style = color ? {color: colors[color]} : undefined
21
+ if (glyph.style === 'fill') {
404
22
  return (
405
- <svg viewBox="0 0 24 24" fill="currentColor" width={size} height={size}>
406
- {filled}
23
+ <svg viewBox="0 0 24 24" fill="currentColor" width={size} height={size} style={style}>
24
+ {shapes}
407
25
  </svg>
408
26
  )
409
27
  }
@@ -418,8 +36,9 @@ export function Icon({name, size: sizeToken = 'lg'}: IconProps) {
418
36
  strokeLinejoin="round"
419
37
  width={size}
420
38
  height={size}
39
+ style={style}
421
40
  >
422
- {strokeIcons[name]}
41
+ {shapes}
423
42
  </svg>
424
43
  )
425
44
  }