@modern-admin/ui 0.1.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/dist/components/accordion.d.ts +7 -0
- package/dist/components/accordion.d.ts.map +1 -0
- package/dist/components/accordion.jsx +19 -0
- package/dist/components/accordion.jsx.map +1 -0
- package/dist/components/alert-dialog.d.ts +22 -0
- package/dist/components/alert-dialog.d.ts.map +1 -0
- package/dist/components/alert-dialog.jsx +27 -0
- package/dist/components/alert-dialog.jsx.map +1 -0
- package/dist/components/audit-timeline.d.ts +24 -0
- package/dist/components/audit-timeline.d.ts.map +1 -0
- package/dist/components/audit-timeline.jsx +60 -0
- package/dist/components/audit-timeline.jsx.map +1 -0
- package/dist/components/avatar.d.ts +6 -0
- package/dist/components/avatar.d.ts.map +1 -0
- package/dist/components/avatar.jsx +10 -0
- package/dist/components/avatar.jsx.map +1 -0
- package/dist/components/badge.d.ts +10 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.jsx +19 -0
- package/dist/components/badge.jsx.map +1 -0
- package/dist/components/breadcrumb.d.ts +17 -0
- package/dist/components/breadcrumb.d.ts.map +1 -0
- package/dist/components/breadcrumb.jsx +27 -0
- package/dist/components/breadcrumb.jsx.map +1 -0
- package/dist/components/button.d.ts +12 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.jsx +37 -0
- package/dist/components/button.jsx.map +1 -0
- package/dist/components/calendar.d.ts +9 -0
- package/dist/components/calendar.d.ts.map +1 -0
- package/dist/components/calendar.jsx +102 -0
- package/dist/components/calendar.jsx.map +1 -0
- package/dist/components/card.d.ts +8 -0
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.jsx +18 -0
- package/dist/components/card.jsx.map +1 -0
- package/dist/components/chart.d.ts +97 -0
- package/dist/components/chart.d.ts.map +1 -0
- package/dist/components/chart.jsx +233 -0
- package/dist/components/chart.jsx.map +1 -0
- package/dist/components/checkbox.d.ts +4 -0
- package/dist/components/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox.jsx +11 -0
- package/dist/components/checkbox.jsx.map +1 -0
- package/dist/components/combobox.d.ts +46 -0
- package/dist/components/combobox.d.ts.map +1 -0
- package/dist/components/combobox.jsx +145 -0
- package/dist/components/combobox.jsx.map +1 -0
- package/dist/components/command.d.ts +80 -0
- package/dist/components/command.d.ts.map +1 -0
- package/dist/components/command.jsx +32 -0
- package/dist/components/command.jsx.map +1 -0
- package/dist/components/date-picker.d.ts +24 -0
- package/dist/components/date-picker.d.ts.map +1 -0
- package/dist/components/date-picker.jsx +149 -0
- package/dist/components/date-picker.jsx.map +1 -0
- package/dist/components/date-range-input.d.ts +22 -0
- package/dist/components/date-range-input.d.ts.map +1 -0
- package/dist/components/date-range-input.jsx +202 -0
- package/dist/components/date-range-input.jsx.map +1 -0
- package/dist/components/dialog.d.ts +19 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.jsx +30 -0
- package/dist/components/dialog.jsx.map +1 -0
- package/dist/components/diff-view.d.ts +24 -0
- package/dist/components/diff-view.d.ts.map +1 -0
- package/dist/components/diff-view.jsx +69 -0
- package/dist/components/diff-view.jsx.map +1 -0
- package/dist/components/dropdown-menu.d.ts +27 -0
- package/dist/components/dropdown-menu.d.ts.map +1 -0
- package/dist/components/dropdown-menu.jsx +48 -0
- package/dist/components/dropdown-menu.jsx.map +1 -0
- package/dist/components/empty.d.ts +15 -0
- package/dist/components/empty.d.ts.map +1 -0
- package/dist/components/empty.jsx +27 -0
- package/dist/components/empty.jsx.map +1 -0
- package/dist/components/field.d.ts +23 -0
- package/dist/components/field.d.ts.map +1 -0
- package/dist/components/field.jsx +60 -0
- package/dist/components/field.jsx.map +1 -0
- package/dist/components/file-input.d.ts +50 -0
- package/dist/components/file-input.d.ts.map +1 -0
- package/dist/components/file-input.jsx +104 -0
- package/dist/components/file-input.jsx.map +1 -0
- package/dist/components/form.d.ts +20 -0
- package/dist/components/form.d.ts.map +1 -0
- package/dist/components/form.jsx +66 -0
- package/dist/components/form.jsx.map +1 -0
- package/dist/components/info-tooltip.d.ts +11 -0
- package/dist/components/info-tooltip.d.ts.map +1 -0
- package/dist/components/info-tooltip.jsx +17 -0
- package/dist/components/info-tooltip.jsx.map +1 -0
- package/dist/components/input.d.ts +13 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.jsx +19 -0
- package/dist/components/input.jsx.map +1 -0
- package/dist/components/json-editor.d.ts +23 -0
- package/dist/components/json-editor.d.ts.map +1 -0
- package/dist/components/json-editor.jsx +143 -0
- package/dist/components/json-editor.jsx.map +1 -0
- package/dist/components/kbd.d.ts +15 -0
- package/dist/components/kbd.d.ts.map +1 -0
- package/dist/components/kbd.jsx +23 -0
- package/dist/components/kbd.jsx.map +1 -0
- package/dist/components/key-value-editor.d.ts +92 -0
- package/dist/components/key-value-editor.d.ts.map +1 -0
- package/dist/components/key-value-editor.jsx +187 -0
- package/dist/components/key-value-editor.jsx.map +1 -0
- package/dist/components/keyboard-shortcuts-help.d.ts +17 -0
- package/dist/components/keyboard-shortcuts-help.d.ts.map +1 -0
- package/dist/components/keyboard-shortcuts-help.jsx +97 -0
- package/dist/components/keyboard-shortcuts-help.jsx.map +1 -0
- package/dist/components/label.d.ts +5 -0
- package/dist/components/label.d.ts.map +1 -0
- package/dist/components/label.jsx +8 -0
- package/dist/components/label.jsx.map +1 -0
- package/dist/components/media-preview.d.ts +30 -0
- package/dist/components/media-preview.d.ts.map +1 -0
- package/dist/components/media-preview.jsx +189 -0
- package/dist/components/media-preview.jsx.map +1 -0
- package/dist/components/multi-file-input.d.ts +76 -0
- package/dist/components/multi-file-input.d.ts.map +1 -0
- package/dist/components/multi-file-input.jsx +131 -0
- package/dist/components/multi-file-input.jsx.map +1 -0
- package/dist/components/password-input.d.ts +10 -0
- package/dist/components/password-input.d.ts.map +1 -0
- package/dist/components/password-input.jsx +18 -0
- package/dist/components/password-input.jsx.map +1 -0
- package/dist/components/popover.d.ts +7 -0
- package/dist/components/popover.d.ts.map +1 -0
- package/dist/components/popover.jsx +11 -0
- package/dist/components/popover.jsx.map +1 -0
- package/dist/components/revision-timeline.d.ts +30 -0
- package/dist/components/revision-timeline.d.ts.map +1 -0
- package/dist/components/revision-timeline.jsx +42 -0
- package/dist/components/revision-timeline.jsx.map +1 -0
- package/dist/components/richtext-editor.d.ts +43 -0
- package/dist/components/richtext-editor.d.ts.map +1 -0
- package/dist/components/richtext-editor.jsx +319 -0
- package/dist/components/richtext-editor.jsx.map +1 -0
- package/dist/components/richtext-mode.d.ts +23 -0
- package/dist/components/richtext-mode.d.ts.map +1 -0
- package/dist/components/richtext-mode.js +36 -0
- package/dist/components/richtext-mode.js.map +1 -0
- package/dist/components/richtext-render.d.ts +8 -0
- package/dist/components/richtext-render.d.ts.map +1 -0
- package/dist/components/richtext-render.jsx +33 -0
- package/dist/components/richtext-render.jsx.map +1 -0
- package/dist/components/richtext-sync.d.ts +37 -0
- package/dist/components/richtext-sync.d.ts.map +1 -0
- package/dist/components/richtext-sync.js +46 -0
- package/dist/components/richtext-sync.js.map +1 -0
- package/dist/components/scroll-area.d.ts +5 -0
- package/dist/components/scroll-area.d.ts.map +1 -0
- package/dist/components/scroll-area.jsx +16 -0
- package/dist/components/scroll-area.jsx.map +1 -0
- package/dist/components/select.d.ts +36 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.jsx +87 -0
- package/dist/components/select.jsx.map +1 -0
- package/dist/components/separator.d.ts +4 -0
- package/dist/components/separator.d.ts.map +1 -0
- package/dist/components/separator.jsx +6 -0
- package/dist/components/separator.jsx.map +1 -0
- package/dist/components/sheet.d.ts +29 -0
- package/dist/components/sheet.d.ts.map +1 -0
- package/dist/components/sheet.jsx +44 -0
- package/dist/components/sheet.jsx.map +1 -0
- package/dist/components/sidebar.d.ts +70 -0
- package/dist/components/sidebar.d.ts.map +1 -0
- package/dist/components/sidebar.jsx +245 -0
- package/dist/components/sidebar.jsx.map +1 -0
- package/dist/components/skeleton.d.ts +3 -0
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton.jsx +6 -0
- package/dist/components/skeleton.jsx.map +1 -0
- package/dist/components/sonner.d.ts +6 -0
- package/dist/components/sonner.d.ts.map +1 -0
- package/dist/components/sonner.jsx +29 -0
- package/dist/components/sonner.jsx.map +1 -0
- package/dist/components/switch.d.ts +4 -0
- package/dist/components/switch.d.ts.map +1 -0
- package/dist/components/switch.jsx +8 -0
- package/dist/components/switch.jsx.map +1 -0
- package/dist/components/table.d.ts +10 -0
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.jsx +21 -0
- package/dist/components/table.jsx.map +1 -0
- package/dist/components/tabs.d.ts +7 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.jsx +14 -0
- package/dist/components/tabs.jsx.map +1 -0
- package/dist/components/textarea.d.ts +4 -0
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/textarea.jsx +5 -0
- package/dist/components/textarea.jsx.map +1 -0
- package/dist/components/tooltip.d.ts +7 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.jsx +11 -0
- package/dist/components/tooltip.jsx.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/theme.d.ts +11 -0
- package/dist/lib/theme.d.ts.map +1 -0
- package/dist/lib/theme.js +44 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles.css +242 -0
- package/package.json +85 -0
- package/src/components/accordion.tsx +48 -0
- package/src/components/alert-dialog.tsx +113 -0
- package/src/components/audit-timeline.tsx +102 -0
- package/src/components/avatar.tsx +42 -0
- package/src/components/badge.tsx +34 -0
- package/src/components/breadcrumb.tsx +99 -0
- package/src/components/button.tsx +58 -0
- package/src/components/calendar.tsx +176 -0
- package/src/components/card.tsx +60 -0
- package/src/components/chart.tsx +558 -0
- package/src/components/checkbox.tsx +23 -0
- package/src/components/combobox.tsx +264 -0
- package/src/components/command.tsx +120 -0
- package/src/components/date-picker.tsx +221 -0
- package/src/components/date-range-input.tsx +295 -0
- package/src/components/dialog.tsx +94 -0
- package/src/components/diff-view.tsx +182 -0
- package/src/components/dropdown-menu.tsx +165 -0
- package/src/components/empty.tsx +100 -0
- package/src/components/field.tsx +168 -0
- package/src/components/file-input.tsx +233 -0
- package/src/components/form.tsx +152 -0
- package/src/components/info-tooltip.tsx +40 -0
- package/src/components/input.tsx +55 -0
- package/src/components/json-editor.tsx +210 -0
- package/src/components/kbd.tsx +35 -0
- package/src/components/key-value-editor.tsx +423 -0
- package/src/components/keyboard-shortcuts-help.tsx +136 -0
- package/src/components/label.tsx +16 -0
- package/src/components/media-preview.tsx +278 -0
- package/src/components/multi-file-input.tsx +315 -0
- package/src/components/password-input.tsx +50 -0
- package/src/components/popover.tsx +26 -0
- package/src/components/revision-timeline.tsx +93 -0
- package/src/components/richtext-editor.tsx +624 -0
- package/src/components/richtext-mode.ts +39 -0
- package/src/components/richtext-render.tsx +51 -0
- package/src/components/richtext-sync.ts +57 -0
- package/src/components/scroll-area.tsx +41 -0
- package/src/components/select.tsx +200 -0
- package/src/components/separator.tsx +21 -0
- package/src/components/sheet.tsx +109 -0
- package/src/components/sidebar.tsx +660 -0
- package/src/components/skeleton.tsx +9 -0
- package/src/components/sonner.tsx +45 -0
- package/src/components/switch.tsx +24 -0
- package/src/components/table.tsx +93 -0
- package/src/components/tabs.tsx +57 -0
- package/src/components/textarea.tsx +18 -0
- package/src/components/tooltip.tsx +25 -0
- package/src/index.ts +342 -0
- package/src/lib/theme.ts +45 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles.css +242 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MultiFileInput — drag-and-drop file picker that accepts multiple files at
|
|
3
|
+
* once and renders a list of currently-attached files with per-file remove
|
|
4
|
+
* controls. Mirrors `FileInput` but works on an array of values.
|
|
5
|
+
*
|
|
6
|
+
* Purely presentational — upload + cancel logic lives in the
|
|
7
|
+
* `packages/react` property renderer.
|
|
8
|
+
*/
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
export interface MultiFileInputItem {
|
|
11
|
+
/** Storage key (or URL). */
|
|
12
|
+
value: string;
|
|
13
|
+
/** Optional public URL used for image thumbnails. */
|
|
14
|
+
previewUrl?: string | null;
|
|
15
|
+
/** Optional display name. Falls back to the last path segment of `value`. */
|
|
16
|
+
displayName?: string | null;
|
|
17
|
+
}
|
|
18
|
+
/** In-progress upload — rendered as a separate row with progress / error. */
|
|
19
|
+
export interface MultiFileInputPendingItem {
|
|
20
|
+
/** Stable identifier for the pending row (e.g. `crypto.randomUUID()`). */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Display name (typically the local file name). */
|
|
23
|
+
name: string;
|
|
24
|
+
/** 0–100. `undefined` while the request is queued or finished. */
|
|
25
|
+
progress?: number;
|
|
26
|
+
/** Status text — when present, replaces the progress bar. */
|
|
27
|
+
status?: 'queued' | 'uploading' | 'error';
|
|
28
|
+
/** Error message to render when `status === 'error'`. */
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface MultiFileInputLabels {
|
|
32
|
+
/** Dropzone aria-label. Default: "Choose files". */
|
|
33
|
+
chooseFiles?: string;
|
|
34
|
+
/** Drop zone hint before the link. Default: "Drag and drop or". */
|
|
35
|
+
dragAndDrop?: string;
|
|
36
|
+
/** Link text when no files selected. Default: "choose files". */
|
|
37
|
+
chooseLink?: string;
|
|
38
|
+
/** Link text when files already exist. Default: "add more files". */
|
|
39
|
+
addMoreLink?: string;
|
|
40
|
+
/** Upload spinner text. Default: "Uploading…". */
|
|
41
|
+
uploading?: string;
|
|
42
|
+
/** Remove button aria-label. Default: "Remove file". */
|
|
43
|
+
removeFile?: string;
|
|
44
|
+
/** Fallback error when pending item has no message. Default: "Upload failed". */
|
|
45
|
+
uploadFailed?: string;
|
|
46
|
+
/** Dismiss error button aria-label. Default: "Dismiss". */
|
|
47
|
+
dismiss?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface MultiFileInputProps {
|
|
50
|
+
/** Currently attached files. */
|
|
51
|
+
items: ReadonlyArray<MultiFileInputItem>;
|
|
52
|
+
/** Files currently being uploaded — rendered below the persisted list. */
|
|
53
|
+
pendingItems?: ReadonlyArray<MultiFileInputPendingItem>;
|
|
54
|
+
/** HTML `accept` attribute (e.g. `'image/*'` or `'.pdf,.docx'`). */
|
|
55
|
+
accept?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Whether files are currently being uploaded. Shows a spinner in the
|
|
58
|
+
* dropzone. Ignored when `pendingItems` is non-empty (the per-item
|
|
59
|
+
* progress rows take over the role of the dropzone spinner).
|
|
60
|
+
*/
|
|
61
|
+
uploading?: boolean;
|
|
62
|
+
/** Upload error message. */
|
|
63
|
+
error?: string;
|
|
64
|
+
disabled?: boolean;
|
|
65
|
+
className?: string;
|
|
66
|
+
/** Translated UI labels. All optional — English strings are the defaults. */
|
|
67
|
+
labels?: MultiFileInputLabels;
|
|
68
|
+
/** Called when the user picks one or more new files. */
|
|
69
|
+
onFilesSelect: (files: File[]) => void;
|
|
70
|
+
/** Called when the user removes the file at the given index. */
|
|
71
|
+
onRemove: (index: number) => void;
|
|
72
|
+
/** Called when the user dismisses an errored pending item. */
|
|
73
|
+
onPendingDismiss?: (id: string) => void;
|
|
74
|
+
}
|
|
75
|
+
export declare function MultiFileInput({ items, pendingItems, accept, uploading, error, disabled, className, labels, onFilesSelect, onRemove, onPendingDismiss, }: MultiFileInputProps): React.ReactElement;
|
|
76
|
+
//# sourceMappingURL=multi-file-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-file-input.d.ts","sourceRoot":"","sources":["../../src/components/multi-file-input.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,6EAA6E;AAC7E,MAAM,WAAW,yBAAyB;IACxC,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAA;IACV,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAA;IACzC,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,KAAK,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAA;IACxC,0EAA0E;IAC1E,YAAY,CAAC,EAAE,aAAa,CAAC,yBAAyB,CAAC,CAAA;IACvD,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,wDAAwD;IACxD,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IACtC,gEAAgE;IAChE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC;AAKD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,YAAY,EACZ,MAAM,EACN,SAAiB,EACjB,KAAK,EACL,QAAgB,EAChB,SAAS,EACT,MAAM,EACN,aAAa,EACb,QAAQ,EACR,gBAAgB,GACjB,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAwN1C"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MultiFileInput — drag-and-drop file picker that accepts multiple files at
|
|
3
|
+
* once and renders a list of currently-attached files with per-file remove
|
|
4
|
+
* controls. Mirrors `FileInput` but works on an array of values.
|
|
5
|
+
*
|
|
6
|
+
* Purely presentational — upload + cancel logic lives in the
|
|
7
|
+
* `packages/react` property renderer.
|
|
8
|
+
*/
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
import { Upload, X, FileText, Loader2 } from 'lucide-react';
|
|
11
|
+
import { cn } from '../lib/utils.js';
|
|
12
|
+
import { Button } from './button.js';
|
|
13
|
+
const isImageUrl = (url) => !!url && /\.(jpe?g|png|gif|webp|avif|svg|bmp)(\?|$)/i.test(url);
|
|
14
|
+
export function MultiFileInput({ items, pendingItems, accept, uploading = false, error, disabled = false, className, labels, onFilesSelect, onRemove, onPendingDismiss, }) {
|
|
15
|
+
const l = {
|
|
16
|
+
chooseFiles: labels?.chooseFiles ?? 'Choose files',
|
|
17
|
+
dragAndDrop: labels?.dragAndDrop ?? 'Drag and drop or',
|
|
18
|
+
chooseLink: labels?.chooseLink ?? 'choose files',
|
|
19
|
+
addMoreLink: labels?.addMoreLink ?? 'add more files',
|
|
20
|
+
uploading: labels?.uploading ?? 'Uploading…',
|
|
21
|
+
removeFile: labels?.removeFile ?? 'Remove file',
|
|
22
|
+
uploadFailed: labels?.uploadFailed ?? 'Upload failed',
|
|
23
|
+
dismiss: labels?.dismiss ?? 'Dismiss',
|
|
24
|
+
};
|
|
25
|
+
const inputRef = React.useRef(null);
|
|
26
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
27
|
+
const hasPending = (pendingItems?.length ?? 0) > 0;
|
|
28
|
+
// The dropzone spinner is redundant when individual progress rows are
|
|
29
|
+
// already on screen — only show it for batch uploads that don't supply
|
|
30
|
+
// per-item progress.
|
|
31
|
+
const showSpinner = uploading && !hasPending;
|
|
32
|
+
const handleFiles = (files) => {
|
|
33
|
+
if (!files || files.length === 0 || disabled)
|
|
34
|
+
return;
|
|
35
|
+
onFilesSelect(Array.from(files));
|
|
36
|
+
};
|
|
37
|
+
const handleInputChange = (e) => {
|
|
38
|
+
handleFiles(e.target.files);
|
|
39
|
+
// Allow re-selecting the same file again immediately after removing it.
|
|
40
|
+
e.target.value = '';
|
|
41
|
+
};
|
|
42
|
+
const handleDrop = (e) => {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
setIsDragging(false);
|
|
45
|
+
handleFiles(e.dataTransfer.files);
|
|
46
|
+
};
|
|
47
|
+
const handleDragOver = (e) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
if (!disabled)
|
|
50
|
+
setIsDragging(true);
|
|
51
|
+
};
|
|
52
|
+
const handleDragLeave = () => setIsDragging(false);
|
|
53
|
+
return (<div className={cn('w-full space-y-2', className)}>
|
|
54
|
+
{/* Drop zone / trigger */}
|
|
55
|
+
<div role="button" tabIndex={disabled ? -1 : 0} aria-label={l.chooseFiles} onClick={() => !disabled && inputRef.current?.click()} onKeyDown={(e) => {
|
|
56
|
+
if ((e.key === 'Enter' || e.key === ' ') && !disabled) {
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
inputRef.current?.click();
|
|
59
|
+
}
|
|
60
|
+
}} onDrop={handleDrop} onDragOver={handleDragOver} onDragLeave={handleDragLeave} className={cn('flex min-h-[5rem] w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-md border-2 border-dashed border-border bg-muted/30 px-4 py-6 text-center transition-colors', 'hover:border-primary/50 hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', isDragging && 'border-primary bg-primary/5', disabled && 'cursor-not-allowed opacity-60')}>
|
|
61
|
+
{showSpinner ? (<>
|
|
62
|
+
<Loader2 className="size-6 animate-spin text-muted-foreground"/>
|
|
63
|
+
<span className="text-sm text-muted-foreground">{l.uploading}</span>
|
|
64
|
+
</>) : (<>
|
|
65
|
+
<Upload className="size-6 text-muted-foreground"/>
|
|
66
|
+
<span className="text-sm font-medium text-foreground">
|
|
67
|
+
<span className="hidden sm:inline">{l.dragAndDrop} </span>
|
|
68
|
+
<span className="text-primary underline-offset-2 hover:underline">
|
|
69
|
+
{items.length > 0 ? l.addMoreLink : l.chooseLink}
|
|
70
|
+
</span>
|
|
71
|
+
</span>
|
|
72
|
+
{accept && (<span className="text-xs text-muted-foreground">{accept}</span>)}
|
|
73
|
+
</>)}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{/* Current file list */}
|
|
77
|
+
{items.length > 0 && (<ul className="space-y-1">
|
|
78
|
+
{items.map((item, idx) => {
|
|
79
|
+
const label = item.displayName || (item.value ? item.value.split('/').pop() : null);
|
|
80
|
+
const showImage = isImageUrl(item.previewUrl);
|
|
81
|
+
return (<li key={`${item.value}-${idx}`} className="flex items-center gap-2 rounded-md border border-border bg-background px-3 py-2">
|
|
82
|
+
{showImage && item.previewUrl ? (<img src={item.previewUrl} alt={label ?? 'preview'} className="size-10 shrink-0 rounded object-cover"/>) : (<FileText className="size-5 shrink-0 text-muted-foreground"/>)}
|
|
83
|
+
<span className="min-w-0 flex-1 truncate text-sm text-foreground" title={label ?? item.value}>
|
|
84
|
+
{label ?? item.value}
|
|
85
|
+
</span>
|
|
86
|
+
{!disabled && (<Button type="button" variant="ghost" size="icon" className="size-7 shrink-0 text-muted-foreground hover:text-destructive" aria-label={l.removeFile} onClick={(e) => {
|
|
87
|
+
e.stopPropagation();
|
|
88
|
+
onRemove(idx);
|
|
89
|
+
}}>
|
|
90
|
+
<X className="size-4"/>
|
|
91
|
+
</Button>)}
|
|
92
|
+
</li>);
|
|
93
|
+
})}
|
|
94
|
+
</ul>)}
|
|
95
|
+
|
|
96
|
+
{/* In-progress uploads */}
|
|
97
|
+
{hasPending && (<ul className="space-y-1">
|
|
98
|
+
{pendingItems.map((p) => (<li key={p.id} className={cn('flex items-center gap-3 rounded-md border bg-background px-3 py-2', p.status === 'error' ? 'border-destructive/50' : 'border-border')}>
|
|
99
|
+
{p.status === 'error' ? (<FileText className="size-5 shrink-0 text-destructive"/>) : (<Loader2 className="size-5 shrink-0 animate-spin text-muted-foreground"/>)}
|
|
100
|
+
<div className="min-w-0 flex-1">
|
|
101
|
+
<div className="truncate text-sm text-foreground" title={p.name}>
|
|
102
|
+
{p.name}
|
|
103
|
+
</div>
|
|
104
|
+
{p.status === 'error' ? (<div className="text-xs text-destructive" role="alert">
|
|
105
|
+
{p.error || l.uploadFailed}
|
|
106
|
+
</div>) : (<div className="mt-1 flex items-center gap-2">
|
|
107
|
+
<div className="h-1.5 flex-1 overflow-hidden rounded-full bg-muted" role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-valuenow={p.progress ?? 0}>
|
|
108
|
+
<div className="h-full rounded-full bg-primary transition-[width] duration-150 ease-out" style={{ width: `${p.progress ?? 0}%` }}/>
|
|
109
|
+
</div>
|
|
110
|
+
<span className="w-10 shrink-0 text-right text-xs tabular-nums text-muted-foreground">
|
|
111
|
+
{p.progress != null ? `${p.progress}%` : '…'}
|
|
112
|
+
</span>
|
|
113
|
+
</div>)}
|
|
114
|
+
</div>
|
|
115
|
+
{p.status === 'error' && onPendingDismiss && (<Button type="button" variant="ghost" size="icon" className="size-7 shrink-0 text-muted-foreground hover:text-destructive" aria-label={l.dismiss} onClick={(e) => {
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
onPendingDismiss(p.id);
|
|
118
|
+
}}>
|
|
119
|
+
<X className="size-4"/>
|
|
120
|
+
</Button>)}
|
|
121
|
+
</li>))}
|
|
122
|
+
</ul>)}
|
|
123
|
+
|
|
124
|
+
{/* Error message */}
|
|
125
|
+
{error && <p className="text-sm text-destructive">{error}</p>}
|
|
126
|
+
|
|
127
|
+
{/* Hidden native input */}
|
|
128
|
+
<input ref={inputRef} type="file" accept={accept} multiple className="sr-only" onChange={handleInputChange} disabled={disabled} tabIndex={-1} aria-hidden/>
|
|
129
|
+
</div>);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=multi-file-input.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-file-input.jsx","sourceRoot":"","sources":["../../src/components/multi-file-input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface PasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
3
|
+
/** Accessible label for the visibility toggle button. */
|
|
4
|
+
toggleLabel?: {
|
|
5
|
+
show: string;
|
|
6
|
+
hide: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare const PasswordInput: React.ForwardRefExoticComponent<PasswordInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
10
|
+
//# sourceMappingURL=password-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-input.d.ts","sourceRoot":"","sources":["../../src/components/password-input.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACjE,yDAAyD;IACzD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7C;AAED,eAAO,MAAM,aAAa,6FAkCzB,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Password field with a built-in show/hide toggle. Drops in anywhere a
|
|
2
|
+
// regular <Input type="password" /> would — it forwards refs and accepts
|
|
3
|
+
// the same props (the `type` prop is intentionally ignored).
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { Eye, EyeOff } from 'lucide-react';
|
|
6
|
+
import { cn } from '../lib/utils.js';
|
|
7
|
+
export const PasswordInput = React.forwardRef(({ className, toggleLabel, disabled, ...props }, ref) => {
|
|
8
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
9
|
+
const labels = toggleLabel ?? { show: 'Show password', hide: 'Hide password' };
|
|
10
|
+
return (<div className="relative">
|
|
11
|
+
<input ref={ref} type={revealed ? 'text' : 'password'} disabled={disabled} className={cn('flex h-9 w-full rounded-md border border-input bg-background pl-3 pr-10 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', className)} {...props}/>
|
|
12
|
+
<button type="button" tabIndex={-1} onClick={() => setRevealed((v) => !v)} disabled={disabled} aria-label={revealed ? labels.hide : labels.show} aria-pressed={revealed} className="absolute inset-y-0 right-0 flex w-9 cursor-pointer items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50">
|
|
13
|
+
{revealed ? (<EyeOff className="size-4" aria-hidden="true"/>) : (<Eye className="size-4" aria-hidden="true"/>)}
|
|
14
|
+
</button>
|
|
15
|
+
</div>);
|
|
16
|
+
});
|
|
17
|
+
PasswordInput.displayName = 'PasswordInput';
|
|
18
|
+
//# sourceMappingURL=password-input.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-input.jsx","sourceRoot":"","sources":["../../src/components/password-input.tsx"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yEAAyE;AACzE,6DAA6D;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAQpC,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAC3C,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IACtD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,WAAW,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,CAAA;IAC9E,OAAO,CACL,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CACvB;QAAA,CAAC,KAAK,CACJ,GAAG,CAAC,CAAC,GAAG,CAAC,CACT,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CACrC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,SAAS,CAAC,CAAC,EAAE,CACX,4QAA4Q,EAC5Q,SAAS,CACV,CAAC,CACF,IAAI,KAAK,CAAC,EAEZ;QAAA,CAAC,MAAM,CACL,IAAI,CAAC,QAAQ,CACb,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CACb,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CACtC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CACjD,YAAY,CAAC,CAAC,QAAQ,CAAC,CACvB,SAAS,CAAC,mRAAmR,CAE7R;UAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,CACV,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAG,CACjD,CAAC,CAAC,CAAC,CACF,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAG,CAC9C,CACH;QAAA,EAAE,MAAM,CACV;MAAA,EAAE,GAAG,CAAC,CACP,CAAA;AACH,CAAC,CACF,CAAA;AACD,aAAa,CAAC,WAAW,GAAG,eAAe,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
3
|
+
export declare const Popover: React.FC<PopoverPrimitive.PopoverProps>;
|
|
4
|
+
export declare const PopoverTrigger: React.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
5
|
+
export declare const PopoverAnchor: React.ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
export declare const PopoverContent: React.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
//# sourceMappingURL=popover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/components/popover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAG3D,eAAO,MAAM,OAAO,yCAAwB,CAAA;AAC5C,eAAO,MAAM,cAAc,gHAA2B,CAAA;AACtD,eAAO,MAAM,aAAa,4GAA0B,CAAA;AAEpD,eAAO,MAAM,cAAc,gKAgBzB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
3
|
+
import { cn } from '../lib/utils.js';
|
|
4
|
+
export const Popover = PopoverPrimitive.Root;
|
|
5
|
+
export const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
6
|
+
export const PopoverAnchor = PopoverPrimitive.Anchor;
|
|
7
|
+
export const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (<PopoverPrimitive.Portal>
|
|
8
|
+
<PopoverPrimitive.Content ref={ref} align={align} sideOffset={sideOffset} className={cn('z-50 w-72 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2', className)} {...props}/>
|
|
9
|
+
</PopoverPrimitive.Portal>));
|
|
10
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
11
|
+
//# sourceMappingURL=popover.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.jsx","sourceRoot":"","sources":["../../src/components/popover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAA;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,OAAO,CAAA;AACtD,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAA;AAEpD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAG5C,CAAC,EAAE,SAAS,EAAE,KAAK,GAAG,QAAQ,EAAE,UAAU,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CACpE,CAAC,gBAAgB,CAAC,MAAM,CACtB;IAAA,CAAC,gBAAgB,CAAC,OAAO,CACvB,GAAG,CAAC,CAAC,GAAG,CAAC,CACT,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,SAAS,CAAC,CAAC,EAAE,CACX,4WAA4W,EAC5W,SAAS,CACV,CAAC,CACF,IAAI,KAAK,CAAC,EAEd;EAAA,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAC3B,CAAC,CAAA;AACF,cAAc,CAAC,WAAW,GAAG,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface RevisionTimelineItem {
|
|
3
|
+
id: string;
|
|
4
|
+
op: 'create' | 'update' | 'delete';
|
|
5
|
+
userId?: string;
|
|
6
|
+
/** Resolved, human-readable label for the user who created the revision
|
|
7
|
+
* (e.g. email or full name). When set, it's shown instead of the raw
|
|
8
|
+
* `userId`. Resolution happens in the React layer so this UI component
|
|
9
|
+
* stays i18n- and data-source-agnostic. */
|
|
10
|
+
userLabel?: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
changes?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RevisionTimelineLabels {
|
|
15
|
+
create?: string;
|
|
16
|
+
update?: string;
|
|
17
|
+
delete?: string;
|
|
18
|
+
unknownUser?: string;
|
|
19
|
+
changes?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface RevisionTimelineProps {
|
|
22
|
+
items: ReadonlyArray<RevisionTimelineItem>;
|
|
23
|
+
selectedId?: string;
|
|
24
|
+
labels?: RevisionTimelineLabels;
|
|
25
|
+
className?: string;
|
|
26
|
+
formatDate?: (value: string) => string;
|
|
27
|
+
onSelect?: (item: RevisionTimelineItem) => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function RevisionTimeline({ items, selectedId, labels, className, formatDate, onSelect, }: RevisionTimelineProps): React.ReactElement;
|
|
30
|
+
//# sourceMappingURL=revision-timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-timeline.d.ts","sourceRoot":"","sources":["../../src/components/revision-timeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;gDAG4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,sBAAsB,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAA;CAChD;AAUD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,UAAU,EACV,MAAM,EACN,SAAS,EACT,UAAqB,EACrB,QAAQ,GACT,EAAE,qBAAqB,GAAG,KAAK,CAAC,YAAY,CAsC5C"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { cn } from '../lib/utils.js';
|
|
3
|
+
const DEFAULT_LABELS = {
|
|
4
|
+
create: 'Created',
|
|
5
|
+
update: 'Updated',
|
|
6
|
+
delete: 'Deleted',
|
|
7
|
+
unknownUser: 'Unknown user',
|
|
8
|
+
changes: 'changes',
|
|
9
|
+
};
|
|
10
|
+
export function RevisionTimeline({ items, selectedId, labels, className, formatDate = (v) => v, onSelect, }) {
|
|
11
|
+
const l = { ...DEFAULT_LABELS, ...labels };
|
|
12
|
+
return (<div className={cn('space-y-2', className)}>
|
|
13
|
+
{items.map((item) => {
|
|
14
|
+
const selected = item.id === selectedId;
|
|
15
|
+
return (<button key={item.id} type="button" onClick={() => onSelect?.(item)} className={cn('relative flex w-full gap-3 rounded-md border p-3 text-left transition-colors', selected ? 'border-primary bg-primary/5' : 'bg-card hover:bg-muted/50')}>
|
|
16
|
+
<span className="mt-1 size-2.5 shrink-0 rounded-full bg-primary"/>
|
|
17
|
+
<span className="min-w-0 flex-1 space-y-1">
|
|
18
|
+
<span className="flex items-center justify-between gap-2">
|
|
19
|
+
<span className="truncate text-sm font-medium">{labelForOp(item.op, l)}</span>
|
|
20
|
+
{item.changes !== undefined && (<span className="shrink-0 text-xs text-muted-foreground">
|
|
21
|
+
{item.changes} {l.changes}
|
|
22
|
+
</span>)}
|
|
23
|
+
</span>
|
|
24
|
+
<span className="block truncate text-xs text-muted-foreground">
|
|
25
|
+
{item.userLabel ?? item.userId ?? l.unknownUser}
|
|
26
|
+
</span>
|
|
27
|
+
<span className="block text-xs text-muted-foreground">
|
|
28
|
+
{formatDate(item.createdAt)}
|
|
29
|
+
</span>
|
|
30
|
+
</span>
|
|
31
|
+
</button>);
|
|
32
|
+
})}
|
|
33
|
+
</div>);
|
|
34
|
+
}
|
|
35
|
+
function labelForOp(op, labels) {
|
|
36
|
+
if (op === 'create')
|
|
37
|
+
return labels.create;
|
|
38
|
+
if (op === 'delete')
|
|
39
|
+
return labels.delete;
|
|
40
|
+
return labels.update;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=revision-timeline.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-timeline.jsx","sourceRoot":"","sources":["../../src/components/revision-timeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAgCpC,MAAM,cAAc,GAAqC;IACvD,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,cAAc;IAC3B,OAAO,EAAE,SAAS;CACnB,CAAA;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,UAAU,EACV,MAAM,EACN,SAAS,EACT,UAAU,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EACrB,QAAQ,GACc;IACtB,MAAM,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAA;IAC1C,OAAO,CACL,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CACzC;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,KAAK,UAAU,CAAA;YACvC,OAAO,CACL,CAAC,MAAM,CACL,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CACb,IAAI,CAAC,QAAQ,CACb,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAChC,SAAS,CAAC,CAAC,EAAE,CACX,8EAA8E,EAC9E,QAAQ,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,2BAA2B,CACvE,CAAC,CAEF;YAAA,CAAC,IAAI,CAAC,SAAS,CAAC,gDAAgD,EAChE;YAAA,CAAC,IAAI,CAAC,SAAS,CAAC,0BAA0B,CACxC;cAAA,CAAC,IAAI,CAAC,SAAS,CAAC,yCAAyC,CACvD;gBAAA,CAAC,IAAI,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAC7E;gBAAA,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,CAC7B,CAAC,IAAI,CAAC,SAAS,CAAC,wCAAwC,CACtD;oBAAA,CAAC,IAAI,CAAC,OAAO,CAAE,CAAA,CAAC,CAAC,CAAC,OAAO,CAC3B;kBAAA,EAAE,IAAI,CAAC,CACR,CACH;cAAA,EAAE,IAAI,CACN;cAAA,CAAC,IAAI,CAAC,SAAS,CAAC,8CAA8C,CAC5D;gBAAA,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,WAAW,CACjD;cAAA,EAAE,IAAI,CACN;cAAA,CAAC,IAAI,CAAC,SAAS,CAAC,qCAAqC,CACnD;gBAAA,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAC7B;cAAA,EAAE,IAAI,CACR;YAAA,EAAE,IAAI,CACR;UAAA,EAAE,MAAM,CAAC,CACV,CAAA;QACH,CAAC,CAAC,CACJ;IAAA,EAAE,GAAG,CAAC,CACP,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAA8B,EAAE,MAAwC;IAC1F,IAAI,EAAE,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,MAAM,CAAA;IACzC,IAAI,EAAE,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,MAAM,CAAA;IACzC,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type RichtextMode } from './richtext-mode.js';
|
|
3
|
+
export type RichtextFormat = 'html' | 'markdown';
|
|
4
|
+
export interface RichtextEditorLabels {
|
|
5
|
+
bold?: string;
|
|
6
|
+
italic?: string;
|
|
7
|
+
strikethrough?: string;
|
|
8
|
+
inlineCode?: string;
|
|
9
|
+
/** Template — `{level}` is replaced with 1/2/3. Default: "Heading {level}". */
|
|
10
|
+
heading?: string;
|
|
11
|
+
bulletList?: string;
|
|
12
|
+
numberedList?: string;
|
|
13
|
+
blockquote?: string;
|
|
14
|
+
horizontalRule?: string;
|
|
15
|
+
insertLink?: string;
|
|
16
|
+
undo?: string;
|
|
17
|
+
redo?: string;
|
|
18
|
+
/** Template — `{format}` is replaced with "html"/"md". Default: "Source ({format})". */
|
|
19
|
+
source?: string;
|
|
20
|
+
splitView?: string;
|
|
21
|
+
visualEditor?: string;
|
|
22
|
+
fullscreen?: string;
|
|
23
|
+
exitFullscreen?: string;
|
|
24
|
+
/** Prompt text for link URL input. Default: "URL". */
|
|
25
|
+
urlPrompt?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface RichtextEditorProps {
|
|
28
|
+
value: string;
|
|
29
|
+
onChange(value: string): void;
|
|
30
|
+
format?: RichtextFormat;
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/** Initial mode of the editor. Defaults to 'wysiwyg'. */
|
|
34
|
+
defaultMode?: RichtextMode;
|
|
35
|
+
className?: string;
|
|
36
|
+
/** Called when the editor blurs. Useful for RHF onBlur. */
|
|
37
|
+
onBlur?(): void;
|
|
38
|
+
ariaLabelledBy?: string;
|
|
39
|
+
/** Translated toolbar labels. All optional — English strings are the defaults. */
|
|
40
|
+
labels?: RichtextEditorLabels;
|
|
41
|
+
}
|
|
42
|
+
export declare function RichtextEditor({ value, onChange, format, placeholder, disabled, defaultMode, className, onBlur, ariaLabelledBy, labels, }: RichtextEditorProps): React.ReactElement;
|
|
43
|
+
//# sourceMappingURL=richtext-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"richtext-editor.d.ts","sourceRoot":"","sources":["../../src/components/richtext-editor.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA2B9B,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAA;AAM3B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAA;AAEhD,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yDAAyD;IACzD,WAAW,CAAC,EAAE,YAAY,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,MAAM,CAAC,IAAI,IAAI,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,kFAAkF;IAClF,MAAM,CAAC,EAAE,oBAAoB,CAAA;CAC9B;AAsDD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,MAAe,EACf,WAAW,EACX,QAAQ,EACR,WAAuB,EACvB,SAAS,EACT,MAAM,EACN,cAAc,EACd,MAAM,GACP,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAud1C"}
|