@ethlete/components 1.0.0-next.77 → 1.0.0-next.79

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 (318) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/design/accordion.ts +73 -0
  3. package/design/avatar.ts +90 -0
  4. package/design/badge.ts +48 -0
  5. package/design/banner.ts +77 -0
  6. package/design/bracket.ts +457 -0
  7. package/design/breadcrumb.ts +145 -0
  8. package/design/button.ts +49 -0
  9. package/design/calendar.ts +306 -0
  10. package/design/card.ts +92 -0
  11. package/design/carousel.ts +240 -0
  12. package/design/chart.ts +512 -0
  13. package/design/checkbox.ts +275 -0
  14. package/design/chip.ts +64 -0
  15. package/design/config.json +22 -0
  16. package/design/control.ts +19 -0
  17. package/design/copy-button.ts +59 -0
  18. package/design/description-list.ts +41 -0
  19. package/design/dialog.ts +214 -0
  20. package/design/divider.ts +27 -0
  21. package/design/empty-state.ts +45 -0
  22. package/design/floating-action.ts +55 -0
  23. package/design/form-field.ts +40 -1
  24. package/design/grid.ts +148 -0
  25. package/design/icon-set.ts +19 -0
  26. package/design/icon.ts +9 -0
  27. package/design/input.ts +86 -0
  28. package/design/kbd.ts +19 -0
  29. package/design/loader.ts +152 -0
  30. package/design/masonry.ts +115 -0
  31. package/design/match.ts +131 -0
  32. package/design/menu.ts +143 -0
  33. package/design/notification.ts +129 -0
  34. package/design/otp-input.ts +107 -0
  35. package/design/pagination.ts +120 -0
  36. package/design/picture.ts +80 -0
  37. package/design/progress-steps.ts +79 -0
  38. package/design/query-error.ts +60 -0
  39. package/design/radio-group.ts +132 -0
  40. package/design/scheduler.ts +369 -0
  41. package/design/scrollable.ts +218 -0
  42. package/design/scrollbar.ts +47 -0
  43. package/design/sdk/assets/fallback.svg +1 -0
  44. package/design/sdk/assets/tall.svg +1 -0
  45. package/design/sdk/assets/wide.svg +1 -0
  46. package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
  47. package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
  48. package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
  49. package/design/sdk/components/accordion/accordion.css +17 -0
  50. package/design/sdk/components/accordion/accordion.ts +64 -0
  51. package/design/sdk/components/avatar/avatar.css +14 -0
  52. package/design/sdk/components/avatar/avatar.ts +78 -0
  53. package/design/sdk/components/badge/badge.css +13 -0
  54. package/design/sdk/components/badge/badge.ts +52 -0
  55. package/design/sdk/components/banner/banner.css +18 -0
  56. package/design/sdk/components/banner/banner.ts +87 -0
  57. package/design/sdk/components/bracket/bracket.css +59 -0
  58. package/design/sdk/components/bracket/bracket.ts +143 -0
  59. package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
  60. package/design/sdk/components/breadcrumb/breadcrumb.ts +81 -0
  61. package/design/sdk/components/button/button.css +33 -0
  62. package/design/sdk/components/button/button.ts +82 -0
  63. package/design/sdk/components/calendar/calendar.css +33 -0
  64. package/design/sdk/components/calendar/calendar.ts +96 -0
  65. package/design/sdk/components/card/card.css +19 -0
  66. package/design/sdk/components/card/card.ts +61 -0
  67. package/design/sdk/components/carousel/carousel.css +44 -0
  68. package/design/sdk/components/carousel/carousel.ts +74 -0
  69. package/design/sdk/components/chart/chart.css +56 -0
  70. package/design/sdk/components/chart/chart.ts +98 -0
  71. package/design/sdk/components/chip/chip.css +18 -0
  72. package/design/sdk/components/chip/chip.ts +76 -0
  73. package/design/sdk/components/copy-button/copy-button.css +14 -0
  74. package/design/sdk/components/copy-button/copy-button.ts +59 -0
  75. package/design/sdk/components/description-list/description-list.css +7 -0
  76. package/design/sdk/components/description-list/description-list.ts +53 -0
  77. package/design/sdk/components/dialog/dialog.css +29 -0
  78. package/design/sdk/components/dialog/dialog.ts +78 -0
  79. package/design/sdk/components/divider/divider.css +26 -0
  80. package/design/sdk/components/divider/divider.ts +43 -0
  81. package/design/sdk/components/empty-state/empty-state.css +15 -0
  82. package/design/sdk/components/empty-state/empty-state.ts +56 -0
  83. package/design/sdk/components/floating-action/floating-action.css +51 -0
  84. package/design/sdk/components/floating-action/floating-action.ts +63 -0
  85. package/design/sdk/components/form-field/form-field.ts +118 -0
  86. package/design/sdk/components/grid/grid.css +17 -0
  87. package/design/sdk/components/grid/grid.ts +80 -0
  88. package/design/sdk/components/input/input.css +75 -0
  89. package/design/sdk/components/input/input.ts +79 -0
  90. package/design/sdk/components/kbd/kbd.css +25 -0
  91. package/design/sdk/components/kbd/kbd.ts +57 -0
  92. package/design/sdk/components/loader/loader.css +37 -0
  93. package/design/sdk/components/loader/loader.ts +68 -0
  94. package/design/sdk/components/masonry/masonry.css +7 -0
  95. package/design/sdk/components/masonry/masonry.ts +42 -0
  96. package/design/sdk/components/match/match.css +25 -0
  97. package/design/sdk/components/match/match.ts +76 -0
  98. package/design/sdk/components/menu/menu.css +22 -0
  99. package/design/sdk/components/menu/menu.ts +91 -0
  100. package/design/sdk/components/notification/notification.css +32 -0
  101. package/design/sdk/components/notification/notification.ts +106 -0
  102. package/design/sdk/components/otp-input/otp-input.css +35 -0
  103. package/design/sdk/components/otp-input/otp-input.ts +64 -0
  104. package/design/sdk/components/pagination/pagination.css +14 -0
  105. package/design/sdk/components/pagination/pagination.ts +75 -0
  106. package/design/sdk/components/picture/picture.css +37 -0
  107. package/design/sdk/components/picture/picture.ts +96 -0
  108. package/design/sdk/components/progress-steps/progress-steps.css +37 -0
  109. package/design/sdk/components/progress-steps/progress-steps.ts +91 -0
  110. package/design/sdk/components/query-error/query-error.css +33 -0
  111. package/design/sdk/components/query-error/query-error.ts +120 -0
  112. package/design/sdk/components/scheduler/scheduler.css +55 -0
  113. package/design/sdk/components/scheduler/scheduler.ts +239 -0
  114. package/design/sdk/components/scrollable/scrollable.css +58 -0
  115. package/design/sdk/components/scrollable/scrollable.ts +133 -0
  116. package/design/sdk/components/scrollbar/scrollbar.css +78 -0
  117. package/design/sdk/components/scrollbar/scrollbar.ts +123 -0
  118. package/design/sdk/components/select/select.css +5 -0
  119. package/design/sdk/components/select/select.ts +16 -0
  120. package/design/sdk/components/select/shared/select-part.ts +75 -0
  121. package/design/sdk/components/select-panel/select-panel.css +3 -0
  122. package/design/sdk/components/select-panel/select-panel.ts +124 -0
  123. package/design/sdk/components/skeleton/skeleton.css +22 -0
  124. package/design/sdk/components/skeleton/skeleton.ts +50 -0
  125. package/design/sdk/components/slider/slider.css +52 -0
  126. package/design/sdk/components/slider/slider.ts +86 -0
  127. package/design/sdk/components/standings/standings.css +33 -0
  128. package/design/sdk/components/standings/standings.ts +130 -0
  129. package/design/sdk/components/stat-tile/stat-tile.css +15 -0
  130. package/design/sdk/components/stat-tile/stat-tile.ts +84 -0
  131. package/design/sdk/components/stream/stream.css +48 -0
  132. package/design/sdk/components/stream/stream.ts +38 -0
  133. package/design/sdk/components/switch/switch.css +35 -0
  134. package/design/sdk/components/switch/switch.ts +63 -0
  135. package/design/sdk/components/table/table.css +67 -0
  136. package/design/sdk/components/table/table.ts +160 -0
  137. package/design/sdk/components/tabs/tabs.css +13 -0
  138. package/design/sdk/components/tabs/tabs.ts +74 -0
  139. package/design/sdk/components/textarea/textarea.css +116 -0
  140. package/design/sdk/components/textarea/textarea.ts +64 -0
  141. package/design/sdk/components/timeline/timeline.css +30 -0
  142. package/design/sdk/components/timeline/timeline.ts +87 -0
  143. package/design/sdk/components/toolbar/toolbar.css +24 -0
  144. package/design/sdk/components/toolbar/toolbar.ts +87 -0
  145. package/design/sdk/components/tooltip/tooltip.css +15 -0
  146. package/design/sdk/components/tooltip/tooltip.ts +28 -0
  147. package/design/sdk/components/tree/selected-tint.css +15 -0
  148. package/design/sdk/components/tree/tree.ts +70 -0
  149. package/design/sdk/fixtures.ts +0 -0
  150. package/design/sdk/foundations/colors/colors.css +632 -0
  151. package/design/sdk/foundations/colors/colors.ts +188 -0
  152. package/design/sdk/foundations/colors/overrides.json +19 -0
  153. package/design/sdk/foundations/colors/shared/contrast.ts +120 -0
  154. package/design/sdk/foundations/elevation/elevation.css +6 -0
  155. package/design/sdk/foundations/elevation/elevation.ts +11 -0
  156. package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
  157. package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
  158. package/design/sdk/foundations/icons/icons.ts +119 -0
  159. package/design/select.ts +113 -28
  160. package/design/skeleton.ts +67 -0
  161. package/design/slider.ts +155 -0
  162. package/design/standings.ts +161 -0
  163. package/design/stat-tile.ts +109 -0
  164. package/design/stream.ts +92 -0
  165. package/design/switch.ts +83 -0
  166. package/design/table.ts +302 -0
  167. package/design/tabs.ts +75 -0
  168. package/design/textarea.ts +92 -0
  169. package/design/timeline.ts +52 -0
  170. package/design/toolbar.ts +95 -0
  171. package/design/tooltip.ts +87 -0
  172. package/design/tree.ts +106 -0
  173. package/fesm2022/ethlete-components.mjs +240 -199
  174. package/fesm2022/ethlete-components.mjs.map +1 -1
  175. package/package.json +1 -1
  176. package/src/lib/accordion/accordion.component.css +2 -1
  177. package/src/lib/avatar/avatar.component.css +10 -0
  178. package/src/lib/badge/badge.component.css +2 -2
  179. package/src/lib/banner/banner.component.css +3 -1
  180. package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
  181. package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
  182. package/src/lib/button/button.component.css +19 -0
  183. package/src/lib/button/icon-button.component.css +19 -20
  184. package/src/lib/button/split-button.component.css +5 -1
  185. package/src/lib/calendar/calendar.component.css +13 -3
  186. package/src/lib/card/card.component.css +4 -0
  187. package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
  188. package/src/lib/carousel/carousel.component.css +2 -2
  189. package/src/lib/chart/chart-axis.component.css +3 -3
  190. package/src/lib/chip/chip.component.css +8 -2
  191. package/src/lib/description-list/description-list.component.css +2 -1
  192. package/src/lib/empty-state/empty-state.component.css +4 -0
  193. package/src/lib/floating-action/floating-action-styles.component.css +27 -0
  194. package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
  195. package/src/lib/forms/checkbox/checkbox.component.css +31 -5
  196. package/src/lib/forms/color-input/color-input.component.css +3 -1
  197. package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
  198. package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
  199. package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
  200. package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
  201. package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
  202. package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
  203. package/src/lib/forms/description/description.component.css +7 -0
  204. package/src/lib/forms/dropzone/dropzone.component.css +26 -0
  205. package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
  206. package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +74 -17
  207. package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
  208. package/src/lib/forms/form-field/form-field.component.css +6 -0
  209. package/src/lib/forms/form-field/headless/label.directive.css +1 -1
  210. package/src/lib/forms/input/input.component.css +6 -2
  211. package/src/lib/forms/input/number-input.component.css +2 -2
  212. package/src/lib/forms/input/password-input.component.css +4 -3
  213. package/src/lib/forms/otp-input/otp-input.component.css +23 -4
  214. package/src/lib/forms/phone-input/phone-input.component.css +4 -3
  215. package/src/lib/forms/rating/rating.component.css +2 -1
  216. package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
  217. package/src/lib/forms/select/select-option-styles.component.css +3 -2
  218. package/src/lib/forms/selection-card-styles.component.css +3 -2
  219. package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
  220. package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
  221. package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
  222. package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
  223. package/src/lib/forms/slider/range-slider.component.css +98 -6
  224. package/src/lib/forms/slider/slider.component.css +96 -4
  225. package/src/lib/forms/switch/switch.component.css +47 -4
  226. package/src/lib/forms/tag-input/tag-input.component.css +2 -2
  227. package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
  228. package/src/lib/forms/textarea/textarea.component.css +7 -2
  229. package/src/lib/grid/grid-item-toolbar.component.css +10 -0
  230. package/src/lib/grid/grid-item.component.css +6 -1
  231. package/src/lib/icon/headless/align-icons.ts +30 -0
  232. package/src/lib/icon/headless/arrow-out-up-right-icon.ts +17 -0
  233. package/src/lib/icon/headless/arrow-right-icon.ts +23 -0
  234. package/src/lib/icon/headless/arrow-up-icon.ts +30 -0
  235. package/src/lib/icon/headless/arrows-left-right-icon.ts +31 -0
  236. package/src/lib/icon/headless/bold-icon.ts +11 -0
  237. package/src/lib/icon/headless/calendar-icon.ts +21 -0
  238. package/src/lib/icon/headless/check-icon.ts +14 -0
  239. package/src/lib/icon/headless/chevron-icon.ts +14 -0
  240. package/src/lib/icon/headless/circle-check-icon.ts +14 -0
  241. package/src/lib/icon/headless/circle-info-icon.ts +14 -0
  242. package/src/lib/icon/headless/clipboard-check-icon.ts +28 -0
  243. package/src/lib/icon/headless/clock-icon.ts +21 -0
  244. package/src/lib/icon/headless/code-block-icon.ts +15 -0
  245. package/src/lib/icon/headless/code-icon.ts +14 -0
  246. package/src/lib/icon/headless/ellipsis-icon.ts +13 -0
  247. package/src/lib/icon/headless/ellipsis-vertical-icon.ts +13 -0
  248. package/src/lib/icon/headless/eye-icons.ts +27 -0
  249. package/src/lib/icon/headless/eyedropper-icon.ts +22 -0
  250. package/src/lib/icon/headless/file-icon.ts +16 -0
  251. package/src/lib/icon/headless/filter-icon.ts +11 -0
  252. package/src/lib/icon/headless/floppy-disk-icon.ts +27 -0
  253. package/src/lib/icon/headless/focus-frame-icon.ts +16 -0
  254. package/src/lib/icon/headless/grid-2x2-icon.ts +17 -0
  255. package/src/lib/icon/headless/heading-1-icon.ts +11 -0
  256. package/src/lib/icon/headless/heading-2-icon.ts +11 -0
  257. package/src/lib/icon/headless/heading-3-icon.ts +11 -0
  258. package/src/lib/icon/headless/icon-definition.ts +14 -0
  259. package/src/lib/icon/headless/image-icon.ts +14 -0
  260. package/src/lib/icon/headless/italic-icon.ts +19 -0
  261. package/src/lib/icon/headless/link-icon.ts +17 -0
  262. package/src/lib/icon/headless/list-bulleted-icon.ts +14 -0
  263. package/src/lib/icon/headless/list-numbered-icon.ts +14 -0
  264. package/src/lib/icon/headless/location-icon.ts +21 -0
  265. package/src/lib/icon/headless/lock-icon.ts +14 -0
  266. package/src/lib/icon/headless/minus-icon.ts +14 -0
  267. package/src/lib/icon/headless/paragraph-icon.ts +11 -0
  268. package/src/lib/icon/headless/pause-icon.ts +11 -0
  269. package/src/lib/icon/headless/pencil-icon.ts +21 -0
  270. package/src/lib/icon/headless/play-icon.ts +10 -0
  271. package/src/lib/icon/headless/plus-icon.ts +21 -0
  272. package/src/lib/icon/headless/quote-icon.ts +15 -0
  273. package/src/lib/icon/headless/rotate-right-icon.ts +16 -0
  274. package/src/lib/icon/headless/star-icon.ts +14 -0
  275. package/src/lib/icon/headless/strikethrough-icon.ts +18 -0
  276. package/src/lib/icon/headless/table-icon.ts +15 -0
  277. package/src/lib/icon/headless/thumbtack-icon.ts +18 -0
  278. package/src/lib/icon/headless/times-icon.ts +14 -0
  279. package/src/lib/icon/headless/trash-icon.ts +24 -0
  280. package/src/lib/icon/headless/triangle-exclamation-icon.ts +14 -0
  281. package/src/lib/icon/headless/trophy-icon.ts +24 -0
  282. package/src/lib/icon/headless/underline-icon.ts +12 -0
  283. package/src/lib/icon/headless/undo-redo-icons.ts +24 -0
  284. package/src/lib/icon/headless/upload-icon.ts +16 -0
  285. package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
  286. package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
  287. package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
  288. package/src/lib/match/match-card.component.css +9 -3
  289. package/src/lib/match/match-score.component.css +4 -1
  290. package/src/lib/menu/menu-selection-item.component.css +1 -1
  291. package/src/lib/menu/menu.component.css +5 -0
  292. package/src/lib/overlay/overlay-container.component.css +4 -0
  293. package/src/lib/pagination/pagination.component.css +4 -0
  294. package/src/lib/progress-steps/progress-step.component.css +4 -4
  295. package/src/lib/query-error/query-error.component.css +4 -0
  296. package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
  297. package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
  298. package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
  299. package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
  300. package/src/lib/standings/standings-pick.component.css +1 -1
  301. package/src/lib/standings/standings.component.css +10 -10
  302. package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
  303. package/src/lib/stream/consent/stream-consent.component.css +99 -0
  304. package/src/lib/stream/error/stream-player-error.component.css +100 -0
  305. package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
  306. package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
  307. package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
  308. package/src/lib/table/table-resize-grip.component.css +2 -1
  309. package/src/lib/table/table-select-cell.component.css +45 -15
  310. package/src/lib/table/table.component.css +15 -5
  311. package/src/lib/tabs/tab-bar-styles.component.css +1 -1
  312. package/src/lib/tabs/tabs/tab-group.component.css +111 -0
  313. package/src/lib/time-picker/time-picker.component.css +2 -1
  314. package/src/lib/timeline/timeline-item.component.css +5 -1
  315. package/src/lib/toolbar/toolbar.component.css +4 -0
  316. package/src/lib/tooltip/tooltip.component.css +14 -0
  317. package/src/lib/tree/tree.component.css +2 -2
  318. package/types/ethlete-components.d.ts +62 -53
