@comitor/ui 1.10.0 → 2.0.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/README.md +24 -5
- package/dist/data-grid/compose-refs.d.ts +19 -0
- package/dist/data-grid/compose-refs.js +41 -0
- package/dist/data-grid/compose-refs.js.map +1 -0
- package/dist/data-grid/data-grid-cell-variants.d.ts +15 -0
- package/dist/data-grid/data-grid-cell-variants.js +1738 -0
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -0
- package/dist/data-grid/data-grid-cell-wrapper.d.ts +9 -0
- package/dist/data-grid/data-grid-cell-wrapper.js +179 -0
- package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -0
- package/dist/data-grid/data-grid-cell.d.ts +8 -0
- package/dist/data-grid/data-grid-cell.js +101 -0
- package/dist/data-grid/data-grid-cell.js.map +1 -0
- package/dist/data-grid/data-grid-column-header.d.ts +12 -0
- package/dist/data-grid/data-grid-column-header.js +207 -0
- package/dist/data-grid/data-grid-column-header.js.map +1 -0
- package/dist/data-grid/data-grid-context-menu.d.ts +12 -0
- package/dist/data-grid/data-grid-context-menu.js +161 -0
- package/dist/data-grid/data-grid-context-menu.js.map +1 -0
- package/dist/data-grid/data-grid-filter-menu.d.ts +23 -0
- package/dist/data-grid/data-grid-filter-menu.js +725 -0
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +31 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.js +229 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -0
- package/dist/data-grid/data-grid-locale.d.ts +24 -0
- package/dist/data-grid/data-grid-locale.js +25 -0
- package/dist/data-grid/data-grid-locale.js.map +1 -0
- package/dist/data-grid/data-grid-paste-dialog.d.ts +11 -0
- package/dist/data-grid/data-grid-paste-dialog.js +104 -0
- package/dist/data-grid/data-grid-paste-dialog.js.map +1 -0
- package/dist/data-grid/data-grid-presence.d.ts +14 -0
- package/dist/data-grid/data-grid-presence.js +16 -0
- package/dist/data-grid/data-grid-presence.js.map +1 -0
- package/dist/data-grid/data-grid-row-height-menu.d.ts +25 -0
- package/dist/data-grid/data-grid-row-height-menu.js +53 -0
- package/dist/data-grid/data-grid-row-height-menu.js.map +1 -0
- package/dist/data-grid/data-grid-row.d.ts +28 -0
- package/dist/data-grid/data-grid-row.js +206 -0
- package/dist/data-grid/data-grid-row.js.map +1 -0
- package/dist/data-grid/data-grid-search.d.ts +10 -0
- package/dist/data-grid/data-grid-search.js +184 -0
- package/dist/data-grid/data-grid-search.js.map +1 -0
- package/dist/data-grid/data-grid-select-column.d.ts +12 -0
- package/dist/data-grid/data-grid-select-column.js +179 -0
- package/dist/data-grid/data-grid-select-column.js.map +1 -0
- package/dist/data-grid/data-grid-skeleton.d.ts +13 -0
- package/dist/data-grid/data-grid-skeleton.js +52 -0
- package/dist/data-grid/data-grid-skeleton.js.map +1 -0
- package/dist/data-grid/data-grid-sort-menu.d.ts +23 -0
- package/dist/data-grid/data-grid-sort-menu.js +283 -0
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -0
- package/dist/data-grid/data-grid-view-menu.d.ts +24 -0
- package/dist/data-grid/data-grid-view-menu.js +74 -0
- package/dist/data-grid/data-grid-view-menu.js.map +1 -0
- package/dist/data-grid/data-grid.d.ts +44 -0
- package/dist/data-grid/data-grid.js +238 -0
- package/dist/data-grid/data-grid.js.map +1 -0
- package/dist/data-grid/filters.d.ts +27 -0
- package/dist/data-grid/filters.js +233 -0
- package/dist/data-grid/filters.js.map +1 -0
- package/dist/data-grid/index.d.ts +25 -0
- package/dist/data-grid/index.js +95 -0
- package/dist/data-grid/index.js.map +1 -0
- package/dist/data-grid/messages-en.d.ts +294 -0
- package/dist/data-grid/messages-en.js +279 -0
- package/dist/data-grid/messages-en.js.map +1 -0
- package/dist/data-grid/messages-vi.d.ts +12 -0
- package/dist/data-grid/messages-vi.js +279 -0
- package/dist/data-grid/messages-vi.js.map +1 -0
- package/dist/data-grid/messages.d.ts +567 -0
- package/dist/data-grid/messages.js +20 -0
- package/dist/data-grid/messages.js.map +1 -0
- package/dist/data-grid/sortable.d.ts +50 -0
- package/dist/data-grid/sortable.js +361 -0
- package/dist/data-grid/sortable.js.map +1 -0
- package/dist/data-grid/toast.d.ts +10 -0
- package/dist/data-grid/toast.js +21 -0
- package/dist/data-grid/toast.js.map +1 -0
- package/dist/data-grid/types.d.ts +189 -0
- package/dist/data-grid/types.js +1 -0
- package/dist/data-grid/types.js.map +1 -0
- package/dist/data-grid/use-as-ref.d.ts +5 -0
- package/dist/data-grid/use-as-ref.js +13 -0
- package/dist/data-grid/use-as-ref.js.map +1 -0
- package/dist/data-grid/use-badge-overflow.d.ts +24 -0
- package/dist/data-grid/use-badge-overflow.js +123 -0
- package/dist/data-grid/use-badge-overflow.js.map +1 -0
- package/dist/data-grid/use-callback-ref.d.ts +10 -0
- package/dist/data-grid/use-callback-ref.js +12 -0
- package/dist/data-grid/use-callback-ref.js.map +1 -0
- package/dist/data-grid/use-data-grid-undo-redo.d.ts +45 -0
- package/dist/data-grid/use-data-grid-undo-redo.js +348 -0
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -0
- package/dist/data-grid/use-data-grid.d.ts +372 -0
- package/dist/data-grid/use-data-grid.js +2697 -0
- package/dist/data-grid/use-data-grid.js.map +1 -0
- package/dist/data-grid/use-debounced-callback.d.ts +6 -0
- package/dist/data-grid/use-debounced-callback.js +19 -0
- package/dist/data-grid/use-debounced-callback.js.map +1 -0
- package/dist/data-grid/use-isomorphic-layout-effect.d.ts +5 -0
- package/dist/data-grid/use-isomorphic-layout-effect.js +6 -0
- package/dist/data-grid/use-isomorphic-layout-effect.js.map +1 -0
- package/dist/data-grid/use-lazy-ref.d.ts +5 -0
- package/dist/data-grid/use-lazy-ref.js +12 -0
- package/dist/data-grid/use-lazy-ref.js.map +1 -0
- package/dist/data-grid/utils.d.ts +81 -0
- package/dist/data-grid/utils.js +409 -0
- package/dist/data-grid/utils.js.map +1 -0
- package/package.json +33 -15
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
closestCenter,
|
|
5
|
+
closestCorners,
|
|
6
|
+
DndContext,
|
|
7
|
+
DragOverlay,
|
|
8
|
+
defaultDropAnimationSideEffects,
|
|
9
|
+
KeyboardSensor,
|
|
10
|
+
MouseSensor,
|
|
11
|
+
TouchSensor,
|
|
12
|
+
useSensor,
|
|
13
|
+
useSensors
|
|
14
|
+
} from "@dnd-kit/core";
|
|
15
|
+
import { restrictToHorizontalAxis, restrictToParentElement, restrictToVerticalAxis } from "@dnd-kit/modifiers";
|
|
16
|
+
import {
|
|
17
|
+
arrayMove,
|
|
18
|
+
horizontalListSortingStrategy,
|
|
19
|
+
SortableContext,
|
|
20
|
+
sortableKeyboardCoordinates,
|
|
21
|
+
useSortable,
|
|
22
|
+
verticalListSortingStrategy
|
|
23
|
+
} from "@dnd-kit/sortable";
|
|
24
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
25
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
26
|
+
import * as React from "react";
|
|
27
|
+
import * as ReactDOM from "react-dom";
|
|
28
|
+
import { cn } from "../lib/cn.js";
|
|
29
|
+
import { useComposedRefs } from "./compose-refs.js";
|
|
30
|
+
const orientationConfig = {
|
|
31
|
+
vertical: {
|
|
32
|
+
modifiers: [restrictToVerticalAxis, restrictToParentElement],
|
|
33
|
+
strategy: verticalListSortingStrategy,
|
|
34
|
+
collisionDetection: closestCenter
|
|
35
|
+
},
|
|
36
|
+
horizontal: {
|
|
37
|
+
modifiers: [restrictToHorizontalAxis, restrictToParentElement],
|
|
38
|
+
strategy: horizontalListSortingStrategy,
|
|
39
|
+
collisionDetection: closestCenter
|
|
40
|
+
},
|
|
41
|
+
mixed: {
|
|
42
|
+
modifiers: [restrictToParentElement],
|
|
43
|
+
strategy: void 0,
|
|
44
|
+
collisionDetection: closestCorners
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const ROOT_NAME = "Sortable";
|
|
48
|
+
const CONTENT_NAME = "SortableContent";
|
|
49
|
+
const ITEM_NAME = "SortableItem";
|
|
50
|
+
const ITEM_HANDLE_NAME = "SortableItemHandle";
|
|
51
|
+
const OVERLAY_NAME = "SortableOverlay";
|
|
52
|
+
const SortableRootContext = React.createContext(null);
|
|
53
|
+
function useSortableContext(consumerName) {
|
|
54
|
+
const context = React.useContext(SortableRootContext);
|
|
55
|
+
if (!context) {
|
|
56
|
+
throw new Error(`\`${consumerName}\` must be used within \`${ROOT_NAME}\``);
|
|
57
|
+
}
|
|
58
|
+
return context;
|
|
59
|
+
}
|
|
60
|
+
function Sortable(props) {
|
|
61
|
+
const {
|
|
62
|
+
value,
|
|
63
|
+
onValueChange,
|
|
64
|
+
collisionDetection,
|
|
65
|
+
modifiers,
|
|
66
|
+
strategy,
|
|
67
|
+
onMove,
|
|
68
|
+
orientation = "vertical",
|
|
69
|
+
flatCursor = false,
|
|
70
|
+
getItemValue: getItemValueProp,
|
|
71
|
+
accessibility,
|
|
72
|
+
...sortableProps
|
|
73
|
+
} = props;
|
|
74
|
+
const id = React.useId();
|
|
75
|
+
const [activeId, setActiveId] = React.useState(null);
|
|
76
|
+
const sensors = useSensors(
|
|
77
|
+
useSensor(MouseSensor),
|
|
78
|
+
useSensor(TouchSensor),
|
|
79
|
+
useSensor(KeyboardSensor, {
|
|
80
|
+
coordinateGetter: sortableKeyboardCoordinates
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
const config = React.useMemo(() => orientationConfig[orientation], [orientation]);
|
|
84
|
+
const getItemValue = React.useCallback(
|
|
85
|
+
(item) => {
|
|
86
|
+
if (typeof item === "object" && !getItemValueProp) {
|
|
87
|
+
throw new Error("`getItemValue` is required when using array of objects");
|
|
88
|
+
}
|
|
89
|
+
return getItemValueProp ? getItemValueProp(item) : item;
|
|
90
|
+
},
|
|
91
|
+
[getItemValueProp]
|
|
92
|
+
);
|
|
93
|
+
const items = React.useMemo(() => {
|
|
94
|
+
return value.map((item) => getItemValue(item));
|
|
95
|
+
}, [value, getItemValue]);
|
|
96
|
+
const onDragStart = React.useCallback(
|
|
97
|
+
(event) => {
|
|
98
|
+
sortableProps.onDragStart?.(event);
|
|
99
|
+
if (event.activatorEvent.defaultPrevented) return;
|
|
100
|
+
setActiveId(event.active.id);
|
|
101
|
+
},
|
|
102
|
+
[sortableProps.onDragStart]
|
|
103
|
+
);
|
|
104
|
+
const onDragEnd = React.useCallback(
|
|
105
|
+
(event) => {
|
|
106
|
+
sortableProps.onDragEnd?.(event);
|
|
107
|
+
if (event.activatorEvent.defaultPrevented) return;
|
|
108
|
+
const { active, over } = event;
|
|
109
|
+
if (over && active.id !== over?.id) {
|
|
110
|
+
const activeIndex = value.findIndex((item) => getItemValue(item) === active.id);
|
|
111
|
+
const overIndex = value.findIndex((item) => getItemValue(item) === over.id);
|
|
112
|
+
if (onMove) {
|
|
113
|
+
onMove({ ...event, activeIndex, overIndex });
|
|
114
|
+
} else {
|
|
115
|
+
onValueChange?.(arrayMove(value, activeIndex, overIndex));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
setActiveId(null);
|
|
119
|
+
},
|
|
120
|
+
[value, onValueChange, onMove, getItemValue, sortableProps.onDragEnd]
|
|
121
|
+
);
|
|
122
|
+
const onDragCancel = React.useCallback(
|
|
123
|
+
(event) => {
|
|
124
|
+
sortableProps.onDragCancel?.(event);
|
|
125
|
+
if (event.activatorEvent.defaultPrevented) return;
|
|
126
|
+
setActiveId(null);
|
|
127
|
+
},
|
|
128
|
+
[sortableProps.onDragCancel]
|
|
129
|
+
);
|
|
130
|
+
const announcements = React.useMemo(
|
|
131
|
+
() => ({
|
|
132
|
+
onDragStart({ active }) {
|
|
133
|
+
return `\u0110\xE3 nh\u1EA5c m\u1EE5c "${active.id.toString()}". V\u1ECB tr\xED hi\u1EC7n t\u1EA1i ${active.data.current?.sortable.index + 1} / ${value.length}. D\xF9ng ph\xEDm m\u0169i t\xEAn \u0111\u1EC3 di chuy\u1EC3n, ph\xEDm c\xE1ch \u0111\u1EC3 th\u1EA3.`;
|
|
134
|
+
},
|
|
135
|
+
onDragOver({ active, over }) {
|
|
136
|
+
if (over) {
|
|
137
|
+
const overIndex = over.data.current?.sortable.index ?? 0;
|
|
138
|
+
const activeIndex = active.data.current?.sortable.index ?? 0;
|
|
139
|
+
const moveDirection = overIndex > activeIndex ? "xu\u1ED1ng" : "l\xEAn";
|
|
140
|
+
return `M\u1EE5c "${active.id.toString()}" \u0111\xE3 chuy\u1EC3n ${moveDirection} v\u1ECB tr\xED ${overIndex + 1} / ${value.length}.`;
|
|
141
|
+
}
|
|
142
|
+
return "M\u1EE5c \u0111ang \u1EDF ngo\xE0i v\xF9ng th\u1EA3. Nh\u1EA5n Esc \u0111\u1EC3 hu\u1EF7.";
|
|
143
|
+
},
|
|
144
|
+
onDragEnd({ active, over }) {
|
|
145
|
+
const activeValue = active.id.toString();
|
|
146
|
+
if (over) {
|
|
147
|
+
const overIndex = over.data.current?.sortable.index ?? 0;
|
|
148
|
+
return `\u0110\xE3 th\u1EA3 m\u1EE5c "${activeValue}" \u1EDF v\u1ECB tr\xED ${overIndex + 1} / ${value.length}.`;
|
|
149
|
+
}
|
|
150
|
+
return `\u0110\xE3 th\u1EA3 m\u1EE5c "${activeValue}". Kh\xF4ng c\xF3 thay \u0111\u1ED5i n\xE0o.`;
|
|
151
|
+
},
|
|
152
|
+
onDragCancel({ active }) {
|
|
153
|
+
const activeIndex = active.data.current?.sortable.index ?? 0;
|
|
154
|
+
return `\u0110\xE3 hu\u1EF7 s\u1EAFp x\u1EBFp. M\u1EE5c "${active.id.toString()}" tr\u1EDF v\u1EC1 v\u1ECB tr\xED ${activeIndex + 1} / ${value.length}.`;
|
|
155
|
+
},
|
|
156
|
+
onDragMove({ active, over }) {
|
|
157
|
+
if (over) {
|
|
158
|
+
const overIndex = over.data.current?.sortable.index ?? 0;
|
|
159
|
+
const activeIndex = active.data.current?.sortable.index ?? 0;
|
|
160
|
+
const moveDirection = overIndex > activeIndex ? "xu\u1ED1ng" : "l\xEAn";
|
|
161
|
+
return `M\u1EE5c "${active.id.toString()}" \u0111ang di chuy\u1EC3n ${moveDirection} v\u1ECB tr\xED ${overIndex + 1} / ${value.length}.`;
|
|
162
|
+
}
|
|
163
|
+
return "M\u1EE5c \u0111ang \u1EDF ngo\xE0i v\xF9ng th\u1EA3. Nh\u1EA5n Esc \u0111\u1EC3 hu\u1EF7.";
|
|
164
|
+
}
|
|
165
|
+
}),
|
|
166
|
+
[value]
|
|
167
|
+
);
|
|
168
|
+
const screenReaderInstructions = React.useMemo(
|
|
169
|
+
() => ({
|
|
170
|
+
draggable: `
|
|
171
|
+
Nh\u1EA5n ph\xEDm c\xE1ch ho\u1EB7c Enter \u0111\u1EC3 nh\u1EA5c m\u1EE5c l\xEAn.
|
|
172
|
+
Khi \u0111ang gi\u1EEF, d\xF9ng ph\xEDm m\u0169i t\xEAn ${orientation === "vertical" ? "l\xEAn/xu\u1ED1ng" : orientation === "horizontal" ? "tr\xE1i/ph\u1EA3i" : ""} \u0111\u1EC3 di chuy\u1EC3n.
|
|
173
|
+
Nh\u1EA5n ph\xEDm c\xE1ch ho\u1EB7c Enter l\u1EA7n n\u1EEFa \u0111\u1EC3 th\u1EA3 v\xE0o v\u1ECB tr\xED m\u1EDBi, ho\u1EB7c Esc \u0111\u1EC3 hu\u1EF7.
|
|
174
|
+
`
|
|
175
|
+
}),
|
|
176
|
+
[orientation]
|
|
177
|
+
);
|
|
178
|
+
const contextValue = React.useMemo(
|
|
179
|
+
() => ({
|
|
180
|
+
id,
|
|
181
|
+
items,
|
|
182
|
+
modifiers: modifiers ?? config.modifiers,
|
|
183
|
+
strategy: strategy ?? config.strategy,
|
|
184
|
+
activeId,
|
|
185
|
+
setActiveId,
|
|
186
|
+
getItemValue,
|
|
187
|
+
flatCursor
|
|
188
|
+
}),
|
|
189
|
+
[id, items, modifiers, strategy, config.modifiers, config.strategy, activeId, getItemValue, flatCursor]
|
|
190
|
+
);
|
|
191
|
+
return /* @__PURE__ */ jsx(SortableRootContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
192
|
+
DndContext,
|
|
193
|
+
{
|
|
194
|
+
collisionDetection: collisionDetection ?? config.collisionDetection,
|
|
195
|
+
modifiers: modifiers ?? config.modifiers,
|
|
196
|
+
sensors,
|
|
197
|
+
...sortableProps,
|
|
198
|
+
id,
|
|
199
|
+
onDragStart,
|
|
200
|
+
onDragEnd,
|
|
201
|
+
onDragCancel,
|
|
202
|
+
accessibility: {
|
|
203
|
+
announcements,
|
|
204
|
+
screenReaderInstructions,
|
|
205
|
+
...accessibility
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
) });
|
|
209
|
+
}
|
|
210
|
+
const SortableContentContext = React.createContext(false);
|
|
211
|
+
function SortableContent(props) {
|
|
212
|
+
const { strategy: strategyProp, asChild, withoutSlot, children, ref, ...contentProps } = props;
|
|
213
|
+
const context = useSortableContext(CONTENT_NAME);
|
|
214
|
+
const ContentPrimitive = asChild ? Slot : "div";
|
|
215
|
+
return /* @__PURE__ */ jsx(SortableContentContext.Provider, { value: true, children: /* @__PURE__ */ jsx(SortableContext, { items: context.items, strategy: strategyProp ?? context.strategy, children: withoutSlot ? children : /* @__PURE__ */ jsx(ContentPrimitive, { "data-slot": "sortable-content", ...contentProps, ref, children }) }) });
|
|
216
|
+
}
|
|
217
|
+
const SortableItemContext = React.createContext(null);
|
|
218
|
+
function useSortableItemContext(consumerName) {
|
|
219
|
+
const context = React.useContext(SortableItemContext);
|
|
220
|
+
if (!context) {
|
|
221
|
+
throw new Error(`\`${consumerName}\` must be used within \`${ITEM_NAME}\``);
|
|
222
|
+
}
|
|
223
|
+
return context;
|
|
224
|
+
}
|
|
225
|
+
function SortableItem(props) {
|
|
226
|
+
const { value, style, asHandle, asChild, disabled, className, ref, ...itemProps } = props;
|
|
227
|
+
const inSortableContent = React.useContext(SortableContentContext);
|
|
228
|
+
const inSortableOverlay = React.useContext(SortableOverlayContext);
|
|
229
|
+
if (!inSortableContent && !inSortableOverlay) {
|
|
230
|
+
throw new Error(`\`${ITEM_NAME}\` must be used within \`${CONTENT_NAME}\` or \`${OVERLAY_NAME}\``);
|
|
231
|
+
}
|
|
232
|
+
if (value === "") {
|
|
233
|
+
throw new Error(`\`${ITEM_NAME}\` value cannot be an empty string`);
|
|
234
|
+
}
|
|
235
|
+
const context = useSortableContext(ITEM_NAME);
|
|
236
|
+
const id = React.useId();
|
|
237
|
+
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({
|
|
238
|
+
id: value,
|
|
239
|
+
disabled
|
|
240
|
+
});
|
|
241
|
+
const composedRef = useComposedRefs(ref, (node) => {
|
|
242
|
+
if (disabled) return;
|
|
243
|
+
setNodeRef(node);
|
|
244
|
+
if (asHandle) setActivatorNodeRef(node);
|
|
245
|
+
});
|
|
246
|
+
const composedStyle = React.useMemo(() => {
|
|
247
|
+
return {
|
|
248
|
+
transform: CSS.Translate.toString(transform),
|
|
249
|
+
transition,
|
|
250
|
+
...style
|
|
251
|
+
};
|
|
252
|
+
}, [transform, transition, style]);
|
|
253
|
+
const itemContext = React.useMemo(
|
|
254
|
+
() => ({
|
|
255
|
+
id,
|
|
256
|
+
attributes,
|
|
257
|
+
listeners,
|
|
258
|
+
setActivatorNodeRef,
|
|
259
|
+
isDragging,
|
|
260
|
+
disabled
|
|
261
|
+
}),
|
|
262
|
+
[id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]
|
|
263
|
+
);
|
|
264
|
+
const ItemPrimitive = asChild ? Slot : "div";
|
|
265
|
+
return /* @__PURE__ */ jsx(SortableItemContext.Provider, { value: itemContext, children: /* @__PURE__ */ jsx(
|
|
266
|
+
ItemPrimitive,
|
|
267
|
+
{
|
|
268
|
+
id,
|
|
269
|
+
"data-disabled": disabled,
|
|
270
|
+
"data-dragging": isDragging ? "" : void 0,
|
|
271
|
+
"data-slot": "sortable-item",
|
|
272
|
+
...itemProps,
|
|
273
|
+
...asHandle && !disabled ? attributes : {},
|
|
274
|
+
...asHandle && !disabled ? listeners : {},
|
|
275
|
+
ref: composedRef,
|
|
276
|
+
style: composedStyle,
|
|
277
|
+
className: cn(
|
|
278
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
279
|
+
{
|
|
280
|
+
"touch-none select-none": asHandle,
|
|
281
|
+
"cursor-default": context.flatCursor,
|
|
282
|
+
"data-[dragging]:cursor-grabbing": !context.flatCursor,
|
|
283
|
+
"cursor-grab": !isDragging && asHandle && !context.flatCursor,
|
|
284
|
+
"opacity-50": isDragging,
|
|
285
|
+
"pointer-events-none opacity-50": disabled
|
|
286
|
+
},
|
|
287
|
+
className
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
) });
|
|
291
|
+
}
|
|
292
|
+
function SortableItemHandle(props) {
|
|
293
|
+
const { asChild, disabled, className, ref, ...itemHandleProps } = props;
|
|
294
|
+
const context = useSortableContext(ITEM_HANDLE_NAME);
|
|
295
|
+
const itemContext = useSortableItemContext(ITEM_HANDLE_NAME);
|
|
296
|
+
const isDisabled = disabled ?? itemContext.disabled;
|
|
297
|
+
const composedRef = useComposedRefs(ref, (node) => {
|
|
298
|
+
if (!isDisabled) return;
|
|
299
|
+
itemContext.setActivatorNodeRef(node);
|
|
300
|
+
});
|
|
301
|
+
const HandlePrimitive = asChild ? Slot : "button";
|
|
302
|
+
return /* @__PURE__ */ jsx(
|
|
303
|
+
HandlePrimitive,
|
|
304
|
+
{
|
|
305
|
+
type: "button",
|
|
306
|
+
"aria-controls": itemContext.id,
|
|
307
|
+
"data-disabled": isDisabled,
|
|
308
|
+
"data-dragging": itemContext.isDragging ? "" : void 0,
|
|
309
|
+
"data-slot": "sortable-item-handle",
|
|
310
|
+
...itemHandleProps,
|
|
311
|
+
...isDisabled ? {} : itemContext.attributes,
|
|
312
|
+
...isDisabled ? {} : itemContext.listeners,
|
|
313
|
+
ref: composedRef,
|
|
314
|
+
className: cn(
|
|
315
|
+
"select-none disabled:pointer-events-none disabled:opacity-50",
|
|
316
|
+
context.flatCursor ? "cursor-default" : "cursor-grab data-[dragging]:cursor-grabbing",
|
|
317
|
+
className
|
|
318
|
+
),
|
|
319
|
+
disabled: isDisabled
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
const SortableOverlayContext = React.createContext(false);
|
|
324
|
+
const dropAnimation = {
|
|
325
|
+
sideEffects: defaultDropAnimationSideEffects({
|
|
326
|
+
styles: {
|
|
327
|
+
active: {
|
|
328
|
+
opacity: "0.4"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
})
|
|
332
|
+
};
|
|
333
|
+
function SortableOverlay(props) {
|
|
334
|
+
const { container: containerProp, children, ...overlayProps } = props;
|
|
335
|
+
const context = useSortableContext(OVERLAY_NAME);
|
|
336
|
+
const [mounted, setMounted] = React.useState(false);
|
|
337
|
+
React.useLayoutEffect(() => setMounted(true), []);
|
|
338
|
+
const container = containerProp ?? (mounted ? globalThis.document?.body : null);
|
|
339
|
+
if (!container) return null;
|
|
340
|
+
return ReactDOM.createPortal(
|
|
341
|
+
/* @__PURE__ */ jsx(
|
|
342
|
+
DragOverlay,
|
|
343
|
+
{
|
|
344
|
+
dropAnimation,
|
|
345
|
+
modifiers: context.modifiers,
|
|
346
|
+
className: cn(!context.flatCursor && "cursor-grabbing"),
|
|
347
|
+
...overlayProps,
|
|
348
|
+
children: /* @__PURE__ */ jsx(SortableOverlayContext.Provider, { value: true, children: context.activeId ? typeof children === "function" ? children({ value: context.activeId }) : children : null })
|
|
349
|
+
}
|
|
350
|
+
),
|
|
351
|
+
container
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
export {
|
|
355
|
+
Sortable,
|
|
356
|
+
SortableContent,
|
|
357
|
+
SortableItem,
|
|
358
|
+
SortableItemHandle,
|
|
359
|
+
SortableOverlay
|
|
360
|
+
};
|
|
361
|
+
//# sourceMappingURL=sortable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/sortable.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type Announcements,\n closestCenter,\n closestCorners,\n DndContext,\n type DndContextProps,\n type DragEndEvent,\n type DraggableAttributes,\n type DraggableSyntheticListeners,\n DragOverlay,\n type DragStartEvent,\n type DropAnimation,\n defaultDropAnimationSideEffects,\n KeyboardSensor,\n MouseSensor,\n type ScreenReaderInstructions,\n TouchSensor,\n type UniqueIdentifier,\n useSensor,\n useSensors\n} from \"@dnd-kit/core\";\nimport { restrictToHorizontalAxis, restrictToParentElement, restrictToVerticalAxis } from \"@dnd-kit/modifiers\";\nimport {\n arrayMove,\n horizontalListSortingStrategy,\n SortableContext,\n type SortableContextProps,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\nimport { cn } from \"../lib/cn.js\";\nimport { useComposedRefs } from \"./compose-refs.js\";\n\nconst orientationConfig = {\n vertical: {\n modifiers: [restrictToVerticalAxis, restrictToParentElement],\n strategy: verticalListSortingStrategy,\n collisionDetection: closestCenter\n },\n horizontal: {\n modifiers: [restrictToHorizontalAxis, restrictToParentElement],\n strategy: horizontalListSortingStrategy,\n collisionDetection: closestCenter\n },\n mixed: {\n modifiers: [restrictToParentElement],\n strategy: undefined,\n collisionDetection: closestCorners\n }\n};\n\nconst ROOT_NAME = \"Sortable\";\nconst CONTENT_NAME = \"SortableContent\";\nconst ITEM_NAME = \"SortableItem\";\nconst ITEM_HANDLE_NAME = \"SortableItemHandle\";\nconst OVERLAY_NAME = \"SortableOverlay\";\n\ninterface SortableRootContextValue<T> {\n id: string;\n items: UniqueIdentifier[];\n modifiers: DndContextProps[\"modifiers\"];\n strategy: SortableContextProps[\"strategy\"];\n activeId: UniqueIdentifier | null;\n setActiveId: (id: UniqueIdentifier | null) => void;\n getItemValue: (item: T) => UniqueIdentifier;\n flatCursor: boolean;\n}\n\nconst SortableRootContext = React.createContext<SortableRootContextValue<unknown> | null>(null);\n\nfunction useSortableContext(consumerName: string) {\n const context = React.useContext(SortableRootContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface GetItemValue<T> {\n /**\n * Callback that returns a unique identifier for each sortable item. Required for array of objects.\n * @example getItemValue={(item) => item.id}\n */\n getItemValue: (item: T) => UniqueIdentifier;\n}\n\ntype SortableProps<T> = DndContextProps &\n (T extends object ? GetItemValue<T> : Partial<GetItemValue<T>>) & {\n value: T[];\n onValueChange?: (items: T[]) => void;\n onMove?: (event: DragEndEvent & { activeIndex: number; overIndex: number }) => void;\n strategy?: SortableContextProps[\"strategy\"];\n orientation?: \"vertical\" | \"horizontal\" | \"mixed\";\n flatCursor?: boolean;\n };\n\nfunction Sortable<T>(props: SortableProps<T>) {\n const {\n value,\n onValueChange,\n collisionDetection,\n modifiers,\n strategy,\n onMove,\n orientation = \"vertical\",\n flatCursor = false,\n getItemValue: getItemValueProp,\n accessibility,\n ...sortableProps\n } = props;\n\n const id = React.useId();\n const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null);\n\n const sensors = useSensors(\n useSensor(MouseSensor),\n useSensor(TouchSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates\n })\n );\n const config = React.useMemo(() => orientationConfig[orientation], [orientation]);\n\n const getItemValue = React.useCallback(\n (item: T): UniqueIdentifier => {\n if (typeof item === \"object\" && !getItemValueProp) {\n throw new Error(\"`getItemValue` is required when using array of objects\");\n }\n return getItemValueProp ? getItemValueProp(item) : (item as UniqueIdentifier);\n },\n [getItemValueProp]\n );\n\n const items = React.useMemo(() => {\n return value.map((item) => getItemValue(item));\n }, [value, getItemValue]);\n\n const onDragStart = React.useCallback(\n (event: DragStartEvent) => {\n sortableProps.onDragStart?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n setActiveId(event.active.id);\n },\n [sortableProps.onDragStart]\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n sortableProps.onDragEnd?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n const { active, over } = event;\n if (over && active.id !== over?.id) {\n const activeIndex = value.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = value.findIndex((item) => getItemValue(item) === over.id);\n\n if (onMove) {\n onMove({ ...event, activeIndex, overIndex });\n } else {\n onValueChange?.(arrayMove(value, activeIndex, overIndex));\n }\n }\n setActiveId(null);\n },\n [value, onValueChange, onMove, getItemValue, sortableProps.onDragEnd]\n );\n\n const onDragCancel = React.useCallback(\n (event: DragEndEvent) => {\n sortableProps.onDragCancel?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n setActiveId(null);\n },\n [sortableProps.onDragCancel]\n );\n\n const announcements: Announcements = React.useMemo(\n () => ({\n onDragStart({ active }) {\n return `Đã nhấc mục \"${active.id.toString()}\". Vị trí hiện tại ${active.data.current?.sortable.index + 1} / ${value.length}. Dùng phím mũi tên để di chuyển, phím cách để thả.`;\n },\n onDragOver({ active, over }) {\n if (over) {\n const overIndex = over.data.current?.sortable.index ?? 0;\n const activeIndex = active.data.current?.sortable.index ?? 0;\n const moveDirection = overIndex > activeIndex ? \"xuống\" : \"lên\";\n return `Mục \"${active.id.toString()}\" đã chuyển ${moveDirection} vị trí ${overIndex + 1} / ${value.length}.`;\n }\n return \"Mục đang ở ngoài vùng thả. Nhấn Esc để huỷ.\";\n },\n onDragEnd({ active, over }) {\n const activeValue = active.id.toString();\n if (over) {\n const overIndex = over.data.current?.sortable.index ?? 0;\n return `Đã thả mục \"${activeValue}\" ở vị trí ${overIndex + 1} / ${value.length}.`;\n }\n return `Đã thả mục \"${activeValue}\". Không có thay đổi nào.`;\n },\n onDragCancel({ active }) {\n const activeIndex = active.data.current?.sortable.index ?? 0;\n return `Đã huỷ sắp xếp. Mục \"${active.id.toString()}\" trở về vị trí ${activeIndex + 1} / ${value.length}.`;\n },\n onDragMove({ active, over }) {\n if (over) {\n const overIndex = over.data.current?.sortable.index ?? 0;\n const activeIndex = active.data.current?.sortable.index ?? 0;\n const moveDirection = overIndex > activeIndex ? \"xuống\" : \"lên\";\n return `Mục \"${active.id.toString()}\" đang di chuyển ${moveDirection} vị trí ${overIndex + 1} / ${value.length}.`;\n }\n return \"Mục đang ở ngoài vùng thả. Nhấn Esc để huỷ.\";\n }\n }),\n [value]\n );\n\n const screenReaderInstructions: ScreenReaderInstructions = React.useMemo(\n () => ({\n draggable: `\n Nhấn phím cách hoặc Enter để nhấc mục lên.\n Khi đang giữ, dùng phím mũi tên ${orientation === \"vertical\" ? \"lên/xuống\" : orientation === \"horizontal\" ? \"trái/phải\" : \"\"} để di chuyển.\n Nhấn phím cách hoặc Enter lần nữa để thả vào vị trí mới, hoặc Esc để huỷ.\n `\n }),\n [orientation]\n );\n\n const contextValue = React.useMemo(\n () => ({\n id,\n items,\n modifiers: modifiers ?? config.modifiers,\n strategy: strategy ?? config.strategy,\n activeId,\n setActiveId,\n getItemValue,\n flatCursor\n }),\n [id, items, modifiers, strategy, config.modifiers, config.strategy, activeId, getItemValue, flatCursor]\n );\n\n return (\n <SortableRootContext.Provider value={contextValue as SortableRootContextValue<unknown>}>\n <DndContext\n collisionDetection={collisionDetection ?? config.collisionDetection}\n modifiers={modifiers ?? config.modifiers}\n sensors={sensors}\n {...sortableProps}\n id={id}\n onDragStart={onDragStart}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n accessibility={{\n announcements,\n screenReaderInstructions,\n ...accessibility\n }}\n />\n </SortableRootContext.Provider>\n );\n}\n\nconst SortableContentContext = React.createContext<boolean>(false);\n\ninterface SortableContentProps extends React.ComponentProps<\"div\"> {\n strategy?: SortableContextProps[\"strategy\"];\n children: React.ReactNode;\n asChild?: boolean;\n withoutSlot?: boolean;\n}\n\nfunction SortableContent(props: SortableContentProps) {\n const { strategy: strategyProp, asChild, withoutSlot, children, ref, ...contentProps } = props;\n\n const context = useSortableContext(CONTENT_NAME);\n\n const ContentPrimitive = asChild ? Slot : \"div\";\n\n return (\n <SortableContentContext.Provider value={true}>\n <SortableContext items={context.items} strategy={strategyProp ?? context.strategy}>\n {withoutSlot ? (\n children\n ) : (\n <ContentPrimitive data-slot=\"sortable-content\" {...contentProps} ref={ref}>\n {children}\n </ContentPrimitive>\n )}\n </SortableContext>\n </SortableContentContext.Provider>\n );\n}\n\ninterface SortableItemContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst SortableItemContext = React.createContext<SortableItemContextValue | null>(null);\n\nfunction useSortableItemContext(consumerName: string) {\n const context = React.useContext(SortableItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface SortableItemProps extends React.ComponentProps<\"div\"> {\n value: UniqueIdentifier;\n asHandle?: boolean;\n asChild?: boolean;\n disabled?: boolean;\n}\n\nfunction SortableItem(props: SortableItemProps) {\n const { value, style, asHandle, asChild, disabled, className, ref, ...itemProps } = props;\n\n const inSortableContent = React.useContext(SortableContentContext);\n const inSortableOverlay = React.useContext(SortableOverlayContext);\n\n if (!inSortableContent && !inSortableOverlay) {\n throw new Error(`\\`${ITEM_NAME}\\` must be used within \\`${CONTENT_NAME}\\` or \\`${OVERLAY_NAME}\\``);\n }\n\n if (value === \"\") {\n throw new Error(`\\`${ITEM_NAME}\\` value cannot be an empty string`);\n }\n\n const context = useSortableContext(ITEM_NAME);\n const id = React.useId();\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled\n });\n\n const composedRef = useComposedRefs(ref, (node) => {\n if (disabled) return;\n setNodeRef(node);\n if (asHandle) setActivatorNodeRef(node);\n });\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Translate.toString(transform),\n transition,\n ...style\n };\n }, [transform, transition, style]);\n\n const itemContext = React.useMemo<SortableItemContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <SortableItemContext.Provider value={itemContext}>\n <ItemPrimitive\n id={id}\n data-disabled={disabled}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"sortable-item\"\n {...itemProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-[dragging]:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled\n },\n className\n )}\n />\n </SortableItemContext.Provider>\n );\n}\n\ninterface SortableItemHandleProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\nfunction SortableItemHandle(props: SortableItemHandleProps) {\n const { asChild, disabled, className, ref, ...itemHandleProps } = props;\n\n const context = useSortableContext(ITEM_HANDLE_NAME);\n const itemContext = useSortableItemContext(ITEM_HANDLE_NAME);\n\n const isDisabled = disabled ?? itemContext.disabled;\n\n const composedRef = useComposedRefs(ref, (node) => {\n if (!isDisabled) return;\n itemContext.setActivatorNodeRef(node);\n });\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n aria-controls={itemContext.id}\n data-disabled={isDisabled}\n data-dragging={itemContext.isDragging ? \"\" : undefined}\n data-slot=\"sortable-item-handle\"\n {...itemHandleProps}\n {...(isDisabled ? {} : itemContext.attributes)}\n {...(isDisabled ? {} : itemContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-[dragging]:cursor-grabbing\",\n className\n )}\n disabled={isDisabled}\n />\n );\n}\n\nconst SortableOverlayContext = React.createContext(false);\n\nconst dropAnimation: DropAnimation = {\n sideEffects: defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: \"0.4\"\n }\n }\n })\n};\n\ninterface SortableOverlayProps extends Omit<React.ComponentProps<typeof DragOverlay>, \"children\"> {\n container?: Element | DocumentFragment | null;\n children?: ((params: { value: UniqueIdentifier }) => React.ReactNode) | React.ReactNode;\n}\n\nfunction SortableOverlay(props: SortableOverlayProps) {\n const { container: containerProp, children, ...overlayProps } = props;\n\n const context = useSortableContext(OVERLAY_NAME);\n\n const [mounted, setMounted] = React.useState(false);\n\n React.useLayoutEffect(() => setMounted(true), []);\n\n const container = containerProp ?? (mounted ? globalThis.document?.body : null);\n\n if (!container) return null;\n\n return ReactDOM.createPortal(\n <DragOverlay\n dropAnimation={dropAnimation}\n modifiers={context.modifiers}\n className={cn(!context.flatCursor && \"cursor-grabbing\")}\n {...overlayProps}\n >\n <SortableOverlayContext.Provider value={true}>\n {context.activeId ? (typeof children === \"function\" ? children({ value: context.activeId }) : children) : null}\n </SortableOverlayContext.Provider>\n </DragOverlay>,\n container\n );\n}\n\nexport { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay, type SortableProps };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lớp mỏng quanh `toast()` của package để DataGrid gọi cho gọn.
|
|
3
|
+
* Thông báo chỉ hiện khi ứng dụng đã đặt `<Toaster />` ở root (xem README).
|
|
4
|
+
*/
|
|
5
|
+
declare function toastSuccess(title: string, description?: string): void;
|
|
6
|
+
declare function toastError(title: string, description?: string): void;
|
|
7
|
+
declare function toastInfo(title: string, description?: string): void;
|
|
8
|
+
declare function toastMessage(title: string, description?: string): void;
|
|
9
|
+
|
|
10
|
+
export { toastError, toastInfo, toastMessage, toastSuccess };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { toast } from "../components/composite/toast.js";
|
|
3
|
+
function toastSuccess(title, description) {
|
|
4
|
+
toast(title, { description, variant: "success" });
|
|
5
|
+
}
|
|
6
|
+
function toastError(title, description) {
|
|
7
|
+
toast(title, { description, variant: "destructive" });
|
|
8
|
+
}
|
|
9
|
+
function toastInfo(title, description) {
|
|
10
|
+
toast(title, { description, variant: "info" });
|
|
11
|
+
}
|
|
12
|
+
function toastMessage(title, description) {
|
|
13
|
+
toast(title, { description });
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
toastError,
|
|
17
|
+
toastInfo,
|
|
18
|
+
toastMessage,
|
|
19
|
+
toastSuccess
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/toast.ts"],"sourcesContent":["\"use client\";\n\nimport { toast } from \"../components/composite/toast.js\";\n\n/**\n * Lớp mỏng quanh `toast()` của package để DataGrid gọi cho gọn.\n * Thông báo chỉ hiện khi ứng dụng đã đặt `<Toaster />` ở root (xem README).\n */\nexport function toastSuccess(title: string, description?: string): void {\n toast(title, { description, variant: \"success\" });\n}\n\nexport function toastError(title: string, description?: string): void {\n toast(title, { description, variant: \"destructive\" });\n}\n\nexport function toastInfo(title: string, description?: string): void {\n toast(title, { description, variant: \"info\" });\n}\n\nexport function toastMessage(title: string, description?: string): void {\n toast(title, { description });\n}\n"],"mappings":";AAEA,SAAS,aAAa;AAMf,SAAS,aAAa,OAAe,aAA4B;AACtE,QAAM,OAAO,EAAE,aAAa,SAAS,UAAU,CAAC;AAClD;AAEO,SAAS,WAAW,OAAe,aAA4B;AACpE,QAAM,OAAO,EAAE,aAAa,SAAS,cAAc,CAAC;AACtD;AAEO,SAAS,UAAU,OAAe,aAA4B;AACnE,QAAM,OAAO,EAAE,aAAa,SAAS,OAAO,CAAC;AAC/C;AAEO,SAAS,aAAa,OAAe,aAA4B;AACtE,QAAM,OAAO,EAAE,YAAY,CAAC;AAC9B;","names":[]}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { RowData, Cell, TableMeta } from '@tanstack/react-table';
|
|
2
|
+
|
|
3
|
+
/** Hướng đọc của lưới (mặc định "ltr" — tiếng Việt) */
|
|
4
|
+
type Direction = "ltr" | "rtl";
|
|
5
|
+
/** Chiều cao dòng: short 36px, medium 56px, tall 76px, extra-tall 96px */
|
|
6
|
+
type RowHeightValue = "short" | "medium" | "tall" | "extra-tall";
|
|
7
|
+
interface CellSelectOption {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string;
|
|
10
|
+
icon?: React.ComponentType<React.ComponentProps<"svg">>;
|
|
11
|
+
/** Số lượng hiển thị bên phải trong danh sách lọc */
|
|
12
|
+
count?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Kiểu ô của một cột — khai báo trong `columnDef.meta.cell`.
|
|
16
|
+
* Quyết định cả cách hiển thị, cách sửa, cách dán và bộ toán tử lọc.
|
|
17
|
+
*/
|
|
18
|
+
type CellOpts = {
|
|
19
|
+
variant: "short-text";
|
|
20
|
+
} | {
|
|
21
|
+
variant: "long-text";
|
|
22
|
+
} | {
|
|
23
|
+
variant: "number";
|
|
24
|
+
min?: number;
|
|
25
|
+
max?: number;
|
|
26
|
+
step?: number;
|
|
27
|
+
} | {
|
|
28
|
+
variant: "select";
|
|
29
|
+
options: CellSelectOption[];
|
|
30
|
+
} | {
|
|
31
|
+
variant: "multi-select";
|
|
32
|
+
options: CellSelectOption[];
|
|
33
|
+
} | {
|
|
34
|
+
variant: "checkbox";
|
|
35
|
+
} | {
|
|
36
|
+
/** Giá trị lưu dạng chuỗi "yyyy-MM-dd", hiển thị dd/MM/yyyy */
|
|
37
|
+
variant: "date";
|
|
38
|
+
} | {
|
|
39
|
+
variant: "url";
|
|
40
|
+
} | {
|
|
41
|
+
variant: "file";
|
|
42
|
+
/** Giới hạn dung lượng mỗi tệp (byte) — mặc định 10MB */
|
|
43
|
+
maxFileSize?: number;
|
|
44
|
+
/** Số tệp tối đa mỗi ô — mặc định 10 */
|
|
45
|
+
maxFiles?: number;
|
|
46
|
+
/** Chuỗi `accept` của input file, vd "image/*,.pdf" */
|
|
47
|
+
accept?: string;
|
|
48
|
+
multiple?: boolean;
|
|
49
|
+
};
|
|
50
|
+
/** Một thay đổi ô: dòng (theo thứ tự đang hiển thị) + cột + giá trị mới */
|
|
51
|
+
interface CellUpdate {
|
|
52
|
+
rowIndex: number;
|
|
53
|
+
columnId: string;
|
|
54
|
+
value: unknown;
|
|
55
|
+
}
|
|
56
|
+
declare module "@tanstack/react-table" {
|
|
57
|
+
interface ColumnMeta<TData extends RowData, TValue> {
|
|
58
|
+
/** Tên cột hiển thị trong menu Lọc/Sắp xếp/Hiển thị cột */
|
|
59
|
+
label?: string;
|
|
60
|
+
/** Kiểu ô của cột — xem {@link CellOpts} */
|
|
61
|
+
cell?: CellOpts;
|
|
62
|
+
}
|
|
63
|
+
interface TableMeta<TData extends RowData> {
|
|
64
|
+
dataGridRef?: React.RefObject<HTMLElement | null>;
|
|
65
|
+
cellMapRef?: React.RefObject<Map<string, HTMLDivElement>>;
|
|
66
|
+
focusedCell?: CellPosition | null;
|
|
67
|
+
editingCell?: CellPosition | null;
|
|
68
|
+
selectionState?: SelectionState;
|
|
69
|
+
searchOpen?: boolean;
|
|
70
|
+
getIsCellSelected?: (rowIndex: number, columnId: string) => boolean;
|
|
71
|
+
getIsSearchMatch?: (rowIndex: number, columnId: string) => boolean;
|
|
72
|
+
getIsActiveSearchMatch?: (rowIndex: number, columnId: string) => boolean;
|
|
73
|
+
getVisualRowIndex?: (rowId: string) => number | undefined;
|
|
74
|
+
scrollToCell?: (rowIndex: number, columnId: string, align?: "auto" | "start" | "center" | "end") => void;
|
|
75
|
+
rowHeight?: RowHeightValue;
|
|
76
|
+
onRowHeightChange?: (value: RowHeightValue) => void;
|
|
77
|
+
onRowSelect?: (rowId: string, checked: boolean, shiftKey: boolean) => void;
|
|
78
|
+
onDataUpdate?: (params: CellUpdate | Array<CellUpdate>) => void;
|
|
79
|
+
onRowsDelete?: (rowIndices: number[]) => void | Promise<void>;
|
|
80
|
+
onColumnClick?: (columnId: string) => void;
|
|
81
|
+
onCellClick?: (rowIndex: number, columnId: string, event?: React.MouseEvent) => void;
|
|
82
|
+
onCellDoubleClick?: (rowIndex: number, columnId: string) => void;
|
|
83
|
+
onCellMouseDown?: (rowIndex: number, columnId: string, event: React.MouseEvent) => void;
|
|
84
|
+
onCellMouseEnter?: (rowIndex: number, columnId: string) => void;
|
|
85
|
+
onCellMouseUp?: () => void;
|
|
86
|
+
onCellContextMenu?: (rowIndex: number, columnId: string, event: React.MouseEvent) => void;
|
|
87
|
+
onCellEditingStart?: (rowIndex: number, columnId: string) => void;
|
|
88
|
+
onCellEditingStop?: (opts?: {
|
|
89
|
+
direction?: NavigationDirection;
|
|
90
|
+
moveToNextRow?: boolean;
|
|
91
|
+
}) => void;
|
|
92
|
+
onCellsCopy?: () => void;
|
|
93
|
+
onCellsCut?: () => void;
|
|
94
|
+
onCellsPaste?: (expand?: boolean) => void;
|
|
95
|
+
onSelectionClear?: () => void;
|
|
96
|
+
onFilesUpload?: (params: {
|
|
97
|
+
files: File[];
|
|
98
|
+
rowIndex: number;
|
|
99
|
+
columnId: string;
|
|
100
|
+
}) => Promise<FileCellData[]>;
|
|
101
|
+
onFilesDelete?: (params: {
|
|
102
|
+
fileIds: string[];
|
|
103
|
+
rowIndex: number;
|
|
104
|
+
columnId: string;
|
|
105
|
+
}) => void | Promise<void>;
|
|
106
|
+
contextMenu?: ContextMenuState;
|
|
107
|
+
onContextMenuOpenChange?: (open: boolean) => void;
|
|
108
|
+
pasteDialog?: PasteDialogState;
|
|
109
|
+
onPasteDialogOpenChange?: (open: boolean) => void;
|
|
110
|
+
readOnly?: boolean;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Vị trí một ô: chỉ số dòng đang hiển thị + id cột */
|
|
114
|
+
interface CellPosition {
|
|
115
|
+
rowIndex: number;
|
|
116
|
+
columnId: string;
|
|
117
|
+
}
|
|
118
|
+
interface CellRange {
|
|
119
|
+
start: CellPosition;
|
|
120
|
+
end: CellPosition;
|
|
121
|
+
}
|
|
122
|
+
interface SelectionState {
|
|
123
|
+
/** Khoá ô đang chọn dạng `"{rowIndex}:{columnId}"` */
|
|
124
|
+
selectedCells: Set<string>;
|
|
125
|
+
selectionRange: CellRange | null;
|
|
126
|
+
/** Đang giữ chuột kéo chọn */
|
|
127
|
+
isSelecting: boolean;
|
|
128
|
+
}
|
|
129
|
+
interface ContextMenuState {
|
|
130
|
+
open: boolean;
|
|
131
|
+
x: number;
|
|
132
|
+
y: number;
|
|
133
|
+
}
|
|
134
|
+
interface PasteDialogState {
|
|
135
|
+
open: boolean;
|
|
136
|
+
/** Số dòng còn thiếu để dán hết nội dung clipboard */
|
|
137
|
+
rowsNeeded: number;
|
|
138
|
+
clipboardText: string;
|
|
139
|
+
}
|
|
140
|
+
type NavigationDirection = "up" | "down" | "left" | "right" | "home" | "end" | "ctrl+up" | "ctrl+down" | "ctrl+home" | "ctrl+end" | "pageup" | "pagedown" | "pageleft" | "pageright";
|
|
141
|
+
/** Trạng thái + hành vi của ô tìm kiếm trong lưới (bật bằng `enableSearch`) */
|
|
142
|
+
interface SearchState {
|
|
143
|
+
searchMatches: CellPosition[];
|
|
144
|
+
matchIndex: number;
|
|
145
|
+
searchOpen: boolean;
|
|
146
|
+
onSearchOpenChange: (open: boolean) => void;
|
|
147
|
+
searchQuery: string;
|
|
148
|
+
onSearchQueryChange: (query: string) => void;
|
|
149
|
+
onSearch: (query: string) => void;
|
|
150
|
+
onNavigateToNextMatch: () => void;
|
|
151
|
+
onNavigateToPrevMatch: () => void;
|
|
152
|
+
}
|
|
153
|
+
interface DataGridCellProps<TData> {
|
|
154
|
+
cell: Cell<TData, unknown>;
|
|
155
|
+
tableMeta: TableMeta<TData>;
|
|
156
|
+
rowIndex: number;
|
|
157
|
+
columnId: string;
|
|
158
|
+
rowHeight: RowHeightValue;
|
|
159
|
+
isEditing: boolean;
|
|
160
|
+
isFocused: boolean;
|
|
161
|
+
isSelected: boolean;
|
|
162
|
+
isSearchMatch: boolean;
|
|
163
|
+
isActiveSearchMatch: boolean;
|
|
164
|
+
readOnly: boolean;
|
|
165
|
+
}
|
|
166
|
+
/** Tệp đính kèm trong ô `variant: "file"` */
|
|
167
|
+
interface FileCellData {
|
|
168
|
+
id: string;
|
|
169
|
+
name: string;
|
|
170
|
+
size: number;
|
|
171
|
+
type: string;
|
|
172
|
+
/** Thiếu url = đang tải lên */
|
|
173
|
+
url?: string;
|
|
174
|
+
}
|
|
175
|
+
type TextFilterOperator = "contains" | "notContains" | "equals" | "notEquals" | "startsWith" | "endsWith" | "isEmpty" | "isNotEmpty";
|
|
176
|
+
type NumberFilterOperator = "equals" | "notEquals" | "lessThan" | "lessThanOrEqual" | "greaterThan" | "greaterThanOrEqual" | "isBetween" | "isEmpty" | "isNotEmpty";
|
|
177
|
+
type DateFilterOperator = "equals" | "notEquals" | "before" | "after" | "onOrBefore" | "onOrAfter" | "isBetween" | "isEmpty" | "isNotEmpty";
|
|
178
|
+
type SelectFilterOperator = "is" | "isNot" | "isAnyOf" | "isNoneOf" | "isEmpty" | "isNotEmpty";
|
|
179
|
+
type BooleanFilterOperator = "isTrue" | "isFalse";
|
|
180
|
+
type FilterOperator = TextFilterOperator | NumberFilterOperator | DateFilterOperator | SelectFilterOperator | BooleanFilterOperator;
|
|
181
|
+
/** Giá trị của một bộ lọc cột (đặt trong `columnFilters[].value`) */
|
|
182
|
+
interface FilterValue {
|
|
183
|
+
operator: FilterOperator;
|
|
184
|
+
value?: string | number | string[];
|
|
185
|
+
/** Vế thứ hai của toán tử `isBetween` */
|
|
186
|
+
endValue?: string | number;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export type { BooleanFilterOperator, CellOpts, CellPosition, CellRange, CellSelectOption, CellUpdate, ContextMenuState, DataGridCellProps, DateFilterOperator, Direction, FileCellData, FilterOperator, FilterValue, NavigationDirection, NumberFilterOperator, PasteDialogState, RowHeightValue, SearchState, SelectFilterOperator, SelectionState, TextFilterOperator };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useIsomorphicLayoutEffect } from "./use-isomorphic-layout-effect.js";
|
|
3
|
+
function useAsRef(props) {
|
|
4
|
+
const ref = React.useRef(props);
|
|
5
|
+
useIsomorphicLayoutEffect(() => {
|
|
6
|
+
ref.current = props;
|
|
7
|
+
});
|
|
8
|
+
return ref;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
useAsRef
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=use-as-ref.js.map
|