@ethlete/components 1.0.0-next.78 → 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 (252) hide show
  1. package/CHANGELOG.md +113 -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 +4 -1
  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/grid.ts +148 -0
  24. package/design/input.ts +86 -0
  25. package/design/kbd.ts +19 -0
  26. package/design/loader.ts +152 -0
  27. package/design/masonry.ts +115 -0
  28. package/design/match.ts +131 -0
  29. package/design/menu.ts +143 -0
  30. package/design/notification.ts +129 -0
  31. package/design/otp-input.ts +107 -0
  32. package/design/pagination.ts +120 -0
  33. package/design/picture.ts +80 -0
  34. package/design/progress-steps.ts +79 -0
  35. package/design/query-error.ts +60 -0
  36. package/design/radio-group.ts +132 -0
  37. package/design/scheduler.ts +369 -0
  38. package/design/scrollable.ts +218 -0
  39. package/design/scrollbar.ts +47 -0
  40. package/design/sdk/assets/fallback.svg +1 -0
  41. package/design/sdk/assets/tall.svg +1 -0
  42. package/design/sdk/assets/wide.svg +1 -0
  43. package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
  44. package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
  45. package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
  46. package/design/sdk/components/accordion/accordion.css +17 -0
  47. package/design/sdk/components/accordion/accordion.ts +64 -0
  48. package/design/sdk/components/avatar/avatar.css +14 -0
  49. package/design/sdk/components/avatar/avatar.ts +78 -0
  50. package/design/sdk/components/badge/badge.css +13 -0
  51. package/design/sdk/components/badge/badge.ts +52 -0
  52. package/design/sdk/components/banner/banner.css +18 -0
  53. package/design/sdk/components/banner/banner.ts +87 -0
  54. package/design/sdk/components/bracket/bracket.css +59 -0
  55. package/design/sdk/components/bracket/bracket.ts +143 -0
  56. package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
  57. package/design/sdk/components/breadcrumb/breadcrumb.ts +81 -0
  58. package/design/sdk/components/button/button.css +33 -0
  59. package/design/sdk/components/button/button.ts +50 -7
  60. package/design/sdk/components/calendar/calendar.css +33 -0
  61. package/design/sdk/components/calendar/calendar.ts +96 -0
  62. package/design/sdk/components/card/card.css +19 -0
  63. package/design/sdk/components/card/card.ts +61 -0
  64. package/design/sdk/components/carousel/carousel.css +44 -0
  65. package/design/sdk/components/carousel/carousel.ts +74 -0
  66. package/design/sdk/components/chart/chart.css +56 -0
  67. package/design/sdk/components/chart/chart.ts +98 -0
  68. package/design/sdk/components/chip/chip.css +18 -0
  69. package/design/sdk/components/chip/chip.ts +76 -0
  70. package/design/sdk/components/copy-button/copy-button.css +14 -0
  71. package/design/sdk/components/copy-button/copy-button.ts +59 -0
  72. package/design/sdk/components/description-list/description-list.css +7 -0
  73. package/design/sdk/components/description-list/description-list.ts +53 -0
  74. package/design/sdk/components/dialog/dialog.css +29 -0
  75. package/design/sdk/components/dialog/dialog.ts +78 -0
  76. package/design/sdk/components/divider/divider.css +26 -0
  77. package/design/sdk/components/divider/divider.ts +43 -0
  78. package/design/sdk/components/empty-state/empty-state.css +15 -0
  79. package/design/sdk/components/empty-state/empty-state.ts +56 -0
  80. package/design/sdk/components/floating-action/floating-action.css +51 -0
  81. package/design/sdk/components/floating-action/floating-action.ts +63 -0
  82. package/design/sdk/components/form-field/form-field.ts +23 -5
  83. package/design/sdk/components/grid/grid.css +17 -0
  84. package/design/sdk/components/grid/grid.ts +80 -0
  85. package/design/sdk/components/input/input.css +75 -0
  86. package/design/sdk/components/input/input.ts +79 -0
  87. package/design/sdk/components/kbd/kbd.css +25 -0
  88. package/design/sdk/components/kbd/kbd.ts +57 -0
  89. package/design/sdk/components/loader/loader.css +37 -0
  90. package/design/sdk/components/loader/loader.ts +68 -0
  91. package/design/sdk/components/masonry/masonry.css +7 -0
  92. package/design/sdk/components/masonry/masonry.ts +42 -0
  93. package/design/sdk/components/match/match.css +25 -0
  94. package/design/sdk/components/match/match.ts +76 -0
  95. package/design/sdk/components/menu/menu.css +22 -0
  96. package/design/sdk/components/menu/menu.ts +91 -0
  97. package/design/sdk/components/notification/notification.css +32 -0
  98. package/design/sdk/components/notification/notification.ts +106 -0
  99. package/design/sdk/components/otp-input/otp-input.css +35 -0
  100. package/design/sdk/components/otp-input/otp-input.ts +64 -0
  101. package/design/sdk/components/pagination/pagination.css +14 -0
  102. package/design/sdk/components/pagination/pagination.ts +75 -0
  103. package/design/sdk/components/picture/picture.css +37 -0
  104. package/design/sdk/components/picture/picture.ts +96 -0
  105. package/design/sdk/components/progress-steps/progress-steps.css +37 -0
  106. package/design/sdk/components/progress-steps/progress-steps.ts +91 -0
  107. package/design/sdk/components/query-error/query-error.css +33 -0
  108. package/design/sdk/components/query-error/query-error.ts +120 -0
  109. package/design/sdk/components/scheduler/scheduler.css +55 -0
  110. package/design/sdk/components/scheduler/scheduler.ts +239 -0
  111. package/design/sdk/components/scrollable/scrollable.css +58 -0
  112. package/design/sdk/components/scrollable/scrollable.ts +133 -0
  113. package/design/sdk/components/scrollbar/scrollbar.css +78 -0
  114. package/design/sdk/components/scrollbar/scrollbar.ts +123 -0
  115. package/design/sdk/components/select/select.ts +1 -1
  116. package/design/sdk/components/select/shared/select-part.ts +16 -1
  117. package/design/sdk/components/select-panel/select-panel.css +3 -0
  118. package/design/sdk/components/select-panel/select-panel.ts +124 -0
  119. package/design/sdk/components/skeleton/skeleton.css +22 -0
  120. package/design/sdk/components/skeleton/skeleton.ts +50 -0
  121. package/design/sdk/components/slider/slider.css +52 -0
  122. package/design/sdk/components/slider/slider.ts +86 -0
  123. package/design/sdk/components/standings/standings.css +33 -0
  124. package/design/sdk/components/standings/standings.ts +130 -0
  125. package/design/sdk/components/stat-tile/stat-tile.css +15 -0
  126. package/design/sdk/components/stat-tile/stat-tile.ts +84 -0
  127. package/design/sdk/components/stream/stream.css +48 -0
  128. package/design/sdk/components/stream/stream.ts +38 -0
  129. package/design/sdk/components/switch/switch.css +35 -0
  130. package/design/sdk/components/switch/switch.ts +63 -0
  131. package/design/sdk/components/table/table.css +67 -0
  132. package/design/sdk/components/table/table.ts +160 -0
  133. package/design/sdk/components/tabs/tabs.css +13 -0
  134. package/design/sdk/components/tabs/tabs.ts +74 -0
  135. package/design/sdk/components/textarea/textarea.css +116 -0
  136. package/design/sdk/components/textarea/textarea.ts +64 -0
  137. package/design/sdk/components/timeline/timeline.css +30 -0
  138. package/design/sdk/components/timeline/timeline.ts +87 -0
  139. package/design/sdk/components/toolbar/toolbar.css +24 -0
  140. package/design/sdk/components/toolbar/toolbar.ts +87 -0
  141. package/design/sdk/components/tooltip/tooltip.css +15 -0
  142. package/design/sdk/components/tooltip/tooltip.ts +28 -0
  143. package/design/sdk/components/tree/selected-tint.css +15 -0
  144. package/design/sdk/components/tree/tree.ts +70 -0
  145. package/design/sdk/foundations/colors/colors.css +108 -4
  146. package/design/sdk/foundations/elevation/elevation.css +6 -0
  147. package/design/sdk/foundations/elevation/elevation.ts +11 -0
  148. package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
  149. package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
  150. package/design/sdk/foundations/icons/icons.ts +119 -0
  151. package/design/skeleton.ts +67 -0
  152. package/design/slider.ts +155 -0
  153. package/design/standings.ts +161 -0
  154. package/design/stat-tile.ts +109 -0
  155. package/design/stream.ts +92 -0
  156. package/design/switch.ts +83 -0
  157. package/design/table.ts +302 -0
  158. package/design/tabs.ts +75 -0
  159. package/design/textarea.ts +92 -0
  160. package/design/timeline.ts +52 -0
  161. package/design/toolbar.ts +95 -0
  162. package/design/tooltip.ts +87 -0
  163. package/fesm2022/ethlete-components.mjs +228 -187
  164. package/fesm2022/ethlete-components.mjs.map +1 -1
  165. package/package.json +1 -1
  166. package/src/lib/accordion/accordion.component.css +2 -1
  167. package/src/lib/avatar/avatar.component.css +10 -0
  168. package/src/lib/badge/badge.component.css +2 -2
  169. package/src/lib/banner/banner.component.css +3 -1
  170. package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
  171. package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
  172. package/src/lib/button/button.component.css +19 -0
  173. package/src/lib/button/icon-button.component.css +19 -20
  174. package/src/lib/button/split-button.component.css +5 -1
  175. package/src/lib/calendar/calendar.component.css +13 -3
  176. package/src/lib/card/card.component.css +4 -0
  177. package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
  178. package/src/lib/carousel/carousel.component.css +2 -2
  179. package/src/lib/chart/chart-axis.component.css +3 -3
  180. package/src/lib/chip/chip.component.css +8 -2
  181. package/src/lib/description-list/description-list.component.css +2 -1
  182. package/src/lib/empty-state/empty-state.component.css +4 -0
  183. package/src/lib/floating-action/floating-action-styles.component.css +27 -0
  184. package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
  185. package/src/lib/forms/checkbox/checkbox.component.css +31 -5
  186. package/src/lib/forms/color-input/color-input.component.css +3 -1
  187. package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
  188. package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
  189. package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
  190. package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
  191. package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
  192. package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
  193. package/src/lib/forms/description/description.component.css +7 -0
  194. package/src/lib/forms/dropzone/dropzone.component.css +26 -0
  195. package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
  196. package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +54 -5
  197. package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
  198. package/src/lib/forms/form-field/form-field.component.css +6 -0
  199. package/src/lib/forms/form-field/headless/label.directive.css +1 -1
  200. package/src/lib/forms/input/input.component.css +6 -2
  201. package/src/lib/forms/input/number-input.component.css +2 -2
  202. package/src/lib/forms/input/password-input.component.css +4 -3
  203. package/src/lib/forms/otp-input/otp-input.component.css +23 -4
  204. package/src/lib/forms/phone-input/phone-input.component.css +4 -3
  205. package/src/lib/forms/rating/rating.component.css +2 -1
  206. package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
  207. package/src/lib/forms/selection-card-styles.component.css +3 -2
  208. package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
  209. package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
  210. package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
  211. package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
  212. package/src/lib/forms/slider/range-slider.component.css +98 -6
  213. package/src/lib/forms/slider/slider.component.css +96 -4
  214. package/src/lib/forms/switch/switch.component.css +47 -4
  215. package/src/lib/forms/tag-input/tag-input.component.css +2 -2
  216. package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
  217. package/src/lib/forms/textarea/textarea.component.css +7 -2
  218. package/src/lib/grid/grid-item-toolbar.component.css +10 -0
  219. package/src/lib/grid/grid-item.component.css +6 -1
  220. package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
  221. package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
  222. package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
  223. package/src/lib/match/match-card.component.css +9 -3
  224. package/src/lib/match/match-score.component.css +4 -1
  225. package/src/lib/menu/menu-selection-item.component.css +1 -1
  226. package/src/lib/menu/menu.component.css +5 -0
  227. package/src/lib/overlay/overlay-container.component.css +4 -0
  228. package/src/lib/pagination/pagination.component.css +4 -0
  229. package/src/lib/progress-steps/progress-step.component.css +4 -4
  230. package/src/lib/query-error/query-error.component.css +4 -0
  231. package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
  232. package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
  233. package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
  234. package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
  235. package/src/lib/standings/standings-pick.component.css +1 -1
  236. package/src/lib/standings/standings.component.css +10 -10
  237. package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
  238. package/src/lib/stream/consent/stream-consent.component.css +99 -0
  239. package/src/lib/stream/error/stream-player-error.component.css +100 -0
  240. package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
  241. package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
  242. package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
  243. package/src/lib/table/table-resize-grip.component.css +2 -1
  244. package/src/lib/table/table-select-cell.component.css +45 -15
  245. package/src/lib/table/table.component.css +15 -5
  246. package/src/lib/tabs/tab-bar-styles.component.css +1 -1
  247. package/src/lib/tabs/tabs/tab-group.component.css +111 -0
  248. package/src/lib/time-picker/time-picker.component.css +2 -1
  249. package/src/lib/timeline/timeline-item.component.css +5 -1
  250. package/src/lib/toolbar/toolbar.component.css +4 -0
  251. package/src/lib/tooltip/tooltip.component.css +14 -0
  252. package/types/ethlete-components.d.ts +11 -2
