@zeyos/zx 4.4.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +283 -0
  2. package/README.md +42 -10
  3. package/dist/types/components/activity-list/activity-list.d.ts +22 -0
  4. package/dist/types/components/app-sidebar/app-sidebar.d.ts +5 -3
  5. package/dist/types/components/avatar/avatar.d.ts +46 -7
  6. package/dist/types/components/badge/badge.d.ts +21 -1
  7. package/dist/types/components/button/button.d.ts +15 -0
  8. package/dist/types/components/chart/chart.d.ts +10 -0
  9. package/dist/types/components/checklist/checklist.d.ts +9 -0
  10. package/dist/types/components/code-editor/code-editor.d.ts +6 -17
  11. package/dist/types/components/datebox/date-range-box.d.ts +5 -1
  12. package/dist/types/components/datebox/datebox.d.ts +7 -2
  13. package/dist/types/components/dialog/dialog.d.ts +46 -6
  14. package/dist/types/components/dropdown/dropdown.d.ts +2 -2
  15. package/dist/types/components/entity-ref/entity-ref.d.ts +2 -2
  16. package/dist/types/components/field/field.d.ts +24 -2
  17. package/dist/types/components/fieldset/fieldset.d.ts +19 -1
  18. package/dist/types/components/file-item/file-item.d.ts +34 -6
  19. package/dist/types/components/form/form.d.ts +12 -1
  20. package/dist/types/components/kanban-view/kanban-card.d.ts +8 -0
  21. package/dist/types/components/launcher/launcher.d.ts +260 -15
  22. package/dist/types/components/list-toolbar/list-toolbar.d.ts +1 -1
  23. package/dist/types/components/menu-button/menu-button.d.ts +33 -5
  24. package/dist/types/components/message/message.d.ts +119 -17
  25. package/dist/types/components/modal/modal.d.ts +13 -2
  26. package/dist/types/components/select/color.d.ts +12 -0
  27. package/dist/types/components/select/glyphs.d.ts +124 -0
  28. package/dist/types/components/select/select.d.ts +11 -3
  29. package/dist/types/components/stat-tile/stat-tile.d.ts +16 -5
  30. package/dist/types/components/tabbox/tabbox.d.ts +9 -0
  31. package/dist/types/components/table/table.d.ts +46 -1
  32. package/dist/types/components/tag-picker/tag-picker.d.ts +21 -4
  33. package/dist/types/components/tree/tree.d.ts +13 -0
  34. package/dist/types/core/breakpoint.d.ts +1 -1
  35. package/dist/types/core/icons.d.ts +23 -25
  36. package/dist/types/core/motion.d.ts +59 -0
  37. package/dist/types/core/overlay-host.d.ts +15 -1
  38. package/dist/types/index.d.ts +5 -3
  39. package/dist/types/zeyos/connect.d.ts +6 -0
  40. package/dist/types/zeyos/form.d.ts +50 -9
  41. package/dist/types/zeyos/index.d.ts +1 -1
  42. package/dist/types/zeyos/query.d.ts +79 -0
  43. package/dist/types/zeyos/schema.d.ts +24 -1
  44. package/dist/types/zeyos/table.d.ts +100 -14
  45. package/dist/types/zeyos/view.d.ts +10 -0
  46. package/dist/zx-zeyos.esm.js +1621 -443
  47. package/dist/zx-zeyos.esm.min.js +53 -5
  48. package/dist/zx.css +1411 -660
  49. package/dist/zx.esm.js +1976 -703
  50. package/dist/zx.esm.min.js +56 -8
  51. package/dist/zx.global.js +1978 -705
  52. package/dist/zx.global.min.js +56 -8
  53. package/dist/zx.min.css +1 -1
  54. package/docs/api.json +219 -34
  55. package/docs/llms.md +472 -110
  56. package/docs/llms.txt +3 -3
  57. package/package.json +1 -1
  58. package/src/components/account-menu/account-menu.css +35 -10
  59. package/src/components/activity-item/activity-item.css +1 -1
  60. package/src/components/activity-item/activity-item.js +3 -0
  61. package/src/components/activity-list/activity-list.css +38 -3
  62. package/src/components/activity-list/activity-list.js +34 -0
  63. package/src/components/app-icon/app-icon.css +1 -1
  64. package/src/components/app-rail/app-rail.css +40 -79
  65. package/src/components/app-sidebar/app-sidebar.css +109 -174
  66. package/src/components/app-sidebar/app-sidebar.js +21 -6
  67. package/src/components/aurora/aurora.css +5 -3
  68. package/src/components/avatar/avatar.css +32 -7
  69. package/src/components/avatar/avatar.js +72 -8
  70. package/src/components/badge/badge.css +54 -2
  71. package/src/components/badge/badge.js +29 -2
  72. package/src/components/button/button.css +67 -9
  73. package/src/components/button/button.js +38 -0
  74. package/src/components/calendar/calendar.css +46 -46
  75. package/src/components/card/card.css +2 -2
  76. package/src/components/card-view/card-view.css +9 -7
  77. package/src/components/chart/chart.css +4 -1
  78. package/src/components/chart/chart.js +12 -0
  79. package/src/components/check-button/check-button.css +10 -2
  80. package/src/components/checklist/checklist.css +9 -2
  81. package/src/components/checklist/checklist.js +11 -5
  82. package/src/components/checklist/field-adapter.js +3 -1
  83. package/src/components/code-editor/code-editor.css +6 -5
  84. package/src/components/code-editor/code-editor.js +19 -1
  85. package/src/components/context-menu/context-menu.css +9 -4
  86. package/src/components/copy/copy-button.css +6 -0
  87. package/src/components/copy/copy-input.css +8 -3
  88. package/src/components/data-filter/data-filter.css +5 -4
  89. package/src/components/date-picker/date-picker.css +6 -6
  90. package/src/components/date-picker/date-range-picker.css +3 -3
  91. package/src/components/date-picker/time-picker.css +1 -1
  92. package/src/components/datebox/date-range-box.css +79 -2
  93. package/src/components/datebox/date-range-box.js +13 -2
  94. package/src/components/datebox/datebox.css +79 -2
  95. package/src/components/datebox/datebox.js +13 -2
  96. package/src/components/dialog/dialog.css +26 -0
  97. package/src/components/dialog/dialog.js +99 -17
  98. package/src/components/dropdown/dropdown.css +1 -1
  99. package/src/components/dropdown/dropdown.js +5 -3
  100. package/src/components/empty-state/empty-state.css +2 -2
  101. package/src/components/entity-ref/entity-ref.css +1 -1
  102. package/src/components/entity-ref/entity-ref.js +1 -1
  103. package/src/components/field/field.css +28 -9
  104. package/src/components/field/field.js +68 -26
  105. package/src/components/field-upload/field-upload.css +1 -1
  106. package/src/components/fieldset/fieldset.css +5 -3
  107. package/src/components/fieldset/fieldset.js +28 -5
  108. package/src/components/file-item/file-item.js +144 -10
  109. package/src/components/filter/filter.js +7 -3
  110. package/src/components/filter-panel/filter-panel.css +1 -1
  111. package/src/components/finder/finder.css +15 -13
  112. package/src/components/form/form.css +5 -4
  113. package/src/components/form/form.js +11 -2
  114. package/src/components/grid/grid.css +1 -1
  115. package/src/components/groupbox/groupbox.css +1 -1
  116. package/src/components/kanban-view/kanban-card.js +11 -3
  117. package/src/components/kanban-view/kanban-view.css +39 -15
  118. package/src/components/kanban-view/kanban-view.js +4 -4
  119. package/src/components/launcher/launcher.css +107 -25
  120. package/src/components/launcher/launcher.js +503 -41
  121. package/src/components/list-toolbar/list-toolbar.css +13 -8
  122. package/src/components/list-toolbar/list-toolbar.js +1 -1
  123. package/src/components/master-panel/master-panel.css +2 -0
  124. package/src/components/menu-button/menu-button.css +9 -4
  125. package/src/components/menu-button/menu-button.js +65 -9
  126. package/src/components/message/message.css +33 -3
  127. package/src/components/message/message.js +217 -15
  128. package/src/components/modal/modal.js +18 -3
  129. package/src/components/navigation-bar/navigation-bar.css +18 -9
  130. package/src/components/number-field/field-adapter.js +1 -0
  131. package/src/components/number-field/number-field.css +70 -0
  132. package/src/components/number-field/number-field.js +2 -0
  133. package/src/components/pagination/pagination.css +8 -6
  134. package/src/components/panel/panel.css +1 -1
  135. package/src/components/rating/rating.css +7 -0
  136. package/src/components/select/color.js +22 -0
  137. package/src/components/select/field-adapter.js +2 -0
  138. package/src/components/select/glyphs.js +165 -0
  139. package/src/components/select/select.css +138 -45
  140. package/src/components/select/select.js +83 -47
  141. package/src/components/sheet/sheet.css +11 -8
  142. package/src/components/slider/slider.css +16 -2
  143. package/src/components/slider/slider.js +1 -1
  144. package/src/components/sort-control/sort-control.css +4 -1
  145. package/src/components/stat-tile/stat-tile.css +41 -46
  146. package/src/components/stat-tile/stat-tile.js +17 -6
  147. package/src/components/tabbox/tabbox.css +32 -27
  148. package/src/components/tabbox/tabbox.js +5 -1
  149. package/src/components/table/table.css +104 -29
  150. package/src/components/table/table.js +90 -16
  151. package/src/components/tag-picker/tag-picker.css +83 -5
  152. package/src/components/tag-picker/tag-picker.js +25 -8
  153. package/src/components/timebox/timebox.css +22 -2
  154. package/src/components/toggle/toggle.css +12 -1
  155. package/src/components/toolbar/toolbar.js +2 -2
  156. package/src/components/tooltip/tooltip.css +4 -0
  157. package/src/components/tooltip/tooltip.js +10 -3
  158. package/src/components/tree/tree.css +25 -16
  159. package/src/components/tree/tree.js +31 -0
  160. package/src/components/value-list/value-list.css +3 -3
  161. package/src/components/view/record-view.js +1 -1
  162. package/src/core/breakpoint.js +1 -1
  163. package/src/core/icons.js +193 -60
  164. package/src/core/motion.js +147 -0
  165. package/src/core/overlay-host.js +21 -2
  166. package/src/index.js +5 -3
  167. package/src/internal/app-rail.js +1 -2
  168. package/src/zeyos/connect.js +6 -2
  169. package/src/zeyos/form.js +67 -27
  170. package/src/zeyos/index.js +1 -1
  171. package/src/zeyos/query.js +153 -0
  172. package/src/zeyos/schema.js +144 -27
  173. package/src/zeyos/table.js +68 -5
  174. package/src/zeyos/view.js +6 -0
  175. package/styles/base.css +56 -0
  176. package/styles/icons.css +11 -1
  177. package/styles/tokens/dark.css +113 -37
  178. package/styles/tokens/global.css +121 -27
  179. package/styles/tokens/semantic.css +100 -31
  180. package/styles/tokens/themes.css +7 -6
  181. package/styles/zx.css +0 -1
  182. package/styles/tokens/density.css +0 -9
