@mitcsutt/kiln-ui 0.6.0 → 0.7.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/actions/CopyButton/CopyButton.d.ts +58 -0
- package/dist/components/actions/CopyButton/CopyButton.js +63 -0
- package/dist/components/actions/CopyButton/CopyButton.js.map +1 -0
- package/dist/components/actions/CopyButton/CopyButton.module.js +9 -0
- package/dist/components/actions/CopyButton/CopyButton.module.js.map +1 -0
- package/dist/components/actions/CopyButton/index.d.ts +4 -0
- package/dist/components/actions/CopyButton/useClipboard.d.ts +35 -0
- package/dist/components/actions/CopyButton/useClipboard.js +62 -0
- package/dist/components/actions/CopyButton/useClipboard.js.map +1 -0
- package/dist/components/actions/ToggleChip/ToggleChip.d.ts +6 -0
- package/dist/components/actions/ToggleChip/ToggleChip.js +26 -24
- package/dist/components/actions/ToggleChip/ToggleChip.js.map +1 -1
- package/dist/components/display/Badge/Badge.d.ts +6 -0
- package/dist/components/display/Badge/Badge.js +16 -15
- package/dist/components/display/Badge/Badge.js.map +1 -1
- package/dist/components/display/CodeBlock/CodeBlock.js +45 -58
- package/dist/components/display/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/components/display/Swatch/Swatch.d.ts +52 -0
- package/dist/components/display/Swatch/Swatch.js +27 -0
- package/dist/components/display/Swatch/Swatch.js.map +1 -0
- package/dist/components/display/Swatch/Swatch.module.js +6 -0
- package/dist/components/display/Swatch/Swatch.module.js.map +1 -0
- package/dist/components/display/Swatch/index.d.ts +2 -0
- package/dist/components/display/Tag/Tag.d.ts +7 -0
- package/dist/components/display/Tag/Tag.js +31 -26
- package/dist/components/display/Tag/Tag.js.map +1 -1
- package/dist/components/feedback/Indicator/Indicator.d.ts +74 -0
- package/dist/components/feedback/Indicator/Indicator.js +50 -0
- package/dist/components/feedback/Indicator/Indicator.js.map +1 -0
- package/dist/components/feedback/Indicator/Indicator.module.js +12 -0
- package/dist/components/feedback/Indicator/Indicator.module.js.map +1 -0
- package/dist/components/feedback/Indicator/index.d.ts +2 -0
- package/dist/components/feedback/Toaster/Toaster.d.ts +71 -0
- package/dist/components/feedback/Toaster/Toaster.js +121 -0
- package/dist/components/feedback/Toaster/Toaster.js.map +1 -0
- package/dist/components/feedback/Toaster/Toaster.module.js +20 -0
- package/dist/components/feedback/Toaster/Toaster.module.js.map +1 -0
- package/dist/components/feedback/Toaster/index.d.ts +4 -0
- package/dist/components/feedback/Toaster/toast.d.ts +96 -0
- package/dist/components/feedback/Toaster/toast.js +131 -0
- package/dist/components/feedback/Toaster/toast.js.map +1 -0
- package/dist/components/inputs/Calendar/Calendar.d.ts +87 -0
- package/dist/components/inputs/Calendar/Calendar.js +217 -0
- package/dist/components/inputs/Calendar/Calendar.js.map +1 -0
- package/dist/components/inputs/Calendar/Calendar.module.js +18 -0
- package/dist/components/inputs/Calendar/Calendar.module.js.map +1 -0
- package/dist/components/inputs/Calendar/index.d.ts +2 -0
- package/dist/components/inputs/Combobox/Combobox.js +36 -44
- package/dist/components/inputs/Combobox/Combobox.js.map +1 -1
- package/dist/components/inputs/DateField/DateField.d.ts +17 -0
- package/dist/components/inputs/DateField/DateField.js +26 -0
- package/dist/components/inputs/DateField/DateField.js.map +1 -0
- package/dist/components/inputs/DateField/index.d.ts +2 -0
- package/dist/components/inputs/DateInput/DateInput.d.ts +75 -0
- package/dist/components/inputs/DateInput/DateInput.js +139 -0
- package/dist/components/inputs/DateInput/DateInput.js.map +1 -0
- package/dist/components/inputs/DateInput/index.d.ts +3 -0
- package/dist/components/inputs/DateRangeField/DateRangeField.d.ts +18 -3
- package/dist/components/inputs/DateRangeField/DateRangeField.js.map +1 -1
- package/dist/components/inputs/DateRangeField/DateRangeField.module.js +8 -3
- package/dist/components/inputs/DateRangeField/DateRangeField.module.js.map +1 -1
- package/dist/components/inputs/DateRangeField/DateRangePickerField.d.ts +48 -0
- package/dist/components/inputs/DateRangeField/DateRangePickerField.js +246 -0
- package/dist/components/inputs/DateRangeField/DateRangePickerField.js.map +1 -0
- package/dist/components/inputs/DateRangeField/index.d.ts +2 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.d.ts +17 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.js +26 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.js.map +1 -0
- package/dist/components/inputs/DateTimeField/index.d.ts +2 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.d.ts +83 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.js +216 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.js.map +1 -0
- package/dist/components/inputs/DateTimeInput/index.d.ts +2 -0
- package/dist/components/inputs/JsonField/JsonField.d.ts +23 -0
- package/dist/components/inputs/JsonField/JsonField.js +33 -0
- package/dist/components/inputs/JsonField/JsonField.js.map +1 -0
- package/dist/components/inputs/JsonField/index.d.ts +2 -0
- package/dist/components/inputs/JsonInput/JsonInput.d.ts +119 -0
- package/dist/components/inputs/JsonInput/JsonInput.js +282 -0
- package/dist/components/inputs/JsonInput/JsonInput.js.map +1 -0
- package/dist/components/inputs/JsonInput/JsonInput.module.js +16 -0
- package/dist/components/inputs/JsonInput/JsonInput.module.js.map +1 -0
- package/dist/components/inputs/JsonInput/index.d.ts +4 -0
- package/dist/components/inputs/JsonInput/json.d.ts +59 -0
- package/dist/components/inputs/JsonInput/json.js +231 -0
- package/dist/components/inputs/JsonInput/json.js.map +1 -0
- package/dist/components/inputs/TagsInput/TagsInput.js +5 -5
- package/dist/components/inputs/TimeField/TimeField.d.ts +17 -0
- package/dist/components/inputs/TimeField/TimeField.js +26 -0
- package/dist/components/inputs/TimeField/TimeField.js.map +1 -0
- package/dist/components/inputs/TimeField/index.d.ts +2 -0
- package/dist/components/inputs/TimeInput/TimeInput.d.ts +54 -0
- package/dist/components/inputs/TimeInput/TimeInput.js +107 -0
- package/dist/components/inputs/TimeInput/TimeInput.js.map +1 -0
- package/dist/components/inputs/TimeInput/index.d.ts +2 -0
- package/dist/components/inputs/internal/DateSegments.d.ts +80 -0
- package/dist/components/inputs/internal/DateSegments.js +345 -0
- package/dist/components/inputs/internal/DateSegments.js.map +1 -0
- package/dist/components/inputs/internal/dates.d.ts +101 -0
- package/dist/components/inputs/internal/dates.js +262 -0
- package/dist/components/inputs/internal/dates.js.map +1 -0
- package/dist/components/inputs/internal/filterOptions.d.ts +22 -1
- package/dist/components/inputs/internal/filterOptions.js +32 -1
- package/dist/components/inputs/internal/filterOptions.js.map +1 -1
- package/dist/components/inputs/internal/picker.d.ts +31 -0
- package/dist/components/inputs/internal/picker.js +29 -0
- package/dist/components/inputs/internal/picker.js.map +1 -0
- package/dist/components/inputs/internal/picker.module.js +15 -0
- package/dist/components/inputs/internal/picker.module.js.map +1 -0
- package/dist/components/inputs/internal/segments.module.js +10 -0
- package/dist/components/inputs/internal/segments.module.js.map +1 -0
- package/dist/components/layout/Collapse/Collapse.d.ts +39 -0
- package/dist/components/layout/Collapse/Collapse.js +24 -0
- package/dist/components/layout/Collapse/Collapse.js.map +1 -0
- package/dist/components/layout/Collapse/Collapse.module.js +6 -0
- package/dist/components/layout/Collapse/Collapse.module.js.map +1 -0
- package/dist/components/layout/Collapse/index.d.ts +2 -0
- package/dist/components/layout/Collapse/useHeightMotion.d.ts +16 -0
- package/dist/components/layout/Collapse/useHeightMotion.js +60 -0
- package/dist/components/layout/Collapse/useHeightMotion.js.map +1 -0
- package/dist/components/layout/ShowMore/ShowMore.d.ts +59 -0
- package/dist/components/layout/ShowMore/ShowMore.js +114 -0
- package/dist/components/layout/ShowMore/ShowMore.js.map +1 -0
- package/dist/components/layout/ShowMore/ShowMore.module.js +12 -0
- package/dist/components/layout/ShowMore/ShowMore.module.js.map +1 -0
- package/dist/components/layout/ShowMore/index.d.ts +2 -0
- package/dist/components/layout/Transition/Transition.d.ts +63 -0
- package/dist/components/layout/Transition/Transition.js +63 -0
- package/dist/components/layout/Transition/Transition.js.map +1 -0
- package/dist/components/layout/Transition/Transition.module.js +17 -0
- package/dist/components/layout/Transition/Transition.module.js.map +1 -0
- package/dist/components/layout/Transition/index.d.ts +2 -0
- package/dist/components/navigation/Collapsible/Collapsible.d.ts +49 -0
- package/dist/components/navigation/Collapsible/Collapsible.js +83 -0
- package/dist/components/navigation/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/navigation/Collapsible/Collapsible.module.js +11 -0
- package/dist/components/navigation/Collapsible/Collapsible.module.js.map +1 -0
- package/dist/components/navigation/Collapsible/index.d.ts +2 -0
- package/dist/components/navigation/NavLinks/NavLinks.d.ts +32 -4
- package/dist/components/navigation/NavLinks/NavLinks.js +69 -39
- package/dist/components/navigation/NavLinks/NavLinks.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinks.module.js +13 -3
- package/dist/components/navigation/NavLinks/NavLinks.module.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinksGroup.d.ts +49 -0
- package/dist/components/navigation/NavLinks/NavLinksGroup.js +185 -0
- package/dist/components/navigation/NavLinks/NavLinksGroup.js.map +1 -0
- package/dist/components/navigation/NavLinks/context.d.ts +28 -0
- package/dist/components/navigation/NavLinks/context.js +13 -0
- package/dist/components/navigation/NavLinks/context.js.map +1 -0
- package/dist/components/navigation/NavLinks/index.d.ts +2 -0
- package/dist/components/navigation/NavLinks/treeKeys.d.ts +8 -0
- package/dist/components/navigation/NavLinks/treeKeys.js +57 -0
- package/dist/components/navigation/NavLinks/treeKeys.js.map +1 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.d.ts +120 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.js +386 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.js.map +1 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.module.js +31 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.module.js.map +1 -0
- package/dist/components/overlays/CommandPalette/index.d.ts +2 -0
- package/dist/components/overlays/CommandPalette/shortcut.d.ts +28 -0
- package/dist/components/overlays/CommandPalette/shortcut.js +104 -0
- package/dist/components/overlays/CommandPalette/shortcut.js.map +1 -0
- package/dist/index.d.ts +40 -4
- package/dist/index.js +123 -100
- package/dist/styles.css +1 -1
- package/dist/themes/fiesta.css +1 -1
- package/dist/themes/flightdeck.css +1 -1
- package/dist/themes/ledger.css +1 -1
- package/dist/themes/monograph.css +1 -1
- package/dist/themes/riso.css +1 -1
- package/package.json +1 -1
- package/skills/custom-theme/SKILL.md +32 -0
- package/skills/custom-theme/references/colour.md +20 -0
- package/skills/custom-theme/references/motion.md +9 -0
- package/skills/custom-theme/references/tokens.md +35 -0
- package/skills/design-rules/SKILL.md +5 -2
- package/skills/setup-and-theming/SKILL.md +1 -1
- package/skills/setup-and-theming/references/paper.md +1 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { cx as e } from "../../../utils/cx.js";
|
|
2
|
+
import { CalendarIcon as t, CloseIcon as n } from "../../../icons/icons.js";
|
|
3
|
+
import { useMergedRefs as r } from "../internal/refs.js";
|
|
4
|
+
import { FieldContext as i, markFieldAware as a, useResolvedField as o } from "../internal/FieldContext.js";
|
|
5
|
+
import s from "../internal/control.module.js";
|
|
6
|
+
import { Popover as c } from "../../overlays/Popover/Popover.js";
|
|
7
|
+
import { DEFAULT_LOCALE as ee, dateOf as l, dayPeriodNames as te, defaultHourCycle as ne, formatDate as u, formatDateTime as re, formatTime as ie, parseDate as d, parseDateTime as f, parseTime as ae, timeZoneName as oe, todayIn as se, zonedParts as ce, zonedToInstant as p } from "../internal/dates.js";
|
|
8
|
+
import { Calendar as le } from "../Calendar/Calendar.js";
|
|
9
|
+
import { useControllableState as m } from "../Combobox/useControllableState.js";
|
|
10
|
+
import { DateSegments as ue, draftDate as h, draftFromParts as g, draftTime as _, segmentPattern as de, useSegmentDraft as fe } from "../internal/DateSegments.js";
|
|
11
|
+
import { DEFAULT_DATE_TIME_LABELS as pe, focusSegment as me, handleBoxPointerDown as he, isLeaving as v } from "../internal/picker.js";
|
|
12
|
+
import y from "../internal/picker.module.js";
|
|
13
|
+
import { TimeInput as ge } from "../TimeInput/TimeInput.js";
|
|
14
|
+
import { forwardRef as b, useId as _e, useMemo as x, useRef as S } from "react";
|
|
15
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
16
|
+
//#region src/components/inputs/DateTimeInput/DateTimeInput.tsx
|
|
17
|
+
function T(e, t) {
|
|
18
|
+
let n = f(e ?? "", t);
|
|
19
|
+
return n ? t ? p(n.date, n.time, t) : Date.UTC(n.date.year, n.date.month - 1, n.date.day, n.time.hour, n.time.minute, n.time.second) : null;
|
|
20
|
+
}
|
|
21
|
+
function E(e, { min: t, max: n, isDateDisabled: r, timeZone: i }) {
|
|
22
|
+
let a = T(e, i);
|
|
23
|
+
if (a === null) return !1;
|
|
24
|
+
let o = T(t, i), s = T(n, i), c = l(e, i);
|
|
25
|
+
return o !== null && a < o || s !== null && a > s || c !== null && (r?.(u(c)) ?? !1);
|
|
26
|
+
}
|
|
27
|
+
var D = a(b(function({ value: a, defaultValue: p, onValueChange: b, timeZone: D, granularity: O = "minute", hourCycle: ve, min: k, max: A, isDateDisabled: j, firstDayOfWeek: ye, locale: M = ee, calendar: N = !0, clearable: P = !1, name: F, form: be, size: xe = "md", id: Se, disabled: Ce, readOnly: we, required: Te, invalid: Ee, open: De, defaultOpen: Oe, onOpenChange: ke, onBlur: Ae, onFocus: je, onKeyDown: Me, labels: Ne, className: Pe, "aria-describedby": Fe, "aria-invalid": Ie, "aria-labelledby": Le, ...Re }, ze) {
|
|
28
|
+
let I = {
|
|
29
|
+
...pe,
|
|
30
|
+
...Ne
|
|
31
|
+
}, L = o({
|
|
32
|
+
id: Se,
|
|
33
|
+
describedBy: Fe,
|
|
34
|
+
invalid: Ee,
|
|
35
|
+
ariaInvalid: Ie,
|
|
36
|
+
disabled: Ce,
|
|
37
|
+
readOnly: we,
|
|
38
|
+
required: Te
|
|
39
|
+
}), Be = _e(), R = S(null), z = S(null), Ve = r(ze, R), B = ve ?? ne(M), He = x(() => de("datetime", M, O, B), [
|
|
40
|
+
M,
|
|
41
|
+
O,
|
|
42
|
+
B
|
|
43
|
+
]), Ue = x(() => te(M), [M]), [V, We] = m(a, p ?? "", b), [Ge, H] = m(De, Oe ?? !1, ke), Ke = (e) => {
|
|
44
|
+
let t = f(e, D);
|
|
45
|
+
return t ? g(t.date, t.time) : {};
|
|
46
|
+
}, qe = (e) => re(e, O, D), [U, W] = fe(V, Ke, (e) => {
|
|
47
|
+
let t = h(e), n = _(e);
|
|
48
|
+
return !t || !n || O === "second" && e.second === void 0 ? "" : qe({
|
|
49
|
+
date: t,
|
|
50
|
+
time: O === "minute" ? {
|
|
51
|
+
...n,
|
|
52
|
+
second: 0
|
|
53
|
+
} : n
|
|
54
|
+
});
|
|
55
|
+
}, We), G = !L.disabled && !L.readOnly, K = L.invalid || E(V, {
|
|
56
|
+
min: k,
|
|
57
|
+
max: A,
|
|
58
|
+
isDateDisabled: j,
|
|
59
|
+
timeZone: D
|
|
60
|
+
}), q = Object.keys(U).length > 0, J = D ? ce(Date.now(), D) : {
|
|
61
|
+
date: se(),
|
|
62
|
+
time: {
|
|
63
|
+
hour: (/* @__PURE__ */ new Date()).getHours(),
|
|
64
|
+
minute: 0,
|
|
65
|
+
second: 0
|
|
66
|
+
}
|
|
67
|
+
}, Je = g(J.date, J.time), Ye = T(V, D), Y = D ? oe(M, D, Ye ?? Date.now()) : null, X = k ? l(k, D) : null, Z = A ? l(A, D) : null, Q = `${Be}-time`, Xe = (e) => {
|
|
68
|
+
Me?.(e), !e.defaultPrevented && N && G && e.altKey && e.key === "ArrowDown" && (e.preventDefault(), H(!0));
|
|
69
|
+
}, Ze = (() => {
|
|
70
|
+
let e = h(U);
|
|
71
|
+
return e ? u(e) : "";
|
|
72
|
+
})(), Qe = (() => {
|
|
73
|
+
let e = _(U);
|
|
74
|
+
return e ? ie(e, O) : "";
|
|
75
|
+
})(), $ = /* @__PURE__ */ w("div", {
|
|
76
|
+
ref: Ve,
|
|
77
|
+
role: "group",
|
|
78
|
+
className: e(s.box, y.root, Pe),
|
|
79
|
+
"data-size": xe,
|
|
80
|
+
"data-invalid": K || void 0,
|
|
81
|
+
"data-disabled": L.disabled || void 0,
|
|
82
|
+
"data-readonly": L.readOnly || void 0,
|
|
83
|
+
"aria-labelledby": Le ?? L.labelId,
|
|
84
|
+
"aria-describedby": L.describedBy,
|
|
85
|
+
"aria-busy": L.busy || void 0,
|
|
86
|
+
...Re,
|
|
87
|
+
onPointerDown: he,
|
|
88
|
+
onKeyDown: Xe,
|
|
89
|
+
onFocus: (e) => {
|
|
90
|
+
v(e, R, z) && je?.(e);
|
|
91
|
+
},
|
|
92
|
+
onBlur: (e) => {
|
|
93
|
+
v(e, R, z) && Ae?.(e);
|
|
94
|
+
},
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ C(ue, {
|
|
97
|
+
pattern: He,
|
|
98
|
+
draft: U,
|
|
99
|
+
onDraftChange: W,
|
|
100
|
+
hourCycle: B,
|
|
101
|
+
periodNames: Ue,
|
|
102
|
+
labels: I,
|
|
103
|
+
reference: Je,
|
|
104
|
+
firstId: L.id,
|
|
105
|
+
disabled: L.disabled,
|
|
106
|
+
readOnly: L.readOnly,
|
|
107
|
+
invalid: K,
|
|
108
|
+
required: L.required
|
|
109
|
+
}),
|
|
110
|
+
Y || P && G && q || N ? /* @__PURE__ */ w("span", {
|
|
111
|
+
className: y.trailing,
|
|
112
|
+
children: [
|
|
113
|
+
Y ? /* @__PURE__ */ C("span", {
|
|
114
|
+
className: y.zone,
|
|
115
|
+
children: Y
|
|
116
|
+
}) : null,
|
|
117
|
+
P && G && q ? /* @__PURE__ */ C("button", {
|
|
118
|
+
type: "button",
|
|
119
|
+
className: y.button,
|
|
120
|
+
"aria-label": I.clear,
|
|
121
|
+
onClick: () => {
|
|
122
|
+
W({}), me(R.current, "first");
|
|
123
|
+
},
|
|
124
|
+
children: /* @__PURE__ */ C(n, {})
|
|
125
|
+
}) : null,
|
|
126
|
+
N ? /* @__PURE__ */ C(c.Trigger, {
|
|
127
|
+
asChild: !0,
|
|
128
|
+
children: /* @__PURE__ */ C("button", {
|
|
129
|
+
type: "button",
|
|
130
|
+
className: y.button,
|
|
131
|
+
"aria-label": I.openCalendar,
|
|
132
|
+
disabled: !G,
|
|
133
|
+
children: /* @__PURE__ */ C(t, {})
|
|
134
|
+
})
|
|
135
|
+
}) : null
|
|
136
|
+
]
|
|
137
|
+
}) : null,
|
|
138
|
+
F === void 0 ? null : /* @__PURE__ */ C("input", {
|
|
139
|
+
type: "hidden",
|
|
140
|
+
name: F,
|
|
141
|
+
form: be,
|
|
142
|
+
value: V,
|
|
143
|
+
disabled: L.disabled || void 0
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
});
|
|
147
|
+
return N ? /* @__PURE__ */ w(c, {
|
|
148
|
+
open: Ge && G,
|
|
149
|
+
onOpenChange: H,
|
|
150
|
+
children: [/* @__PURE__ */ C(c.Anchor, {
|
|
151
|
+
asChild: !0,
|
|
152
|
+
children: $
|
|
153
|
+
}), /* @__PURE__ */ C(c.Content, {
|
|
154
|
+
ref: z,
|
|
155
|
+
className: y.popover,
|
|
156
|
+
align: "start",
|
|
157
|
+
"aria-label": I.openCalendar,
|
|
158
|
+
onOpenAutoFocus: (e) => {
|
|
159
|
+
e.preventDefault();
|
|
160
|
+
},
|
|
161
|
+
children: /* @__PURE__ */ C(i.Provider, {
|
|
162
|
+
value: null,
|
|
163
|
+
children: /* @__PURE__ */ w("div", {
|
|
164
|
+
className: y.panel,
|
|
165
|
+
children: [/* @__PURE__ */ C(le, {
|
|
166
|
+
autoFocus: !0,
|
|
167
|
+
value: d(Ze) ? Ze : "",
|
|
168
|
+
min: X ? u(X) : void 0,
|
|
169
|
+
max: Z ? u(Z) : void 0,
|
|
170
|
+
isDateDisabled: j,
|
|
171
|
+
firstDayOfWeek: ye,
|
|
172
|
+
locale: M,
|
|
173
|
+
timeZone: D,
|
|
174
|
+
labels: I,
|
|
175
|
+
onValueChange: (e) => {
|
|
176
|
+
let t = d(e);
|
|
177
|
+
t && W({
|
|
178
|
+
hour: 0,
|
|
179
|
+
minute: 0,
|
|
180
|
+
second: 0,
|
|
181
|
+
...U,
|
|
182
|
+
...t
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}), /* @__PURE__ */ w("div", {
|
|
186
|
+
className: y.timeRow,
|
|
187
|
+
children: [/* @__PURE__ */ C("span", {
|
|
188
|
+
id: Q,
|
|
189
|
+
className: y.timeLabel,
|
|
190
|
+
children: I.time
|
|
191
|
+
}), /* @__PURE__ */ C(ge, {
|
|
192
|
+
"aria-labelledby": Q,
|
|
193
|
+
value: Qe,
|
|
194
|
+
granularity: O,
|
|
195
|
+
hourCycle: B,
|
|
196
|
+
locale: M,
|
|
197
|
+
size: "sm",
|
|
198
|
+
labels: I,
|
|
199
|
+
onValueChange: (e) => {
|
|
200
|
+
let t = ae(e);
|
|
201
|
+
t && W({
|
|
202
|
+
...U,
|
|
203
|
+
...t
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
})]
|
|
207
|
+
})]
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
})]
|
|
211
|
+
}) : $;
|
|
212
|
+
}));
|
|
213
|
+
//#endregion
|
|
214
|
+
export { D as DateTimeInput, E as isDateTimeOutOfRange };
|
|
215
|
+
|
|
216
|
+
//# sourceMappingURL=DateTimeInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateTimeInput.js","names":["control","picker","control_module_default","picker_module_default","instantOf","parts","parseDateTime","text","timeZone","zonedToInstant","isDateTimeOutOfRange","at","value","lower","min","upper","max","date","dateOf","isDateDisabled","formatDate","DateTimeInput","markFieldAware","forwardRef","valueProp","hourCycleProp","DEFAULT_LOCALE","idProp","disabledProp","readOnlyProp","requiredProp","invalidProp","openProp","labelsProp","describedByProp","ariaInvalid","ariaLabelledBy","rest","labels","DEFAULT_DATE_TIME_LABELS","field","useResolvedField","autoId","useId","rootRef","useRef","panelRef","composedRef","useMergedRefs","ref","hourCycle","defaultHourCycle","locale","pattern","useMemo","segmentPattern","granularity","periodNames","dayPeriodNames","setValue","useControllableState","defaultValue","onValueChange","open","setOpen","defaultOpen","onOpenChange","toDraft","draftFromParts","toValue","formatDateTime","draft","setDraft","useSegmentDraft","draftDate","time","draftTime","interactive","invalid","hasEntry","nowParts","zonedParts","todayIn","reference","instant","zone","timeZoneName","minDate","maxDate","timeLabelId","handleKeyDown","onKeyDown","event","calendar","draftDateText","draftTimeText","formatTime","box","cx","className","size","handleBoxPointerDown","isLeaving","onFocus","onBlur","DateSegments","clearable","focusSegment","CloseIcon","Popover","CalendarIcon","name","FieldContext","Calendar","parseDate","next","TimeInput","parseTime"],"sources":["../../../../src/components/inputs/DateTimeInput/DateTimeInput.tsx"],"sourcesContent":["import {\n forwardRef,\n useId,\n useMemo,\n useRef,\n type FocusEventHandler,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { CalendarIcon, CloseIcon } from '#icons'\nimport { cx } from '#utils/cx'\nimport type { Size } from '#utils/tokens'\nimport { Popover } from '#components/overlays/Popover'\nimport { Calendar } from '#components/inputs/Calendar'\nimport { TimeInput } from '#components/inputs/TimeInput'\nimport { useControllableState } from '#components/inputs/Combobox/useControllableState'\nimport {\n FieldContext,\n markFieldAware,\n useResolvedField,\n} from '#components/inputs/internal/FieldContext'\nimport { useMergedRefs } from '#components/inputs/internal/refs'\nimport {\n DateSegments,\n draftDate,\n draftFromParts,\n draftTime,\n segmentPattern,\n useSegmentDraft,\n type Draft,\n} from '#components/inputs/internal/DateSegments'\nimport {\n DEFAULT_LOCALE,\n dateOf,\n dayPeriodNames,\n defaultHourCycle,\n formatDate,\n formatDateTime,\n formatTime,\n parseDate,\n parseDateTime,\n parseTime,\n timeZoneName,\n todayIn,\n zonedParts,\n zonedToInstant,\n type DateTimeParts,\n type TimeGranularity,\n} from '#components/inputs/internal/dates'\nimport {\n DEFAULT_DATE_TIME_LABELS,\n focusSegment,\n handleBoxPointerDown,\n isLeaving,\n type DateTimeLabels,\n} from '#components/inputs/internal/picker'\nimport control from '#components/inputs/internal/control.module.css'\nimport picker from '#components/inputs/internal/picker.module.css'\n\nexport interface DateTimeInputProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | 'onBlur' | 'onFocus'\n> {\n /**\n * `YYYY-MM-DDTHH:mm` (a wall-clock time, like `datetime-local`), or with `timeZone` the UTC\n * instant `YYYY-MM-DDTHH:mm:ssZ`. `''` until every part is filled in.\n */\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n /**\n * Makes the value an instant: it's shown and typed as the wall clock in this zone (an IANA\n * name such as `Australia/Perth`, or `UTC`) and reported in UTC. The zone's short name shows\n * in the box.\n */\n timeZone?: string\n /** `minute` (default) or `second`: the smallest part shown and kept. */\n granularity?: TimeGranularity\n /** 12 (with am/pm) or 24. Defaults to the locale's own clock. */\n hourCycle?: 12 | 24\n /** Earliest date-time, in the same form as `value`. Earlier days can't be picked. */\n min?: string\n /** Latest date-time, in the same form as `value`. */\n max?: string\n /** Marks dates unavailable, in the calendar and when typed. */\n isDateDisabled?: (date: string) => boolean\n /** 0 (Sunday) to 6 (Saturday). Defaults to the locale's own week. */\n firstDayOfWeek?: number\n /** BCP 47 locale for the order of the parts, the clock and the calendar. Default `en-AU`. */\n locale?: string\n /** Show the calendar button. Default `true`. */\n calendar?: boolean\n /** Show a clear button while there's a value. */\n clearable?: boolean\n /** Submits the value (`''` when incomplete). */\n name?: string\n form?: string\n size?: Size\n disabled?: boolean\n readOnly?: boolean\n required?: boolean\n /** Critical border + `aria-invalid`. Inside a `<Field error>` this is set for you. */\n invalid?: boolean\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Fires once focus leaves the whole control, calendar included. */\n onBlur?: FocusEventHandler<HTMLElement>\n onFocus?: FocusEventHandler<HTMLElement>\n labels?: Partial<DateTimeLabels>\n}\n\n/** Milliseconds for ordering two values in the same zone. */\nfunction instantOf(text: string | undefined, timeZone?: string): number | null {\n const parts = parseDateTime(text ?? '', timeZone)\n if (!parts) return null\n return timeZone\n ? zonedToInstant(parts.date, parts.time, timeZone)\n : Date.UTC(\n parts.date.year,\n parts.date.month - 1,\n parts.date.day,\n parts.time.hour,\n parts.time.minute,\n parts.time.second,\n )\n}\n\n/** Whether a date-time `value` falls outside `min`/`max` or on a disabled date. */\nexport function isDateTimeOutOfRange(\n value: string,\n {\n min,\n max,\n isDateDisabled,\n timeZone,\n }: {\n min?: string\n max?: string\n isDateDisabled?: (date: string) => boolean\n timeZone?: string\n },\n): boolean {\n const at = instantOf(value, timeZone)\n if (at === null) return false\n const lower = instantOf(min, timeZone)\n const upper = instantOf(max, timeZone)\n const date = dateOf(value, timeZone)\n return (\n (lower !== null && at < lower) ||\n (upper !== null && at > upper) ||\n (date !== null && (isDateDisabled?.(formatDate(date)) ?? false))\n )\n}\n\n/**\n * A date and a time typed part by part, with a calendar and the time together in one panel.\n *\n * @remarks\n * `DateTimeInput` holds a moment as an ISO string. Without `timeZone` it's a wall-clock time\n * (`2026-10-15T14:30`), the same as a native `datetime-local`: right for \"the meeting is at 2:30\"\n * wherever the reader is. With `timeZone` it's an instant (`2026-10-15T03:30:00Z`), shown and typed\n * as the clock in that zone, with the zone's name in the box: right for logs, deadlines and\n * anything stored as a timestamp.\n *\n * The parts type like {@link DateInput | DateInput} and {@link TimeInput | TimeInput}. The\n * calendar button opens a {@link Calendar | Calendar} with the time beneath it; picking a day keeps\n * the time (or starts at midnight), and the panel stays open to set the time. For the usual\n * labelled field, use {@link DateTimeField | DateTimeField}.\n *\n * @privateRemarks\n * One draft holds the date and time; the panel's Calendar and TimeInput are views of it. A\n * zoned value is converted to wall time on the way in (`parseDateTime`) and back to UTC on the\n * way out (`formatDateTime`), so the parts always show the zone's clock. The ref goes to the box.\n *\n * <DateTimeInput timeZone=\"UTC\" value={publishAt} onValueChange={setPublishAt} />\n */\nexport const DateTimeInput = markFieldAware(\n forwardRef<HTMLDivElement, DateTimeInputProps>(function DateTimeInput(\n {\n value: valueProp,\n defaultValue,\n onValueChange,\n timeZone,\n granularity = 'minute',\n hourCycle: hourCycleProp,\n min,\n max,\n isDateDisabled,\n firstDayOfWeek,\n locale = DEFAULT_LOCALE,\n calendar = true,\n clearable = false,\n name,\n form,\n size = 'md',\n id: idProp,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n required: requiredProp,\n invalid: invalidProp,\n open: openProp,\n defaultOpen,\n onOpenChange,\n onBlur,\n onFocus,\n onKeyDown,\n labels: labelsProp,\n className,\n 'aria-describedby': describedByProp,\n 'aria-invalid': ariaInvalid,\n 'aria-labelledby': ariaLabelledBy,\n ...rest\n },\n ref,\n ) {\n const labels = { ...DEFAULT_DATE_TIME_LABELS, ...labelsProp }\n const field = useResolvedField({\n id: idProp,\n describedBy: describedByProp,\n invalid: invalidProp,\n ariaInvalid,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n required: requiredProp,\n })\n const autoId = useId()\n const rootRef = useRef<HTMLDivElement>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const composedRef = useMergedRefs(ref, rootRef)\n const hourCycle = hourCycleProp ?? defaultHourCycle(locale)\n const pattern = useMemo(\n () => segmentPattern('datetime', locale, granularity, hourCycle),\n [locale, granularity, hourCycle],\n )\n const periodNames = useMemo(() => dayPeriodNames(locale), [locale])\n const [value, setValue] = useControllableState(valueProp, defaultValue ?? '', onValueChange)\n const [open, setOpen] = useControllableState(openProp, defaultOpen ?? false, onOpenChange)\n\n const toDraft = (text: string): Draft => {\n const parts = parseDateTime(text, timeZone)\n return parts ? draftFromParts(parts.date, parts.time) : {}\n }\n const toValue = (parts: DateTimeParts) => formatDateTime(parts, granularity, timeZone)\n const fromDraft = (draft: Draft): string => {\n const date = draftDate(draft)\n const time = draftTime(draft)\n if (!date || !time || (granularity === 'second' && draft.second === undefined)) return ''\n return toValue({ date, time: granularity === 'minute' ? { ...time, second: 0 } : time })\n }\n const [draft, setDraft] = useSegmentDraft(value, toDraft, fromDraft, setValue)\n const interactive = !field.disabled && !field.readOnly\n const invalid =\n field.invalid || isDateTimeOutOfRange(value, { min, max, isDateDisabled, timeZone })\n const hasEntry = Object.keys(draft).length > 0\n const nowParts = timeZone\n ? zonedParts(Date.now(), timeZone)\n : { date: todayIn(), time: { hour: new Date().getHours(), minute: 0, second: 0 } }\n const reference = draftFromParts(nowParts.date, nowParts.time)\n const instant = instantOf(value, timeZone)\n const zone = timeZone ? timeZoneName(locale, timeZone, instant ?? Date.now()) : null\n const minDate = min ? dateOf(min, timeZone) : null\n const maxDate = max ? dateOf(max, timeZone) : null\n const timeLabelId = `${autoId}-time`\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event)\n if (event.defaultPrevented) return\n if (calendar && interactive && event.altKey && event.key === 'ArrowDown') {\n event.preventDefault()\n setOpen(true)\n }\n }\n\n const draftDateText = (() => {\n const date = draftDate(draft)\n return date ? formatDate(date) : ''\n })()\n const draftTimeText = (() => {\n const time = draftTime(draft)\n return time ? formatTime(time, granularity) : ''\n })()\n\n const box = (\n // The group only routes what its parts don't handle: a click on its padding, and\n // Alt + Down Arrow from any part to open the calendar.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions\n <div\n ref={composedRef}\n role=\"group\"\n className={cx(control.box, picker.root, className)}\n data-size={size}\n data-invalid={invalid || undefined}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readOnly || undefined}\n aria-labelledby={ariaLabelledBy ?? field.labelId}\n aria-describedby={field.describedBy}\n aria-busy={field.busy || undefined}\n {...rest}\n onPointerDown={handleBoxPointerDown}\n onKeyDown={handleKeyDown}\n onFocus={(event) => {\n if (isLeaving(event, rootRef, panelRef)) onFocus?.(event)\n }}\n onBlur={(event) => {\n if (isLeaving(event, rootRef, panelRef)) onBlur?.(event)\n }}\n >\n <DateSegments\n pattern={pattern}\n draft={draft}\n onDraftChange={setDraft}\n hourCycle={hourCycle}\n periodNames={periodNames}\n labels={labels}\n reference={reference}\n firstId={field.id}\n disabled={field.disabled}\n readOnly={field.readOnly}\n invalid={invalid}\n required={field.required}\n />\n {zone || (clearable && interactive && hasEntry) || calendar ? (\n <span className={picker.trailing}>\n {zone ? <span className={picker.zone}>{zone}</span> : null}\n {clearable && interactive && hasEntry ? (\n <button\n type=\"button\"\n className={picker.button}\n aria-label={labels.clear}\n onClick={() => {\n setDraft({})\n focusSegment(rootRef.current, 'first')\n }}\n >\n <CloseIcon />\n </button>\n ) : null}\n {calendar ? (\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n className={picker.button}\n aria-label={labels.openCalendar}\n disabled={!interactive}\n >\n <CalendarIcon />\n </button>\n </Popover.Trigger>\n ) : null}\n </span>\n ) : null}\n {name !== undefined ? (\n <input\n type=\"hidden\"\n name={name}\n form={form}\n value={value}\n disabled={field.disabled || undefined}\n />\n ) : null}\n </div>\n )\n\n if (!calendar) return box\n\n return (\n <Popover open={open && interactive} onOpenChange={setOpen}>\n <Popover.Anchor asChild>{box}</Popover.Anchor>\n <Popover.Content\n ref={panelRef}\n className={picker.popover}\n align=\"start\"\n aria-label={labels.openCalendar}\n onOpenAutoFocus={(event) => {\n event.preventDefault()\n }}\n >\n {/* The panel's time box isn't the field's control: no label, error or id from it. */}\n <FieldContext.Provider value={null}>\n <div className={picker.panel}>\n <Calendar\n // The panel is a dialog: opening it moves focus to its current day.\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n value={parseDate(draftDateText) ? draftDateText : ''}\n min={minDate ? formatDate(minDate) : undefined}\n max={maxDate ? formatDate(maxDate) : undefined}\n isDateDisabled={isDateDisabled}\n firstDayOfWeek={firstDayOfWeek}\n locale={locale}\n timeZone={timeZone}\n labels={labels}\n onValueChange={(next) => {\n const date = parseDate(next)\n if (date) setDraft({ hour: 0, minute: 0, second: 0, ...draft, ...date })\n }}\n />\n <div className={picker.timeRow}>\n <span id={timeLabelId} className={picker.timeLabel}>\n {labels.time}\n </span>\n <TimeInput\n aria-labelledby={timeLabelId}\n value={draftTimeText}\n granularity={granularity}\n hourCycle={hourCycle}\n locale={locale}\n size=\"sm\"\n labels={labels}\n onValueChange={(next) => {\n const time = parseTime(next)\n if (time) setDraft({ ...draft, ...time })\n }}\n />\n </div>\n </div>\n </FieldContext.Provider>\n </Popover.Content>\n </Popover>\n )\n }),\n)\n"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type FieldLabelProps } from '../Field/index.js';
|
|
2
|
+
import { type JsonInputError, type JsonInputProps } from '../JsonInput/index.js';
|
|
3
|
+
export interface JsonFieldProps extends FieldLabelProps, Omit<JsonInputProps, 'invalid'> {
|
|
4
|
+
}
|
|
5
|
+
/** "Line 3, column 12: Remove this comma: nothing follows it". */
|
|
6
|
+
export declare function describeJsonError(error: JsonInputError): string;
|
|
7
|
+
/**
|
|
8
|
+
* A labelled JSON editor that says where the JSON is wrong, formats it on demand and highlights
|
|
9
|
+
* it with the theme.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* `JsonField` is a {@link Field | Field} around a {@link JsonInput | JsonInput}. Once typing pauses,
|
|
13
|
+
* or the field loses focus, a syntax error shows as the field's error with its line and column
|
|
14
|
+
* ("Line 3, column 12: Remove this comma: nothing follows it"), and so does a message from
|
|
15
|
+
* `validate`. An `error` you pass wins over both, so a form library can still own the message.
|
|
16
|
+
* JsonInput props and the ref go to the `<textarea>`.
|
|
17
|
+
*
|
|
18
|
+
* @privateRemarks
|
|
19
|
+
* Label + JsonInput + description + error. `className`/`style` go to the field wrapper.
|
|
20
|
+
*
|
|
21
|
+
* <JsonField label="Payload" formatOnBlur validate={check} />
|
|
22
|
+
*/
|
|
23
|
+
export declare const JsonField: import("react").ForwardRefExoticComponent<JsonFieldProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Field as e } from "../Field/Field.js";
|
|
2
|
+
import { splitFieldLabelProps as t } from "../internal/fieldProps.js";
|
|
3
|
+
import { JsonInput as n } from "../JsonInput/JsonInput.js";
|
|
4
|
+
import { forwardRef as r, useState as i } from "react";
|
|
5
|
+
import { jsx as a } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/inputs/JsonField/JsonField.tsx
|
|
7
|
+
function o(e) {
|
|
8
|
+
return e.line === void 0 ? e.message : `Line ${String(e.line)}, column ${String(e.column ?? 1)}: ${e.message}`;
|
|
9
|
+
}
|
|
10
|
+
var s = r(function(r, s) {
|
|
11
|
+
let [c, l] = t(r), { id: u, disabled: d, className: f, style: p, onValidationChange: m, ...h } = l, [g, _] = i(void 0), v = g?.error ? o(g.error) : void 0;
|
|
12
|
+
return /* @__PURE__ */ a(e, {
|
|
13
|
+
...c,
|
|
14
|
+
error: c.error ?? v,
|
|
15
|
+
htmlFor: u,
|
|
16
|
+
disabled: d,
|
|
17
|
+
className: f,
|
|
18
|
+
style: p,
|
|
19
|
+
children: /* @__PURE__ */ a(n, {
|
|
20
|
+
ref: s,
|
|
21
|
+
id: u,
|
|
22
|
+
disabled: d,
|
|
23
|
+
onValidationChange: (e) => {
|
|
24
|
+
_(e), m?.(e);
|
|
25
|
+
},
|
|
26
|
+
...h
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
//#endregion
|
|
31
|
+
export { s as JsonField, o as describeJsonError };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=JsonField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonField.js","names":["describeJsonError","error","JsonField","forwardRef","fieldProps","rest","splitFieldLabelProps","props","inputRest","shown","setShown","useState","own","Field","id","JsonInput","validation","onValidationChange"],"sources":["../../../../src/components/inputs/JsonField/JsonField.tsx"],"sourcesContent":["import { forwardRef, useState } from 'react'\nimport { Field, type FieldLabelProps } from '#components/inputs/Field'\nimport {\n JsonInput,\n type JsonInputError,\n type JsonInputProps,\n type JsonValidation,\n} from '#components/inputs/JsonInput'\nimport { splitFieldLabelProps } from '#components/inputs/internal/fieldProps'\n\nexport interface JsonFieldProps extends FieldLabelProps, Omit<JsonInputProps, 'invalid'> {}\n\n/** \"Line 3, column 12: Remove this comma: nothing follows it\". */\nexport function describeJsonError(error: JsonInputError): string {\n return error.line === undefined\n ? error.message\n : `Line ${String(error.line)}, column ${String(error.column ?? 1)}: ${error.message}`\n}\n\n/**\n * A labelled JSON editor that says where the JSON is wrong, formats it on demand and highlights\n * it with the theme.\n *\n * @remarks\n * `JsonField` is a {@link Field | Field} around a {@link JsonInput | JsonInput}. Once typing pauses,\n * or the field loses focus, a syntax error shows as the field's error with its line and column\n * (\"Line 3, column 12: Remove this comma: nothing follows it\"), and so does a message from\n * `validate`. An `error` you pass wins over both, so a form library can still own the message.\n * JsonInput props and the ref go to the `<textarea>`.\n *\n * @privateRemarks\n * Label + JsonInput + description + error. `className`/`style` go to the field wrapper.\n *\n * <JsonField label=\"Payload\" formatOnBlur validate={check} />\n */\nexport const JsonField = forwardRef<HTMLTextAreaElement, JsonFieldProps>(\n function JsonField(props, ref) {\n const [fieldProps, rest] = splitFieldLabelProps(props)\n const { id, disabled, className, style, onValidationChange, ...inputRest } = rest\n const [shown, setShown] = useState<JsonValidation | undefined>(undefined)\n const own = shown?.error ? describeJsonError(shown.error) : undefined\n\n return (\n <Field\n {...fieldProps}\n error={fieldProps.error ?? own}\n htmlFor={id}\n disabled={disabled}\n className={className}\n style={style}\n >\n <JsonInput\n ref={ref}\n id={id}\n disabled={disabled}\n onValidationChange={(validation) => {\n setShown(validation)\n onValidationChange?.(validation)\n }}\n {...inputRest}\n />\n </Field>\n )\n },\n)\n"],"mappings":";;;;;;AAaA,SAAgBA,EAAkB,GAA+B;CAC/D,OAAOC,EAAM,SAAS,KAAA,IAClBA,EAAM,UACN,QAAQ,OAAOA,EAAM,IAAI,EAAE,WAAW,OAAOA,EAAM,UAAU,CAAC,EAAE,IAAIA,EAAM;AAChF;AAkBA,IAAaC,IAAYC,EACvB,SAAmB,GAAO,GAAK;CAC7B,IAAM,CAACC,GAAYC,KAAQC,EAAqBC,CAAK,GAC/C,EAAE,OAAI,aAAU,cAAW,UAAO,uBAAoB,GAAGC,MAAcH,GACvE,CAACI,GAAOC,KAAYC,EAAqC,KAAA,CAAS,GAClEC,IAAMH,GAAO,QAAQT,EAAkBS,EAAM,KAAK,IAAI,KAAA;CAE5D,OACE,kBAACI,GAAD;EACE,GAAIT;EACJ,OAAOA,EAAW,SAASQ;EAC3B,SAASE;EACC;EACC;EACJ;EAEP,UAAA,kBAACC,GAAD;GACO;GACD;GACM;GACV,qBAAqB,MAAe;IAElC,AADAL,EAASM,CAAU,GACnBC,IAAqBD,CAAU;GACjC;GACA,GAAIR;EACL,CAAA;CACI,CAAA;AAEX,CACF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type TextareaHTMLAttributes } from 'react';
|
|
2
|
+
import { type JsonIndent } from './json.js';
|
|
3
|
+
/** Why the text isn't acceptable. A syntax error has the line and column it points at. */
|
|
4
|
+
export interface JsonInputError {
|
|
5
|
+
message: string;
|
|
6
|
+
line?: number;
|
|
7
|
+
column?: number;
|
|
8
|
+
}
|
|
9
|
+
/** What a JSON text holds, and whether it's acceptable. */
|
|
10
|
+
export interface JsonValidation {
|
|
11
|
+
/** The parsed value, when the text is valid JSON. `undefined` when it's empty or invalid. */
|
|
12
|
+
parsed: unknown;
|
|
13
|
+
/** `true` when the text is valid JSON that passes `validate`, or is empty. */
|
|
14
|
+
valid: boolean;
|
|
15
|
+
/** Why it isn't valid. */
|
|
16
|
+
error?: JsonInputError;
|
|
17
|
+
}
|
|
18
|
+
export interface JsonInputProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue' | 'wrap' | 'rows' | 'cols' | 'children'> {
|
|
19
|
+
/** The text (controlled). */
|
|
20
|
+
value?: string;
|
|
21
|
+
/** The starting text (uncontrolled). */
|
|
22
|
+
defaultValue?: string;
|
|
23
|
+
/** Called with the new text, and what it holds, on every change. */
|
|
24
|
+
onValueChange?: (value: string, validation: JsonValidation) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Called when the validation the input shows changes: once typing pauses for
|
|
27
|
+
* `validationDelay`, on blur, and straight away when the text becomes valid again.
|
|
28
|
+
*/
|
|
29
|
+
onValidationChange?: (validation: JsonValidation) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Your own rules for a value that parses: return a message to reject it, or `undefined` to
|
|
32
|
+
* accept it. Wire a JSON Schema validator in here.
|
|
33
|
+
*/
|
|
34
|
+
validate?: (parsed: unknown) => string | undefined;
|
|
35
|
+
/** How long typing has to pause before an error shows, in ms. Default `500`. */
|
|
36
|
+
validationDelay?: number;
|
|
37
|
+
/** How Format indents: `2` (default), `4` or `'tab'`. Also what Tab inserts. */
|
|
38
|
+
indent?: JsonIndent;
|
|
39
|
+
/** Sort object keys when formatting or minifying. */
|
|
40
|
+
sortKeys?: boolean;
|
|
41
|
+
/** Format the text when the input loses focus, if it's valid. */
|
|
42
|
+
formatOnBlur?: boolean;
|
|
43
|
+
/** Close brackets and quotes as you type them. Default `true`. */
|
|
44
|
+
autoClose?: boolean;
|
|
45
|
+
/** Number the lines. Default `true`. */
|
|
46
|
+
lineNumbers?: boolean;
|
|
47
|
+
/** Wrap long lines instead of scrolling sideways. */
|
|
48
|
+
wrap?: boolean;
|
|
49
|
+
/** Show the Format, Minify and Copy actions above the text. Default `true`. */
|
|
50
|
+
toolbar?: boolean;
|
|
51
|
+
/** The least height, in lines. Default `4`. */
|
|
52
|
+
minRows?: number;
|
|
53
|
+
/** Grow with the text up to this many lines, then scroll. Without it, it keeps growing. */
|
|
54
|
+
maxRows?: number;
|
|
55
|
+
/** Critical border and `aria-invalid`, on top of its own validation. Set for you inside a `Field`. */
|
|
56
|
+
invalid?: boolean;
|
|
57
|
+
/** Name of the copy action. Default "Copy JSON". */
|
|
58
|
+
copyLabel?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Parses `text` and runs `validate` on the result. Empty text is valid and holds nothing. */
|
|
61
|
+
export declare function validateJson(text: string, validate?: (parsed: unknown) => string | undefined): JsonValidation;
|
|
62
|
+
/**
|
|
63
|
+
* A JSON editor in a field box: it highlights with the theme, numbers the lines, marks the line
|
|
64
|
+
* with an error, and formats or minifies on demand.
|
|
65
|
+
*
|
|
66
|
+
* @remarks
|
|
67
|
+
* `JsonInput` is for JSON that people edit by hand: a config blob, a request payload, a fixture.
|
|
68
|
+
* It parses as you type and, once typing pauses, marks the line that's wrong and sets
|
|
69
|
+
* `aria-invalid`. It never changes text that isn't valid. `onValueChange` gets the text and what
|
|
70
|
+
* it holds (`parsed`, `valid` and `error`) on every change. For a labelled field that shows the
|
|
71
|
+
* error message, use {@link JsonField | JsonField}.
|
|
72
|
+
*
|
|
73
|
+
* Format re-indents the text (`indent` is `2`, `4` or `'tab'`), and Minify puts it on one line.
|
|
74
|
+
* Both keep numbers and strings exactly as written, so a long ID or a price like `1.50` survives,
|
|
75
|
+
* and both keep the order of keys unless you pass `sortKeys`. `formatOnBlur` formats valid text
|
|
76
|
+
* as the input loses focus.
|
|
77
|
+
*
|
|
78
|
+
* It grows with its content from `minRows` up to `maxRows`, then scrolls. `readOnly` makes it a
|
|
79
|
+
* viewer: no Format or Minify, and Tab moves on as usual.
|
|
80
|
+
*
|
|
81
|
+
* ## Keyboard
|
|
82
|
+
*
|
|
83
|
+
* - **Tab** indents, and **Shift+Tab** outdents, the line or the selected lines. To leave the
|
|
84
|
+
* editor with the keyboard, press **Escape**, then **Tab**. Screen readers hear this in the
|
|
85
|
+
* input's description.
|
|
86
|
+
* - **Enter** keeps the indent, and indents again after `{` or `[`.
|
|
87
|
+
* - Typing `{`, `[` or `"` closes it for you (`autoClose`), and typing the closer steps over it.
|
|
88
|
+
* - **Shift+Alt+F** formats.
|
|
89
|
+
*
|
|
90
|
+
* ## Your own rules and JSON Schema
|
|
91
|
+
*
|
|
92
|
+
* `validate` gets the parsed value and returns a message to reject it. That's where a JSON Schema
|
|
93
|
+
* validator goes, so Kiln doesn't bundle one. With [Ajv](https://ajv.js.org):
|
|
94
|
+
*
|
|
95
|
+
* ```tsx
|
|
96
|
+
* import Ajv from 'ajv'
|
|
97
|
+
* import { JsonField } from '@mitcsutt/kiln-ui'
|
|
98
|
+
*
|
|
99
|
+
* const ajv = new Ajv()
|
|
100
|
+
* const check = ajv.compile(payloadSchema)
|
|
101
|
+
*
|
|
102
|
+
* export function PayloadField() {
|
|
103
|
+
* return (
|
|
104
|
+
* <JsonField
|
|
105
|
+
* label="Payload"
|
|
106
|
+
* validate={(value) => (check(value) ? undefined : ajv.errorsText(check.errors))}
|
|
107
|
+
* />
|
|
108
|
+
* )
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @privateRemarks
|
|
113
|
+
* A transparent textarea over a highlighted <pre> in the same grid cell, so the browser does the
|
|
114
|
+
* editing, selection, undo and IME, and the <pre> only paints. Highlighting is a built-in JSON
|
|
115
|
+
* tokenizer rather than the shiki `highlight` entry: JSON's grammar is small enough to get exactly
|
|
116
|
+
* right without a peer dependency, so the field works the same everywhere. Edits from the keyboard
|
|
117
|
+
* go through execCommand('insertText') so they stay on the native undo stack.
|
|
118
|
+
*/
|
|
119
|
+
export declare const JsonInput: import("react").ForwardRefExoticComponent<JsonInputProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|