@nexub/react 6.3.0 → 6.5.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/accessibility.json +55 -1
- package/dist/components/ActionBar/ActionBar.d.ts +12 -0
- package/dist/components/ActionBar/ActionBar.js +27 -0
- package/dist/components/ActionBar/index.d.ts +2 -0
- package/dist/components/ActionBar/index.js +4 -0
- package/dist/components/DataTable/DataTable.d.ts +8 -1
- package/dist/components/DataTable/DataTable.js +31 -4
- package/dist/components/Kanban/Kanban.d.ts +20 -0
- package/dist/components/Kanban/Kanban.js +50 -0
- package/dist/components/Kanban/index.d.ts +2 -0
- package/dist/components/Kanban/index.js +4 -0
- package/dist/components/ResizablePanels/ResizablePanels.d.ts +20 -0
- package/dist/components/ResizablePanels/ResizablePanels.js +121 -0
- package/dist/components/ResizablePanels/index.d.ts +2 -0
- package/dist/components/ResizablePanels/index.js +4 -0
- package/dist/components/Sortable/Sortable.d.ts +18 -0
- package/dist/components/Sortable/Sortable.js +31 -0
- package/dist/components/Sortable/index.d.ts +2 -0
- package/dist/components/Sortable/index.js +4 -0
- package/dist/components/Sortable/reorder.d.ts +29 -0
- package/dist/components/Sortable/reorder.js +114 -0
- package/dist/components/Stepper/Stepper.d.ts +27 -0
- package/dist/components/Stepper/Stepper.js +74 -0
- package/dist/components/Stepper/index.d.ts +2 -0
- package/dist/components/Stepper/index.js +4 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/styles.css +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { GripVertical } from "@nexub/icons";
|
|
5
|
+
import { cn } from "../../utils/cn.js";
|
|
6
|
+
import { useLocale, useNexubMessages } from "../NexubProvider/NexubProvider.js";
|
|
7
|
+
function moveItem(lists, [fc, fi], [tc, ti]) {
|
|
8
|
+
const next = lists.map((l) => [...l]);
|
|
9
|
+
const [item] = next[fc].splice(fi, 1);
|
|
10
|
+
if (item === void 0) return lists;
|
|
11
|
+
next[tc].splice(Math.min(ti, next[tc].length), 0, item);
|
|
12
|
+
return next;
|
|
13
|
+
}
|
|
14
|
+
function useReorder({ lists, getId, getLabel, listLabels, onMove }) {
|
|
15
|
+
const t = useNexubMessages();
|
|
16
|
+
const { dir } = useLocale();
|
|
17
|
+
const dragged = React.useRef(null);
|
|
18
|
+
const handles = React.useRef(/* @__PURE__ */ new Map());
|
|
19
|
+
const refocus = React.useRef(null);
|
|
20
|
+
const [announcement, setAnnouncement] = React.useState("");
|
|
21
|
+
const hintId = React.useId();
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (refocus.current) handles.current.get(refocus.current)?.focus();
|
|
24
|
+
refocus.current = null;
|
|
25
|
+
});
|
|
26
|
+
const move = (from, to, keepFocus) => {
|
|
27
|
+
if (from[0] === to[0] && from[1] === to[1]) return;
|
|
28
|
+
const item = lists[from[0]][from[1]];
|
|
29
|
+
const next = moveItem(lists, from, to);
|
|
30
|
+
const [tc] = to;
|
|
31
|
+
const ti = next[tc].indexOf(item);
|
|
32
|
+
if (keepFocus) refocus.current = getId(item);
|
|
33
|
+
onMove(next);
|
|
34
|
+
const total = next[tc].length;
|
|
35
|
+
setAnnouncement(
|
|
36
|
+
from[0] !== tc && listLabels?.[tc] ? t.itemMovedToColumn(getLabel(item), listLabels[tc], ti + 1, total) : t.itemMoved(getLabel(item), ti + 1, total)
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
const itemProps = (pos) => ({
|
|
40
|
+
draggable: true,
|
|
41
|
+
onDragStart: (e) => {
|
|
42
|
+
dragged.current = pos;
|
|
43
|
+
e.dataTransfer.effectAllowed = "move";
|
|
44
|
+
},
|
|
45
|
+
onDragOver: (e) => {
|
|
46
|
+
if (dragged.current) e.preventDefault();
|
|
47
|
+
},
|
|
48
|
+
onDrop: (e) => {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
e.stopPropagation();
|
|
51
|
+
if (dragged.current) move(dragged.current, pos, false);
|
|
52
|
+
dragged.current = null;
|
|
53
|
+
},
|
|
54
|
+
onDragEnd: () => {
|
|
55
|
+
dragged.current = null;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const listProps = (list) => ({
|
|
59
|
+
onDragOver: (e) => {
|
|
60
|
+
if (dragged.current) e.preventDefault();
|
|
61
|
+
},
|
|
62
|
+
onDrop: (e) => {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
if (dragged.current) move(dragged.current, [list, lists[list].length], false);
|
|
65
|
+
dragged.current = null;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const handle = (pos, className) => {
|
|
69
|
+
const item = lists[pos[0]][pos[1]];
|
|
70
|
+
const id = getId(item);
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
"button",
|
|
73
|
+
{
|
|
74
|
+
type: "button",
|
|
75
|
+
ref: (el) => {
|
|
76
|
+
if (el) handles.current.set(id, el);
|
|
77
|
+
else handles.current.delete(id);
|
|
78
|
+
},
|
|
79
|
+
"aria-label": t.moveItem(getLabel(item)),
|
|
80
|
+
"aria-describedby": hintId,
|
|
81
|
+
onKeyDown: (e) => {
|
|
82
|
+
if (!e.altKey) return;
|
|
83
|
+
const [c, i] = pos;
|
|
84
|
+
const sideways = lists.length > 1;
|
|
85
|
+
const toNext = dir === "rtl" ? "ArrowLeft" : "ArrowRight";
|
|
86
|
+
const toPrev = dir === "rtl" ? "ArrowRight" : "ArrowLeft";
|
|
87
|
+
let to = null;
|
|
88
|
+
if (e.key === "ArrowUp" && i > 0) to = [c, i - 1];
|
|
89
|
+
else if (e.key === "ArrowDown" && i < lists[c].length - 1) to = [c, i + 1];
|
|
90
|
+
else if (sideways && e.key === toNext && c < lists.length - 1) to = [c + 1, i];
|
|
91
|
+
else if (sideways && e.key === toPrev && c > 0) to = [c - 1, i];
|
|
92
|
+
if (!to) return;
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
move(pos, to, true);
|
|
95
|
+
},
|
|
96
|
+
className: cn(
|
|
97
|
+
"inline-flex size-7 shrink-0 cursor-grab items-center justify-center rounded-shape-min text-[var(--color-on-surface-variant)]",
|
|
98
|
+
"hover:bg-[var(--color-surface-container-high)] active:cursor-grabbing",
|
|
99
|
+
className
|
|
100
|
+
),
|
|
101
|
+
children: /* @__PURE__ */ jsx(GripVertical, { size: "sm", "aria-hidden": "true" })
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
const live = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
106
|
+
/* @__PURE__ */ jsx("span", { id: hintId, hidden: true, children: t.reorderHint }),
|
|
107
|
+
/* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: announcement })
|
|
108
|
+
] });
|
|
109
|
+
return { itemProps, listProps, handle, live };
|
|
110
|
+
}
|
|
111
|
+
export {
|
|
112
|
+
moveItem,
|
|
113
|
+
useReorder
|
|
114
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface StepperStep {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface StepperProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
8
|
+
steps: StepperStep[];
|
|
9
|
+
/** Index of the step being shown. */
|
|
10
|
+
current: number;
|
|
11
|
+
/** Indexes of finished steps. @default every step before `current` */
|
|
12
|
+
completed?: number[];
|
|
13
|
+
/**
|
|
14
|
+
* Makes steps clickable. Linear by default: finished steps, the current one
|
|
15
|
+
* and the first unfinished one can be reached; the rest wait.
|
|
16
|
+
*/
|
|
17
|
+
onStepChange?: (index: number) => void;
|
|
18
|
+
/** Any step can be reached. */
|
|
19
|
+
nonLinear?: boolean;
|
|
20
|
+
/** @default 'horizontal' */
|
|
21
|
+
orientation?: 'horizontal' | 'vertical';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Progress through a multi-step flow. Validate each step (a `Form` per step
|
|
25
|
+
* works well) and move `current` forward from its submit.
|
|
26
|
+
*/
|
|
27
|
+
export declare const Stepper: React.ForwardRefExoticComponent<StepperProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Check } from "@nexub/icons";
|
|
5
|
+
import { cn } from "../../utils/cn.js";
|
|
6
|
+
import { useNexubMessages } from "../NexubProvider/NexubProvider.js";
|
|
7
|
+
const Stepper = React.forwardRef(function Stepper2({ steps, current, completed: completedProp, onStepChange, nonLinear = false, orientation = "horizontal", className, ...props }, ref) {
|
|
8
|
+
const t = useNexubMessages();
|
|
9
|
+
const completed = new Set(completedProp ?? steps.slice(0, current).map((_, i) => i));
|
|
10
|
+
const firstOpen = steps.findIndex((_, i) => !completed.has(i));
|
|
11
|
+
const vertical = orientation === "vertical";
|
|
12
|
+
return /* @__PURE__ */ jsx("nav", { ref, className, ...props, children: /* @__PURE__ */ jsx("ol", { className: cn("m-0 flex list-none p-0", vertical ? "flex-col" : "flex-row items-start"), children: steps.map((step, i) => {
|
|
13
|
+
const done = completed.has(i);
|
|
14
|
+
const isCurrent = i === current;
|
|
15
|
+
const reachable = Boolean(onStepChange) && !isCurrent && (nonLinear || done || i === firstOpen);
|
|
16
|
+
const marker = /* @__PURE__ */ jsx(
|
|
17
|
+
"span",
|
|
18
|
+
{
|
|
19
|
+
"aria-hidden": "true",
|
|
20
|
+
className: cn(
|
|
21
|
+
"inline-flex size-8 shrink-0 items-center justify-center rounded-full text-label-md font-semibold",
|
|
22
|
+
done && !isCurrent ? "bg-[var(--color-primary)] text-[var(--color-on-primary)]" : isCurrent ? "border-2 border-[var(--color-primary)] bg-[var(--color-surface)] text-[var(--color-primary)]" : "border-2 border-[var(--color-outline-variant)] bg-[var(--color-surface)] text-[var(--color-on-surface-muted)]"
|
|
23
|
+
),
|
|
24
|
+
children: done && !isCurrent ? /* @__PURE__ */ jsx(Check, { size: "xs" }) : i + 1
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
const text = /* @__PURE__ */ jsxs("span", { className: cn("flex min-w-0 flex-col gap-0.5", vertical ? "items-start text-start" : "items-center text-center"), children: [
|
|
28
|
+
/* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
29
|
+
t.stepOf(i + 1, steps.length),
|
|
30
|
+
":"
|
|
31
|
+
] }),
|
|
32
|
+
" ",
|
|
33
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-label-lg font-medium", isCurrent || done ? "text-[var(--color-on-surface)]" : "text-[var(--color-on-surface-muted)]"), children: step.label }),
|
|
34
|
+
done && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
35
|
+
", ",
|
|
36
|
+
t.stepCompleted
|
|
37
|
+
] }),
|
|
38
|
+
step.description && /* @__PURE__ */ jsx("span", { className: "text-body-sm text-[var(--color-on-surface-muted)]", children: step.description })
|
|
39
|
+
] });
|
|
40
|
+
const body = vertical ? /* @__PURE__ */ jsxs("span", { className: "flex gap-3", children: [
|
|
41
|
+
marker,
|
|
42
|
+
/* @__PURE__ */ jsx("span", { className: "pt-1", children: text })
|
|
43
|
+
] }) : /* @__PURE__ */ jsxs("span", { className: "flex flex-col items-center gap-2 text-center", children: [
|
|
44
|
+
marker,
|
|
45
|
+
text
|
|
46
|
+
] });
|
|
47
|
+
return /* @__PURE__ */ jsx(
|
|
48
|
+
"li",
|
|
49
|
+
{
|
|
50
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
51
|
+
className: cn(
|
|
52
|
+
"relative flex",
|
|
53
|
+
vertical ? "pb-6 last:pb-0" : "flex-1 justify-center",
|
|
54
|
+
// Connector to the next step.
|
|
55
|
+
i < steps.length - 1 && (vertical ? "after:absolute after:start-4 after:top-9 after:bottom-1 after:w-px" : "after:absolute after:top-4 after:start-[calc(50%+1.25rem)] after:end-[calc(-50%+1.25rem)] after:h-px"),
|
|
56
|
+
i < steps.length - 1 && (done ? "after:bg-[var(--color-primary)]" : "after:bg-[var(--color-outline-variant)]")
|
|
57
|
+
),
|
|
58
|
+
children: reachable ? /* @__PURE__ */ jsx(
|
|
59
|
+
"button",
|
|
60
|
+
{
|
|
61
|
+
type: "button",
|
|
62
|
+
onClick: () => onStepChange(i),
|
|
63
|
+
className: "rounded-shape-control p-1 hover:bg-[var(--color-surface-container-high)]",
|
|
64
|
+
children: body
|
|
65
|
+
}
|
|
66
|
+
) : /* @__PURE__ */ jsx("span", { className: "p-1", children: body })
|
|
67
|
+
},
|
|
68
|
+
step.id
|
|
69
|
+
);
|
|
70
|
+
}) }) });
|
|
71
|
+
});
|
|
72
|
+
export {
|
|
73
|
+
Stepper
|
|
74
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -228,6 +228,16 @@ export { EventCalendar } from './components/EventCalendar/index.js';
|
|
|
228
228
|
export type { EventCalendarProps, EventCalendarView, CalendarEvent, EventTone } from './components/EventCalendar/index.js';
|
|
229
229
|
export { TreeView } from './components/TreeView/index.js';
|
|
230
230
|
export type { TreeViewProps, TreeNode } from './components/TreeView/index.js';
|
|
231
|
+
export { ResizablePanels } from './components/ResizablePanels/index.js';
|
|
232
|
+
export type { ResizablePanelsProps } from './components/ResizablePanels/index.js';
|
|
233
|
+
export { Stepper } from './components/Stepper/index.js';
|
|
234
|
+
export type { StepperProps, StepperStep } from './components/Stepper/index.js';
|
|
235
|
+
export { ActionBar } from './components/ActionBar/index.js';
|
|
236
|
+
export type { ActionBarProps } from './components/ActionBar/index.js';
|
|
237
|
+
export { Sortable } from './components/Sortable/index.js';
|
|
238
|
+
export type { SortableProps } from './components/Sortable/index.js';
|
|
239
|
+
export { Kanban } from './components/Kanban/index.js';
|
|
240
|
+
export type { KanbanProps, KanbanColumn } from './components/Kanban/index.js';
|
|
231
241
|
export type { OTPInputProps } from './components/OTPInput/index.js';
|
|
232
242
|
export { DatePicker } from './components/DatePicker/index.js';
|
|
233
243
|
export type { DatePickerProps } from './components/DatePicker/index.js';
|
package/dist/index.js
CHANGED
|
@@ -128,6 +128,11 @@ import { TimePicker } from "./components/TimePicker/index.js";
|
|
|
128
128
|
import { DateTimePicker } from "./components/DateTimePicker/index.js";
|
|
129
129
|
import { EventCalendar } from "./components/EventCalendar/index.js";
|
|
130
130
|
import { TreeView } from "./components/TreeView/index.js";
|
|
131
|
+
import { ResizablePanels } from "./components/ResizablePanels/index.js";
|
|
132
|
+
import { Stepper } from "./components/Stepper/index.js";
|
|
133
|
+
import { ActionBar } from "./components/ActionBar/index.js";
|
|
134
|
+
import { Sortable } from "./components/Sortable/index.js";
|
|
135
|
+
import { Kanban } from "./components/Kanban/index.js";
|
|
131
136
|
import { DatePicker } from "./components/DatePicker/index.js";
|
|
132
137
|
import { DateRangePicker } from "./components/DateRangePicker/index.js";
|
|
133
138
|
import { todayIn } from "./components/DateRangePicker/index.js";
|
|
@@ -135,6 +140,7 @@ import { ThemeProvider, ThemeScript, useTheme } from "./components/ThemeProvider
|
|
|
135
140
|
import { Fade, Slide, Scale, Collapse, ListTransition, SkeletonSwap, usePrefersReducedMotion, Reveal, Float, Marquee } from "./components/Motion/index.js";
|
|
136
141
|
export {
|
|
137
142
|
Accordion,
|
|
143
|
+
ActionBar,
|
|
138
144
|
Alert,
|
|
139
145
|
AlertDialog,
|
|
140
146
|
Amount,
|
|
@@ -207,6 +213,7 @@ export {
|
|
|
207
213
|
IconButton,
|
|
208
214
|
InlineEdit,
|
|
209
215
|
Input,
|
|
216
|
+
Kanban,
|
|
210
217
|
Kbd,
|
|
211
218
|
KeyboardShortcut,
|
|
212
219
|
KpiTile,
|
|
@@ -239,6 +246,7 @@ export {
|
|
|
239
246
|
RadioCardGroup,
|
|
240
247
|
RadioGroup,
|
|
241
248
|
Rating,
|
|
249
|
+
ResizablePanels,
|
|
242
250
|
Reveal,
|
|
243
251
|
SavedViews,
|
|
244
252
|
Scale,
|
|
@@ -256,12 +264,14 @@ export {
|
|
|
256
264
|
SkeletonSwap,
|
|
257
265
|
Slide,
|
|
258
266
|
Slider,
|
|
267
|
+
Sortable,
|
|
259
268
|
SourceChip,
|
|
260
269
|
SourceList,
|
|
261
270
|
Sparkline,
|
|
262
271
|
Spinner,
|
|
263
272
|
SplitButton,
|
|
264
273
|
Stack,
|
|
274
|
+
Stepper,
|
|
265
275
|
StreamingText,
|
|
266
276
|
Switch,
|
|
267
277
|
Table,
|