package/src/core/icons.js CHANGED
@@ -2,7 +2,8 @@
2
2
  /**
3
3
  * The icon layer. Two renderers sit behind one `icon()` call:
4
4
  *
5
- * - **built-in** (default) — the inline SVG glyphs below, no network, no stylesheet, no font.
5
+ * - **built-in** (default) — the inline SVG outline glyphs below (Lucide), no network, no
6
+ * stylesheet, no font. Applications can add their own, filled or outlined, with `registerIcons()`.
6
7
  * - **Font Awesome** — `<i>` elements carrying Font Awesome classes, after an application opts in
7
8
  * with `useFontAwesome()` or `loadFontAwesome(kit)`. Zx never loads a kit by itself.
8
9
  *
@@ -28,52 +29,139 @@ const SVG_NS = 'http://www.w3.org/2000/svg';
28
29
  */
29
30
 
30
31
  /**
31
- * Icon glyphs from Font Awesome Free 6 (solid, plus `square` from regular), fontawesome.com,
32
- * licensed CC BY 4.0 (https://fontawesome.com/license/free). Path data is embedded unmodified so
33
- * the library carries no webfont, stylesheet, or package dependency. Each entry is
34
- * `[viewBox, path]`; Font Awesome glyphs are filled (not stroked) and use per-glyph 512-unit view
35
- * boxes — outlines such as `square` are a filled path with a counter-wound hole.
36
- * Extend the set with `registerIcons()`; read every available name with `iconNames()`.
37
- * @type {Readonly<Record<string, [string, string]>>}
32
+ * How a glyph's path is painted. `'fill'` fills the shape — the form Font Awesome and other solid
33
+ * sets ship in. `'stroke'` draws the outline with the icon pen: `currentColor`, round caps and
34
+ * joins, and a width of 1.75 units in a 24-unit view box — the form the bundled set uses.
35
+ * @typedef {'fill'|'stroke'} IconPaint
36
+ */
37
+
38
+ /**
39
+ * One inline SVG glyph: `[viewBox, path]` for a filled shape, or `[viewBox, path, 'stroke']` for
40
+ * an outline. A path may hold any number of subpaths; the two-element form is the original format
41
+ * and always renders filled.
42
+ * @typedef {[string, string] | [string, string, IconPaint]} IconGlyph
43
+ */
44
+
45
+ /** The view box every bundled glyph is drawn in: Lucide's 24-unit square. */
46
+ const VIEW_BOX = '0 0 24 24';
47
+
48
+ /**
49
+ * Stroke width of an outline glyph, in units of a 24-unit view box. At the default 16px it draws
50
+ * a line of about 1.2px — the stem weight of 13–14px interface text, so an icon sits beside a
51
+ * label without outweighing it.
52
+ */
53
+ const STROKE_WIDTH = 1.75;
54
+
55
+ /**
56
+ * Thinnest line an outline glyph is drawn with, in CSS pixels. Below 16px the proportional width
57
+ * would fall under a pixel and wash out (a 12px chevron, an 8px tick), so small glyphs keep one
58
+ * full pixel instead.
59
+ */
60
+ const MIN_STROKE_PX = 1;
61
+
62
+ /**
63
+ * Wraps bundled path data as an outline glyph in the shared view box.
64
+ * @param {string} path Path data.
65
+ * @returns {IconGlyph}
66
+ */
67
+ const outline = (path) => [VIEW_BOX, path, 'stroke'];
68
+
69
+ /*
70
+ * @license Lucide 1.53.0 (ISC), including icons derived from Feather (MIT) — notices below.
71
+ *
72
+ * The bundled glyphs are Lucide 1.53.0 (https://lucide.dev), outline icons drawn on a 24-unit grid.
73
+ * Each Lucide icon is stored as one path: its circles, rectangles, lines, and polylines are
74
+ * rewritten as equivalent path data, which renders identically because every part shares the same
75
+ * stroke. Where a Zx name differs from the Lucide one, the Lucide name is noted beside the glyph.
76
+ *
77
+ * ISC License
78
+ *
79
+ * Copyright (c) 2026 Lucide Icons and Contributors
80
+ *
81
+ * Permission to use, copy, modify, and/or distribute this software for any
82
+ * purpose with or without fee is hereby granted, provided that the above
83
+ * copyright notice and this permission notice appear in all copies.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
86
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
87
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
88
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
89
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
90
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
91
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
92
+ *
93
+ * Lucide icons derived from the Feather project (Lucide's LICENSE lists them) are also covered by:
94
+ *
95
+ * The MIT License (MIT)
96
+ *
97
+ * Copyright (c) 2013-present Cole Bemis
98
+ *
99
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
100
+ * of this software and associated documentation files (the "Software"), to deal
101
+ * in the Software without restriction, including without limitation the rights
102
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
103
+ * copies of the Software, and to permit persons to whom the Software is
104
+ * furnished to do so, subject to the following conditions:
105
+ *
106
+ * The above copyright notice and this permission notice shall be included in all
107
+ * copies or substantial portions of the Software.
108
+ *
109
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
110
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
111
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
112
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
113
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
114
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
115
+ * SOFTWARE.
116
+ */
117
+
118
+ /**
119
+ * The bundled glyph set: outline icons from Lucide (ISC; see the notice above), embedded as path
120
+ * data so the library carries no webfont, stylesheet, or package dependency. Every entry is
121
+ * `[viewBox, path, 'stroke']` in a 24-unit view box. Extend the set with `registerIcons()`; read
122
+ * every available name with `iconNames()`.
123
+ * @type {Readonly<Record<string, IconGlyph>>}
38
124
  */
