@skiddph/prui 0.7.0 → 0.8.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 (77) hide show
  1. package/dist/app/resource.d.ts +44 -1
  2. package/dist/app.js +1 -1
  3. package/dist/chunks/auth-shell-DQJ4UmUv.js +1208 -0
  4. package/dist/chunks/data-table-toolbar-B-5J2Ozl.js +736 -0
  5. package/dist/core/accordion.d.ts +16 -0
  6. package/dist/core/accordion.js +108 -0
  7. package/dist/core/alert.d.ts +20 -0
  8. package/dist/core/alert.js +63 -0
  9. package/dist/core/anchor.d.ts +35 -0
  10. package/dist/core/anchor.js +39 -0
  11. package/dist/core/breadcrumb.d.ts +30 -0
  12. package/dist/core/breadcrumb.js +67 -0
  13. package/dist/core/button.d.ts +8 -1
  14. package/dist/core/button.js +23 -18
  15. package/dist/core/calendar.d.ts +29 -0
  16. package/dist/core/calendar.js +180 -0
  17. package/dist/core/card.d.ts +5 -1
  18. package/dist/core/card.js +33 -29
  19. package/dist/core/checkbox.d.ts +19 -0
  20. package/dist/core/checkbox.js +55 -0
  21. package/dist/core/combobox.d.ts +32 -0
  22. package/dist/core/combobox.js +183 -0
  23. package/dist/core/date-picker.d.ts +41 -0
  24. package/dist/core/date-picker.js +202 -0
  25. package/dist/core/dialog.d.ts +8 -0
  26. package/dist/core/dialog.js +59 -61
  27. package/dist/core/drawer.d.ts +34 -0
  28. package/dist/core/drawer.js +129 -0
  29. package/dist/core/dropdown.d.ts +8 -4
  30. package/dist/core/dropdown.js +136 -51
  31. package/dist/core/file-upload.d.ts +28 -0
  32. package/dist/core/file-upload.js +111 -0
  33. package/dist/core/index.d.ts +21 -0
  34. package/dist/core/list-nav.d.ts +27 -0
  35. package/dist/core/list-nav.js +51 -0
  36. package/dist/core/modal.d.ts +14 -5
  37. package/dist/core/modal.js +163 -156
  38. package/dist/core/overlay.d.ts +93 -0
  39. package/dist/core/overlay.js +189 -0
  40. package/dist/core/popover.d.ts +29 -0
  41. package/dist/core/popover.js +124 -0
  42. package/dist/core/progress.d.ts +21 -0
  43. package/dist/core/progress.js +59 -0
  44. package/dist/core/radio.d.ts +20 -0
  45. package/dist/core/radio.js +115 -0
  46. package/dist/core/select.d.ts +6 -0
  47. package/dist/core/select.js +178 -97
  48. package/dist/core/skeleton.d.ts +20 -0
  49. package/dist/core/skeleton.js +41 -0
  50. package/dist/core/spinner.d.ts +15 -0
  51. package/dist/core/spinner.js +41 -0
  52. package/dist/core/tabs.js +82 -53
  53. package/dist/core/timeline.d.ts +22 -0
  54. package/dist/core/timeline.js +57 -0
  55. package/dist/core/toast.d.ts +36 -0
  56. package/dist/core/toast.js +123 -0
  57. package/dist/core/tooltip.d.ts +23 -0
  58. package/dist/core/tooltip.js +96 -0
  59. package/dist/core/tree-view.d.ts +34 -0
  60. package/dist/core/tree-view.js +133 -0
  61. package/dist/core.js +152 -62
  62. package/dist/data-table/data-table.d.ts +22 -1
  63. package/dist/data-table.js +1 -1
  64. package/dist/forms/form.d.ts +8 -0
  65. package/dist/forms.js +213 -200
  66. package/dist/i18n/index.d.ts +83 -0
  67. package/dist/i18n.js +99 -0
  68. package/dist/index.d.ts +1 -0
  69. package/dist/index.js +256 -156
  70. package/dist/prui-utilities.css +1 -1
  71. package/dist/prui.css +111 -4
  72. package/dist/theme/base.css +110 -3
  73. package/dist/theme/index.d.ts +27 -0
  74. package/dist/theme.js +86 -58
  75. package/package.json +9 -2
  76. package/dist/chunks/auth-shell-BG5vx9eG.js +0 -1054
  77. package/dist/chunks/data-table-toolbar-BUy2EWPy.js +0 -581
package/dist/forms.js CHANGED
@@ -1,304 +1,317 @@
1
1
  import { jsx as v, jsxs as O } from "react/jsx-runtime";
