@soulbatical/tetra-ui 0.1.0 → 0.1.2

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.

Potentially problematic release.


This version of @soulbatical/tetra-ui might be problematic. Click here for more details.

Files changed (69) hide show
  1. package/dist/components/FeatureFilters.d.ts +72 -0
  2. package/dist/components/FeatureFilters.d.ts.map +1 -0
  3. package/dist/components/FeatureFilters.js +229 -0
  4. package/dist/components/FeatureFilters.js.map +1 -0
  5. package/dist/components/FeatureForm.d.ts +100 -0
  6. package/dist/components/FeatureForm.d.ts.map +1 -0
  7. package/dist/components/FeatureForm.js +336 -0
  8. package/dist/components/FeatureForm.js.map +1 -0
  9. package/dist/components/FeatureTable.d.ts +95 -0
  10. package/dist/components/FeatureTable.d.ts.map +1 -0
  11. package/dist/components/FeatureTable.js +278 -0
  12. package/dist/components/FeatureTable.js.map +1 -0
  13. package/dist/components/ui/badge.d.ts +10 -0
  14. package/dist/components/ui/badge.d.ts.map +1 -0
  15. package/dist/components/ui/badge.js +21 -0
  16. package/dist/components/ui/badge.js.map +1 -0
  17. package/dist/components/ui/button.d.ts +12 -0
  18. package/dist/components/ui/button.d.ts.map +1 -0
  19. package/dist/components/ui/button.js +34 -0
  20. package/dist/components/ui/button.js.map +1 -0
  21. package/dist/components/ui/card.d.ts +9 -0
  22. package/dist/components/ui/card.d.ts.map +1 -0
  23. package/dist/components/ui/card.js +17 -0
  24. package/dist/components/ui/card.js.map +1 -0
  25. package/dist/components/ui/dialog.d.ts +20 -0
  26. package/dist/components/ui/dialog.d.ts.map +1 -0
  27. package/dist/components/ui/dialog.js +24 -0
  28. package/dist/components/ui/dialog.js.map +1 -0
  29. package/dist/components/ui/input.d.ts +6 -0
  30. package/dist/components/ui/input.d.ts.map +1 -0
  31. package/dist/components/ui/input.js +9 -0
  32. package/dist/components/ui/input.js.map +1 -0
  33. package/dist/components/ui/label.d.ts +8 -0
  34. package/dist/components/ui/label.d.ts.map +1 -0
  35. package/dist/components/ui/label.js +10 -0
  36. package/dist/components/ui/label.js.map +1 -0
  37. package/dist/components/ui/select.d.ts +14 -0
  38. package/dist/components/ui/select.d.ts.map +1 -0
  39. package/dist/components/ui/select.js +28 -0
  40. package/dist/components/ui/select.js.map +1 -0
  41. package/dist/components/ui/table.d.ts +11 -0
  42. package/dist/components/ui/table.d.ts.map +1 -0
  43. package/dist/components/ui/table.js +21 -0
  44. package/dist/components/ui/table.js.map +1 -0
  45. package/dist/components/ui/tabs.d.ts +8 -0
  46. package/dist/components/ui/tabs.d.ts.map +1 -0
  47. package/dist/components/ui/tabs.js +14 -0
  48. package/dist/components/ui/tabs.js.map +1 -0
  49. package/dist/components/ui/textarea.d.ts +6 -0
  50. package/dist/components/ui/textarea.d.ts.map +1 -0
  51. package/dist/components/ui/textarea.js +9 -0
  52. package/dist/components/ui/textarea.js.map +1 -0
  53. package/dist/hooks/useAffiliateDashboard.d.ts +86 -0
  54. package/dist/hooks/useAffiliateDashboard.d.ts.map +1 -0
  55. package/dist/hooks/useAffiliateDashboard.js +161 -0
  56. package/dist/hooks/useAffiliateDashboard.js.map +1 -0
  57. package/dist/hooks/useFeature.d.ts +100 -0
  58. package/dist/hooks/useFeature.d.ts.map +1 -0
  59. package/dist/hooks/useFeature.js +325 -0
  60. package/dist/hooks/useFeature.js.map +1 -0
  61. package/dist/index.d.ts +19 -0
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +18 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/tailwind-preset.d.ts +17 -0
  66. package/dist/tailwind-preset.d.ts.map +1 -0
  67. package/dist/tailwind-preset.js +86 -0
  68. package/dist/tailwind-preset.js.map +1 -0
  69. package/package.json +37 -7
