@vertebr/react 0.10.0 → 0.11.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/admin/AddonEditor.d.ts.map +1 -1
- package/dist/components/admin/AddonEditor.js +10 -8
- package/dist/components/admin/AdminContent.d.ts.map +1 -1
- package/dist/components/admin/AdminContent.js +55 -7
- package/dist/components/admin/AdminSaveBar.d.ts.map +1 -1
- package/dist/components/admin/AdminSaveBar.js +6 -1
- package/dist/components/admin/AdminSyncPage.d.ts.map +1 -1
- package/dist/components/admin/AdminSyncPage.js +50 -6
- package/dist/components/admin/PagePreviewPane.d.ts +3 -1
- package/dist/components/admin/PagePreviewPane.d.ts.map +1 -1
- package/dist/components/admin/PagePreviewPane.js +41 -9
- package/dist/components/admin/SyncPreviewFrame.d.ts +22 -0
- package/dist/components/admin/SyncPreviewFrame.d.ts.map +1 -0
- package/dist/components/admin/SyncPreviewFrame.js +135 -0
- package/dist/components/config/DatetimeInput.d.ts +15 -0
- package/dist/components/config/DatetimeInput.d.ts.map +1 -0
- package/dist/components/config/DatetimeInput.js +287 -0
- package/dist/components/config/EnumInput.d.ts.map +1 -1
- package/dist/components/config/EnumInput.js +4 -4
- package/dist/components/config/EnumListInput.d.ts.map +1 -1
- package/dist/components/config/EnumListInput.js +13 -3
- package/dist/components/config/RevisionHistory.d.ts +4 -0
- package/dist/components/config/RevisionHistory.d.ts.map +1 -1
- package/dist/components/config/RevisionHistory.js +63 -8
- package/dist/components/config/form/ConfigField.d.ts.map +1 -1
- package/dist/components/config/form/ConfigField.js +2 -1
- package/dist/components/config/form/ConfigForm.d.ts +1 -1
- package/dist/components/config/form/ConfigForm.d.ts.map +1 -1
- package/dist/components/config/form/ConfigForm.js +54 -9
- package/dist/components/config/form/types.d.ts +9 -0
- package/dist/components/config/form/types.d.ts.map +1 -1
- package/dist/hooks/useSaveBar.d.ts +6 -0
- package/dist/hooks/useSaveBar.d.ts.map +1 -1
- package/dist/styles/form.css +452 -17
- package/dist/styles/page-preview.css +84 -0
- package/dist/styles/select.css +23 -0
- package/dist/styles/sync.css +388 -4
- package/dist/themes/light.css +27 -0
- package/package.json +3 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DatetimeInputProps = {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
value: unknown;
|
|
5
|
+
readOnly?: boolean;
|
|
6
|
+
onBlur?: () => void;
|
|
7
|
+
onChange: (next: string) => void;
|
|
8
|
+
inputRef?: React.Ref<HTMLButtonElement>;
|
|
9
|
+
};
|
|
10
|
+
/** @deprecated Prefer parts helpers; kept for callers/tests. */
|
|
11
|
+
export declare function toDatetimeLocalValue(value: unknown): string;
|
|
12
|
+
/** @deprecated Prefer parts helpers; kept for callers/tests. */
|
|
13
|
+
export declare function fromDatetimeLocalValue(local: string): string;
|
|
14
|
+
export declare function DatetimeInput({ id, name, value, readOnly, onBlur, onChange, inputRef, }: DatetimeInputProps): import("react").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=DatetimeInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatetimeInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/DatetimeInput.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;CACzC,CAAC;AAsMF,gEAAgE;AAChE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAI3D;AAED,gEAAgE;AAChE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM5D;AAuED,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,+BAgQpB"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as Popover from "@radix-ui/react-popover";
|
|
3
|
+
import { useEffect, useId, useMemo, useState } from "react";
|
|
4
|
+
import { DayPicker } from "react-day-picker";
|
|
5
|
+
function pad(n) {
|
|
6
|
+
return String(n).padStart(2, "0");
|
|
7
|
+
}
|
|
8
|
+
function browserTimeZone() {
|
|
9
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
10
|
+
}
|
|
11
|
+
const TIME_ZONES = [
|
|
12
|
+
{ id: "America/New_York", label: "Eastern (ET)" },
|
|
13
|
+
{ id: "America/Chicago", label: "Central (CT)" },
|
|
14
|
+
{ id: "America/Denver", label: "Mountain (MT)" },
|
|
15
|
+
{ id: "America/Los_Angeles", label: "Pacific (PT)" },
|
|
16
|
+
{ id: "America/Phoenix", label: "Arizona (MST)" },
|
|
17
|
+
{ id: "America/Anchorage", label: "Alaska (AKT)" },
|
|
18
|
+
{ id: "Pacific/Honolulu", label: "Hawaii (HST)" },
|
|
19
|
+
{ id: "UTC", label: "UTC" },
|
|
20
|
+
{ id: "Europe/London", label: "London (GMT/BST)" },
|
|
21
|
+
{ id: "Europe/Paris", label: "Central Europe (CET)" },
|
|
22
|
+
{ id: "Asia/Tokyo", label: "Tokyo (JST)" },
|
|
23
|
+
{ id: "Australia/Sydney", label: "Sydney (AEST)" },
|
|
24
|
+
];
|
|
25
|
+
function timeZoneOptions(current) {
|
|
26
|
+
const known = new Set(TIME_ZONES.map((zone) => zone.id));
|
|
27
|
+
if (known.has(current))
|
|
28
|
+
return TIME_ZONES;
|
|
29
|
+
return [{ id: current, label: current.replace(/_/g, " ") }, ...TIME_ZONES];
|
|
30
|
+
}
|
|
31
|
+
function zonedParts(instant, timeZone) {
|
|
32
|
+
const bits = Object.fromEntries(new Intl.DateTimeFormat("en-US", {
|
|
33
|
+
timeZone,
|
|
34
|
+
year: "numeric",
|
|
35
|
+
month: "2-digit",
|
|
36
|
+
day: "2-digit",
|
|
37
|
+
hour: "2-digit",
|
|
38
|
+
minute: "2-digit",
|
|
39
|
+
hourCycle: "h23",
|
|
40
|
+
})
|
|
41
|
+
.formatToParts(instant)
|
|
42
|
+
.filter((part) => part.type !== "literal")
|
|
43
|
+
.map((part) => [part.type, part.value]));
|
|
44
|
+
return {
|
|
45
|
+
date: `${bits.year}-${bits.month}-${bits.day}`,
|
|
46
|
+
time: `${bits.hour}:${bits.minute}`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Wall-clock date/time in `timeZone` → UTC ISO. */
|
|
50
|
+
function toIsoInZone(parts, timeZone) {
|
|
51
|
+
if (!parts.date)
|
|
52
|
+
return "";
|
|
53
|
+
const time = parts.time || "00:00";
|
|
54
|
+
const dateBits = parts.date.split("-").map(Number);
|
|
55
|
+
const timeBits = time.split(":").map(Number);
|
|
56
|
+
const year = dateBits[0];
|
|
57
|
+
const month = dateBits[1];
|
|
58
|
+
const day = dateBits[2];
|
|
59
|
+
const hour = timeBits[0];
|
|
60
|
+
const minute = timeBits[1];
|
|
61
|
+
if (year === undefined ||
|
|
62
|
+
month === undefined ||
|
|
63
|
+
day === undefined ||
|
|
64
|
+
hour === undefined ||
|
|
65
|
+
minute === undefined ||
|
|
66
|
+
![year, month, day, hour, minute].every(Number.isFinite)) {
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
const desired = Date.UTC(year, month - 1, day, hour, minute, 0);
|
|
70
|
+
let utcMs = desired;
|
|
71
|
+
for (let i = 0; i < 2; i += 1) {
|
|
72
|
+
const shown = zonedParts(new Date(utcMs), timeZone);
|
|
73
|
+
const shownDate = shown.date.split("-").map(Number);
|
|
74
|
+
const shownTime = shown.time.split(":").map(Number);
|
|
75
|
+
const sy = shownDate[0];
|
|
76
|
+
const sm = shownDate[1];
|
|
77
|
+
const sd = shownDate[2];
|
|
78
|
+
const sh = shownTime[0];
|
|
79
|
+
const smin = shownTime[1];
|
|
80
|
+
if (sy === undefined ||
|
|
81
|
+
sm === undefined ||
|
|
82
|
+
sd === undefined ||
|
|
83
|
+
sh === undefined ||
|
|
84
|
+
smin === undefined) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
const asUtc = Date.UTC(sy, sm - 1, sd, sh, smin, 0);
|
|
88
|
+
utcMs -= asUtc - desired;
|
|
89
|
+
}
|
|
90
|
+
return new Date(utcMs).toISOString();
|
|
91
|
+
}
|
|
92
|
+
function partsFromValue(value, timeZone) {
|
|
93
|
+
if (typeof value !== "string")
|
|
94
|
+
return { date: "", time: "" };
|
|
95
|
+
const trimmed = value.trim();
|
|
96
|
+
if (!trimmed)
|
|
97
|
+
return { date: "", time: "" };
|
|
98
|
+
const ms = Date.parse(trimmed);
|
|
99
|
+
if (Number.isFinite(ms))
|
|
100
|
+
return zonedParts(new Date(ms), timeZone);
|
|
101
|
+
const match = trimmed.match(/^(\d{4}-\d{2}-\d{2})(?:[T\s](\d{2}:\d{2})(?::\d{2})?)?/);
|
|
102
|
+
if (!match)
|
|
103
|
+
return { date: "", time: "" };
|
|
104
|
+
return { date: match[1] ?? "", time: match[2] ?? "00:00" };
|
|
105
|
+
}
|
|
106
|
+
function to24h(hour12, meridiem) {
|
|
107
|
+
const hour = ((hour12 - 1) % 12) + 1;
|
|
108
|
+
if (meridiem === "AM")
|
|
109
|
+
return hour === 12 ? 0 : hour;
|
|
110
|
+
return hour === 12 ? 12 : hour + 12;
|
|
111
|
+
}
|
|
112
|
+
function toClock(time) {
|
|
113
|
+
const [hRaw, mRaw] = (time || "12:00").split(":");
|
|
114
|
+
let hour24 = Number(hRaw);
|
|
115
|
+
const minute = pad(Number.isFinite(Number(mRaw)) ? Number(mRaw) : 0);
|
|
116
|
+
if (!Number.isFinite(hour24))
|
|
117
|
+
hour24 = 12;
|
|
118
|
+
const meridiem = hour24 >= 12 ? "PM" : "AM";
|
|
119
|
+
const hour12 = hour24 % 12 === 0 ? 12 : hour24 % 12;
|
|
120
|
+
return { hour12: String(hour12), minute, meridiem };
|
|
121
|
+
}
|
|
122
|
+
function fromClock(clock) {
|
|
123
|
+
const hour12 = Number(clock.hour12);
|
|
124
|
+
const safeHour = Number.isFinite(hour12) ? hour12 : 12;
|
|
125
|
+
return `${pad(to24h(safeHour, clock.meridiem))}:${clock.minute || "00"}`;
|
|
126
|
+
}
|
|
127
|
+
function dateFromYmd(ymd) {
|
|
128
|
+
if (!ymd)
|
|
129
|
+
return undefined;
|
|
130
|
+
const [year, month, day] = ymd.split("-").map(Number);
|
|
131
|
+
if (!year || !month || !day)
|
|
132
|
+
return undefined;
|
|
133
|
+
return new Date(year, month - 1, day);
|
|
134
|
+
}
|
|
135
|
+
function ymdFromDate(date) {
|
|
136
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
137
|
+
}
|
|
138
|
+
function formatDateLabel(ymd) {
|
|
139
|
+
const date = dateFromYmd(ymd);
|
|
140
|
+
if (!date)
|
|
141
|
+
return "mm/dd/yyyy";
|
|
142
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
143
|
+
month: "short",
|
|
144
|
+
day: "numeric",
|
|
145
|
+
year: "numeric",
|
|
146
|
+
}).format(date);
|
|
147
|
+
}
|
|
148
|
+
function formatTimeLabel(time) {
|
|
149
|
+
if (!time)
|
|
150
|
+
return "--:-- --";
|
|
151
|
+
const clock = toClock(time);
|
|
152
|
+
return `${clock.hour12}:${clock.minute} ${clock.meridiem}`;
|
|
153
|
+
}
|
|
154
|
+
function formatTimeZoneShort(timeZone, instant = new Date()) {
|
|
155
|
+
const part = new Intl.DateTimeFormat("en-US", {
|
|
156
|
+
timeZone,
|
|
157
|
+
timeZoneName: "short",
|
|
158
|
+
})
|
|
159
|
+
.formatToParts(instant)
|
|
160
|
+
.find((item) => item.type === "timeZoneName");
|
|
161
|
+
return part?.value ?? timeZone;
|
|
162
|
+
}
|
|
163
|
+
function formatSummary(parts, timeZone) {
|
|
164
|
+
if (!parts.date)
|
|
165
|
+
return null;
|
|
166
|
+
const iso = toIsoInZone(parts, timeZone);
|
|
167
|
+
if (!iso)
|
|
168
|
+
return null;
|
|
169
|
+
const instant = new Date(iso);
|
|
170
|
+
const when = new Intl.DateTimeFormat(undefined, {
|
|
171
|
+
timeZone,
|
|
172
|
+
weekday: "short",
|
|
173
|
+
month: "short",
|
|
174
|
+
day: "numeric",
|
|
175
|
+
year: "numeric",
|
|
176
|
+
hour: "numeric",
|
|
177
|
+
minute: "2-digit",
|
|
178
|
+
}).format(instant);
|
|
179
|
+
return `${when} ${formatTimeZoneShort(timeZone, instant)}`;
|
|
180
|
+
}
|
|
181
|
+
/** @deprecated Prefer parts helpers; kept for callers/tests. */
|
|
182
|
+
export function toDatetimeLocalValue(value) {
|
|
183
|
+
const parts = partsFromValue(value, browserTimeZone());
|
|
184
|
+
if (!parts.date)
|
|
185
|
+
return "";
|
|
186
|
+
return `${parts.date}T${parts.time || "00:00"}`;
|
|
187
|
+
}
|
|
188
|
+
/** @deprecated Prefer parts helpers; kept for callers/tests. */
|
|
189
|
+
export function fromDatetimeLocalValue(local) {
|
|
190
|
+
const trimmed = local.trim();
|
|
191
|
+
if (!trimmed)
|
|
192
|
+
return "";
|
|
193
|
+
const ms = Date.parse(trimmed);
|
|
194
|
+
if (!Number.isFinite(ms))
|
|
195
|
+
return "";
|
|
196
|
+
return new Date(ms).toISOString();
|
|
197
|
+
}
|
|
198
|
+
const HOURS_12 = Array.from({ length: 12 }, (_, i) => String(i + 1));
|
|
199
|
+
const MINUTES = Array.from({ length: 60 }, (_, i) => pad(i));
|
|
200
|
+
function IconCalendar() {
|
|
201
|
+
return (_jsxs("svg", { className: "vertebr-datetime-icon", width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "4.5", width: "14", height: "12", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }), _jsx("path", { d: "M3 8.5h14M7 3v3M13 3v3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] }));
|
|
202
|
+
}
|
|
203
|
+
function IconClock() {
|
|
204
|
+
return (_jsxs("svg", { className: "vertebr-datetime-icon", width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: [_jsx("circle", { cx: "10", cy: "10", r: "7", stroke: "currentColor", strokeWidth: "1.5" }), _jsx("path", { d: "M10 6.5V10l2.5 1.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
205
|
+
}
|
|
206
|
+
function IconChevron({ direction }) {
|
|
207
|
+
return (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", "aria-hidden": "true", children: _jsx("path", { d: direction === "left" ? "M8.5 3.5 5 7l3.5 3.5" : "M5.5 3.5 9 7l-3.5 3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
208
|
+
}
|
|
209
|
+
export function DatetimeInput({ id, name, value, readOnly, onBlur, onChange, inputRef, }) {
|
|
210
|
+
const labelId = useId();
|
|
211
|
+
const [open, setOpen] = useState(false);
|
|
212
|
+
const [timeZone, setTimeZone] = useState(browserTimeZone);
|
|
213
|
+
const [parts, setParts] = useState(() => partsFromValue(value, browserTimeZone()));
|
|
214
|
+
const summary = useMemo(() => formatSummary(parts, timeZone), [parts, timeZone]);
|
|
215
|
+
const selected = useMemo(() => dateFromYmd(parts.date), [parts.date]);
|
|
216
|
+
const clock = useMemo(() => toClock(parts.time || "12:00"), [parts.time]);
|
|
217
|
+
const zones = useMemo(() => timeZoneOptions(timeZone), [timeZone]);
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
setParts(partsFromValue(value, timeZone));
|
|
220
|
+
// Re-parse when the stored ISO changes; timezone switches keep wall-clock
|
|
221
|
+
// and rewrite ISO via onTimeZoneChange instead.
|
|
222
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- intentional
|
|
223
|
+
}, [value]);
|
|
224
|
+
const commit = (next, zone = timeZone) => {
|
|
225
|
+
setParts(next);
|
|
226
|
+
onChange(toIsoInZone(next, zone));
|
|
227
|
+
};
|
|
228
|
+
const setClock = (next) => {
|
|
229
|
+
const time = fromClock(next);
|
|
230
|
+
if (!parts.date) {
|
|
231
|
+
commit({ date: ymdFromDate(new Date()), time });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
commit({ date: parts.date, time });
|
|
235
|
+
};
|
|
236
|
+
const onTimeZoneChange = (nextZone) => {
|
|
237
|
+
setTimeZone(nextZone);
|
|
238
|
+
if (!parts.date)
|
|
239
|
+
return;
|
|
240
|
+
// Keep the wall-clock launch time; reinterpret in the new zone.
|
|
241
|
+
onChange(toIsoInZone(parts, nextZone));
|
|
242
|
+
};
|
|
243
|
+
return (_jsxs("div", { className: "vertebr-datetime", "data-empty": parts.date ? "false" : "true", children: [_jsxs(Popover.Root, { open: readOnly ? false : open, onOpenChange: (next) => {
|
|
244
|
+
if (readOnly)
|
|
245
|
+
return;
|
|
246
|
+
setOpen(next);
|
|
247
|
+
if (!next)
|
|
248
|
+
onBlur?.();
|
|
249
|
+
}, children: [_jsxs("div", { className: "vertebr-datetime-shell", children: [_jsx(Popover.Trigger, { asChild: true, children: _jsxs("button", { id: id, ref: inputRef, type: "button", name: name, className: "vertebr-datetime-cell", disabled: readOnly, "aria-labelledby": `${labelId}-date ${labelId}-time`, children: [_jsxs("span", { className: "vertebr-datetime-cell-inner", children: [_jsx(IconCalendar, {}), _jsxs("span", { className: "vertebr-datetime-cell-copy", children: [_jsx("span", { className: "vertebr-datetime-cell-label", id: `${labelId}-date`, children: "Date" }), _jsx("span", { className: "vertebr-datetime-value", "data-empty": parts.date ? "false" : "true", children: formatDateLabel(parts.date) })] })] }), _jsx("span", { className: "vertebr-datetime-divider", "aria-hidden": "true" }), _jsxs("span", { className: "vertebr-datetime-cell-inner", children: [_jsx(IconClock, {}), _jsxs("span", { className: "vertebr-datetime-cell-copy", children: [_jsx("span", { className: "vertebr-datetime-cell-label", id: `${labelId}-time`, children: "Time" }), _jsx("span", { className: "vertebr-datetime-value", "data-empty": parts.time ? "false" : "true", children: parts.time
|
|
250
|
+
? `${formatTimeLabel(parts.time)} ${formatTimeZoneShort(timeZone)}`
|
|
251
|
+
: "--:-- --" })] })] })] }) }), parts.date && !readOnly ? (_jsx("button", { type: "button", className: "vertebr-datetime-clear", "aria-label": "Clear date and time", onClick: () => {
|
|
252
|
+
commit({ date: "", time: "" });
|
|
253
|
+
setOpen(false);
|
|
254
|
+
}, children: "Clear" })) : null] }), _jsx(Popover.Portal, { children: _jsxs(Popover.Content, { className: "vertebr-datetime-popover", align: "start", sideOffset: 8, collisionPadding: 12, onOpenAutoFocus: (event) => event.preventDefault(), children: [_jsx(DayPicker, { mode: "single", navLayout: "around", selected: selected, defaultMonth: selected ?? new Date(), onSelect: (day) => {
|
|
255
|
+
if (!day)
|
|
256
|
+
return;
|
|
257
|
+
commit({
|
|
258
|
+
date: ymdFromDate(day),
|
|
259
|
+
time: parts.time || fromClock({ hour12: "12", minute: "00", meridiem: "PM" }),
|
|
260
|
+
});
|
|
261
|
+
}, className: "vertebr-day-picker", classNames: {
|
|
262
|
+
root: "vertebr-day-picker",
|
|
263
|
+
months: "vertebr-day-picker-months",
|
|
264
|
+
month: "vertebr-day-picker-month",
|
|
265
|
+
month_caption: "vertebr-day-picker-caption",
|
|
266
|
+
month_grid: "vertebr-day-picker-grid",
|
|
267
|
+
caption_label: "vertebr-day-picker-caption-label",
|
|
268
|
+
nav: "vertebr-day-picker-nav",
|
|
269
|
+
button_previous: "vertebr-day-picker-nav-btn",
|
|
270
|
+
button_next: "vertebr-day-picker-nav-btn",
|
|
271
|
+
weekdays: "vertebr-day-picker-weekdays",
|
|
272
|
+
weekday: "vertebr-day-picker-weekday",
|
|
273
|
+
week: "vertebr-day-picker-week",
|
|
274
|
+
day: "vertebr-day-picker-day",
|
|
275
|
+
day_button: "vertebr-day-picker-day-btn",
|
|
276
|
+
selected: "vertebr-day-picker-selected",
|
|
277
|
+
today: "vertebr-day-picker-today",
|
|
278
|
+
outside: "vertebr-day-picker-outside",
|
|
279
|
+
disabled: "vertebr-day-picker-disabled",
|
|
280
|
+
hidden: "vertebr-day-picker-hidden",
|
|
281
|
+
}, components: {
|
|
282
|
+
Chevron: ({ orientation }) => (_jsx(IconChevron, { direction: orientation === "left" ? "left" : "right" })),
|
|
283
|
+
} }), _jsxs("div", { className: "vertebr-datetime-time-row", children: [_jsxs("label", { className: "vertebr-datetime-time-field", children: [_jsx("span", { children: "Hour" }), _jsx("select", { className: "vertebr-datetime-time-select", value: clock.hour12, onChange: (event) => setClock({ ...clock, hour12: event.target.value }), children: HOURS_12.map((value) => (_jsx("option", { value: value, children: value }, value))) })] }), _jsx("span", { className: "vertebr-datetime-time-sep", "aria-hidden": "true", children: ":" }), _jsxs("label", { className: "vertebr-datetime-time-field", children: [_jsx("span", { children: "Minute" }), _jsx("select", { className: "vertebr-datetime-time-select", value: clock.minute, onChange: (event) => setClock({ ...clock, minute: event.target.value }), children: MINUTES.map((value) => (_jsx("option", { value: value, children: value }, value))) })] }), _jsxs("label", { className: "vertebr-datetime-time-field vertebr-datetime-time-field-meridiem", children: [_jsx("span", { children: "AM/PM" }), _jsxs("select", { className: "vertebr-datetime-time-select", value: clock.meridiem, onChange: (event) => setClock({
|
|
284
|
+
...clock,
|
|
285
|
+
meridiem: event.target.value,
|
|
286
|
+
}), children: [_jsx("option", { value: "AM", children: "AM" }), _jsx("option", { value: "PM", children: "PM" })] })] })] }), _jsxs("label", { className: "vertebr-datetime-time-field vertebr-datetime-timezone", children: [_jsx("span", { children: "Timezone" }), _jsx("select", { className: "vertebr-datetime-time-select", value: timeZone, onChange: (event) => onTimeZoneChange(event.target.value), children: zones.map((zone) => (_jsx("option", { value: zone.id, children: zone.label }, zone.id))) })] })] }) })] }), summary ? (_jsx("p", { className: "vertebr-datetime-summary", children: summary })) : (_jsx("p", { className: "vertebr-datetime-summary vertebr-datetime-summary-empty", children: "Pick a launch date and time" }))] }));
|
|
287
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnumInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/EnumInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,wBAAgB,SAAS,CAAC,EACxB,EAAE,EACF,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,+
|
|
1
|
+
{"version":3,"file":"EnumInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/EnumInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,wBAAgB,SAAS,CAAC,EACxB,EAAE,EACF,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,+BAkDhB"}
|
|
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import * as Select from "@radix-ui/react-select";
|
|
3
3
|
import { optionLabel } from "./form/helpers/labels";
|
|
4
4
|
export function EnumInput({ id, value, field, readOnly, onChange, }) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const baseOptions = field.options?.filter(Boolean) ?? [];
|
|
6
|
+
const raw = typeof value === "string" ? value : "";
|
|
7
|
+
const options = raw && !baseOptions.includes(raw) ? [raw, ...baseOptions] : baseOptions;
|
|
8
|
+
const current = raw && options.includes(raw) ? raw : (options[0] ?? "");
|
|
9
9
|
if (options.length === 0) {
|
|
10
10
|
return (_jsx("input", { id: id, type: "text", readOnly: readOnly, value: current, disabled: true }));
|
|
11
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnumListInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/EnumListInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;
|
|
1
|
+
{"version":3,"file":"EnumListInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/EnumListInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;AAyBF,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,+BAyEpB"}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { optionLabel } from "./form/helpers/labels";
|
|
3
3
|
function asStringList(value) {
|
|
4
|
-
if (
|
|
5
|
-
return
|
|
6
|
-
|
|
4
|
+
if (Array.isArray(value)) {
|
|
5
|
+
return value.map((item) => String(item).trim()).filter(Boolean);
|
|
6
|
+
}
|
|
7
|
+
if (typeof value === "string") {
|
|
8
|
+
return value
|
|
9
|
+
.split(",")
|
|
10
|
+
.map((item) => item.trim())
|
|
11
|
+
.filter(Boolean);
|
|
12
|
+
}
|
|
13
|
+
return [];
|
|
7
14
|
}
|
|
8
15
|
function orderedRows(options, selected) {
|
|
9
16
|
const known = new Set(options);
|
|
@@ -18,6 +25,9 @@ export function EnumListInput({ id, value, field, readOnly, onChange, }) {
|
|
|
18
25
|
const options = field.options?.filter(Boolean) ?? [];
|
|
19
26
|
const selected = asStringList(value);
|
|
20
27
|
const rows = orderedRows(options, selected);
|
|
28
|
+
if (options.length === 0) {
|
|
29
|
+
return (_jsx("p", { className: "vertebr-field-files-empty", id: id, children: "No products available in this environment." }));
|
|
30
|
+
}
|
|
21
31
|
const commit = (nextRows) => {
|
|
22
32
|
onChange(nextRows.filter((row) => row.on).map((row) => row.id));
|
|
23
33
|
};
|
|
@@ -4,5 +4,9 @@ export type RevisionHistoryProps = {
|
|
|
4
4
|
configId: string;
|
|
5
5
|
onPublished?: () => void | Promise<void>;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Compact History control — opens revision list in a modal so the
|
|
9
|
+
* editor form stays the primary surface.
|
|
10
|
+
*/
|
|
7
11
|
export declare function RevisionHistory({ client, configId, onPublished, }: RevisionHistoryProps): import("react").JSX.Element;
|
|
8
12
|
//# sourceMappingURL=RevisionHistory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RevisionHistory.d.ts","sourceRoot":"","sources":["../../../src/components/config/RevisionHistory.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGnE,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C,CAAC;
|
|
1
|
+
{"version":3,"file":"RevisionHistory.d.ts","sourceRoot":"","sources":["../../../src/components/config/RevisionHistory.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGnE,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C,CAAC;AAoBF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,WAAW,GACZ,EAAE,oBAAoB,+BAuNtB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useState } from "react";
|
|
3
3
|
import { useToast } from "../../hooks/useToast";
|
|
4
4
|
function formatWhen(at) {
|
|
@@ -12,16 +12,32 @@ function formatWhen(at) {
|
|
|
12
12
|
minute: "2-digit",
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
+
function formatActor(value) {
|
|
16
|
+
if (!value)
|
|
17
|
+
return null;
|
|
18
|
+
if (value.includes("@"))
|
|
19
|
+
return value;
|
|
20
|
+
if (value.length <= 12)
|
|
21
|
+
return value;
|
|
22
|
+
return `${value.slice(0, 6)}…${value.slice(-4)}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Compact History control — opens revision list in a modal so the
|
|
26
|
+
* editor form stays the primary surface.
|
|
27
|
+
*/
|
|
15
28
|
export function RevisionHistory({ client, configId, onPublished, }) {
|
|
16
29
|
const { push } = useToast();
|
|
30
|
+
const [open, setOpen] = useState(false);
|
|
17
31
|
const [items, setItems] = useState([]);
|
|
18
|
-
const [
|
|
32
|
+
const [count, setCount] = useState(null);
|
|
33
|
+
const [loading, setLoading] = useState(false);
|
|
19
34
|
const [busyId, setBusyId] = useState(null);
|
|
20
35
|
const refresh = useCallback(async () => {
|
|
21
36
|
setLoading(true);
|
|
22
37
|
try {
|
|
23
38
|
const data = await client.listRevisions(configId, { fresh: true });
|
|
24
39
|
setItems(data.items);
|
|
40
|
+
setCount(data.items.length);
|
|
25
41
|
}
|
|
26
42
|
finally {
|
|
27
43
|
setLoading(false);
|
|
@@ -31,10 +47,30 @@ export function RevisionHistory({ client, configId, onPublished, }) {
|
|
|
31
47
|
let cancelled = false;
|
|
32
48
|
void (async () => {
|
|
33
49
|
try {
|
|
34
|
-
setLoading(true);
|
|
35
50
|
const data = await client.listRevisions(configId, { fresh: true });
|
|
36
51
|
if (!cancelled)
|
|
52
|
+
setCount(data.items.length);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* badge is optional */
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
return () => {
|
|
59
|
+
cancelled = true;
|
|
60
|
+
};
|
|
61
|
+
}, [client, configId]);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (!open)
|
|
64
|
+
return;
|
|
65
|
+
let cancelled = false;
|
|
66
|
+
void (async () => {
|
|
67
|
+
try {
|
|
68
|
+
setLoading(true);
|
|
69
|
+
const data = await client.listRevisions(configId, { fresh: true });
|
|
70
|
+
if (!cancelled) {
|
|
37
71
|
setItems(data.items);
|
|
72
|
+
setCount(data.items.length);
|
|
73
|
+
}
|
|
38
74
|
}
|
|
39
75
|
catch (err) {
|
|
40
76
|
if (!cancelled) {
|
|
@@ -49,7 +85,22 @@ export function RevisionHistory({ client, configId, onPublished, }) {
|
|
|
49
85
|
return () => {
|
|
50
86
|
cancelled = true;
|
|
51
87
|
};
|
|
52
|
-
}, [client, configId, push]);
|
|
88
|
+
}, [open, client, configId, push]);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!open)
|
|
91
|
+
return;
|
|
92
|
+
const onKeyDown = (event) => {
|
|
93
|
+
if (event.key === "Escape")
|
|
94
|
+
setOpen(false);
|
|
95
|
+
};
|
|
96
|
+
window.addEventListener("keydown", onKeyDown);
|
|
97
|
+
const previous = document.body.style.overflow;
|
|
98
|
+
document.body.style.overflow = "hidden";
|
|
99
|
+
return () => {
|
|
100
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
101
|
+
document.body.style.overflow = previous;
|
|
102
|
+
};
|
|
103
|
+
}, [open]);
|
|
53
104
|
const publish = async (revId) => {
|
|
54
105
|
setBusyId(revId);
|
|
55
106
|
try {
|
|
@@ -65,20 +116,24 @@ export function RevisionHistory({ client, configId, onPublished, }) {
|
|
|
65
116
|
setBusyId(null);
|
|
66
117
|
}
|
|
67
118
|
};
|
|
68
|
-
const
|
|
119
|
+
const useRevision = async (revId) => {
|
|
69
120
|
setBusyId(revId);
|
|
70
121
|
try {
|
|
71
122
|
await client.restoreRevision(configId, revId);
|
|
72
|
-
push("
|
|
123
|
+
push("Now editing this revision", "ok");
|
|
73
124
|
await refresh();
|
|
74
125
|
await onPublished?.();
|
|
75
126
|
}
|
|
76
127
|
catch (err) {
|
|
77
|
-
push(err instanceof Error ? err.message : "
|
|
128
|
+
push(err instanceof Error ? err.message : "Could not switch revision", "danger");
|
|
78
129
|
}
|
|
79
130
|
finally {
|
|
80
131
|
setBusyId(null);
|
|
81
132
|
}
|
|
82
133
|
};
|
|
83
|
-
return (_jsxs(
|
|
134
|
+
return (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "vertebr-revisions-trigger", "aria-haspopup": "dialog", "aria-expanded": open, onClick: () => setOpen(true), children: ["History", count != null ? (_jsx("span", { className: "vertebr-revisions-trigger-count", children: count })) : null] }), open ? (_jsx("div", { className: "vertebr-modal-backdrop", role: "presentation", onClick: () => setOpen(false), children: _jsxs("div", { className: "vertebr-modal vertebr-modal-sm vertebr-revisions-modal", role: "dialog", "aria-modal": "true", "aria-label": "Revision history", onClick: (event) => event.stopPropagation(), children: [_jsxs("header", { className: "vertebr-modal-head", children: [_jsxs("div", { className: "vertebr-modal-heading", children: [_jsx("p", { className: "vertebr-modal-eyebrow", children: "Change safety" }), _jsx("h2", { children: "Revisions" })] }), _jsxs("div", { className: "vertebr-modal-actions", children: [_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", disabled: loading || busyId != null, onClick: () => void refresh(), children: loading ? "…" : "Refresh" }), _jsx("button", { type: "button", className: "vertebr-btn", onClick: () => setOpen(false), children: "Close" })] })] }), _jsx("div", { className: "vertebr-modal-body", children: items.length === 0 && !loading ? (_jsx("p", { className: "vertebr-revisions-empty", children: "No revisions yet. Save to create a draft." })) : (_jsx("ul", { className: "vertebr-revisions-list", children: items.map((rev) => {
|
|
135
|
+
const actor = formatActor(rev.createdBy);
|
|
136
|
+
const isCurrent = Boolean(rev.active);
|
|
137
|
+
return (_jsxs("li", { className: "vertebr-revisions-item", "data-active": isCurrent ? "true" : undefined, children: [_jsxs("div", { className: "vertebr-revisions-meta", children: [_jsx("strong", { children: rev.label?.trim() || rev.id }), _jsx("span", { "data-status": rev.status, children: rev.status }), isCurrent ? (_jsx("span", { "data-status": "current", children: "Current" })) : null, _jsxs("span", { className: "vertebr-revisions-when", children: [formatWhen(rev.createdAt), actor ? ` · ${actor}` : ""] })] }), _jsxs("div", { className: "vertebr-revisions-actions", children: [rev.status !== "published" ? (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", disabled: busyId != null, onClick: () => void publish(rev.id), children: busyId === rev.id ? "…" : "Publish" })) : null, isCurrent ? null : (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", disabled: busyId != null, onClick: () => void useRevision(rev.id), children: "Use" }))] })] }, rev.id));
|
|
138
|
+
}) })) })] }) })) : null] }));
|
|
84
139
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigField.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/ConfigField.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIjE,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfigField.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/ConfigField.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIjE,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAuBtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEvF,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAC5C,mBAAmB,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,EACN,OAAO,EACP,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,EACf,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,WAAW,EACX,MAAM,GACP,EAAE,gBAAgB,+BAkUlB"}
|
|
@@ -9,6 +9,7 @@ import { isCentsField, isPriceField } from "../../../lib/price";
|
|
|
9
9
|
import { FontPickerField } from "../../fonts/FontPickerField";
|
|
10
10
|
import { ImageUploadControl } from "../../resources/ImageUploadControl";
|
|
11
11
|
import { DescriptionInput } from "../DescriptionInput";
|
|
12
|
+
import { DatetimeInput } from "../DatetimeInput";
|
|
12
13
|
import { EnumInput } from "../EnumInput";
|
|
13
14
|
import { EnumListInput } from "../EnumListInput";
|
|
14
15
|
import { PriceInput } from "../PriceInput";
|
|
@@ -39,7 +40,7 @@ export function ConfigField({ fieldKey, field, groupLabel, variant, schema, watc
|
|
|
39
40
|
: "", onBlur: controllerField.onBlur, onChange: (event) => {
|
|
40
41
|
const next = event.target.value;
|
|
41
42
|
controllerField.onChange(next === "" ? undefined : Number(next));
|
|
42
|
-
}, name: controllerField.name, ref: controllerField.ref })) })) : field.type === "enum" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(EnumInput, { id: fieldKey, value: controllerField.value, field: field, readOnly: field.readOnly, onChange: controllerField.onChange })) })) : field.type === "enum[]" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(EnumListInput, { id: fieldKey, value: controllerField.value, field: field, readOnly: field.readOnly, onChange: controllerField.onChange })) })) : field.type === "font" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(FontPickerField, { id: fieldKey, value: controllerField.value, label: field.label, description: field.description, readOnly: field.readOnly, fonts: fonts ?? [], loading: fontsLoading, onChange: controllerField.onChange, onRefreshFonts: onRefreshFonts })) })) : field.type === "reference" && client ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(ReferenceInput, { id: fieldKey, value: controllerField.value, field: field, client: client, readOnly: field.readOnly, onChange: controllerField.onChange })) })) : isMultilineField(fieldKey, field) ? (_jsx("textarea", { id: fieldKey, rows: 5, readOnly: field.readOnly, ...form.register(fieldKey) })) : (_jsx("input", { id: fieldKey, type: "text", readOnly: field.readOnly, ...form.register(fieldKey) })), !hideUpload && uploads?.[fieldKey] && onUpload && !field.readOnly ? (_jsx(ImageUploadControl, { meta: uploads[fieldKey], multiple: field.type === "file[]", onUpload: async (files) => {
|
|
43
|
+
}, name: controllerField.name, ref: controllerField.ref })) })) : field.type === "datetime" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(DatetimeInput, { id: fieldKey, name: controllerField.name, inputRef: controllerField.ref, value: controllerField.value, readOnly: field.readOnly, onBlur: controllerField.onBlur, onChange: controllerField.onChange })) })) : field.type === "enum" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(EnumInput, { id: fieldKey, value: controllerField.value, field: field, readOnly: field.readOnly, onChange: controllerField.onChange })) })) : field.type === "enum[]" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(EnumListInput, { id: fieldKey, value: controllerField.value, field: field, readOnly: field.readOnly, onChange: controllerField.onChange })) })) : field.type === "font" ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(FontPickerField, { id: fieldKey, value: controllerField.value, label: field.label, description: field.description, readOnly: field.readOnly, fonts: fonts ?? [], loading: fontsLoading, onChange: controllerField.onChange, onRefreshFonts: onRefreshFonts })) })) : field.type === "reference" && client ? (_jsx(Controller, { control: form.control, name: fieldKey, render: ({ field: controllerField }) => (_jsx(ReferenceInput, { id: fieldKey, value: controllerField.value, field: field, client: client, readOnly: field.readOnly, onChange: controllerField.onChange })) })) : isMultilineField(fieldKey, field) ? (_jsx("textarea", { id: fieldKey, rows: 5, readOnly: field.readOnly, ...form.register(fieldKey) })) : (_jsx("input", { id: fieldKey, type: "text", readOnly: field.readOnly, ...form.register(fieldKey) })), !hideUpload && uploads?.[fieldKey] && onUpload && !field.readOnly ? (_jsx(ImageUploadControl, { meta: uploads[fieldKey], multiple: field.type === "file[]", onUpload: async (files) => {
|
|
43
44
|
const uploaded = await onUpload(fieldKey, files);
|
|
44
45
|
const urls = uploaded
|
|
45
46
|
.map((item) => item.url)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ConfigFormProps } from "./types";
|
|
2
2
|
export type { ConfigFormProps, ConfigFormVariant } from "./types";
|
|
3
|
-
export declare function ConfigForm({ schema, value, onSave, submitLabel, variant, uploads, onUpload, galleryUpload, onListGallery, onUploadGallery, fonts, fontsLoading, onListFonts, onRefreshFonts, onChange, hideActions, client, canWrite, }: ConfigFormProps): import("react").JSX.Element;
|
|
3
|
+
export declare function ConfigForm({ schema, value, onSave, submitLabel, variant, uploads, onUpload, galleryUpload, onListGallery, onUploadGallery, fonts, fontsLoading, onListFonts, onRefreshFonts, onChange, hideActions, client, canWrite, revisionsEnabled, onPublish, canPublish, }: ConfigFormProps): import("react").JSX.Element;
|
|
4
4
|
//# sourceMappingURL=ConfigForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigForm.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/ConfigForm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAElE,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,MAAM,EACN,WAAW,EACX,OAAkB,EAClB,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,EACf,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACd,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAe,
|
|
1
|
+
{"version":3,"file":"ConfigForm.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/ConfigForm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAElE,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,MAAM,EACN,WAAW,EACX,OAAkB,EAClB,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,EACf,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACd,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAe,EACf,gBAAwB,EACxB,SAAS,EACT,UAAkB,GACnB,EAAE,eAAe,+BA2LjB"}
|