@@ -0,0 +1,101 @@
1
+ .sdk-elevation {
2
+ box-sizing: border-box;
3
+ width: max-content;
4
+ padding: 4rem;
5
+ background: var(--et-surface-background-solid);
6
+ color: var(--et-surface-color-solid);
7
+ font-size: 1.4rem;
8
+ }
9
+
10
+ .sdk-elevation-row {
11
+ display: flex;
12
+ gap: 4rem;
13
+ align-items: flex-start;
14
+ }
15
+
16
+ .sdk-elevation-card,
17
+ .sdk-elevation-panel,
18
+ .sdk-elevation-pane-panel {
19
+ --sdk-elevation-edge: var(--et-surface-border-solid);
20
+ --sdk-elevation-highlight: 0 0 0 0 transparent;
21
+
22
+ box-sizing: border-box;
23
+ border: 0.1rem solid var(--sdk-elevation-edge);
24
+ background: var(--et-surface-background-solid);
25
+ color: var(--et-surface-color-solid);
26
+ box-shadow: var(--sdk-elevation-highlight), var(--sdk-elevation-shadow);
27
+ }
28
+
29
+ .sdk-elevation-card {
30
+ --sdk-elevation-shadow:
31
+ 0 0.3rem 0.8rem rgb(var(--et-shadow-color-rgb) / 0.2), 0 0.1rem 0.3rem rgb(var(--et-shadow-color-rgb) / 0.12);
32
+
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: 0.4rem;
36
+ width: 20rem;
37
+ padding: 1.6rem;
38
+ border-radius: 1.2rem;
39
+ }
40
+
41
+ .sdk-elevation-panel {
42
+ --sdk-elevation-shadow:
43
+ 0 0.6rem 1.2rem rgb(var(--et-shadow-color-rgb) / 0.22), 0 0.2rem 0.4rem rgb(var(--et-shadow-color-rgb) / 0.14);
44
+
45
+ display: flex;
46
+ flex-direction: column;
47
+ gap: 0.6rem;
48
+ width: 28rem;
49
+ padding: 2rem;
50
+ border-radius: 1.6rem;
51
+ }
52
+
53
+ .sdk-elevation-pane-panel {
54
+ --sdk-elevation-shadow: var(--et-anchored-panel-shadow, 0 1rem 2.4rem rgb(var(--et-shadow-color-rgb) / 0.16));
55
+
56
+ width: 22rem;
57
+ }
58
+
59
+ .sdk-elevation-pane {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: 0.8rem;
63
+ }
64
+
65
+ .sdk-elevation-label {
66
+ color: var(--et-surface-color-muted-solid);
67
+ font-size: 1.2rem;
68
+ }
69
+
70
+ .sdk-elevation-muted {
71
+ color: var(--et-surface-color-muted-solid);
72
+ }
73
+
74
+ .sdk-elevation-line {
75
+ height: 3.2rem;
76
+ margin-top: 0.8rem;
77
+ border-radius: 0.6rem;
78
+ background: color-mix(in srgb, var(--et-surface-interaction-solid) 12%, transparent);
79
+ }
80
+
81
+ .sdk-elevation-line--short {
82
+ width: 60%;
83
+ margin-top: 0;
84
+ }
85
+
86
+ .sdk-elevation-stack {
87
+ position: relative;
88
+ width: 40rem;
89
+ height: 30rem;
90
+ }
91
+
92
+ .sdk-elevation-stack .sdk-elevation-panel {
93
+ width: 32rem;
94
+ height: 22rem;
95
+ }
96
+
97
+ .sdk-elevation-pane--over {
98
+ position: absolute;
99
+ top: 12rem;
100
+ left: 16rem;
101
+ }
@@ -0,0 +1,74 @@
1
+ import { selectOption, selectPanel, selectStyles } from '@ethlete/components/design/select';
2
+ import { drawing, html } from '@design-system';
3
+ import sceneStyles from './scene.css?inline';
4
+
5
+ export type ElevationProps = { scene: 'overview' | 'stacked' };
6
+
7
+ /** The variant's class for each elevated thing. */
8
+ type ElevationEdges = { card: string; panel: string; pane: string };
9
+
10
+ const OPTIONS = [
11
+ { value: 'drafts', label: 'Drafts' },
12
+ { value: 'review', label: 'In review' },
13
+ { value: 'merged', label: 'Merged' },
14
+ { value: 'archived', label: 'Archived' },
15
+ ];
16
+
17
+ const pane = (id: string, edge: string) =>
18
+ selectPanel({
19
+ id,
20
+ color: 'brand',
21
+ content: OPTIONS.map((option) =>
22
+ selectOption(option, {
23
+ id: `${id}-${option.value}`,
24
+ selected: option.value === 'review',
25
+ active: option.value === 'merged' ? 'keyboard' : undefined,
26
+ }),
27
+ ).join(''),
28
+ }).replace(
29
+ '<et-select-panel class="',
30
+ `<et-select-panel data-et-surface-fill class="sdk-elevation-pane-panel ${edge} `,
31
+ );
32
+
33
+ const card = (edge: string) =>
34
+ html`<article class="sdk-elevation-card ${edge} et-surface--inherited" data-et-surface-fill>
35
+ <span class="sdk-elevation-label">Card</span>
36
+ <strong>Season 2026</strong>
37
+ <span class="sdk-elevation-muted">12 matches, 3 open</span>
38
+ </article>`;
39
+
40
+ const panel = (edge: string) =>
41
+ html`<section class="sdk-elevation-panel ${edge} et-surface--inherited" data-et-surface-fill>
42
+ <span class="sdk-elevation-label">Panel</span>
43
+ <strong>Edit match</strong>
44
+ <span class="sdk-elevation-muted">Kick-off, venue and referee</span>
45
+ <div class="sdk-elevation-line"></div>
46
+ <div class="sdk-elevation-line sdk-elevation-line--short"></div>
47
+ </section>`;
48
+
49
+ const overview = (edges: ElevationEdges) =>
50
+ html`<div class="sdk-elevation-row">
51
+ ${card(edges.card)} ${panel(edges.panel)}
52
+ <div class="sdk-elevation-pane">
53
+ <span class="sdk-elevation-label">Overlay pane</span>
54
+ ${pane('overview', edges.pane)}
55
+ </div>
56
+ </div>`;
57
+
58
+ const stacked = (edges: ElevationEdges) =>
59
+ html`<div class="sdk-elevation-stack">
60
+ ${panel(edges.panel)}
61
+ <div class="sdk-elevation-pane sdk-elevation-pane--over">${pane('stacked', edges.pane)}</div>
62
+ </div>`;
63
+
64
+ /** Draws the elevated things of one scene on the base surface, each with its class from `edges`. */
65
+ export const elevationScene = ({ scene }: ElevationProps, edges: ElevationEdges, styles: string) =>
66
+ drawing({
67
+ body: html`<div class="sdk-elevation">${scene === 'overview' ? overview(edges) : stacked(edges)}</div>`,
68
+ styles: [selectStyles, sceneStyles, styles].join('\n'),
69
+ });
70
+
71
+ export const ELEVATION_STATES = {
72
+ overview: { scene: 'overview' },
73
+ stacked: { scene: 'stacked' },
74
+ } satisfies Record<string, ElevationProps>;
@@ -0,0 +1,119 @@
1
+ import { SDK_ICONS } from '@ethlete/components/design/icon-set';
2
+ import { definePart, iconSheet } from '@design-system';
3
+
4
+ const GRID = 16;
5
+
6
+ const PADDING = 1;
7
+
8
+ const svg = (body: string) =>
9
+ `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`;
10
+
11
+ const FILL = 'fill="currentColor" stroke="none"';
12
+
13
+ const REDRAWN: Record<string, string> = {
14
+ 'et-arrow-out-up-right': svg(
15
+ '<path d="M5.5 5.5H4A1.5 1.5 0 0 0 2.5 7v5A1.5 1.5 0 0 0 4 13.5h5a1.5 1.5 0 0 0 1.5-1.5v-1.5"/><path d="M9.5 2.5h4v4M13.5 2.5l-6 6"/>',
16
+ ),
17
+ 'et-arrow-right': svg('<path d="M2.5 8.5h11M9 4l4.5 4.5L9 13"/>'),
18
+ 'et-arrow-up': svg('<path d="M8.5 13.5v-11M4 7l4.5-4.5L13 7"/>'),
19
+ 'et-arrows-left-right': svg('<path d="M2 8.5h12M5.5 5 2 8.5 5.5 12M10.5 5 14 8.5 10.5 12"/>'),
20
+ 'et-calendar': svg('<rect x="2.5" y="3.5" width="11" height="10" rx="1.5"/><path d="M5.5 2v3M10.5 2v3M2.5 6.5h11"/>'),
21
+ 'et-check': svg('<path d="M2.5 8.5 6 12l7.5-7.5"/>'),
22
+ 'et-chevron': svg('<path d="M3 10.5 8 5.5l5 5"/>'),
23
+ 'et-circle-check': svg('<circle cx="8" cy="8" r="6.25"/><path d="M5.25 8.25 7.2 10.2 10.75 6.5"/>'),
24
+ 'et-circle-info': svg(
25
+ `<circle cx="8" cy="8" r="6.25"/><path d="M8 7.25V11"/><circle cx="8" cy="4.75" r=".85" ${FILL}/>`,
26
+ ),
27
+ 'et-clipboard-check': svg(
28
+ '<path d="M5.5 3.5H4A1.5 1.5 0 0 0 2.5 5v7A1.5 1.5 0 0 0 4 13.5h8a1.5 1.5 0 0 0 1.5-1.5V5A1.5 1.5 0 0 0 12 3.5h-1.5"/><rect x="5.5" y="2" width="5" height="2.5" rx=".75"/><path d="M5.5 9 7.25 10.75 10.5 7.5"/>',
29
+ ),
30
+ 'et-clock': svg('<circle cx="8" cy="8" r="6.25"/><path d="M8 4.5V8l2.5 1.5"/>'),
31
+ 'et-ellipsis': svg(
32
+ `<circle cx="3" cy="8" r="1.25" ${FILL}/><circle cx="8" cy="8" r="1.25" ${FILL}/><circle cx="13" cy="8" r="1.25" ${FILL}/>`,
33
+ ),
34
+ 'et-ellipsis-vertical': svg(
35
+ `<circle cx="8" cy="3" r="1.25" ${FILL}/><circle cx="8" cy="8" r="1.25" ${FILL}/><circle cx="8" cy="13" r="1.25" ${FILL}/>`,
36
+ ),
37
+ 'et-eye': svg(
38
+ '<path d="M1.75 8C3 5.5 5.25 3.5 8 3.5s5 2 6.25 4.5C13 10.5 10.75 12.5 8 12.5S3 10.5 1.75 8Z"/><circle cx="8" cy="8" r="2"/>',
39
+ ),
40
+ 'et-eye-slash': svg(
41
+ '<mask id="et-eye-slash-cut"><rect width="16" height="16" fill="#fff"/><path d="M2.5 2.5l11 11" stroke="#000" stroke-width="4.2"/></mask><g mask="url(#et-eye-slash-cut)"><path d="M1.75 8C3 5.5 5.25 3.5 8 3.5s5 2 6.25 4.5C13 10.5 10.75 12.5 8 12.5S3 10.5 1.75 8Z"/><circle cx="8" cy="8" r="2"/></g><path d="M2.5 2.5l11 11"/>',
42
+ ),
43
+ 'et-eyedropper': svg(
44
+ '<path d="M2 14l.67-.67h2l5.67-5.67"/><path d="M2.67 13.33v-2l5.67-5.67"/><path d="M10 4l1.93-1.93a1.37 1.37 0 0 1 1.93 1.93L11.93 5.93l.27.27a1.37 1.37 0 0 1-1.93 1.93l-2.4-2.4a1.37 1.37 0 0 1 1.93-1.93l.2.2Z"/>',
45
+ ),
46
+ 'et-file': svg(
47
+ '<path d="M9 2H5a1.5 1.5 0 0 0-1.5 1.5v9A1.5 1.5 0 0 0 5 14h6a1.5 1.5 0 0 0 1.5-1.5V5.5M9 2l3.5 3.5M9 2v3.5h3.5"/>',
48
+ ),
49
+ 'et-floppy-disk': svg(
50
+ '<path d="M2.5 2.5H11l2.5 2.5v7a1.5 1.5 0 0 1-1.5 1.5H4A1.5 1.5 0 0 1 2.5 12Z"/><path d="M5.5 2.5v3h4v-3M5.5 10.5h5"/>',
51
+ ),
52
+ 'et-focus-frame': svg(
53
+ `<rect x="2.5" y="2.5" width="11" height="11" rx="1.5"/><rect x="5.5" y="5.5" width="5" height="5" rx=".75" ${FILL}/>`,
54
+ ),
55
+ 'et-grid-2x2': svg('<rect x="2.5" y="2.5" width="11" height="11" rx="1.5"/><path d="M8 2.5v11M2.5 8h11"/>'),
56
+ 'et-image': svg(
57
+ `<rect x="1.5" y="2.5" width="13" height="11" rx="1.5"/><circle cx="5.25" cy="5.75" r="1.1" ${FILL}/><path d="M3.75 11 6.5 8l1.6 1.75L10 6.5l2.25 4.5Z" ${FILL}/>`,
58
+ ),
59
+ 'et-location': svg(
60
+ '<path d="M8 14.25s-4.75-4.2-4.75-7.75a4.75 4.75 0 0 1 9.5 0c0 3.55-4.75 7.75-4.75 7.75Z"/><circle cx="8" cy="6.5" r="1.75"/>',
61
+ ),
62
+ 'et-lock': svg(
63
+ `<path d="M5.5 7.5V4.75a2.5 2.5 0 0 1 5 0V7.5"/><rect x="2.5" y="7.5" width="11" height="6" rx="1.5"/><circle cx="8" cy="10.5" r="1" ${FILL}/>`,
64
+ ),
65
+ 'et-minus': svg('<path d="M3.5 8.5h10"/>'),
66
+ 'et-pause': svg(
67
+ `<rect x="4" y="3" width="3" height="10" rx=".75" ${FILL}/><rect x="9" y="3" width="3" height="10" rx=".75" ${FILL}/>`,
68
+ ),
69
+ 'et-pencil': svg(
70
+ '<path d="M2.5 13.5l.75-3.1L9.6 4.05a1.3 1.3 0 0 1 1.85 0l.5.5a1.3 1.3 0 0 1 0 1.85L5.6 12.75Z"/><path d="M8.5 5.25l2.25 2.25"/>',
71
+ ),
72
+ 'et-play': svg('<path d="M5 3.5v9l7.5-4.5Z" fill="currentColor"/>'),
73
+ 'et-plus': svg('<path d="M8.5 3.5v10M3.5 8.5h10"/>'),
74
+ 'et-quote': svg(
75
+ `<path d="M6.5 4.5C4.5 5.17 3.5 6.83 3.5 8.83V11.5H7V8H5.17c0-1.33.47-2.2 1.33-2.67Z" ${FILL}/><path d="M12.5 4.5c-2 .67-3 2.33-3 4.33v2.67H13V8h-1.83c0-1.33.47-2.2 1.33-2.67Z" ${FILL}/>`,
76
+ ),
77
+ 'et-redo': svg('<path d="M10 10l3.5-3.5L10 3M13.5 6.5h-7a3.5 3.5 0 0 0 0 7h2"/>'),
78
+ 'et-rotate-right': svg(
79
+ '<path d="M2.75 6A5.5 5.5 0 0 1 12.25 4M13.5 2v4h-4M13.25 10A5.5 5.5 0 0 1 3.75 12M2.5 14v-4h4"/>',
80
+ ),
81
+ 'et-star': svg(
82
+ '<path d="M8 2.5l1.62 3.88 4.18.33-3.18 2.74.97 4.09L8 11.35l-3.59 2.19.97-4.09L2.2 6.71l4.18-.33Z" fill="currentColor"/>',
83
+ ),
84
+ 'et-thumbtack': svg('<path d="M6 2.5h4M6.75 2.5v3.75L4.5 9.5h7L9.25 6.25V2.5M8 9.5v4"/>'),
85
+ 'et-times': svg('<path d="M4 4l8 8M12 4l-8 8"/>'),
86
+ 'et-trash': svg(
87
+ '<path d="M2.5 4h11M6 4V2.75A.75.75 0 0 1 6.75 2h2.5a.75.75 0 0 1 .75.75V4M3.75 4l.7 8.75A1.25 1.25 0 0 0 5.7 14h4.6a1.25 1.25 0 0 0 1.25-1.25l.7-8.75M6.5 7v4M9.5 7v4"/>',
88
+ ),
89
+ 'et-triangle-exclamation': svg(
90
+ `<path d="M8 1.75 14.25 13.75H1.75Z"/><path d="M8 6.25v3"/><circle cx="8" cy="11.4" r=".85" ${FILL}/>`,
91
+ ),
92
+ 'et-trophy': svg(
93
+ '<path d="M4.5 2.5h7V6a3.5 3.5 0 0 1-7 0Z"/><path d="M4.5 3.5h-2v1a2.5 2.5 0 0 0 2.2 2.48M11.5 3.5h2v1a2.5 2.5 0 0 1-2.2 2.48M8 9.5v2M5 13.5h6l-.5-2h-5Z"/>',
94
+ ),
95
+ 'et-undo': svg('<path d="M6 10 2.5 6.5 6 3M2.5 6.5h7a3.5 3.5 0 0 1 0 7h-2"/>'),
96
+ 'et-upload': svg(
97
+ '<path d="M8 10V2.5M4.5 6 8 2.5 11.5 6M2.5 10.5V12A1.5 1.5 0 0 0 4 13.5h8a1.5 1.5 0 0 0 1.5-1.5v-1.5"/>',
98
+ ),
99
+ };
100
+
101
+ const icons = SDK_ICONS.map((icon) => {
102
+ const name = icon.variant ? `${icon.name}--${icon.variant}` : icon.name;
103
+
104
+ return { name, svg: REDRAWN[name] ?? icon.data, grid: GRID, padding: PADDING };
105
+ });
106
+
107
+ const titles = {
108
+ catalogue: `Icons: the ${SDK_ICONS.length} icons the SDK ships, at each size a component draws`,
109
+ construction: `Every icon on the ${GRID} px candidate grid: pixel lines, centre lines, and the ${PADDING} px padding`,
110
+ };
111
+
112
+ type View = 'catalogue' | 'construction';
113
+
114
+ export default definePart<{ view: View }>({
115
+ note: "Today's look",
116
+ madeBy: ['claude-opus-5-5'],
117
+ states: { catalogue: { view: 'catalogue' }, construction: { view: 'construction' } },
118
+ render: ({ view }) => iconSheet({ view, title: titles[view], icons, sizes: [16, 20, 24] }),
119
+ });
@@ -0,0 +1,67 @@
1
+ import skeletonBase from '../src/lib/skeleton/skeleton.component.css?inline';
2
+
3
+ export type SkeletonShapeMock = 'text' | 'rect' | 'circle';
4
+
5
+ export type SkeletonItemMockOptions = {
6
+ /** Left out, `text`, as `et-skeleton-item` defaults to. */
7
+ shape?: SkeletonShapeMock;
8
+ /** Inline style on the item, e.g. `--et-skeleton-size: 40px` or `block-size: 140px`. */
9
+ style?: string;
10
+ };
11
+
12
+ export type SkeletonTextMockOptions = {
13
+ /** Left out, 3. */
14
+ lines?: number;
15
+ /** Width (%) of the last line. Left out, 60. */
16
+ lastLineWidth?: number;
17
+ };
18
+
19
+ export type SkeletonMockOptions = {
20
+ /** The projected content, built from `skeletonItem()`, `skeletonText()` and any layout markup. */
21
+ content: string;
22
+ /** Left out, `true`, as `et-skeleton` defaults to. */
23
+ animated?: boolean;
24
+ /** Where the shimmer is drawn, as a fraction of its sweep from 0 to 1. Left out, 0.5: the highlight centred on each bone. */
25
+ shimmerAt?: number;
26
+ /** Extra attributes on the skeleton, e.g. design markers. */
27
+ attributes?: string;
28
+ };
29
+
30
+ /** The stylesheet `skeleton()` draws with: the real skeleton CSS, plus the rule that holds the shimmer still. */
31
+ export const skeletonStyles = /* @__PURE__ */ [
32
+ skeletonBase,
33
+ `.et-skeleton[data-et-shimmer-at] .et-skeleton-item::after {
34
+ animation-play-state: paused;
35
+ animation-delay: calc(var(--et-skeleton-shimmer-at) * -1 * var(--et-skeleton-duration));
36
+ }`,
37
+ ].join('\n');
38
+
39
+ /** Draws one `et-skeleton-item` as the component renders it, as HTML. */
40
+ export const skeletonItem = (options: SkeletonItemMockOptions = {}) => {
41
+ const style = options.style ? ` style="${options.style}"` : '';
42
+
43
+ return `<et-skeleton-item class="et-skeleton-item" aria-hidden="true" data-shape="${options.shape ?? 'text'}"${style}></et-skeleton-item>`;
44
+ };
45
+
46
+ /** Draws an `et-skeleton-text` with its lines as the component renders it, as HTML. */
47
+ export const skeletonText = (options: SkeletonTextMockOptions = {}) => {
48
+ const lines = Math.max(1, Math.floor(options.lines ?? 3));
49
+ const items = Array.from({ length: lines }, (_, index) =>
50
+ skeletonItem({ style: `inline-size: ${index === lines - 1 ? (options.lastLineWidth ?? 60) : 100}%` }),
51
+ ).join('');
52
+
53
+ return `<et-skeleton-text class="et-skeleton-text">${items}</et-skeleton-text>`;
54
+ };
55
+
56
+ /** Draws an `et-skeleton` around `content` as the component renders it, as HTML, without its visually hidden label and with the shimmer held at one frame. */
57
+ export const skeleton = (options: SkeletonMockOptions) => {
58
+ const animated = options.animated ?? true;
59
+ const attributes = [
60
+ options.attributes,
61
+ `class="et-skeleton${animated ? ' et-skeleton--animated' : ''}"`,
62
+ 'role="status"',
63
+ animated && `data-et-shimmer-at style="--et-skeleton-shimmer-at: ${options.shimmerAt ?? 0.5}"`,
64
+ ].filter(Boolean);
65
+
66
+ return `<et-skeleton ${attributes.join(' ')}>${options.content}</et-skeleton>`;
67
+ };
@@ -0,0 +1,155 @@
1
+ import formSupport from '../src/lib/forms/form-field/form-support-styles.component.css?inline';
2
+ import label from '../src/lib/forms/form-field/headless/label.directive.css?inline';
3
+ import hint from '../src/lib/forms/form-field/hint.component.css?inline';
4
+ import rangeSliderBase from '../src/lib/forms/slider/range-slider.component.css?inline';
5
+ import sliderBase from '../src/lib/forms/slider/slider.component.css?inline';
6
+
7
+ /** An interaction a frame forces on a thumb with the `data-et-force` design marker. */
8
+ export type SliderMockForce = 'hover' | 'focus-visible' | 'active';
9
+
10
+ export type SliderMockMark = { value: number; label?: string };
11
+
12
+ export type SliderMockOptions = {
13
+ /** One number draws `et-slider`, a pair draws `et-range-slider` with two thumbs. */
14
+ value: number | [number, number];
15
+ min?: number;
16
+ max?: number;
17
+ /** `true` draws a tick at every `step`; a list draws the given ticks, with labels where set. */
18
+ marks?: boolean | SliderMockMark[];
19
+ step?: number;
20
+ /** The label, as HTML. */
21
+ label?: string;
22
+ /** The hint, as HTML. Hidden while an `error` shows. */
23
+ hint?: string;
24
+ /** The error message, as HTML. Draws the slider touched and invalid. */
25
+ error?: string;
26
+ /** The color theme name the app registers for errors, e.g. `danger` in Storybook. */
27
+ errorColor?: string;
28
+ /** A color theme name the app registers. */
29
+ color?: string;
30
+ required?: boolean;
31
+ disabled?: boolean;
32
+ /** View-only: the value shows, the thumb takes focus but does not move. */
33
+ readonly?: boolean;
34
+ /** An unresolved bulk-edit value: the thumbs park at the track start. */
35
+ mixed?: boolean;
36
+ mixedLabel?: string;
37
+ orientation?: 'horizontal' | 'vertical';
38
+ /** Draws the value bubble an `etSliderThumbLabel` template renders above each thumb. */
39
+ valueLabel?: boolean;
40
+ /** The thumb index that is being dragged. */
41
+ dragging?: number;
42
+ /** Forced interactions, per thumb index (a single slider uses index 0). */
43
+ force?: Partial<Record<number, SliderMockForce | SliderMockForce[]>>;
44
+ /** Unique per frame: the label and message ids derive from it. */
45
+ id?: string;
46
+ };
47
+
48
+ /** The stylesheets `slider()` draws with: the real `et-slider`, `et-range-slider` and form support CSS. */
49
+ export const sliderStyles = /* @__PURE__ */ [label, hint, formSupport, sliderBase, rangeSliderBase].join('\n');
50
+
51
+ const styled = (css: string) => ` style="${css}"`;
52
+
53
+ const forceList = (force: SliderMockForce | SliderMockForce[] | undefined) =>
54
+ force === undefined ? [] : Array.isArray(force) ? force : [force];
55
+
56
+ /** Draws `<et-slider>`, or `<et-range-slider>` for a value pair, as HTML, with the DOM the components render. */
57
+ export const slider = (options: SliderMockOptions) => {
58
+ const { id = 'slider', min = 0, max = 100, step = 1, orientation = 'horizontal' } = options;
59
+ const range = Array.isArray(options.value);
60
+ const prefix = range ? 'et-range-slider' : 'et-slider';
61
+ const [start, end] = Array.isArray(options.value) ? options.value : [min, options.value];
62
+ const values = range ? [start, end] : [end];
63
+ const shown = options.mixed ? values.map(() => min) : values;
64
+ const [shownStart, shownEnd] = options.mixed ? [min, min] : [start, end];
65
+ const percent = (value: number) => ((value - min) / (max - min)) * 100;
66
+ const ids = { hint: `et-form-field-hint-${id}`, error: `et-form-field-error-${id}` };
67
+ const labelId = options.label !== undefined ? `et-label-${id}` : null;
68
+ const invalid = options.error !== undefined;
69
+ const supportId = invalid ? ids.error : options.hint !== undefined ? ids.hint : null;
70
+ const colorClass = invalid && options.errorColor ? options.errorColor : (options.color ?? 'inherited');
71
+ const activeRange = options.mixed ? null : { start, end };
72
+
73
+ const markList: SliderMockMark[] =
74
+ options.marks === true
75
+ ? Array.from({ length: Math.floor((max - min) / step) + 1 }, (_, index) => ({ value: min + index * step }))
76
+ : options.marks || [];
77
+ const hasMarkLabels = markList.some((mark) => !!mark.label);
78
+
79
+ const hostAttributes = [
80
+ `class="${prefix} et-color--${colorClass}"`,
81
+ options.mixed && 'data-mixed="true"',
82
+ `data-orientation="${orientation}"`,
83
+ invalid && 'data-error="true"',
84
+ options.disabled && 'data-disabled="true"',
85
+ options.readonly && 'data-readonly="true"',
86
+ options.dragging !== undefined && 'data-dragging="true"',
87
+ hasMarkLabels && 'data-mark-labels="true"',
88
+ options.valueLabel && 'data-thumb-value="true"',
89
+ ].filter(Boolean);
90
+
91
+ const labelHtml = labelId
92
+ ? `<et-label id="${labelId}"${options.disabled ? ' data-disabled="true"' : ''}><span class="et-label-content">${options.label}</span>${options.required ? '<span aria-hidden="true" class="et-label-required-marker">*</span>' : ''}</et-label>`
93
+ : '';
94
+
95
+ const fillStyle = range
96
+ ? `--_et-slider-fill-start: ${percent(shownStart)}; --_et-slider-fill-end: ${percent(shownEnd)};`
97
+ : `--_et-slider-fill-end: ${percent(shownEnd)};`;
98
+
99
+ const marksHtml = markList.length
100
+ ? `<div aria-hidden="true" class="${prefix}-marks">${markList
101
+ .map((mark) => {
102
+ const active = activeRange !== null && mark.value >= activeRange.start && mark.value <= activeRange.end;
103
+ const markLabel = mark.label ? `<span class="${prefix}-mark-label">${mark.label}</span>` : '';
104
+
105
+ return `<span class="${prefix}-mark"${active ? ' data-active="true"' : ''} data-et-slider-mark-value="${mark.value}"${styled(`--_et-slider-mark-position: ${percent(mark.value)};`)}>${markLabel}</span>`;
106
+ })
107
+ .join('')}</div>`
108
+ : '';
109
+
110
+ const thumbs = shown
111
+ .map((value, index) => {
112
+ const forced = forceList(options.force?.[index]);
113
+ const markLabel = markList.find((mark) => mark.value === values[index])?.label;
114
+ const valueText = options.mixed ? (options.mixedLabel ?? 'Mixed') : markLabel;
115
+ const ariaMin = range && index === 1 ? start : min;
116
+ const ariaMax = range && index === 0 ? end : max;
117
+ const attributes = [
118
+ 'role="slider"',
119
+ `class="${prefix}-thumb"`,
120
+ `aria-orientation="${orientation}"`,
121
+ `tabindex="${options.disabled ? -1 : 0}"`,
122
+ `aria-valuemin="${ariaMin}"`,
123
+ `aria-valuemax="${ariaMax}"`,
124
+ !options.mixed && `aria-valuenow="${value}"`,
125
+ valueText && `aria-valuetext="${valueText}"`,
126
+ range ? `aria-label="${index === 0 ? 'Minimum' : 'Maximum'}"` : labelId && `aria-labelledby="${labelId}"`,
127
+ supportId && `aria-describedby="${supportId}"`,
128
+ options.disabled && 'aria-disabled="true"',
129
+ options.readonly && 'aria-readonly="true"',
130
+ invalid && 'aria-invalid="true"',
131
+ options.disabled && 'data-disabled="true"',
132
+ options.readonly && 'data-readonly="true"',
133
+ options.dragging === index && 'data-dragging="true"',
134
+ forced.length > 0 && `data-et-force="${forced.join(' ')}"`,
135
+ styled(`--_et-slider-thumb-position: ${percent(value)};`).trim(),
136
+ ].filter(Boolean);
137
+ const bubble = options.valueLabel
138
+ ? `<div aria-hidden="true" class="${prefix}-thumb-value">${values[index]}</div>`
139
+ : '';
140
+
141
+ return `<div ${attributes.join(' ')}>${bubble}</div>`;
142
+ })
143
+ .join('');
144
+
145
+ const support =
146
+ options.hint === undefined && options.error === undefined
147
+ ? ''
148
+ : `<et-form-support class="et-form-support"><div class="et-form-support-stack">${
149
+ invalid
150
+ ? `<div class="et-form-support-content et-form-support-errors${options.errorColor ? ` et-color--${options.errorColor}` : ''}" id="${ids.error}" aria-atomic="true" aria-live="polite" data-active="true" data-direction="from-below" data-state="active"><et-form-error class="et-form-error">${options.error}</et-form-error></div>`
151
+ : `<div class="et-form-support-content et-form-support-hint" id="${ids.hint}" data-active="true" data-direction="from-above" data-state="active"><et-hint>${options.hint}</et-hint></div>`
152
+ }</div></et-form-support>`;
153
+
154
+ return `<${prefix} ${hostAttributes.join(' ')}>${labelHtml}<div class="${prefix}-interaction"><div aria-hidden="true" class="${prefix}-rail"></div><div aria-hidden="true" class="${prefix}-fill"${styled(fillStyle)}></div>${marksHtml}${thumbs}</div>${support}</${prefix}>`;
155
+ };