@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.
- package/dist/core/combobox.js +123 -113
- package/dist/core/date-picker.d.ts +26 -5
- package/dist/core/date-picker.js +245 -133
- package/dist/core/dialog.d.ts +7 -0
- package/dist/core/dialog.js +63 -44
- package/dist/core/index.d.ts +3 -2
- package/dist/core/modal.js +133 -126
- package/dist/core/select.js +136 -128
- package/dist/core/time-picker.d.ts +68 -0
- package/dist/core/time-picker.js +305 -0
- package/dist/core/toast.js +73 -64
- package/dist/core.js +113 -105
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n.js +17 -11
- package/dist/index.js +210 -202
- package/dist/prui-utilities.css +1 -1
- package/dist/prui.css +1 -1
- package/package.json +1 -1
package/dist/core/combobox.js
CHANGED
|
@@ -1,158 +1,168 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import * as
|
|
3
|
-
import { ChevronDown as
|
|
4
|
-
import { cn as
|
|
5
|
-
import { useOverlayStack as
|
|
6
|
-
import { useAnchoredPosition as
|
|
7
|
-
import { endIndex as
|
|
8
|
-
const
|
|
9
|
-
options:
|
|
10
|
-
value:
|
|
11
|
-
defaultValue:
|
|
12
|
-
onChange:
|
|
1
|
+
import { jsxs as $, Fragment as Z, jsx as c } from "react/jsx-runtime";
|
|
2
|
+
import * as a from "react";
|
|
3
|
+
import { ChevronDown as _ } from "lucide-react";
|
|
4
|
+
import { cn as x } from "./cn.js";
|
|
5
|
+
import { useOverlayStack as K, useEscapeKey as ee, Portal as te } from "./overlay.js";
|
|
6
|
+
import { useAnchoredPosition as re } from "./anchor.js";
|
|
7
|
+
import { endIndex as ae, homeIndex as ne, moveIndex as j } from "./list-nav.js";
|
|
8
|
+
const oe = a.forwardRef(function({
|
|
9
|
+
options: d,
|
|
10
|
+
value: h,
|
|
11
|
+
defaultValue: P,
|
|
12
|
+
onChange: g,
|
|
13
13
|
onOpenChange: y,
|
|
14
|
-
placeholder:
|
|
15
|
-
emptyText:
|
|
16
|
-
noMatchText:
|
|
17
|
-
defaultOpen:
|
|
18
|
-
filter:
|
|
19
|
-
disabled:
|
|
20
|
-
id:
|
|
21
|
-
className:
|
|
22
|
-
onKeyDown:
|
|
23
|
-
...
|
|
24
|
-
},
|
|
25
|
-
var
|
|
26
|
-
const [
|
|
27
|
-
var t,
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
14
|
+
placeholder: U = "Type to search...",
|
|
15
|
+
emptyText: I,
|
|
16
|
+
noMatchText: z = "No matches.",
|
|
17
|
+
defaultOpen: F = !1,
|
|
18
|
+
filter: w,
|
|
19
|
+
disabled: D,
|
|
20
|
+
id: W,
|
|
21
|
+
className: A,
|
|
22
|
+
onKeyDown: k,
|
|
23
|
+
...S
|
|
24
|
+
}, v) {
|
|
25
|
+
var q, C;
|
|
26
|
+
const [H, O] = a.useState(P ?? ""), [n, Q] = a.useState(F), [m, R] = a.useState(null), [l, s] = a.useState(0), p = a.useRef(null), E = a.useRef(null), N = a.useRef(null), b = a.useId(), L = h !== void 0 ? h : H, V = (q = d.find((e) => e.value === L)) == null ? void 0 : q.label, u = (e) => {
|
|
27
|
+
var t, o;
|
|
28
|
+
if (Q(e), y == null || y(e), !e) {
|
|
29
|
+
R(null);
|
|
30
|
+
const i = document.activeElement;
|
|
31
|
+
i && ((t = E.current) != null && t.contains(i)) && ((o = p.current) == null || o.focus());
|
|
32
32
|
}
|
|
33
|
-
}, { setElement:
|
|
34
|
-
|
|
33
|
+
}, { setElement: B, isTop: G } = K(n);
|
|
34
|
+
ee(n, G, () => {
|
|
35
35
|
var e;
|
|
36
|
-
|
|
36
|
+
u(!1), (e = p.current) == null || e.focus();
|
|
37
|
+
}), a.useEffect(() => {
|
|
38
|
+
if (!n) return;
|
|
39
|
+
const e = (t) => {
|
|
40
|
+
var i, T;
|
|
41
|
+
const o = t.target;
|
|
42
|
+
(i = N.current) != null && i.contains(o) || (T = E.current) != null && T.contains(o) || u(!1);
|
|
43
|
+
};
|
|
44
|
+
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
37
45
|
});
|
|
38
|
-
const r =
|
|
39
|
-
if (
|
|
40
|
-
const e =
|
|
41
|
-
return e ?
|
|
42
|
-
}, [
|
|
43
|
-
|
|
46
|
+
const r = a.useMemo(() => {
|
|
47
|
+
if (m === null) return d;
|
|
48
|
+
const e = m.toLowerCase();
|
|
49
|
+
return e ? d.filter((t) => w ? w(t, e) : t.label.toLowerCase().includes(e)) : d;
|
|
50
|
+
}, [d, m, w]);
|
|
51
|
+
a.useEffect(() => {
|
|
44
52
|
s((e) => e < r.length ? e : Math.max(0, r.length - 1));
|
|
45
53
|
}, [r.length]);
|
|
46
|
-
const
|
|
54
|
+
const M = (e) => {
|
|
47
55
|
var t;
|
|
48
|
-
e.disabled || (
|
|
49
|
-
}, { ref:
|
|
50
|
-
if (
|
|
51
|
-
if (!
|
|
52
|
-
e.preventDefault(),
|
|
56
|
+
e.disabled || (h === void 0 && O(e.value), g == null || g(e.value), R(null), u(!1), (t = p.current) == null || t.focus());
|
|
57
|
+
}, J = N, { ref: X, position: f } = re({ active: n, anchorRef: J, side: "bottom", align: "start" }), Y = (e) => {
|
|
58
|
+
if (k == null || k(e), e.defaultPrevented) return;
|
|
59
|
+
if (!n && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
|
|
60
|
+
e.preventDefault(), u(!0);
|
|
53
61
|
return;
|
|
54
62
|
}
|
|
55
|
-
if (!
|
|
56
|
-
const t = (
|
|
57
|
-
var
|
|
58
|
-
return !((
|
|
63
|
+
if (!n) return;
|
|
64
|
+
const t = (o) => {
|
|
65
|
+
var i;
|
|
66
|
+
return !((i = r[o]) != null && i.disabled);
|
|
59
67
|
};
|
|
60
68
|
switch (e.key) {
|
|
61
69
|
case "ArrowDown":
|
|
62
|
-
e.preventDefault(), s(
|
|
70
|
+
e.preventDefault(), s(j(l, 1, r.length, { enabled: t }));
|
|
63
71
|
break;
|
|
64
72
|
case "ArrowUp":
|
|
65
|
-
e.preventDefault(), s(
|
|
73
|
+
e.preventDefault(), s(j(l, -1, r.length, { enabled: t }));
|
|
66
74
|
break;
|
|
67
75
|
case "Home":
|
|
68
|
-
r.length && (e.preventDefault(), s(
|
|
76
|
+
r.length && (e.preventDefault(), s(ne(r.length, t)));
|
|
69
77
|
break;
|
|
70
78
|
case "End":
|
|
71
|
-
r.length && (e.preventDefault(), s(
|
|
79
|
+
r.length && (e.preventDefault(), s(ae(r.length, t)));
|
|
72
80
|
break;
|
|
73
81
|
case "Enter":
|
|
74
|
-
e.preventDefault(), r[
|
|
82
|
+
e.preventDefault(), r[l] && M(r[l]);
|
|
75
83
|
break;
|
|
76
84
|
case "Tab":
|
|
77
|
-
|
|
85
|
+
u(!1);
|
|
78
86
|
break;
|
|
79
87
|
}
|
|
80
88
|
};
|
|
81
|
-
return /* @__PURE__ */
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
89
|
+
return /* @__PURE__ */ $(Z, { children: [
|
|
90
|
+
/* @__PURE__ */ $("div", { ref: N, className: x("prui-combobox relative inline-flex w-full items-center", A), children: [
|
|
91
|
+
/* @__PURE__ */ c(
|
|
92
|
+
"input",
|
|
93
|
+
{
|
|
94
|
+
ref: (e) => {
|
|
95
|
+
p.current = e, typeof v == "function" ? v(e) : v && (v.current = e);
|
|
96
|
+
},
|
|
97
|
+
id: W,
|
|
98
|
+
type: "text",
|
|
99
|
+
role: "combobox",
|
|
100
|
+
"aria-expanded": n,
|
|
101
|
+
"aria-haspopup": "listbox",
|
|
102
|
+
"aria-controls": n ? b : void 0,
|
|
103
|
+
"aria-activedescendant": n && r[l] ? `${b}-option-${l}` : void 0,
|
|
104
|
+
"aria-autocomplete": "list",
|
|
105
|
+
autoComplete: "off",
|
|
106
|
+
disabled: D,
|
|
107
|
+
placeholder: U,
|
|
108
|
+
className: x(
|
|
109
|
+
"prui-combobox-trigger h-9 w-full pr-8",
|
|
110
|
+
"bg-[var(--prui-background)] rounded-[var(--prui-radius)] px-3 text-sm text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)]",
|
|
111
|
+
"outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30",
|
|
112
|
+
"disabled:opacity-50 disabled:cursor-not-allowed cursor-text",
|
|
113
|
+
A
|
|
114
|
+
),
|
|
115
|
+
value: m !== null ? m : V ?? "",
|
|
116
|
+
onChange: (e) => {
|
|
117
|
+
R(e.target.value), u(!0), s(0);
|
|
118
|
+
},
|
|
119
|
+
onFocus: () => {
|
|
120
|
+
!n && !D && u(!0);
|
|
121
|
+
},
|
|
122
|
+
onKeyDown: Y,
|
|
123
|
+
...S
|
|
124
|
+
}
|
|
125
|
+
),
|
|
126
|
+
/* @__PURE__ */ c(_, { className: "pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--prui-dim)]", "aria-hidden": !0 })
|
|
127
|
+
] }),
|
|
128
|
+
n ? /* @__PURE__ */ c(te, { children: /* @__PURE__ */ c(
|
|
119
129
|
"div",
|
|
120
130
|
{
|
|
121
131
|
ref: (e) => {
|
|
122
|
-
E.current = e,
|
|
132
|
+
E.current = e, X(e), B(e);
|
|
123
133
|
},
|
|
124
|
-
id:
|
|
134
|
+
id: b,
|
|
125
135
|
role: "listbox",
|
|
126
|
-
"aria-label":
|
|
136
|
+
"aria-label": S["aria-label"] ?? "Options",
|
|
127
137
|
tabIndex: -1,
|
|
128
138
|
"data-state": "open",
|
|
129
|
-
className:
|
|
139
|
+
className: x(
|
|
130
140
|
"prui-combobox-content fixed z-[var(--prui-z-overlay)] min-w-40 max-h-60 overflow-auto p-1",
|
|
131
141
|
"border border-[var(--prui-line)] rounded-[var(--prui-radius)] bg-[var(--prui-surface)] shadow-[var(--prui-shadow-md)]"
|
|
132
142
|
),
|
|
133
143
|
style: {
|
|
134
144
|
top: (f == null ? void 0 : f.top) ?? -9999,
|
|
135
145
|
left: (f == null ? void 0 : f.left) ?? -9999,
|
|
136
|
-
minWidth: ((
|
|
146
|
+
minWidth: ((C = p.current) == null ? void 0 : C.offsetWidth) ?? 200
|
|
137
147
|
},
|
|
138
|
-
children:
|
|
139
|
-
const
|
|
140
|
-
return /* @__PURE__ */
|
|
148
|
+
children: d.length === 0 && I ? /* @__PURE__ */ c("div", { className: "px-3 py-2 text-sm text-[var(--prui-dim)]", children: I }) : r.length === 0 ? /* @__PURE__ */ c("div", { className: "px-3 py-2 text-sm text-[var(--prui-dim)]", role: "option", "aria-selected": "false", "aria-disabled": "true", children: z }) : r.map((e, t) => {
|
|
149
|
+
const o = L === e.value;
|
|
150
|
+
return /* @__PURE__ */ c(
|
|
141
151
|
"div",
|
|
142
152
|
{
|
|
143
|
-
id: `${
|
|
153
|
+
id: `${b}-option-${t}`,
|
|
144
154
|
role: "option",
|
|
145
|
-
"aria-selected":
|
|
155
|
+
"aria-selected": o,
|
|
146
156
|
"aria-disabled": e.disabled,
|
|
147
|
-
"data-active": t ===
|
|
148
|
-
"data-selected":
|
|
157
|
+
"data-active": t === l || void 0,
|
|
158
|
+
"data-selected": o || void 0,
|
|
149
159
|
tabIndex: -1,
|
|
150
160
|
onMouseEnter: () => s(t),
|
|
151
|
-
onClick: () =>
|
|
152
|
-
className:
|
|
161
|
+
onClick: () => M(e),
|
|
162
|
+
className: x(
|
|
153
163
|
"flex cursor-pointer items-center rounded-[calc(var(--prui-radius)-1px)] px-3 py-1.5 text-sm text-[var(--prui-fg)]",
|
|
154
|
-
t ===
|
|
155
|
-
|
|
164
|
+
t === l && "bg-[var(--prui-raise)]",
|
|
165
|
+
o && "font-medium",
|
|
156
166
|
e.disabled && "opacity-50 pointer-events-none"
|
|
157
167
|
),
|
|
158
168
|
children: e.label
|
|
@@ -164,8 +174,8 @@ const re = o.forwardRef(function({
|
|
|
164
174
|
) }) : null
|
|
165
175
|
] });
|
|
166
176
|
});
|
|
167
|
-
|
|
168
|
-
const
|
|
177
|
+
oe.displayName = "Combobox";
|
|
178
|
+
const me = {
|
|
169
179
|
name: "Combobox",
|
|
170
180
|
props: [
|
|
171
181
|
{ name: "options", type: "ComboboxOption[]", default: null, control: "object" },
|
|
@@ -178,6 +188,6 @@ const ce = {
|
|
|
178
188
|
]
|
|
179
189
|
};
|
|
180
190
|
export {
|
|
181
|
-
|
|
182
|
-
|
|
191
|
+
oe as Combobox,
|
|
192
|
+
me as comboboxPropsMeta
|
|
183
193
|
};
|
|
@@ -2,11 +2,14 @@ import { PropsMeta } from './props-meta';
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
/**
|
|
4
4
|
* DatePicker / DateRangePicker: a text trigger opening a Calendar popover.
|
|
5
|
-
* Values stay plain "YYYY-MM-DD"
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Values stay plain strings — "YYYY-MM-DD" by default, or
|
|
6
|
+
* "YYYY-MM-DD HH:mm(:ss)" with timepicker on — so they remain
|
|
7
|
+
* native-input compatible with no date library. The trigger is
|
|
8
|
+
* keyboard-operable (Enter/ArrowDown opens, Escape topmost closes and
|
|
9
|
+
* refocuses, typing a full value commits); clicking outside dismisses.
|
|
10
|
+
* The range picker anchors on the start date, supports a maxRange cap
|
|
11
|
+
* ("90d", "12w", "3m", "1y", or a plain number of days), and restarts
|
|
12
|
+
* when the picked end precedes the start.
|
|
10
13
|
*/
|
|
11
14
|
export interface DatePickerProps {
|
|
12
15
|
value?: string;
|
|
@@ -19,22 +22,40 @@ export interface DatePickerProps {
|
|
|
19
22
|
className?: string;
|
|
20
23
|
/** Accessible label for the trigger input. */
|
|
21
24
|
ariaLabel?: string;
|
|
25
|
+
/** Include a time panel; values become "YYYY-MM-DD HH:mm(:ss)". Default false. */
|
|
26
|
+
timepicker?: boolean;
|
|
27
|
+
/** Seconds column for the time panel (requires timepicker). */
|
|
28
|
+
seconds?: boolean;
|
|
29
|
+
/** Minute step for the time panel (requires timepicker). */
|
|
30
|
+
minuteStep?: number;
|
|
22
31
|
}
|
|
23
32
|
export declare const DatePicker: React.ForwardRefExoticComponent<DatePickerProps & React.RefAttributes<HTMLInputElement>>;
|
|
24
33
|
export interface DateRange {
|
|
25
34
|
from?: string;
|
|
26
35
|
to?: string;
|
|
27
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* maxRange caps the span between from and to. Accept a plain number of
|
|
39
|
+
* days, or a string with a unit: "90d" days, "12w" weeks, "3m" months
|
|
40
|
+
* (calendar-aware), "1y" years.
|
|
41
|
+
*/
|
|
42
|
+
export type MaxRange = number | `${number}d` | `${number}w` | `${number}m` | `${number}y` | (string & {});
|
|
28
43
|
export interface DateRangePickerProps {
|
|
29
44
|
value?: DateRange;
|
|
30
45
|
defaultValue?: DateRange;
|
|
31
46
|
onChange?: (range: DateRange) => void;
|
|
32
47
|
min?: string;
|
|
33
48
|
max?: string;
|
|
49
|
+
/** Cap the selectable span, e.g. 90, "90d", "12w", "3m", "1y". */
|
|
50
|
+
maxRange?: MaxRange;
|
|
34
51
|
placeholder?: string;
|
|
35
52
|
disabled?: boolean;
|
|
36
53
|
className?: string;
|
|
37
54
|
ariaLabel?: string;
|
|
55
|
+
/** Include time panels; values become "YYYY-MM-DD HH:mm(:ss)". Default false. */
|
|
56
|
+
timepicker?: boolean;
|
|
57
|
+
seconds?: boolean;
|
|
58
|
+
minuteStep?: number;
|
|
38
59
|
}
|
|
39
60
|
export declare const DateRangePicker: React.ForwardRefExoticComponent<DateRangePickerProps & React.RefAttributes<HTMLInputElement>>;
|
|
40
61
|
export declare const datePickerPropsMeta: PropsMeta;
|