@nexub/patterns 1.5.0 → 1.6.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/{chunk-TLOLIMPY.js → chunk-5JU6HUVJ.js} +2 -2
- package/dist/{chunk-AEYLZU3F.js → chunk-7NYGYETG.js} +4 -4
- package/dist/{chunk-ZFHA46UX.js → chunk-H5UTW5ML.js} +5 -5
- package/dist/{chunk-AOE6GQSH.js → chunk-HMJRSNJD.js} +4 -4
- package/dist/{chunk-YX7UO577.js → chunk-JTIMCXPS.js} +4 -4
- package/dist/{chunk-7GYTYFUD.js → chunk-K5EFLRKU.js} +9 -9
- package/dist/{chunk-MXPRKZPB.js → chunk-L456OB3Q.js} +6 -6
- package/dist/{chunk-OYSWFXRD.js → chunk-LAYYOVIK.js} +14 -19
- package/dist/chunk-RWPFCNMJ.js +75 -0
- package/dist/{chunk-OTNHVOPC.js → chunk-U3FT7XAU.js} +2 -2
- package/dist/{chunk-5QFC4WFD.js → chunk-WIHNK7RT.js} +12 -12
- package/dist/{chunk-74JVLMLE.js → chunk-WPNT5JOU.js} +3 -3
- package/dist/chunk-WRP73TXG.js +109 -0
- package/dist/chunk-WZTDCJYP.js +23 -0
- package/dist/{chunk-QMYBXQG4.js → chunk-YB7G4YBU.js} +8 -8
- package/dist/{chunk-EOA5C3Q4.js → chunk-Z6VMCMSW.js} +2 -2
- package/dist/{chunk-Y3TNGDKC.js → chunk-ZV73WS4X.js} +7 -7
- package/dist/components/ActivityFeed/index.js +1 -1
- package/dist/components/AppHeader/index.js +2 -2
- package/dist/components/AppLauncher/index.js +1 -1
- package/dist/components/AuthCard/index.js +1 -1
- package/dist/components/BentoGrid/index.js +9 -0
- package/dist/components/Conversation/index.js +7 -0
- package/dist/components/ErrorSummary/index.js +9 -0
- package/dist/components/FilterBar/index.js +1 -1
- package/dist/components/InfoList/index.js +1 -1
- package/dist/components/ListDetail/index.js +1 -1
- package/dist/components/NotificationItem/index.js +1 -1
- package/dist/components/PlanCard/index.js +1 -1
- package/dist/components/SettingsLayout/index.js +1 -1
- package/dist/components/SettingsSection/index.js +1 -1
- package/dist/components/StatCard/index.js +1 -1
- package/dist/components/StepIndicator/index.js +1 -1
- package/dist/components/UserCard/index.js +1 -1
- package/dist/index.d.ts +88 -5
- package/dist/index.js +38 -22
- package/package.json +17 -16
|
@@ -29,7 +29,7 @@ var ListDetail = React.forwardRef(
|
|
|
29
29
|
"aria-label": listLabel,
|
|
30
30
|
className: cn(
|
|
31
31
|
"min-h-0 w-full shrink-0 flex-col overflow-y-auto",
|
|
32
|
-
"[@container(min-width:720px)]:flex [@container(min-width:720px)]:border-
|
|
32
|
+
"[@container(min-width:720px)]:flex [@container(min-width:720px)]:border-e [@container(min-width:720px)]:border-[var(--color-outline-variant)]",
|
|
33
33
|
widths[listWidth],
|
|
34
34
|
showDetail ? "hidden" : "flex"
|
|
35
35
|
),
|
|
@@ -46,7 +46,7 @@ var ListDetail = React.forwardRef(
|
|
|
46
46
|
showDetail ? "flex" : "hidden"
|
|
47
47
|
),
|
|
48
48
|
children: [
|
|
49
|
-
onBack && /* @__PURE__ */ jsx("div", { className: "p-2 [@container(min-width:720px)]:hidden", children: /* @__PURE__ */ jsx(IconButton, { label: backLabel, onClick: onBack, children: /* @__PURE__ */ jsx(ArrowLeft, { size: "md", "aria-hidden": "true" }) }) }),
|
|
49
|
+
onBack && /* @__PURE__ */ jsx("div", { className: "p-2 [@container(min-width:720px)]:hidden", children: /* @__PURE__ */ jsx(IconButton, { label: backLabel, onClick: onBack, children: /* @__PURE__ */ jsx(ArrowLeft, { size: "md", "aria-hidden": "true", className: "rtl:-scale-x-100" }) }) }),
|
|
50
50
|
detail
|
|
51
51
|
]
|
|
52
52
|
}
|
|
@@ -21,7 +21,7 @@ var UserCard = React.forwardRef(
|
|
|
21
21
|
{
|
|
22
22
|
ref,
|
|
23
23
|
className: cn(
|
|
24
|
-
"flex items-center gap-3 rounded-
|
|
24
|
+
"flex items-center gap-3 rounded-shape-container border border-[color-mix(in_srgb,var(--color-outline-variant)_60%,transparent)] bg-[var(--color-surface-elevated)] p-4",
|
|
25
25
|
className
|
|
26
26
|
),
|
|
27
27
|
...props,
|
|
@@ -36,9 +36,9 @@ var UserCard = React.forwardRef(
|
|
|
36
36
|
}
|
|
37
37
|
),
|
|
38
38
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex flex-col gap-0.5", children: [
|
|
39
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-[var(--color-
|
|
40
|
-
role && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-
|
|
41
|
-
email && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-
|
|
39
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-[var(--color-on-surface)] truncate", children: name }),
|
|
40
|
+
role && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-on-surface-muted)] truncate", children: role }),
|
|
41
|
+
email && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-on-surface-variant)] truncate", children: email })
|
|
42
42
|
] }),
|
|
43
43
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0", children: actions })
|
|
44
44
|
]
|
|
@@ -16,12 +16,12 @@ function AppIcon({ app }) {
|
|
|
16
16
|
alt: "",
|
|
17
17
|
width: 40,
|
|
18
18
|
height: 40,
|
|
19
|
-
className: "h-10 w-10 rounded-
|
|
19
|
+
className: "h-10 w-10 rounded-[12px] object-cover",
|
|
20
20
|
onError: () => setFailed(true)
|
|
21
21
|
}
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
|
-
return /* @__PURE__ */ jsx(Avatar, { name: app.name, size: "md", className: "rounded-
|
|
24
|
+
return /* @__PURE__ */ jsx(Avatar, { name: app.name, size: "md", className: "rounded-[12px]", "aria-hidden": "true" });
|
|
25
25
|
}
|
|
26
26
|
var AppLauncher = React.forwardRef(
|
|
27
27
|
({ apps, onNavigate, surface = "solid", label = "Nexub apps", className }, ref) => {
|
|
@@ -75,9 +75,9 @@ var AppLauncher = React.forwardRef(
|
|
|
75
75
|
"aria-current": app.current ? "page" : void 0,
|
|
76
76
|
onClick: (e) => onClick(e, app),
|
|
77
77
|
className: cn(
|
|
78
|
-
"flex flex-col items-center gap-1.5 rounded-
|
|
79
|
-
"hover:bg-[
|
|
80
|
-
app.current && "bg-[var(--color-
|
|
78
|
+
"flex flex-col items-center gap-1.5 rounded-[8px] px-1 py-3 text-center text-xs text-[var(--color-on-surface)] transition-colors",
|
|
79
|
+
"hover:bg-[color-mix(in_srgb,var(--color-on-surface)_8%,transparent)]",
|
|
80
|
+
app.current && "bg-[var(--color-surface-container-low)] font-semibold"
|
|
81
81
|
),
|
|
82
82
|
children: [
|
|
83
83
|
/* @__PURE__ */ jsx(AppIcon, { app }),
|
|
@@ -22,11 +22,11 @@ function AuthCard({
|
|
|
22
22
|
children: [
|
|
23
23
|
logo && /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: logo }),
|
|
24
24
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-center", children: [
|
|
25
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight text-[var(--color-
|
|
26
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
25
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight text-[var(--color-on-surface)]", children: title }),
|
|
26
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)]", children: description })
|
|
27
27
|
] }),
|
|
28
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-
|
|
29
|
-
footer && /* @__PURE__ */ jsx("div", { className: "flex flex-col items-center gap-2 text-sm text-[var(--color-
|
|
28
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-shape-container border border-[color-mix(in_srgb,var(--color-outline-variant)_60%,transparent)] bg-[var(--color-surface-elevated)] shadow-elevation-1 p-6 flex flex-col gap-4", children }),
|
|
29
|
+
footer && /* @__PURE__ */ jsx("div", { className: "flex flex-col items-center gap-2 text-sm text-[var(--color-on-surface-muted)]", children: footer })
|
|
30
30
|
]
|
|
31
31
|
}
|
|
32
32
|
);
|
|
@@ -11,7 +11,7 @@ var Root = React.forwardRef(
|
|
|
11
11
|
ref,
|
|
12
12
|
role: "feed",
|
|
13
13
|
"aria-label": "Activity feed",
|
|
14
|
-
className: cn("flex flex-col divide-y divide-[var(--color-
|
|
14
|
+
className: cn("flex flex-col divide-y divide-[var(--color-outline-variant)]", className),
|
|
15
15
|
...props,
|
|
16
16
|
children
|
|
17
17
|
}
|
|
@@ -21,10 +21,10 @@ Root.displayName = "ActivityFeed.Root";
|
|
|
21
21
|
var Item = ({ avatar, title, description, timestamp, className }) => /* @__PURE__ */ jsxs("li", { className: cn("flex items-start gap-3 py-3", className), children: [
|
|
22
22
|
avatar && /* @__PURE__ */ jsx("div", { className: "shrink-0 mt-0.5", children: avatar }),
|
|
23
23
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
24
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--color-
|
|
25
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
24
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--color-on-surface)]", children: title }),
|
|
25
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)] mt-0.5", children: description })
|
|
26
26
|
] }),
|
|
27
|
-
timestamp && /* @__PURE__ */ jsx("time", { className: "shrink-0 text-xs text-[var(--color-
|
|
27
|
+
timestamp && /* @__PURE__ */ jsx("time", { className: "shrink-0 text-xs text-[var(--color-on-surface-muted)]", children: timestamp })
|
|
28
28
|
] });
|
|
29
29
|
Item.displayName = "ActivityFeed.Item";
|
|
30
30
|
var ActivityFeed = { Root, Item };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/components/StatCard/StatCard.tsx
|
|
4
4
|
import * as React from "react";
|
|
5
|
-
import { cn } from "@nexub/react";
|
|
5
|
+
import { cn, NumberTicker } from "@nexub/react";
|
|
6
6
|
import { TrendingUp, TrendingDown, Minus } from "@nexub/icons";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
var StatCard = React.forwardRef(
|
|
@@ -13,32 +13,32 @@ var StatCard = React.forwardRef(
|
|
|
13
13
|
deltaType = "neutral",
|
|
14
14
|
icon,
|
|
15
15
|
description,
|
|
16
|
+
animate = false,
|
|
16
17
|
className,
|
|
17
18
|
...props
|
|
18
19
|
}, ref) => {
|
|
19
|
-
const deltaColor = deltaType === "increase" ? "var(--color-success
|
|
20
|
+
const deltaColor = deltaType === "increase" ? "text-[var(--color-success)]" : deltaType === "decrease" ? "text-[var(--color-error)]" : "text-[var(--color-on-surface-muted)]";
|
|
20
21
|
const DeltaIcon = deltaType === "increase" ? TrendingUp : deltaType === "decrease" ? TrendingDown : Minus;
|
|
21
22
|
return /* @__PURE__ */ jsxs(
|
|
22
23
|
"div",
|
|
23
24
|
{
|
|
24
25
|
ref,
|
|
25
26
|
className: cn(
|
|
26
|
-
"rounded-
|
|
27
|
+
"rounded-shape-container border border-[color-mix(in_srgb,var(--color-outline-variant)_60%,transparent)] bg-[var(--color-surface-elevated)] p-6 flex flex-col gap-3",
|
|
27
28
|
className
|
|
28
29
|
),
|
|
29
30
|
...props,
|
|
30
31
|
children: [
|
|
31
32
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
32
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--color-
|
|
33
|
-
icon && /* @__PURE__ */ jsx("span", { className: "text-[var(--color-
|
|
33
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--color-on-surface-muted)]", children: label }),
|
|
34
|
+
icon && /* @__PURE__ */ jsx("span", { className: "text-[var(--color-on-surface-muted)]", children: icon })
|
|
34
35
|
] }),
|
|
35
|
-
/* @__PURE__ */ jsx("div", { className: "text-3xl font-bold tracking-tight text-[var(--color-
|
|
36
|
+
/* @__PURE__ */ jsx("div", { className: "text-3xl font-bold tracking-tight tabular-nums text-[var(--color-on-surface)]", children: animate && (typeof value === "number" || typeof value === "string") ? /* @__PURE__ */ jsx(NumberTicker, { value, "aria-live": "polite" }) : value }),
|
|
36
37
|
(delta || description) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
37
38
|
delta && /* @__PURE__ */ jsxs(
|
|
38
39
|
"span",
|
|
39
40
|
{
|
|
40
|
-
className: "inline-flex items-center gap-1 text-xs font-medium",
|
|
41
|
-
style: { color: deltaColor },
|
|
41
|
+
className: cn("inline-flex items-center gap-1 text-xs font-medium", deltaColor),
|
|
42
42
|
"data-delta-type": deltaType,
|
|
43
43
|
children: [
|
|
44
44
|
/* @__PURE__ */ jsx(DeltaIcon, { size: "xs", "aria-hidden": "true" }),
|
|
@@ -46,7 +46,7 @@ var StatCard = React.forwardRef(
|
|
|
46
46
|
]
|
|
47
47
|
}
|
|
48
48
|
),
|
|
49
|
-
description && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-
|
|
49
|
+
description && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-on-surface-muted)]", children: description })
|
|
50
50
|
] })
|
|
51
51
|
]
|
|
52
52
|
}
|
|
@@ -12,7 +12,7 @@ var StepIndicator = React.forwardRef(
|
|
|
12
12
|
index < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
13
13
|
"div",
|
|
14
14
|
{
|
|
15
|
-
className: "absolute
|
|
15
|
+
className: "absolute start-4 top-8 h-full w-px bg-[var(--color-outline-variant)]",
|
|
16
16
|
"aria-hidden": "true"
|
|
17
17
|
}
|
|
18
18
|
),
|
|
@@ -21,17 +21,17 @@ var StepIndicator = React.forwardRef(
|
|
|
21
21
|
{
|
|
22
22
|
className: cn(
|
|
23
23
|
"relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-xs font-semibold",
|
|
24
|
-
status === "complete" && "bg-[var(--color-
|
|
25
|
-
status === "current" && "border-2 border-[var(--color-
|
|
26
|
-
status === "upcoming" && "border-2 border-[var(--color-
|
|
24
|
+
status === "complete" && "bg-[var(--color-primary)] text-[var(--color-on-primary)]",
|
|
25
|
+
status === "current" && "border-2 border-[var(--color-primary)] text-[var(--color-primary)] bg-[var(--color-surface)]",
|
|
26
|
+
status === "upcoming" && "border-2 border-[var(--color-outline-variant)] text-[var(--color-on-surface-muted)] bg-[var(--color-surface)]"
|
|
27
27
|
),
|
|
28
28
|
"aria-current": status === "current" ? "step" : void 0,
|
|
29
29
|
children: status === "complete" ? /* @__PURE__ */ jsx(Check, { size: "xs", "aria-hidden": "true" }) : index + 1
|
|
30
30
|
}
|
|
31
31
|
),
|
|
32
32
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 pt-0.5", children: [
|
|
33
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--color-
|
|
34
|
-
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--color-
|
|
33
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--color-on-surface)]", children: step.label }),
|
|
34
|
+
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--color-on-surface-muted)]", children: step.description })
|
|
35
35
|
] })
|
|
36
36
|
] }, step.label);
|
|
37
37
|
}) })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
AppLauncher
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H5UTW5ML.js";
|
|
5
5
|
|
|
6
6
|
// src/components/AppHeader/AppHeader.tsx
|
|
7
7
|
import * as React from "react";
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
import { Building2, ChevronDown, Moon, Search, Sun } from "@nexub/icons";
|
|
20
20
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
21
21
|
var SEARCH_DEBOUNCE_MS = 200;
|
|
22
|
-
var focusRing = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-ring-default)] focus-visible:ring-offset-2 ring-offset-[var(--color-ring-offset)]";
|
|
23
22
|
var isPlainClick = (e) => e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;
|
|
24
23
|
var isTextField = (t) => t instanceof HTMLElement && (t.isContentEditable || t.matches("input, textarea, select"));
|
|
25
24
|
function HeaderSearch({
|
|
@@ -99,13 +98,10 @@ function HeaderSearch({
|
|
|
99
98
|
{
|
|
100
99
|
type: "button",
|
|
101
100
|
...triggerProps,
|
|
102
|
-
className:
|
|
103
|
-
"hidden h-9 w-full max-w-xl items-center gap-2 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-subtle)] px-3 text-sm text-[var(--color-text-muted)] transition-colors hover:bg-[var(--color-bg-muted)] md:flex",
|
|
104
|
-
focusRing
|
|
105
|
-
),
|
|
101
|
+
className: "nx-state-layer hidden h-9 w-full max-w-xl items-center gap-2 rounded-shape-field border border-[var(--color-outline-variant)] bg-[var(--color-surface-container-low)] px-3 text-sm text-[var(--color-on-surface-muted)] md:flex",
|
|
106
102
|
children: [
|
|
107
103
|
/* @__PURE__ */ jsx(Search, { size: "sm", "aria-hidden": "true", className: "shrink-0" }),
|
|
108
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-
|
|
104
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-start", children: placeholder }),
|
|
109
105
|
/* @__PURE__ */ jsx(Kbd, { "aria-hidden": "true", className: "shrink-0", children: isMac ? "\u2318K" : "Ctrl K" })
|
|
110
106
|
]
|
|
111
107
|
}
|
|
@@ -122,7 +118,7 @@ function HeaderSearch({
|
|
|
122
118
|
children: [
|
|
123
119
|
/* @__PURE__ */ jsx(CommandPalette.Input, { placeholder, value: query, onValueChange: setQuery }),
|
|
124
120
|
/* @__PURE__ */ jsxs(CommandPalette.List, { children: [
|
|
125
|
-
loading && /* @__PURE__ */ jsx("div", { role: "status", className: "px-3 py-2 text-sm text-[var(--color-
|
|
121
|
+
loading && /* @__PURE__ */ jsx("div", { role: "status", className: "px-3 py-2 text-sm text-[var(--color-on-surface-muted)]", children: "Searching\u2026" }),
|
|
126
122
|
!loading && /* @__PURE__ */ jsx(CommandPalette.Empty, { children: failed ? "Search failed. Try again." : query ? `No results for \u201C${query}\u201D` : "Type to search" }),
|
|
127
123
|
groups.map((group) => /* @__PURE__ */ jsx(CommandPalette.Group, { heading: group.label, children: group.items.map((item) => /* @__PURE__ */ jsxs(
|
|
128
124
|
CommandPalette.Item,
|
|
@@ -134,9 +130,9 @@ function HeaderSearch({
|
|
|
134
130
|
item.onSelect();
|
|
135
131
|
},
|
|
136
132
|
children: [
|
|
137
|
-
item.icon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "
|
|
133
|
+
item.icon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "me-2 flex shrink-0 text-[var(--color-on-surface-muted)]", children: item.icon }),
|
|
138
134
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: item.label }),
|
|
139
|
-
item.hint && /* @__PURE__ */ jsx("span", { className: "
|
|
135
|
+
item.hint && /* @__PURE__ */ jsx("span", { className: "ms-auto shrink-0 ps-3 text-xs text-[var(--color-on-surface-muted)]", children: item.hint })
|
|
140
136
|
]
|
|
141
137
|
},
|
|
142
138
|
item.id
|
|
@@ -156,7 +152,7 @@ function OrgSwitcher({
|
|
|
156
152
|
const current = orgs.find((o) => o.id === currentOrgId) ?? orgs[0];
|
|
157
153
|
if (!current) return null;
|
|
158
154
|
if (orgs.length === 1) {
|
|
159
|
-
return /* @__PURE__ */ jsx("span", { title: current.name, className: cn("px-2 text-sm font-medium text-[var(--color-
|
|
155
|
+
return /* @__PURE__ */ jsx("span", { title: current.name, className: cn("px-2 text-sm font-medium text-[var(--color-on-surface-variant)]", orgLabelClass), children: current.name });
|
|
160
156
|
}
|
|
161
157
|
return (
|
|
162
158
|
// modal={false}: Radix's modal menu injects a <style> scroll lock (strict CSP).
|
|
@@ -167,14 +163,11 @@ function OrgSwitcher({
|
|
|
167
163
|
type: "button",
|
|
168
164
|
"aria-label": `${current.name}, switch organization`,
|
|
169
165
|
title: current.name,
|
|
170
|
-
className:
|
|
171
|
-
"inline-flex h-9 min-w-0 shrink-0 items-center gap-1 rounded-md px-2 text-sm sm:shrink font-medium text-[var(--color-text-primary)] transition-colors hover:bg-[var(--color-bg-subtle)]",
|
|
172
|
-
focusRing
|
|
173
|
-
),
|
|
166
|
+
className: "nx-state-layer inline-flex h-9 min-w-0 shrink-0 items-center gap-1 rounded-shape-control px-2 text-sm sm:shrink font-medium text-[var(--color-on-surface)]",
|
|
174
167
|
children: [
|
|
175
168
|
/* @__PURE__ */ jsx(Building2, { size: "md", "aria-hidden": "true", className: "shrink-0 sm:hidden" }),
|
|
176
169
|
/* @__PURE__ */ jsx("span", { className: cn("hidden sm:inline", orgLabelClass), children: current.name }),
|
|
177
|
-
/* @__PURE__ */ jsx(ChevronDown, { size: "sm", "aria-hidden": "true", className: "shrink-0 text-[var(--color-
|
|
170
|
+
/* @__PURE__ */ jsx(ChevronDown, { size: "sm", "aria-hidden": "true", className: "shrink-0 text-[var(--color-on-surface-muted)]" })
|
|
178
171
|
]
|
|
179
172
|
}
|
|
180
173
|
) }),
|
|
@@ -231,7 +224,7 @@ function AccountMenu({
|
|
|
231
224
|
return (
|
|
232
225
|
// modal={false}: Radix's modal menu injects a <style> scroll lock (strict CSP).
|
|
233
226
|
/* @__PURE__ */ jsxs(DropdownMenu.Root, { open, onOpenChange: setOpen, modal: false, children: [
|
|
234
|
-
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", "aria-label": `Account: ${user.name}`, className:
|
|
227
|
+
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", "aria-label": `Account: ${user.name}`, className: "ms-1 shrink-0 rounded-full", children: /* @__PURE__ */ jsx(Avatar, { name: user.name, src: user.avatarUrl, size: "sm", "aria-hidden": "true" }) }) }),
|
|
235
228
|
/* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsxs(DropdownMenu.Content, { align: "end", className: "w-72 max-w-[calc(100vw-1rem)]", children: [
|
|
236
229
|
/* @__PURE__ */ jsxs(DropdownMenu.Label, { className: "flex flex-col gap-0.5 py-2", children: [
|
|
237
230
|
/* @__PURE__ */ jsx("span", { className: "truncate text-title-sm text-[var(--color-on-surface)]", children: user.name }),
|
|
@@ -268,6 +261,7 @@ var AppHeader = React.forwardRef(
|
|
|
268
261
|
onSignOut,
|
|
269
262
|
accountMenuItems,
|
|
270
263
|
surface = "solid",
|
|
264
|
+
condense = false,
|
|
271
265
|
className,
|
|
272
266
|
...props
|
|
273
267
|
}, ref) => {
|
|
@@ -279,6 +273,7 @@ var AppHeader = React.forwardRef(
|
|
|
279
273
|
ref,
|
|
280
274
|
role: "banner",
|
|
281
275
|
surface,
|
|
276
|
+
"data-condense": condense ? "" : void 0,
|
|
282
277
|
className: cn("fixed inset-x-0 top-0 h-[var(--app-header-height,64px)] px-2 sm:px-4", className),
|
|
283
278
|
...props,
|
|
284
279
|
children: /* @__PURE__ */ jsxs("div", { className: "flex w-full min-w-0 items-center gap-1 sm:gap-2", children: [
|
|
@@ -293,11 +288,11 @@ var AppHeader = React.forwardRef(
|
|
|
293
288
|
onNavigate(homeHref);
|
|
294
289
|
}
|
|
295
290
|
},
|
|
296
|
-
className:
|
|
291
|
+
className: "flex min-w-0 shrink items-center rounded-shape-min p-1",
|
|
297
292
|
children: /* @__PURE__ */ jsx(Logo, { size: "sm", product: productName })
|
|
298
293
|
}
|
|
299
294
|
),
|
|
300
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
295
|
+
/* @__PURE__ */ jsx("div", { className: "ms-auto flex shrink-0 md:ms-0 md:min-w-0 md:flex-1 md:justify-center md:px-2 lg:px-4", children: (onSearch || searchItems) && /* @__PURE__ */ jsx(HeaderSearch, { placeholder, items: searchItems, onSearch }) }),
|
|
301
296
|
/* @__PURE__ */ jsxs("nav", { "aria-label": "Account and apps", className: "flex shrink-0 items-center gap-0.5 sm:gap-1", children: [
|
|
302
297
|
orgs.length > 0 && /* @__PURE__ */ jsx(OrgSwitcher, { orgs, currentOrgId, onOrgChange }),
|
|
303
298
|
showThemeSwitch && /* @__PURE__ */ jsx(ThemeSwitch, {}),
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/components/ErrorSummary/ErrorSummary.tsx
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { cn } from "@nexub/react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
var ErrorSummary = React.forwardRef(
|
|
8
|
+
({ errors, title = "There is a problem", onFocusField, className, ...props }, forwardedRef) => {
|
|
9
|
+
const ref = React.useRef(null);
|
|
10
|
+
const headingId = React.useId();
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
if (errors.length) ref.current?.focus();
|
|
13
|
+
}, [errors]);
|
|
14
|
+
if (!errors.length) return null;
|
|
15
|
+
return /* @__PURE__ */ jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
ref: (node) => {
|
|
19
|
+
ref.current = node;
|
|
20
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
21
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
22
|
+
},
|
|
23
|
+
role: "alert",
|
|
24
|
+
"aria-labelledby": headingId,
|
|
25
|
+
tabIndex: -1,
|
|
26
|
+
className: cn(
|
|
27
|
+
"w-full rounded-shape-container border-s-4 border-s-[var(--color-error)] p-4",
|
|
28
|
+
"bg-[var(--color-error-container)] text-[var(--color-on-error-container)]",
|
|
29
|
+
className
|
|
30
|
+
),
|
|
31
|
+
...props,
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsx("h2", { id: headingId, className: "text-title-md font-semibold", children: title }),
|
|
34
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-2 flex flex-col gap-1 text-body-md", children: errors.map((error) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
35
|
+
"a",
|
|
36
|
+
{
|
|
37
|
+
href: `#${error.id}`,
|
|
38
|
+
className: "underline underline-offset-[0.2em]",
|
|
39
|
+
onClick: (e) => {
|
|
40
|
+
const field = document.getElementById(error.id);
|
|
41
|
+
if (!field) return;
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
field.scrollIntoView({ block: "center" });
|
|
44
|
+
field.focus({ preventScroll: true });
|
|
45
|
+
onFocusField?.(error.id);
|
|
46
|
+
},
|
|
47
|
+
children: error.message
|
|
48
|
+
}
|
|
49
|
+
) }, error.id)) })
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
ErrorSummary.displayName = "ErrorSummary";
|
|
56
|
+
function useFormErrors(map) {
|
|
57
|
+
const errors = React.useMemo(
|
|
58
|
+
() => Object.entries(map).flatMap(([id, message]) => message ? [{ id, message }] : []),
|
|
59
|
+
[map]
|
|
60
|
+
);
|
|
61
|
+
return {
|
|
62
|
+
errors,
|
|
63
|
+
fieldProps: (id) => ({
|
|
64
|
+
id,
|
|
65
|
+
"aria-invalid": map[id] ? true : void 0,
|
|
66
|
+
"aria-describedby": map[id] ? `${id}-error` : void 0
|
|
67
|
+
}),
|
|
68
|
+
errorProps: (id) => ({ id: `${id}-error` })
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
ErrorSummary,
|
|
74
|
+
useFormErrors
|
|
75
|
+
};
|
|
@@ -7,8 +7,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
var SettingsSection = React.forwardRef(
|
|
8
8
|
({ title, description, actions, children, className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-8", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6 md:flex-row md:gap-8", children: [
|
|
9
9
|
/* @__PURE__ */ jsxs("div", { className: "md:w-1/3 flex flex-col gap-1", children: [
|
|
10
|
-
/* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-[var(--color-
|
|
11
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
10
|
+
/* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-[var(--color-on-surface)]", children: title }),
|
|
11
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)]", children: description })
|
|
12
12
|
] }),
|
|
13
13
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col gap-4", children: [
|
|
14
14
|
children,
|
|
@@ -36,8 +36,8 @@ var Root = React.forwardRef(
|
|
|
36
36
|
}
|
|
37
37
|
setMenuOpen(false);
|
|
38
38
|
};
|
|
39
|
-
const menuButton = /* @__PURE__ */ jsx(IconButton, { label: `Open ${navLabel.toLowerCase()} menu`, className: "-
|
|
40
|
-
return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex min-h-screen flex-col bg-[var(--color-
|
|
39
|
+
const menuButton = /* @__PURE__ */ jsx(IconButton, { label: `Open ${navLabel.toLowerCase()} menu`, className: "-ms-2 md:hidden", onClick: () => setMenuOpen(true), children: /* @__PURE__ */ jsx(Menu, { size: "md", "aria-hidden": "true" }) });
|
|
40
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex min-h-screen flex-col bg-[var(--color-surface)]", className), ...props, children: [
|
|
41
41
|
header ? header(menuButton) : /* @__PURE__ */ jsxs(TopNav.Root, { className: "h-[var(--app-header-height,64px)]", children: [
|
|
42
42
|
menuButton,
|
|
43
43
|
logo && /* @__PURE__ */ jsx(TopNav.Logo, { className: "min-w-0 shrink", children: logo }),
|
|
@@ -56,8 +56,8 @@ var Root = React.forwardRef(
|
|
|
56
56
|
),
|
|
57
57
|
/* @__PURE__ */ jsx("main", { className: "min-w-0 flex-1 px-4 py-6 md:px-8 md:py-10", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-6", children: [
|
|
58
58
|
(title || description) && /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-1", children: [
|
|
59
|
-
title && /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight text-[var(--color-
|
|
60
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
59
|
+
title && /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight text-[var(--color-on-surface)]", children: title }),
|
|
60
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)]", children: description })
|
|
61
61
|
] }),
|
|
62
62
|
children
|
|
63
63
|
] }) })
|
|
@@ -66,7 +66,7 @@ var Root = React.forwardRef(
|
|
|
66
66
|
/* @__PURE__ */ jsx(Sheet.Overlay, { className: "md:hidden" }),
|
|
67
67
|
/* @__PURE__ */ jsxs(Sheet.Content, { side: "left", "aria-describedby": void 0, className: "md:hidden", children: [
|
|
68
68
|
/* @__PURE__ */ jsx(Sheet.Title, { className: "px-5 pb-2 pt-5 text-base", children: navLabel }),
|
|
69
|
-
/* @__PURE__ */ jsx(SectionNav, { items, activeId, onChoose, label: navLabel, className: "w-full border-
|
|
69
|
+
/* @__PURE__ */ jsx(SectionNav, { items, activeId, onChoose, label: navLabel, className: "w-full border-e-0" })
|
|
70
70
|
] })
|
|
71
71
|
] }) })
|
|
72
72
|
] });
|
|
@@ -75,9 +75,9 @@ var Root = React.forwardRef(
|
|
|
75
75
|
Root.displayName = "SettingsLayout";
|
|
76
76
|
var Section = React.forwardRef(
|
|
77
77
|
({ title, description, className, children, ...props }, ref) => /* @__PURE__ */ jsx(Card, { asChild: true, className: cn("px-5 py-1", className), children: /* @__PURE__ */ jsxs("section", { ref, ...props, children: [
|
|
78
|
-
(title || description) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 border-b border-[var(--color-
|
|
79
|
-
title && /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-[var(--color-
|
|
80
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
78
|
+
(title || description) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 border-b border-[var(--color-outline-variant)] pb-4 pt-4", children: [
|
|
79
|
+
title && /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-[var(--color-on-surface)]", children: title }),
|
|
80
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)]", children: description })
|
|
81
81
|
] }),
|
|
82
82
|
children
|
|
83
83
|
] }) })
|
|
@@ -89,16 +89,16 @@ var SettingsRow = React.forwardRef(
|
|
|
89
89
|
{
|
|
90
90
|
ref,
|
|
91
91
|
className: cn(
|
|
92
|
-
"flex flex-col gap-2 border-t border-[var(--color-
|
|
92
|
+
"flex flex-col gap-2 border-t border-[var(--color-outline-variant)] py-4 first:border-t-0 sm:flex-row sm:items-center sm:gap-4",
|
|
93
93
|
className
|
|
94
94
|
),
|
|
95
95
|
...props,
|
|
96
96
|
children: [
|
|
97
97
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 sm:w-1/3 sm:shrink-0", children: [
|
|
98
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--color-
|
|
99
|
-
description && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-
|
|
98
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--color-on-surface)]", children: label }),
|
|
99
|
+
description && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--color-on-surface-muted)]", children: description })
|
|
100
100
|
] }),
|
|
101
|
-
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 break-words text-sm text-[var(--color-
|
|
101
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 break-words text-sm text-[var(--color-on-surface-variant)]", children: value }),
|
|
102
102
|
action && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: action })
|
|
103
103
|
]
|
|
104
104
|
}
|
|
@@ -9,7 +9,7 @@ var Root = React.forwardRef(
|
|
|
9
9
|
"dl",
|
|
10
10
|
{
|
|
11
11
|
ref,
|
|
12
|
-
className: cn("divide-y divide-[var(--color-
|
|
12
|
+
className: cn("divide-y divide-[var(--color-outline-variant)]", className),
|
|
13
13
|
...props,
|
|
14
14
|
children
|
|
15
15
|
}
|
|
@@ -17,8 +17,8 @@ var Root = React.forwardRef(
|
|
|
17
17
|
);
|
|
18
18
|
Root.displayName = "InfoList.Root";
|
|
19
19
|
var Item = ({ label, value, className }) => /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between py-3 gap-4", className), children: [
|
|
20
|
-
/* @__PURE__ */ jsx("dt", { className: "text-sm text-[var(--color-
|
|
21
|
-
/* @__PURE__ */ jsx("dd", { className: "text-sm font-medium text-[var(--color-
|
|
20
|
+
/* @__PURE__ */ jsx("dt", { className: "text-sm text-[var(--color-on-surface-muted)] shrink-0", children: label }),
|
|
21
|
+
/* @__PURE__ */ jsx("dd", { className: "text-sm font-medium text-[var(--color-on-surface)] text-end", children: value })
|
|
22
22
|
] });
|
|
23
23
|
Item.displayName = "InfoList.Item";
|
|
24
24
|
var InfoList = { Root, Item };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/components/Conversation/Conversation.tsx
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { Button, cn, useNexubMessages } from "@nexub/react";
|
|
6
|
+
import { ArrowDown } from "@nexub/icons";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var fallbackMessages = {
|
|
9
|
+
jumpToLatest: "Jump to latest",
|
|
10
|
+
conversation: "Conversation"
|
|
11
|
+
};
|
|
12
|
+
var STICK_THRESHOLD = 48;
|
|
13
|
+
function atBottom(el) {
|
|
14
|
+
return el.scrollHeight - el.scrollTop - el.clientHeight <= STICK_THRESHOLD;
|
|
15
|
+
}
|
|
16
|
+
var Conversation = React.forwardRef(
|
|
17
|
+
({ children, composer, autoScroll = true, announce = false, messages, className, ...props }, ref) => {
|
|
18
|
+
const provided = useNexubMessages();
|
|
19
|
+
const m = {
|
|
20
|
+
jumpToLatest: messages?.jumpToLatest ?? provided.jumpToLatest ?? fallbackMessages.jumpToLatest,
|
|
21
|
+
conversation: messages?.conversation ?? provided.conversation ?? fallbackMessages.conversation
|
|
22
|
+
};
|
|
23
|
+
const scrollRef = React.useRef(null);
|
|
24
|
+
const contentRef = React.useRef(null);
|
|
25
|
+
const pinnedRef = React.useRef(true);
|
|
26
|
+
const lastTop = React.useRef(0);
|
|
27
|
+
const [pinned, setPinned] = React.useState(true);
|
|
28
|
+
const setPin = React.useCallback((value) => {
|
|
29
|
+
pinnedRef.current = value;
|
|
30
|
+
setPinned(value);
|
|
31
|
+
}, []);
|
|
32
|
+
React.useEffect(() => {
|
|
33
|
+
const scroller = scrollRef.current;
|
|
34
|
+
const content = contentRef.current;
|
|
35
|
+
if (!autoScroll || !scroller || !content) return;
|
|
36
|
+
const follow = () => {
|
|
37
|
+
if (pinnedRef.current) scroller.scrollTop = scroller.scrollHeight;
|
|
38
|
+
lastTop.current = scroller.scrollTop;
|
|
39
|
+
};
|
|
40
|
+
follow();
|
|
41
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(follow) : void 0;
|
|
42
|
+
ro?.observe(content);
|
|
43
|
+
const mo = new MutationObserver(follow);
|
|
44
|
+
mo.observe(content, { childList: true, subtree: true, characterData: true });
|
|
45
|
+
return () => {
|
|
46
|
+
ro?.disconnect();
|
|
47
|
+
mo.disconnect();
|
|
48
|
+
};
|
|
49
|
+
}, [autoScroll]);
|
|
50
|
+
const onScroll = () => {
|
|
51
|
+
const el = scrollRef.current;
|
|
52
|
+
if (!el) return;
|
|
53
|
+
if (atBottom(el)) {
|
|
54
|
+
if (!pinnedRef.current) setPin(true);
|
|
55
|
+
} else if (el.scrollTop < lastTop.current && pinnedRef.current) {
|
|
56
|
+
setPin(false);
|
|
57
|
+
}
|
|
58
|
+
lastTop.current = el.scrollTop;
|
|
59
|
+
};
|
|
60
|
+
const jump = () => {
|
|
61
|
+
const el = scrollRef.current;
|
|
62
|
+
if (!el) return;
|
|
63
|
+
setPin(true);
|
|
64
|
+
const reduce = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
65
|
+
const top = el.scrollHeight;
|
|
66
|
+
if (typeof el.scrollTo === "function") el.scrollTo({ top, behavior: reduce ? "auto" : "smooth" });
|
|
67
|
+
else el.scrollTop = top;
|
|
68
|
+
};
|
|
69
|
+
const live = announce ? { role: "log", "aria-live": "polite", "aria-relevant": "additions" } : { role: "region" };
|
|
70
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex h-full min-h-0 flex-col", className), ...props, children: [
|
|
71
|
+
/* @__PURE__ */ jsxs("div", { className: "relative min-h-0 flex-1", children: [
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
"div",
|
|
74
|
+
{
|
|
75
|
+
ref: scrollRef,
|
|
76
|
+
onScroll,
|
|
77
|
+
"aria-label": m.conversation,
|
|
78
|
+
tabIndex: 0,
|
|
79
|
+
...live,
|
|
80
|
+
className: cn(
|
|
81
|
+
"h-full overflow-y-auto",
|
|
82
|
+
composer && "[-webkit-mask-image:linear-gradient(to_bottom,black_calc(100%-24px),transparent)] [mask-image:linear-gradient(to_bottom,black_calc(100%-24px),transparent)]"
|
|
83
|
+
),
|
|
84
|
+
children: /* @__PURE__ */ jsx("div", { ref: contentRef, className: "mx-auto flex w-full max-w-3xl flex-col gap-6 px-4 pb-8 pt-6", children })
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
autoScroll && !pinned && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
88
|
+
Button,
|
|
89
|
+
{
|
|
90
|
+
type: "button",
|
|
91
|
+
variant: "tonal",
|
|
92
|
+
size: "sm",
|
|
93
|
+
"data-state": "open",
|
|
94
|
+
onClick: jump,
|
|
95
|
+
leadingIcon: /* @__PURE__ */ jsx(ArrowDown, { size: "sm", "aria-hidden": "true" }),
|
|
96
|
+
className: "nx-motion nx-pop pointer-events-auto shadow-elevation-2",
|
|
97
|
+
children: m.jumpToLatest
|
|
98
|
+
}
|
|
99
|
+
) })
|
|
100
|
+
] }),
|
|
101
|
+
composer && /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-4 pb-4", children: composer })
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
Conversation.displayName = "Conversation";
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
Conversation
|
|
109
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/components/BentoGrid/BentoGrid.tsx
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { Card, cn } from "@nexub/react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var BentoGrid = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("[container-type:inline-size]", className), ...props, children: /* @__PURE__ */ jsx("div", { className: "grid grid-flow-row-dense auto-rows-[minmax(10rem,auto)] grid-cols-1 gap-4 [@container(min-width:480px)]:grid-cols-2 [@container(min-width:768px)]:grid-cols-4", children }) }));
|
|
8
|
+
BentoGrid.displayName = "BentoGrid";
|
|
9
|
+
var sizes = {
|
|
10
|
+
"1x1": "",
|
|
11
|
+
"2x1": "[@container(min-width:480px)]:col-span-2",
|
|
12
|
+
"1x2": "row-span-2",
|
|
13
|
+
"2x2": "[@container(min-width:480px)]:col-span-2 row-span-2"
|
|
14
|
+
};
|
|
15
|
+
var BentoTile = React.forwardRef(
|
|
16
|
+
({ size = "1x1", className, ...props }, ref) => /* @__PURE__ */ jsx(Card, { ref, variant: "surface", className: cn("min-w-0 p-4", sizes[size], className), "data-size": size, ...props })
|
|
17
|
+
);
|
|
18
|
+
BentoTile.displayName = "BentoTile";
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
BentoGrid,
|
|
22
|
+
BentoTile
|
|
23
|
+
};
|
|
@@ -23,27 +23,27 @@ var PlanCard = React.forwardRef(
|
|
|
23
23
|
{
|
|
24
24
|
ref,
|
|
25
25
|
className: cn(
|
|
26
|
-
"relative flex flex-col gap-6 rounded-
|
|
27
|
-
highlighted ? "border-[var(--color-
|
|
26
|
+
"relative flex flex-col gap-6 rounded-shape-container bg-[var(--color-surface-elevated)] text-[var(--color-on-surface)] p-6",
|
|
27
|
+
highlighted ? "border-2 border-[var(--color-primary)] shadow-elevation-2" : "border border-[color-mix(in_srgb,var(--color-outline-variant)_60%,transparent)] shadow-elevation-1",
|
|
28
28
|
className
|
|
29
29
|
),
|
|
30
30
|
...props,
|
|
31
31
|
children: [
|
|
32
32
|
badge && /* @__PURE__ */ jsx("div", { className: "absolute -top-3 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx(Badge, { tone: "info", children: badge }) }),
|
|
33
33
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
34
|
-
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-[var(--color-
|
|
34
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-[var(--color-on-surface)]", children: name }),
|
|
35
35
|
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1", children: [
|
|
36
|
-
/* @__PURE__ */ jsx("span", { className: "text-3xl font-bold text-[var(--color-
|
|
37
|
-
period && /* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--color-
|
|
36
|
+
/* @__PURE__ */ jsx("span", { className: "text-3xl font-bold text-[var(--color-on-surface)]", children: price }),
|
|
37
|
+
period && /* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--color-on-surface-muted)]", children: period })
|
|
38
38
|
] }),
|
|
39
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
39
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)]", children: description })
|
|
40
40
|
] }),
|
|
41
41
|
/* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: features.map((feature) => /* @__PURE__ */ jsxs(
|
|
42
42
|
"li",
|
|
43
43
|
{
|
|
44
|
-
className: "flex items-center gap-2 text-sm text-[var(--color-
|
|
44
|
+
className: "flex items-center gap-2 text-sm text-[var(--color-on-surface-variant)]",
|
|
45
45
|
children: [
|
|
46
|
-
/* @__PURE__ */ jsx(Check, { size: "xs", className: "text-[var(--color-success
|
|
46
|
+
/* @__PURE__ */ jsx(Check, { size: "xs", className: "text-[var(--color-success)] shrink-0", "aria-hidden": "true" }),
|
|
47
47
|
feature
|
|
48
48
|
]
|
|
49
49
|
},
|
|
@@ -13,11 +13,11 @@ var FilterBar = React.forwardRef(
|
|
|
13
13
|
placeholder: searchPlaceholder ?? "Search\u2026",
|
|
14
14
|
value: searchValue,
|
|
15
15
|
onChange: (e) => onSearch?.(e.target.value),
|
|
16
|
-
className: "h-9 rounded-
|
|
16
|
+
className: "h-9 rounded-shape-field border border-[var(--color-outline-variant)] bg-[var(--color-surface-container-lowest)] px-3 py-2 text-sm text-[var(--color-on-surface)] placeholder:text-[var(--color-on-surface-muted)] w-full sm:w-64"
|
|
17
17
|
}
|
|
18
18
|
),
|
|
19
19
|
filters && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: filters }),
|
|
20
|
-
actions && /* @__PURE__ */ jsx("div", { className: "
|
|
20
|
+
actions && /* @__PURE__ */ jsx("div", { className: "ms-auto flex items-center gap-2", children: actions })
|
|
21
21
|
] })
|
|
22
22
|
);
|
|
23
23
|
FilterBar.displayName = "FilterBar";
|
|
@@ -10,8 +10,8 @@ var NotificationItem = React.forwardRef(
|
|
|
10
10
|
{
|
|
11
11
|
ref,
|
|
12
12
|
className: cn(
|
|
13
|
-
"flex items-start gap-3 p-3 rounded-
|
|
14
|
-
!read && "bg-[var(--color-
|
|
13
|
+
"nx-state-layer flex items-start gap-3 p-3 rounded-shape-container",
|
|
14
|
+
!read && "bg-[var(--color-surface-container-low)]",
|
|
15
15
|
className
|
|
16
16
|
),
|
|
17
17
|
...props,
|
|
@@ -19,15 +19,15 @@ var NotificationItem = React.forwardRef(
|
|
|
19
19
|
!read && /* @__PURE__ */ jsx(
|
|
20
20
|
"span",
|
|
21
21
|
{
|
|
22
|
-
className: "mt-1.5 h-2 w-2 shrink-0 rounded-full bg-[var(--color-
|
|
22
|
+
className: "mt-1.5 h-2 w-2 shrink-0 rounded-full bg-[var(--color-primary)]",
|
|
23
23
|
"aria-label": "Unread"
|
|
24
24
|
}
|
|
25
25
|
),
|
|
26
26
|
icon && /* @__PURE__ */ jsx("div", { className: "shrink-0 mt-0.5", children: icon }),
|
|
27
27
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
28
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--color-
|
|
29
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-
|
|
30
|
-
timestamp && /* @__PURE__ */ jsx("time", { className: "text-xs text-[var(--color-
|
|
28
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--color-on-surface)] truncate", children: title }),
|
|
29
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--color-on-surface-muted)] mt-0.5 line-clamp-2", children: description }),
|
|
30
|
+
timestamp && /* @__PURE__ */ jsx("time", { className: "text-xs text-[var(--color-on-surface-muted)] mt-1 block", children: timestamp })
|
|
31
31
|
] }),
|
|
32
32
|
onDismiss && /* @__PURE__ */ jsx(
|
|
33
33
|
"button",
|
|
@@ -35,7 +35,7 @@ var NotificationItem = React.forwardRef(
|
|
|
35
35
|
type: "button",
|
|
36
36
|
onClick: onDismiss,
|
|
37
37
|
"aria-label": "Dismiss notification",
|
|
38
|
-
className: "shrink-0 text-[var(--color-
|
|
38
|
+
className: "shrink-0 text-[var(--color-on-surface-muted)] hover:text-[var(--color-on-surface)] p-1 rounded-shape-control",
|
|
39
39
|
children: "\xD7"
|
|
40
40
|
}
|
|
41
41
|
)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import * as React from 'react';
|
|
2
|
+
import { CardProps } from '@nexub/react';
|
|
3
3
|
|
|
4
4
|
interface ActivityItemProps {
|
|
5
5
|
avatar?: React.ReactNode;
|
|
@@ -11,7 +11,7 @@ interface ActivityItemProps {
|
|
|
11
11
|
declare const ActivityFeed: {
|
|
12
12
|
Root: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLUListElement> & React.RefAttributes<HTMLUListElement>>;
|
|
13
13
|
Item: {
|
|
14
|
-
({ avatar, title, description, timestamp, className }: ActivityItemProps):
|
|
14
|
+
({ avatar, title, description, timestamp, className }: ActivityItemProps): React.JSX.Element;
|
|
15
15
|
displayName: string;
|
|
16
16
|
};
|
|
17
17
|
};
|
|
@@ -32,6 +32,8 @@ interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
32
32
|
deltaType?: 'increase' | 'decrease' | 'neutral';
|
|
33
33
|
icon?: React.ReactNode;
|
|
34
34
|
description?: string;
|
|
35
|
+
/** Roll digits when a number/string `value` changes (NumberTicker); announced politely. */
|
|
36
|
+
animate?: boolean;
|
|
35
37
|
}
|
|
36
38
|
declare const StatCard: React.ForwardRefExoticComponent<StatCardProps & React.RefAttributes<HTMLDivElement>>;
|
|
37
39
|
|
|
@@ -54,7 +56,7 @@ interface AuthCardProps {
|
|
|
54
56
|
footer?: React.ReactNode;
|
|
55
57
|
className?: string;
|
|
56
58
|
}
|
|
57
|
-
declare function AuthCard({ logo, title, description, children, footer, className, }: AuthCardProps):
|
|
59
|
+
declare function AuthCard({ logo, title, description, children, footer, className, }: AuthCardProps): React.JSX.Element;
|
|
58
60
|
declare namespace AuthCard {
|
|
59
61
|
var displayName: string;
|
|
60
62
|
}
|
|
@@ -78,7 +80,7 @@ interface InfoListItemProps {
|
|
|
78
80
|
declare const InfoList: {
|
|
79
81
|
Root: React.ForwardRefExoticComponent<InfoListRootProps & React.RefAttributes<HTMLDListElement>>;
|
|
80
82
|
Item: {
|
|
81
|
-
({ label, value, className }: InfoListItemProps):
|
|
83
|
+
({ label, value, className }: InfoListItemProps): React.JSX.Element;
|
|
82
84
|
displayName: string;
|
|
83
85
|
};
|
|
84
86
|
};
|
|
@@ -264,6 +266,8 @@ interface AppHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'childr
|
|
|
264
266
|
surface?: 'solid' | 'glass';
|
|
265
267
|
/** `soft`: page content dissolves under the header instead of meeting a divider. */
|
|
266
268
|
scrollEdge?: 'soft' | 'hard';
|
|
269
|
+
/** Shrink 64 → 52px and lift onto elevation 1 over the first 64px of page scroll (CSS scroll timeline; static where unsupported). */
|
|
270
|
+
condense?: boolean;
|
|
267
271
|
}
|
|
268
272
|
/**
|
|
269
273
|
* The one top header every Nexub app shares. Fixed to the top; renders a
|
|
@@ -271,4 +275,83 @@ interface AppHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'childr
|
|
|
271
275
|
*/
|
|
272
276
|
declare const AppHeader: React.ForwardRefExoticComponent<AppHeaderProps & React.RefAttributes<HTMLElement>>;
|
|
273
277
|
|
|
274
|
-
|
|
278
|
+
interface BentoGridProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* A bento grid that responds to its *own* width (container query): 1 column,
|
|
282
|
+
* 2 at 480px, 4 at 768px. Dense packing back-fills gaps left by large tiles.
|
|
283
|
+
*/
|
|
284
|
+
declare const BentoGrid: React.ForwardRefExoticComponent<BentoGridProps & React.RefAttributes<HTMLDivElement>>;
|
|
285
|
+
type BentoTileSize = '1x1' | '2x1' | '1x2' | '2x2';
|
|
286
|
+
interface BentoTileProps extends Omit<CardProps, 'variant'> {
|
|
287
|
+
/** @default '1x1' */
|
|
288
|
+
size?: BentoTileSize;
|
|
289
|
+
}
|
|
290
|
+
/** A Card-styled cell of a BentoGrid. */
|
|
291
|
+
declare const BentoTile: React.ForwardRefExoticComponent<BentoTileProps & React.RefAttributes<HTMLDivElement>>;
|
|
292
|
+
|
|
293
|
+
interface ErrorSummaryItem {
|
|
294
|
+
/** The field's DOM id (the link target). */
|
|
295
|
+
id: string;
|
|
296
|
+
message: string;
|
|
297
|
+
}
|
|
298
|
+
interface ErrorSummaryProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
299
|
+
errors: ErrorSummaryItem[];
|
|
300
|
+
/** @default 'There is a problem' */
|
|
301
|
+
title?: React.ReactNode;
|
|
302
|
+
/** Called after a link moves focus to its field. */
|
|
303
|
+
onFocusField?: (id: string) => void;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Lists a form's errors after a failed submit (GOV.UK pattern). It takes focus
|
|
307
|
+
* whenever it receives a new `errors` array with entries, so pass a new array per
|
|
308
|
+
* submit (not per keystroke). Each link focuses its field.
|
|
309
|
+
*/
|
|
310
|
+
declare const ErrorSummary: React.ForwardRefExoticComponent<ErrorSummaryProps & React.RefAttributes<HTMLDivElement>>;
|
|
311
|
+
type FormErrorMap = Record<string, string | null | undefined | false>;
|
|
312
|
+
/**
|
|
313
|
+
* Turns `{ fieldId: message }` into the ErrorSummary list plus the ARIA wiring
|
|
314
|
+
* for each field and its inline message (`${id}-error`, the same id
|
|
315
|
+
* FormField.Error uses).
|
|
316
|
+
*/
|
|
317
|
+
declare function useFormErrors(map: FormErrorMap): {
|
|
318
|
+
errors: ErrorSummaryItem[];
|
|
319
|
+
fieldProps: (id: string) => {
|
|
320
|
+
id: string;
|
|
321
|
+
'aria-invalid': true | undefined;
|
|
322
|
+
'aria-describedby': string | undefined;
|
|
323
|
+
};
|
|
324
|
+
errorProps: (id: string) => {
|
|
325
|
+
id: string;
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
interface ConversationMessages {
|
|
330
|
+
/** Floating button shown when the reader has scrolled up. */
|
|
331
|
+
jumpToLatest: string;
|
|
332
|
+
/** Accessible name of the message list. */
|
|
333
|
+
conversation: string;
|
|
334
|
+
}
|
|
335
|
+
interface ConversationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
336
|
+
/** The messages. */
|
|
337
|
+
children?: React.ReactNode;
|
|
338
|
+
/** Sticky composer slot under the list, e.g. a PromptInput. */
|
|
339
|
+
composer?: React.ReactNode;
|
|
340
|
+
/** Keep the view pinned to the newest content while the reader is at the bottom. @default true */
|
|
341
|
+
autoScroll?: boolean;
|
|
342
|
+
/**
|
|
343
|
+
* Make the list a polite live log (role="log"). Off by default: token streaming
|
|
344
|
+
* would announce every chunk. Turn on for whole-message updates only.
|
|
345
|
+
* @default false
|
|
346
|
+
*/
|
|
347
|
+
announce?: boolean;
|
|
348
|
+
messages?: Partial<ConversationMessages>;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Chat layout: a scrolling message list (max-w-3xl, centred) with a sticky
|
|
352
|
+
* composer at the bottom. Sticks to the bottom as content streams in while the
|
|
353
|
+
* reader is there; scrolling up stops following and offers "Jump to latest".
|
|
354
|
+
*/
|
|
355
|
+
declare const Conversation: React.ForwardRefExoticComponent<ConversationProps & React.RefAttributes<HTMLDivElement>>;
|
|
356
|
+
|
|
357
|
+
export { ActivityFeed, type ActivityItemProps, AppHeader, type AppHeaderOrg, type AppHeaderProps, type AppHeaderSearchGroup, type AppHeaderSearchItem, type AppHeaderUser, AppLauncher, type AppLauncherApp, type AppLauncherProps, AuthCard, type AuthCardProps, BentoGrid, type BentoGridProps, BentoTile, type BentoTileProps, type BentoTileSize, Conversation, type ConversationMessages, type ConversationProps, ErrorSummary, type ErrorSummaryItem, type ErrorSummaryProps, FilterBar, type FilterBarProps, type FormErrorMap, InfoList, type InfoListItemProps, type InfoListRootProps, ListDetail, type ListDetailProps, NotificationItem, type NotificationItemProps, PlanCard, type PlanCardProps, SettingsLayout, type SettingsLayoutItem, type SettingsLayoutProps, type SettingsLayoutSectionProps, SettingsRow, type SettingsRowProps, SettingsSection, type SettingsSectionProps, StatCard, type StatCardProps, StepIndicator, type StepIndicatorProps, type StepIndicatorStep, UserCard, type UserCardProps, useFormErrors };
|
package/dist/index.js
CHANGED
|
@@ -1,53 +1,68 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import {
|
|
3
|
+
InfoList
|
|
4
|
+
} from "./chunk-WPNT5JOU.js";
|
|
5
|
+
import {
|
|
6
|
+
StepIndicator
|
|
7
|
+
} from "./chunk-L456OB3Q.js";
|
|
8
|
+
import {
|
|
9
|
+
FilterBar
|
|
10
|
+
} from "./chunk-Z6VMCMSW.js";
|
|
11
|
+
import {
|
|
12
|
+
ListDetail
|
|
13
|
+
} from "./chunk-5JU6HUVJ.js";
|
|
2
14
|
import {
|
|
3
15
|
NotificationItem
|
|
4
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ZV73WS4X.js";
|
|
5
17
|
import {
|
|
6
18
|
PlanCard
|
|
7
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-YB7G4YBU.js";
|
|
8
20
|
import {
|
|
9
21
|
SettingsLayout,
|
|
10
22
|
SettingsRow
|
|
11
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-WIHNK7RT.js";
|
|
12
24
|
import {
|
|
13
25
|
SettingsSection
|
|
14
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-U3FT7XAU.js";
|
|
15
27
|
import {
|
|
16
28
|
StatCard
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import {
|
|
19
|
-
StepIndicator
|
|
20
|
-
} from "./chunk-MXPRKZPB.js";
|
|
29
|
+
} from "./chunk-K5EFLRKU.js";
|
|
21
30
|
import {
|
|
22
31
|
UserCard
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import {
|
|
25
|
-
AppHeader
|
|
26
|
-
} from "./chunk-OYSWFXRD.js";
|
|
32
|
+
} from "./chunk-7NYGYETG.js";
|
|
27
33
|
import {
|
|
28
34
|
ActivityFeed
|
|
29
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-JTIMCXPS.js";
|
|
36
|
+
import {
|
|
37
|
+
AppHeader
|
|
38
|
+
} from "./chunk-LAYYOVIK.js";
|
|
30
39
|
import "./chunk-VYMTTYPR.js";
|
|
31
40
|
import {
|
|
32
41
|
AppLauncher
|
|
33
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-H5UTW5ML.js";
|
|
34
43
|
import {
|
|
35
44
|
AuthCard
|
|
36
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-HMJRSNJD.js";
|
|
37
46
|
import {
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
BentoGrid,
|
|
48
|
+
BentoTile
|
|
49
|
+
} from "./chunk-WZTDCJYP.js";
|
|
40
50
|
import {
|
|
41
|
-
|
|
42
|
-
} from "./chunk-
|
|
51
|
+
Conversation
|
|
52
|
+
} from "./chunk-WRP73TXG.js";
|
|
43
53
|
import {
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
ErrorSummary,
|
|
55
|
+
useFormErrors
|
|
56
|
+
} from "./chunk-RWPFCNMJ.js";
|
|
46
57
|
export {
|
|
47
58
|
ActivityFeed,
|
|
48
59
|
AppHeader,
|
|
49
60
|
AppLauncher,
|
|
50
61
|
AuthCard,
|
|
62
|
+
BentoGrid,
|
|
63
|
+
BentoTile,
|
|
64
|
+
Conversation,
|
|
65
|
+
ErrorSummary,
|
|
51
66
|
FilterBar,
|
|
52
67
|
InfoList,
|
|
53
68
|
ListDetail,
|
|
@@ -58,5 +73,6 @@ export {
|
|
|
58
73
|
SettingsSection,
|
|
59
74
|
StatCard,
|
|
60
75
|
StepIndicator,
|
|
61
|
-
UserCard
|
|
76
|
+
UserCard,
|
|
77
|
+
useFormErrors
|
|
62
78
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexub/patterns",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Composite UI patterns for Nexub Design System — pre-built, production-ready layouts and widgets built on @nexub/react.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": ">=18 <20",
|
|
38
38
|
"react-dom": ">=18 <20",
|
|
39
|
-
"@nexub/
|
|
40
|
-
"@nexub/
|
|
41
|
-
"@nexub/tokens": "^1.
|
|
39
|
+
"@nexub/icons": "^1.6.0",
|
|
40
|
+
"@nexub/react": "^1.6.0",
|
|
41
|
+
"@nexub/tokens": "^1.6.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"@nexub/icons": {
|
|
@@ -49,18 +49,19 @@
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@testing-library/jest-dom": "^6.
|
|
53
|
-
"@testing-library/react": "^16.
|
|
54
|
-
"@testing-library/user-event": "^14.
|
|
55
|
-
"@types/react": "^19.
|
|
56
|
-
"@types/react-dom": "^19.
|
|
57
|
-
"jsdom": "^
|
|
58
|
-
"tsup": "^8.
|
|
59
|
-
"typescript": "^5.
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"@nexub/
|
|
63
|
-
"@nexub/
|
|
52
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
53
|
+
"@testing-library/react": "^16.3.3",
|
|
54
|
+
"@testing-library/user-event": "^14.6.8",
|
|
55
|
+
"@types/react": "^19.3.0",
|
|
56
|
+
"@types/react-dom": "^19.3.0",
|
|
57
|
+
"jsdom": "^30.1.3",
|
|
58
|
+
"tsup": "^8.5.1",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"vite": "^7.3.7",
|
|
61
|
+
"vitest": "^5.0.5",
|
|
62
|
+
"@nexub/icons": "1.6.0",
|
|
63
|
+
"@nexub/react": "1.6.0",
|
|
64
|
+
"@nexub/tokens": "1.6.0"
|
|
64
65
|
},
|
|
65
66
|
"scripts": {
|
|
66
67
|
"build": "tsup",
|