@@ -0,0 +1,214 @@
1
+ import iconButtonBase from '../src/lib/button/icon-button.component.css?inline';
2
+ import { TIMES_ICON } from '../src/lib/icon/headless/times-icon';
3
+ import iconBase from '../src/lib/icon/headless/icon-styles.component.css?inline';
4
+ import alertDialogBase from '../src/lib/overlay/alert-dialog/alert-dialog.component.css?inline';
5
+ import overlayContainer from '../src/lib/overlay/overlay-container.component.css?inline';
6
+ import overlayMain from '../src/lib/overlay/overlay-main-styles.component.css?inline';
7
+ import dialogStrategy from '../src/lib/overlay/strategies/dialog-styles.component.css?inline';
8
+ import { button, buttonStyles } from './button';
9
+ import { iconMarkup } from './icon';
10
+
11
+ export type DialogMockButton = {
12
+ label: string;
13
+ variant?: 'filled' | 'outline' | 'tonal' | 'transparent';
14
+ /** A color theme name the app registers. Left out, the button takes the dialog's color theme. */
15
+ color?: string;
16
+ /** Extra attributes on the button, e.g. design markers. */
17
+ attributes?: string;
18
+ };
19
+
20
+ export type DialogMockOptions = {
21
+ /** The title, as HTML. */
22
+ title: string;
23
+ /** The body content, as HTML. */
24
+ body: string;
25
+ /** The footer buttons, in order. Leave it out for a dialog without a footer. */
26
+ actions?: DialogMockButton[];
27
+ /** Draws an `et-icon-button` with `etOverlayClose` in the header; the string adds attributes to it. */
28
+ close?: boolean | string;
29
+ /** As the body's `dividers` input. `dynamic` draws the body scrolled to its start. */
30
+ dividers?: false | 'static' | 'dynamic';
31
+ /** A surface theme name the app registers, for the pane. */
32
+ surface?: string;
33
+ /** Extra attributes on the pane, e.g. design markers. */
34
+ attributes?: string;
35
+ /** Unique per frame: the title id derives from it. */
36
+ id?: string;
37
+ };
38
+
39
+ export type AlertDialogMockOptions = {
40
+ kind: 'alert' | 'confirm';
41
+ title: string;
42
+ message?: string;
43
+ /** The confirm button's color theme name, as `confirmColor` sets it. */
44
+ confirmColor?: string;
45
+ confirmLabel?: string;
46
+ cancelLabel?: string;
47
+ acknowledgeLabel?: string;
48
+ /** Extra attributes on the confirm (or acknowledge) button. */
49
+ confirmAttributes?: string;
50
+ /** Extra attributes on the cancel button. */
51
+ cancelAttributes?: string;
52
+ surface?: string;
53
+ attributes?: string;
54
+ id?: string;
55
+ };
56
+
57
+ /** The stylesheets `dialog()` and `alertDialog()` draw with: the real overlay pane, dialog, button and icon button CSS. */
58
+ export const dialogStyles = /* @__PURE__ */ [
59
+ buttonStyles,
60
+ iconBase,
61
+ iconButtonBase,
62
+ overlayContainer,
63
+ overlayMain,
64
+ dialogStrategy,
65
+ alertDialogBase,
66
+ `@layer components {
67
+ .et-dialog-mock-header {
68
+ display: flex;
69
+ align-items: center;
70
+ justify-content: space-between;
71
+ gap: 1.2rem;
72
+ }
73
+ .et-dialog-mock-title {
74
+ margin: 0;
75
+ font-size: 1.8rem;
76
+ font-weight: 600;
77
+ }
78
+ .et-dialog-mock-actions {
79
+ display: flex;
80
+ flex-wrap: wrap;
81
+ justify-content: flex-end;
82
+ gap: 0.8rem;
83
+ }
84
+ .et-dialog-mock-scene {
85
+ position: relative;
86
+ display: grid;
87
+ place-items: center;
88
+ padding: 4rem 2.4rem;
89
+ }
90
+ .et-dialog-mock-scene > .et-overlay-runtime-backdrop {
91
+ position: absolute;
92
+ inset: 0;
93
+ }
94
+ }`,
95
+ ].join('\n');
96
+
97
+ const footerButton = (action: DialogMockButton) => {
98
+ const markup = button({ label: action.label, variant: action.variant ?? 'filled', color: action.color, size: 'md' });
99
+
100
+ return action.attributes ? markup.replace(/^<button /, `<button ${action.attributes} `) : markup;
101
+ };
102
+
103
+ const closeButton = (attributes?: string) => {
104
+ const classes = [
105
+ 'et-surface-interactive',
106
+ 'et-color-interactive',
107
+ 'et-icon-button',
108
+ 'et-focus-ring',
109
+ 'et-color--inherited',
110
+ ];
111
+
112
+ return `<button ${attributes ?? ''} etOverlayClose type="button" aria-label="Close" class="${classes.join(' ')}" data-variant="transparent" data-size="sm"><div class="et-icon-button-icon">${iconMarkup(TIMES_ICON)}</div></button>`;
113
+ };
114
+
115
+ const pane = (
116
+ options: { surface?: string; attributes?: string; role: string; labelledBy: string; describedBy?: string },
117
+ content: string,
118
+ ) => {
119
+ const classes = [
120
+ 'et-overlay',
121
+ 'et-overlay-runtime-pane',
122
+ 'et-overlay--dialog',
123
+ 'et-color--inherited',
124
+ `et-surface--${options.surface ?? 'inherited'}`,
125
+ 'et-with-default-animation',
126
+ 'et-animation-enter-done',
127
+ ];
128
+ const attributes = [
129
+ options.attributes,
130
+ `role="${options.role}"`,
131
+ 'aria-modal="true"',
132
+ 'tabindex="-1"',
133
+ `aria-labelledby="${options.labelledBy}"`,
134
+ options.describedBy && `aria-describedby="${options.describedBy}"`,
135
+ `class="${classes.join(' ')}"`,
136
+ ].filter(Boolean);
137
+
138
+ return `<et-overlay-container ${attributes.join(' ')}>${content}</et-overlay-container>`;
139
+ };
140
+
141
+ const body = (content: string, dividers: DialogMockOptions['dividers'] = false) => {
142
+ const classes = [
143
+ 'et-overlay-body',
144
+ dividers && 'et-overlay-body--render-dividers',
145
+ dividers === 'dynamic' && 'et-overlay-body--dynamic-dividers',
146
+ dividers === 'dynamic' && 'et-scrollable-body--can-scroll',
147
+ dividers === 'dynamic' && 'et-scrollable-body--is-at-start',
148
+ ].filter(Boolean);
149
+
150
+ return `<div class="${classes.join(' ')}"><div class="et-overlay-body-container"><div class="et-overlay-body-start-element"></div>${content}<div class="et-overlay-body-end-element"></div></div></div>`;
151
+ };
152
+
153
+ /**
154
+ * Draws an open dialog pane (`dialogOverlayStrategy`) with an `et-overlay-main` of header, body and
155
+ * footer, as HTML. The pane sits in flow; wrap it in `overlayBackdrop()` to draw the scrim.
156
+ */
157
+ export const dialog = (options: DialogMockOptions) => {
158
+ const titleId = `et-overlay-title-${options.id ?? 'dialog'}`;
159
+ const close = options.close ? closeButton(typeof options.close === 'string' ? options.close : undefined) : '';
160
+ const header = `<div class="et-overlay-header et-dialog-mock-header"><h2 class="et-dialog-mock-title" id="${titleId}" et-overlay-title>${options.title}</h2>${close}</div>`;
161
+ const footer = options.actions
162
+ ? `<div class="et-overlay-footer et-dialog-mock-actions">${options.actions.map(footerButton).join('')}</div>`
163
+ : '';
164
+
165
+ return pane(
166
+ { surface: options.surface, attributes: options.attributes, role: 'dialog', labelledBy: titleId },
167
+ `<et-overlay-main class="et-overlay-main">${header}${body(options.body, options.dividers)}${footer}</et-overlay-main>`,
168
+ );
169
+ };
170
+
171
+ /** Draws the open `et-alert-dialog` from `injectAlertDialog()` in its dialog pane, as HTML. */
172
+ export const alertDialog = (options: AlertDialogMockOptions) => {
173
+ const id = options.id ?? 'alert';
174
+ const titleId = `et-overlay-title-${id}`;
175
+ const messageId = `et-alert-dialog-message-${id}`;
176
+ const actions =
177
+ options.kind === 'confirm'
178
+ ? [
179
+ footerButton({
180
+ label: options.cancelLabel ?? 'Cancel',
181
+ variant: 'outline',
182
+ attributes: ['data-et-alert-dialog-initial-focus', options.cancelAttributes].filter(Boolean).join(' '),
183
+ }),
184
+ footerButton({
185
+ label: options.confirmLabel ?? 'Confirm',
186
+ color: options.confirmColor,
187
+ attributes: options.confirmAttributes,
188
+ }),
189
+ ]
190
+ : [
191
+ footerButton({
192
+ label: options.acknowledgeLabel ?? 'OK',
193
+ attributes: ['data-et-alert-dialog-initial-focus', options.confirmAttributes].filter(Boolean).join(' '),
194
+ }),
195
+ ];
196
+ const message = options.message
197
+ ? body(`<p id="${messageId}" class="et-alert-dialog-message">${options.message}</p>`)
198
+ : '';
199
+
200
+ return pane(
201
+ {
202
+ surface: options.surface,
203
+ attributes: options.attributes,
204
+ role: 'alertdialog',
205
+ labelledBy: titleId,
206
+ describedBy: options.message ? messageId : undefined,
207
+ },
208
+ `<et-alert-dialog class="et-alert-dialog et-overlay-main" data-kind="${options.kind}"><div class="et-overlay-header"><h2 class="et-alert-dialog-title" id="${titleId}" et-overlay-title>${options.title}</h2></div>${message}<div class="et-alert-dialog-actions et-overlay-footer">${actions.join('')}</div></et-alert-dialog>`,
209
+ );
210
+ };
211
+
212
+ /** Draws the visible `et-overlay-runtime-backdrop` behind `content`, both in flow. */
213
+ export const overlayBackdrop = (content: string) =>
214
+ `<div class="et-dialog-mock-scene"><div class="et-overlay-runtime-backdrop et-overlay-backdrop--visible"></div>${content}</div>`;
@@ -0,0 +1,27 @@
1
+ import dividerBase from '../src/lib/divider/divider.component.css?inline';
2
+
3
+ export type DividerMockOptions = {
4
+ orientation?: 'horizontal' | 'vertical';
5
+ /** Draws the divider as `decorative`: no separator role, hidden from assistive tech. */
6
+ decorative?: boolean;
7
+ /** Extra attributes on the divider, e.g. design markers. */
8
+ attributes?: string;
9
+ };
10
+
11
+ /** The stylesheets `divider()` draws with: the real divider CSS. */
12
+ export const dividerStyles = /* @__PURE__ */ [dividerBase].join('\n');
13
+
14
+ /** Draws an `et-divider` as the component renders it, as HTML. */
15
+ export const divider = (options: DividerMockOptions = {}) => {
16
+ const orientation = options.orientation ?? 'horizontal';
17
+ const attributes = [
18
+ options.attributes,
19
+ 'class="et-divider"',
20
+ `data-orientation="${orientation}"`,
21
+ options.decorative ? 'role="presentation"' : 'role="separator"',
22
+ !options.decorative && `aria-orientation="${orientation}"`,
23
+ options.decorative && 'aria-hidden="true"',
24
+ ].filter(Boolean);
25
+
26
+ return `<et-divider ${attributes.join(' ')}></et-divider>`;
27
+ };
@@ -0,0 +1,45 @@
1
+ import emptyStateBase from '../src/lib/empty-state/empty-state.component.css?inline';
2
+ import { FILE_ICON } from '../src/lib/icon/headless/file-icon';
3
+ import iconBase from '../src/lib/icon/headless/icon-styles.component.css?inline';
4
+ import { TRIANGLE_EXCLAMATION_ICON } from '../src/lib/icon/headless/triangle-exclamation-icon';
5
+ import { button, ButtonMockOptions, buttonStyles } from './button';
6
+ import { iconMarkup } from './icon';
7
+
8
+ export type EmptyStateMockOptions = {
9
+ heading?: string;
10
+ description?: string;
11
+ /** The projected `[etIcon]`. Left out, the file icon; `false` draws none. */
12
+ icon?: 'file' | 'triangle' | false;
13
+ /** The label of a projected `et-button etEmptyStateAction`. Left out, no action. */
14
+ action?: string;
15
+ /** The action's button variant. Left out, `filled`, as `et-button` defaults to. */
16
+ actionVariant?: ButtonMockOptions['variant'];
17
+ /** Extra attributes on the action button, e.g. design markers. */
18
+ actionAttributes?: string;
19
+ /** Extra attributes on the empty state, e.g. design markers. */
20
+ attributes?: string;
21
+ };
22
+
23
+ const ICONS = {
24
+ file: FILE_ICON,
25
+ triangle: TRIANGLE_EXCLAMATION_ICON,
26
+ } as const;
27
+
28
+ /** The stylesheets `emptyState()` draws with: the real empty-state, button and icon CSS. */
29
+ export const emptyStateStyles = /* @__PURE__ */ [buttonStyles, iconBase, emptyStateBase].join('\n');
30
+
31
+ /** Draws an `et-empty-state` with its projected icon and action as the component renders it, as HTML. */
32
+ export const emptyState = (options: EmptyStateMockOptions) => {
33
+ const icon = options.icon === false ? '' : iconMarkup(ICONS[options.icon ?? 'file']);
34
+ const heading = options.heading ? `<p class="et-empty-state-title">${options.heading}</p>` : '';
35
+ const description = options.description ? `<p class="et-empty-state-description">${options.description}</p>` : '';
36
+ const action = options.action
37
+ ? button({ label: options.action, variant: options.actionVariant }).replace(
38
+ /^<button /,
39
+ `<button ${options.actionAttributes ?? ''} etEmptyStateAction `,
40
+ )
41
+ : '';
42
+ const attributes = [options.attributes, 'class="et-empty-state"'].filter(Boolean);
43
+
44
+ return `<et-empty-state ${attributes.join(' ')}>${icon}${heading}${description}${action}</et-empty-state>`;
45
+ };
@@ -0,0 +1,55 @@
1
+ import floatingActionBase from '../src/lib/floating-action/floating-action-styles.component.css?inline';
2
+ import { FILTER_ICON } from '../src/lib/icon/headless/filter-icon';
3
+ import iconBase from '../src/lib/icon/headless/icon-styles.component.css?inline';
4
+ import { button, buttonStyles, ButtonMockOptions } from './button';
5
+ import { iconMarkup } from './icon';
6
+
7
+ export type FloatingActionMockOptions = {
8
+ /** The trigger, drawn as an `et-button`. */
9
+ trigger: ButtonMockOptions;
10
+ /** Draws the filter icon in the trigger, as the story's Filter button could carry. */
11
+ filterIcon?: boolean;
12
+ /** Where the trigger is. Left out, `inline`. */
13
+ state?: 'inline' | 'floating' | 'hidden';
14
+ /** The in-flow size the anchor holds while the trigger is out of the flow, in px. */
15
+ heldSize?: { inlineSize: number; blockSize: number };
16
+ /** Extra attributes on the trigger, e.g. design markers. */
17
+ triggerAttributes?: string;
18
+ /** Content before the anchor, as HTML. */
19
+ before?: string;
20
+ /** The region the trigger acts on (`etFloatingActionScope`), as HTML. Left out, no scope. */
21
+ scope?: string;
22
+ /** Content after the scope, as HTML. */
23
+ after?: string;
24
+ /** Extra attributes on the host, e.g. a style or design markers. */
25
+ attributes?: string;
26
+ };
27
+
28
+ /** The stylesheets `floatingAction()` draws with: the real floating-action, button and icon CSS. */
29
+ export const floatingActionStyles = /* @__PURE__ */ [buttonStyles, iconBase, floatingActionBase].join('\n');
30
+
31
+ /** Draws `[etFloatingAction]` with its anchor, trigger and scope as a static snapshot of one state. */
32
+ export const floatingAction = (options: FloatingActionMockOptions) => {
33
+ const { state = 'inline', heldSize } = options;
34
+ const trigger = button({
35
+ ...options.trigger,
36
+ icon: options.filterIcon ? iconMarkup(FILTER_ICON) : options.trigger.icon,
37
+ class: ['et-floating-action-trigger', options.trigger.class].filter(Boolean).join(' '),
38
+ style: [state !== 'inline' && 'animation: none; transition: none', options.trigger.style]
39
+ .filter(Boolean)
40
+ .join('; '),
41
+ }).replace(
42
+ /^<(button|a) /,
43
+ `<$1 ${[options.triggerAttributes, `data-floating-action-state="${state}"`].filter(Boolean).join(' ')} `,
44
+ );
45
+
46
+ const held =
47
+ state !== 'inline' && heldSize
48
+ ? ` style="min-inline-size: ${heldSize.inlineSize}px; min-block-size: ${heldSize.blockSize}px"`
49
+ : '';
50
+ const anchor = `<div class="et-floating-action-anchor"${held}>${trigger}</div>`;
51
+ const scope = options.scope === undefined ? '' : `<div class="et-floating-action-scope">${options.scope}</div>`;
52
+ const host = [options.attributes, 'class="et-floating-action"', `data-state="${state}"`].filter(Boolean);
53
+
54
+ return `<div ${host.join(' ')}>${options.before ?? ''}${anchor}${scope}${options.after ?? ''}</div>`;
55
+ };
@@ -5,6 +5,8 @@ import suffixOverlap from '../src/lib/forms/form-field/form-field-suffix-overlap
5
5
  import label from '../src/lib/forms/form-field/headless/label.directive.css?inline';