39
125
  export const icons = Object.freeze({
40
- 'arrow-up-wide-short': ['0 0 576 512', 'M151.6 42.4C145.5 35.8 137 32 128 32s-17.5 3.8-23.6 10.4l-88 96c-11.9 13-11.1 33.3 2 45.2s33.3 11.1 45.2-2L96 146.3 96 448c0 17.7 14.3 32 32 32s32-14.3 32-32l0-301.7 32.4 35.4c11.9 13 32.2 13.9 45.2 2s13.9-32.2 2-45.2l-88-96zM320 480l32 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-32 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128l160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-160 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm0-128l224 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L320 32c-17.7 0-32 14.3-32 32s14.3 32 32 32z'],
41
- 'arrow-down-wide-short': ['0 0 576 512', 'M151.6 469.6C145.5 476.2 137 480 128 480s-17.5-3.8-23.6-10.4l-88-96c-11.9-13-11.1-33.3 2-45.2s33.3-11.1 45.2 2L96 365.7 96 64c0-17.7 14.3-32 32-32s32 14.3 32 32l0 301.7 32.4-35.4c11.9-13 32.2-13.9 45.2-2s13.9 32.2 2 45.2l-88 96zM320 480c-17.7 0-32-14.3-32-32s14.3-32 32-32l32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0zm0-128c-17.7 0-32-14.3-32-32s14.3-32 32-32l96 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-96 0zm0-128c-17.7 0-32-14.3-32-32s14.3-32 32-32l160 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-160 0zm0-128c-17.7 0-32-14.3-32-32s14.3-32 32-32l224 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L320 96z'],
42
- 'chevron-down': ['0 0 512 512', 'M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z'],
43
- 'chevron-up': ['0 0 512 512', 'M233.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L256 173.3 86.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z'],
44
- 'chevron-left': ['0 0 320 512', 'M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z'],
45
- 'chevron-right': ['0 0 320 512', 'M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z'],
46
- check: ['0 0 448 512', 'M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z'],
47
- x: ['0 0 384 512', 'M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z'],
48
- plus: ['0 0 448 512', 'M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32V224H48c-17.7 0-32 14.3-32 32s14.3 32 32 32H192V432c0 17.7 14.3 32 32 32s32-14.3 32-32V288H400c17.7 0 32-14.3 32-32s-14.3-32-32-32H256V80z'],
49
- minus: ['0 0 448 512', 'M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z'],
50
- search: ['0 0 512 512', 'M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z'],
51
- calendar: ['0 0 448 512', 'M128 0c17.7 0 32 14.3 32 32V64H288V32c0-17.7 14.3-32 32-32s32 14.3 32 32V64h48c26.5 0 48 21.5 48 48v48H0V112C0 85.5 21.5 64 48 64H96V32c0-17.7 14.3-32 32-32zM0 192H448V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V192z'],
52
- clock: ['0 0 512 512', 'M256 0a256 256 0 1 1 0 512A256 256 0 1 1 256 0zM232 120V256c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2V120c0-13.3-10.7-24-24-24s-24 10.7-24 24z'],
53
- trash: ['0 0 448 512', 'M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z'],
54
- gear: ['0 0 512 512', 'M481.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z'],
55
- eye: ['0 0 576 512', 'M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1-288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z'],
56
- lock: ['0 0 448 512', 'M144 144v48H304V144c0-44.2-35.8-80-80-80s-80 35.8-80 80zM80 192V144C80 64.5 144.5 0 224 0s144 64.5 144 144v48h16c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V256c0-35.3 28.7-64 64-64H80z'],
57
- reload: ['0 0 512 512', 'M386.3 160H336c-17.7 0-32 14.3-32 32s14.3 32 32 32H464c17.7 0 32-14.3 32-32V64c0-17.7-14.3-32-32-32s-32 14.3-32 32v51.2L414.4 97.6c-87.5-87.5-229.3-87.5-316.8 0s-87.5 229.3 0 316.8s229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3s163.8-62.5 226.3 0L386.3 160z'],
58
- list: ['0 0 512 512', 'M40 48C26.7 48 16 58.7 16 72v48c0 13.3 10.7 24 24 24H88c13.3 0 24-10.7 24-24V72c0-13.3-10.7-24-24-24H40zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zM16 232v48c0 13.3 10.7 24 24 24H88c13.3 0 24-10.7 24-24V232c0-13.3-10.7-24-24-24H40c-13.3 0-24 10.7-24 24zM40 368c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24H88c13.3 0 24-10.7 24-24V392c0-13.3-10.7-24-24-24H40z'],
59
- filter: ['0 0 512 512', 'M3.9 54.9C10.5 40.9 24.5 32 40 32H472c15.5 0 29.5 8.9 36.1 22.9s4.6 30.5-5.2 42.5L320 320.9V448c0 12.1-6.8 23.2-17.7 28.6s-23.8 4.3-33.5-3l-64-48c-8.1-6-12.8-15.5-12.8-25.6V320.9L9 97.3C-.7 85.4-2.8 68.8 3.9 54.9z'],
60
- dots: ['0 0 448 512', 'M8 256a56 56 0 1 1 112 0A56 56 0 1 1 8 256zm160 0a56 56 0 1 1 112 0 56 56 0 1 1-112 0zm216-56a56 56 0 1 1 0 112 56 56 0 1 1 0-112z'],
61
- info: ['0 0 512 512', 'M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z'],
62
- warning: ['0 0 512 512', 'M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480H40c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24V296c0 13.3 10.7 24 24 24s24-10.7 24-24V184c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0-64 0 32 32 0 1 0 64 0z'],
63
- error: ['0 0 512 512', 'M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24V264c0 13.3-10.7 24-24 24s-24-10.7-24-24V152c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1-64 0z'],
64
- success: ['0 0 512 512', 'M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z'],
65
- upload: ['0 0 512 512', 'M288 109.3V352c0 17.7-14.3 32-32 32s-32-14.3-32-32V109.3l-73.4 73.4c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l128-128c12.5-12.5 32.8-12.5 45.3 0l128 128c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L288 109.3zM64 352H192c0 35.3 28.7 64 64 64s64-28.7 64-64H448c35.3 0 64 28.7 64 64v32c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V416c0-35.3 28.7-64 64-64z'],
66
- drag: ['0 0 320 512', 'M40 352l48 0c22.1 0 40 17.9 40 40l0 48c0 22.1-17.9 40-40 40l-48 0c-22.1 0-40-17.9-40-40l0-48c0-22.1 17.9-40 40-40zm192 0l48 0c22.1 0 40 17.9 40 40l0 48c0 22.1-17.9 40-40 40l-48 0c-22.1 0-40-17.9-40-40l0-48c0-22.1 17.9-40 40-40zM40 176l48 0c22.1 0 40 17.9 40 40l0 48c0 22.1-17.9 40-40 40l-48 0c-22.1 0-40-17.9-40-40l0-48c0-22.1 17.9-40 40-40zm192 0l48 0c22.1 0 40 17.9 40 40l0 48c0 22.1-17.9 40-40 40l-48 0c-22.1 0-40-17.9-40-40l0-48c0-22.1 17.9-40 40-40zM40 0L88 0c22.1 0 40 17.9 40 40l0 48c0 22.1-17.9 40-40 40L40 128C17.9 128 0 110.1 0 88L0 40C0 17.9 17.9 0 40 0zM232 0l48 0c22.1 0 40 17.9 40 40l0 48c0 22.1-17.9 40-40 40l-48 0c-22.1 0-40-17.9-40-40l0-48c0-22.1 17.9-40 40-40z'],
67
- star: ['0 0 576 512', 'M287.9 0c9.2 0 17.6 5.2 21.6 13.5l68.6 141.3 153.2 22.6c9 1.3 16.5 7.6 19.3 16.3s.5 18.1-5.9 24.5L433.6 328.4l26.2 155.6c1.5 9-2.2 18.1-9.7 23.5s-17.3 6-25.3 1.7l-137-73.2L151 509.1c-8.1 4.3-17.9 3.7-25.3-1.7s-11.2-14.5-9.7-23.5l26.2-155.6L31.1 218.2c-6.5-6.4-8.7-15.9-5.9-24.5s10.3-14.9 19.3-16.3l153.2-22.6L266.3 13.5C270.4 5.2 278.7 0 287.9 0z'],
68
- heart: ['0 0 512 512', 'M47.6 300.4L228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6 0 115.2 0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z'],
69
- tag: ['0 0 448 512', 'M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z'],
70
- folder: ['0 0 512 512', 'M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H298.5c-17 0-33.3-6.7-45.3-18.7L226.7 50.7c-12-12-28.3-18.7-45.3-18.7H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z'],
71
- 'folder-open': ['0 0 576 512', 'M88.7 223.8L0 375.8V96C0 60.7 28.7 32 64 32H181.5c17 0 33.3 6.7 45.3 18.7l26.5 26.5c12 12 28.3 18.7 45.3 18.7H416c35.3 0 64 28.7 64 64v32H144c-22.8 0-43.8 12.1-55.3 31.8zm27.6 16.1C122.1 230 132.6 224 144 224H544c11.5 0 22 6.1 27.7 16.1s5.7 22.2-.1 32.1l-112 192C453.9 474 443.4 480 432 480H32c-11.5 0-22-6.1-27.7-16.1s-5.7-22.2 .1-32.1l112-192z'],
72
- file: ['0 0 384 512', 'M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64zm384 64H256V0L384 128z'],
73
- copy: ['0 0 448 512', 'M208 0L332.1 0c12.7 0 24.9 5.1 33.9 14.1l67.9 67.9c9 9 14.1 21.2 14.1 33.9L448 336c0 26.5-21.5 48-48 48l-192 0c-26.5 0-48-21.5-48-48l0-288c0-26.5 21.5-48 48-48zM48 128l80 0 0 64-64 0 0 256 192 0 0-32 64 0 0 48c0 26.5-21.5 48-48 48L48 512c-26.5 0-48-21.5-48-48L0 176c0-26.5 21.5-48 48-48z'],
74
- square: ['0 0 448 512', 'M384 80c8.8 0 16 7.2 16 16V416c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16V96c0-8.8 7.2-16 16-16H384zM64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64z'],
75
- code: ['0 0 640 512', 'M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z'],
76
- book: ['0 0 448 512', 'M96 0C43 0 0 43 0 96V416c0 53 43 96 96 96H384h32c17.7 0 32-14.3 32-32s-14.3-32-32-32V384c17.7 0 32-14.3 32-32V32c0-17.7-14.3-32-32-32H384 96zm0 384H352v64H96c-17.7 0-32-14.3-32-32s14.3-32 32-32zm32-240c0-8.8 7.2-16 16-16H336c8.8 0 16 7.2 16 16s-7.2 16-16 16H144c-8.8 0-16-7.2-16-16zm16 48H336c8.8 0 16 7.2 16 16s-7.2 16-16 16H144c-8.8 0-16-7.2-16-16s7.2-16 16-16z']
126
+ // <lucide-glyphs>
127
+ 'arrow-up-wide-short': outline('M3 8l4-4 4 4M7 4v16M11 12h10M11 16h7M11 20h4'), // arrow-up-wide-narrow
128
+ 'arrow-down-wide-short': outline('M3 16l4 4 4-4M7 20V4M11 4h10M11 8h7M11 12h4'), // arrow-down-wide-narrow
129
+ 'chevron-down': outline('M6 9l6 6 6-6'),
130
+ 'chevron-up': outline('M18 15l-6-6-6 6'),
131
+ 'chevron-left': outline('M15 18l-6-6 6-6'),
132
+ 'chevron-right': outline('M9 18l6-6-6-6'),
133
+ check: outline('M20 6 9 17l-5-5'),
134
+ x: outline('M18 6 6 18M6 6l12 12'),
135
+ plus: outline('M5 12h14M12 5v14'),
136
+ minus: outline('M5 12h14'),
137
+ search: outline('M21 21l-4.34-4.34M3 11a8 8 0 1 0 16 0a8 8 0 1 0-16 0z'),
138
+ calendar: outline('M8 2v3M16 2v3M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-14a2 2 0 0 1-2-2v-14a2 2 0 0 1 2-2zM3 9h18'),
139
+ clock: outline('M2 12a10 10 0 1 0 20 0a10 10 0 1 0-20 0zM12 6v6l4 2'),
140
+ trash: outline('M10 11v6M14 11v6M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2'),
141
+ gear: outline('M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915M9 12a3 3 0 1 0 6 0a3 3 0 1 0-6 0z'), // settings
142
+ eye: outline('M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0M9 12a3 3 0 1 0 6 0a3 3 0 1 0-6 0z'),
143
+ lock: outline('M5 11h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-14a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2zM7 11V7a5 5 0 0 1 10 0v4'),
144
+ reload: outline('M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8M21 3v5h-5'), // rotate-cw
145
+ list: outline('M3 5h.01M3 12h.01M3 19h.01M8 5h13M8 12h13M8 19h13'),
146
+ filter: outline('M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z'), // funnel
147
+ dots: outline('M11 12a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM18 12a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM4 12a1 1 0 1 0 2 0a1 1 0 1 0-2 0z'), // ellipsis
148
+ info: outline('M2 12a10 10 0 1 0 20 0a10 10 0 1 0-20 0zM12 16v-4M12 8h.01'),
149
+ warning: outline('M21.73 18l-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4M12 17h.01'), // triangle-alert
150
+ error: outline('M2 12a10 10 0 1 0 20 0a10 10 0 1 0-20 0zM12 8V12M12 16H12.01'), // circle-alert
151
+ success: outline('M2 12a10 10 0 1 0 20 0a10 10 0 1 0-20 0zM16 9l-5.5 5.5L8 12'), // circle-check
152
+ upload: outline('M12 3v12M17 8l-5-5-5 5M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'),
153
+ drag: outline('M8 12a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM8 5a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM8 19a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM14 12a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM14 5a1 1 0 1 0 2 0a1 1 0 1 0-2 0zM14 19a1 1 0 1 0 2 0a1 1 0 1 0-2 0z'), // grip-vertical
154
+ star: outline('M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z'),
155
+ heart: outline('M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5'),
156
+ tag: outline('M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42zM7 7.5a.5 .5 0 1 0 1 0a.5 .5 0 1 0-1 0z'),
157
+ folder: outline('M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z'),
158
+ 'folder-open': outline('M6 14l1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2'),
159
+ file: outline('M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2zM14 2v5a1 1 0 0 0 1 1h5'),
160
+ copy: outline('M10 8h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-10a2 2 0 0 1-2-2v-10a2 2 0 0 1 2-2zM4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'),
161
+ square: outline('M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-14a2 2 0 0 1-2-2v-14a2 2 0 0 1 2-2z'),
162
+ code: outline('M18 16l4-4-4-4M6 8l-4 4 4 4M14.5 4l-5 16'), // code-xml
163
+ book: outline('M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20')
164
+ // </lucide-glyphs>
77
165
  });
