@sentropic/design-system-svelte 0.10.2 → 0.10.4

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 (87) hide show
  1. package/dist/AreaChart.svelte +38 -26
  2. package/dist/AreaChart.svelte.d.ts.map +1 -1
  3. package/dist/BackToTop.svelte +157 -0
  4. package/dist/BackToTop.svelte.d.ts +14 -0
  5. package/dist/BackToTop.svelte.d.ts.map +1 -0
  6. package/dist/BarChart.svelte +38 -39
  7. package/dist/BarChart.svelte.d.ts.map +1 -1
  8. package/dist/Card.svelte +2 -0
  9. package/dist/ChartDataList.svelte +33 -0
  10. package/dist/ChartDataList.svelte.d.ts +9 -0
  11. package/dist/ChartDataList.svelte.d.ts.map +1 -0
  12. package/dist/ChatComposer.svelte +20 -3
  13. package/dist/ChatComposer.svelte.d.ts +6 -30
  14. package/dist/ChatComposer.svelte.d.ts.map +1 -1
  15. package/dist/Checkbox.svelte +4 -0
  16. package/dist/Combobox.svelte +1 -1
  17. package/dist/ContentSwitcher.svelte +1 -0
  18. package/dist/DataTable.svelte +4 -1
  19. package/dist/DatePicker.svelte +1 -1
  20. package/dist/DisplaySettings.svelte +210 -0
  21. package/dist/DisplaySettings.svelte.d.ts +24 -0
  22. package/dist/DisplaySettings.svelte.d.ts.map +1 -0
  23. package/dist/DonutChart.svelte +44 -29
  24. package/dist/DonutChart.svelte.d.ts.map +1 -1
  25. package/dist/Dropdown.svelte +1 -1
  26. package/dist/FileUploader.svelte +2 -2
  27. package/dist/ForceGraph.svelte +485 -22
  28. package/dist/ForceGraph.svelte.d.ts +48 -0
  29. package/dist/ForceGraph.svelte.d.ts.map +1 -1
  30. package/dist/GraphLegend.svelte +142 -0
  31. package/dist/GraphLegend.svelte.d.ts +12 -0
  32. package/dist/GraphLegend.svelte.d.ts.map +1 -0
  33. package/dist/Header.svelte +2 -1
  34. package/dist/IconButton.svelte +1 -1
  35. package/dist/InlineLoading.svelte +10 -1
  36. package/dist/InlineLoading.svelte.d.ts.map +1 -1
  37. package/dist/Input.svelte +3 -2
  38. package/dist/LanguageSelector.svelte +2 -1
  39. package/dist/LineChart.svelte +38 -26
  40. package/dist/LineChart.svelte.d.ts.map +1 -1
  41. package/dist/Link.svelte +7 -1
  42. package/dist/MediaContent.svelte +124 -0
  43. package/dist/MediaContent.svelte.d.ts +22 -0
  44. package/dist/MediaContent.svelte.d.ts.map +1 -0
  45. package/dist/Menu.svelte +56 -3
  46. package/dist/Menu.svelte.d.ts.map +1 -1
  47. package/dist/MessageStatusBadge.svelte +1 -1
  48. package/dist/MultiSelect.svelte +2 -2
  49. package/dist/Notification.svelte +150 -0
  50. package/dist/Notification.svelte.d.ts +17 -0
  51. package/dist/Notification.svelte.d.ts.map +1 -0
  52. package/dist/NumberInput.svelte +1 -0
  53. package/dist/OverflowMenu.svelte +84 -13
  54. package/dist/OverflowMenu.svelte.d.ts.map +1 -1
  55. package/dist/Pagination.svelte +7 -0
  56. package/dist/PaginationNav.svelte +2 -2
  57. package/dist/ProgressIndicator.svelte +13 -1
  58. package/dist/ProgressIndicator.svelte.d.ts +1 -0
  59. package/dist/ProgressIndicator.svelte.d.ts.map +1 -1
  60. package/dist/Radio.svelte +7 -3
  61. package/dist/ScatterPlot.svelte +64 -45
  62. package/dist/ScatterPlot.svelte.d.ts.map +1 -1
  63. package/dist/Search.svelte +6 -3
  64. package/dist/Select.svelte +8 -2
  65. package/dist/SideNav.svelte +6 -0
  66. package/dist/StackedBarChart.svelte +51 -30
  67. package/dist/StackedBarChart.svelte.d.ts.map +1 -1
  68. package/dist/StreamingMessage.svelte +2 -2
  69. package/dist/Switch.svelte +4 -0
  70. package/dist/Table.svelte +4 -1
  71. package/dist/TableOfContents.svelte +109 -0
  72. package/dist/TableOfContents.svelte.d.ts +16 -0
  73. package/dist/TableOfContents.svelte.d.ts.map +1 -0
  74. package/dist/Tag.svelte +1 -1
  75. package/dist/Textarea.svelte +3 -2
  76. package/dist/Tile.svelte +4 -0
  77. package/dist/TileGroup.svelte +4 -0
  78. package/dist/Toggle.svelte +4 -0
  79. package/dist/Toggletip.svelte +1 -1
  80. package/dist/Transcription.svelte +135 -0
  81. package/dist/Transcription.svelte.d.ts +19 -0
  82. package/dist/Transcription.svelte.d.ts.map +1 -0
  83. package/dist/TreeView.svelte +2 -2
  84. package/dist/index.d.ts +12 -1
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +8 -0
  87. package/package.json +2 -2