6
6
  import hint from '../src/lib/forms/form-field/hint.component.css?inline';
7
7
  import inputBase from '../src/lib/forms/input/input.component.css?inline';
8
+ import textareaBase from '../src/lib/forms/textarea/textarea.component.css?inline';
9
+ import textareaAutosize from '../src/lib/forms/textarea/textarea-autosize-styles.component.css?inline';
8
10
  import iconStyles from '../src/lib/icon/headless/icon-styles.component.css?inline';
9
11
 
10
12
  /** The field state a control draws itself from. */
@@ -75,7 +77,16 @@ export type InputMockOptions = {
75
77
  textAlign?: 'start' | 'center' | 'end';
76
78
  };
77
79
 
78
- /** The stylesheets `formField()` and `input()` draw with: the real `et-form-field` CSS. */
80
+ export type TextareaMockOptions = {
81
+ value?: string;
82
+ placeholder?: string;
83
+ rows?: number;
84
+ /** Grows with its content, from `minRows` (default `rows`). On by default, like the real textarea. */
85
+ autosize?: boolean;
86
+ minRows?: number;
87
+ };
88
+
89
+ /** The stylesheets `formField()`, `input()` and `textarea()` draw with: the real `et-form-field` CSS. */
79
90
  export const formFieldStyles = /* @__PURE__ */ [
80
91
  interactiveStyles,
81
92
  iconStyles,
@@ -85,6 +96,8 @@ export const formFieldStyles = /* @__PURE__ */ [
85
96
  label,
86
97
  hint,
87
98
  inputBase,
99
+ textareaBase,
100
+ textareaAutosize,
88
101
  `.et-design-panel-anchor { position: relative; }
89
102
  .et-design-panel { position: absolute; inset-inline: 0; inset-block-start: calc(100% + 0.3rem); z-index: 1; }`,
90
103
  ].join('\n');
@@ -114,6 +127,32 @@ export const input = (options: InputMockOptions = {}): FormFieldControlMock => (
114
127
  },
115
128
  });