2
- import * as m from "react";
3
- import { Button as L } from "./core/button.js";
4
- import { Textarea as q, Input as z } from "./core/input.js";
5
- import { Label as H } from "./core/label.js";
6
- import { Select as J } from "./core/select.js";
7
- import { Switch as K } from "./core/switch.js";
8
- import { cn as k } from "./core/cn.js";
9
- const M = /* @__PURE__ */ new Map();
10
- function Q(t) {
11
- return M.set(t.id, t), () => {
12
- M.get(t.id) === t && M.delete(t.id);
2
+ import * as p from "react";
3
+ import { Button as z } from "./core/button.js";
4
+ import { Textarea as W, Input as H } from "./core/input.js";
5
+ import { Label as J } from "./core/label.js";
6
+ import { Select as K } from "./core/select.js";
7
+ import { Switch as Q } from "./core/switch.js";
8
+ import { cn as N } from "./core/cn.js";
9
+ import { getPruiDictionary as U } from "./i18n.js";
10
+ const T = /* @__PURE__ */ new Map();
11
+ function X(e) {
12
+ return T.set(e.id, e), () => {
13
+ T.get(e.id) === e && T.delete(e.id);
13
14
  };
14
15
  }
15
- function R(t) {
16
- return M.get(t);
16
+ function A(e) {
17
+ return T.get(e);
17
18
  }
18
- function at() {
19
- return [...M.keys()];
19
+ function pe() {
20
+ return [...T.keys()];
20
21
  }
21
- const G = m.createContext(null);
22
- function U() {
23
- const t = m.useContext(G);
24
- if (!t) throw new Error("Form components must be rendered inside <Form>.");
25
- return t;
22
+ const Y = () => U(), M = (e, r) => e.replace(/\{(\w+)\}/g, (s, o) => String(r[o] ?? ""));
23
+ let R = !1;
24
+ function Z() {
25
+ var e;
26
+ R || typeof process < "u" && ((e = process.env) == null ? void 0 : e.NODE_ENV) === "test" || (R = !0, console.warn(
27
+ "[prui] The registry-driven <Form> from '@skiddph/prui/forms' is deprecated. Migrate to the schema-driven <Form> from '@skiddph/prui/app' — see the Forms page migration notes. This implementation keeps working and will not be removed before v2."
28
+ ));
26
29
  }
27
- function _(t) {
28
- return t == null || t === "" || Array.isArray(t) && t.length === 0;
30
+ const q = p.createContext(null);
31
+ function ee() {
32
+ const e = p.useContext(q);
33
+ if (!e) throw new Error("Form components must be rendered inside <Form>.");
34
+ return e;
29
35
  }
30
- function D(t, r, o) {
31
- var i;
32
- return r.required && _(t) ? `${r.label} is required.` : _(t) ? null : r.minLength !== void 0 && String(t).length < r.minLength ? `${r.label} must be at least ${r.minLength} characters.` : r.maxLength !== void 0 && String(t).length > r.maxLength ? `${r.label} must be at most ${r.maxLength} characters.` : r.min !== void 0 && typeof t == "number" && t < r.min ? `${r.label} must be ${r.min} or more.` : r.max !== void 0 && typeof t == "number" && t > r.max ? `${r.label} must be ${r.max} or less.` : r.pattern && !r.pattern.test(String(t)) ? r.patternMessage ?? `${r.label} has an invalid format.` : ((i = r.validate) == null ? void 0 : i.call(r, t, o)) ?? null;
36
+ function G(e) {
37
+ return e == null || e === "" || Array.isArray(e) && e.length === 0;
33
38
  }
34
- function ut({ id: t, children: r, schema: o, initialValues: i = {}, onSubmit: p, onReset: g, validateOnChange: a = !0, className: h }) {
35
- const [s, d] = m.useState({ ...i }), [w, b] = m.useState({}), [T, y] = m.useState(null), S = m.useRef(/* @__PURE__ */ new Map()), P = m.useRef(/* @__PURE__ */ new Set()), C = m.useRef({ ...i }), I = () => {
36
- let e = !0;
37
- for (const [l, u] of S.current)
38
- if (D(s[l], u, s) !== null) {
39
- e = !1;
39
+ function _(e, r, s) {
40
+ var c;
41
+ const o = Y();
42
+ return r.required && G(e) ? M(o.requiredField, { label: r.label }) : G(e) ? null : r.minLength !== void 0 && String(e).length < r.minLength ? M(o.minLength, { label: r.label, min: r.minLength }) : r.maxLength !== void 0 && String(e).length > r.maxLength ? M(o.maxLength, { label: r.label, max: r.maxLength }) : r.min !== void 0 && typeof e == "number" && e < r.min ? M(o.minNumber, { label: r.label, min: r.min }) : r.max !== void 0 && typeof e == "number" && e > r.max ? M(o.maxNumber, { label: r.label, max: r.max }) : r.pattern && !r.pattern.test(String(e)) ? r.patternMessage ?? M(o.invalidFormat, { label: r.label }) : ((c = r.validate) == null ? void 0 : c.call(r, e, s)) ?? null;
43
+ }
44
+ function ge({ id: e, children: r, schema: s, initialValues: o = {}, onSubmit: c, onReset: g, validateOnChange: a = !0, className: h }) {
45
+ p.useEffect(() => {
46
+ Z();
47
+ }, []);
48
+ const [l, m] = p.useState({ ...o }), [w, b] = p.useState({}), [L, y] = p.useState(null), S = p.useRef(/* @__PURE__ */ new Map()), C = p.useRef(/* @__PURE__ */ new Set()), D = p.useRef({ ...o }), $ = () => {
49
+ let t = !0;
50
+ for (const [i, u] of S.current)
51
+ if (_(l[i], u, l) !== null) {
52
+ t = !1;
40
53
  break;
41
54
  }
42
- e && o && (o.safeParse(s).success || (e = !1));
43
- const n = Object.keys(s).some((l) => s[l] !== C.current[l]) || Object.keys(C.current).length !== Object.keys(s).length;
44
- return { isValid: e, isDirty: n, errorCount: Object.keys(w).length, values: { ...s } };
45
- }, V = (e) => {
46
- var l;
55
+ t && s && (s.safeParse(l).success || (t = !1));
56
+ const n = Object.keys(l).some((i) => l[i] !== D.current[i]) || Object.keys(D.current).length !== Object.keys(l).length;
57
+ return { isValid: t, isDirty: n, errorCount: Object.keys(w).length, values: { ...l } };
58
+ }, V = (t) => {
59
+ var i;
47
60
  const n = {};
48
61
  for (const [u, f] of S.current) {
49
- const x = D(e[u], f, e);
62
+ const x = _(t[u], f, t);
50
63
  x && (n[u] = x);
51
64
  }
52
- if (o) {
53
- const u = o.safeParse(e);
65
+ if (s) {
66
+ const u = s.safeParse(t);
54
67
  if (!u.success)
55
- for (const f of ((l = u.error) == null ? void 0 : l.issues) ?? []) {
68
+ for (const f of ((i = u.error) == null ? void 0 : i.issues) ?? []) {
56
69
  const x = String(f.path[0] ?? "");
57
70
  x && !n[x] ? n[x] = f.message : x || (n.__form__ = f.message);
58
71
  }
59
72
  }
60
73
  return n;
61
- }, A = async () => {
62
- const e = V(s);
63
- if (b(e), Object.keys(e).length > 0)
74
+ }, I = async () => {
75
+ const t = V(l);
76
+ if (b(t), Object.keys(t).length > 0)
64
77
  return y(null), !1;
65
78
  y(null);
66
79
  try {
67
- return await (p == null ? void 0 : p({ ...s })), !0;
80
+ return await (c == null ? void 0 : c({ ...l })), !0;
68
81
  } catch (n) {
69
82
  return y(n instanceof Error ? n.message : String(n)), !1;
70
83
  }
84
+ }, E = () => {
85
+ m({ ...D.current }), b({}), y(null), g == null || g();
71
86
  }, j = () => {
72
- d({ ...C.current }), b({}), y(null), g == null || g();
73
- }, B = () => {
74
- d({}), b({}), y(null);
75
- }, F = (e, n) => d((l) => ({ ...l, [e]: n })), E = () => {
76
- const e = I();
77
- for (const n of P.current) n(e);
78
- }, $ = m.useMemo(
87
+ m({}), b({}), y(null);
88
+ }, F = (t, n) => m((i) => ({ ...i, [t]: n })), B = () => {
89
+ const t = $();
90
+ for (const n of C.current) n(t);
91
+ }, k = p.useMemo(
79
92
  () => ({
80
- id: t,
81
- submit: async () => A(),
82
- reset: j,
83
- clear: B,
93
+ id: e,
94
+ submit: async () => I(),
95
+ reset: E,
96
+ clear: j,
84
97
  setField: F,
85
- getValue: (e) => s[e],
86
- getState: () => I(),
87
- subscribe: (e) => (P.current.add(e), () => P.current.delete(e))
98
+ getValue: (t) => l[t],
99
+ getState: () => $(),
100
+ subscribe: (t) => (C.current.add(t), () => C.current.delete(t))
88
101
  }),
89
102
  // eslint-disable-next-line react-hooks/exhaustive-deps -- the api closes over the latest render state
90
- [t, s, w, o, p, g]
103
+ [e, l, w, s, c, g]
91
104
  );
92
- m.useEffect(() => Q($), [$]), m.useEffect(() => {
93
- E();
105
+ p.useEffect(() => X(k), [k]), p.useEffect(() => {
106
+ B();
94
107
  });
95
- const N = {
96
- id: t,
97
- getValue: (e) => s[e],
98
- setValue: (e, n) => {
99
- if (d((l) => ({ ...l, [e]: n })), a) {
100
- const l = S.current.get(e);
101
- if (l) {
102
- const u = D(n, l, { ...s, [e]: n });
108
+ const P = {
109
+ id: e,
110
+ getValue: (t) => l[t],
111
+ setValue: (t, n) => {
112
+ if (m((i) => ({ ...i, [t]: n })), a) {
113
+ const i = S.current.get(t);
114
+ if (i) {
115
+ const u = _(n, i, { ...l, [t]: n });
103
116
  b((f) => {
104
- if (u) return { ...f, [e]: u };
105
- if (!(e in f)) return f;
117
+ if (u) return { ...f, [t]: u };
118
+ if (!(t in f)) return f;
106
119
  const x = { ...f };
107
- return delete x[e], x;
120
+ return delete x[t], x;
108
121
  });
109
122
  }
110
123
  }
111
124
  y(null);
112
125
  },
113
- registerField: (e, n) => S.current.set(e, n),
114
- unregisterField: (e) => S.current.delete(e),
115
- errorFor: (e) => w[e],
116
- markTouched: (e) => {
117
- const n = S.current.get(e);
126
+ registerField: (t, n) => S.current.set(t, n),
127
+ unregisterField: (t) => S.current.delete(t),
128
+ errorFor: (t) => w[t],
129
+ markTouched: (t) => {
130
+ const n = S.current.get(t);
118
131
  if (n && a) {
119
- const l = D(s[e], n, s);
132
+ const i = _(l[t], n, l);
120
133
  b((u) => {
121
- if (l) return { ...u, [e]: l };
122
- if (!(e in u)) return u;
134
+ if (i) return { ...u, [t]: i };
135
+ if (!(t in u)) return u;
123
136
  const f = { ...u };
124
- return delete f[e], f;
137
+ return delete f[t], f;
125
138
  });
126
139
  }
127
140
  },
128
- formError: T
141
+ formError: L
129
142
  };
130
- return /* @__PURE__ */ v(G.Provider, { value: N, children: /* @__PURE__ */ v(
143
+ return /* @__PURE__ */ v(q.Provider, { value: P, children: /* @__PURE__ */ v(
131
144
  "form",
132
145
  {
133
- id: t,
134
- className: k("prui-form flex flex-col gap-4", h),
146
+ id: e,
147
+ className: N("prui-form flex flex-col gap-4", h),
135
148
  noValidate: !0,
136
- onSubmit: (e) => {
137
- e.preventDefault(), A();
149
+ onSubmit: (t) => {
150
+ t.preventDefault(), I();
138
151
  },
139
- onReset: (e) => {
140
- e.preventDefault(), j();
152
+ onReset: (t) => {
153
+ t.preventDefault(), E();
141
154
  },
142
155
  children: r
143
156
  }
144
157
  ) });
145
158
  }
146
- const W = { 1: "grid-cols-1", 2: "grid-cols-2", 3: "grid-cols-3", 4: "grid-cols-4" }, X = { 2: "sm:grid-cols-2", 3: "sm:grid-cols-3", 4: "sm:grid-cols-4" }, Y = { 2: "md:grid-cols-2", 3: "md:grid-cols-3", 4: "md:grid-cols-4" }, Z = { 2: "lg:grid-cols-2", 3: "lg:grid-cols-3", 4: "lg:grid-cols-4" };
147
- function ct({ label: t, description: r, columns: o = 1, gap: i = "md", children: p, className: g }) {
148
- const a = typeof o == "number" ? { base: o } : o, h = a.base ?? 1, s = [
159
+ const te = { 1: "grid-cols-1", 2: "grid-cols-2", 3: "grid-cols-3", 4: "grid-cols-4" }, re = { 2: "sm:grid-cols-2", 3: "sm:grid-cols-3", 4: "sm:grid-cols-4" }, ne = { 2: "md:grid-cols-2", 3: "md:grid-cols-3", 4: "md:grid-cols-4" }, oe = { 2: "lg:grid-cols-2", 3: "lg:grid-cols-3", 4: "lg:grid-cols-4" };
160
+ function be({ label: e, description: r, columns: s = 1, gap: o = "md", children: c, className: g }) {
161
+ const a = typeof s == "number" ? { base: s } : s, h = a.base ?? 1, l = [
149
162
  "grid",
150
- W[h],
151
- a.sm && a.sm > 1 ? X[a.sm] : null,
152
- a.md && a.md > 1 ? Y[a.md] : null,
153
- a.lg && a.lg > 1 ? Z[a.lg] : null
154
- ].filter(Boolean), d = i === "sm" ? "gap-x-2 gap-y-3" : i === "lg" ? "gap-x-6 gap-y-4" : "gap-x-4 gap-y-3";
163
+ te[h],
164
+ a.sm && a.sm > 1 ? re[a.sm] : null,
165
+ a.md && a.md > 1 ? ne[a.md] : null,
166
+ a.lg && a.lg > 1 ? oe[a.lg] : null
167
+ ].filter(Boolean), m = o === "sm" ? "gap-x-2 gap-y-3" : o === "lg" ? "gap-x-6 gap-y-4" : "gap-x-4 gap-y-3";
155
168
  return /* @__PURE__ */ O(
156
169
  "div",
157
170
  {
158
171
  role: "group",
159
- className: k("prui-form-group rounded-[var(--prui-radius)] border border-[var(--prui-line)] bg-[var(--prui-surface)] p-4", g),
172
+ className: N("prui-form-group rounded-[var(--prui-radius)] border border-[var(--prui-line)] bg-[var(--prui-surface)] p-4", g),
160
173
  children: [
161
- t ? /* @__PURE__ */ v("div", { className: "text-sm font-semibold text-[var(--prui-fg)]", children: t }) : null,
174
+ e ? /* @__PURE__ */ v("div", { className: "text-sm font-semibold text-[var(--prui-fg)]", children: e }) : null,
162
175
  r ? /* @__PURE__ */ v("div", { className: "mb-1 text-xs text-[var(--prui-dim)]", children: r }) : null,
163
- /* @__PURE__ */ v("div", { className: k(...s, d), children: p })
176
+ /* @__PURE__ */ v("div", { className: N(...l, m), children: c })
164
177
  ]
165
178
  }
166
179
  );
167
180
  }
168
- function dt({
169
- name: t,
170
- label: r = t,
171
- type: o = "text",
172
- placeholder: i,
173
- required: p,
181
+ function xe({
182
+ name: e,
183
+ label: r = e,
184
+ type: s = "text",
185
+ placeholder: o,
186
+ required: c,
174
187
  disabled: g,
175
188
  readOnly: a,
176
189
  autoFocus: h,
177
- minLength: s,
178
- maxLength: d,
190
+ minLength: l,
191
+ maxLength: m,
179
192
  min: w,
180
193
  max: b,
181
- step: T,
194
+ step: L,
182
195
  pattern: y,
183
196
  patternMessage: S,
184
- options: P,
185
- rows: C = 3,
186
- help: I,
197
+ options: C,
198
+ rows: D = 3,
199
+ help: $,
187
200
  message: V,
188
- validate: A,
189
- onChange: j,
190
- className: B
201
+ validate: I,
202
+ onChange: E,
203
+ className: j
191
204
  }) {
192
- const F = U();
193
- m.useEffect(() => (F.registerField(t, { label: r, required: p, validate: A, minLength: s, maxLength: d, min: w, max: b, pattern: y, patternMessage: S }), () => F.unregisterField(t)), [t]);
194
- const E = F.getValue(t), $ = F.errorFor(t), N = (c) => {
195
- F.setValue(t, c), j == null || j(c);
196
- }, e = `prui-field-${F.id}-${t}`, n = `${e}-msg`, l = $ ?? (V == null ? void 0 : V.message) ?? I, u = $ ? "error" : V ? V.type ?? "info" : "help", f = {
205
+ const F = ee();
206
+ p.useEffect(() => (F.registerField(e, { label: r, required: c, validate: I, minLength: l, maxLength: m, min: w, max: b, pattern: y, patternMessage: S }), () => F.unregisterField(e)), [e]);
207
+ const B = F.getValue(e), k = F.errorFor(e), P = (d) => {
208
+ F.setValue(e, d), E == null || E(d);
209
+ }, t = `prui-field-${F.id}-${e}`, n = `${t}-msg`, i = k ?? (V == null ? void 0 : V.message) ?? $, u = k ? "error" : V ? V.type ?? "info" : "help", f = {
197
210
  error: "text-[var(--prui-danger)]",
198
211
  warning: "text-[var(--prui-warn)]",
199
212
  info: "text-[var(--prui-dim)]",
200
213
  success: "text-[var(--prui-ok)]",
201
214
  help: "text-[var(--prui-dim)]"
202
- }[u], x = o === "textarea" ? /* @__PURE__ */ v(
203
- q,
215
+ }[u], x = s === "textarea" ? /* @__PURE__ */ v(
216
+ W,
204
217
  {
205
- id: e,
206
- rows: C,
207
- placeholder: i,
218
+ id: t,
219
+ rows: D,
220
+ placeholder: o,
208
221
  disabled: g,
209
222
  readOnly: a,
210
223
  autoFocus: h,
211
- minLength: s,
212
- maxLength: d,
213
- className: k("w-full", B),
214
- value: String(E ?? ""),
215
- onChange: (c) => N(c.target.value),
216
- onBlur: () => F.markTouched(t),
217
- "aria-invalid": $ ? !0 : void 0,
218
- "aria-describedby": l ? n : void 0
224
+ minLength: l,
225
+ maxLength: m,
226
+ className: N("w-full", j),
227
+ value: String(B ?? ""),
228
+ onChange: (d) => P(d.target.value),
229
+ onBlur: () => F.markTouched(e),
230
+ "aria-invalid": k ? !0 : void 0,
231
+ "aria-describedby": i ? n : void 0
219
232
  }
220
- ) : o === "select" ? /* @__PURE__ */ v(
221
- J,
233
+ ) : s === "select" ? /* @__PURE__ */ v(
234
+ K,
222
235
  {
223
- id: e,
224
- className: k("w-full", B),
225
- options: (P ?? []).map((c) => ({ label: c.label, value: c.value, disabled: c.disabled })),
226
- placeholder: i,
236
+ id: t,
237
+ className: N("w-full", j),
238
+ options: (C ?? []).map((d) => ({ label: d.label, value: d.value, disabled: d.disabled })),
239
+ placeholder: o,
227
240
  disabled: g,
228
- value: String(E ?? ""),
229
- onChange: (c) => N(c),
241
+ value: String(B ?? ""),
242
+ onChange: (d) => P(d),
230
243
  "aria-label": r
231
244
  }
232
- ) : o === "switch" || o === "checkbox" ? /* @__PURE__ */ v(
233
- K,
245
+ ) : s === "switch" || s === "checkbox" ? /* @__PURE__ */ v(
246
+ Q,
234
247
  {
235
- id: e,
236
- checked: !!E,
248
+ id: t,
249
+ checked: !!B,
237
250
  disabled: g,
238
- onChange: (c) => N(c),
251
+ onChange: (d) => P(d),
239
252
  "aria-label": r
240
253
  }
241
254
  ) : /* @__PURE__ */ v(
242
- z,
255
+ H,
243
256
  {
244
- id: e,
245
- type: o,
246
- placeholder: i,
257
+ id: t,
258
+ type: s,
259
+ placeholder: o,
247
260
  disabled: g,
248
261
  readOnly: a,
249
262
  autoFocus: h,
250
- minLength: s,
251
- maxLength: d,
263
+ minLength: l,
264
+ maxLength: m,
252
265
  min: w,
253
266
  max: b,
254
- step: T,
267
+ step: L,
255
268
  pattern: y == null ? void 0 : y.source,
256
- className: k("w-full", B),
257
- value: String(E ?? ""),
258
- onChange: (c) => N(o === "number" ? c.target.value === "" ? "" : Number(c.target.value) : c.target.value),
259
- onBlur: () => F.markTouched(t),
260
- "aria-invalid": $ ? !0 : void 0,
261
- "aria-describedby": l ? n : void 0
269
+ className: N("w-full", j),
270
+ value: String(B ?? ""),
271
+ onChange: (d) => P(s === "number" ? d.target.value === "" ? "" : Number(d.target.value) : d.target.value),
272
+ onBlur: () => F.markTouched(e),
273
+ "aria-invalid": k ? !0 : void 0,
274
+ "aria-describedby": i ? n : void 0
262
275
  }
263
276
  );
264
- return /* @__PURE__ */ O("div", { className: k("prui-form-input flex flex-col gap-1.5", B), "data-testid": `form-input-${t}`, children: [
265
- r ? /* @__PURE__ */ O(H, { htmlFor: e, children: [
277
+ return /* @__PURE__ */ O("div", { className: N("prui-form-input flex flex-col gap-1.5", j), "data-testid": `form-input-${e}`, children: [
278
+ r ? /* @__PURE__ */ O(J, { htmlFor: t, children: [
266
279
  r,
267
- p ? /* @__PURE__ */ v("span", { className: "ml-0.5 text-[var(--prui-danger)]", children: "*" }) : null
280
+ c ? /* @__PURE__ */ v("span", { className: "ml-0.5 text-[var(--prui-danger)]", children: "*" }) : null
268
281
  ] }) : null,
269
282
  x,
270
- l ? /* @__PURE__ */ v("p", { id: n, className: k("text-xs", f), role: $ ? "alert" : void 0, children: l }) : null
283
+ i ? /* @__PURE__ */ v("p", { id: n, className: N("text-xs", f), role: k ? "alert" : void 0, children: i }) : null
271
284
  ] });
272
285
  }
273
- function tt(t) {
274
- const [r, o] = m.useState(() => {
275
- var i;
276
- return ((i = R(t)) == null ? void 0 : i.getState()) ?? null;
286
+ function se(e) {
287
+ const [r, s] = p.useState(() => {
288
+ var o;
289
+ return ((o = A(e)) == null ? void 0 : o.getState()) ?? null;
277
290
  });
278
- return m.useEffect(() => {
279
- const i = R(t);
280
- if (!i) {
281
- o(null);
291
+ return p.useEffect(() => {
292
+ const o = A(e);
293
+ if (!o) {
294
+ s(null);
282
295
  return;
283
296
  }
284
- return o(i.getState()), i.subscribe((p) => o(p));
285
- }, [t]), r;
297
+ return s(o.getState()), o.subscribe((c) => s(c));
298
+ }, [e]), r;
286
299
  }
287
- function ft({ form: t, action: r = "submit", disableWhen: o = "never", variant: i, size: p, disabled: g, children: a, onClick: h, className: s }) {
288
- const d = tt(t), w = g || (o === "invalid" && d ? !d.isValid : !1) || (o === "pristine" && d ? !d.isDirty : !1);
300
+ function ve({ form: e, action: r = "submit", disableWhen: s = "never", variant: o, size: c, disabled: g, children: a, onClick: h, className: l }) {
301
+ const m = se(e), w = g || (s === "invalid" && m ? !m.isValid : !1) || (s === "pristine" && m ? !m.isDirty : !1);
289
302
  return /* @__PURE__ */ v(
290
- L,
303
+ z,
291
304
  {
292
305
  type: "button",
293
- variant: i ?? "default",
294
- size: p,
306
+ variant: o ?? "default",
307
+ size: c,
295
308
  disabled: w,
296
- className: s,
297
- "data-testid": `form-button-${t}-${r}`,
309
+ className: l,
310
+ "data-testid": `form-button-${e}-${r}`,
298
311
  onClick: () => {
299
- const b = R(t);
312
+ const b = A(e);
300
313
  if (!b) {
301
- console.warn(`[prui] FormButton: no <Form id="${t}"> is mounted.`);
314
+ console.warn(`[prui] FormButton: no <Form id="${e}"> is mounted.`);
302
315
  return;
303
316
  }
304
317
  r === "submit" ? b.submit() : r === "reset" ? b.reset() : r === "clear" && b.clear(), h == null || h();
@@ -307,7 +320,7 @@ function ft({ form: t, action: r = "submit", disableWhen: o = "never", variant:
307
320
  }
308
321
  );
309
322
  }
310
- const mt = {
323
+ const ye = {
311
324
  name: "Form",
312
325
  props: [
313
326
  { name: "id", type: "string", default: null, control: "text" },
@@ -316,7 +329,7 @@ const mt = {
316
329
  { name: "onSubmit", type: "(values) => void | Promise<void>", default: null, control: "none" },
317
330
  { name: "validateOnChange", type: "boolean", default: "true", control: "boolean" }
318
331
  ]
319
- }, pt = {
332
+ }, he = {
320
333
  name: "FormGroup",
321
334
  props: [
322
335
  { name: "label", type: "string", default: null, control: "text" },
@@ -324,7 +337,7 @@ const mt = {
324
337
  { name: "columns", type: "number | { base?, sm?, md?, lg? }", default: "1", control: "number" },
325
338
  { name: "gap", type: "'sm' | 'md' | 'lg'", default: "'md'", control: "select", options: ["sm", "md", "lg"] }
326
339
  ]
327
- }, gt = {
340
+ }, Fe = {
328
341
  name: "FormInput",
329
342
  props: [
330
343
  { name: "name", type: "string", default: null, control: "text" },
@@ -336,7 +349,7 @@ const mt = {
336
349
  { name: "options", type: "{ label, value }[]", default: "select/switch only", control: "object" },
337
350
  { name: "validate", type: "(value, values) => string | null", default: null, control: "none" }
338
351
  ]
339
- }, bt = {
352
+ }, we = {
340
353
  name: "FormButton",
341
354
  props: [
342
355
  { name: "form", type: "string (id of the target <Form>)", default: null, control: "text" },
@@ -345,20 +358,20 @@ const mt = {
345
358
  { name: "variant", type: "ButtonVariant", default: "'default'", control: "select", options: ["primary", "default", "ghost", "danger", "outline", "soft", "link"] }
346
359
  ]
347
360
  };
348
- function xt(t) {
349
- return R(t);
361
+ function Se(e) {
362
+ return A(e);
350
363
  }
351
364
  export {
352
- ut as Form,
353
- ft as FormButton,
354
- ct as FormGroup,
355
- dt as FormInput,
356
- bt as formButtonPropsMeta,
357
- pt as formGroupPropsMeta,
358
- at as formIds,
359
- gt as formInputPropsMeta,
360
- mt as formPropsMeta,
361
- R as getFormApi,
362
- Q as registerForm,
363
- xt as useFormApi
365
+ ge as Form,
366
+ ve as FormButton,
367
+ be as FormGroup,
368
+ xe as FormInput,
369
+ we as formButtonPropsMeta,
370
+ he as formGroupPropsMeta,
371
+ pe as formIds,
372
+ Fe as formInputPropsMeta,
373
+ ye as formPropsMeta,
374
+ A as getFormApi,
375
+ X as registerForm,
376
+ Se as useFormApi
364
377
  };
@@ -0,0 +1,83 @@
1
+ import * as React from "react";
2
+ /**
3
+ * PRUI internationalization.
4
+ *
5
+ * Every user-facing string PRUI renders comes from a dictionary. The
6
+ * default dictionary is English; apps override it wholesale or per-key via
7
+ * <PruiProvider dictionary={...}> or setPruiDictionary(). Components read
8
+ * strings through usePruiI18n().t("key") so translations need no re-render
9
+ * wiring beyond the provider.
10
+ */
11
+ export interface PruiDictionary {
12
+ close: string;
13
+ closeDialog: string;
14
+ cancel: string;
15
+ confirm: string;
16
+ delete: string;
17
+ save: string;
18
+ create: string;
19
+ edit: string;
20
+ loading: string;
21
+ commandPlaceholder: string;
22
+ commandNoMatches: string;
23
+ search: string;
24
+ noResults: string;
25
+ rowsPerPage: string;
26
+ page: string;
27
+ nextPage: string;
28
+ previousPage: string;
29
+ selectAllRows: string;
30
+ selectRow: string;
31
+ expandRow: string;
32
+ collapseRow: string;
33
+ yes: string;
34
+ no: string;
35
+ requiredField: string;
36
+ formErrorTitle: string;
37
+ invalidFormat: string;
38
+ minLength: string;
39
+ maxLength: string;
40
+ minNumber: string;
41
+ maxNumber: string;
42
+ newEntity: string;
43
+ editEntity: string;
44
+ searchEntity: string;
45
+ deleteConfirmMessage: string;
46
+ dismiss: string;
47
+ notifications: string;
48
+ mainNavigation: string;
49
+ openNavigation: string;
50
+ closeNavigation: string;
51
+ switchTheme: string;
52
+ expandSidebar: string;
53
+ collapseSidebar: string;
54
+ today: string;
55
+ clear: string;
56
+ apply: string;
57
+ dropFiles: string;
58
+ browseFiles: string;
59
+ removeFile: string;
60
+ of: string;
61
+ }
62
+ export declare const defaultDictionary: PruiDictionary;
63
+ /**
64
+ * Replace the active PRUI dictionary globally (no React context needed,
65
+ * useful outside components / at startup). Merge partials for per-key
66
+ * overrides.
67
+ */
68
+ export declare function setPruiDictionary(dict: Partial<PruiDictionary>): void;
69
+ /** Reset to the built-in English dictionary. */
70
+ export declare function resetPruiDictionary(): void;
71
+ /** The active dictionary (readonly snapshot). */
72
+ export declare function getPruiDictionary(): Readonly<PruiDictionary>;
73
+ /** Provider that scopes a dictionary to a subtree. */
74
+ export declare function PruiProvider({ dictionary, children, }: {
75
+ dictionary?: Partial<PruiDictionary>;
76
+ children?: React.ReactNode;
77
+ }): React.JSX.Element;
78
+ export interface PruiI18n {
79
+ /** The active dictionary. */
80
+ t: Readonly<PruiDictionary>;
81
+ }
82
+ /** Read the active PRUI dictionary (falls back to the global one). */
83
+ export declare function usePruiI18n(): PruiI18n;