@danieljoffe/shared-ui 0.0.1 → 0.1.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/index.js +110 -5358
- package/dist/lib/Alert.js +72 -0
- package/dist/lib/AspectRatio.js +31 -0
- package/dist/lib/Avatar.js +47 -0
- package/dist/lib/Badge.js +43 -0
- package/dist/lib/Breadcrumb.js +28 -0
- package/dist/lib/Button.js +82 -0
- package/dist/lib/CTACard.js +31 -0
- package/dist/lib/Card.js +91 -0
- package/dist/lib/Checkbox.js +75 -0
- package/dist/lib/Container.js +35 -0
- package/dist/lib/Divider.js +48 -0
- package/dist/lib/Dropdown.js +158 -0
- package/dist/lib/FormFieldError.js +8 -0
- package/dist/lib/Grid.js +67 -0
- package/dist/lib/GridBg.js +31 -0
- package/dist/lib/Heading.js +40 -0
- package/dist/lib/Input.js +55 -0
- package/dist/lib/Kbd.js +19 -0
- package/dist/lib/Loading.js +44 -0
- package/dist/lib/Modal.js +119 -0
- package/dist/lib/PageContainer.js +35 -0
- package/dist/lib/PageLayout.js +25 -0
- package/dist/lib/Pagination.js +111 -0
- package/dist/lib/ProgressBar.js +68 -0
- package/dist/lib/Section.js +58 -0
- package/dist/lib/SectionLabel.js +19 -0
- package/dist/lib/Select.js +67 -0
- package/dist/lib/Sidebar.js +97 -0
- package/dist/lib/Skeleton.js +63 -0
- package/dist/lib/Spacer.js +17 -0
- package/dist/lib/Spinner.js +39 -0
- package/dist/lib/Stack.js +59 -0
- package/dist/lib/StatsCard.js +79 -0
- package/dist/lib/StructuredData.js +15 -0
- package/dist/lib/Switch.js +69 -0
- package/dist/lib/Table.js +91 -0
- package/dist/lib/Tabs.js +101 -0
- package/dist/lib/Text.js +48 -0
- package/dist/lib/Textarea.js +50 -0
- package/dist/lib/ThemeProvider.js +54 -0
- package/dist/lib/ThemeToggle.js +29 -0
- package/dist/lib/Toast.js +95 -0
- package/dist/lib/Tooltip.js +70 -0
- package/dist/lib/index.js +112 -0
- package/dist/lib/styles/formStyles.js +24 -0
- package/dist/lib/styles/semanticVariants.js +27 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utils/ErrorBoundary.js +17 -0
- package/dist/lib/utils/ModalErrorBoundary.js +17 -0
- package/dist/lib/utils/cn.js +8 -0
- package/dist/lib/utils/index.js +10 -0
- package/dist/lib/utils/validateProps.js +7 -0
- package/package.json +7 -4
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsxs as d, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import { useId as b } from "react";
|
|
3
|
+
import { DISABLED as x, FOCUS_RING_OFFSET as v, FOCUS_RING as g } from "./styles/formStyles.js";
|
|
4
|
+
import { Text as I } from "./Text.js";
|
|
5
|
+
import { cn as o } from "./utils/cn.js";
|
|
6
|
+
function F({
|
|
7
|
+
checked: e,
|
|
8
|
+
onChange: c,
|
|
9
|
+
label: t,
|
|
10
|
+
error: r,
|
|
11
|
+
disabled: a = !1,
|
|
12
|
+
className: m,
|
|
13
|
+
id: f,
|
|
14
|
+
ref: u
|
|
15
|
+
}) {
|
|
16
|
+
const p = b(), i = f || p, s = t ? `${i}-label` : void 0, l = r ? `${i}-error` : void 0;
|
|
17
|
+
return /* @__PURE__ */ d("div", { children: [
|
|
18
|
+
/* @__PURE__ */ d("div", { className: "flex items-center gap-2", children: [
|
|
19
|
+
/* @__PURE__ */ n(
|
|
20
|
+
"button",
|
|
21
|
+
{
|
|
22
|
+
ref: u,
|
|
23
|
+
type: "button",
|
|
24
|
+
role: "switch",
|
|
25
|
+
id: i,
|
|
26
|
+
"aria-checked": e,
|
|
27
|
+
"aria-invalid": r ? "true" : void 0,
|
|
28
|
+
"aria-labelledby": s,
|
|
29
|
+
"aria-describedby": l,
|
|
30
|
+
disabled: a,
|
|
31
|
+
onClick: () => c(!e),
|
|
32
|
+
className: o(
|
|
33
|
+
"relative inline-flex h-6 w-11 items-center rounded-full transition-colors motion-reduce:transition-none",
|
|
34
|
+
g,
|
|
35
|
+
v,
|
|
36
|
+
x,
|
|
37
|
+
e ? "bg-brand-500" : "bg-border-strong",
|
|
38
|
+
r && "ring-1 ring-error",
|
|
39
|
+
m
|
|
40
|
+
),
|
|
41
|
+
children: /* @__PURE__ */ n(
|
|
42
|
+
"span",
|
|
43
|
+
{
|
|
44
|
+
className: o(
|
|
45
|
+
"inline-block h-4 w-4 transform rounded-full bg-surface transition-transform motion-reduce:transition-none",
|
|
46
|
+
e ? "translate-x-6" : "translate-x-1"
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
t && /* @__PURE__ */ n(
|
|
53
|
+
"span",
|
|
54
|
+
{
|
|
55
|
+
id: s,
|
|
56
|
+
className: o(
|
|
57
|
+
"text-text-primary select-none",
|
|
58
|
+
a && "opacity-50 cursor-not-allowed"
|
|
59
|
+
),
|
|
60
|
+
children: t
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
] }),
|
|
64
|
+
r && /* @__PURE__ */ n(I, { variant: "error", id: l, className: "mt-1.5", role: "alert", children: r })
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
F as Switch
|
|
69
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as t, jsxs as f } from "react/jsx-runtime";
|
|
3
|
+
import { Text as y } from "./Text.js";
|
|
4
|
+
import { cn as n } from "./utils/cn.js";
|
|
5
|
+
function D({
|
|
6
|
+
columns: s,
|
|
7
|
+
data: l,
|
|
8
|
+
onRowClick: r,
|
|
9
|
+
striped: x = !1,
|
|
10
|
+
className: h,
|
|
11
|
+
caption: i,
|
|
12
|
+
ariaLabel: m,
|
|
13
|
+
rowKey: o,
|
|
14
|
+
getRowAriaLabel: c
|
|
15
|
+
}) {
|
|
16
|
+
const b = {
|
|
17
|
+
left: "text-left",
|
|
18
|
+
center: "text-center",
|
|
19
|
+
right: "text-right"
|
|
20
|
+
}, p = (e, d) => {
|
|
21
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), r?.(d));
|
|
22
|
+
};
|
|
23
|
+
return /* @__PURE__ */ t(
|
|
24
|
+
"div",
|
|
25
|
+
{
|
|
26
|
+
className: n(
|
|
27
|
+
"w-full overflow-x-auto border border-border rounded-xl",
|
|
28
|
+
h
|
|
29
|
+
),
|
|
30
|
+
children: /* @__PURE__ */ f(
|
|
31
|
+
"table",
|
|
32
|
+
{
|
|
33
|
+
className: "w-full text-sm",
|
|
34
|
+
"aria-label": i ? void 0 : m,
|
|
35
|
+
children: [
|
|
36
|
+
i && /* @__PURE__ */ t("caption", { className: "px-4 py-3 text-left text-sm font-medium text-text-secondary", children: i }),
|
|
37
|
+
/* @__PURE__ */ t("thead", { children: /* @__PURE__ */ t("tr", { className: "border-b border-border bg-surface-secondary", children: s.map((e) => /* @__PURE__ */ t(
|
|
38
|
+
"th",
|
|
39
|
+
{
|
|
40
|
+
scope: "col",
|
|
41
|
+
className: n(
|
|
42
|
+
"px-4 py-3 font-medium text-text-secondary",
|
|
43
|
+
b[e.align || "left"]
|
|
44
|
+
),
|
|
45
|
+
style: e.width ? { width: e.width } : void 0,
|
|
46
|
+
children: e.header
|
|
47
|
+
},
|
|
48
|
+
e.key
|
|
49
|
+
)) }) }),
|
|
50
|
+
/* @__PURE__ */ f("tbody", { children: [
|
|
51
|
+
l.map((e, d) => {
|
|
52
|
+
const u = o ? o(e) : d;
|
|
53
|
+
return /* @__PURE__ */ t(
|
|
54
|
+
"tr",
|
|
55
|
+
{
|
|
56
|
+
onClick: r ? () => r(e) : void 0,
|
|
57
|
+
onKeyDown: r ? (a) => p(a, e) : void 0,
|
|
58
|
+
tabIndex: r ? 0 : void 0,
|
|
59
|
+
role: r ? "button" : void 0,
|
|
60
|
+
"aria-label": r && c ? c(e) : void 0,
|
|
61
|
+
className: n(
|
|
62
|
+
"border-b border-border last:border-b-0 transition-colors",
|
|
63
|
+
r && "cursor-pointer hover:bg-surface-secondary focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-accent",
|
|
64
|
+
x && d % 2 === 1 && "bg-surface-secondary"
|
|
65
|
+
),
|
|
66
|
+
children: s.map((a) => /* @__PURE__ */ t(
|
|
67
|
+
"td",
|
|
68
|
+
{
|
|
69
|
+
className: n(
|
|
70
|
+
"px-4 py-3 text-text-primary",
|
|
71
|
+
b[a.align || "left"]
|
|
72
|
+
),
|
|
73
|
+
children: a.render ? a.render(e) : e[a.key]
|
|
74
|
+
},
|
|
75
|
+
a.key
|
|
76
|
+
))
|
|
77
|
+
},
|
|
78
|
+
u
|
|
79
|
+
);
|
|
80
|
+
}),
|
|
81
|
+
l.length === 0 && /* @__PURE__ */ t("tr", { children: /* @__PURE__ */ t("td", { colSpan: s.length, className: "px-4 py-12 text-center", children: /* @__PURE__ */ t(y, { variant: "caption", as: "span", children: "No data available" }) }) })
|
|
82
|
+
] })
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
export {
|
|
90
|
+
D as Table
|
|
91
|
+
};
|
package/dist/lib/Tabs.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as k, jsx as s } from "react/jsx-runtime";
|
|
3
|
+
import { useState as T, useId as N, useCallback as c } from "react";
|
|
4
|
+
import { cn as i } from "./utils/cn.js";
|
|
5
|
+
function D({
|
|
6
|
+
tabs: r,
|
|
7
|
+
defaultTab: h,
|
|
8
|
+
onChange: m,
|
|
9
|
+
className: p,
|
|
10
|
+
variant: a = "underline",
|
|
11
|
+
ref: g
|
|
12
|
+
}) {
|
|
13
|
+
const v = r[0], [n, y] = T(h ?? v?.id ?? ""), o = N(), u = c(
|
|
14
|
+
(e) => {
|
|
15
|
+
y(e), m?.(e);
|
|
16
|
+
},
|
|
17
|
+
[m]
|
|
18
|
+
), w = r.find((e) => e.id === n)?.content, l = c(
|
|
19
|
+
(e) => `${o}-tab-${e}`,
|
|
20
|
+
[o]
|
|
21
|
+
), x = c(
|
|
22
|
+
(e) => `${o}-panel-${e}`,
|
|
23
|
+
[o]
|
|
24
|
+
), I = c(
|
|
25
|
+
(e, f) => {
|
|
26
|
+
const b = r.findIndex((d) => d.id === f);
|
|
27
|
+
let t = null;
|
|
28
|
+
switch (e.key) {
|
|
29
|
+
case "ArrowRight":
|
|
30
|
+
t = (b + 1) % r.length;
|
|
31
|
+
break;
|
|
32
|
+
case "ArrowLeft":
|
|
33
|
+
t = (b - 1 + r.length) % r.length;
|
|
34
|
+
break;
|
|
35
|
+
case "Home":
|
|
36
|
+
t = 0;
|
|
37
|
+
break;
|
|
38
|
+
case "End":
|
|
39
|
+
t = r.length - 1;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
if (t !== null) {
|
|
43
|
+
const d = r[t];
|
|
44
|
+
if (!d) return;
|
|
45
|
+
e.preventDefault(), u(d.id), document.getElementById(l(d.id))?.focus();
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
[r, u, l]
|
|
49
|
+
);
|
|
50
|
+
return r.length === 0 ? null : /* @__PURE__ */ k("div", { ref: g, className: i("w-full", p), children: [
|
|
51
|
+
/* @__PURE__ */ s("div", { className: a === "underline" ? "border-b border-border" : "", children: /* @__PURE__ */ s(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
role: "tablist",
|
|
55
|
+
className: i(
|
|
56
|
+
"flex flex-wrap",
|
|
57
|
+
a === "underline" ? "gap-1" : "gap-1 p-1 bg-surface-tertiary rounded-lg"
|
|
58
|
+
),
|
|
59
|
+
children: r.map((e) => /* @__PURE__ */ s(
|
|
60
|
+
"button",
|
|
61
|
+
{
|
|
62
|
+
id: l(e.id),
|
|
63
|
+
role: "tab",
|
|
64
|
+
"aria-selected": n === e.id,
|
|
65
|
+
"aria-controls": x(e.id),
|
|
66
|
+
tabIndex: n === e.id ? 0 : -1,
|
|
67
|
+
onClick: () => u(e.id),
|
|
68
|
+
onKeyDown: (f) => I(f, e.id),
|
|
69
|
+
className: i(
|
|
70
|
+
"px-4 py-2.5 transition-colors focus-visible:outline-none",
|
|
71
|
+
"focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-2",
|
|
72
|
+
a === "underline" ? i(
|
|
73
|
+
"border-b-2",
|
|
74
|
+
n === e.id ? "border-brand-500 text-brand-500" : "border-transparent text-text-secondary hover:text-text-primary hover:border-border-secondary"
|
|
75
|
+
) : i(
|
|
76
|
+
"rounded-md text-sm font-medium",
|
|
77
|
+
n === e.id ? "bg-surface text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"
|
|
78
|
+
)
|
|
79
|
+
),
|
|
80
|
+
children: e.label
|
|
81
|
+
},
|
|
82
|
+
e.id
|
|
83
|
+
))
|
|
84
|
+
}
|
|
85
|
+
) }),
|
|
86
|
+
/* @__PURE__ */ s(
|
|
87
|
+
"div",
|
|
88
|
+
{
|
|
89
|
+
id: x(n),
|
|
90
|
+
role: "tabpanel",
|
|
91
|
+
tabIndex: 0,
|
|
92
|
+
"aria-labelledby": l(n),
|
|
93
|
+
className: "mt-4",
|
|
94
|
+
children: w
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
] });
|
|
98
|
+
}
|
|
99
|
+
export {
|
|
100
|
+
D as Tabs
|
|
101
|
+
};
|
package/dist/lib/Text.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { cn as n } from "./utils/cn.js";
|
|
3
|
+
import "react";
|
|
4
|
+
const d = {
|
|
5
|
+
body: "text-sm text-text-secondary leading-relaxed",
|
|
6
|
+
bodyLg: "text-base text-text-secondary leading-relaxed",
|
|
7
|
+
subtitle: "text-lg text-text-secondary leading-relaxed",
|
|
8
|
+
cardDescription: "text-sm text-text-secondary leading-relaxed",
|
|
9
|
+
detail: "text-xs text-text-secondary",
|
|
10
|
+
label: "text-xs font-semibold uppercase tracking-wider text-text-tertiary",
|
|
11
|
+
meta: "text-xs text-text-tertiary",
|
|
12
|
+
caption: "text-sm text-text-tertiary",
|
|
13
|
+
helper: "text-sm text-text-tertiary",
|
|
14
|
+
error: "text-sm text-error"
|
|
15
|
+
}, l = {
|
|
16
|
+
body: "p",
|
|
17
|
+
bodyLg: "p",
|
|
18
|
+
subtitle: "p",
|
|
19
|
+
cardDescription: "p",
|
|
20
|
+
detail: "p",
|
|
21
|
+
label: "span",
|
|
22
|
+
meta: "span",
|
|
23
|
+
caption: "p",
|
|
24
|
+
helper: "p",
|
|
25
|
+
error: "p"
|
|
26
|
+
};
|
|
27
|
+
function y({
|
|
28
|
+
as: e,
|
|
29
|
+
variant: t,
|
|
30
|
+
className: r,
|
|
31
|
+
children: x,
|
|
32
|
+
ref: a,
|
|
33
|
+
...s
|
|
34
|
+
}) {
|
|
35
|
+
const o = e ?? l[t];
|
|
36
|
+
return /* @__PURE__ */ i(
|
|
37
|
+
o,
|
|
38
|
+
{
|
|
39
|
+
ref: a,
|
|
40
|
+
className: n(d[t], r),
|
|
41
|
+
...s,
|
|
42
|
+
children: x
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
y as Text
|
|
48
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsxs as n, jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { FORM_LABEL as L, REQUIRED_MARK as p, DISABLED as v, FIELD_PLACEHOLDER as f, FIELD_PADDING as R, BASE_FIELD as h, FIELD_ERROR as F, FIELD_SUCCESS as N } from "./styles/formStyles.js";
|
|
3
|
+
import { Text as o } from "./Text.js";
|
|
4
|
+
import { cn as S } from "./utils/cn.js";
|
|
5
|
+
import "react";
|
|
6
|
+
function g({
|
|
7
|
+
label: s,
|
|
8
|
+
error: e,
|
|
9
|
+
helperText: i,
|
|
10
|
+
success: l,
|
|
11
|
+
className: m,
|
|
12
|
+
id: E,
|
|
13
|
+
required: r,
|
|
14
|
+
ref: D,
|
|
15
|
+
...I
|
|
16
|
+
}) {
|
|
17
|
+
const a = E || s?.toLowerCase().replace(/\s+/g, "-"), c = e ? `${a}-error` : void 0, d = i && !e ? `${a}-helper` : void 0;
|
|
18
|
+
return /* @__PURE__ */ n("div", { className: "w-full", children: [
|
|
19
|
+
s && /* @__PURE__ */ n("label", { htmlFor: a, className: L, children: [
|
|
20
|
+
s,
|
|
21
|
+
r && /* @__PURE__ */ t("span", { className: p, children: "*" })
|
|
22
|
+
] }),
|
|
23
|
+
/* @__PURE__ */ t(
|
|
24
|
+
"textarea",
|
|
25
|
+
{
|
|
26
|
+
ref: D,
|
|
27
|
+
id: a,
|
|
28
|
+
"aria-invalid": e ? "true" : void 0,
|
|
29
|
+
"aria-required": r || void 0,
|
|
30
|
+
"aria-describedby": c || d,
|
|
31
|
+
required: r,
|
|
32
|
+
className: S(
|
|
33
|
+
h,
|
|
34
|
+
R,
|
|
35
|
+
f,
|
|
36
|
+
"resize-vertical",
|
|
37
|
+
v,
|
|
38
|
+
e ? F : l ? N : "",
|
|
39
|
+
m
|
|
40
|
+
),
|
|
41
|
+
...I
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
e && /* @__PURE__ */ t(o, { variant: "error", id: c, className: "mt-1.5", role: "alert", children: e }),
|
|
45
|
+
i && !e && /* @__PURE__ */ t(o, { variant: "helper", id: d, className: "mt-1.5", children: i })
|
|
46
|
+
] });
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
g as Textarea
|
|
50
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as T } from "react/jsx-runtime";
|
|
3
|
+
import { createContext as v, useState as h, useEffect as n, useMemo as l, useCallback as f, useContext as w } from "react";
|
|
4
|
+
const g = v({
|
|
5
|
+
theme: "system",
|
|
6
|
+
resolvedTheme: "light",
|
|
7
|
+
isDarkMode: !1,
|
|
8
|
+
setTheme: () => {
|
|
9
|
+
},
|
|
10
|
+
toggleDarkMode: () => {
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
function x() {
|
|
14
|
+
return w(g);
|
|
15
|
+
}
|
|
16
|
+
const k = "theme";
|
|
17
|
+
function E() {
|
|
18
|
+
return typeof window > "u" ? !1 : window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
19
|
+
}
|
|
20
|
+
function p() {
|
|
21
|
+
if (typeof window > "u") return "system";
|
|
22
|
+
const t = localStorage.getItem(k);
|
|
23
|
+
return t === "light" || t === "dark" || t === "system" ? t : "system";
|
|
24
|
+
}
|
|
25
|
+
function C({ children: t }) {
|
|
26
|
+
const [s, a] = h("system"), [m, c] = h(!1);
|
|
27
|
+
n(() => {
|
|
28
|
+
queueMicrotask(() => {
|
|
29
|
+
a(p()), c(E());
|
|
30
|
+
});
|
|
31
|
+
}, []), n(() => {
|
|
32
|
+
const r = window.matchMedia("(prefers-color-scheme: dark)"), u = (M) => {
|
|
33
|
+
c(M.matches);
|
|
34
|
+
};
|
|
35
|
+
return r.addEventListener("change", u), () => r.removeEventListener("change", u);
|
|
36
|
+
}, []);
|
|
37
|
+
const e = l(() => s === "system" ? m : s === "dark", [s, m]), d = e ? "dark" : "light";
|
|
38
|
+
n(() => {
|
|
39
|
+
document.documentElement.classList.toggle("dark", e);
|
|
40
|
+
}, [e]);
|
|
41
|
+
const o = f((r) => {
|
|
42
|
+
a(r), localStorage.setItem(k, r);
|
|
43
|
+
}, []), i = f(() => {
|
|
44
|
+
o(e ? "light" : "dark");
|
|
45
|
+
}, [e, o]), y = l(
|
|
46
|
+
() => ({ theme: s, resolvedTheme: d, isDarkMode: e, setTheme: o, toggleDarkMode: i }),
|
|
47
|
+
[s, d, e, o, i]
|
|
48
|
+
);
|
|
49
|
+
return /* @__PURE__ */ T(g.Provider, { value: y, children: t });
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
C as ThemeProvider,
|
|
53
|
+
x as useTheme
|
|
54
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { Sun as s, Moon as a, Monitor as m } from "lucide-react";
|
|
4
|
+
import { useTheme as c } from "./ThemeProvider.js";
|
|
5
|
+
import { cn as l } from "./utils/cn.js";
|
|
6
|
+
function f() {
|
|
7
|
+
const { theme: o, setTheme: r } = c();
|
|
8
|
+
return /* @__PURE__ */ t("div", { className: "inline-flex items-center gap-0.5 p-0.5 bg-surface-tertiary rounded-lg", children: [
|
|
9
|
+
{ value: "light", icon: s, label: "Light" },
|
|
10
|
+
{ value: "dark", icon: a, label: "Dark" },
|
|
11
|
+
{ value: "system", icon: m, label: "System" }
|
|
12
|
+
].map(({ value: e, icon: n, label: i }) => /* @__PURE__ */ t(
|
|
13
|
+
"button",
|
|
14
|
+
{
|
|
15
|
+
onClick: () => r(e),
|
|
16
|
+
title: i,
|
|
17
|
+
"aria-pressed": o === e,
|
|
18
|
+
className: l(
|
|
19
|
+
"p-1.5 rounded-md transition-all duration-150 cursor-pointer motion-reduce:transition-none",
|
|
20
|
+
o === e ? "bg-surface text-text-primary shadow-xs" : "text-text-tertiary hover:text-text-secondary"
|
|
21
|
+
),
|
|
22
|
+
children: /* @__PURE__ */ t(n, { className: "h-4 w-4" })
|
|
23
|
+
},
|
|
24
|
+
e
|
|
25
|
+
)) });
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
f as ThemeToggle
|
|
29
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as p, jsx as o } from "react/jsx-runtime";
|
|
3
|
+
import { XCircle as C, AlertTriangle as w, CheckCircle as D, Info as N, X as S } from "lucide-react";
|
|
4
|
+
import { createContext as b, useState as v, useCallback as i, useContext as I, useRef as d, useEffect as M } from "react";
|
|
5
|
+
import { Heading as E } from "./Heading.js";
|
|
6
|
+
import { DISMISS_BUTTON as k } from "./styles/formStyles.js";
|
|
7
|
+
import { SEMANTIC_TEXT as R } from "./styles/semanticVariants.js";
|
|
8
|
+
import { Text as _ } from "./Text.js";
|
|
9
|
+
import { cn as f } from "./utils/cn.js";
|
|
10
|
+
const g = b({ toast: () => {
|
|
11
|
+
} });
|
|
12
|
+
function y() {
|
|
13
|
+
return I(g);
|
|
14
|
+
}
|
|
15
|
+
const A = {
|
|
16
|
+
info: N,
|
|
17
|
+
success: D,
|
|
18
|
+
warning: w,
|
|
19
|
+
error: C
|
|
20
|
+
}, U = R, X = 4e3;
|
|
21
|
+
let j = 0;
|
|
22
|
+
function B({
|
|
23
|
+
toast: t,
|
|
24
|
+
onDismiss: a
|
|
25
|
+
}) {
|
|
26
|
+
const c = t.duration ?? X, r = d(null), l = d(c), e = d(Date.now()), [n, s] = v(!1), h = t.variant === "error" || t.variant === "warning", x = A[t.variant], m = i(() => {
|
|
27
|
+
s(!0), setTimeout(() => a(t.id), 150);
|
|
28
|
+
}, [a, t.id]), u = i(() => {
|
|
29
|
+
e.current = Date.now(), r.current = setTimeout(() => {
|
|
30
|
+
m();
|
|
31
|
+
}, l.current);
|
|
32
|
+
}, [m]), T = i(() => {
|
|
33
|
+
r.current && (clearTimeout(r.current), r.current = null, l.current -= Date.now() - e.current);
|
|
34
|
+
}, []);
|
|
35
|
+
return M(() => (u(), () => {
|
|
36
|
+
r.current && clearTimeout(r.current);
|
|
37
|
+
}), [u]), // eslint-disable-next-line jsx-a11y/no-static-element-interactions -- hover/focus pause timer, not user interaction
|
|
38
|
+
/* @__PURE__ */ p(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
role: h ? "alert" : "status",
|
|
42
|
+
"aria-atomic": "true",
|
|
43
|
+
onMouseEnter: T,
|
|
44
|
+
onMouseLeave: u,
|
|
45
|
+
onFocus: T,
|
|
46
|
+
onBlur: u,
|
|
47
|
+
className: f(
|
|
48
|
+
"flex items-start gap-3 p-4 bg-surface-elevated border border-border",
|
|
49
|
+
"rounded-lg shadow-lg motion-reduce:animate-none",
|
|
50
|
+
n ? "animate-slide-out-down" : "animate-slide-up"
|
|
51
|
+
),
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ o(x, { className: f("h-5 w-5 shrink-0", U[t.variant]) }),
|
|
54
|
+
/* @__PURE__ */ p("div", { className: "flex-1 min-w-0", children: [
|
|
55
|
+
/* @__PURE__ */ o(E, { variant: "cardTitle", as: "p", children: t.title }),
|
|
56
|
+
t.description && /* @__PURE__ */ o(_, { variant: "meta", className: "mt-0.5", children: t.description })
|
|
57
|
+
] }),
|
|
58
|
+
/* @__PURE__ */ o(
|
|
59
|
+
"button",
|
|
60
|
+
{
|
|
61
|
+
onClick: () => m(),
|
|
62
|
+
"aria-label": "Dismiss notification",
|
|
63
|
+
className: f("p-0.5 cursor-pointer", k),
|
|
64
|
+
children: /* @__PURE__ */ o(S, { className: "h-4 w-4" })
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
function G({ children: t }) {
|
|
72
|
+
const [a, c] = v([]), r = i((e) => {
|
|
73
|
+
const n = `toast-${++j}`;
|
|
74
|
+
c((s) => [...s, { ...e, id: n }]);
|
|
75
|
+
}, []), l = i(
|
|
76
|
+
(e) => c((n) => n.filter((s) => s.id !== e)),
|
|
77
|
+
[]
|
|
78
|
+
);
|
|
79
|
+
return /* @__PURE__ */ p(g.Provider, { value: { toast: r }, children: [
|
|
80
|
+
t,
|
|
81
|
+
/* @__PURE__ */ o(
|
|
82
|
+
"div",
|
|
83
|
+
{
|
|
84
|
+
"aria-live": "polite",
|
|
85
|
+
"aria-atomic": "true",
|
|
86
|
+
className: "fixed bottom-4 right-4 z-[100] flex flex-col gap-2 max-w-sm",
|
|
87
|
+
children: a.map((e) => /* @__PURE__ */ o(B, { toast: e, onDismiss: l }, e.id))
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
] });
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
G as ToastProvider,
|
|
94
|
+
y as useToast
|
|
95
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as x, jsx as c } from "react/jsx-runtime";
|
|
3
|
+
import { useState as v, useRef as T, useId as w, useCallback as r, useEffect as E, isValidElement as g, cloneElement as k } from "react";
|
|
4
|
+
import { cn as u } from "./utils/cn.js";
|
|
5
|
+
const I = {
|
|
6
|
+
top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
|
|
7
|
+
bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
|
|
8
|
+
left: "right-full top-1/2 -translate-y-1/2 mr-2",
|
|
9
|
+
right: "left-full top-1/2 -translate-y-1/2 ml-2"
|
|
10
|
+
};
|
|
11
|
+
function K({
|
|
12
|
+
content: p,
|
|
13
|
+
children: o,
|
|
14
|
+
position: d = "top",
|
|
15
|
+
delay: n = 200,
|
|
16
|
+
className: m,
|
|
17
|
+
ref: f
|
|
18
|
+
}) {
|
|
19
|
+
const [i, l] = v(!1), e = T(null), s = w(), a = r(() => {
|
|
20
|
+
e.current = setTimeout(() => {
|
|
21
|
+
l(!0);
|
|
22
|
+
}, n);
|
|
23
|
+
}, [n]), t = r(() => {
|
|
24
|
+
e.current && (clearTimeout(e.current), e.current = null), l(!1);
|
|
25
|
+
}, []), b = r(
|
|
26
|
+
(h) => {
|
|
27
|
+
h.key === "Escape" && t();
|
|
28
|
+
},
|
|
29
|
+
[t]
|
|
30
|
+
);
|
|
31
|
+
E(() => () => {
|
|
32
|
+
e.current && clearTimeout(e.current);
|
|
33
|
+
}, []);
|
|
34
|
+
const y = g(o) ? k(o, {
|
|
35
|
+
"aria-describedby": s
|
|
36
|
+
}) : o;
|
|
37
|
+
return /* @__PURE__ */ x("div", { ref: f, className: u("relative inline-block", m), children: [
|
|
38
|
+
/* @__PURE__ */ c(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
onMouseEnter: a,
|
|
42
|
+
onMouseLeave: t,
|
|
43
|
+
onFocus: a,
|
|
44
|
+
onBlur: t,
|
|
45
|
+
onKeyDown: b,
|
|
46
|
+
role: "presentation",
|
|
47
|
+
children: y
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ c(
|
|
51
|
+
"div",
|
|
52
|
+
{
|
|
53
|
+
id: s,
|
|
54
|
+
role: "tooltip",
|
|
55
|
+
"aria-hidden": !i,
|
|
56
|
+
className: u(
|
|
57
|
+
"absolute z-50 px-3 py-1.5 bg-surface-elevated border",
|
|
58
|
+
"border-border-secondary rounded-md text-sm text-text-primary",
|
|
59
|
+
"whitespace-nowrap pointer-events-none transition-opacity duration-150",
|
|
60
|
+
I[d],
|
|
61
|
+
i ? "opacity-100" : "opacity-0"
|
|
62
|
+
),
|
|
63
|
+
children: p
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
] });
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
K as Tooltip
|
|
70
|
+
};
|