package/dist/Menu.svelte CHANGED
@@ -62,6 +62,26 @@
62
62
  }: MenuProps = $props();
63
63
 
64
64
  let host: HTMLDivElement | undefined = $state();
65
+ function getFocusableItems(): HTMLButtonElement[] {
66
+ return Array.from(
67
+ host?.querySelectorAll<HTMLButtonElement>('[role="menuitem"]:not(:disabled)') ?? []
68
+ );
69
+ }
70
+
71
+ function moveIndex(index: number, size: number, step: number) {
72
+ if (size <= 0) return 0;
73
+ return ((index + step) % size + size) % size;
74
+ }
75
+
76
+ function focusAt(index: number) {
77
+ const focusable = getFocusableItems();
78
+ if (!focusable.length) return;
79
+ const target = moveIndex(index, focusable.length, 0);
80
+ focusable.forEach((button, idx) => {
81
+ button.tabIndex = idx === target ? 0 : -1;
82
+ });
83
+ focusable[target]?.focus();
84
+ }
65
85
 
66
86
  const classes = () =>
67
87
  ["st-menu", dense ? "st-menu--dense" : null, className].filter(Boolean).join(" ");
@@ -76,6 +96,35 @@
76
96
  return item.kind === undefined || item.kind === "item";
77
97
  }
78
98
 