@@ -0,0 +1,336 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * FeatureForm — Config-driven create/edit form component
4
+ *
5
+ * Replaces ALL per-feature form implementations with a single generic component
6
+ * driven by FeatureConfig.formFields[].
7
+ *
8
+ * Field type → UI mapping:
9
+ * - text/email/password/url/phone → text input
10
+ * - number/currency/percentage → number input (with prefix/suffix)
11
+ * - textarea → textarea
12
+ * - select/combobox → select dropdown
13
+ * - multiselect → multi-checkbox dropdown
14
+ * - boolean/switch/checkbox → toggle / checkbox
15
+ * - date/datetime → date/datetime input
16
+ * - daterange → two date inputs
17
+ * - color → color input
18
+ * - file/image → file input
19
+ * - hidden → hidden input
20
+ * - richtext → textarea (upgrade to rich editor via customComponents)
21
+ * - custom → custom component from registry
22
+ *
23
+ * @module @tetra/ui
24
+ */
25
+ import { useMemo, useCallback, useState } from 'react';
26
+ // ─── DOM Helpers (no DOM lib in tsconfig) ───────────────────
27
+ function getInputValue(e) {
28
+ return e.target.value;
29
+ }
30
+ function getChecked(e) {
31
+ return e.target.checked;
32
+ }
33
+ function getFiles(e) {
34
+ const files = e.target.files;
35
+ return files ? Array.from(files) : [];
36
+ }
37
+ // ─── Conditional Visibility ─────────────────────────────────
38
+ function isFieldVisible(field, mode, formValues) {
39
+ if (field.showIn && field.showIn !== 'both' && field.showIn !== mode) {
40
+ return false;
41
+ }
42
+ if (field.showWhen) {
43
+ const depValue = formValues[field.showWhen.field];
44
+ const targetValue = field.showWhen.value;
45
+ const operator = field.showWhen.operator ?? 'equals';
46
+ switch (operator) {
47
+ case 'equals':
48
+ return depValue === targetValue;
49
+ case 'not-equals':
50
+ return depValue !== targetValue;
51
+ case 'exists':
52
+ return depValue !== undefined && depValue !== null && depValue !== '';
53
+ case 'in':
54
+ return Array.isArray(targetValue) && targetValue.includes(depValue);
55
+ default:
56
+ return true;
57
+ }
58
+ }
59
+ return true;
60
+ }
61
+ function groupFields(fields) {
62
+ const groups = [];
63
+ let currentGroup = null;
64
+ for (const field of fields) {
65
+ const groupName = field.group ?? null;
66
+ if (!currentGroup || currentGroup.name !== groupName) {
67
+ currentGroup = { name: groupName, fields: [] };
68
+ groups.push(currentGroup);
69
+ }
70
+ currentGroup.fields.push(field);
71
+ }
72
+ return groups;
73
+ }
74
+ function TextField({ field, value, onChange, error, disabled }) {
75
+ const inputType = field.type === 'phone' ? 'tel' : field.type === 'url' ? 'url' : field.type;
76
+ return (_jsx("input", { type: inputType, value: String(value ?? ''), onChange: (e) => onChange(getInputValue(e) || undefined), placeholder: field.placeholder, disabled: disabled || field.disabled, readOnly: field.readOnly, maxLength: field.maxLength, className: `h-9 w-full rounded-md border bg-background px-3 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'} ${field.readOnly ? 'bg-muted cursor-not-allowed' : ''}`, "aria-label": field.label, "aria-invalid": !!error, "aria-describedby": error ? `${field.name}-error` : field.description ? `${field.name}-desc` : undefined }));
77
+ }
78
+ function NumberField({ field, value, onChange, error, disabled }) {
79
+ const prefix = field.type === 'currency' ? (field.currency ?? 'EUR') === 'EUR' ? '\u20AC' : field.currency : undefined;
80
+ const suffix = field.type === 'percentage' ? '%' : undefined;
81
+ return (_jsxs("div", { className: "flex items-center gap-1.5", children: [prefix && _jsx("span", { className: "text-sm text-muted-foreground", children: prefix }), _jsx("input", { type: "number", value: value !== undefined && value !== null ? String(value) : '', onChange: (e) => {
82
+ const v = getInputValue(e);
83
+ onChange(v === '' ? undefined : Number(v));
84
+ }, placeholder: field.placeholder, disabled: disabled || field.disabled, readOnly: field.readOnly, min: field.min, max: field.max, step: field.step ?? (field.type === 'currency' || field.type === 'percentage' ? 0.01 : 1), className: `h-9 w-full rounded-md border bg-background px-3 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'}`, "aria-label": field.label, "aria-invalid": !!error }), suffix && _jsx("span", { className: "text-sm text-muted-foreground", children: suffix })] }));
85
+ }
86
+ function TextareaField({ field, value, onChange, error, disabled }) {
87
+ return (_jsx("textarea", { value: String(value ?? ''), onChange: (e) => onChange(getInputValue(e) || undefined), placeholder: field.placeholder, disabled: disabled || field.disabled, readOnly: field.readOnly, maxLength: field.maxLength, rows: field.rows ?? 4, className: `w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'} ${field.readOnly ? 'bg-muted cursor-not-allowed' : ''}`, "aria-label": field.label, "aria-invalid": !!error }));
88
+ }
89
+ function SelectField({ field, value, onChange, error, disabled }) {
90
+ const options = field.options ?? [];
91
+ return (_jsxs("select", { value: String(value ?? ''), onChange: (e) => {
92
+ const v = getInputValue(e);
93
+ onChange(v === '' ? undefined : v);
94
+ }, disabled: disabled || field.disabled, className: `h-9 w-full rounded-md border bg-background px-3 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'}`, "aria-label": field.label, "aria-invalid": !!error, children: [!field.required && (_jsx("option", { value: "", children: field.placeholder ?? 'Select...' })), options.map(opt => (_jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }));
95
+ }
96
+ function MultiSelectField({ field, value, onChange, error, disabled }) {
97
+ const [open, setOpen] = useState(false);
98
+ const selectedValues = Array.isArray(value) ? value : [];
99
+ const options = field.options ?? [];
100
+ const handleToggle = useCallback((optionValue) => {
101
+ const next = selectedValues.includes(optionValue)
102
+ ? selectedValues.filter(v => v !== optionValue)
103
+ : [...selectedValues, optionValue];
104
+ onChange(next.length > 0 ? next : undefined);
105
+ }, [selectedValues, onChange]);
106
+ const selectedLabel = selectedValues.length === 0
107
+ ? (field.placeholder ?? 'Select...')
108
+ : selectedValues.length === 1
109
+ ? options.find(o => o.value === selectedValues[0])?.label ?? selectedValues[0]
110
+ : `${selectedValues.length} selected`;
111
+ return (_jsxs("div", { className: "relative", children: [_jsxs("button", { type: "button", onClick: () => !disabled && !field.disabled && setOpen(!open), className: `flex h-9 w-full items-center justify-between rounded-md border bg-background px-3 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'} ${disabled || field.disabled ? 'opacity-50 cursor-not-allowed' : ''}`, "aria-expanded": open, "aria-label": field.label, "aria-invalid": !!error, disabled: disabled || field.disabled, children: [_jsx("span", { className: selectedValues.length === 0 ? 'text-muted-foreground' : '', children: selectedLabel }), _jsx("svg", { className: "h-4 w-4 opacity-50", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "m6 9 6 6 6-6" }) })] }), open && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40", onClick: () => setOpen(false) }), _jsxs("div", { className: "absolute top-full left-0 z-50 mt-1 w-full rounded-md border bg-popover shadow-md", children: [_jsx("div", { className: "max-h-60 overflow-y-auto p-1", children: options.map(opt => (_jsxs("label", { className: "flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent", children: [_jsx("input", { type: "checkbox", checked: selectedValues.includes(opt.value), onChange: () => handleToggle(opt.value), className: "h-4 w-4 rounded border-input" }), _jsx("span", { children: opt.label }), opt.description && (_jsx("span", { className: "text-xs text-muted-foreground", children: opt.description }))] }, opt.value))) }), selectedValues.length > 0 && (_jsx("div", { className: "border-t p-1", children: _jsx("button", { type: "button", onClick: () => { onChange(undefined); setOpen(false); }, className: "w-full rounded-sm px-2 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground", children: "Clear selection" }) }))] })] }))] }));
112
+ }
113
+ function BooleanField({ field, value, onChange, error, disabled }) {
114
+ const checked = value === true || value === 'true';
115
+ if (field.type === 'checkbox') {
116
+ return (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: checked, onChange: (e) => onChange(getChecked(e)), disabled: disabled || field.disabled, className: "h-4 w-4 rounded border-input", "aria-label": field.label, "aria-invalid": !!error }), _jsx("span", { className: "text-sm", children: field.label })] }));
117
+ }
118
+ return (_jsx("button", { type: "button", role: "switch", "aria-checked": checked, "aria-label": field.label, "aria-invalid": !!error, onClick: () => !(disabled || field.disabled) && onChange(!checked), disabled: disabled || field.disabled, className: `relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${checked ? 'bg-primary' : 'bg-input'} ${disabled || field.disabled ? 'opacity-50 cursor-not-allowed' : ''}`, children: _jsx("span", { className: `pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform ${checked ? 'translate-x-4' : 'translate-x-0'}` }) }));
119
+ }
120
+ function DateField({ field, value, onChange, error, disabled }) {
121
+ const inputType = field.type === 'datetime' ? 'datetime-local' : 'date';
122
+ return (_jsx("input", { type: inputType, value: String(value ?? ''), onChange: (e) => onChange(getInputValue(e) || undefined), disabled: disabled || field.disabled, className: `h-9 w-full rounded-md border bg-background px-3 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'}`, "aria-label": field.label, "aria-invalid": !!error }));
123
+ }
124
+ function DateRangeField({ field, value, onChange, error, disabled }) {
125
+ const parts = typeof value === 'string' ? value.split('|') : ['', ''];
126
+ const startDate = parts[0] || '';
127
+ const endDate = parts[1] || '';
128
+ const handleChange = useCallback((start, end) => {
129
+ if (!start && !end) {
130
+ onChange(undefined);
131
+ }
132
+ else {
133
+ onChange(`${start}|${end}`);
134
+ }
135
+ }, [onChange]);
136
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "date", value: startDate, onChange: (e) => handleChange(getInputValue(e), endDate), disabled: disabled || field.disabled, className: `h-9 rounded-md border bg-background px-3 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'}`, "aria-label": `${field.label} from` }), _jsx("span", { className: "text-muted-foreground text-sm", children: '\u2013' }), _jsx("input", { type: "date", value: endDate, onChange: (e) => handleChange(startDate, getInputValue(e)), disabled: disabled || field.disabled, className: `h-9 rounded-md border bg-background px-3 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${error ? 'border-destructive' : 'border-input'}`, "aria-label": `${field.label} to` })] }));
137
+ }
138
+ function ColorField({ field, value, onChange, error, disabled }) {
139
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "color", value: String(value ?? '#000000'), onChange: (e) => onChange(getInputValue(e)), disabled: disabled || field.disabled, className: `h-9 w-12 rounded-md border bg-background p-1 ${error ? 'border-destructive' : 'border-input'}`, "aria-label": field.label }), _jsx("input", { type: "text", value: String(value ?? ''), onChange: (e) => onChange(getInputValue(e) || undefined), placeholder: "#000000", disabled: disabled || field.disabled, className: `h-9 w-28 rounded-md border bg-background px-3 text-sm font-mono ${error ? 'border-destructive' : 'border-input'}`, "aria-label": `${field.label} hex value` })] }));
140
+ }
141
+ function FileField({ field, value, onChange, error, disabled }) {
142
+ return (_jsx("input", { type: "file", accept: field.accept ?? (field.type === 'image' ? 'image/*' : undefined), onChange: (e) => {
143
+ const files = getFiles(e);
144
+ onChange(files.length > 0 ? files[0] : undefined);
145
+ }, disabled: disabled || field.disabled, className: `h-9 w-full rounded-md border bg-background px-3 text-sm file:mr-4 file:border-0 file:bg-transparent file:text-sm file:font-medium ${error ? 'border-destructive' : 'border-input'}`, "aria-label": field.label, "aria-invalid": !!error }));
146
+ }
147
+ // ─── Field Router ───────────────────────────────────────────
148
+ function renderField(field, value, onChange, error, disabled, customComponents) {
149
+ if (field.customComponent && customComponents?.[field.customComponent]) {
150
+ return customComponents[field.customComponent]({ field, value, onChange, error, disabled });
151
+ }
152
+ const props = { field, value, onChange, error, disabled };
153
+ switch (field.type) {
154
+ case 'text':
155
+ case 'email':
156
+ case 'password':
157
+ case 'url':
158
+ case 'phone':
159
+ return _jsx(TextField, { ...props });
160
+ case 'number':
161
+ case 'currency':
162
+ case 'percentage':
163
+ return _jsx(NumberField, { ...props });
164
+ case 'textarea':
165
+ case 'richtext':
166
+ return _jsx(TextareaField, { ...props });
167
+ case 'select':
168
+ case 'combobox':
169
+ return _jsx(SelectField, { ...props });
170
+ case 'multiselect':
171
+ return _jsx(MultiSelectField, { ...props });
172
+ case 'boolean':
173
+ case 'switch':
174
+ case 'checkbox':
175
+ return _jsx(BooleanField, { ...props });
176
+ case 'date':
177
+ case 'datetime':
178
+ return _jsx(DateField, { ...props });
179
+ case 'daterange':
180
+ return _jsx(DateRangeField, { ...props });
181
+ case 'color':
182
+ return _jsx(ColorField, { ...props });
183
+ case 'file':
184
+ case 'image':
185
+ return _jsx(FileField, { ...props });
186
+ case 'hidden':
187
+ return null;
188
+ case 'custom':
189
+ if (field.customComponent && customComponents?.[field.customComponent]) {
190
+ return customComponents[field.customComponent]({ field, value, onChange, error, disabled });
191
+ }
192
+ return _jsx(TextField, { ...props });
193
+ default:
194
+ return _jsx(TextField, { ...props });
195
+ }
196
+ }
197
+ // ─── Validation ─────────────────────────────────────────────
198
+ function validateWithSchema(data, schema) {
199
+ if (!schema)
200
+ return {};
201
+ const result = schema.safeParse(data);
202
+ if (result.success)
203
+ return {};
204
+ const errors = {};
205
+ if (result.error?.issues) {
206
+ for (const issue of result.error.issues) {
207
+ const path = issue.path.join('.');
208
+ if (path && !errors[path]) {
209
+ errors[path] = issue.message;
210
+ }
211
+ }
212
+ }
213
+ return errors;
214
+ }
215
+ function validateRequired(data, fields, mode, formValues) {
216
+ const errors = {};
217
+ for (const field of fields) {
218
+ if (!field.required)
219
+ continue;
220
+ if (!isFieldVisible(field, mode, formValues))
221
+ continue;
222
+ const value = data[field.name];
223
+ if (value === undefined || value === null || value === '') {
224
+ errors[field.name] = `${field.label} is required`;
225
+ }
226
+ if (Array.isArray(value) && value.length === 0) {
227
+ errors[field.name] = `${field.label} is required`;
228
+ }
229
+ }
230
+ return errors;
231
+ }
232
+ // ─── Main Component ─────────────────────────────────────────
233
+ /**
234
+ * FeatureForm — Config-driven create/edit form
235
+ *
236
+ * @example
237
+ * ```tsx
238
+ * import { ordersConfig } from '@/config/features/orders.config';
239
+ * import { FeatureForm } from '@soulbatical/tetra-ui';
240
+ *
241
+ * function CreateOrderDialog() {
242
+ * return (
243
+ * <FeatureForm
244
+ * config={ordersConfig}
245
+ * mode="create"
246
+ * onSubmit={async (data) => {
247
+ * await createOrder(data);
248
+ * }}
249
+ * onCancel={() => setOpen(false)}
250
+ * />
251
+ * );
252
+ * }
253
+ * ```
254
+ */
255
+ export function FeatureForm({ config, mode, defaultValues, onSubmit, onCancel, errors: externalErrors, schema, customComponents, submitLabel, cancelLabel = 'Cancel', showCancel, submitting = false, className, disabled: formDisabled = false, layout, }) {
256
+ const initialValues = useMemo(() => {
257
+ const values = {};
258
+ const defaults = (defaultValues ?? {});
259
+ for (const field of config.formFields || []) {
260
+ if (field.name in defaults) {
261
+ values[field.name] = defaults[field.name];
262
+ }
263
+ else if (field.defaultValue !== undefined) {
264
+ values[field.name] = field.defaultValue;
265
+ }
266
+ else {
267
+ values[field.name] = undefined;
268
+ }
269
+ }
270
+ return values;
271
+ }, [config.formFields, defaultValues]);
272
+ const [formValues, setFormValues] = useState(initialValues);
273
+ const [validationErrors, setValidationErrors] = useState({});
274
+ const allErrors = useMemo(() => ({
275
+ ...validationErrors,
276
+ ...externalErrors,
277
+ }), [validationErrors, externalErrors]);
278
+ const visibleFields = useMemo(() => {
279
+ const fields = (config.formFields || [])
280
+ .filter(f => f.type !== 'hidden')
281
+ .filter(f => isFieldVisible(f, mode, formValues))
282
+ .sort((a, b) => (a.order ?? 999) - (b.order ?? 999));
283
+ return fields;
284
+ }, [config.formFields, mode, formValues]);
285
+ const hiddenFields = useMemo(() => {
286
+ return (config.formFields || []).filter(f => f.type === 'hidden');
287
+ }, [config.formFields]);
288
+ const fieldGroups = useMemo(() => groupFields(visibleFields), [visibleFields]);
289
+ const useGrid = layout === 'grid' || (layout !== 'single' && visibleFields.some(f => f.width === 'half'));
290
+ const handleFieldChange = useCallback((name, value) => {
291
+ setFormValues(prev => ({ ...prev, [name]: value }));
292
+ if (validationErrors[name]) {
293
+ setValidationErrors(prev => {
294
+ const next = { ...prev };
295
+ delete next[name];
296
+ return next;
297
+ });
298
+ }
299
+ }, [validationErrors]);
300
+ const handleSubmit = useCallback((e) => {
301
+ e.preventDefault();
302
+ const data = { ...formValues };
303
+ for (const field of hiddenFields) {
304
+ const defaults = (defaultValues ?? {});
305
+ if (field.name in defaults) {
306
+ data[field.name] = defaults[field.name];
307
+ }
308
+ else if (field.defaultValue !== undefined) {
309
+ data[field.name] = field.defaultValue;
310
+ }
311
+ }
312
+ const schemaErrors = validateWithSchema(data, schema);
313
+ if (Object.keys(schemaErrors).length > 0) {
314
+ setValidationErrors(schemaErrors);
315
+ return;
316
+ }
317
+ const requiredErrors = validateRequired(data, config.formFields || [], mode, formValues);
318
+ if (Object.keys(requiredErrors).length > 0) {
319
+ setValidationErrors(requiredErrors);
320
+ return;
321
+ }
322
+ setValidationErrors({});
323
+ onSubmit(data);
324
+ }, [formValues, hiddenFields, defaultValues, schema, config.formFields, mode, onSubmit]);
325
+ const defaultSubmitLabel = mode === 'create' ? 'Create' : 'Save';
326
+ const resolvedSubmitLabel = submitLabel ?? defaultSubmitLabel;
327
+ const resolvedShowCancel = showCancel ?? !!onCancel;
328
+ const isDisabled = formDisabled || submitting;
329
+ return (_jsxs("form", { onSubmit: handleSubmit, className: `space-y-6 ${className ?? ''}`, noValidate: true, children: [fieldGroups.map((group, groupIdx) => (_jsxs("fieldset", { className: "space-y-4", children: [group.name && (_jsx("legend", { className: "text-sm font-semibold text-foreground border-b pb-2 mb-2 w-full", children: group.name })), _jsx("div", { className: useGrid ? 'grid grid-cols-2 gap-4' : 'space-y-4', children: group.fields.map(field => {
330
+ const error = allErrors[field.name];
331
+ const fieldWidth = field.width ?? 'full';
332
+ const isBooleanType = field.type === 'boolean' || field.type === 'switch' || field.type === 'checkbox';
333
+ return (_jsxs("div", { className: useGrid && fieldWidth === 'full' ? 'col-span-2' : '', children: [!isBooleanType && (_jsxs("label", { className: "block text-sm font-medium text-foreground mb-1.5", htmlFor: field.name, children: [field.label, field.required && (_jsx("span", { className: "text-destructive ml-0.5", children: "*" }))] })), renderField(field, formValues[field.name], (value) => handleFieldChange(field.name, value), error, isDisabled, customComponents), (field.type === 'boolean' || field.type === 'switch') && (_jsxs("label", { className: "block text-sm font-medium text-foreground mt-1.5", children: [field.label, field.required && (_jsx("span", { className: "text-destructive ml-0.5", children: "*" }))] })), field.description && (_jsx("p", { id: `${field.name}-desc`, className: "text-xs text-muted-foreground mt-1", children: field.description })), error && (_jsx("p", { id: `${field.name}-error`, className: "text-xs text-destructive mt-1", role: "alert", children: error }))] }, field.name));
334
+ }) })] }, group.name ?? groupIdx))), _jsxs("div", { className: "flex items-center justify-end gap-3 pt-4 border-t", children: [resolvedShowCancel && onCancel && (_jsx("button", { type: "button", onClick: onCancel, disabled: submitting, className: "inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 text-sm font-medium hover:bg-accent hover:text-accent-foreground disabled:opacity-50", children: cancelLabel })), _jsxs("button", { type: "submit", disabled: isDisabled, className: "inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 disabled:opacity-50 disabled:pointer-events-none", children: [submitting && (_jsxs("svg", { className: "mr-2 h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] })), resolvedSubmitLabel] })] })] }));
335
+ }
336
+ //# sourceMappingURL=FeatureForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureForm.js","sourceRoot":"","sources":["../../src/components/FeatureForm.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * FeatureTable — Config-driven data table component
3
+ *
4
+ * Replaces ALL per-feature table implementations with a single generic component
5
+ * driven by FeatureConfig.columns[].
6
+ *
7
+ * Before (100+ lines boilerplate PER feature):
8
+ * <DataTable columns={orderColumns} data={orders} ... />
9
+ *
10
+ * After (ZERO boilerplate):
11
+ * <FeatureTable config={ordersConfig} feature={feature} />
12
+ *
13
+ * Features:
14
+ * - Auto-generates columns from config.columns[]
15
+ * - Sorting (server-side via useFeature)
16
+ * - Pagination (server-side via useFeature)
17
+ * - Row selection (optional)
18
+ * - Slot pattern for custom cell renderers
19
+ * - Responsive column visibility
20
+ * - Empty state
21
+ * - Loading skeleton
22
+ *
23
+ * @module @tetra/ui
24
+ */
25
+ import React from 'react';
26
+ import { type RowSelectionState } from '@tanstack/react-table';
27
+ import type { FeatureConfig } from '@soulbatical/tetra-core';
28
+ import type { UseFeatureResult } from '../hooks/useFeature.js';
29
+ /** Registry of custom cell renderers */
30
+ export type CellRendererMap = Record<string, (value: unknown, row: Record<string, unknown>) => React.ReactNode>;
31
+ export interface FeatureTableProps<TItem = Record<string, unknown>> {
32
+ /** Feature configuration with columns[] */
33
+ config: FeatureConfig<TItem>;
34
+ /** Result from useFeature() hook */
35
+ feature: UseFeatureResult<TItem>;
36
+ /** Enable row selection (default: false) */
37
+ selectable?: boolean;
38
+ /** Controlled row selection state */
39
+ rowSelection?: RowSelectionState;
40
+ /** Row selection change handler */
41
+ onRowSelectionChange?: (selection: RowSelectionState) => void;
42
+ /** Row click handler */
43
+ onRowClick?: (row: TItem) => void;
44
+ /** Custom cell renderers (keyed by cellRenderer name from ColumnConfig) */
45
+ cellRenderers?: CellRendererMap;
46
+ /** Override column visibility (keyed by accessor) */
47
+ columnVisibility?: Record<string, boolean>;
48
+ /** Custom empty state message */
49
+ emptyMessage?: string;
50
+ /** Custom empty state component */
51
+ emptyState?: React.ReactNode;
52
+ /** CSS class for the table wrapper */
53
+ className?: string;
54
+ /** Show loading skeleton (overrides feature.loading) */
55
+ loading?: boolean;
56
+ /** Number of skeleton rows to show (default: 5) */
57
+ skeletonRows?: number;
58
+ /** Row key accessor (default: 'id') */
59
+ getRowId?: (row: TItem) => string;
60
+ /** Pagination labels */
61
+ paginationLabels?: {
62
+ previous?: string;
63
+ next?: string;
64
+ showing?: string;
65
+ of?: string;
66
+ results?: string;
67
+ page?: string;
68
+ };
69
+ }
70
+ /**
71
+ * FeatureTable — Config-driven data table
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * import { ordersConfig } from '@/config/features/orders.config';
76
+ * import { useFeature, FeatureTable } from '@soulbatical/tetra-ui';
77
+ *
78
+ * function OrdersPage() {
79
+ * const feature = useFeature(ordersConfig, supabase, { organizationId });
80
+ *
81
+ * return (
82
+ * <FeatureTable
83
+ * config={ordersConfig}
84
+ * feature={feature}
85
+ * onRowClick={(order) => router.push(`/orders/${order.id}`)}
86
+ * cellRenderers={{
87
+ * orderStatus: (value) => <CustomStatusBadge status={value} />,
88
+ * }}
89
+ * />
90
+ * );
91
+ * }
92
+ * ```
93
+ */
94
+ export declare function FeatureTable<TItem = Record<string, unknown>>({ config, feature, selectable, rowSelection: controlledRowSelection, onRowSelectionChange, onRowClick, cellRenderers, columnVisibility: controlledColumnVisibility, emptyMessage, emptyState, className, loading: loadingOverride, skeletonRows, getRowId, paginationLabels, }: FeatureTableProps<TItem>): import("react/jsx-runtime").JSX.Element;
95
+ //# sourceMappingURL=FeatureTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureTable.d.ts","sourceRoot":"","sources":["../../src/components/FeatureTable.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI/D,wCAAwC;AACxC,MAAM,MAAM,eAAe,GAAG,MAAM,CAClC,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,KAAK,CAAC,SAAS,CAClE,CAAC;AAEF,MAAM,WAAW,iBAAiB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,2CAA2C;IAC3C,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAE7B,oCAAoC;IACpC,OAAO,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAEjC,4CAA4C;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,qCAAqC;IACrC,YAAY,CAAC,EAAE,iBAAiB,CAAC;IAEjC,mCAAmC;IACnC,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAE9D,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAElC,2EAA2E;IAC3E,aAAa,CAAC,EAAE,eAAe,CAAC;IAEhC,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3C,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mCAAmC;IACnC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE7B,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAC;IAElC,wBAAwB;IACxB,gBAAgB,CAAC,EAAE;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAiRD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC5D,MAAM,EACN,OAAO,EACP,UAAkB,EAClB,YAAY,EAAE,sBAAsB,EACpC,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,gBAAgB,EAAE,0BAA0B,EAC5C,YAAY,EACZ,UAAU,EACV,SAAS,EACT,OAAO,EAAE,eAAe,EACxB,YAAgB,EAChB,QAAQ,EACR,gBAAgB,GACjB,EAAE,iBAAiB,CAAC,KAAK,CAAC,2CA2K1B"}