116
129
 
130
+ /** Draws `<et-textarea>` as a control for `formField()`. */
131
+ export const textarea = (options: TextareaMockOptions = {}): FormFieldControlMock => ({
132
+ controlType: 'textarea',
133
+ hasValue: !!options.value,
134
+ html: (state) => {
135
+ const rows = options.rows ?? 3;
136
+ const autosize = options.autosize ?? true;
137
+ const attributes = attributesOf([
138
+ 'class="et-textarea-native"',
139
+ `rows="${rows}"`,
140
+ state.disabled && 'disabled',
141
+ state.readonly && 'readonly',
142
+ state.required && 'required',
143
+ options.placeholder && `placeholder="${options.placeholder}"`,
144
+ state.invalid && 'aria-invalid="true"',
145
+ state.describedBy && `aria-describedby="${state.describedBy}"`,
146
+ state.labelId && `aria-labelledby="${state.labelId}"`,
147
+ `data-resize="${autosize ? 'none' : 'vertical'}"`,
148
+ autosize && 'data-et-textarea-autosize=""',
149
+ autosize && `style="--et-textarea-min-rows: ${options.minRows ?? rows}"`,
150
+ ]);
151
+
152
+ return `<et-textarea class="et-color-interactive et-textarea"><textarea ${attributes}>${options.value ?? ''}</textarea></et-textarea>`;
153
+ },
154
+ });
155
+
117
156
  /** Draws `<et-form-field>` with a control, its label, affixes and messages, as the component renders them. */