78
166
 
79
167
  /** Legacy gx Factory icon names mapped to their Zx equivalents. */
@@ -86,7 +174,7 @@ const aliases = Object.freeze({
86
174
  fields: 'list'
87
175
  });
88
176
 
89
- /** @type {Record<string, [string, string]>} Glyphs added at runtime by `registerIcons`. */
177
+ /** @type {Record<string, IconGlyph>} Glyphs added at runtime by `registerIcons`. */
90
178
  const extraGlyphs = Object.create(null);
91
179
 
92
180
  /**
@@ -163,17 +251,31 @@ export async function loadFontAwesome(options) {
163
251
  }
164
252
 
165
253
  /**
166
- * Adds inline SVG glyphs to the built-in set, or replaces existing ones. Entries use the same
167
- * `[viewBox, path]` shape as `icons`.
168
- * @param {Record<string, [string, string]>} glyphs Glyphs keyed by icon name.
254
+ * Adds inline SVG glyphs to the built-in set, or replaces existing ones.
255
+ *
256
+ * An entry is `[viewBox, path]` — a filled shape, the format Font Awesome path data comes in, and
257
+ * how it always rendered — or `[viewBox, path, 'stroke']` — an outline drawn with the same pen as
258
+ * the bundled set: `currentColor`, round caps and joins, and a stroke scaled to the view box, so a
259
+ * glyph from a 24-unit outline set such as Lucide renders exactly like a bundled one.
260
+ *
261
+ * registerIcons({ rocket: ['0 0 512 512', 'M…'] }); // filled
262
+ * registerIcons({ anchor: ['0 0 24 24', 'M12 6v16…', 'stroke'] }); // outline
263
+ * @param {Record<string, IconGlyph>} glyphs Glyphs keyed by icon name.
169
264
  * @returns {void}
265
+ * @throws {TypeError} When an entry is neither a `[viewBox, path]` pair nor a
266
+ * `[viewBox, path, 'fill'|'stroke']` triple.
170
267
  */