99
+ function onItemKeyDown(event: KeyboardEvent, item: MenuActionItem) {
100
+ const focusable = getFocusableItems();
101
+ const current = focusable.indexOf(event.currentTarget as HTMLButtonElement);
102
+ if (event.key === "ArrowDown") {
103
+ event.preventDefault();
104
+ focusAt(current + 1);
105
+ return;
106
+ }
107
+ if (event.key === "ArrowUp") {
108
+ event.preventDefault();
109
+ focusAt(current - 1);
110
+ return;
111
+ }
112
+ if (event.key === "Home") {
113
+ event.preventDefault();
114
+ focusAt(0);
115
+ return;
116
+ }
117
+ if (event.key === "End") {
118
+ event.preventDefault();
119
+ focusAt(focusable.length - 1);
120
+ return;
121
+ }
122
+ if (event.key === "Enter" || event.key === " ") {
123
+ event.preventDefault();
124
+ if (!item.disabled) selectItem(item);
125
+ }
126
+ }
127
+
79
128
  function onWindowKeydown(event: KeyboardEvent) {
80
129
  if (event.key === "Escape" && open && dismissOnSelect) {
81
130
  event.preventDefault();
@@ -105,6 +154,7 @@
105
154
  aria-disabled={item.disabled ? "true" : undefined}
106
155
  disabled={item.disabled}
107
156
  onclick={() => selectItem(item)}
157
+ onkeydown={(event) => onItemKeyDown(event, item)}
108
158
  >
109
159
  {#if Icon}
110
160
  <span class="st-menu__itemIcon" aria-hidden="true">
@@ -163,7 +213,7 @@
163
213
 
164
214
  .st-menu__item:hover:not(:disabled),
165
215
  .st-menu__item:focus-visible {
166
- background: var(--st-component-menu-itemHoverBackground, var(--st-semantic-surface-subtle));
216
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
167
217
  outline: none;
168
218
  }
169
219
 
@@ -173,12 +223,15 @@
173
223
  }
174
224
 
175
225
  .st-menu__item--danger {
176
- color: var(--st-component-menu-dangerText, var(--st-semantic-feedback-error, #b91c1c));
226
+ color: var(--st-component-menu-dangerText, var(--st-semantic-feedback-error));
177
227
  }
178
228
 
179
229
  .st-menu__item--danger:hover:not(:disabled),
180
230
  .st-menu__item--danger:focus-visible {
181
- background: var(--st-component-menu-dangerHoverBackground, rgba(185, 28, 28, 0.08));
231
+ background: var(
232
+ --st-component-menu-dangerHoverBackground,
233
+ var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle))
234
+ );
182
235
  }
183
236
 
184
237
  .st-menu__itemIcon {
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Menu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;AAEtC,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;AAS1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AA8EJ,QAAA,MAAM,IAAI,kCAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Menu.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Menu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;AAEtC,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;AAS1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AA+HJ,QAAA,MAAM,IAAI,kCAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -41,7 +41,7 @@
41
41
  </Tag>
42
42
 
43
43
  <style>
44
- .st-messageStatusBadge {
44
+ :global(.st-messageStatusBadge) {
45
45
  align-items: center;
46
46
  text-transform: none;
47
47
  }
@@ -346,7 +346,7 @@
346
346
  }
347
347
 
348
348
  .st-multiSelect__tagRemove:hover:not(:disabled) {
349
- background: color-mix(in srgb, currentColor 18%, transparent);
349
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
350
350
  }
351
351
 
352
352
  .st-multiSelect__tagRemove:focus-visible {
@@ -426,7 +426,7 @@
426
426
  .st-multiSelect__option:hover:not(:disabled),
427
427
  .st-multiSelect__option:focus-visible {
428
428
  background: var(
429
- --st-component-dropdown-optionHoverBackground,
429
+ --st-component-control-hoverBackground,
430
430
  var(--st-semantic-surface-subtle)
431
431
  );
432
432
  outline: none;
@@ -0,0 +1,150 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ type NotificationProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
6
+ tone?: "info" | "success" | "warning" | "error";
7
+ title: string;
8
+ message?: string;
9
+ dismissible?: boolean;
10
+ dismissLabel?: string;
11
+ onDismiss?: () => void;
12
+ class?: string;
13
+ actions?: Snippet;
14
+ children?: Snippet;
15
+ };
16
+
17
+ let {
18
+ tone = "info",
19
+ title,
20
+ message,
21
+ dismissible = false,
22
+ dismissLabel = "Dismiss",
23
+ onDismiss,
24
+ class: className,
25
+ actions,
26
+ children,
27
+ ...rest
28
+ }: NotificationProps = $props();
29
+
30
+ const classes = () =>
31
+ ["st-notification", `st-notification--${tone}`, className].filter(Boolean).join(" ");
32
+
33
+ const canDismiss = () => dismissible && typeof onDismiss === "function";
34
+ const role = () => (tone === "error" ? "alert" : "status");
35
+
36
+ const onDismissClick = () => onDismiss?.();
37
+ </script>
38
+
39
+ <section {...rest} class={classes()} role={role()}>
40
+ <div class="st-notification__content">
41
+ <h2 class="st-notification__title">{title}</h2>
42
+ {#if message}
43
+ <p class="st-notification__message">{message}</p>
44
+ {/if}
45
+ {@render children?.()}
46
+ </div>
47
+ <div class="st-notification__meta">
48
+ {#if actions}
49
+ <div class="st-notification__actions">
50
+ {@render actions()}
51
+ </div>
52
+ {/if}
53
+ {#if canDismiss()}
54
+ <button
55
+ type="button"
56
+ class="st-notification__close"
57
+ aria-label={dismissLabel}
58
+ title={dismissLabel}
59
+ onclick={onDismissClick}
60
+ >
61
+ ×
62
+ </button>
63
+ {/if}
64
+ </div>
65
+ </section>
66
+
67
+ <style>
68
+ .st-notification {
69
+ background: var(--st-component-notification-background, var(--st-semantic-surface-raised));
70
+ border: 1px solid var(--st-component-notification-border, var(--st-semantic-border-subtle));
71
+ border-left-width: var(--st-component-notification-accentWidth, 0.25rem);
72
+ border-left-style: solid;
73
+ border-left-color: var(--st-component-notification-accent, var(--st-semantic-feedback-info));
74
+ border-radius: 0;
75
+ color: var(--st-component-notification-text, var(--st-semantic-text-primary));
76
+ display: flex;
77
+ gap: var(--st-spacing-4, 1rem);
78
+ justify-content: space-between;
79
+ padding: var(--st-spacing-4, 1rem);
80
+ width: min(100%, 32rem);
81
+ }
82
+
83
+ .st-notification--info {
84
+ --st-component-notification-accent: var(--st-component-notification-infoAccent, var(--st-semantic-feedback-info));
85
+ }
86
+
87
+ .st-notification--success {
88
+ --st-component-notification-accent: var(--st-component-notification-successAccent, var(--st-semantic-feedback-success));
89
+ }
90
+
91
+ .st-notification--warning {
92
+ --st-component-notification-accent: var(--st-component-notification-warningAccent, var(--st-semantic-feedback-warning));
93
+ }
94
+
95
+ .st-notification--error {
96
+ --st-component-notification-accent: var(--st-component-notification-errorAccent, var(--st-semantic-feedback-error));
97
+ }
98
+
99
+ .st-notification__content {
100
+ display: grid;
101
+ gap: 0.25rem;
102
+ flex: 1;
103
+ min-width: 0;
104
+ }
105
+
106
+ .st-notification__title {
107
+ font-size: 0.9375rem;
108
+ margin: 0;
109
+ }
110
+
111
+ .st-notification__message {
112
+ color: var(--st-semantic-text-secondary);
113
+ font-size: 0.875rem;
114
+ line-height: 1.5;
115
+ margin: 0;
116
+ }
117
+
118
+ .st-notification__meta {
119
+ align-items: start;
120
+ display: flex;
121
+ flex-shrink: 0;
122
+ gap: 0.5rem;
123
+ }
124
+
125
+ .st-notification__actions {
126
+ align-items: start;
127
+ display: flex;
128
+ gap: var(--st-spacing-2, 0.5rem);
129
+ }
130
+
131
+ .st-notification__close {
132
+ align-items: center;
133
+ background: transparent;
134
+ border: 1px solid var(--st-semantic-border-subtle);
135
+ border-radius: var(--st-border-radius-full, 999px);
136
+ color: var(--st-semantic-text-secondary);
137
+ cursor: var(--st-cursor-interactive, pointer);
138
+ display: inline-flex;
139
+ font-size: 0.875rem;
140
+ height: 1.75rem;
141
+ justify-content: center;
142
+ min-width: 1.75rem;
143
+ padding: 0;
144
+ width: 1.75rem;
145
+ }
146
+
147
+ .st-notification__close:hover {
148
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
149
+ }
150
+ </style>
@@ -0,0 +1,17 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ type NotificationProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
4
+ tone?: "info" | "success" | "warning" | "error";
5
+ title: string;
6
+ message?: string;
7
+ dismissible?: boolean;
8
+ dismissLabel?: string;
9
+ onDismiss?: () => void;
10
+ class?: string;
11
+ actions?: Snippet;
12
+ children?: Snippet;
13
+ };
14
+ declare const Notification: import("svelte").Component<NotificationProps, {}, "">;
15
+ type Notification = ReturnType<typeof Notification>;
16
+ export default Notification;
17
+ //# sourceMappingURL=Notification.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Notification.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Notification.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,iBAAiB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG;IACpE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAsDJ,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -217,6 +217,7 @@
217
217
  }
218
218
 
219
219
  .st-numberInput__control[type="number"] {
220
+ appearance: textfield;
220
221
  -moz-appearance: textfield;
221
222
  }
222
223
 
@@ -38,6 +38,7 @@
38
38
  <script lang="ts">
39
39
  import { Ellipsis } from "@lucide/svelte";
40
40
  import type { HTMLAttributes } from "svelte/elements";
41
+ import { tick } from "svelte";
41
42
 
42
43
  type OverflowMenuProps = Omit<HTMLAttributes<HTMLDivElement>, "class" | "onselect"> & {
43
44
  items: OverflowMenuItem[];
@@ -63,6 +64,35 @@
63
64
  }: OverflowMenuProps = $props();
64
65
 
65
66
  let host: HTMLDivElement | undefined = $state();
67
+ let list: HTMLUListElement | undefined = $state();
68
+
69
+ function getFocusableItems(): HTMLButtonElement[] {
70
+ return Array.from(
71
+ list?.querySelectorAll<HTMLButtonElement>('[role="menuitem"]:not(:disabled)') ?? []
72
+ );
73
+ }
74
+
75
+ function moveIndex(index: number, size: number, step: number) {
76
+ if (size <= 0) return 0;
77
+ return ((index + step) % size + size) % size;
78
+ }
79
+
80
+ function focusAt(index: number) {
81
+ const focusable = getFocusableItems();
82
+ if (!focusable.length) return;
83
+ const target = moveIndex(index, focusable.length, 0);
84
+ focusable.forEach((button, idx) => {
85
+ button.tabIndex = idx === target ? 0 : -1;
86
+ });
87
+ focusable[target]?.focus();
88
+ }
89
+
90
+ function openAndFocus() {
91
+ open = true;
92
+ tick().then(() => {
93
+ focusAt(0);
94
+ });
95
+ }
66
96
 
67
97
  const classes = () =>
68
98
  [
@@ -71,11 +101,15 @@
71
101
  dense ? "st-overflowMenu--dense" : null,
72
102
  className
73
103
  ]
74
- .filter(Boolean)
75
- .join(" ");
104
+ .filter(Boolean)
105
+ .join(" ");
76
106
 
77
107
  function toggle() {
78
- open = !open;
108
+ if (open) {
109
+ close();
110
+ } else {
111
+ openAndFocus();
112
+ }
79
113
  }
80
114
 
81
115
  function close() {
@@ -105,6 +139,46 @@
105
139
  const target = event.target as Node | null;
106
140
  if (host && target && !host.contains(target)) close();
107
141
  }
142
+
143
+ function onTriggerKeyDown(event: KeyboardEvent) {
144
+ if (!["ArrowDown", "Enter", " "].includes(event.key)) return;
145
+ event.preventDefault();
146
+ if (open) {
147
+ focusAt(0);
148
+ } else {
149
+ openAndFocus();
150
+ }
151
+ }
152
+
153
+ function onItemKeyDown(event: KeyboardEvent, item: OverflowMenuActionItem) {
154
+ const focusable = getFocusableItems();
155
+ const current = focusable.indexOf(event.currentTarget as HTMLButtonElement);
156
+ if (event.key === "ArrowDown") {
157
+ event.preventDefault();
158
+ focusAt(current + 1);
159
+ return;
160
+ }
161
+ if (event.key === "ArrowUp") {
162
+ event.preventDefault();
163
+ focusAt(current - 1);
164
+ return;
165
+ }
166
+ if (event.key === "Home") {
167
+ event.preventDefault();
168
+ focusAt(0);
169
+ return;
170
+ }
171
+ if (event.key === "End") {
172
+ event.preventDefault();
173
+ focusAt(focusable.length - 1);
174
+ return;
175
+ }
176
+ if (item.disabled) return;
177
+ if (event.key === "Enter" || event.key === " ") {
178
+ event.preventDefault();
179
+ selectItem(item);
180
+ }
181
+ }
108
182
  </script>
109
183
 
110
184
  <svelte:window onkeydown={onWindowKeydown} onpointerdown={onWindowPointerDown} />
@@ -117,11 +191,12 @@
117
191
  aria-expanded={open ? "true" : "false"}
118
192
  aria-label={triggerLabel}
119
193
  onclick={toggle}
194
+ onkeydown={onTriggerKeyDown}
120
195
  >
121
196
  <Ellipsis size={18} strokeWidth={2.25} aria-hidden="true" />
122
197
  </button>
123
198
  {#if open}
124
- <ul class="st-overflowMenu__list" role="menu" aria-label={label}>
199
+ <ul bind:this={list} class="st-overflowMenu__list" role="menu" aria-label={label}>
125
200
  {#each items as item, index (index)}
126
201
  {#if isAction(item)}
127
202
  {@const Icon = item.icon}
@@ -133,7 +208,9 @@
133
208
  role="menuitem"
134
209
  aria-disabled={item.disabled ? "true" : undefined}
135
210
  disabled={item.disabled}
211
+ tabindex={-1}
136
212
  onclick={() => selectItem(item)}
213
+ onkeydown={(event) => onItemKeyDown(event, item)}
137
214
  >
138
215
  {#if Icon}
139
216
  <span class="st-overflowMenu__itemIcon" aria-hidden="true">
@@ -174,10 +251,7 @@
174
251
  }
175
252
 
176
253
  .st-overflowMenu__trigger:hover {
177
- background: var(
178
- --st-component-overflowMenu-triggerHoverBackground,
179
- var(--st-semantic-surface-subtle)
180
- );
254
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
181
255
  }
182
256
 
183
257
  /* Focus = stratégie d'anatomie partagée (outline DSFR / inset Carbon / ring base). */
@@ -190,10 +264,7 @@
190
264
  }
191
265
 
192
266
  .st-overflowMenu__trigger[aria-expanded="true"] {
193
- background: var(
194
- --st-component-overflowMenu-triggerHoverBackground,
195
- var(--st-semantic-surface-subtle)
196
- );
267
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
197
268
  }
198
269
 
199
270
  .st-overflowMenu__list {
@@ -257,7 +328,7 @@
257
328
 
258
329
  .st-overflowMenu__item:hover:not(:disabled),
259
330
  .st-overflowMenu__item:focus-visible {
260
- background: var(--st-component-menu-itemHoverBackground, var(--st-semantic-surface-subtle));
331
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
261
332
  outline: none;
262
333
  }
263
334
 
@@ -1 +1 @@
1
- {"version":3,"file":"OverflowMenu.svelte.d.ts","sourceRoot":"","sources":["../src/lib/OverflowMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;AAEtC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAEhE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,gBAAgB,GACxB,sBAAsB,GACtB,uBAAuB,GACvB,qBAAqB,CAAC;AAI5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,iBAAiB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IACpF,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAoGJ,QAAA,MAAM,YAAY,0CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"OverflowMenu.svelte.d.ts","sourceRoot":"","sources":["../src/lib/OverflowMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;AAEtC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAEhE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,gBAAgB,GACxB,sBAAsB,GACtB,uBAAuB,GACvB,qBAAqB,CAAC;AAI5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIpD,KAAK,iBAAiB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IACpF,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AA8KJ,QAAA,MAAM,YAAY,0CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -85,6 +85,13 @@
85
85
  font-weight: var(--st-component-pagination-activeWeight, inherit);
86
86
  }
87
87
 
88
+ .st-pagination button:hover:not(:disabled) {
89
+ background: var(
90
+ --st-component-control-hoverBackground,
91
+ var(--st-component-pagination-hoverBackground, var(--st-semantic-surface-subtle))
92
+ );
93
+ }
94
+
88
95
  .st-pagination button:disabled {
89
96
  color: var(--st-component-pagination-disabledText, var(--st-semantic-text-muted));
90
97
  cursor: not-allowed;
@@ -163,8 +163,8 @@
163
163
  .st-paginationNav__page:hover:not(:disabled),
164
164
  .st-paginationNav__nav:hover:not(:disabled) {
165
165
  background: var(
166
- --st-component-paginationNav-hoverBackground,
167
- var(--st-semantic-surface-subtle)
166
+ --st-component-control-hoverBackground,
167
+ var(--st-component-paginationNav-hoverBackground, var(--st-semantic-surface-subtle))
168
168
  );
169
169
  }
170
170
 
@@ -22,13 +22,23 @@
22
22
  items: ProgressIndicatorItem[];
23
23
  vertical?: boolean;
24
24
  label?: string;
25
+ statusLabels?: Partial<Record<ProgressIndicatorStatus, string>>;
25
26
  class?: string;
26
27
  };
27
28
 
29
+ const DEFAULT_STATUS_LABELS: Record<ProgressIndicatorStatus, string> = {
30
+ complete: "Complete",
31
+ current: "Current",
32
+ upcoming: "Upcoming",
33
+ invalid: "Invalid",
34
+ disabled: "Disabled"
35
+ };
36
+
28
37
  let {
29
38
  items,
30
39
  vertical = false,
31
40
  label = "Progress",
41
+ statusLabels,
32
42
  class: className,
33
43
  ...rest
34
44
  }: ProgressIndicatorProps = $props();
@@ -44,6 +54,8 @@
44
54
 
45
55
  const resolvedStatus = (item: ProgressIndicatorItem): ProgressIndicatorStatus =>
46
56
  item.status ?? "upcoming";
57
+ const indicatorLabel = (item: ProgressIndicatorItem, status: ProgressIndicatorStatus) =>
58
+ `${statusLabels?.[status] ?? DEFAULT_STATUS_LABELS[status]}: ${item.label}`;
47
59
  </script>
48
60
 
49
61
  <ol {...rest} class={classes()} aria-label={label}>
@@ -54,7 +66,7 @@
54
66
  class={["st-progressIndicator__step", `st-progressIndicator__step--${status}`].join(" ")}
55
67
  aria-current={status === "current" ? "step" : undefined}
56
68
  >
57
- <span class="st-progressIndicator__indicator" aria-hidden="true">
69
+ <span class="st-progressIndicator__indicator" role="img" aria-label={indicatorLabel(item, status)}>
58
70
  <span class="st-progressIndicator__circle">
59
71
  {#if status === "complete"}
60
72
  <Check size={14} strokeWidth={2} aria-hidden="true" />
@@ -10,6 +10,7 @@ type ProgressIndicatorProps = Omit<HTMLAttributes<HTMLOListElement>, "class"> &
10
10
  items: ProgressIndicatorItem[];
11
11
  vertical?: boolean;
12
12
  label?: string;
13
+ statusLabels?: Partial<Record<ProgressIndicatorStatus, string>>;
13
14
  class?: string;
14
15
  };
15
16
  declare const ProgressIndicator: import("svelte").Component<ProgressIndicatorProps, {}, "">;
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressIndicator.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ProgressIndicator.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,MAAM,uBAAuB,GAC/B,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,GACT,UAAU,CAAC;AAEf,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIpD,KAAK,sBAAsB,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,GAAG;IAC9E,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAgEJ,QAAA,MAAM,iBAAiB,4DAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"ProgressIndicator.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ProgressIndicator.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,MAAM,uBAAuB,GAC/B,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,GACT,UAAU,CAAC;AAEf,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIpD,KAAK,sBAAsB,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,GAAG;IAC9E,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA2EJ,QAAA,MAAM,iBAAiB,4DAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
package/dist/Radio.svelte CHANGED
@@ -12,8 +12,8 @@
12
12
  const classes = () => ["st-choice", "st-choice--radio", className].filter(Boolean).join(" ");
13
13
  </script>
14
14
 
15
- <label class={classes()}>
16
- <input {...rest} class="st-choice__input" type="radio" aria-invalid={invalid ? "true" : undefined} />
15
+ <label class={classes()} data-invalid={invalid ? "true" : undefined}>
16
+ <input {...rest} class="st-choice__input" type="radio" />
17
17
  <span class="st-choice__content">
18
18
  <span class="st-choice__label">{label}</span>
19
19
  {#if helperText}<span class="st-choice__help">{helperText}</span>{/if}
@@ -48,7 +48,11 @@
48
48
  0 0 0 2px var(--st-component-control-focusRing, var(--st-semantic-border-interactive)));
49
49
  }
50
50
 
51
- .st-choice__input[aria-invalid="true"] {
51
+ .st-choice:hover .st-choice__input {
52
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
53
+ }
54
+
55
+ .st-choice[data-invalid="true"] .st-choice__input {
52
56
  accent-color: var(--st-component-control-invalidBorder, var(--st-semantic-feedback-error));
53
57
  outline-color: var(--st-component-control-invalidBorder, var(--st-semantic-feedback-error));
54
58
  }