@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,187 @@
|
|
|
1
|
+
// KeyValueEditor + KeyValueView — a friendly alternative to JsonEditor for
|
|
2
|
+
// JSON columns with a *fixed* set of keys.
|
|
3
|
+
//
|
|
4
|
+
// Instead of showing the raw JSON (`{ "locale": "en", "featured": true }`)
|
|
5
|
+
// the editor renders one row per declared key, each with a normal form
|
|
6
|
+
// input typed appropriately (string, number, boolean, textarea, select).
|
|
7
|
+
// No braces, no quotes, no parse errors — the user just edits the values.
|
|
8
|
+
//
|
|
9
|
+
// The component is i18n-unaware: it accepts an optional `labels` prop with
|
|
10
|
+
// English fallbacks so it works standalone in tests/Storybook. The
|
|
11
|
+
// `packages/react` layer translates and feeds them in.
|
|
12
|
+
//
|
|
13
|
+
// Mobile-first: each row stacks label-above-input on narrow screens and
|
|
14
|
+
// switches to a two-column label/input layout from `sm:` upwards.
|
|
15
|
+
import * as React from 'react';
|
|
16
|
+
import { cn } from '../lib/utils.js';
|
|
17
|
+
import { Input } from './input.js';
|
|
18
|
+
import { Textarea } from './textarea.js';
|
|
19
|
+
import { Switch } from './switch.js';
|
|
20
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from './select.js';
|
|
21
|
+
import { Combobox } from './combobox.js';
|
|
22
|
+
import { InfoTooltip } from './info-tooltip.js';
|
|
23
|
+
const defaultLabels = {
|
|
24
|
+
emptyOption: '—',
|
|
25
|
+
fieldLabelFallback: (key) => key,
|
|
26
|
+
};
|
|
27
|
+
const toRecord = (value) => {
|
|
28
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
return {};
|
|
32
|
+
};
|
|
33
|
+
const normaliseAvailableValues = (raw) => {
|
|
34
|
+
if (!raw)
|
|
35
|
+
return [];
|
|
36
|
+
return raw.map((v) => (typeof v === 'string' ? { value: v, label: v } : v));
|
|
37
|
+
};
|
|
38
|
+
const SENTINEL_EMPTY = '__kv_empty__';
|
|
39
|
+
export function KeyValueEditor({ fields, value, onChange, onBlur, disabled, className, labels, suggestionsByKey, suggestionsLoadingByKey, }) {
|
|
40
|
+
const l = { ...defaultLabels, ...labels };
|
|
41
|
+
const obj = toRecord(value);
|
|
42
|
+
// Replace `key` with `next` and emit a brand-new object so callers using
|
|
43
|
+
// referential equality (e.g. RHF) detect the change.
|
|
44
|
+
const set = (key, next) => {
|
|
45
|
+
const out = { ...obj };
|
|
46
|
+
if (next === null || next === undefined) {
|
|
47
|
+
delete out[key];
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
out[key] = next;
|
|
51
|
+
}
|
|
52
|
+
onChange(out);
|
|
53
|
+
};
|
|
54
|
+
return (<div className={cn('divide-y divide-border rounded-md border border-border bg-card', className)}>
|
|
55
|
+
{fields.map((f) => {
|
|
56
|
+
const fieldType = f.type ?? 'string';
|
|
57
|
+
const label = f.label ?? l.fieldLabelFallback(f.key);
|
|
58
|
+
const inputId = `kv-${f.key}`;
|
|
59
|
+
const raw = obj[f.key];
|
|
60
|
+
let control;
|
|
61
|
+
if (fieldType === 'boolean') {
|
|
62
|
+
control = (<Switch id={inputId} checked={Boolean(raw)} onCheckedChange={(v) => set(f.key, Boolean(v))} disabled={disabled} aria-label={label}/>);
|
|
63
|
+
}
|
|
64
|
+
else if (fieldType === 'number') {
|
|
65
|
+
control = (<Input id={inputId} type="number" inputMode="decimal" value={raw == null ? '' : String(raw)} placeholder={f.placeholder} disabled={disabled} onBlur={onBlur} onChange={(e) => {
|
|
66
|
+
const v = e.target.value;
|
|
67
|
+
if (v === '')
|
|
68
|
+
return set(f.key, null);
|
|
69
|
+
const n = Number(v);
|
|
70
|
+
set(f.key, Number.isFinite(n) ? n : v);
|
|
71
|
+
}} aria-label={label}/>);
|
|
72
|
+
}
|
|
73
|
+
else if (fieldType === 'textarea') {
|
|
74
|
+
control = (<Textarea id={inputId} value={raw == null ? '' : String(raw)} placeholder={f.placeholder} disabled={disabled} onBlur={onBlur} onChange={(e) => set(f.key, e.target.value === '' ? null : e.target.value)} rows={3} aria-label={label}/>);
|
|
75
|
+
}
|
|
76
|
+
else if (fieldType === 'select') {
|
|
77
|
+
const opts = normaliseAvailableValues(f.availableValues);
|
|
78
|
+
const current = raw == null || raw === '' ? SENTINEL_EMPTY : String(raw);
|
|
79
|
+
control = (<Select value={current} onValueChange={(v) => set(f.key, v === SENTINEL_EMPTY ? null : v)} disabled={disabled}>
|
|
80
|
+
<SelectTrigger id={inputId} aria-label={label}>
|
|
81
|
+
<SelectValue placeholder={l.emptyOption}/>
|
|
82
|
+
</SelectTrigger>
|
|
83
|
+
<SelectContent>
|
|
84
|
+
<SelectItem value={SENTINEL_EMPTY}>{l.emptyOption}</SelectItem>
|
|
85
|
+
{opts.map((opt) => (<SelectItem key={opt.value} value={opt.value}>
|
|
86
|
+
{opt.label}
|
|
87
|
+
</SelectItem>))}
|
|
88
|
+
</SelectContent>
|
|
89
|
+
</Select>);
|
|
90
|
+
}
|
|
91
|
+
else if (fieldType === 'autocomplete') {
|
|
92
|
+
// Combine static `availableValues` declared on the field with
|
|
93
|
+
// any dynamic values pre-loaded by the parent (e.g. distinct
|
|
94
|
+
// values from a DB column). Dedupe by `value` so a static hint
|
|
95
|
+
// and a DB row that share a value collapse to a single item.
|
|
96
|
+
const fromStatic = normaliseAvailableValues(f.availableValues);
|
|
97
|
+
const fromDynamic = suggestionsByKey?.[f.key] ?? [];
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
const merged = [];
|
|
100
|
+
for (const s of [...fromStatic, ...fromDynamic]) {
|
|
101
|
+
const v = typeof s === 'string' ? s : s.value;
|
|
102
|
+
if (seen.has(v))
|
|
103
|
+
continue;
|
|
104
|
+
seen.add(v);
|
|
105
|
+
merged.push(s);
|
|
106
|
+
}
|
|
107
|
+
control = (<Combobox id={inputId} value={raw == null ? '' : String(raw)} onChange={(v) => set(f.key, v === '' ? null : v)} onBlur={onBlur} suggestions={merged} loading={suggestionsLoadingByKey?.[f.key]} disabled={disabled} placeholder={f.placeholder} aria-label={label} labels={labels?.combobox}/>);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// string (default)
|
|
111
|
+
control = (<Input id={inputId} type="text" value={raw == null ? '' : String(raw)} placeholder={f.placeholder} disabled={disabled} onBlur={onBlur} onChange={(e) => set(f.key, e.target.value === '' ? null : e.target.value)} aria-label={label}/>);
|
|
112
|
+
}
|
|
113
|
+
return (<div key={f.key} className="flex flex-col gap-1.5 p-3 sm:flex-row sm:items-start sm:gap-4">
|
|
114
|
+
<label htmlFor={inputId} className="flex shrink-0 items-center gap-1 text-sm font-medium text-foreground sm:w-44 sm:pt-2">
|
|
115
|
+
<span className="truncate">{label}</span>
|
|
116
|
+
{f.description ? (<InfoTooltip content={f.description} ariaLabel={f.description}/>) : null}
|
|
117
|
+
{f.isRequired ? (<span aria-hidden="true" className="text-destructive">
|
|
118
|
+
*
|
|
119
|
+
</span>) : null}
|
|
120
|
+
</label>
|
|
121
|
+
<div className="min-w-0 flex-1">
|
|
122
|
+
{control}
|
|
123
|
+
</div>
|
|
124
|
+
</div>);
|
|
125
|
+
})}
|
|
126
|
+
</div>);
|
|
127
|
+
}
|
|
128
|
+
const defaultViewLabels = {
|
|
129
|
+
emptyValue: '—',
|
|
130
|
+
fieldLabelFallback: (key) => key,
|
|
131
|
+
trueLabel: 'Yes',
|
|
132
|
+
falseLabel: 'No',
|
|
133
|
+
};
|
|
134
|
+
const stringifyDisplay = (raw, field, l) => {
|
|
135
|
+
if (raw == null || raw === '')
|
|
136
|
+
return l.emptyValue;
|
|
137
|
+
if (field.type === 'boolean')
|
|
138
|
+
return raw ? l.trueLabel : l.falseLabel;
|
|
139
|
+
if ((field.type === 'select' || field.type === 'autocomplete') &&
|
|
140
|
+
field.availableValues) {
|
|
141
|
+
const opts = normaliseAvailableValues(field.availableValues);
|
|
142
|
+
const match = opts.find((o) => o.value === String(raw));
|
|
143
|
+
return match?.label ?? String(raw);
|
|
144
|
+
}
|
|
145
|
+
if (typeof raw === 'object') {
|
|
146
|
+
try {
|
|
147
|
+
return JSON.stringify(raw);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return String(raw);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return String(raw);
|
|
154
|
+
};
|
|
155
|
+
export function KeyValueView({ fields, value, className, variant = 'block', labels, }) {
|
|
156
|
+
const l = { ...defaultViewLabels, ...labels };
|
|
157
|
+
const obj = toRecord(value);
|
|
158
|
+
if (variant === 'inline') {
|
|
159
|
+
const parts = fields
|
|
160
|
+
.map((f) => {
|
|
161
|
+
const raw = obj[f.key];
|
|
162
|
+
if (raw == null || raw === '')
|
|
163
|
+
return null;
|
|
164
|
+
const label = f.label ?? l.fieldLabelFallback(f.key);
|
|
165
|
+
return `${label}: ${stringifyDisplay(raw, f, l)}`;
|
|
166
|
+
})
|
|
167
|
+
.filter((s) => s !== null);
|
|
168
|
+
return (<span className={cn('line-clamp-1 max-w-[24rem] truncate text-xs text-muted-foreground', className)} title={parts.join(', ') || undefined}>
|
|
169
|
+
{parts.length > 0 ? parts.join(', ') : l.emptyValue}
|
|
170
|
+
</span>);
|
|
171
|
+
}
|
|
172
|
+
return (<dl className={cn('divide-y divide-border rounded-md border border-border bg-muted/30 text-sm', className)}>
|
|
173
|
+
{fields.map((f) => {
|
|
174
|
+
const label = f.label ?? l.fieldLabelFallback(f.key);
|
|
175
|
+
const text = stringifyDisplay(obj[f.key], f, l);
|
|
176
|
+
return (<div key={f.key} className="flex flex-col gap-0.5 p-3 sm:flex-row sm:items-baseline sm:gap-4">
|
|
177
|
+
<dt className="shrink-0 text-xs font-medium uppercase tracking-wide text-muted-foreground sm:w-44">
|
|
178
|
+
{label}
|
|
179
|
+
</dt>
|
|
180
|
+
<dd className="min-w-0 flex-1 break-words text-foreground">
|
|
181
|
+
{text}
|
|
182
|
+
</dd>
|
|
183
|
+
</div>);
|
|
184
|
+
})}
|
|
185
|
+
</dl>);
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=key-value-editor.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-value-editor.jsx","sourceRoot":"","sources":["../../src/components/key-value-editor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface KeyboardShortcutItem {
|
|
3
|
+
/** Combo in `useHotkey` syntax, e.g. `mod+s`, `shift+/`, `esc`. */
|
|
4
|
+
keys: string;
|
|
5
|
+
description: string;
|
|
6
|
+
group?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface KeyboardShortcutsHelpProps {
|
|
9
|
+
open: boolean;
|
|
10
|
+
onOpenChange: (open: boolean) => void;
|
|
11
|
+
items: KeyboardShortcutItem[];
|
|
12
|
+
title?: React.ReactNode;
|
|
13
|
+
description?: React.ReactNode;
|
|
14
|
+
emptyMessage?: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export declare function KeyboardShortcutsHelp({ open, onOpenChange, items, title, description, emptyMessage, }: KeyboardShortcutsHelpProps): React.ReactElement;
|
|
17
|
+
//# sourceMappingURL=keyboard-shortcuts-help.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard-shortcuts-help.d.ts","sourceRoot":"","sources":["../../src/components/keyboard-shortcuts-help.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,KAAK,EAAE,oBAAoB,EAAE,CAAA;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC/B;AA6BD,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,KAAK,EACL,WAAW,EACX,YAAY,GACb,EAAE,0BAA0B,GAAG,KAAK,CAAC,YAAY,CAqEjD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Presentational dialog that lists keyboard shortcuts. Pass `items`;
|
|
2
|
+
// each entry's `keys` is a `+`-separated combo string (e.g. `mod+s`)
|
|
3
|
+
// and gets rendered as <Kbd> caps. `mod` resolves to ⌘ on macOS / Ctrl
|
|
4
|
+
// elsewhere via `getModKeyLabel()`. Items can optionally be grouped via
|
|
5
|
+
// `group` and the dialog sorts groups in insertion order.
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from './dialog.js';
|
|
8
|
+
import { Kbd, getModKeyLabel } from './kbd.js';
|
|
9
|
+
function chordParts(combo, modLabel) {
|
|
10
|
+
// Pick the first alternative (`a|b`) — the help dialog shows one
|
|
11
|
+
// canonical chord per entry.
|
|
12
|
+
const first = combo.split('|')[0] ?? '';
|
|
13
|
+
return first
|
|
14
|
+
.split('+')
|
|
15
|
+
.map((s) => s.trim().toLowerCase())
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.map((p) => {
|
|
18
|
+
if (p === 'mod' || p === 'ctrl' || p === 'meta' || p === 'cmd')
|
|
19
|
+
return modLabel;
|
|
20
|
+
if (p === 'shift')
|
|
21
|
+
return 'Shift';
|
|
22
|
+
if (p === 'alt' || p === 'option')
|
|
23
|
+
return 'Alt';
|
|
24
|
+
if (p === 'esc' || p === 'escape')
|
|
25
|
+
return 'Esc';
|
|
26
|
+
if (p === 'space' || p === ' ' || p === 'spacebar')
|
|
27
|
+
return 'Space';
|
|
28
|
+
if (p === 'enter' || p === 'return')
|
|
29
|
+
return 'Enter';
|
|
30
|
+
if (p === 'tab')
|
|
31
|
+
return 'Tab';
|
|
32
|
+
if (p === 'backspace')
|
|
33
|
+
return '⌫';
|
|
34
|
+
if (p === 'delete' || p === 'del')
|
|
35
|
+
return 'Del';
|
|
36
|
+
if (p === 'arrowup')
|
|
37
|
+
return '↑';
|
|
38
|
+
if (p === 'arrowdown')
|
|
39
|
+
return '↓';
|
|
40
|
+
if (p === 'arrowleft')
|
|
41
|
+
return '←';
|
|
42
|
+
if (p === 'arrowright')
|
|
43
|
+
return '→';
|
|
44
|
+
if (p.length === 1)
|
|
45
|
+
return p.toUpperCase();
|
|
46
|
+
return p.charAt(0).toUpperCase() + p.slice(1);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export function KeyboardShortcutsHelp({ open, onOpenChange, items, title, description, emptyMessage, }) {
|
|
50
|
+
const modLabel = getModKeyLabel();
|
|
51
|
+
// Group preserving insertion order.
|
|
52
|
+
const groups = React.useMemo(() => {
|
|
53
|
+
const m = new Map();
|
|
54
|
+
for (const it of items) {
|
|
55
|
+
const key = it.group ?? '';
|
|
56
|
+
const list = m.get(key);
|
|
57
|
+
if (list)
|
|
58
|
+
list.push(it);
|
|
59
|
+
else
|
|
60
|
+
m.set(key, [it]);
|
|
61
|
+
}
|
|
62
|
+
return Array.from(m.entries());
|
|
63
|
+
}, [items]);
|
|
64
|
+
return (<Dialog open={open} onOpenChange={onOpenChange}>
|
|
65
|
+
{/* aria-describedby={undefined} explicitly suppresses Radix's missing-
|
|
66
|
+
description warning for dialogs where no <DialogDescription> is
|
|
67
|
+
rendered. When `description` is provided the prop is omitted so
|
|
68
|
+
Radix can wire its context-based aria-describedby automatically. */}
|
|
69
|
+
<DialogContent className="max-w-md" {...(!description ? { 'aria-describedby': undefined } : {})}>
|
|
70
|
+
<DialogHeader>
|
|
71
|
+
<DialogTitle>{title ?? 'Keyboard shortcuts'}</DialogTitle>
|
|
72
|
+
{description && <DialogDescription>{description}</DialogDescription>}
|
|
73
|
+
</DialogHeader>
|
|
74
|
+
{items.length === 0 ? (<p className="text-sm text-muted-foreground">
|
|
75
|
+
{emptyMessage ?? 'No shortcuts available on this screen.'}
|
|
76
|
+
</p>) : (<div className="flex flex-col gap-4">
|
|
77
|
+
{groups.map(([groupName, list]) => (<div key={groupName || '__default__'} className="flex flex-col gap-2">
|
|
78
|
+
{groupName && (<h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
79
|
+
{groupName}
|
|
80
|
+
</h3>)}
|
|
81
|
+
<ul className="flex flex-col divide-y divide-border rounded-md border border-border">
|
|
82
|
+
{list.map((it, idx) => (<li key={`${it.keys}:${idx}`} className="flex items-center justify-between gap-3 px-3 py-2">
|
|
83
|
+
<span className="text-sm">{it.description}</span>
|
|
84
|
+
<span className="inline-flex shrink-0 items-center gap-1">
|
|
85
|
+
{chordParts(it.keys, modLabel).map((part, i, arr) => (<React.Fragment key={i}>
|
|
86
|
+
<Kbd>{part}</Kbd>
|
|
87
|
+
{i < arr.length - 1 && (<span className="text-muted-foreground">+</span>)}
|
|
88
|
+
</React.Fragment>))}
|
|
89
|
+
</span>
|
|
90
|
+
</li>))}
|
|
91
|
+
</ul>
|
|
92
|
+
</div>))}
|
|
93
|
+
</div>)}
|
|
94
|
+
</DialogContent>
|
|
95
|
+
</Dialog>);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=keyboard-shortcuts-help.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard-shortcuts-help.jsx","sourceRoot":"","sources":["../../src/components/keyboard-shortcuts-help.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
3
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
4
|
+
export declare const Label: React.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: import("class-variance-authority/types").ClassProp | undefined) => string> & React.RefAttributes<HTMLLabelElement>>;
|
|
5
|
+
//# sourceMappingURL=label.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../src/components/label.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAOjE,eAAO,MAAM,KAAK,4PAKhB,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { cn } from '../lib/utils.js';
|
|
5
|
+
const labelVariants = cva('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70');
|
|
6
|
+
export const Label = React.forwardRef(({ className, ...props }, ref) => (<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props}/>));
|
|
7
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
8
|
+
//# sourceMappingURL=label.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.jsx","sourceRoot":"","sources":["../../src/components/label.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC,MAAM,aAAa,GAAG,GAAG,CACvB,4FAA4F,CAC7F,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAGnC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,EAAG,CACxF,CAAC,CAAA;AACF,KAAK,CAAC,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type MediaKind = 'image' | 'video' | 'audio' | 'unknown';
|
|
3
|
+
export declare function detectMediaKind(url: string): MediaKind;
|
|
4
|
+
export interface MediaPreviewProps {
|
|
5
|
+
/** Media URL. Should be a fully-qualified HTTP(S) URL. */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Optional override for the auto-detected media kind. */
|
|
8
|
+
kind?: MediaKind;
|
|
9
|
+
/** Suggested file name for the download. Falls back to URL pathname. */
|
|
10
|
+
downloadName?: string;
|
|
11
|
+
/** Strings (already-translated) to render in the UI. */
|
|
12
|
+
labels?: {
|
|
13
|
+
preview?: string;
|
|
14
|
+
download?: string;
|
|
15
|
+
downloadError?: string;
|
|
16
|
+
openInNewTab?: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
cannotPreview?: string;
|
|
20
|
+
};
|
|
21
|
+
/** Show the URL as secondary text next to the trigger. */
|
|
22
|
+
showUrl?: boolean;
|
|
23
|
+
/** Variant of the trigger button. Defaults to 'outline'. */
|
|
24
|
+
triggerVariant?: 'default' | 'outline' | 'secondary' | 'ghost' | 'link';
|
|
25
|
+
/** Size of the trigger button. Defaults to 'sm'. */
|
|
26
|
+
triggerSize?: 'default' | 'sm' | 'lg' | 'icon';
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function MediaPreview({ url, kind: kindProp, downloadName, labels, showUrl, triggerVariant, triggerSize, className, }: MediaPreviewProps): React.ReactElement;
|
|
30
|
+
//# sourceMappingURL=media-preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-preview.d.ts","sourceRoot":"","sources":["../../src/components/media-preview.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;AAM/D,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAMtD;AA0ED,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAA;IACX,0DAA0D;IAC1D,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wDAAwD;IACxD,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IACD,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAA;IACvE,oDAAoD;IACpD,WAAW,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAA;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,IAAI,EAAE,QAAQ,EACd,YAAY,EACZ,MAAM,EACN,OAAe,EACf,cAA0B,EAC1B,WAAkB,EAClB,SAAS,GACV,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CA2IxC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// MediaPreview — opens a dialog with an image/video preview and a download
|
|
2
|
+
// button. Used by the `previewMedia` property type to render HTTP(S) URLs to
|
|
3
|
+
// remote photos/videos as a "Preview" button instead of raw text.
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { Download, Eye, ExternalLink, Loader2, AlertCircle } from 'lucide-react';
|
|
6
|
+
import { cn } from '../lib/utils.js';
|
|
7
|
+
import { Button } from './button.js';
|
|
8
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from './dialog.js';
|
|
9
|
+
const IMAGE_EXT = /\.(jpe?g|png|gif|webp|avif|bmp|svg|ico|heic|heif)(\?|#|$)/i;
|
|
10
|
+
const VIDEO_EXT = /\.(mp4|webm|mov|m4v|ogv|avi|mkv)(\?|#|$)/i;
|
|
11
|
+
const AUDIO_EXT = /\.(mp3|wav|ogg|m4a|aac|flac)(\?|#|$)/i;
|
|
12
|
+
export function detectMediaKind(url) {
|
|
13
|
+
if (!url)
|
|
14
|
+
return 'unknown';
|
|
15
|
+
if (IMAGE_EXT.test(url))
|
|
16
|
+
return 'image';
|
|
17
|
+
if (VIDEO_EXT.test(url))
|
|
18
|
+
return 'video';
|
|
19
|
+
if (AUDIO_EXT.test(url))
|
|
20
|
+
return 'audio';
|
|
21
|
+
return 'unknown';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Probes the Content-Type of `url` when extension-based detection returns
|
|
25
|
+
* 'unknown'. Runs only when `enabled` is true (dialog has been opened).
|
|
26
|
+
*
|
|
27
|
+
* Strategy:
|
|
28
|
+
* 1. HEAD request — reads Content-Type header (works for same-origin or
|
|
29
|
+
* CORS-enabled APIs like public avatar services).
|
|
30
|
+
* 2. Image constructor fallback — handles servers that block HEAD but allow
|
|
31
|
+
* img GET (bypasses CORS for image fetches by design).
|
|
32
|
+
*
|
|
33
|
+
* Returns [resolvedKind, isLoading].
|
|
34
|
+
*/
|
|
35
|
+
function useProbeMediaKind(url, kindOverride, enabled) {
|
|
36
|
+
const byExt = React.useMemo(() => detectMediaKind(url), [url]);
|
|
37
|
+
const [kind, setKind] = React.useState(kindOverride ?? byExt);
|
|
38
|
+
const [loading, setLoading] = React.useState(false);
|
|
39
|
+
// Keep kind in sync when url or kindOverride changes (e.g. parent re-renders).
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
setKind(kindOverride ?? detectMediaKind(url));
|
|
42
|
+
setLoading(false);
|
|
43
|
+
}, [url, kindOverride]);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!enabled)
|
|
46
|
+
return;
|
|
47
|
+
if (kindOverride)
|
|
48
|
+
return;
|
|
49
|
+
if (byExt !== 'unknown')
|
|
50
|
+
return;
|
|
51
|
+
if (!url.startsWith('http'))
|
|
52
|
+
return;
|
|
53
|
+
let cancelled = false;
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
setLoading(true);
|
|
56
|
+
const resolve = (k) => {
|
|
57
|
+
if (cancelled)
|
|
58
|
+
return;
|
|
59
|
+
setKind(k);
|
|
60
|
+
setLoading(false);
|
|
61
|
+
};
|
|
62
|
+
// Image constructor fallback — works even when HEAD is CORS-blocked.
|
|
63
|
+
const tryImage = () => {
|
|
64
|
+
const img = new window.Image();
|
|
65
|
+
img.onload = () => resolve('image');
|
|
66
|
+
img.onerror = () => resolve('unknown');
|
|
67
|
+
img.src = url;
|
|
68
|
+
};
|
|
69
|
+
fetch(url, { method: 'HEAD', signal: controller.signal })
|
|
70
|
+
.then((res) => {
|
|
71
|
+
const ct = res.headers.get('content-type') ?? '';
|
|
72
|
+
if (ct.startsWith('image/'))
|
|
73
|
+
resolve('image');
|
|
74
|
+
else if (ct.startsWith('video/'))
|
|
75
|
+
resolve('video');
|
|
76
|
+
else if (ct.startsWith('audio/'))
|
|
77
|
+
resolve('audio');
|
|
78
|
+
else
|
|
79
|
+
tryImage();
|
|
80
|
+
})
|
|
81
|
+
.catch(() => {
|
|
82
|
+
if (!cancelled)
|
|
83
|
+
tryImage();
|
|
84
|
+
});
|
|
85
|
+
return () => {
|
|
86
|
+
cancelled = true;
|
|
87
|
+
controller.abort();
|
|
88
|
+
};
|
|
89
|
+
}, [url, kindOverride, byExt, enabled]);
|
|
90
|
+
return [kind, loading];
|
|
91
|
+
}
|
|
92
|
+
export function MediaPreview({ url, kind: kindProp, downloadName, labels, showUrl = false, triggerVariant = 'outline', triggerSize = 'sm', className, }) {
|
|
93
|
+
const [open, setOpen] = React.useState(false);
|
|
94
|
+
const [kind, kindLoading] = useProbeMediaKind(url, kindProp, open);
|
|
95
|
+
const [downloading, setDownloading] = React.useState(false);
|
|
96
|
+
const [downloadError, setDownloadError] = React.useState(false);
|
|
97
|
+
const previewLabel = labels?.preview ?? 'Preview';
|
|
98
|
+
const downloadLabel = labels?.download ?? 'Download';
|
|
99
|
+
const openLabel = labels?.openInNewTab ?? 'Open in new tab';
|
|
100
|
+
const titleLabel = labels?.title ?? previewLabel;
|
|
101
|
+
const cannotLabel = labels?.cannotPreview ?? 'Preview is unavailable for this media type.';
|
|
102
|
+
const inferredName = React.useMemo(() => {
|
|
103
|
+
if (downloadName)
|
|
104
|
+
return downloadName;
|
|
105
|
+
try {
|
|
106
|
+
const u = new URL(url);
|
|
107
|
+
const last = u.pathname.split('/').filter(Boolean).pop();
|
|
108
|
+
return last || 'download';
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return 'download';
|
|
112
|
+
}
|
|
113
|
+
}, [downloadName, url]);
|
|
114
|
+
// Force a file download via fetch → blob → blob URL. The <a download> attribute
|
|
115
|
+
// is silently ignored by browsers for cross-origin URLs, so we always use the
|
|
116
|
+
// blob approach. Falls back to window.open if fetch fails (e.g. no CORS).
|
|
117
|
+
const handleDownload = async () => {
|
|
118
|
+
setDownloadError(false);
|
|
119
|
+
setDownloading(true);
|
|
120
|
+
try {
|
|
121
|
+
const res = await fetch(url);
|
|
122
|
+
const blob = await res.blob();
|
|
123
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
124
|
+
const a = document.createElement('a');
|
|
125
|
+
a.href = blobUrl;
|
|
126
|
+
a.download = inferredName;
|
|
127
|
+
document.body.appendChild(a);
|
|
128
|
+
a.click();
|
|
129
|
+
document.body.removeChild(a);
|
|
130
|
+
URL.revokeObjectURL(blobUrl);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
setDownloadError(true);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
setDownloading(false);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
// Stop click propagation so that events from the Dialog portal (which bubble
|
|
140
|
+
// through the React component tree, not the DOM) do not reach parent row
|
|
141
|
+
// click handlers and trigger unintended navigation (e.g. list-page TableRow
|
|
142
|
+
// opening edit on backdrop/dialog click).
|
|
143
|
+
const stopClick = (e) => e.stopPropagation();
|
|
144
|
+
return (<div className={cn('inline-flex items-center gap-2', className)} onClick={stopClick}>
|
|
145
|
+
<Button type="button" variant={triggerVariant} size={triggerSize} onClick={() => setOpen(true)} disabled={!url}>
|
|
146
|
+
<Eye className="size-4"/>
|
|
147
|
+
<span>{previewLabel}</span>
|
|
148
|
+
</Button>
|
|
149
|
+
|
|
150
|
+
{showUrl && url ? (<span className="max-w-[24rem] truncate text-xs text-muted-foreground" title={url}>
|
|
151
|
+
{url}
|
|
152
|
+
</span>) : null}
|
|
153
|
+
|
|
154
|
+
<Dialog open={open} onOpenChange={setOpen}>
|
|
155
|
+
<DialogContent className="max-w-3xl">
|
|
156
|
+
<DialogHeader>
|
|
157
|
+
<DialogTitle>{titleLabel}</DialogTitle>
|
|
158
|
+
{labels?.description ? (<DialogDescription>{labels.description}</DialogDescription>) : (<DialogDescription className="break-all text-xs">{url}</DialogDescription>)}
|
|
159
|
+
</DialogHeader>
|
|
160
|
+
|
|
161
|
+
<div className="flex max-h-[70vh] items-center justify-center overflow-auto rounded-md border border-border bg-muted/30 p-2">
|
|
162
|
+
{kindLoading ? (<Loader2 className="size-8 animate-spin text-muted-foreground"/>) : kind === 'image' ? (<img src={url} alt={inferredName} className="max-h-[68vh] w-auto max-w-full object-contain"/>) : kind === 'video' ? (<video src={url} controls className="max-h-[68vh] w-full max-w-full"/>) : kind === 'audio' ? (<audio src={url} controls className="w-full"/>) : (<div className="p-6 text-center text-sm text-muted-foreground">
|
|
163
|
+
{cannotLabel}
|
|
164
|
+
</div>)}
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<DialogFooter>
|
|
168
|
+
{downloadError && (<span className="flex items-center gap-1.5 text-xs text-destructive">
|
|
169
|
+
<AlertCircle className="size-3.5"/>
|
|
170
|
+
{labels?.downloadError ?? 'Download failed'}
|
|
171
|
+
</span>)}
|
|
172
|
+
<Button asChild variant="ghost" size="sm">
|
|
173
|
+
<a href={url} target="_blank" rel="noopener noreferrer">
|
|
174
|
+
<ExternalLink className="size-4"/>
|
|
175
|
+
<span>{openLabel}</span>
|
|
176
|
+
</a>
|
|
177
|
+
</Button>
|
|
178
|
+
<Button variant="default" size="sm" disabled={downloading} onClick={() => { void handleDownload(); }}>
|
|
179
|
+
{downloading
|
|
180
|
+
? <Loader2 className="size-4 animate-spin"/>
|
|
181
|
+
: <Download className="size-4"/>}
|
|
182
|
+
<span>{downloadLabel}</span>
|
|
183
|
+
</Button>
|
|
184
|
+
</DialogFooter>
|
|
185
|
+
</DialogContent>
|
|
186
|
+
</Dialog>
|
|
187
|
+
</div>);
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=media-preview.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-preview.jsx","sourceRoot":"","sources":["../../src/components/media-preview.tsx"],"names":[],"mappings":"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"}
|