@sentropic/design-system-svelte 0.34.50 → 0.34.52

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 (85) hide show
  1. package/README.md +62 -0
  2. package/dist/AnomalySwimLaneChart.svelte +10 -1
  3. package/dist/AnomalySwimLaneChart.svelte.d.ts +2 -0
  4. package/dist/AnomalySwimLaneChart.svelte.d.ts.map +1 -1
  5. package/dist/CalendarHeatmapChart.svelte +11 -1
  6. package/dist/CalendarHeatmapChart.svelte.d.ts +2 -0
  7. package/dist/CalendarHeatmapChart.svelte.d.ts.map +1 -1
  8. package/dist/Combobox.svelte +5 -1
  9. package/dist/Combobox.svelte.d.ts.map +1 -1
  10. package/dist/ContourChart.svelte +76 -13
  11. package/dist/ContourChart.svelte.d.ts +3 -1
  12. package/dist/ContourChart.svelte.d.ts.map +1 -1
  13. package/dist/CopyButton.svelte +9 -3
  14. package/dist/CopyButton.svelte.d.ts +1 -0
  15. package/dist/CopyButton.svelte.d.ts.map +1 -1
  16. package/dist/Dashboard.svelte +155 -0
  17. package/dist/Dashboard.svelte.d.ts +21 -0
  18. package/dist/Dashboard.svelte.d.ts.map +1 -0
  19. package/dist/DashboardGrid.svelte +237 -0
  20. package/dist/DashboardGrid.svelte.d.ts +24 -0
  21. package/dist/DashboardGrid.svelte.d.ts.map +1 -0
  22. package/dist/DataTable.svelte +3 -1
  23. package/dist/DataTable.svelte.d.ts +1 -0
  24. package/dist/DataTable.svelte.d.ts.map +1 -1
  25. package/dist/DatePicker.svelte +33 -28
  26. package/dist/DatePicker.svelte.d.ts.map +1 -1
  27. package/dist/Density2DChart.svelte +10 -1
  28. package/dist/Density2DChart.svelte.d.ts +2 -0
  29. package/dist/Density2DChart.svelte.d.ts.map +1 -1
  30. package/dist/Dropdown.svelte +40 -11
  31. package/dist/Dropdown.svelte.d.ts +1 -0
  32. package/dist/Dropdown.svelte.d.ts.map +1 -1
  33. package/dist/EventFeedPanel.svelte +3 -3
  34. package/dist/EventFeedPanel.svelte.d.ts +1 -1
  35. package/dist/EventFeedPanel.svelte.d.ts.map +1 -1
  36. package/dist/FileUploader.svelte +7 -3
  37. package/dist/Footer.svelte +75 -11
  38. package/dist/Footer.svelte.d.ts +16 -6
  39. package/dist/Footer.svelte.d.ts.map +1 -1
  40. package/dist/ForceGraph.svelte +9 -3
  41. package/dist/ForceGraph.svelte.d.ts +4 -0
  42. package/dist/ForceGraph.svelte.d.ts.map +1 -1
  43. package/dist/HeatmapChart.svelte +39 -3
  44. package/dist/HeatmapChart.svelte.d.ts +4 -1
  45. package/dist/HeatmapChart.svelte.d.ts.map +1 -1
  46. package/dist/KanbanBoard.svelte +144 -0
  47. package/dist/KanbanBoard.svelte.d.ts +23 -0
  48. package/dist/KanbanBoard.svelte.d.ts.map +1 -0
  49. package/dist/ListReportPage.svelte +184 -0
  50. package/dist/ListReportPage.svelte.d.ts +46 -0
  51. package/dist/ListReportPage.svelte.d.ts.map +1 -0
  52. package/dist/MasterDetail.svelte +267 -0
  53. package/dist/MasterDetail.svelte.d.ts +35 -0
  54. package/dist/MasterDetail.svelte.d.ts.map +1 -0
  55. package/dist/MultiSelect.svelte +20 -11
  56. package/dist/MultiSelect.svelte.d.ts +1 -0
  57. package/dist/MultiSelect.svelte.d.ts.map +1 -1
  58. package/dist/NavItem.svelte +6 -6
  59. package/dist/ObjectPage.svelte +222 -0
  60. package/dist/ObjectPage.svelte.d.ts +46 -0
  61. package/dist/ObjectPage.svelte.d.ts.map +1 -0
  62. package/dist/OrderedList.svelte +7 -12
  63. package/dist/OrderedList.svelte.d.ts.map +1 -1
  64. package/dist/PaginationNav.svelte +10 -4
  65. package/dist/PaginationNav.svelte.d.ts +1 -0
  66. package/dist/PaginationNav.svelte.d.ts.map +1 -1
  67. package/dist/PointAndFigureChart.svelte +18 -11
  68. package/dist/PointAndFigureChart.svelte.d.ts +1 -1
  69. package/dist/PointAndFigureChart.svelte.d.ts.map +1 -1
  70. package/dist/RenkoChart.svelte +40 -13
  71. package/dist/RenkoChart.svelte.d.ts +1 -1
  72. package/dist/RenkoChart.svelte.d.ts.map +1 -1
  73. package/dist/VectorFieldChart.svelte +5 -5
  74. package/dist/VectorFieldChart.svelte.d.ts +1 -1
  75. package/dist/VectorFieldChart.svelte.d.ts.map +1 -1
  76. package/dist/WindBarbChart.svelte +5 -5
  77. package/dist/WindBarbChart.svelte.d.ts +1 -1
  78. package/dist/WindBarbChart.svelte.d.ts.map +1 -1
  79. package/dist/Wizard.svelte +125 -0
  80. package/dist/Wizard.svelte.d.ts +25 -0
  81. package/dist/Wizard.svelte.d.ts.map +1 -0
  82. package/dist/index.d.ts +24 -10
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +7 -0
  85. package/package.json +1 -1