171
268
  export function registerIcons(glyphs) {
172
269
  for (const [name, entry] of Object.entries(glyphs)) {
173
- if (!Array.isArray(entry) || entry.length !== 2) {
174
- throw new TypeError(`Icon "${name}" must be a [viewBox, path] pair`);
270
+ if (!Array.isArray(entry) || (entry.length !== 2 && entry.length !== 3)
271
+ || (entry.length === 3 && entry[2] !== 'fill' && entry[2] !== 'stroke')) {
272
+ throw new TypeError(
273
+ `Icon "${name}" must be a [viewBox, path] pair or a [viewBox, path, 'stroke'] triple`
274
+ );
175
275
  }
176
- extraGlyphs[name] = [String(entry[0]), String(entry[1])];
276
+ extraGlyphs[name] = entry[2] === 'stroke'
277
+ ? [String(entry[0]), String(entry[1]), 'stroke']
278
+ : [String(entry[0]), String(entry[1])];
177
279
  }
178
280
  }
179
281
 
@@ -244,8 +346,8 @@ function builtinIcon(name, options) {
244
346
  warnMissingIcon(name);
245
347
  return missingIcon(name, options);
246
348
  }
247
- const [viewBox, pathData] = entry;
248
- const svg = iconSvg(viewBox, options);
349
+ const [viewBox, pathData, paint = 'fill'] = entry;
350
+ const svg = iconSvg(viewBox, paint, options);
249
351
  const path = document.createElementNS(SVG_NS, 'path');
250
352
  path.setAttribute('d', pathData);
251
353
  svg.append(path);
@@ -254,26 +356,57 @@ function builtinIcon(name, options) {
254
356
 
255
357
  /**
256
358
  * Builds the `<svg>` root every inline glyph shares, so the placeholder is the same element in
257
- * the same box as the icon it stands in for.
359
+ * the same box as the icon it stands in for. The paint attributes sit on the root and the path
360
+ * inherits them, so component CSS can restyle a glyph with `fill`, `stroke`, or `color` on the
361
+ * `.zx-icon` element alone — `fill: currentColor` turns an outline into its solid form, for a set
362
+ * star or a liked heart.
258
363
  * @param {string} viewBox The glyph's view box.
364
+ * @param {IconPaint} paint Whether the glyph is filled or stroked.
259
365
  * @param {IconOptions} options Display and accessibility options.
260
366
  * @returns {SVGSVGElement}
261
367
  */
262
- function iconSvg(viewBox, options) {
368
+ function iconSvg(viewBox, paint, options) {
263
369
  const { size = 16 } = options;
264
370
  const svg = document.createElementNS(SVG_NS, 'svg');
265
371
  svg.setAttribute('class', classList('zx-icon', options.class));
266
372
  svg.setAttribute('viewBox', viewBox);
267
373
  svg.setAttribute('width', String(size));
268
374
  svg.setAttribute('height', String(size));
269
- svg.setAttribute('fill', 'currentColor');
375
+ if (paint === 'stroke') {
376
+ svg.setAttribute('fill', 'none');
377
+ svg.setAttribute('stroke', 'currentColor');
378
+ svg.setAttribute('stroke-width', strokeWidth(viewBox, size));
379
+ svg.setAttribute('stroke-linecap', 'round');
380
+ svg.setAttribute('stroke-linejoin', 'round');
381
+ } else {
382
+ svg.setAttribute('fill', 'currentColor');
383
+ }
270
384
  svg.setAttribute('focusable', 'false');
271
385
  applyLabel(svg, options.label ?? null);
272
386
  return svg;
273
387
  }
274
388
 
275
- /** View box the placeholder reserves — the square most Font Awesome glyphs are drawn in. */
276
- const PLACEHOLDER_VIEW_BOX = '0 0 512 512';
389
+ /**
390
+ * The stroke width an outline glyph is drawn with, in its own view-box units: `STROKE_WIDTH` per
391
+ * 24 units, so outline sets drawn on another grid keep the same weight, and never thinner than
392
+ * `MIN_STROKE_PX` at the rendered size. A size given as a CSS length other than pixels (`'1em'`)
393
+ * cannot be measured here and keeps the proportional width.
394
+ * @param {string} viewBox The glyph's view box.
395
+ * @param {number|string} size The rendered size the caller asked for.
396
+ * @returns {string}
397
+ */
398
+ function strokeWidth(viewBox, size) {
399
+ const [, , width, height] = viewBox.trim().split(/[\s,]+/).map(Number);
400
+ const extent = Math.max(width, height) || 24;
401
+ let units = STROKE_WIDTH * extent / 24;
402
+ const pixels = typeof size === 'number' ? size
403
+ : /^\d*\.?\d+(px)?$/.test(String(size).trim()) ? parseFloat(String(size)) : NaN;
404
+ if (pixels > 0) units = Math.max(units, MIN_STROKE_PX * extent / pixels);
405
+ return String(Math.round(units * 1000) / 1000);
406
+ }
407
+
408
+ /** View box the placeholder reserves — the square the bundled glyphs are drawn in. */
409
+ const PLACEHOLDER_VIEW_BOX = VIEW_BOX;
277
410
 
278
411
  /**
279
412
  * The element an unresolvable name renders as: the ordinary `zx-icon` root at the requested size,
@@ -290,7 +423,7 @@ const PLACEHOLDER_VIEW_BOX = '0 0 512 512';
290
423
  * @returns {SVGSVGElement}
291
424
  */
292
425
  function missingIcon(name, options) {
293
- const svg = iconSvg(PLACEHOLDER_VIEW_BOX, options);
426
+ const svg = iconSvg(PLACEHOLDER_VIEW_BOX, 'stroke', options);
294
427
  svg.setAttribute('data-zx-icon-missing', name);
295
428
  return svg;
296
429
  }
@@ -0,0 +1,147 @@
1
+ // @ts-check
2
+ /**
3
+ * Motion as a setting, for the code that animates in script.
4
+ *
5
+ * CSS motion needs nothing from here: `tokens/global.css` sets every `--zx-dur-*` to 0ms and
6
+ * `base.css` stops animations and transitions both under the operating system's reduced-motion
7
+ * preference and inside any `data-zx-motion="reduced"` region. A chart engine's own tweening, a
8
+ * `requestAnimationFrame` loop, or `element.animate()` never sees those rules, so a component that
9
+ * moves things itself asks `prefersReducedMotion()` before it starts and `watchMotion()` for the
10
+ * moment the answer changes.
11
+ *
12
+ * There is no "full motion" value: a region can only ask for less. Someone who asked their system
13
+ * for reduced motion gets it whatever an application or a region says.
14
+ * @module zx/core/motion
15
+ */
16
+
17
+ /** The attribute that marks a reduced-motion region. Its one meaningful value is `reduced`. */
18
+ export const MOTION_ATTRIBUTE = 'data-zx-motion';
19
+
20
+ const REDUCED_REGION = '[data-zx-motion="reduced"]';
21
+ const REDUCED_QUERY = '(prefers-reduced-motion: reduce)';
22
+
23
+ /**
24
+ * Whether motion should stop where `element` is: true under the operating system's reduced-motion
25
+ * preference, or when the element sits inside a `data-zx-motion="reduced"` region (the element
26
+ * itself included). The region check crosses shadow-root boundaries.
27
+ * @param {Element|null} [element] Where the motion would happen. Omitted, the document root is
28
+ * asked — which answers for an application that sets the attribute on `<html>`.
29
+ * @returns {boolean}
30
+ */
31
+ export function prefersReducedMotion(element) {
32
+ if (systemPrefersReducedMotion()) return true;
33
+ const target = element ?? globalThis.document?.documentElement ?? null;
34
+ return inReducedRegion(target);
35
+ }
36
+
37
+ /**
38
+ * @typedef {Object} WatchMotionOptions
39
+ * @property {AbortSignal} [signal] Stops watching when aborted, exactly as calling the returned
40
+ * disposer does. A signal that is already aborted watches nothing.
41
+ * @property {boolean} [immediate=false] Also calls back once, synchronously, with the current
42
+ * answer — convenient for a loop that starts or stays stopped in the same callback.
43
+ */
44
+
45
+ /**
46
+ * Calls back whenever `prefersReducedMotion(element)` changes: when the operating-system preference
47
+ * flips, or when a `data-zx-motion` attribute is set, changed, or removed on the element or any
48
+ * ancestor (in the document, or in the shadow root the element lives in). The callback receives
49
+ * the new answer and runs only on a real change.
50
+ *
51
+ * Moving the element into or out of a reduced region is not observed — ask
52
+ * `prefersReducedMotion()` again after re-parenting.
53
+ * @param {Element|null} element Where the motion happens. Null watches the document root.
54
+ * @param {(reduced: boolean) => void} fn Receives `true` when motion must stop, `false` when it may
55
+ * run again.
56
+ * @param {WatchMotionOptions} [options={}]
57
+ * @returns {() => void} Disposer: stops watching. Safe to call more than once.
58
+ */
59
+ export function watchMotion(element, fn, options = {}) {
60
+ if (typeof fn !== 'function') throw new TypeError('watchMotion requires a callback');
61
+ const { signal, immediate = false } = options;
62
+ if (signal?.aborted) return () => {};
63
+
64
+ let current = prefersReducedMotion(element);
65
+ let stopped = false;
66
+
67
+ const check = () => {
68
+ if (stopped) return;
69
+ const next = prefersReducedMotion(element);
70
+ if (next === current) return;
71
+ current = next;
72
+ fn(next);
73
+ };
74
+
75
+ const media = typeof globalThis.matchMedia === 'function' ? globalThis.matchMedia(REDUCED_QUERY) : null;
76
+ media?.addEventListener?.('change', check);
77
+
78
+ // One observer over every tree the element's ancestry passes through: the document, and each
79
+ // shadow root on the way up. The attribute filter keeps it to the one attribute that matters.
80
+ const observer = typeof MutationObserver === 'function' ? new MutationObserver(check) : null;
81
+ if (observer) {
82
+ for (const root of treesAbove(element)) {
83
+ observer.observe(root, { attributes: true, attributeFilter: [MOTION_ATTRIBUTE], subtree: true });
84
+ }
85
+ }
86
+
87
+ const stop = () => {
88
+ if (stopped) return;
89
+ stopped = true;
90
+ media?.removeEventListener?.('change', check);
91
+ observer?.disconnect();
92
+ signal?.removeEventListener('abort', stop);
93
+ };
94
+ signal?.addEventListener('abort', stop, { once: true });
95
+
96
+ if (immediate) fn(current);
97
+ return stop;
98
+ }
99
+
100
+ /** @returns {boolean} Whether the operating system asks for reduced motion. */
101
+ function systemPrefersReducedMotion() {
102
+ return typeof globalThis.matchMedia === 'function' && globalThis.matchMedia(REDUCED_QUERY).matches;
103
+ }
104
+
105
+ /**
106
+ * @param {Element|null} element
107
+ * @returns {boolean} Whether the element is inside a reduced region, across shadow boundaries.
108
+ */
109
+ function inReducedRegion(element) {
110
+ /** @type {Element|null} */
111
+ let node = element;
112
+ while (node && typeof node.closest === 'function') {
113
+ if (node.closest(REDUCED_REGION)) return true;
114
+ const root = node.getRootNode?.();
115
+ node = isShadowRoot(root) ? root.host : null;
116
+ }
117
+ return false;
118
+ }
119
+
120
+ /**
121
+ * The trees a region attribute could be set in: the shadow roots on the element's way up, and the
122
+ * document element.
123
+ * @param {Element|null} element
124
+ * @returns {Node[]}
125
+ */
126
+ function treesAbove(element) {
127
+ const trees = [];
128
+ /** @type {Element|null} */
129
+ let node = element;
130
+ while (node && typeof node.getRootNode === 'function') {
131
+ const root = node.getRootNode();
132
+ if (!isShadowRoot(root)) break;
133
+ trees.push(root);
134
+ node = root.host;
135
+ }
136
+ const documentElement = (element?.ownerDocument ?? globalThis.document)?.documentElement;
137
+ if (documentElement) trees.push(documentElement);
138
+ return trees;
139
+ }
140
+
141
+ /**
142
+ * @param {unknown} node
143
+ * @returns {node is ShadowRoot}
144
+ */
145
+ function isShadowRoot(node) {
146
+ return Boolean(node) && /** @type {Node} */ (node).nodeType === 11 && 'host' in /** @type {object} */ (node);
147
+ }
@@ -1,12 +1,12 @@
1
1
  import { resolveElement } from './dom.js';
2
2
 
3
- const SCOPE_SELECTOR = '.zx-scope, [data-zx-theme], [data-zx-density], [data-zx-preset]';
3
+ const SCOPE_SELECTOR = '.zx-scope, [data-zx-theme], [data-zx-preset]';
4
4
 
5
5
  /**
6
6
  * Finds the closest styling scope for a top-layer element.
7
7
  *
8
8
  * Popovers and dialogs escape clipping even when their DOM parent is inside an application shell,
9
- * so keeping them below that parent preserves inherited theme, density, material, and product
9
+ * so keeping them below that parent preserves inherited theme, preset, material, and product
10
10
  * token overrides without sacrificing top-layer behaviour. The document body remains the safe
11
11
  * fallback for unscoped applications.
12
12
  *
@@ -21,3 +21,22 @@ export function overlayHost(source = null) {
21
21
  if (!scope || scope === document.documentElement || scope === document.body) return document.body;
22
22
  return scope;
23
23
  }
24
+
25
+ /**
26
+ * Like `overlayHost()`, but declines to guess for a source that is not in the document yet.
27
+ *
28
+ * A component created before its anchor is connected cannot know which themed region the anchor
29
+ * will end up in: the anchor's ancestors are not there yet, so `overlayHost()` would answer
30
+ * `<body>`, outside every `[data-zx-theme]` and `.zx-scope`. This returns null instead, so the
31
+ * overlay can stay detached until it first opens and resolve its host with `overlayHost()` then,
32
+ * when the anchor is in place. The focused-element default (`source` null) is always connected and
33
+ * resolves exactly as `overlayHost()` does.
34
+ *
35
+ * @param {Element|string|null} [source=null] Element or selector whose styling scope should own the overlay.
36
+ * @returns {Element|null} The host, or null while the source is not connected to the document.
37
+ */
38
+ export function connectedOverlayHost(source = null) {
39
+ if (source == null) return overlayHost(null);
40
+ const context = resolveElement(source);
41
+ return context?.isConnected ? overlayHost(context) : null;
42
+ }
package/src/index.js CHANGED
@@ -52,6 +52,7 @@ export {
52
52
  } from './core/dom.js';
53
53
  export { position } from './core/position.js';
54
54
  export { breakpoints, breakpointOf, matchBreakpoint, onBreakpoint } from './core/breakpoint.js';
55
+ export { MOTION_ATTRIBUTE, prefersReducedMotion, watchMotion } from './core/motion.js';
55
56
  export { Http, zeyosService, parseResult } from './core/http.js';
56
57
  export { setTranslator, setLanguage, getLanguage, translate, printf } from './core/i18n.js';
57
58
  export { focusTrap, rovingTabindex, typeahead } from './core/keyboard.js';
@@ -75,8 +76,8 @@ export {
75
76
  export { storage } from './core/storage.js';
76
77
  export { toCsv, downloadBlob, copyToClipboard } from './core/export.js';
77
78
  export { defineElements } from './elements/define.js';
78
- export { button, buttonGroup } from './components/button/button.js';
79
- export { badge, badgeGroup } from './components/badge/badge.js';
79
+ export { button, buttonGroup, setButtonBusy } from './components/button/button.js';
80
+ export { BADGE_TONES, badge, badgeGroup } from './components/badge/badge.js';
80
81
  export { CheckButton } from './components/check-button/check-button.js';
81
82
  export { emptyState } from './components/empty-state/empty-state.js';
82
83
  export { spinner } from './components/loading/spinner.js';
@@ -108,7 +109,7 @@ export { Pagination, paginationRange } from './components/pagination/pagination.
108
109
  export { Search } from './components/search/search.js';
109
110
  export { AppIcon, appIcon } from './components/app-icon/app-icon.js';
110
111
  export { Launcher, rankLauncherItems } from './components/launcher/launcher.js';
111
- export { Avatar, avatarInitials } from './components/avatar/avatar.js';
112
+ export { AVATAR_TONES, Avatar, avatarInitials, avatarTone } from './components/avatar/avatar.js';
112
113
  export {
113
114
  EntityRef, normalizeEntityRef, normalizeEntityRefLink,
114
115
  normalizeEntityRefMetadata, normalizeEntityRefActions
@@ -134,6 +135,7 @@ export { Tooltip, tooltip, describe } from './components/tooltip/tooltip.js';
134
135
  export { MenuButton } from './components/menu-button/menu-button.js';
135
136
  export { ContextMenu } from './components/context-menu/context-menu.js';
136
137
  export { Select } from './components/select/select.js';
138
+ export { statusIcon, priorityIcon } from './components/select/glyphs.js';
137
139
  export { Checklist } from './components/checklist/checklist.js';
138
140
  export { TagPicker } from './components/tag-picker/tag-picker.js';
139
141
  export { NumberField, parseNumber, snapNumber } from './components/number-field/number-field.js';
@@ -294,8 +294,7 @@ export class AppRailPresenter extends Component {
294
294
  const actualPanel = dropdown.getPanel();
295
295
  actualPanel.classList.add('zx-app-rail__popover');
296
296
  // The panel is portaled out of the rail, so its stylesheet cannot ask which edge the rail
297
- // occupies. Presentation only: it carries the active marker to the edge facing the screen
298
- // on a right-hand rail, exactly as the expanded tree does.
297
+ // occupies. Presentation only: it tells the panel's styles which side it opened from.
299
298
  actualPanel.dataset.side = this.el.dataset.side;
300
299
  actualPanel.setAttribute('role', 'region');
301
300
  actualPanel.setAttribute('aria-label', this._message('appRail.subNavigation', '%1 sub-navigation', item.label));
@@ -107,8 +107,12 @@ function isRecord(value) {
107
107
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
108
108
  }
109
109
 
110
- /** @param {unknown} error @returns {string} */
111
- function errorMessage(error) {
110
+ /**
111
+ * The text a failed request is reported with: the error's own message, or a generic sentence.
112
+ * @param {unknown} error Rejection reason.
113
+ * @returns {string}
114
+ */
115
+ export function errorMessage(error) {
112
116
  if (error instanceof Error && error.message) return error.message;
113
117
  if (error && typeof error === 'object' && typeof error.message === 'string') return error.message;
114
118
  return String(error ?? 'ZeyOS request failed');