@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.
Files changed (39) hide show
  1. package/dist/components/admin/AddonEditor.d.ts.map +1 -1
  2. package/dist/components/admin/AddonEditor.js +10 -8
  3. package/dist/components/admin/AdminContent.d.ts.map +1 -1
  4. package/dist/components/admin/AdminContent.js +55 -7
  5. package/dist/components/admin/AdminSaveBar.d.ts.map +1 -1
  6. package/dist/components/admin/AdminSaveBar.js +6 -1
  7. package/dist/components/admin/AdminSyncPage.d.ts.map +1 -1
  8. package/dist/components/admin/AdminSyncPage.js +50 -6
  9. package/dist/components/admin/PagePreviewPane.d.ts +3 -1
  10. package/dist/components/admin/PagePreviewPane.d.ts.map +1 -1
  11. package/dist/components/admin/PagePreviewPane.js +41 -9
  12. package/dist/components/admin/SyncPreviewFrame.d.ts +22 -0
  13. package/dist/components/admin/SyncPreviewFrame.d.ts.map +1 -0
  14. package/dist/components/admin/SyncPreviewFrame.js +135 -0
  15. package/dist/components/config/DatetimeInput.d.ts +15 -0
  16. package/dist/components/config/DatetimeInput.d.ts.map +1 -0
  17. package/dist/components/config/DatetimeInput.js +287 -0
  18. package/dist/components/config/EnumInput.d.ts.map +1 -1
  19. package/dist/components/config/EnumInput.js +4 -4
  20. package/dist/components/config/EnumListInput.d.ts.map +1 -1
  21. package/dist/components/config/EnumListInput.js +13 -3
  22. package/dist/components/config/RevisionHistory.d.ts +4 -0
  23. package/dist/components/config/RevisionHistory.d.ts.map +1 -1
  24. package/dist/components/config/RevisionHistory.js +63 -8
  25. package/dist/components/config/form/ConfigField.d.ts.map +1 -1
  26. package/dist/components/config/form/ConfigField.js +2 -1
  27. package/dist/components/config/form/ConfigForm.d.ts +1 -1
  28. package/dist/components/config/form/ConfigForm.d.ts.map +1 -1
  29. package/dist/components/config/form/ConfigForm.js +54 -9
  30. package/dist/components/config/form/types.d.ts +9 -0
  31. package/dist/components/config/form/types.d.ts.map +1 -1
  32. package/dist/hooks/useSaveBar.d.ts +6 -0
  33. package/dist/hooks/useSaveBar.d.ts.map +1 -1
  34. package/dist/styles/form.css +452 -17
  35. package/dist/styles/page-preview.css +84 -0
  36. package/dist/styles/select.css +23 -0
  37. package/dist/styles/sync.css +388 -4
  38. package/dist/themes/light.css +27 -0
  39. 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,+BAmDhB"}
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 options = field.options?.filter(Boolean) ?? [];
6
- const current = typeof value === "string" && options.includes(value)
7
- ? value
8
- : (options[0] ?? "");
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;AAiBF,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,+BAiEpB"}
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 (!Array.isArray(value))
5
- return [];
6
- return value.map((item) => String(item).trim()).filter(Boolean);
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;AAaF,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,WAAW,GACZ,EAAE,oBAAoB,+BAmHtB"}
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 [loading, setLoading] = useState(true);
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 restore = async (revId) => {
119
+ const useRevision = async (revId) => {
69
120
  setBusyId(revId);
70
121
  try {
71
122
  await client.restoreRevision(configId, revId);
72
- push("Draft restored from revision", "ok");
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 : "Restore failed", "danger");
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("div", { className: "vertebr-revisions", children: [_jsxs("div", { className: "vertebr-panel-head", children: [_jsx("h3", { children: "Revisions" }), _jsx("span", { className: "vertebr-count", children: loading ? "…" : `${items.length}` })] }), items.length === 0 && !loading ? (_jsx("p", { className: "vertebr-revisions-empty", children: "No revisions yet." })) : (_jsx("ul", { className: "vertebr-revisions-list", children: items.map((rev) => (_jsxs("li", { className: "vertebr-revisions-item", 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 }), _jsxs("span", { className: "vertebr-revisions-when", children: [formatWhen(rev.createdAt), rev.createdBy ? ` · ${rev.createdBy}` : ""] })] }), _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, _jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", disabled: busyId != null, onClick: () => void restore(rev.id), children: "Restore" })] })] }, rev.id))) }))] }));
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;AAsBtF,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,+BAkTlB"}
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,GAChB,EAAE,eAAe,+BA2IjB"}
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"}