@vantageos/mosaic 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +145 -0
- package/README.md +193 -0
- package/dist/Alert.schema-LPJE5gFP.d.cts +71 -0
- package/dist/Alert.schema-LPJE5gFP.d.ts +71 -0
- package/dist/ConfirmDialog-B3CQQGmJ.d.cts +34 -0
- package/dist/ConfirmDialog-B3CQQGmJ.d.ts +34 -0
- package/dist/MarkdownRenderer.schema-Rx7kIeVA.d.cts +22 -0
- package/dist/MarkdownRenderer.schema-Rx7kIeVA.d.ts +22 -0
- package/dist/ProgressBar.schema-CdVYx0Wq.d.cts +22 -0
- package/dist/ProgressBar.schema-CdVYx0Wq.d.ts +22 -0
- package/dist/StatusBadge.schema-1tOjB4Ir.d.cts +22 -0
- package/dist/StatusBadge.schema-1tOjB4Ir.d.ts +22 -0
- package/dist/Tabs.schema-BzcEyeq8.d.cts +79 -0
- package/dist/Tabs.schema-BzcEyeq8.d.ts +79 -0
- package/dist/artifacts.cjs +144 -2
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.d.cts +3 -21
- package/dist/artifacts.d.ts +3 -21
- package/dist/artifacts.js +144 -2
- package/dist/artifacts.js.map +1 -1
- package/dist/confirmation.cjs +168 -2
- package/dist/confirmation.cjs.map +1 -1
- package/dist/confirmation.d.cts +24 -20
- package/dist/confirmation.d.ts +24 -20
- package/dist/confirmation.js +165 -3
- package/dist/confirmation.js.map +1 -1
- package/dist/display.cjs +272 -2
- package/dist/display.cjs.map +1 -1
- package/dist/display.d.cts +132 -1
- package/dist/display.d.ts +132 -1
- package/dist/display.js +267 -3
- package/dist/display.js.map +1 -1
- package/dist/forms.cjs +1415 -0
- package/dist/forms.cjs.map +1 -0
- package/dist/forms.d.cts +159 -0
- package/dist/forms.d.ts +159 -0
- package/dist/forms.js +1334 -0
- package/dist/forms.js.map +1 -0
- package/dist/index-CwXVgtGb.d.cts +917 -0
- package/dist/index-CwXVgtGb.d.ts +917 -0
- package/dist/index.cjs +315 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -6
- package/dist/index.d.ts +11 -6
- package/dist/index.js +304 -3
- package/dist/index.js.map +1 -1
- package/dist/input.cjs +19 -0
- package/dist/input.cjs.map +1 -1
- package/dist/input.d.cts +4 -34
- package/dist/input.d.ts +4 -34
- package/dist/input.js +18 -1
- package/dist/input.js.map +1 -1
- package/dist/media.cjs +144 -2
- package/dist/media.cjs.map +1 -1
- package/dist/media.d.cts +3 -21
- package/dist/media.d.ts +3 -21
- package/dist/media.js +144 -2
- package/dist/media.js.map +1 -1
- package/dist/preact/artifacts.d.ts +39 -1
- package/dist/preact/artifacts.js +234 -0
- package/dist/preact/artifacts.js.map +1 -1
- package/dist/preact/confirmation.d.ts +115 -1
- package/dist/preact/confirmation.js +503 -0
- package/dist/preact/confirmation.js.map +1 -1
- package/dist/preact/display.d.ts +366 -1
- package/dist/preact/display.js +774 -0
- package/dist/preact/display.js.map +1 -1
- package/dist/preact/forms.d.ts +875 -0
- package/dist/preact/forms.js +1326 -0
- package/dist/preact/forms.js.map +1 -0
- package/dist/preact/input.d.ts +88 -1
- package/dist/preact/input.js +194 -0
- package/dist/preact/input.js.map +1 -1
- package/dist/preact/progress.d.ts +35 -1
- package/dist/preact/progress.js +263 -0
- package/dist/preact/progress.js.map +1 -1
- package/dist/progress.cjs +144 -2
- package/dist/progress.cjs.map +1 -1
- package/dist/progress.d.cts +3 -21
- package/dist/progress.d.ts +3 -21
- package/dist/progress.js +144 -2
- package/dist/progress.js.map +1 -1
- package/dist/react/artifacts.cjs +241 -0
- package/dist/react/artifacts.cjs.map +1 -1
- package/dist/react/artifacts.d.cts +20 -1
- package/dist/react/artifacts.d.ts +20 -1
- package/dist/react/artifacts.js +234 -0
- package/dist/react/artifacts.js.map +1 -1
- package/dist/react/confirmation.cjs +513 -0
- package/dist/react/confirmation.cjs.map +1 -1
- package/dist/react/confirmation.d.cts +21 -1
- package/dist/react/confirmation.d.ts +21 -1
- package/dist/react/confirmation.js +503 -0
- package/dist/react/confirmation.js.map +1 -1
- package/dist/react/display.cjs +788 -0
- package/dist/react/display.cjs.map +1 -1
- package/dist/react/display.d.cts +129 -1
- package/dist/react/display.d.ts +129 -1
- package/dist/react/display.js +771 -0
- package/dist/react/display.js.map +1 -1
- package/dist/react/forms.cjs +1387 -0
- package/dist/react/forms.cjs.map +1 -0
- package/dist/react/forms.d.cts +5 -0
- package/dist/react/forms.d.ts +5 -0
- package/dist/react/forms.js +1326 -0
- package/dist/react/forms.js.map +1 -0
- package/dist/react/input.cjs +197 -0
- package/dist/react/input.cjs.map +1 -1
- package/dist/react/input.d.cts +13 -1
- package/dist/react/input.d.ts +13 -1
- package/dist/react/input.js +194 -0
- package/dist/react/input.js.map +1 -1
- package/dist/react/progress.cjs +266 -0
- package/dist/react/progress.cjs.map +1 -1
- package/dist/react/progress.d.cts +17 -1
- package/dist/react/progress.d.ts +17 -1
- package/dist/react/progress.js +263 -0
- package/dist/react/progress.js.map +1 -1
- package/package.json +87 -61
- package/registry.yaml +167 -1
package/dist/react/display.cjs
CHANGED
|
@@ -1,4 +1,792 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
var reactVirtual = require('@tanstack/react-virtual');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
|
|
8
|
+
// src/components/display/EmptyState.logic.ts
|
|
9
|
+
var ACTION_VARIANT_CLASSES = {
|
|
10
|
+
primary: "inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white shadow-sm transition-colors hover:bg-slate-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-900 disabled:pointer-events-none disabled:opacity-50",
|
|
11
|
+
secondary: "inline-flex items-center justify-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm transition-colors hover:bg-slate-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-400 disabled:pointer-events-none disabled:opacity-50"
|
|
12
|
+
};
|
|
13
|
+
var EmptyStatePropsSchema = zod.z.object({
|
|
14
|
+
title: zod.z.string().min(1),
|
|
15
|
+
description: zod.z.string().optional(),
|
|
16
|
+
action: zod.z.object({
|
|
17
|
+
label: zod.z.string().min(1),
|
|
18
|
+
variant: zod.z.enum(["primary", "secondary"]).default("primary")
|
|
19
|
+
}).optional(),
|
|
20
|
+
locale: zod.z.enum(["en", "fr"]).default("en")
|
|
21
|
+
});
|
|
22
|
+
function validateEmptyStateProps(raw) {
|
|
23
|
+
return EmptyStatePropsSchema.parse(raw);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/i18n/strings.ts
|
|
27
|
+
var EN = {
|
|
28
|
+
// ─── Non-forms components ──────────────────────────────────────────────────
|
|
29
|
+
"ProgressBar.aria.label": "Progress",
|
|
30
|
+
"ProgressBar.error.invalidProps": "ProgressBar: invalid props",
|
|
31
|
+
"ConfirmDialog.button.confirm": "Confirm",
|
|
32
|
+
"ConfirmDialog.button.cancel": "Cancel",
|
|
33
|
+
"ConfirmDialog.aria.dialog": "Confirmation dialog",
|
|
34
|
+
"TableView.aria.table": "Data table",
|
|
35
|
+
"TableView.pagination.next": "Next page",
|
|
36
|
+
"TableView.pagination.prev": "Previous page",
|
|
37
|
+
"TableView.empty.message": "No data to display",
|
|
38
|
+
"TableView.error.invalidProps": "TableView: invalid props",
|
|
39
|
+
"MarkdownRenderer.aria.content": "Rendered Markdown content",
|
|
40
|
+
"MarkdownRenderer.error.invalidProps": "MarkdownRenderer: invalid props",
|
|
41
|
+
"MarkdownRenderer.error.tooLong": "Content exceeds maximum length",
|
|
42
|
+
"TokenDisplayOnceModal.button.copy": "Copy token",
|
|
43
|
+
"TokenDisplayOnceModal.button.close": "Close",
|
|
44
|
+
"TokenDisplayOnceModal.warning.once": "This token will only be shown once. Copy it now.",
|
|
45
|
+
"TokenDisplayOnceModal.copied": "Copied",
|
|
46
|
+
"StatusBadge.aria.status": "Status",
|
|
47
|
+
"StatusBadge.error.invalidProps": "StatusBadge: invalid props",
|
|
48
|
+
"EmptyState.error.invalidProps": "EmptyState: invalid props",
|
|
49
|
+
"Toast.aria.close": "Close notification",
|
|
50
|
+
"Toast.error.invalidProps": "Toast: invalid props",
|
|
51
|
+
"Alert.aria.dismiss": "Dismiss alert",
|
|
52
|
+
"Alert.error.invalidProps": "Alert: invalid props",
|
|
53
|
+
"VirtualList.empty.message": "No items to display",
|
|
54
|
+
"VirtualList.error.invalidProps": "VirtualList: invalid props",
|
|
55
|
+
"Skeleton.aria.label": "Loading",
|
|
56
|
+
"Skeleton.error.invalidProps": "Skeleton: invalid props",
|
|
57
|
+
// ─── Forms — useMosaicForm ─────────────────────────────────────────────────
|
|
58
|
+
"useMosaicForm.error.invalidProps": "useMosaicForm: invalid options",
|
|
59
|
+
// ─── Forms — FormProvider ──────────────────────────────────────────────────
|
|
60
|
+
"FormProvider.error.invalidProps": "FormProvider: invalid props",
|
|
61
|
+
// ─── Forms — FormField ────────────────────────────────────────────────────
|
|
62
|
+
"FormField.error.invalidProps": "FormField: invalid props",
|
|
63
|
+
// ─── Forms — ErrorDisplay ─────────────────────────────────────────────────
|
|
64
|
+
"ErrorDisplay.error.required": "This field is required",
|
|
65
|
+
"ErrorDisplay.error.min": "Value is below the minimum",
|
|
66
|
+
"ErrorDisplay.error.max": "Value exceeds the maximum",
|
|
67
|
+
"ErrorDisplay.error.minLength": "Input is too short",
|
|
68
|
+
"ErrorDisplay.error.maxLength": "Input is too long",
|
|
69
|
+
"ErrorDisplay.error.pattern": "Invalid format",
|
|
70
|
+
"ErrorDisplay.error.email": "Enter a valid email address",
|
|
71
|
+
"ErrorDisplay.error.url": "Enter a valid URL",
|
|
72
|
+
"ErrorDisplay.error.generic": "Invalid value",
|
|
73
|
+
// ─── Forms — SubmitButton ─────────────────────────────────────────────────
|
|
74
|
+
"SubmitButton.aria.submit": "Submit form",
|
|
75
|
+
"SubmitButton.state.loading": "Submitting\u2026",
|
|
76
|
+
"SubmitButton.error.invalidProps": "SubmitButton: invalid props",
|
|
77
|
+
// ─── Forms — Input ────────────────────────────────────────────────────────
|
|
78
|
+
"Input.aria.label": "Input field",
|
|
79
|
+
"Input.error.required": "This field is required",
|
|
80
|
+
"Input.error.invalid": "Invalid value",
|
|
81
|
+
"Input.error.tooLong": "Input is too long",
|
|
82
|
+
"Input.error.tooShort": "Input is too short",
|
|
83
|
+
"Input.error.invalidProps": "Input: invalid props",
|
|
84
|
+
// ─── Forms — Textarea ─────────────────────────────────────────────────────
|
|
85
|
+
"Textarea.aria.label": "Text area",
|
|
86
|
+
"Textarea.error.required": "This field is required",
|
|
87
|
+
"Textarea.error.tooLong": "Text is too long",
|
|
88
|
+
"Textarea.counter.remaining": "characters remaining",
|
|
89
|
+
"Textarea.error.invalidProps": "Textarea: invalid props",
|
|
90
|
+
// ─── Forms — FieldArray ───────────────────────────────────────────────────
|
|
91
|
+
"FieldArray.aria.list": "List of items",
|
|
92
|
+
"FieldArray.aria.addItem": "Add item",
|
|
93
|
+
"FieldArray.aria.removeItem": "Remove item",
|
|
94
|
+
"FieldArray.error.invalidProps": "FieldArray: invalid props",
|
|
95
|
+
// ─── Forms — Checkbox ─────────────────────────────────────────────────────
|
|
96
|
+
"Checkbox.aria.label": "Checkbox",
|
|
97
|
+
"Checkbox.error.required": "This field must be checked",
|
|
98
|
+
"Checkbox.error.invalidProps": "Checkbox: invalid props",
|
|
99
|
+
// ─── Forms — MultiSelect ──────────────────────────────────────────────────
|
|
100
|
+
"MultiSelect.aria.label": "Multi-select field",
|
|
101
|
+
"MultiSelect.aria.removeChip": "Remove",
|
|
102
|
+
"MultiSelect.error.required": "Select at least one option",
|
|
103
|
+
"MultiSelect.error.maxItems": "Maximum number of selections reached",
|
|
104
|
+
"MultiSelect.placeholder": "Select options\u2026",
|
|
105
|
+
"MultiSelect.search.placeholder": "Search\u2026",
|
|
106
|
+
"MultiSelect.empty": "No options available",
|
|
107
|
+
"MultiSelect.error.invalidProps": "MultiSelect: invalid props",
|
|
108
|
+
// ─── Forms — RadioGroup ───────────────────────────────────────────────────
|
|
109
|
+
"RadioGroup.aria.label": "Radio group",
|
|
110
|
+
"RadioGroup.error.required": "Select one option",
|
|
111
|
+
"RadioGroup.error.invalidProps": "RadioGroup: invalid props",
|
|
112
|
+
// ─── Forms — Select ───────────────────────────────────────────────────────
|
|
113
|
+
"Select.placeholder": "Select an option\u2026",
|
|
114
|
+
"Select.search.placeholder": "Search\u2026",
|
|
115
|
+
"Select.empty": "No options available",
|
|
116
|
+
"Select.error.required": "Select an option",
|
|
117
|
+
"Select.error.invalidProps": "Select: invalid props"
|
|
118
|
+
};
|
|
119
|
+
var FR = {
|
|
120
|
+
// ─── Non-forms components ──────────────────────────────────────────────────
|
|
121
|
+
"ProgressBar.aria.label": "Progression",
|
|
122
|
+
"ProgressBar.error.invalidProps": "ProgressBar : propri\xE9t\xE9s invalides",
|
|
123
|
+
"ConfirmDialog.button.confirm": "Confirmer",
|
|
124
|
+
"ConfirmDialog.button.cancel": "Annuler",
|
|
125
|
+
"ConfirmDialog.aria.dialog": "Bo\xEEte de dialogue de confirmation",
|
|
126
|
+
"TableView.aria.table": "Tableau de donn\xE9es",
|
|
127
|
+
"TableView.pagination.next": "Page suivante",
|
|
128
|
+
"TableView.pagination.prev": "Page pr\xE9c\xE9dente",
|
|
129
|
+
"TableView.empty.message": "Aucune donn\xE9e \xE0 afficher",
|
|
130
|
+
"TableView.error.invalidProps": "TableView : propri\xE9t\xE9s invalides",
|
|
131
|
+
"MarkdownRenderer.aria.content": "Contenu Markdown rendu",
|
|
132
|
+
"MarkdownRenderer.error.invalidProps": "MarkdownRenderer : propri\xE9t\xE9s invalides",
|
|
133
|
+
"MarkdownRenderer.error.tooLong": "Le contenu d\xE9passe la longueur maximale",
|
|
134
|
+
"TokenDisplayOnceModal.button.copy": "Copier le jeton",
|
|
135
|
+
"TokenDisplayOnceModal.button.close": "Fermer",
|
|
136
|
+
"TokenDisplayOnceModal.warning.once": "Ce jeton ne sera affich\xE9 qu'une seule fois. Copiez-le maintenant.",
|
|
137
|
+
"TokenDisplayOnceModal.copied": "Copi\xE9",
|
|
138
|
+
"StatusBadge.aria.status": "Statut",
|
|
139
|
+
"StatusBadge.error.invalidProps": "StatusBadge : propri\xE9t\xE9s invalides",
|
|
140
|
+
"EmptyState.error.invalidProps": "EmptyState : propri\xE9t\xE9s invalides",
|
|
141
|
+
"Toast.aria.close": "Fermer la notification",
|
|
142
|
+
"Toast.error.invalidProps": "Toast : propri\xE9t\xE9s invalides",
|
|
143
|
+
"Alert.aria.dismiss": "Fermer l'alerte",
|
|
144
|
+
"Alert.error.invalidProps": "Alert : propri\xE9t\xE9s invalides",
|
|
145
|
+
"VirtualList.empty.message": "Aucun \xE9l\xE9ment \xE0 afficher",
|
|
146
|
+
"VirtualList.error.invalidProps": "VirtualList : propri\xE9t\xE9s invalides",
|
|
147
|
+
"Skeleton.aria.label": "Chargement",
|
|
148
|
+
"Skeleton.error.invalidProps": "Skeleton : propri\xE9t\xE9s invalides",
|
|
149
|
+
// ─── Forms — useMosaicForm ─────────────────────────────────────────────────
|
|
150
|
+
"useMosaicForm.error.invalidProps": "useMosaicForm : options invalides",
|
|
151
|
+
// ─── Forms — FormProvider ──────────────────────────────────────────────────
|
|
152
|
+
"FormProvider.error.invalidProps": "FormProvider : propri\xE9t\xE9s invalides",
|
|
153
|
+
// ─── Forms — FormField ────────────────────────────────────────────────────
|
|
154
|
+
"FormField.error.invalidProps": "FormField : propri\xE9t\xE9s invalides",
|
|
155
|
+
// ─── Forms — ErrorDisplay ─────────────────────────────────────────────────
|
|
156
|
+
"ErrorDisplay.error.required": "Ce champ est obligatoire",
|
|
157
|
+
"ErrorDisplay.error.min": "La valeur est inf\xE9rieure au minimum",
|
|
158
|
+
"ErrorDisplay.error.max": "La valeur d\xE9passe le maximum",
|
|
159
|
+
"ErrorDisplay.error.minLength": "La saisie est trop courte",
|
|
160
|
+
"ErrorDisplay.error.maxLength": "La saisie est trop longue",
|
|
161
|
+
"ErrorDisplay.error.pattern": "Format invalide",
|
|
162
|
+
"ErrorDisplay.error.email": "Saisissez une adresse e-mail valide",
|
|
163
|
+
"ErrorDisplay.error.url": "Saisissez une URL valide",
|
|
164
|
+
"ErrorDisplay.error.generic": "Valeur invalide",
|
|
165
|
+
// ─── Forms — SubmitButton ─────────────────────────────────────────────────
|
|
166
|
+
"SubmitButton.aria.submit": "Soumettre le formulaire",
|
|
167
|
+
"SubmitButton.state.loading": "Envoi en cours\u2026",
|
|
168
|
+
"SubmitButton.error.invalidProps": "SubmitButton : propri\xE9t\xE9s invalides",
|
|
169
|
+
// ─── Forms — Input ────────────────────────────────────────────────────────
|
|
170
|
+
"Input.aria.label": "Champ de saisie",
|
|
171
|
+
"Input.error.required": "Ce champ est obligatoire",
|
|
172
|
+
"Input.error.invalid": "Valeur invalide",
|
|
173
|
+
"Input.error.tooLong": "La saisie est trop longue",
|
|
174
|
+
"Input.error.tooShort": "La saisie est trop courte",
|
|
175
|
+
"Input.error.invalidProps": "Input : propri\xE9t\xE9s invalides",
|
|
176
|
+
// ─── Forms — Textarea ─────────────────────────────────────────────────────
|
|
177
|
+
"Textarea.aria.label": "Zone de texte",
|
|
178
|
+
"Textarea.error.required": "Ce champ est obligatoire",
|
|
179
|
+
"Textarea.error.tooLong": "Le texte est trop long",
|
|
180
|
+
"Textarea.counter.remaining": "caract\xE8res restants",
|
|
181
|
+
"Textarea.error.invalidProps": "Textarea : propri\xE9t\xE9s invalides",
|
|
182
|
+
// ─── Forms — FieldArray ───────────────────────────────────────────────────
|
|
183
|
+
"FieldArray.aria.list": "Liste d'\xE9l\xE9ments",
|
|
184
|
+
"FieldArray.aria.addItem": "Ajouter un \xE9l\xE9ment",
|
|
185
|
+
"FieldArray.aria.removeItem": "Supprimer l'\xE9l\xE9ment",
|
|
186
|
+
"FieldArray.error.invalidProps": "FieldArray : propri\xE9t\xE9s invalides",
|
|
187
|
+
// ─── Forms — Checkbox ─────────────────────────────────────────────────────
|
|
188
|
+
"Checkbox.aria.label": "Case \xE0 cocher",
|
|
189
|
+
"Checkbox.error.required": "Ce champ doit \xEAtre coch\xE9",
|
|
190
|
+
"Checkbox.error.invalidProps": "Checkbox : propri\xE9t\xE9s invalides",
|
|
191
|
+
// ─── Forms — MultiSelect ──────────────────────────────────────────────────
|
|
192
|
+
"MultiSelect.aria.label": "Champ de s\xE9lection multiple",
|
|
193
|
+
"MultiSelect.aria.removeChip": "Retirer",
|
|
194
|
+
"MultiSelect.error.required": "S\xE9lectionnez au moins une option",
|
|
195
|
+
"MultiSelect.error.maxItems": "Nombre maximum de s\xE9lections atteint",
|
|
196
|
+
"MultiSelect.placeholder": "S\xE9lectionner des options\u2026",
|
|
197
|
+
"MultiSelect.search.placeholder": "Rechercher\u2026",
|
|
198
|
+
"MultiSelect.empty": "Aucune option disponible",
|
|
199
|
+
"MultiSelect.error.invalidProps": "MultiSelect : propri\xE9t\xE9s invalides",
|
|
200
|
+
// ─── Forms — RadioGroup ───────────────────────────────────────────────────
|
|
201
|
+
"RadioGroup.aria.label": "Groupe de boutons radio",
|
|
202
|
+
"RadioGroup.error.required": "S\xE9lectionnez une option",
|
|
203
|
+
"RadioGroup.error.invalidProps": "RadioGroup : propri\xE9t\xE9s invalides",
|
|
204
|
+
// ─── Forms — Select ───────────────────────────────────────────────────────
|
|
205
|
+
"Select.placeholder": "S\xE9lectionner une option\u2026",
|
|
206
|
+
"Select.search.placeholder": "Rechercher\u2026",
|
|
207
|
+
"Select.empty": "Aucune option disponible",
|
|
208
|
+
"Select.error.required": "S\xE9lectionnez une option",
|
|
209
|
+
"Select.error.invalidProps": "Select : propri\xE9t\xE9s invalides"
|
|
210
|
+
};
|
|
211
|
+
var TABLE = {
|
|
212
|
+
en: EN,
|
|
213
|
+
fr: FR
|
|
214
|
+
};
|
|
215
|
+
function t(key, locale = "en") {
|
|
216
|
+
return TABLE[locale]?.[key] ?? TABLE.en[key];
|
|
217
|
+
}
|
|
218
|
+
function EmptyStateInner({
|
|
219
|
+
icon,
|
|
220
|
+
title,
|
|
221
|
+
description,
|
|
222
|
+
action,
|
|
223
|
+
locale: _locale
|
|
224
|
+
}) {
|
|
225
|
+
const variant = action?.variant ?? "primary";
|
|
226
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
227
|
+
"section",
|
|
228
|
+
{
|
|
229
|
+
"aria-label": title,
|
|
230
|
+
className: "flex flex-col items-center justify-center gap-4 px-6 py-12 text-center",
|
|
231
|
+
children: [
|
|
232
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-slate-400", children: icon }),
|
|
233
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold text-slate-900", children: title }),
|
|
234
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-sm text-sm leading-relaxed text-slate-500", children: description }),
|
|
235
|
+
action && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: action.onClick, className: ACTION_VARIANT_CLASSES[variant], children: action.label })
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
function EmptyState(raw) {
|
|
241
|
+
try {
|
|
242
|
+
const parsed = validateEmptyStateProps(raw);
|
|
243
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
244
|
+
EmptyStateInner,
|
|
245
|
+
{
|
|
246
|
+
...parsed,
|
|
247
|
+
icon: raw.icon,
|
|
248
|
+
action: parsed.action && raw.action?.onClick ? { ...parsed.action, onClick: raw.action.onClick } : void 0
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
} catch (err) {
|
|
252
|
+
console.error("[EmptyState] Invalid props \u2014 component will not render.", err);
|
|
253
|
+
const locale = raw.locale === "fr" ? "fr" : "en";
|
|
254
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { role: "alert", children: t("EmptyState.error.invalidProps", locale) });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/components/display/Skeleton.logic.ts
|
|
259
|
+
function getAnimationClass(animation) {
|
|
260
|
+
switch (animation) {
|
|
261
|
+
case "pulse":
|
|
262
|
+
return "animate-pulse";
|
|
263
|
+
case "wave":
|
|
264
|
+
return "skeleton-wave";
|
|
265
|
+
case "none":
|
|
266
|
+
return "";
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function getVariantClass(variant) {
|
|
270
|
+
switch (variant) {
|
|
271
|
+
case "rect":
|
|
272
|
+
return "rounded-md";
|
|
273
|
+
case "circle":
|
|
274
|
+
return "rounded-full";
|
|
275
|
+
case "text":
|
|
276
|
+
return "rounded";
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
var SKELETON_BG_CLASS = "bg-gray-200 dark:bg-gray-700";
|
|
280
|
+
function textLineKey(index) {
|
|
281
|
+
return `skeleton-line-${index}`;
|
|
282
|
+
}
|
|
283
|
+
function lastLineWidth(index, total, baseWidth) {
|
|
284
|
+
if (total > 1 && index === total - 1) {
|
|
285
|
+
return "75%";
|
|
286
|
+
}
|
|
287
|
+
return baseWidth;
|
|
288
|
+
}
|
|
289
|
+
var SkeletonPropsSchema = zod.z.object({
|
|
290
|
+
variant: zod.z.enum(["rect", "circle", "text"]).default("rect"),
|
|
291
|
+
width: zod.z.union([zod.z.string().min(1), zod.z.number().positive()]).optional(),
|
|
292
|
+
height: zod.z.union([zod.z.string().min(1), zod.z.number().positive()]).optional(),
|
|
293
|
+
count: zod.z.number().int().min(1).max(20).default(1),
|
|
294
|
+
animation: zod.z.enum(["pulse", "wave", "none"]).default("pulse"),
|
|
295
|
+
locale: zod.z.enum(["en", "fr"]).default("en")
|
|
296
|
+
});
|
|
297
|
+
function validateSkeletonProps(raw) {
|
|
298
|
+
return SkeletonPropsSchema.parse(raw);
|
|
299
|
+
}
|
|
300
|
+
function resolveSkeletonDimensions(variant, width, height) {
|
|
301
|
+
const toCss = (v, fallback) => {
|
|
302
|
+
if (v === void 0) return fallback;
|
|
303
|
+
if (typeof v === "number") return `${v}px`;
|
|
304
|
+
return v;
|
|
305
|
+
};
|
|
306
|
+
if (variant === "circle") {
|
|
307
|
+
const size = width !== void 0 ? toCss(width, "40px") : height !== void 0 ? toCss(height, "40px") : "40px";
|
|
308
|
+
return { widthCss: size, heightCss: size };
|
|
309
|
+
}
|
|
310
|
+
if (variant === "text") {
|
|
311
|
+
return {
|
|
312
|
+
widthCss: toCss(width, "100%"),
|
|
313
|
+
heightCss: toCss(height, "16px")
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
widthCss: toCss(width, "100%"),
|
|
318
|
+
heightCss: toCss(height, "100px")
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function SkeletonInner({ variant, width, height, count, animation, locale }) {
|
|
322
|
+
const { widthCss, heightCss } = resolveSkeletonDimensions(variant, width, height);
|
|
323
|
+
const animClass = getAnimationClass(animation);
|
|
324
|
+
const variantClass = getVariantClass(variant);
|
|
325
|
+
const ariaLabel = t("Skeleton.aria.label", locale);
|
|
326
|
+
const baseClass = `${SKELETON_BG_CLASS} ${variantClass} ${animClass}`.trim();
|
|
327
|
+
if (variant === "text") {
|
|
328
|
+
return (
|
|
329
|
+
// biome-ignore lint/a11y/useSemanticElements: role="status" is the correct ARIA pattern for loading indicators; <output> conveys form output semantics which is incorrect here
|
|
330
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-label": ariaLabel, "aria-busy": "true", className: "flex flex-col gap-2", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
331
|
+
"span",
|
|
332
|
+
{
|
|
333
|
+
className: `block ${baseClass}`,
|
|
334
|
+
style: {
|
|
335
|
+
width: lastLineWidth(i, count, widthCss),
|
|
336
|
+
height: heightCss
|
|
337
|
+
},
|
|
338
|
+
"aria-hidden": "true"
|
|
339
|
+
},
|
|
340
|
+
textLineKey(i)
|
|
341
|
+
)) })
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
345
|
+
"div",
|
|
346
|
+
{
|
|
347
|
+
role: "status",
|
|
348
|
+
"aria-label": ariaLabel,
|
|
349
|
+
"aria-busy": "true",
|
|
350
|
+
className: `block ${baseClass}`,
|
|
351
|
+
style: { width: widthCss, height: heightCss }
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
function Skeleton(raw) {
|
|
356
|
+
try {
|
|
357
|
+
const props = validateSkeletonProps(raw);
|
|
358
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SkeletonInner, { ...props });
|
|
359
|
+
} catch {
|
|
360
|
+
const locale = raw.locale === "fr" ? "fr" : "en";
|
|
361
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { role: "alert", className: "text-red-600 text-sm", children: t("Skeleton.error.invalidProps", locale) });
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
var VirtualListPropsSchema = zod.z.object({
|
|
365
|
+
/** Array of items to render — required, can be empty */
|
|
366
|
+
items: zod.z.array(zod.z.unknown()),
|
|
367
|
+
/** Fixed row height in px — mutually exclusive with estimateSize */
|
|
368
|
+
itemHeight: zod.z.number().positive().optional(),
|
|
369
|
+
/** Variable row height estimator — mutually exclusive with itemHeight */
|
|
370
|
+
estimateSize: zod.z.function().args(zod.z.number()).returns(zod.z.number()).optional(),
|
|
371
|
+
/** Row renderer — required (runtime function, excluded from strict Zod parse but validated for presence) */
|
|
372
|
+
renderItem: zod.z.function().args(zod.z.unknown(), zod.z.number()).returns(zod.z.unknown()).optional(),
|
|
373
|
+
/** Rows to render outside visible area (default: 5) */
|
|
374
|
+
overscan: zod.z.number().int().min(0).optional(),
|
|
375
|
+
/** CSS class applied to the scroll container */
|
|
376
|
+
className: zod.z.string().optional(),
|
|
377
|
+
/** Locale for built-in empty state + error messages */
|
|
378
|
+
locale: zod.z.enum(["en", "fr"]).optional(),
|
|
379
|
+
/** a11y: when provided, rows become keyboard-activable (role=button + tabIndex=0 + Enter/Space) */
|
|
380
|
+
onRowClick: zod.z.function().args(zod.z.unknown(), zod.z.number()).returns(zod.z.void()).optional()
|
|
381
|
+
});
|
|
382
|
+
function validateVirtualListProps(raw) {
|
|
383
|
+
return VirtualListPropsSchema.parse(raw);
|
|
384
|
+
}
|
|
385
|
+
var DEFAULT_OVERSCAN = 5;
|
|
386
|
+
var DEFAULT_ITEM_HEIGHT = 40;
|
|
387
|
+
function VirtualList(props) {
|
|
388
|
+
try {
|
|
389
|
+
validateVirtualListProps({
|
|
390
|
+
items: props.items,
|
|
391
|
+
itemHeight: props.itemHeight,
|
|
392
|
+
overscan: props.overscan,
|
|
393
|
+
className: props.className,
|
|
394
|
+
locale: props.locale
|
|
395
|
+
});
|
|
396
|
+
} catch {
|
|
397
|
+
const locale2 = props.locale === "fr" ? "fr" : "en";
|
|
398
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", children: t("VirtualList.error.invalidProps", locale2) });
|
|
399
|
+
}
|
|
400
|
+
const locale = props.locale === "fr" ? "fr" : "en";
|
|
401
|
+
if (props.items.length === 0) {
|
|
402
|
+
return /* @__PURE__ */ jsxRuntime.jsx("output", { "aria-live": "polite", children: t("VirtualList.empty.message", locale) });
|
|
403
|
+
}
|
|
404
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
405
|
+
VirtualListInner,
|
|
406
|
+
{
|
|
407
|
+
items: props.items,
|
|
408
|
+
itemHeight: props.itemHeight,
|
|
409
|
+
estimateSize: props.estimateSize,
|
|
410
|
+
renderItem: props.renderItem,
|
|
411
|
+
onRowClick: props.onRowClick,
|
|
412
|
+
overscan: props.overscan ?? DEFAULT_OVERSCAN,
|
|
413
|
+
className: props.className,
|
|
414
|
+
locale
|
|
415
|
+
}
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
function VirtualListInner({
|
|
419
|
+
items,
|
|
420
|
+
itemHeight,
|
|
421
|
+
estimateSize,
|
|
422
|
+
renderItem,
|
|
423
|
+
onRowClick,
|
|
424
|
+
overscan,
|
|
425
|
+
className
|
|
426
|
+
}) {
|
|
427
|
+
const scrollRef = react.useRef(null);
|
|
428
|
+
const resolvedEstimateSize = react.useCallback(
|
|
429
|
+
(index) => {
|
|
430
|
+
if (estimateSize) return estimateSize(index);
|
|
431
|
+
return itemHeight ?? DEFAULT_ITEM_HEIGHT;
|
|
432
|
+
},
|
|
433
|
+
[estimateSize, itemHeight]
|
|
434
|
+
);
|
|
435
|
+
const rowVirtualizer = reactVirtual.useVirtualizer({
|
|
436
|
+
count: items.length,
|
|
437
|
+
/* v8 ignore next 1 */
|
|
438
|
+
getScrollElement: () => scrollRef.current,
|
|
439
|
+
estimateSize: resolvedEstimateSize,
|
|
440
|
+
overscan
|
|
441
|
+
});
|
|
442
|
+
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
443
|
+
const totalSize = rowVirtualizer.getTotalSize();
|
|
444
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
445
|
+
"div",
|
|
446
|
+
{
|
|
447
|
+
"data-virtual": "true",
|
|
448
|
+
ref: scrollRef,
|
|
449
|
+
className,
|
|
450
|
+
style: { height: 400, overflow: "auto", position: "relative" },
|
|
451
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: `${totalSize}px`, position: "relative" }, children: virtualItems.map((virtualRow) => {
|
|
452
|
+
const item = items[virtualRow.index];
|
|
453
|
+
const index = virtualRow.index;
|
|
454
|
+
const rowProps = onRowClick ? {
|
|
455
|
+
role: "button",
|
|
456
|
+
tabIndex: 0,
|
|
457
|
+
"data-list-row": true,
|
|
458
|
+
style: {
|
|
459
|
+
position: "absolute",
|
|
460
|
+
top: 0,
|
|
461
|
+
left: 0,
|
|
462
|
+
width: "100%",
|
|
463
|
+
transform: `translateY(${virtualRow.start}px)`,
|
|
464
|
+
cursor: "pointer"
|
|
465
|
+
},
|
|
466
|
+
onClick: () => onRowClick(item, index),
|
|
467
|
+
onKeyDown: (e) => {
|
|
468
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
469
|
+
e.preventDefault();
|
|
470
|
+
onRowClick(item, index);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
} : {
|
|
474
|
+
"data-list-row": true,
|
|
475
|
+
style: {
|
|
476
|
+
position: "absolute",
|
|
477
|
+
top: 0,
|
|
478
|
+
left: 0,
|
|
479
|
+
width: "100%",
|
|
480
|
+
transform: `translateY(${virtualRow.start}px)`
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ...rowProps, children: renderItem(item, index) }, virtualRow.key);
|
|
484
|
+
}) })
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
var StatusBadgePropsSchema = zod.z.object({
|
|
489
|
+
status: zod.z.string(),
|
|
490
|
+
variant: zod.z.enum(["success", "warning", "danger", "info", "neutral"]).default("neutral"),
|
|
491
|
+
label: zod.z.string().optional(),
|
|
492
|
+
locale: zod.z.enum(["en", "fr"])
|
|
493
|
+
});
|
|
494
|
+
function validateProps(raw) {
|
|
495
|
+
return StatusBadgePropsSchema.parse(raw);
|
|
496
|
+
}
|
|
497
|
+
var variantClasses = {
|
|
498
|
+
success: "bg-green-100 text-green-800 ring-1 ring-green-300",
|
|
499
|
+
warning: "bg-amber-100 text-amber-800 ring-1 ring-amber-300",
|
|
500
|
+
danger: "bg-red-100 text-red-800 ring-1 ring-red-300",
|
|
501
|
+
info: "bg-blue-100 text-blue-800 ring-1 ring-blue-300",
|
|
502
|
+
neutral: "bg-slate-100 text-slate-800 ring-1 ring-slate-300"
|
|
503
|
+
};
|
|
504
|
+
function StatusBadgeInner({ status, variant, label, locale }) {
|
|
505
|
+
const ariaLabel = label ?? status;
|
|
506
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
507
|
+
"output",
|
|
508
|
+
{
|
|
509
|
+
"aria-label": ariaLabel,
|
|
510
|
+
lang: locale,
|
|
511
|
+
className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${variantClasses[variant]}`,
|
|
512
|
+
children: label ?? status
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
function StatusBadge(raw) {
|
|
517
|
+
try {
|
|
518
|
+
const props = validateProps(raw);
|
|
519
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatusBadgeInner, { ...props });
|
|
520
|
+
} catch {
|
|
521
|
+
const locale = raw.locale === "fr" ? "fr" : "en";
|
|
522
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { role: "alert", children: t("StatusBadge.error.invalidProps", locale) });
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
var ColumnDefSchema = zod.z.object({
|
|
526
|
+
key: zod.z.string().min(1),
|
|
527
|
+
header: zod.z.string().min(1)
|
|
528
|
+
// render is a runtime function — excluded from Zod, typed separately
|
|
529
|
+
});
|
|
530
|
+
var TableViewPropsSchema = zod.z.object({
|
|
531
|
+
columns: zod.z.array(ColumnDefSchema).min(1, "TableView requires at least one column"),
|
|
532
|
+
virtualizeThreshold: zod.z.number().int().positive().default(100),
|
|
533
|
+
ariaLabel: zod.z.string().min(1),
|
|
534
|
+
locale: zod.z.enum(["en", "fr"]).default("en")
|
|
535
|
+
});
|
|
536
|
+
function validateTableViewProps(raw) {
|
|
537
|
+
return TableViewPropsSchema.parse(raw);
|
|
538
|
+
}
|
|
539
|
+
var OVERSCAN = 5;
|
|
540
|
+
function TableView(props) {
|
|
541
|
+
let validatedThreshold = 100;
|
|
542
|
+
try {
|
|
543
|
+
const validated = validateTableViewProps({
|
|
544
|
+
columns: props.columns.map(({ key, header }) => ({ key, header })),
|
|
545
|
+
virtualizeThreshold: props.virtualizeThreshold,
|
|
546
|
+
ariaLabel: props.ariaLabel,
|
|
547
|
+
locale: props.locale
|
|
548
|
+
});
|
|
549
|
+
validatedThreshold = validated.virtualizeThreshold;
|
|
550
|
+
} catch {
|
|
551
|
+
const locale = props.locale === "fr" ? "fr" : "en";
|
|
552
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", children: t("TableView.error.invalidProps", locale) });
|
|
553
|
+
}
|
|
554
|
+
const isVirtual = props.rows.length > validatedThreshold;
|
|
555
|
+
const resolvedLocale = props.locale === "fr" ? "fr" : "en";
|
|
556
|
+
if (isVirtual) {
|
|
557
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
558
|
+
VirtualTable,
|
|
559
|
+
{
|
|
560
|
+
rows: props.rows,
|
|
561
|
+
columns: props.columns,
|
|
562
|
+
ariaLabel: props.ariaLabel,
|
|
563
|
+
locale: resolvedLocale,
|
|
564
|
+
onRowClick: props.onRowClick
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
569
|
+
StaticTable,
|
|
570
|
+
{
|
|
571
|
+
rows: props.rows,
|
|
572
|
+
columns: props.columns,
|
|
573
|
+
ariaLabel: props.ariaLabel,
|
|
574
|
+
locale: resolvedLocale,
|
|
575
|
+
onRowClick: props.onRowClick
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
function StreamingTableView(props) {
|
|
580
|
+
let validatedThreshold = 100;
|
|
581
|
+
try {
|
|
582
|
+
const validated = validateTableViewProps({
|
|
583
|
+
columns: props.columns.map(({ key, header }) => ({ key, header })),
|
|
584
|
+
virtualizeThreshold: props.virtualizeThreshold,
|
|
585
|
+
ariaLabel: props.ariaLabel,
|
|
586
|
+
locale: props.locale
|
|
587
|
+
});
|
|
588
|
+
validatedThreshold = validated.virtualizeThreshold;
|
|
589
|
+
} catch {
|
|
590
|
+
const locale = props.locale === "fr" ? "fr" : "en";
|
|
591
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", children: t("TableView.error.invalidProps", locale) });
|
|
592
|
+
}
|
|
593
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
594
|
+
StreamingTableViewInner,
|
|
595
|
+
{
|
|
596
|
+
...props,
|
|
597
|
+
virtualizeThreshold: validatedThreshold,
|
|
598
|
+
onRowClick: props.onRowClick
|
|
599
|
+
}
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
function StreamingTableViewInner({
|
|
603
|
+
columns,
|
|
604
|
+
rows$,
|
|
605
|
+
virtualizeThreshold = 100,
|
|
606
|
+
ariaLabel,
|
|
607
|
+
locale,
|
|
608
|
+
onRowClick
|
|
609
|
+
}) {
|
|
610
|
+
const resolvedLocale = locale === "fr" ? "fr" : "en";
|
|
611
|
+
const [rows, setRows] = react.useState([]);
|
|
612
|
+
react.useEffect(() => {
|
|
613
|
+
setRows([]);
|
|
614
|
+
const sub = rows$.subscribe((chunk) => {
|
|
615
|
+
setRows((prev) => [...prev, ...chunk]);
|
|
616
|
+
});
|
|
617
|
+
return () => {
|
|
618
|
+
sub.unsubscribe();
|
|
619
|
+
};
|
|
620
|
+
}, [rows$]);
|
|
621
|
+
const isVirtual = rows.length > virtualizeThreshold;
|
|
622
|
+
if (isVirtual) {
|
|
623
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
624
|
+
VirtualTable,
|
|
625
|
+
{
|
|
626
|
+
rows,
|
|
627
|
+
columns,
|
|
628
|
+
ariaLabel,
|
|
629
|
+
locale: resolvedLocale,
|
|
630
|
+
onRowClick
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
635
|
+
StaticTable,
|
|
636
|
+
{
|
|
637
|
+
rows,
|
|
638
|
+
columns,
|
|
639
|
+
ariaLabel,
|
|
640
|
+
locale: resolvedLocale,
|
|
641
|
+
onRowClick
|
|
642
|
+
}
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
function renderCell(col, row) {
|
|
646
|
+
if (col.render) {
|
|
647
|
+
return col.render(row);
|
|
648
|
+
}
|
|
649
|
+
return String(row[col.key] ?? "");
|
|
650
|
+
}
|
|
651
|
+
function StaticTable({
|
|
652
|
+
rows,
|
|
653
|
+
columns,
|
|
654
|
+
ariaLabel,
|
|
655
|
+
locale,
|
|
656
|
+
onRowClick
|
|
657
|
+
}) {
|
|
658
|
+
const emptyMsg = t("TableView.empty.message", locale);
|
|
659
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
660
|
+
"table",
|
|
661
|
+
{
|
|
662
|
+
"aria-label": ariaLabel,
|
|
663
|
+
"aria-rowcount": rows.length,
|
|
664
|
+
style: { width: "100%", borderCollapse: "collapse" },
|
|
665
|
+
children: [
|
|
666
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: col.header }, col.key)) }) }),
|
|
667
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: columns.length, "aria-label": emptyMsg, children: emptyMsg }) }) : rows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
668
|
+
"tr",
|
|
669
|
+
{
|
|
670
|
+
"aria-rowindex": rowIndex + 2,
|
|
671
|
+
...onRowClick ? {
|
|
672
|
+
role: "button",
|
|
673
|
+
tabIndex: 0,
|
|
674
|
+
style: { cursor: "pointer" },
|
|
675
|
+
onClick: () => onRowClick(row, rowIndex),
|
|
676
|
+
onKeyDown: (e) => {
|
|
677
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
678
|
+
e.preventDefault();
|
|
679
|
+
onRowClick(row, rowIndex);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
} : {},
|
|
683
|
+
children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: renderCell(col, row) }, col.key))
|
|
684
|
+
},
|
|
685
|
+
row.id != null ? String(row.id) : `row-${rowIndex}`
|
|
686
|
+
)) })
|
|
687
|
+
]
|
|
688
|
+
}
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
function VirtualTable({
|
|
692
|
+
rows,
|
|
693
|
+
columns,
|
|
694
|
+
ariaLabel,
|
|
695
|
+
// locale reserved for future virtual-mode empty/pagination strings
|
|
696
|
+
locale: _locale,
|
|
697
|
+
onRowClick
|
|
698
|
+
}) {
|
|
699
|
+
const scrollRef = react.useRef(null);
|
|
700
|
+
const rowVirtualizer = reactVirtual.useVirtualizer({
|
|
701
|
+
count: rows.length,
|
|
702
|
+
/* v8 ignore next 1 */
|
|
703
|
+
getScrollElement: () => scrollRef.current,
|
|
704
|
+
estimateSize: react.useCallback(() => 40, []),
|
|
705
|
+
overscan: OVERSCAN
|
|
706
|
+
});
|
|
707
|
+
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
708
|
+
const totalSize = rowVirtualizer.getTotalSize();
|
|
709
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
710
|
+
"div",
|
|
711
|
+
{
|
|
712
|
+
"data-virtual": "true",
|
|
713
|
+
ref: scrollRef,
|
|
714
|
+
tabIndex: 0,
|
|
715
|
+
role: "region",
|
|
716
|
+
"aria-label": ariaLabel,
|
|
717
|
+
style: { height: 400, overflow: "auto", position: "relative" },
|
|
718
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
719
|
+
"table",
|
|
720
|
+
{
|
|
721
|
+
"aria-label": ariaLabel,
|
|
722
|
+
"aria-rowcount": rows.length,
|
|
723
|
+
style: { width: "100%", borderCollapse: "collapse" },
|
|
724
|
+
children: [
|
|
725
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: col.header }, col.key)) }) }),
|
|
726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
727
|
+
"tbody",
|
|
728
|
+
{
|
|
729
|
+
style: {
|
|
730
|
+
height: `${totalSize}px`,
|
|
731
|
+
position: "relative",
|
|
732
|
+
display: "block"
|
|
733
|
+
},
|
|
734
|
+
children: virtualItems.map((virtualRow) => {
|
|
735
|
+
const row = rows[virtualRow.index] ?? {};
|
|
736
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
737
|
+
"tr",
|
|
738
|
+
{
|
|
739
|
+
"aria-rowindex": virtualRow.index + 2,
|
|
740
|
+
style: {
|
|
741
|
+
position: "absolute",
|
|
742
|
+
top: 0,
|
|
743
|
+
left: 0,
|
|
744
|
+
width: "100%",
|
|
745
|
+
transform: `translateY(${virtualRow.start}px)`,
|
|
746
|
+
display: "flex",
|
|
747
|
+
...onRowClick ? { cursor: "pointer" } : {}
|
|
748
|
+
},
|
|
749
|
+
...onRowClick ? {
|
|
750
|
+
role: "button",
|
|
751
|
+
tabIndex: 0,
|
|
752
|
+
onClick: () => onRowClick(row, virtualRow.index),
|
|
753
|
+
onKeyDown: (e) => {
|
|
754
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
755
|
+
e.preventDefault();
|
|
756
|
+
onRowClick(row, virtualRow.index);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
} : {},
|
|
760
|
+
children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { style: { flex: 1 }, children: renderCell(col, row) }, col.key))
|
|
761
|
+
},
|
|
762
|
+
row.id != null ? String(row.id) : `vrow-${virtualRow.index}`
|
|
763
|
+
);
|
|
764
|
+
})
|
|
765
|
+
}
|
|
766
|
+
)
|
|
767
|
+
]
|
|
768
|
+
}
|
|
769
|
+
)
|
|
770
|
+
}
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
exports.EmptyState = EmptyState;
|
|
775
|
+
exports.EmptyStatePropsSchema = EmptyStatePropsSchema;
|
|
776
|
+
exports.Skeleton = Skeleton;
|
|
777
|
+
exports.SkeletonPropsSchema = SkeletonPropsSchema;
|
|
778
|
+
exports.StatusBadge = StatusBadge;
|
|
779
|
+
exports.StatusBadgePropsSchema = StatusBadgePropsSchema;
|
|
780
|
+
exports.StreamingTableView = StreamingTableView;
|
|
781
|
+
exports.TableView = TableView;
|
|
782
|
+
exports.TableViewPropsSchema = TableViewPropsSchema;
|
|
783
|
+
exports.VirtualList = VirtualList;
|
|
784
|
+
exports.VirtualListPropsSchema = VirtualListPropsSchema;
|
|
785
|
+
exports.resolveSkeletonDimensions = resolveSkeletonDimensions;
|
|
786
|
+
exports.validateEmptyStateProps = validateEmptyStateProps;
|
|
787
|
+
exports.validateSkeletonProps = validateSkeletonProps;
|
|
788
|
+
exports.validateStatusBadgeProps = validateProps;
|
|
789
|
+
exports.validateTableViewProps = validateTableViewProps;
|
|
790
|
+
exports.validateVirtualListProps = validateVirtualListProps;
|
|
3
791
|
//# sourceMappingURL=display.cjs.map
|
|
4
792
|
//# sourceMappingURL=display.cjs.map
|