@skiddph/prui 0.8.0 → 0.9.1

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.
@@ -1,172 +1,277 @@
1
- import { jsxs as x, Fragment as $, jsx as a } from "react/jsx-runtime";
2
- import * as s from "react";
3
- import { CalendarDays as z } from "lucide-react";
4
- import { cn as j } from "./cn.js";
5
- import { useOverlayStack as E, useEscapeKey as F, Portal as T } from "./overlay.js";
6
- import { useAnchoredPosition as H } from "./anchor.js";
7
- import { Calendar as U } from "./calendar.js";
8
- import { usePruiI18n as I } from "../i18n.js";
9
- const K = s.forwardRef(function({ value: v, defaultValue: D, onChange: t, min: h, max: M, placeholder: R = "YYYY-MM-DD", disabled: b, className: k, ariaLabel: w }, l) {
10
- const [g, N] = s.useState(D ?? ""), m = v !== void 0, f = m ? v : g, [r, o] = s.useState(!1), i = s.useRef(null), [u, y] = s.useState(""), { setElement: P, isTop: S } = E(r);
11
- F(r, S, () => {
12
- var e;
13
- o(!1), (e = i.current) == null || e.focus();
14
- });
15
- const { ref: d, position: c } = H({ active: r, anchorRef: i, side: "bottom", align: "start", offsetHeight: 360 }), Y = (e) => {
1
+ import { jsxs as h, Fragment as G, jsx as r } from "react/jsx-runtime";
2
+ import * as b from "react";
3
+ import { Clock as J, CalendarDays as Q } from "lucide-react";
4
+ import { cn as V } from "./cn.js";
5
+ import { Portal as W, useOverlayStack as te, useEscapeKey as re } from "./overlay.js";
6
+ import { useAnchoredPosition as ae } from "./anchor.js";
7
+ import { Calendar as X, fromDateKey as ne } from "./calendar.js";
8
+ import { TimePanel as U } from "./time-picker.js";
9
+ import { usePruiI18n as oe } from "../i18n.js";
10
+ const ie = /^\d{4}-\d{2}-\d{2}$/, le = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/;
11
+ function _(c, o) {
12
+ if (!c) return { date: "", time: o ? "00:00" : "" };
13
+ const [s, i] = c.split(" ");
14
+ return { date: s ?? "", time: o ? i ?? "00:00" : i ?? "" };
15
+ }
16
+ function Z(c, o, s) {
17
+ const { setElement: i, isTop: f } = te(o);
18
+ re(o, f, s);
19
+ const { ref: l, position: g } = ae({ active: o, anchorRef: c, side: "bottom", align: "start", offsetHeight: 380 });
20
+ return b.useEffect(() => {
21
+ if (!o) return;
22
+ const M = (R) => {
23
+ var u;
24
+ const D = R.target;
25
+ (u = c.current) != null && u.contains(D) || (!(D instanceof Element) || !D.closest("[data-prui-picker-panel]")) && s();
26
+ };
27
+ return document.addEventListener("mousedown", M), () => document.removeEventListener("mousedown", M);
28
+ }), { setElement: i, floatingRef: l, position: g };
29
+ }
30
+ const de = b.forwardRef(function({
31
+ value: o,
32
+ defaultValue: s,
33
+ onChange: i,
34
+ min: f,
35
+ max: l,
36
+ placeholder: g,
37
+ disabled: M,
38
+ className: R,
39
+ ariaLabel: D,
40
+ timepicker: u = !1,
41
+ seconds: m = !1,
42
+ minuteStep: H
43
+ }, N) {
44
+ const E = g ?? (u ? "YYYY-MM-DD HH:mm" : "YYYY-MM-DD"), [y, j] = b.useState(s ?? ""), C = o !== void 0, T = C ? o : y, [$, d] = b.useState(!1), x = b.useRef(null), [Y, w] = b.useState(""), { date: k, time: F } = _(T, u), O = x, { setElement: I, floatingRef: K, position: v } = Z(O, $, () => {
16
45
  var n;
17
- m || N(e), t == null || t(e), o(!1), (n = i.current) == null || n.focus();
46
+ d(!1), (n = x.current) == null || n.focus();
47
+ }), a = (n) => {
48
+ var p;
49
+ C || j(n), i == null || i(n), u || (d(!1), (p = x.current) == null || p.focus());
50
+ }, t = (n) => {
51
+ a(u ? `${n} ${F || "00:00"}` : n);
52
+ }, P = (n) => {
53
+ k && a(`${k} ${n}`);
18
54
  };
19
- return /* @__PURE__ */ x($, { children: [
20
- /* @__PURE__ */ a(
55
+ return /* @__PURE__ */ h(G, { children: [
56
+ /* @__PURE__ */ r(
21
57
  "input",
22
58
  {
23
- ref: (e) => {
24
- i.current = e, typeof l == "function" ? l(e) : l && (l.current = e);
59
+ ref: (n) => {
60
+ x.current = n, typeof N == "function" ? N(n) : N && (N.current = n);
25
61
  },
26
62
  type: "text",
27
63
  readOnly: !0,
28
64
  role: "combobox",
29
- "aria-expanded": r,
65
+ "aria-expanded": $,
30
66
  "aria-haspopup": "dialog",
31
- "aria-label": w,
32
- placeholder: R,
33
- disabled: b,
34
- value: u !== "" ? u : f,
67
+ "aria-label": D,
68
+ placeholder: E,
69
+ disabled: M,
70
+ value: Y !== "" ? Y : T,
71
+ onClick: () => d(!0),
35
72
  onFocus: () => {
36
- !b && !r && o(!0);
73
+ !M && !$ && d(!0);
37
74
  },
38
- onClick: () => o(!0),
39
- onChange: (e) => {
40
- const n = e.target.value;
41
- y(n), /^\d{4}-\d{2}-\d{2}$/.test(n) && (y(""), Y(n));
75
+ onChange: (n) => {
76
+ const p = n.target.value;
77
+ w(p), (u ? le.test(p) : ie.test(p)) && (w(""), a(p));
42
78
  },
43
- className: j(
44
- "prui-date-picker flex h-9 w-full cursor-pointer items-center gap-2 border border-[var(--prui-line)]",
45
- "bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
79
+ className: V(
80
+ "prui-date-picker h-9 w-full cursor-pointer rounded-[var(--prui-radius)] border border-[var(--prui-line)]",
81
+ "bg-[var(--prui-background)] px-3 pr-8 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
46
82
  "outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
47
83
  "disabled:opacity-50 disabled:cursor-not-allowed",
48
- k
84
+ R
49
85
  )
50
86
  }
51
87
  ),
52
- /* @__PURE__ */ a(z, { className: "pointer-events-none -ml-7 h-4 w-4 text-[var(--prui-dim)]", "aria-hidden": !0 }),
53
- r ? /* @__PURE__ */ a(T, { children: /* @__PURE__ */ a(
88
+ u ? /* @__PURE__ */ r(J, { className: "pointer-events-none -ml-7 h-4 w-4 text-[var(--prui-dim)]", "aria-hidden": !0 }) : /* @__PURE__ */ r(Q, { className: "pointer-events-none -ml-7 h-4 w-4 text-[var(--prui-dim)]", "aria-hidden": !0 }),
89
+ $ ? /* @__PURE__ */ r(W, { children: /* @__PURE__ */ r(
54
90
  "div",
55
91
  {
56
- ref: (e) => {
57
- d(e), P(e);
92
+ ref: (n) => {
93
+ K(n), I(n);
58
94
  },
59
95
  role: "dialog",
60
- "aria-label": "Choose date",
61
- className: "fixed z-[var(--prui-z-overlay)]",
62
- style: { top: (c == null ? void 0 : c.top) ?? -9999, left: (c == null ? void 0 : c.left) ?? -9999 },
63
- children: /* @__PURE__ */ a(U, { value: f, onSelect: Y, min: h, max: M, className: "shadow-[var(--prui-shadow-lg)]" })
96
+ "aria-label": D ?? "Choose date",
97
+ "data-prui-picker-panel": !0,
98
+ className: "fixed z-[var(--prui-z-overlay)] rounded-[var(--prui-radius)] border border-[var(--prui-line)] bg-[var(--prui-surface)] p-1 shadow-[var(--prui-shadow-lg)]",
99
+ style: { top: (v == null ? void 0 : v.top) ?? -9999, left: (v == null ? void 0 : v.left) ?? -9999 },
100
+ children: /* @__PURE__ */ h("div", { className: V("flex gap-2", u && "p-1"), children: [
101
+ /* @__PURE__ */ r(
102
+ X,
103
+ {
104
+ value: k || void 0,
105
+ onSelect: t,
106
+ min: f ? f.slice(0, 10) : void 0,
107
+ max: l ? l.slice(0, 10) : void 0,
108
+ showToday: !1,
109
+ className: "border-0 shadow-none"
110
+ }
111
+ ),
112
+ u ? /* @__PURE__ */ r("div", { className: "flex flex-col gap-1 border-l border-[var(--prui-line)] pl-2", children: /* @__PURE__ */ r(U, { value: F, onSelect: P, seconds: m, minuteStep: H }) }) : null
113
+ ] })
64
114
  }
65
115
  ) }) : null
66
116
  ] });
67
117
  });
68
- K.displayName = "DatePicker";
69
- const q = s.forwardRef(function({ value: v, defaultValue: D, onChange: t, min: h, max: M, placeholder: R = "YYYY-MM-DD – YYYY-MM-DD", disabled: b, className: k, ariaLabel: w }, l) {
70
- const { t: g } = I(), [N, m] = s.useState(D ?? {}), f = v !== void 0, r = f ? v : N, [o, i] = s.useState(!1), u = s.useRef(null), { setElement: y, isTop: P } = E(o);
71
- F(o, P, () => {
118
+ de.displayName = "DatePicker";
119
+ function se(c, o) {
120
+ const s = typeof o == "string" ? /^(\d+)([dwmy])$/i.exec(o.trim()) : null, i = Number(s ? s[1] : o), f = s ? s[2].toLowerCase() : "d", l = new Date(c);
121
+ return f === "d" ? l.setDate(l.getDate() + i) : f === "w" ? l.setDate(l.getDate() + i * 7) : f === "m" ? l.setMonth(l.getMonth() + i) : l.setFullYear(l.getFullYear() + i), l;
122
+ }
123
+ function A(c, o) {
124
+ const s = se(ne(c), o), i = s.getFullYear(), f = String(s.getMonth() + 1).padStart(2, "0"), l = String(s.getDate()).padStart(2, "0");
125
+ return `${i}-${f}-${l}`;
126
+ }
127
+ function B(c) {
128
+ return c ? c.slice(0, 10) : void 0;
129
+ }
130
+ const ce = b.forwardRef(function({
131
+ value: o,
132
+ defaultValue: s,
133
+ onChange: i,
134
+ min: f,
135
+ max: l,
136
+ maxRange: g,
137
+ placeholder: M,
138
+ disabled: R,
139
+ className: D,
140
+ ariaLabel: u,
141
+ timepicker: m = !1,
142
+ seconds: H = !1,
143
+ minuteStep: N
144
+ }, E) {
145
+ const { t: y } = oe(), j = M ?? (m ? "YYYY-MM-DD HH:mm – YYYY-MM-DD HH:mm" : "YYYY-MM-DD – YYYY-MM-DD"), [C, T] = b.useState(s ?? {}), $ = o !== void 0, d = $ ? o : C, [x, Y] = b.useState(!1), w = b.useRef(null), k = w, [F, O] = b.useState(void 0), { setElement: I, floatingRef: K, position: v } = Z(k, x, () => {
72
146
  var e;
73
- i(!1), (e = u.current) == null || e.focus();
147
+ Y(!1), (e = w.current) == null || e.focus();
74
148
  });
75
- const { ref: S, position: d } = H({ active: o, anchorRef: u, side: "bottom", align: "start", offsetHeight: 360 }), c = (e) => {
76
- var O;
77
- const { from: n, to: A } = r;
78
- let p;
79
- if (!n || n && A)
80
- p = { from: e };
81
- else if (e < n)
82
- p = { from: e };
83
- else {
84
- p = { from: n, to: e }, t == null || t(p), f || m(p), i(!1), (O = u.current) == null || O.focus();
149
+ b.useEffect(() => {
150
+ x && O(d.from ? d.from.slice(0, 7) : void 0);
151
+ }, [x, d.from === void 0]);
152
+ const a = d.from ? _(d.from, m) : void 0, t = d.to ? _(d.to, m) : void 0, P = (a == null ? void 0 : a.date) ?? "", n = b.useCallback(
153
+ (e) => !g || !P || t != null && t.date ? !1 : e > A(P, g),
154
+ [g, P, t == null ? void 0 : t.date]
155
+ ), p = (e) => {
156
+ $ || T(e), i == null || i(e);
157
+ }, ee = (e) => {
158
+ var z;
159
+ if (!a || a.date && (t != null && t.date)) {
160
+ p({ from: m ? `${e} 00:00` : e });
85
161
  return;
86
162
  }
87
- f || m(p), t == null || t(p);
88
- }, Y = r.from ? r.to ? `${r.from} – ${r.to}` : `${r.from} – …` : "";
89
- return /* @__PURE__ */ x($, { children: [
90
- /* @__PURE__ */ a(
163
+ if (e < a.date) {
164
+ p({ from: m ? `${e} 00:00` : e });
165
+ return;
166
+ }
167
+ if (g && e > A(a.date, g)) {
168
+ const S = A(a.date, g);
169
+ p({ from: d.from, to: m ? `${S} ${(t == null ? void 0 : t.time) ?? "23:59"}` : S });
170
+ return;
171
+ }
172
+ p({ from: d.from, to: m ? `${e} ${(t == null ? void 0 : t.time) ?? "23:59"}` : e }), m || (Y(!1), (z = w.current) == null || z.focus());
173
+ }, L = (e, z) => {
174
+ const S = e === "from" ? a : t;
175
+ S != null && S.date && p({ ...d, [e]: `${S.date} ${z}` });
176
+ }, q = a ? t ? `${d.from} – ${d.to}` : `${d.from} – …` : "";
177
+ return /* @__PURE__ */ h(G, { children: [
178
+ /* @__PURE__ */ r(
91
179
  "input",
92
180
  {
93
181
  ref: (e) => {
94
- u.current = e, typeof l == "function" ? l(e) : l && (l.current = e);
182
+ w.current = e, typeof E == "function" ? E(e) : E && (E.current = e);
95
183
  },
96
184
  type: "text",
97
185
  readOnly: !0,
98
186
  role: "combobox",
99
- "aria-expanded": o,
187
+ "aria-expanded": x,
100
188
  "aria-haspopup": "dialog",
101
- "aria-label": w,
102
- placeholder: R,
103
- disabled: b,
104
- value: Y,
105
- onClick: () => i(!0),
189
+ "aria-label": u,
190
+ placeholder: j,
191
+ disabled: R,
192
+ value: q,
193
+ onClick: () => Y(!0),
106
194
  onFocus: () => {
107
- !b && !o && i(!0);
195
+ !R && !x && Y(!0);
108
196
  },
109
- className: j(
110
- "prui-date-range-picker flex h-9 w-full cursor-pointer items-center border border-[var(--prui-line)]",
111
- "bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
197
+ className: V(
198
+ "prui-date-range-picker h-9 w-full cursor-pointer rounded-[var(--prui-radius)] border border-[var(--prui-line)]",
199
+ "bg-[var(--prui-background)] px-3 pr-8 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
112
200
  "outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
113
201
  "disabled:opacity-50 disabled:cursor-not-allowed",
114
- k
202
+ D
115
203
  )
116
204
  }
117
205
  ),
118
- /* @__PURE__ */ a(z, { className: "pointer-events-none -ml-7 h-4 w-4 text-[var(--prui-dim)]", "aria-hidden": !0 }),
119
- o ? /* @__PURE__ */ a(T, { children: /* @__PURE__ */ a(
206
+ m ? /* @__PURE__ */ r(J, { className: "pointer-events-none -ml-7 h-4 w-4 text-[var(--prui-dim)]", "aria-hidden": !0 }) : /* @__PURE__ */ r(Q, { className: "pointer-events-none -ml-7 h-4 w-4 text-[var(--prui-dim)]", "aria-hidden": !0 }),
207
+ x ? /* @__PURE__ */ r(W, { children: /* @__PURE__ */ r(
120
208
  "div",
121
209
  {
122
210
  ref: (e) => {
123
- S(e), y(e);
211
+ K(e), I(e);
124
212
  },
125
213
  role: "dialog",
126
- "aria-label": "Choose date range",
127
- className: "fixed z-[var(--prui-z-overlay)]",
128
- style: { top: (d == null ? void 0 : d.top) ?? -9999, left: (d == null ? void 0 : d.left) ?? -9999 },
129
- children: /* @__PURE__ */ x("div", { className: "shadow-[var(--prui-shadow-lg)]", children: [
130
- /* @__PURE__ */ a(
131
- U,
132
- {
133
- value: r.to ?? r.from,
134
- month: r.from ? `${r.from.slice(0, 7)}` : void 0,
135
- onSelect: c,
136
- min: h,
137
- max: M,
138
- showToday: !1,
139
- className: "border-0 shadow-none",
140
- "data-range-from": r.from ?? "",
141
- "data-range-to": r.to ?? ""
142
- }
143
- ),
144
- /* @__PURE__ */ x("div", { className: "flex items-center justify-between gap-2 border-t border-[var(--prui-line)] px-3 py-2 text-xs text-[var(--prui-dim)]", children: [
145
- /* @__PURE__ */ a("span", { "data-testid": "range-label", children: Y || g.today }),
146
- /* @__PURE__ */ x("div", { className: "flex gap-2", children: [
147
- /* @__PURE__ */ a(
148
- "button",
149
- {
150
- type: "button",
151
- onClick: () => {
152
- f || m({}), t == null || t({});
153
- },
154
- className: "cursor-pointer rounded-[var(--prui-radius-1)] px-2 py-1 transition-colors hover:bg-[var(--prui-raise)]",
155
- children: g.clear
156
- }
157
- ),
158
- /* @__PURE__ */ a(
159
- "button",
160
- {
161
- type: "button",
162
- onClick: () => {
163
- var e;
164
- i(!1), (e = u.current) == null || e.focus();
165
- },
166
- className: "cursor-pointer rounded-[var(--prui-radius-1)] bg-[var(--prui-brand)]/15 px-2 py-1 text-[var(--prui-brand)] transition-colors hover:bg-[var(--prui-brand)]/25",
167
- children: g.apply
168
- }
169
- )
214
+ "aria-label": u ?? "Choose date range",
215
+ "data-prui-picker-panel": !0,
216
+ className: "fixed z-[var(--prui-z-overlay)] rounded-[var(--prui-radius)] border border-[var(--prui-line)] bg-[var(--prui-surface)] shadow-[var(--prui-shadow-lg)]",
217
+ style: { top: (v == null ? void 0 : v.top) ?? -9999, left: (v == null ? void 0 : v.left) ?? -9999 },
218
+ children: /* @__PURE__ */ h("div", { className: V("flex gap-2 p-1", m && "p-2"), children: [
219
+ /* @__PURE__ */ h("div", { children: [
220
+ /* @__PURE__ */ r("div", { className: "px-1 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wide text-[var(--prui-dim)]", children: y.from }),
221
+ /* @__PURE__ */ r(
222
+ X,
223
+ {
224
+ value: a == null ? void 0 : a.date,
225
+ month: F,
226
+ onMonthChange: O,
227
+ onSelect: ee,
228
+ min: f ? B(f) : void 0,
229
+ max: l ? B(l) : g && P && !(t != null && t.date) ? A(P, g) : void 0,
230
+ disabled: n,
231
+ showToday: !1,
232
+ className: "border-0 shadow-none"
233
+ }
234
+ )
235
+ ] }),
236
+ /* @__PURE__ */ h("div", { className: "flex flex-col gap-1 border-l border-[var(--prui-line)] pl-2", children: [
237
+ m ? /* @__PURE__ */ h("div", { children: [
238
+ /* @__PURE__ */ r("div", { className: "mb-1 px-1 text-[10px] font-semibold uppercase tracking-wide text-[var(--prui-dim)]", children: y.time }),
239
+ /* @__PURE__ */ h("div", { className: "flex gap-2", children: [
240
+ /* @__PURE__ */ h("div", { children: [
241
+ /* @__PURE__ */ r("div", { className: "mb-1 px-1 text-[10px] font-semibold uppercase tracking-wide text-[var(--prui-dim)]", children: y.from }),
242
+ /* @__PURE__ */ r(U, { compact: !0, value: a == null ? void 0 : a.time, onSelect: (e) => L("from", e), seconds: H, minuteStep: N })
243
+ ] }),
244
+ /* @__PURE__ */ h("div", { children: [
245
+ /* @__PURE__ */ r("div", { className: "mb-1 px-1 text-[10px] font-semibold uppercase tracking-wide text-[var(--prui-dim)]", children: y.to }),
246
+ /* @__PURE__ */ r(U, { compact: !0, value: t == null ? void 0 : t.time, onSelect: (e) => L("to", e), seconds: H, minuteStep: N })
247
+ ] })
248
+ ] })
249
+ ] }) : null,
250
+ /* @__PURE__ */ h("div", { className: "mt-auto flex items-center justify-between gap-2 border-t border-[var(--prui-line)] px-1 pb-1 pt-2 text-xs text-[var(--prui-dim)]", children: [
251
+ /* @__PURE__ */ r("span", { "data-testid": "range-label", children: q || y.today }),
252
+ /* @__PURE__ */ h("div", { className: "flex gap-1", children: [
253
+ /* @__PURE__ */ r(
254
+ "button",
255
+ {
256
+ type: "button",
257
+ onClick: () => p({}),
258
+ className: "cursor-pointer rounded-[var(--prui-radius-1)] px-2 py-1 transition-colors hover:bg-[var(--prui-raise)]",
259
+ children: y.clear
260
+ }
261
+ ),
262
+ /* @__PURE__ */ r(
263
+ "button",
264
+ {
265
+ type: "button",
266
+ onClick: () => {
267
+ var e;
268
+ Y(!1), (e = w.current) == null || e.focus();
269
+ },
270
+ className: "cursor-pointer rounded-[var(--prui-radius-1)] bg-[var(--prui-brand)]/15 px-2 py-1 text-[var(--prui-brand)] transition-colors hover:bg-[var(--prui-brand)]/25",
271
+ children: y.apply
272
+ }
273
+ )
274
+ ] })
170
275
  ] })
171
276
  ] })
172
277
  ] })
@@ -174,29 +279,36 @@ const q = s.forwardRef(function({ value: v, defaultValue: D, onChange: t, min: h
174
279
  ) }) : null
175
280
  ] });
176
281
  });
177
- q.displayName = "DateRangePicker";
178
- const Z = {
282
+ ce.displayName = "DateRangePicker";
283
+ const xe = {
179
284
  name: "DatePicker",
180
285
  props: [
181
- { name: "value", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
182
- { name: "defaultValue", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
286
+ { name: "value", type: "string 'YYYY-MM-DD' | 'YYYY-MM-DD HH:mm'", default: "undefined", control: "date" },
287
+ { name: "defaultValue", type: "string", default: "undefined", control: "date" },
183
288
  { name: "onChange", type: "(date: string) => void", default: null, control: "none" },
184
- { name: "min", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
185
- { name: "max", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" }
289
+ { name: "min", type: "string", default: "undefined", control: "date" },
290
+ { name: "max", type: "string", default: "undefined", control: "date" },
291
+ { name: "timepicker", type: "boolean", default: "false", control: "boolean", description: "Adds a time panel; values become 'YYYY-MM-DD HH:mm(:ss)'." },
292
+ { name: "seconds", type: "boolean", default: "false", control: "boolean", description: "Seconds column (needs timepicker)." },
293
+ { name: "minuteStep", type: "number", default: "1", control: "number", description: "Minute step (needs timepicker)." }
186
294
  ]
187
- }, _ = {
295
+ }, ye = {
188
296
  name: "DateRangePicker",
189
297
  props: [
190
298
  { name: "value", type: "{ from?: string, to?: string }", default: "{}", control: "daterange" },
191
299
  { name: "defaultValue", type: "{ from?: string, to?: string }", default: "{}", control: "daterange" },
192
300
  { name: "onChange", type: "(range: DateRange) => void", default: null, control: "none" },
193
- { name: "min", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" },
194
- { name: "max", type: "string 'YYYY-MM-DD'", default: "undefined", control: "date" }
301
+ { name: "min", type: "string", default: "undefined", control: "date" },
302
+ { name: "max", type: "string", default: "undefined", control: "date" },
303
+ { name: "maxRange", type: "number | '90d' | '12w' | '3m' | '1y'", default: "undefined", control: "text", description: "Caps the selectable span; days beyond from+maxRange are disabled." },
304
+ { name: "timepicker", type: "boolean", default: "false", control: "boolean" },
305
+ { name: "seconds", type: "boolean", default: "false", control: "boolean" },
306
+ { name: "minuteStep", type: "number", default: "1", control: "number" }
195
307
  ]
196
308
  };
197
309
  export {
198
- K as DatePicker,
199
- q as DateRangePicker,
200
- Z as datePickerPropsMeta,
201
- _ as dateRangePickerPropsMeta
310
+ de as DatePicker,
311
+ ce as DateRangePicker,
312
+ xe as datePickerPropsMeta,
313
+ ye as dateRangePickerPropsMeta
202
314
  };
@@ -28,6 +28,13 @@ export interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement>
28
28
  export declare const DialogContent: React.ForwardRefExoticComponent<DialogContentProps & React.RefAttributes<HTMLDivElement>>;
29
29
  export declare const DialogHeader: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
30
30
  export declare const DialogTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLHeadingElement>>;
31
+ export interface DialogBodyProps extends React.HTMLAttributes<HTMLDivElement> {
32
+ /** Remove the default vertical padding (keeps horizontal). */
33
+ flush?: boolean;
34
+ }
35
+ /** Padded content area for DialogContent: consistent x/y gutters. */
36
+ export declare const DialogBody: React.ForwardRefExoticComponent<DialogBodyProps & React.RefAttributes<HTMLDivElement>>;
31
37
  export declare const DialogDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
32
38
  export declare const DialogFooter: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
33
39
  export declare const dialogPropsMeta: PropsMeta;
40
+ export declare const dialogBodyPropsMeta: PropsMeta;
@@ -1,64 +1,64 @@
1
- import { jsx as t, jsxs as y } from "react/jsx-runtime";
2
- import * as a from "react";
1
+ import { jsx as r, jsxs as x } from "react/jsx-runtime";
2
+ import * as t from "react";
3
3
  import { X as D } from "lucide-react";
4
- import { cn as n } from "./cn.js";
5
- import { useOverlay as h, Portal as w } from "./overlay.js";
6
- import { usePruiI18n as N } from "../i18n.js";
7
- const v = a.createContext(null);
8
- function g() {
9
- const e = a.useContext(v);
4
+ import { cn as i } from "./cn.js";
5
+ import { useOverlay as h, Portal as N } from "./overlay.js";
6
+ import { usePruiI18n as w } from "../i18n.js";
7
+ const g = t.createContext(null);
8
+ function v() {
9
+ const e = t.useContext(g);
10
10
  if (!e) throw new Error("Dialog parts must be used inside <Dialog>");
11
11
  return e;
12
12
  }
13
- const I = ({ open: e, defaultOpen: o = !1, onOpenChange: r, children: i }) => {
14
- const [c, p] = a.useState(o), s = e !== void 0, f = s ? e : c, d = a.useId(), l = (u) => {
15
- s || p(u), r == null || r(u);
13
+ const R = ({ open: e, defaultOpen: o = !1, onOpenChange: a, children: l }) => {
14
+ const [u, c] = t.useState(o), s = e !== void 0, f = s ? e : u, d = t.useId(), n = (p) => {
15
+ s || c(p), a == null || a(p);
16
16
  };
17
- return /* @__PURE__ */ t(v.Provider, { value: { open: f, setOpen: l, labelId: d }, children: i });
17
+ return /* @__PURE__ */ r(g.Provider, { value: { open: f, setOpen: n, labelId: d }, children: l });
18
18
  };
19
- I.displayName = "Dialog";
20
- const C = a.forwardRef(
21
- ({ className: e, children: o, ariaLabel: r, hideClose: i, initialFocus: c = "first", onClick: p, ...s }, f) => {
22
- const { open: d, setOpen: l, labelId: u } = g(), { t: b } = N(), { ref: x } = h({
19
+ R.displayName = "Dialog";
20
+ const I = t.forwardRef(
21
+ ({ className: e, children: o, ariaLabel: a, hideClose: l, initialFocus: u = "first", onClick: c, ...s }, f) => {
22
+ const { open: d, setOpen: n, labelId: p } = v(), { t: b } = w(), { ref: y } = h({
23
23
  open: d,
24
- onEscape: () => l(!1),
25
- initialFocus: c
24
+ onEscape: () => n(!1),
25
+ initialFocus: u
26
26
  });
27
- return d ? /* @__PURE__ */ t(w, { children: /* @__PURE__ */ t("div", { ref: x, children: /* @__PURE__ */ t(
27
+ return d ? /* @__PURE__ */ r(N, { children: /* @__PURE__ */ r("div", { ref: y, children: /* @__PURE__ */ r(
28
28
  "div",
29
29
  {
30
30
  className: "prui-dialog-overlay fixed inset-0 z-[var(--prui-z-overlay)] flex items-center justify-center p-4",
31
31
  style: { backgroundColor: "var(--prui-scrim)" },
32
32
  onMouseDown: (m) => {
33
- m.target === m.currentTarget && l(!1);
33
+ m.target === m.currentTarget && n(!1);
34
34
  },
35
- children: /* @__PURE__ */ y(
35
+ children: /* @__PURE__ */ x(
36
36
  "div",
37
37
  {
38
38
  ref: f,
39
39
  role: "dialog",
40
40
  "aria-modal": "true",
41
- "aria-label": r,
42
- "aria-labelledby": r ? void 0 : u,
41
+ "aria-label": a,
42
+ "aria-labelledby": a ? void 0 : p,
43
43
  tabIndex: -1,
44
- className: n(
44
+ className: i(
45
45
  "prui-dialog-content relative z-[var(--prui-z-content)] w-full max-w-lg rounded-[var(--prui-radius)]",
46
46
  "border border-[var(--prui-line)] bg-[var(--prui-surface)] shadow-[var(--prui-shadow-lg)]",
47
47
  "max-h-[85vh] overflow-auto outline-none",
48
48
  e
49
49
  ),
50
- onClick: p,
50
+ onClick: c,
51
51
  ...s,
52
52
  children: [
53
53
  o,
54
- i ? null : /* @__PURE__ */ t(
54
+ l ? null : /* @__PURE__ */ r(
55
55
  "button",
56
56
  {
57
57
  type: "button",
58
58
  "aria-label": b.close,
59
- onClick: () => l(!1),
59
+ onClick: () => n(!1),
60
60
  className: "absolute right-3 top-3 rounded-[var(--prui-radius-1)] p-1 text-[var(--prui-dim)] hover:text-[var(--prui-fg)] hover:bg-[var(--prui-raise)] cursor-pointer",
61
- children: /* @__PURE__ */ t(D, { className: "h-4 w-4", "aria-hidden": !0 })
61
+ children: /* @__PURE__ */ r(D, { className: "h-4 w-4", "aria-hidden": !0 })
62
62
  }
63
63
  )
64
64
  ]
@@ -68,19 +68,30 @@ const C = a.forwardRef(
68
68
  ) }) }) : null;
69
69
  }
70
70
  );
71
- C.displayName = "DialogContent";
72
- const F = ({ className: e, ...o }) => /* @__PURE__ */ t("div", { className: n("prui-dialog-header flex flex-col gap-1 p-4 pb-2", e), ...o }), R = a.forwardRef(
73
- ({ className: e, ...o }, r) => {
74
- const { labelId: i } = g();
75
- return /* @__PURE__ */ t("h2", { ref: r, id: i, className: n("prui-dialog-title text-base font-semibold text-[var(--prui-fg)]", e), ...o });
71
+ I.displayName = "DialogContent";
72
+ const E = ({ className: e, ...o }) => /* @__PURE__ */ r("div", { className: i("prui-dialog-header flex flex-col gap-1 p-4 pb-2", e), ...o }), C = t.forwardRef(
73
+ ({ className: e, ...o }, a) => {
74
+ const { labelId: l } = v();
75
+ return /* @__PURE__ */ r("h2", { ref: a, id: l, className: i("prui-dialog-title text-base font-semibold text-[var(--prui-fg)]", e), ...o });
76
76
  }
77
77
  );
78
- R.displayName = "DialogTitle";
79
- const j = a.forwardRef(
80
- ({ className: e, ...o }, r) => /* @__PURE__ */ t("p", { ref: r, className: n("prui-dialog-description text-sm text-[var(--prui-dim)]", e), ...o })
78
+ C.displayName = "DialogTitle";
79
+ const j = t.forwardRef(
80
+ ({ className: e, flush: o, ...a }, l) => /* @__PURE__ */ r(
81
+ "div",
82
+ {
83
+ ref: l,
84
+ className: i("prui-dialog-body px-4", o ? "pt-0 pb-0" : "pt-1 pb-4", e),
85
+ ...a
86
+ }
87
+ )
81
88
  );
82
- j.displayName = "DialogDescription";
83
- const M = ({ className: e, ...o }) => /* @__PURE__ */ t("div", { className: n("prui-dialog-footer flex items-center justify-end gap-2 p-4 pt-2", e), ...o }), H = {
89
+ j.displayName = "DialogBody";
90
+ const z = t.forwardRef(
91
+ ({ className: e, ...o }, a) => /* @__PURE__ */ r("p", { ref: a, className: i("prui-dialog-description text-sm text-[var(--prui-dim)]", e), ...o })
92
+ );
93
+ z.displayName = "DialogDescription";
94
+ const F = ({ className: e, ...o }) => /* @__PURE__ */ r("div", { className: i("prui-dialog-footer flex items-center justify-end gap-2 p-4 pt-2", e), ...o }), H = {
84
95
  name: "Dialog",
85
96
  props: [
86
97
  { name: "open", type: "boolean", default: "undefined", control: "boolean" },
@@ -88,13 +99,21 @@ const M = ({ className: e, ...o }) => /* @__PURE__ */ t("div", { className: n("p
88
99
  { name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" },
89
100
  { name: "initialFocus", type: 'ref | "first" | "container" | false', default: '"first"', control: "none" }
90
101
  ]
102
+ }, O = {
103
+ name: "DialogBody",
104
+ props: [
105
+ { name: "flush", type: "boolean", default: "false", control: "boolean", description: "Remove vertical padding." },
106
+ { name: "className", type: "string", default: "undefined", control: "text" }
107
+ ]
91
108
  };
92
109
  export {
93
- I as Dialog,
94
- C as DialogContent,
95
- j as DialogDescription,
96
- M as DialogFooter,
97
- F as DialogHeader,
98
- R as DialogTitle,
110
+ R as Dialog,
111
+ j as DialogBody,
112
+ I as DialogContent,
113
+ z as DialogDescription,
114
+ F as DialogFooter,
115
+ E as DialogHeader,
116
+ C as DialogTitle,
117
+ O as dialogBodyPropsMeta,
99
118
  H as dialogPropsMeta
100
119
  };