118
157
  export const formField = (options: FormFieldMockOptions) => {
119
158
  const control: FormFieldControlMock =
package/design/grid.ts ADDED
@@ -0,0 +1,148 @@
1
+ import { resizeHandlesStyles } from '@ethlete/core/design/resize-handles';
2
+ import iconButtonBase from '../src/lib/button/icon-button.component.css?inline';
3
+ import defaultActionsBase from '../src/lib/grid/grid-item-default-actions.component.css?inline';
4
+ import toolbarBase from '../src/lib/grid/grid-item-toolbar.component.css?inline';
5
+ import gridItemBase from '../src/lib/grid/grid-item.component.css?inline';
6
+ import gridBase from '../src/lib/grid/grid.component.css?inline';
7
+ import iconBase from '../src/lib/icon/headless/icon-styles.component.css?inline';
8
+ import { TIMES_ICON } from '../src/lib/icon/headless/times-icon';
9
+ import { buttonStyles } from './button';
10
+ import { iconMarkup } from './icon';
11
+
12
+ export type GridMockPosition = {
13
+ col: number;
14
+ row: number;
15
+ colSpan: number;
16
+ rowSpan: number;
17
+ };
18
+
19
+ export type GridMockItem = GridMockPosition & {
20
+ title: string;
21
+ /** A muted second line under the title. */
22
+ subtitle?: string;
23
+ /** A design marker for the item, e.g. `hover` or `focus-visible`. */
24
+ force?: string;
25
+ /** A design marker for the default remove action, e.g. `hover` or `focus-visible`. */
26
+ removeForce?: string;
27
+ /** `dragging` lifts the item off its slot by `offset`; `resizing` shows every handle, `activeEdge` held. */
28
+ state?: 'dragging' | 'resizing';
29
+ /** The pixel offset from the slot a dragged item follows the pointer by. */
30
+ offset?: { x: number; y: number };
31
+ activeEdge?: 'n' | 'e' | 's' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
32
+ };
33
+
34
+ export type GridMockOptions = {
35
+ items: readonly GridMockItem[];
36
+ /** Left out, 448: the content width the grid would measure, in px. */
37
+ width?: number;
38
+ /** Left out, 4: the columns of the active breakpoint. */
39
+ columns?: number;
40
+ /** Left out, 100, the component default. */
41
+ rowHeight?: number;
42
+ /** Left out, 16, the component default. */
43
+ gap?: number;
44
+ /** Draws `et-grid-item-default-actions` in every item, as a registered `actionsComponent` does. */
45
+ actions?: boolean;
46
+ /** The drop placeholder (`.et-grid-ghost`) at the dragged item's target slot. */
47
+ ghost?: GridMockPosition;
48
+ readOnly?: boolean;
49
+ /** Extra attributes on the host, e.g. a style or design markers. */
50
+ attributes?: string;
51
+ };
52
+
53
+ const RESIZE_EDGES = ['n', 'e', 's', 'w', 'ne', 'nw', 'se', 'sw'] as const;
54
+
55
+ /** The stylesheets the grid mock draws with: the real grid, grid item, toolbar, default actions and resize handle CSS. */
56
+ export const gridStyles = /* @__PURE__ */ [
57
+ buttonStyles,
58
+ iconBase,
59
+ iconButtonBase,
60
+ resizeHandlesStyles,
61
+ gridBase,
62
+ gridItemBase,
63
+ toolbarBase,
64
+ defaultActionsBase,
65
+ `@layer components {
66
+ .et-grid-mock-content {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: 2px;
70
+ box-sizing: border-box;
71
+ height: 100%;
72
+ padding: 12px;
73
+ }
74
+ .et-grid-mock-title {
75
+ overflow: hidden;
76
+ font-size: 1.4rem;
77
+ font-weight: 600;
78
+ white-space: nowrap;
79
+ text-overflow: ellipsis;
80
+ color: var(--et-surface-color-solid);
81
+ }
82
+ .et-grid-mock-subtitle {
83
+ font-size: 1.2rem;
84
+ color: var(--et-surface-color-muted-solid);
85
+ }
86
+ }`,
87
+ ].join('\n');
88
+
89
+ const geometryOf = (options: GridMockOptions) => {
90
+ const width = options.width ?? 448;
91
+ const columns = options.columns ?? 4;
92
+ const gap = options.gap ?? 16;
93
+ const rowHeight = options.rowHeight ?? 100;
94
+ const cellWidth = Math.max(0, (width - gap * (columns - 1)) / columns);
95
+
96
+ return { gap, rowHeight, cellWidth };
97
+ };
98
+
99
+ const rectOf = (position: GridMockPosition, geometry: ReturnType<typeof geometryOf>) => ({
100
+ x: position.col * (geometry.cellWidth + geometry.gap),
101
+ y: position.row * (geometry.rowHeight + geometry.gap),
102
+ width: position.colSpan * geometry.cellWidth + (position.colSpan - 1) * geometry.gap,
103
+ height: position.rowSpan * geometry.rowHeight + (position.rowSpan - 1) * geometry.gap,
104
+ });
105
+
106
+ const styled = (css: string) => ` style="${css}"`;
107
+
108
+ const sizeStyle = (rect: { x: number; y: number; width: number; height: number }) =>
109
+ styled(`translate: ${rect.x}px ${rect.y}px; width: ${rect.width}px; height: ${rect.height}px;`);
110
+
111
+ const removeAction = (item: GridMockItem) =>
112
+ `<div etGridItemAction><et-grid-item-default-actions><et-grid-item-toolbar class="et-grid-item-toolbar"><button aria-label="Remove ${item.title}" type="button" class="et-grid-item-default-actions__remove et-surface-interactive et-color-interactive et-icon-button et-focus-ring et-color--inherited" data-variant="transparent" data-size="xs"${item.removeForce ? ` data-et-force="${item.removeForce}"` : ''}><div class="et-icon-button-icon">${iconMarkup(TIMES_ICON)}</div></button></et-grid-item-toolbar></et-grid-item-default-actions></div>`;
113
+
114
+ const gridItem = (item: GridMockItem, options: GridMockOptions) => {
115
+ const geometry = geometryOf(options);
116
+ const slot = rectOf(item, geometry);
117
+ const rect =
118
+ item.state === 'dragging' && item.offset ? { ...slot, x: slot.x + item.offset.x, y: slot.y + item.offset.y } : slot;
119
+ const classes = [
120
+ 'et-grid-item',
121
+ 'et-surface--inherited',
122
+ item.state === 'dragging' && 'et-grid-item--dragging et-grid-item--direct',
123
+ item.state === 'resizing' && 'et-grid-item--resizing',
124
+ ]
125
+ .filter(Boolean)
126
+ .join(' ');
127
+ const handles = RESIZE_EDGES.map((edge) => `<div class="et-resize-handle et-resize-handle--${edge}"></div>`).join('');
128
+ const subtitle = item.subtitle ? `<div class="et-grid-mock-subtitle">${item.subtitle}</div>` : '';
129
+
130
+ return [
131
+ `<et-grid-item class="${classes}" data-et-surface-fill role="group" aria-label="${item.title}" tabindex="0" ${sizeStyle(rect)}${item.force ? ` data-et-force="${item.force}"` : ''}>`,
132
+ `<div class="et-grid-item__content"><div class="et-grid-mock-content"><div class="et-grid-mock-title">${item.title}</div>${subtitle}</div></div>`,
133
+ `<et-resize-handles class="et-resize-handles"${item.activeEdge ? ` data-active-edge="${item.activeEdge}"` : ''}${options.readOnly ? ' inert=""' : ''}>${handles}</et-resize-handles>`,
134
+ `<div class="et-grid-item__actions">${options.actions ? removeAction(item) : ''}</div>`,
135
+ `</et-grid-item>`,
136
+ ].join('');
137
+ };
138
+
139
+ /** Draws an `et-grid` with its items laid out by the grid maths, at rest or mid-drag or mid-resize. */
140
+ export const grid = (options: GridMockOptions) => {
141
+ const geometry = geometryOf(options);
142
+ const rows = Math.max(0, ...options.items.map((item) => item.row + item.rowSpan));
143
+ const height = rows <= 0 ? 0 : rows * geometry.rowHeight + (rows - 1) * geometry.gap;
144
+ const classes = ['et-grid', options.readOnly && 'et-grid--readonly'].filter(Boolean).join(' ');
145
+ const ghost = options.ghost ? `<div class="et-grid-ghost" ${sizeStyle(rectOf(options.ghost, geometry))}></div>` : '';
146
+
147
+ return `<et-grid class="${classes}" role="region" aria-label="Dashboard" ${styled(`height: ${height}px; --et-grid-gap: ${geometry.gap}px;`)} ${options.attributes ?? ''}>${options.items.map((item) => gridItem(item, options)).join('')}${ghost}</et-grid>`;
148
+ };
@@ -0,0 +1,19 @@
1
+ /// <reference types="vite/client" />
2
+ import { IconDefinition } from '../src/lib/icon/headless/icon-definition';
3
+
4
+ const modules = /* @__PURE__ */ import.meta.glob<Record<string, unknown>>(
5
+ ['../src/lib/icon/headless/*-icon.ts', '../src/lib/icon/headless/*-icons.ts'],
6
+ { eager: true },
7
+ );
8
+
9
+ const isIconDefinition = (value: unknown): value is IconDefinition =>
10
+ !!value &&
11
+ typeof value === 'object' &&
12
+ typeof (value as IconDefinition).name === 'string' &&
13
+ typeof (value as IconDefinition).data === 'string';
14
+
15
+ /** Every icon the SDK ships, read from the icon source files and sorted by name. */
16
+ export const SDK_ICONS: readonly IconDefinition[] = /* @__PURE__ */ Object.values(modules)
17
+ .flatMap((module) => Object.values(module))
18
+ .filter(isIconDefinition)
19
+ .sort((a, b) => a.name.localeCompare(b.name));
package/design/icon.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { IconDefinition } from '../src/lib/icon/headless/icon-definition';
2
+
3
+ /** Draws `<i etIcon>` as the icon directive renders it: the icon's classes around its trimmed SVG. */
4
+ export const iconMarkup = (icon: IconDefinition, className?: string) => {
5
+ const base = `et-icon et-icon--${icon.name}`;
6
+ const classes = [className, base, icon.variant ? `${base}--${icon.variant}` : undefined].filter(Boolean).join(' ');
7
+
8
+ return `<i etIcon="${icon.name}" aria-hidden="true" class="${classes}">${icon.data.trim()}</i>`;
9
+ };