@@ -0,0 +1,184 @@
1
+ <script lang="ts" module>
2
+ import type { SideNavItem } from "./SideNav.svelte";
3
+
4
+ export interface ListReportPageNavItem extends SideNavItem {}
5
+
6
+ export interface ListReportPageColumn {
7
+ key: string;
8
+ label: string;
9
+ sortable?: boolean;
10
+ align?: "start" | "center" | "end";
11
+ width?: string;
12
+ }
13
+
14
+ export interface ListReportPageRow {
15
+ id: string;
16
+ [key: string]: unknown;
17
+ }
18
+
19
+ export interface ListReportPageFilter {
20
+ field: string;
21
+ value: string;
22
+ operator?: string;
23
+ }
24
+
25
+ export interface ListReportPageAction {
26
+ value: string;
27
+ label: string;
28
+ danger?: boolean;
29
+ }
30
+
31
+ export type ListReportPageProps = {
32
+ appTitle: string;
33
+ navItems?: ListReportPageNavItem[];
34
+ pageTitle: string;
35
+ primaryAction?: string;
36
+ secondaryAction?: string;
37
+ searchLabel?: string;
38
+ searchPlaceholder?: string;
39
+ filterBarLabel?: string;
40
+ filters?: ListReportPageFilter[];
41
+ columns: ListReportPageColumn[];
42
+ rows: ListReportPageRow[];
43
+ pageSize?: number;
44
+ rowActions?: ListReportPageAction[];
45
+ rowActionsLabel?: string;
46
+ onprimaryaction?: () => void;
47
+ onsearch?: (q: string) => void;
48
+ };
49
+ </script>
50
+
51
+ <script lang="ts">
52
+ import SideNav from "./SideNav.svelte";
53
+ import DataTable from "./DataTable.svelte";
54
+ import Search from "./Search.svelte";
55
+ import FilterBar from "./FilterBar.svelte";
56
+ import FilterPill from "./FilterPill.svelte";
57
+ import Button from "./Button.svelte";
58
+
59
+ let {
60
+ appTitle,
61
+ navItems = [],
62
+ pageTitle,
63
+ primaryAction,
64
+ secondaryAction,
65
+ searchLabel,
66
+ searchPlaceholder = "Rechercher…",
67
+ filterBarLabel = "Filtres actifs",
68
+ filters = [],
69
+ columns,
70
+ rows,
71
+ pageSize = 10,
72
+ rowActions = [],
73
+ rowActionsLabel,
74
+ onprimaryaction,
75
+ onsearch,
76
+ }: ListReportPageProps = $props();
77
+
78
+ let searchValue = $state("");
79
+
80
+ function handleSearch(q: string) {
81
+ searchValue = q;
82
+ onsearch?.(q);
83
+ }
84
+ </script>
85
+
86
+ <div class="st-lrp">
87
+ <header class="st-lrp__header">
88
+ <span class="st-lrp__appTitle">{appTitle}</span>
89
+ </header>
90
+ <div class="st-lrp__body">
91
+ {#if navItems.length > 0}
92
+ <aside class="st-lrp__aside">
93
+ <SideNav items={navItems} />
94
+ </aside>
95
+ {/if}
96
+ <main class="st-lrp__main">
97
+ <div class="st-lrp__titlebar">
98
+ <h1 class="st-lrp__pageTitle">{pageTitle}</h1>
99
+ <div class="st-lrp__titleActions">
100
+ {#if secondaryAction}
101
+ <Button variant="secondary">{secondaryAction}</Button>
102
+ {/if}
103
+ {#if primaryAction}
104
+ <Button variant="primary" onclick={onprimaryaction}>{primaryAction}</Button>
105
+ {/if}
106
+ </div>
107
+ </div>
108
+ <div class="st-lrp__toolbar">
109
+ <Search
110
+ label={searchLabel}
111
+ placeholder={searchPlaceholder}
112
+ value={searchValue}
113
+ fluid
114
+ oninput={(e) => handleSearch((e.target as HTMLInputElement).value)}
115
+ />
116
+ {#if filters.length > 0}
117
+ <FilterBar label={filterBarLabel}>
118
+ {#each filters as f}
119
+ <FilterPill field={f.field} value={f.value} operator={f.operator} />
120
+ {/each}
121
+ </FilterBar>
122
+ {/if}
123
+ </div>
124
+ <DataTable {columns} {rows} />
125
+ </main>
126
+ </div>
127
+ </div>
128
+
129
+ <style>
130
+ .st-lrp {
131
+ display: grid;
132
+ grid-template-rows: auto 1fr;
133
+ min-block-size: 100vh;
134
+ background: var(--st-semantic-surface-default);
135
+ color: var(--st-semantic-text-primary);
136
+ }
137
+ .st-lrp__header {
138
+ border-block-end: 1px solid var(--st-semantic-border-subtle);
139
+ padding: var(--st-spacing-3, 0.75rem) var(--st-spacing-6, 1.5rem);
140
+ display: flex;
141
+ align-items: center;
142
+ }
143
+ .st-lrp__appTitle {
144
+ font-weight: 700;
145
+ font-size: 1rem;
146
+ }
147
+ .st-lrp__body {
148
+ display: grid;
149
+ grid-template-columns: 220px 1fr;
150
+ }
151
+ .st-lrp__aside {
152
+ border-inline-end: 1px solid var(--st-semantic-border-subtle);
153
+ background: var(--st-semantic-surface-raised);
154
+ overflow-y: auto;
155
+ }
156
+ .st-lrp__main {
157
+ display: flex;
158
+ flex-direction: column;
159
+ gap: var(--st-spacing-4, 1rem);
160
+ padding: var(--st-spacing-6, 1.5rem);
161
+ overflow: auto;
162
+ }
163
+ .st-lrp__titlebar {
164
+ display: flex;
165
+ align-items: center;
166
+ justify-content: space-between;
167
+ gap: var(--st-spacing-3, 0.75rem);
168
+ }
169
+ .st-lrp__pageTitle {
170
+ font-size: 1.5rem;
171
+ font-weight: 700;
172
+ margin: 0;
173
+ color: var(--st-semantic-text-primary);
174
+ }
175
+ .st-lrp__titleActions {
176
+ display: flex;
177
+ gap: var(--st-spacing-2, 0.5rem);
178
+ }
179
+ .st-lrp__toolbar {
180
+ display: flex;
181
+ flex-direction: column;
182
+ gap: var(--st-spacing-2, 0.5rem);
183
+ }
184
+ </style>
@@ -0,0 +1,46 @@
1
+ import type { SideNavItem } from "./SideNav.svelte";
2
+ export interface ListReportPageNavItem extends SideNavItem {
3
+ }
4
+ export interface ListReportPageColumn {
5
+ key: string;
6
+ label: string;
7
+ sortable?: boolean;
8
+ align?: "start" | "center" | "end";
9
+ width?: string;
10
+ }
11
+ export interface ListReportPageRow {
12
+ id: string;
13
+ [key: string]: unknown;
14
+ }
15
+ export interface ListReportPageFilter {
16
+ field: string;
17
+ value: string;
18
+ operator?: string;
19
+ }
20
+ export interface ListReportPageAction {
21
+ value: string;
22
+ label: string;
23
+ danger?: boolean;
24
+ }
25
+ export type ListReportPageProps = {
26
+ appTitle: string;
27
+ navItems?: ListReportPageNavItem[];
28
+ pageTitle: string;
29
+ primaryAction?: string;
30
+ secondaryAction?: string;
31
+ searchLabel?: string;
32
+ searchPlaceholder?: string;
33
+ filterBarLabel?: string;
34
+ filters?: ListReportPageFilter[];
35
+ columns: ListReportPageColumn[];
36
+ rows: ListReportPageRow[];
37
+ pageSize?: number;
38
+ rowActions?: ListReportPageAction[];
39
+ rowActionsLabel?: string;
40
+ onprimaryaction?: () => void;
41
+ onsearch?: (q: string) => void;
42
+ };
43
+ declare const ListReportPage: import("svelte").Component<ListReportPageProps, {}, "">;
44
+ type ListReportPage = ReturnType<typeof ListReportPage>;
45
+ export default ListReportPage;
46
+ //# sourceMappingURL=ListReportPage.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListReportPage.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ListReportPage.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,qBAAsB,SAAQ,WAAW;CAAG;AAE7D,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC,CAAC;AAwFJ,QAAA,MAAM,cAAc,yDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -0,0 +1,267 @@
1
+ <script lang="ts" module>
2
+ import type { SideNavItem } from "./SideNav.svelte";
3
+
4
+ export interface MasterDetailNavItem extends SideNavItem {}
5
+
6
+ export type MasterDetailStatusTone = "neutral" | "info" | "success" | "warning" | "error";
7
+
8
+ export interface MasterDetailItem {
9
+ id: string;
10
+ primary: string;
11
+ secondary?: string;
12
+ statusLabel?: string;
13
+ statusTone?: MasterDetailStatusTone;
14
+ active?: boolean;
15
+ }
16
+
17
+ export interface MasterDetailField {
18
+ key: string;
19
+ value: string;
20
+ }
21
+
22
+ export type MasterDetailProps = {
23
+ appTitle?: string;
24
+ navItems?: MasterDetailNavItem[];
25
+ listTitle: string;
26
+ searchPlaceholder?: string;
27
+ listItems: MasterDetailItem[];
28
+ detailTitle: string;
29
+ detailStatus?: { label: string; tone: MasterDetailStatusTone };
30
+ detailActions?: string[];
31
+ detailFields: MasterDetailField[];
32
+ onlistitemclick?: (id: string) => void;
33
+ };
34
+ </script>
35
+
36
+ <script lang="ts">
37
+ import SideNav from "./SideNav.svelte";
38
+ import Badge from "./Badge.svelte";
39
+ import Button from "./Button.svelte";
40
+ import Search from "./Search.svelte";
41
+
42
+ let {
43
+ appTitle,
44
+ navItems = [],
45
+ listTitle,
46
+ searchPlaceholder = "Rechercher…",
47
+ listItems,
48
+ detailTitle,
49
+ detailStatus,
50
+ detailActions = [],
51
+ detailFields,
52
+ onlistitemclick,
53
+ }: MasterDetailProps = $props();
54
+
55
+ let searchValue = $state("");
56
+ </script>
57
+
58
+ <div class="st-md">
59
+ {#if appTitle}
60
+ <header class="st-md__header">
61
+ <span class="st-md__appTitle">{appTitle}</span>
62
+ </header>
63
+ {/if}
64
+ <div class="st-md__body">
65
+ {#if navItems.length > 0}
66
+ <aside class="st-md__aside">
67
+ <SideNav items={navItems} />
68
+ </aside>
69
+ {/if}
70
+ <div class="st-md__split">
71
+ <aside class="st-md__list" aria-label={listTitle}>
72
+ <div class="st-md__listHeader">
73
+ <h2 class="st-md__listTitle">{listTitle}</h2>
74
+ <Search
75
+ placeholder={searchPlaceholder}
76
+ value={searchValue}
77
+ fluid
78
+ oninput={(e) => (searchValue = (e.target as HTMLInputElement).value)}
79
+ />
80
+ </div>
81
+ <ul class="st-md__listItems">
82
+ {#each listItems as item (item.id)}
83
+ <li>
84
+ <button
85
+ class="st-md__listItem"
86
+ class:st-md__listItem--active={item.active}
87
+ onclick={() => onlistitemclick?.(item.id)}
88
+ type="button"
89
+ >
90
+ <span class="st-md__itemPrimary">{item.primary}</span>
91
+ {#if item.secondary}
92
+ <span class="st-md__itemSecondary">{item.secondary}</span>
93
+ {/if}
94
+ {#if item.statusLabel}
95
+ <Badge tone={item.statusTone ?? "neutral"}>{item.statusLabel}</Badge>
96
+ {/if}
97
+ </button>
98
+ </li>
99
+ {/each}
100
+ </ul>
101
+ </aside>
102
+ <main class="st-md__detail">
103
+ <div class="st-md__detailHeader">
104
+ <div class="st-md__detailTitleRow">
105
+ <h1 class="st-md__detailTitle">{detailTitle}</h1>
106
+ {#if detailStatus}
107
+ <Badge tone={detailStatus.tone}>{detailStatus.label}</Badge>
108
+ {/if}
109
+ </div>
110
+ {#if detailActions.length > 0}
111
+ <div class="st-md__detailActions">
112
+ {#each detailActions as action, i}
113
+ <Button variant={i === 0 ? "primary" : "secondary"}>{action}</Button>
114
+ {/each}
115
+ </div>
116
+ {/if}
117
+ </div>
118
+ <dl class="st-md__fields">
119
+ {#each detailFields as field}
120
+ <div class="st-md__fieldRow">
121
+ <dt class="st-md__fieldKey">{field.key}</dt>
122
+ <dd class="st-md__fieldValue">{field.value}</dd>
123
+ </div>
124
+ {/each}
125
+ </dl>
126
+ </main>
127
+ </div>
128
+ </div>
129
+ </div>
130
+
131
+ <style>
132
+ .st-md {
133
+ display: grid;
134
+ grid-template-rows: auto 1fr;
135
+ min-block-size: 100vh;
136
+ background: var(--st-semantic-surface-default);
137
+ color: var(--st-semantic-text-primary);
138
+ }
139
+ .st-md__header {
140
+ border-block-end: 1px solid var(--st-semantic-border-subtle);
141
+ padding: var(--st-spacing-3, 0.75rem) var(--st-spacing-6, 1.5rem);
142
+ display: flex;
143
+ align-items: center;
144
+ }
145
+ .st-md__appTitle {
146
+ font-weight: 700;
147
+ font-size: 1rem;
148
+ }
149
+ .st-md__body {
150
+ display: grid;
151
+ grid-template-columns: 220px 1fr;
152
+ overflow: hidden;
153
+ }
154
+ .st-md__aside {
155
+ border-inline-end: 1px solid var(--st-semantic-border-subtle);
156
+ background: var(--st-semantic-surface-raised);
157
+ overflow-y: auto;
158
+ }
159
+ .st-md__split {
160
+ display: grid;
161
+ grid-template-columns: 320px 1fr;
162
+ overflow: hidden;
163
+ }
164
+ .st-md__list {
165
+ border-inline-end: 1px solid var(--st-semantic-border-subtle);
166
+ display: flex;
167
+ flex-direction: column;
168
+ overflow: hidden;
169
+ }
170
+ .st-md__listHeader {
171
+ padding: var(--st-spacing-4, 1rem);
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: var(--st-spacing-2, 0.5rem);
175
+ border-block-end: 1px solid var(--st-semantic-border-subtle);
176
+ }
177
+ .st-md__listTitle {
178
+ font-size: 1rem;
179
+ font-weight: 650;
180
+ margin: 0;
181
+ }
182
+ .st-md__listItems {
183
+ list-style: none;
184
+ margin: 0;
185
+ padding: var(--st-spacing-2, 0.5rem);
186
+ overflow-y: auto;
187
+ flex: 1;
188
+ }
189
+ .st-md__listItem {
190
+ width: 100%;
191
+ text-align: start;
192
+ background: transparent;
193
+ border: none;
194
+ border-radius: var(--st-radius-md, 0.375rem);
195
+ padding: var(--st-spacing-3, 0.75rem);
196
+ cursor: pointer;
197
+ display: flex;
198
+ flex-direction: column;
199
+ gap: var(--st-spacing-1, 0.25rem);
200
+ color: var(--st-semantic-text-primary);
201
+ }
202
+ .st-md__listItem:hover {
203
+ background: var(--st-semantic-surface-subtle, #f1f5f9);
204
+ }
205
+ .st-md__listItem--active {
206
+ background: var(--st-semantic-surface-selected, #eff6ff);
207
+ }
208
+ .st-md__itemPrimary {
209
+ font-size: 0.875rem;
210
+ font-weight: 600;
211
+ }
212
+ .st-md__itemSecondary {
213
+ font-size: 0.75rem;
214
+ color: var(--st-semantic-text-secondary);
215
+ }
216
+ .st-md__detail {
217
+ display: flex;
218
+ flex-direction: column;
219
+ gap: var(--st-spacing-6, 1.5rem);
220
+ padding: var(--st-spacing-6, 1.5rem);
221
+ overflow-y: auto;
222
+ }
223
+ .st-md__detailHeader {
224
+ display: flex;
225
+ align-items: flex-start;
226
+ justify-content: space-between;
227
+ gap: var(--st-spacing-4, 1rem);
228
+ flex-wrap: wrap;
229
+ }
230
+ .st-md__detailTitleRow {
231
+ display: flex;
232
+ align-items: center;
233
+ gap: var(--st-spacing-3, 0.75rem);
234
+ flex-wrap: wrap;
235
+ }
236
+ .st-md__detailTitle {
237
+ font-size: 1.5rem;
238
+ font-weight: 700;
239
+ margin: 0;
240
+ }
241
+ .st-md__detailActions {
242
+ display: flex;
243
+ gap: var(--st-spacing-2, 0.5rem);
244
+ flex-shrink: 0;
245
+ }
246
+ .st-md__fields {
247
+ margin: 0;
248
+ display: grid;
249
+ grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
250
+ gap: var(--st-spacing-3, 0.75rem) var(--st-spacing-6, 1.5rem);
251
+ }
252
+ .st-md__fieldRow {
253
+ display: flex;
254
+ flex-direction: column;
255
+ gap: 0.2rem;
256
+ }
257
+ .st-md__fieldKey {
258
+ font-size: 0.75rem;
259
+ color: var(--st-semantic-text-secondary);
260
+ font-weight: 500;
261
+ }
262
+ .st-md__fieldValue {
263
+ margin: 0;
264
+ font-size: 0.875rem;
265
+ color: var(--st-semantic-text-primary);
266
+ }
267
+ </style>
@@ -0,0 +1,35 @@
1
+ import type { SideNavItem } from "./SideNav.svelte";
2
+ export interface MasterDetailNavItem extends SideNavItem {
3
+ }
4
+ export type MasterDetailStatusTone = "neutral" | "info" | "success" | "warning" | "error";
5
+ export interface MasterDetailItem {
6
+ id: string;
7
+ primary: string;
8
+ secondary?: string;
9
+ statusLabel?: string;
10
+ statusTone?: MasterDetailStatusTone;
11
+ active?: boolean;
12
+ }
13
+ export interface MasterDetailField {
14
+ key: string;
15
+ value: string;
16
+ }
17
+ export type MasterDetailProps = {
18
+ appTitle?: string;
19
+ navItems?: MasterDetailNavItem[];
20
+ listTitle: string;
21
+ searchPlaceholder?: string;
22
+ listItems: MasterDetailItem[];
23
+ detailTitle: string;
24
+ detailStatus?: {
25
+ label: string;
26
+ tone: MasterDetailStatusTone;
27
+ };
28
+ detailActions?: string[];
29
+ detailFields: MasterDetailField[];
30
+ onlistitemclick?: (id: string) => void;
31
+ };
32
+ declare const MasterDetail: import("svelte").Component<MasterDetailProps, {}, "">;
33
+ type MasterDetail = ReturnType<typeof MasterDetail>;
34
+ export default MasterDetail;
35
+ //# sourceMappingURL=MasterDetail.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MasterDetail.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MasterDetail.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,mBAAoB,SAAQ,WAAW;CAAG;AAE3D,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1F,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,sBAAsB,CAAA;KAAE,CAAC;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAmGJ,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -18,6 +18,7 @@
18
18
  size?: "sm" | "md" | "lg";
19
19
  options: MultiSelectOption[];
20
20
  selected?: string[];
21
+ locale?: string;
21
22
  placeholder?: string;
22
23
  searchPlaceholder?: string;
23
24
  noResultsLabel?: string;
@@ -37,11 +38,12 @@
37
38
  size = "md",
38
39
  options,
39
40
  selected = $bindable([]),
40
- placeholder = "Select items",
41
- searchPlaceholder = "Filter",
42
- noResultsLabel = "No results",
43
- toggleLabel = "Toggle options",
44
- removeLabel = "Remove",
41
+ locale = "fr-FR",
42
+ placeholder,
43
+ searchPlaceholder,
44
+ noResultsLabel,
45
+ toggleLabel,
46
+ removeLabel,
45
47
  listLabel,
46
48
  disabled = false,
47
49
  class: className,
@@ -49,6 +51,13 @@
49
51
  ...rest
50
52
  }: MultiSelectProps = $props();
51
53
 
54
+ const isFr = $derived(locale.toLowerCase().startsWith("fr"));
55
+ const resolvedPlaceholder = $derived(placeholder ?? (isFr ? "Sélectionner des éléments" : "Select items"));
56
+ const resolvedSearchPlaceholder = $derived(searchPlaceholder ?? (isFr ? "Filtrer" : "Filter"));
57
+ const resolvedNoResultsLabel = $derived(noResultsLabel ?? (isFr ? "Aucun résultat" : "No results"));
58
+ const resolvedToggleLabel = $derived(toggleLabel ?? (isFr ? "Afficher les options" : "Toggle options"));
59
+ const resolvedRemoveLabel = $derived(removeLabel ?? (isFr ? "Supprimer" : "Remove"));
60
+
52
61
  let expanded = $state(false);
53
62
  let query = $state("");
54
63
 
@@ -112,7 +121,7 @@
112
121
  <button
113
122
  type="button"
114
123
  class="st-multiSelect__tagRemove"
115
- aria-label={`${removeLabel} ${option.label}`}
124
+ aria-label={`${resolvedRemoveLabel} ${option.label}`}
116
125
  {disabled}
117
126
  onclick={() => removeOption(option.value)}
118
127
  >
@@ -132,7 +141,7 @@
132
141
  onclick={toggleOpen}
133
142
  >
134
143
  {#if selectedOptions.length === 0}
135
- <span class="st-multiSelect__placeholder">{placeholder}</span>
144
+ <span class="st-multiSelect__placeholder">{resolvedPlaceholder}</span>
136
145
  {:else}
137
146
  <span class="st-multiSelect__count">{selectedOptions.length} selected</span>
138
147
  {/if}
@@ -143,7 +152,7 @@
143
152
  strokeWidth={2.25}
144
153
  />
145
154
  </span>
146
- <span class="st-visually-hidden">{toggleLabel}</span>
155
+ <span class="st-visually-hidden">{resolvedToggleLabel}</span>
147
156
  </button>
148
157
  </span>
149
158
  {#if expanded}
@@ -151,13 +160,13 @@
151
160
  <input
152
161
  type="search"
153
162
  class="st-multiSelect__search"
154
- placeholder={searchPlaceholder}
163
+ placeholder={resolvedSearchPlaceholder}
155
164
  bind:value={query}
156
- aria-label={searchPlaceholder}
165
+ aria-label={resolvedSearchPlaceholder}
157
166
  />
158
167
  <div class="st-multiSelect__list" role="listbox" aria-label={listLabel ?? label ?? "Options"} aria-multiselectable="true">
159
168
  {#if filtered.length === 0}
160
- <div class="st-multiSelect__empty">{noResultsLabel}</div>
169
+ <div class="st-multiSelect__empty">{resolvedNoResultsLabel}</div>
161
170
  {:else}
162
171
  {#each filtered as option (option.value)}
163
172
  {@const isSelected = selected.includes(option.value)}
@@ -12,6 +12,7 @@ type MultiSelectProps = Omit<HTMLAttributes<HTMLDivElement>, "class" | "onchange
12
12
  size?: "sm" | "md" | "lg";
13
13
  options: MultiSelectOption[];
14
14
  selected?: string[];
15
+ locale?: string;
15
16
  placeholder?: string;
16
17
  searchPlaceholder?: string;
17
18
  noResultsLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"MultiSelect.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MultiSelect.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACzC,CAAC;AAqIJ,QAAA,MAAM,WAAW,8DAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MultiSelect.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MultiSelect.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACzC,CAAC;AA6IJ,QAAA,MAAM,WAAW,8DAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -87,8 +87,8 @@
87
87
  selected = $bindable(false),
88
88
  disabled = false,
89
89
  href,
90
- leading,
91
- trailing,
90
+ leading: leadingProp,
91
+ trailing: trailingProp,
92
92
  divider = false,
93
93
  class: className
94
94
  }: NavItemProps = $props();
@@ -150,8 +150,8 @@
150
150
  caption={caption ? captionSnippet : undefined}
151
151
  >
152
152
  {#snippet leading()}
153
- {#if leading}
154
- {@render leading()}
153
+ {#if leadingProp}
154
+ {@render leadingProp()}
155
155
  {:else if swatch}
156
156
  <!-- Tête : ColorSwatch pour une couleur arbitraire, sinon StatusDot pour
157
157
  un ton sémantique. Décoratif → aria géré par la primitive. -->
@@ -168,8 +168,8 @@
168
168
  {/snippet}
169
169
 
170
170
  {#snippet trailing()}
171
- {#if trailing}
172
- {@render trailing()}
171
+ {#if trailingProp}
172
+ {@render trailingProp()}
173
173
  {:else if count != null}
174
174
  <!-- Queue : bulle de compte. Badge shape="circle" size="sm" (tabular-nums),
175
175
  ton sémantique aligné sur le `status` de la rangée. aria-label explicite. -->