@comitor/ui 1.10.0 → 1.11.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 +15 -4
- 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 +1734 -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 +205 -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 +160 -0
- package/dist/data-grid/data-grid-context-menu.js.map +1 -0
- package/dist/data-grid/data-grid-filter-menu.d.ts +12 -0
- package/dist/data-grid/data-grid-filter-menu.js +714 -0
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +20 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.js +227 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.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 +103 -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 +15 -0
- package/dist/data-grid/data-grid-row-height-menu.js +56 -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 +183 -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 +177 -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 +12 -0
- package/dist/data-grid/data-grid-sort-menu.js +271 -0
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -0
- package/dist/data-grid/data-grid-view-menu.d.ts +13 -0
- package/dist/data-grid/data-grid-view-menu.js +66 -0
- package/dist/data-grid/data-grid-view-menu.js.map +1 -0
- package/dist/data-grid/data-grid.d.ts +32 -0
- package/dist/data-grid/data-grid.js +235 -0
- package/dist/data-grid/data-grid.js.map +1 -0
- package/dist/data-grid/filters.d.ts +31 -0
- package/dist/data-grid/filters.js +212 -0
- package/dist/data-grid/filters.js.map +1 -0
- package/dist/data-grid/index.d.ts +22 -0
- package/dist/data-grid/index.js +77 -0
- package/dist/data-grid/index.js.map +1 -0
- package/dist/data-grid/messages.d.ts +280 -0
- package/dist/data-grid/messages.js +279 -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 +33 -0
- package/dist/data-grid/use-data-grid-undo-redo.js +345 -0
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -0
- package/dist/data-grid/use-data-grid.d.ts +92 -0
- package/dist/data-grid/use-data-grid.js +2692 -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 +73 -0
- package/dist/data-grid/utils.js +408 -0
- package/dist/data-grid/utils.js.map +1 -0
- package/package.json +33 -15
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { format } from "date-fns";
|
|
2
|
+
import {
|
|
3
|
+
BaselineIcon,
|
|
4
|
+
CalendarIcon,
|
|
5
|
+
CheckSquareIcon,
|
|
6
|
+
File,
|
|
7
|
+
FileArchive,
|
|
8
|
+
FileAudio,
|
|
9
|
+
FileIcon,
|
|
10
|
+
FileImage,
|
|
11
|
+
FileSpreadsheet,
|
|
12
|
+
FileText,
|
|
13
|
+
FileVideo,
|
|
14
|
+
HashIcon,
|
|
15
|
+
LinkIcon,
|
|
16
|
+
ListChecksIcon,
|
|
17
|
+
ListIcon,
|
|
18
|
+
Presentation,
|
|
19
|
+
WrapTextIcon
|
|
20
|
+
} from "lucide-react";
|
|
21
|
+
import { msg } from "./messages.js";
|
|
22
|
+
function flexRender(Comp, props) {
|
|
23
|
+
if (typeof Comp === "string") {
|
|
24
|
+
return Comp;
|
|
25
|
+
}
|
|
26
|
+
return Comp?.(props);
|
|
27
|
+
}
|
|
28
|
+
function getIsFileCellData(item) {
|
|
29
|
+
return !!item && typeof item === "object" && "id" in item && "name" in item && "size" in item && "type" in item;
|
|
30
|
+
}
|
|
31
|
+
function matchSelectOption(value, options) {
|
|
32
|
+
return options.find(
|
|
33
|
+
(o) => o.value === value || o.value.toLowerCase() === value.toLowerCase() || o.label.toLowerCase() === value.toLowerCase()
|
|
34
|
+
)?.value;
|
|
35
|
+
}
|
|
36
|
+
function getCellKey(rowIndex, columnId) {
|
|
37
|
+
return `${rowIndex}:${columnId}`;
|
|
38
|
+
}
|
|
39
|
+
function parseCellKey(cellKey) {
|
|
40
|
+
const parts = cellKey.split(":");
|
|
41
|
+
const rowIndexStr = parts[0];
|
|
42
|
+
const columnId = parts[1];
|
|
43
|
+
if (rowIndexStr && columnId) {
|
|
44
|
+
const rowIndex = parseInt(rowIndexStr, 10);
|
|
45
|
+
if (!Number.isNaN(rowIndex)) {
|
|
46
|
+
return { rowIndex, columnId };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { rowIndex: 0, columnId: "" };
|
|
50
|
+
}
|
|
51
|
+
function getRowHeightValue(rowHeight) {
|
|
52
|
+
const rowHeightMap = {
|
|
53
|
+
short: 36,
|
|
54
|
+
medium: 56,
|
|
55
|
+
tall: 76,
|
|
56
|
+
"extra-tall": 96
|
|
57
|
+
};
|
|
58
|
+
return rowHeightMap[rowHeight];
|
|
59
|
+
}
|
|
60
|
+
function getLineCount(rowHeight) {
|
|
61
|
+
const lineCountMap = {
|
|
62
|
+
short: 1,
|
|
63
|
+
medium: 2,
|
|
64
|
+
tall: 3,
|
|
65
|
+
"extra-tall": 4
|
|
66
|
+
};
|
|
67
|
+
return lineCountMap[rowHeight];
|
|
68
|
+
}
|
|
69
|
+
function getColumnBorderVisibility(params) {
|
|
70
|
+
const { column, nextColumn, isLastColumn } = params;
|
|
71
|
+
const isPinned = column.getIsPinned();
|
|
72
|
+
const isFirstRightPinnedColumn = isPinned === "right" && column.getIsFirstColumn("right");
|
|
73
|
+
const isLastRightPinnedColumn = isPinned === "right" && column.getIsLastColumn("right");
|
|
74
|
+
const nextIsPinned = nextColumn?.getIsPinned();
|
|
75
|
+
const isBeforeRightPinned = nextIsPinned === "right" && nextColumn?.getIsFirstColumn("right");
|
|
76
|
+
const showEndBorder = !isBeforeRightPinned && (isLastColumn || !isLastRightPinnedColumn);
|
|
77
|
+
const showStartBorder = isFirstRightPinnedColumn;
|
|
78
|
+
return {
|
|
79
|
+
showEndBorder,
|
|
80
|
+
showStartBorder
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function getColumnPinningStyle(params) {
|
|
84
|
+
const { column, dir = "ltr", withBorder = false } = params;
|
|
85
|
+
const isPinned = column.getIsPinned();
|
|
86
|
+
const isLastLeftPinnedColumn = isPinned === "left" && column.getIsLastColumn("left");
|
|
87
|
+
const isFirstRightPinnedColumn = isPinned === "right" && column.getIsFirstColumn("right");
|
|
88
|
+
const isRtl = dir === "rtl";
|
|
89
|
+
const leftPosition = isPinned === "left" ? `${column.getStart("left")}px` : void 0;
|
|
90
|
+
const rightPosition = isPinned === "right" ? `${column.getAfter("right")}px` : void 0;
|
|
91
|
+
return {
|
|
92
|
+
boxShadow: withBorder ? isLastLeftPinnedColumn ? isRtl ? "4px 0 4px -4px var(--border) inset" : "-4px 0 4px -4px var(--border) inset" : isFirstRightPinnedColumn ? isRtl ? "-4px 0 4px -4px var(--border) inset" : "4px 0 4px -4px var(--border) inset" : void 0 : void 0,
|
|
93
|
+
left: isRtl ? rightPosition : leftPosition,
|
|
94
|
+
right: isRtl ? leftPosition : rightPosition,
|
|
95
|
+
opacity: isPinned ? 0.97 : 1,
|
|
96
|
+
position: isPinned ? "sticky" : "relative",
|
|
97
|
+
background: "var(--card)",
|
|
98
|
+
width: column.getSize(),
|
|
99
|
+
zIndex: isPinned ? 1 : void 0
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function getScrollDirection(direction) {
|
|
103
|
+
if (direction === "left" || direction === "right" || direction === "home" || direction === "end") {
|
|
104
|
+
return direction;
|
|
105
|
+
}
|
|
106
|
+
if (direction === "pageleft") return "left";
|
|
107
|
+
if (direction === "pageright") return "right";
|
|
108
|
+
return void 0;
|
|
109
|
+
}
|
|
110
|
+
function scrollCellIntoView(params) {
|
|
111
|
+
const { container, targetCell, tableRef, direction, viewportOffset, isRtl } = params;
|
|
112
|
+
const containerRect = container.getBoundingClientRect();
|
|
113
|
+
const cellRect = targetCell.getBoundingClientRect();
|
|
114
|
+
const hasNegativeScroll = container.scrollLeft < 0;
|
|
115
|
+
const isActuallyRtl = isRtl || hasNegativeScroll;
|
|
116
|
+
const currentTable = tableRef.current;
|
|
117
|
+
const leftPinnedColumns = currentTable?.getLeftVisibleLeafColumns() ?? [];
|
|
118
|
+
const rightPinnedColumns = currentTable?.getRightVisibleLeafColumns() ?? [];
|
|
119
|
+
const leftPinnedWidth = leftPinnedColumns.reduce((sum, c) => sum + c.getSize(), 0);
|
|
120
|
+
const rightPinnedWidth = rightPinnedColumns.reduce((sum, c) => sum + c.getSize(), 0);
|
|
121
|
+
const viewportLeft = isActuallyRtl ? containerRect.left + rightPinnedWidth + viewportOffset : containerRect.left + leftPinnedWidth + viewportOffset;
|
|
122
|
+
const viewportRight = isActuallyRtl ? containerRect.right - leftPinnedWidth - viewportOffset : containerRect.right - rightPinnedWidth - viewportOffset;
|
|
123
|
+
const isFullyVisible = cellRect.left >= viewportLeft && cellRect.right <= viewportRight;
|
|
124
|
+
if (isFullyVisible) return;
|
|
125
|
+
const isClippedLeft = cellRect.left < viewportLeft;
|
|
126
|
+
const isClippedRight = cellRect.right > viewportRight;
|
|
127
|
+
let scrollDelta = 0;
|
|
128
|
+
if (!direction) {
|
|
129
|
+
if (isClippedRight) {
|
|
130
|
+
scrollDelta = cellRect.right - viewportRight;
|
|
131
|
+
} else if (isClippedLeft) {
|
|
132
|
+
scrollDelta = -(viewportLeft - cellRect.left);
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
const shouldScrollRight = isActuallyRtl ? direction === "right" || direction === "home" : direction === "right" || direction === "end";
|
|
136
|
+
if (shouldScrollRight) {
|
|
137
|
+
scrollDelta = cellRect.right - viewportRight;
|
|
138
|
+
} else {
|
|
139
|
+
scrollDelta = -(viewportLeft - cellRect.left);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
container.scrollLeft += scrollDelta;
|
|
143
|
+
}
|
|
144
|
+
function countTabs(s) {
|
|
145
|
+
let n = 0;
|
|
146
|
+
for (let i = 0; i < s.length; i++) if (s[i] === " ") n++;
|
|
147
|
+
return n;
|
|
148
|
+
}
|
|
149
|
+
function parseTsv(text, fallbackColumnCount) {
|
|
150
|
+
if (text.startsWith('"') || text.includes(' "')) {
|
|
151
|
+
const rows2 = [];
|
|
152
|
+
let currentRow = [];
|
|
153
|
+
let currentField = "";
|
|
154
|
+
let inQuotes = false;
|
|
155
|
+
let i = 0;
|
|
156
|
+
while (i < text.length) {
|
|
157
|
+
const char = text[i];
|
|
158
|
+
const nextChar = text[i + 1];
|
|
159
|
+
if (inQuotes) {
|
|
160
|
+
if (char === '"' && nextChar === '"') {
|
|
161
|
+
currentField += '"';
|
|
162
|
+
i += 2;
|
|
163
|
+
} else if (char === '"') {
|
|
164
|
+
inQuotes = false;
|
|
165
|
+
i++;
|
|
166
|
+
} else {
|
|
167
|
+
currentField += char;
|
|
168
|
+
i++;
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
if (char === '"' && currentField === "") {
|
|
172
|
+
inQuotes = true;
|
|
173
|
+
i++;
|
|
174
|
+
} else if (char === " ") {
|
|
175
|
+
currentRow.push(currentField);
|
|
176
|
+
currentField = "";
|
|
177
|
+
i++;
|
|
178
|
+
} else if (char === "\n") {
|
|
179
|
+
currentRow.push(currentField);
|
|
180
|
+
if (currentRow.length > 1 || currentRow.some((f) => f.length > 0)) {
|
|
181
|
+
rows2.push(currentRow);
|
|
182
|
+
}
|
|
183
|
+
currentRow = [];
|
|
184
|
+
currentField = "";
|
|
185
|
+
i++;
|
|
186
|
+
} else if (char === "\r" && nextChar === "\n") {
|
|
187
|
+
currentRow.push(currentField);
|
|
188
|
+
if (currentRow.length > 1 || currentRow.some((f) => f.length > 0)) {
|
|
189
|
+
rows2.push(currentRow);
|
|
190
|
+
}
|
|
191
|
+
currentRow = [];
|
|
192
|
+
currentField = "";
|
|
193
|
+
i += 2;
|
|
194
|
+
} else {
|
|
195
|
+
currentField += char;
|
|
196
|
+
i++;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
currentRow.push(currentField);
|
|
201
|
+
if (currentRow.length > 1 || currentRow.some((f) => f.length > 0)) {
|
|
202
|
+
rows2.push(currentRow);
|
|
203
|
+
}
|
|
204
|
+
return rows2;
|
|
205
|
+
}
|
|
206
|
+
const lines = text.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
207
|
+
let maxTabCount = 0;
|
|
208
|
+
for (const line of lines) {
|
|
209
|
+
const n = countTabs(line);
|
|
210
|
+
if (n > maxTabCount) maxTabCount = n;
|
|
211
|
+
}
|
|
212
|
+
const columnCount = maxTabCount > 0 ? maxTabCount + 1 : fallbackColumnCount;
|
|
213
|
+
if (columnCount <= 0) return [];
|
|
214
|
+
const expectedTabCount = columnCount - 1;
|
|
215
|
+
const rows = [];
|
|
216
|
+
let buf = "";
|
|
217
|
+
let bufTabCount = 0;
|
|
218
|
+
for (const line of lines) {
|
|
219
|
+
const tc = countTabs(line);
|
|
220
|
+
if (tc === expectedTabCount) {
|
|
221
|
+
if (buf && bufTabCount === expectedTabCount) rows.push(buf.split(" "));
|
|
222
|
+
buf = "";
|
|
223
|
+
bufTabCount = 0;
|
|
224
|
+
rows.push(line.split(" "));
|
|
225
|
+
} else {
|
|
226
|
+
buf = buf ? `${buf}
|
|
227
|
+
${line}` : line;
|
|
228
|
+
bufTabCount += tc;
|
|
229
|
+
if (bufTabCount === expectedTabCount) {
|
|
230
|
+
rows.push(buf.split(" "));
|
|
231
|
+
buf = "";
|
|
232
|
+
bufTabCount = 0;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (buf && bufTabCount === expectedTabCount) rows.push(buf.split(" "));
|
|
237
|
+
return rows.length > 0 ? rows : lines.filter((l) => l.length > 0).map((l) => l.split(" "));
|
|
238
|
+
}
|
|
239
|
+
function getIsInPopover(element) {
|
|
240
|
+
if (!(element instanceof Element)) return false;
|
|
241
|
+
return element.closest("[data-grid-cell-editor]") !== null || element.closest("[data-grid-popover]") !== null || element.closest("[data-radix-popper-content-wrapper]") !== null || element.closest("[role='dialog']") !== null || element.closest("[role='menu']") !== null || element.closest("[role='listbox']") !== null;
|
|
242
|
+
}
|
|
243
|
+
function getColumnVariant(variant) {
|
|
244
|
+
switch (variant) {
|
|
245
|
+
case "short-text":
|
|
246
|
+
return { label: msg.column.variant.shortText, icon: BaselineIcon };
|
|
247
|
+
case "long-text":
|
|
248
|
+
return { label: msg.column.variant.longText, icon: WrapTextIcon };
|
|
249
|
+
case "number":
|
|
250
|
+
return { label: msg.column.variant.number, icon: HashIcon };
|
|
251
|
+
case "url":
|
|
252
|
+
return { label: msg.column.variant.url, icon: LinkIcon };
|
|
253
|
+
case "checkbox":
|
|
254
|
+
return { label: msg.column.variant.checkbox, icon: CheckSquareIcon };
|
|
255
|
+
case "select":
|
|
256
|
+
return { label: msg.column.variant.select, icon: ListIcon };
|
|
257
|
+
case "multi-select":
|
|
258
|
+
return { label: msg.column.variant.multiSelect, icon: ListChecksIcon };
|
|
259
|
+
case "date":
|
|
260
|
+
return { label: msg.column.variant.date, icon: CalendarIcon };
|
|
261
|
+
case "file":
|
|
262
|
+
return { label: msg.column.variant.file, icon: FileIcon };
|
|
263
|
+
default:
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function getEmptyCellValue(variant) {
|
|
268
|
+
if (variant === "multi-select" || variant === "file") return [];
|
|
269
|
+
if (variant === "number" || variant === "date" || variant === "select") return null;
|
|
270
|
+
if (variant === "checkbox") return false;
|
|
271
|
+
return "";
|
|
272
|
+
}
|
|
273
|
+
function getUrlHref(urlString) {
|
|
274
|
+
if (!urlString || urlString.trim() === "") return "";
|
|
275
|
+
const trimmed = urlString.trim();
|
|
276
|
+
if (/^(javascript|data|vbscript|file):/i.test(trimmed)) {
|
|
277
|
+
return "";
|
|
278
|
+
}
|
|
279
|
+
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
|
|
280
|
+
return trimmed;
|
|
281
|
+
}
|
|
282
|
+
return `http://${trimmed}`;
|
|
283
|
+
}
|
|
284
|
+
function parseLocalDate(dateStr) {
|
|
285
|
+
if (!dateStr) return null;
|
|
286
|
+
if (dateStr instanceof Date) return dateStr;
|
|
287
|
+
if (typeof dateStr !== "string") return null;
|
|
288
|
+
const [year, month, day] = dateStr.split("-").map(Number);
|
|
289
|
+
if (!year || !month || !day) return null;
|
|
290
|
+
const date = new Date(year, month - 1, day);
|
|
291
|
+
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
return date;
|
|
295
|
+
}
|
|
296
|
+
function formatDateToString(date) {
|
|
297
|
+
const year = date.getFullYear();
|
|
298
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
299
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
300
|
+
return `${year}-${month}-${day}`;
|
|
301
|
+
}
|
|
302
|
+
function formatDate(date) {
|
|
303
|
+
if (!date) return "";
|
|
304
|
+
const value = date instanceof Date ? date : new Date(date);
|
|
305
|
+
if (Number.isNaN(value.getTime())) return "";
|
|
306
|
+
return format(value, "dd/MM/yyyy");
|
|
307
|
+
}
|
|
308
|
+
function formatDateForDisplay(dateStr) {
|
|
309
|
+
if (!dateStr) return "";
|
|
310
|
+
const date = parseLocalDate(dateStr);
|
|
311
|
+
if (!date) return typeof dateStr === "string" ? dateStr : "";
|
|
312
|
+
return formatDate(date);
|
|
313
|
+
}
|
|
314
|
+
function generateFileId() {
|
|
315
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
316
|
+
return crypto.randomUUID();
|
|
317
|
+
}
|
|
318
|
+
return `file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
319
|
+
}
|
|
320
|
+
async function writeClipboardText(text) {
|
|
321
|
+
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
|
|
322
|
+
try {
|
|
323
|
+
await navigator.clipboard.writeText(text);
|
|
324
|
+
return;
|
|
325
|
+
} catch {
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (!copyWithExecCommand(text)) {
|
|
329
|
+
throw new Error("Clipboard kh\xF4ng kh\u1EA3 d\u1EE5ng");
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function copyWithExecCommand(text) {
|
|
333
|
+
if (typeof document === "undefined") return false;
|
|
334
|
+
const textarea = document.createElement("textarea");
|
|
335
|
+
textarea.value = text;
|
|
336
|
+
textarea.setAttribute("readonly", "");
|
|
337
|
+
textarea.style.position = "fixed";
|
|
338
|
+
textarea.style.top = "0";
|
|
339
|
+
textarea.style.insetInlineStart = "-9999px";
|
|
340
|
+
document.body.appendChild(textarea);
|
|
341
|
+
const previouslyFocused = document.activeElement;
|
|
342
|
+
textarea.select();
|
|
343
|
+
let copied = false;
|
|
344
|
+
try {
|
|
345
|
+
copied = document.execCommand("copy");
|
|
346
|
+
} catch {
|
|
347
|
+
copied = false;
|
|
348
|
+
}
|
|
349
|
+
document.body.removeChild(textarea);
|
|
350
|
+
if (previouslyFocused instanceof HTMLElement) {
|
|
351
|
+
previouslyFocused.focus();
|
|
352
|
+
}
|
|
353
|
+
return copied;
|
|
354
|
+
}
|
|
355
|
+
async function readClipboardText() {
|
|
356
|
+
if (typeof navigator === "undefined" || !navigator.clipboard?.readText) return null;
|
|
357
|
+
try {
|
|
358
|
+
return await navigator.clipboard.readText();
|
|
359
|
+
} catch {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function formatFileSize(bytes) {
|
|
364
|
+
if (bytes <= 0 || !Number.isFinite(bytes)) return "0 B";
|
|
365
|
+
const k = 1024;
|
|
366
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
367
|
+
const i = Math.min(sizes.length - 1, Math.floor(Math.log(bytes) / Math.log(k)));
|
|
368
|
+
return `${Number.parseFloat((bytes / k ** i).toFixed(1))} ${sizes[i]}`;
|
|
369
|
+
}
|
|
370
|
+
function getFileIcon(type) {
|
|
371
|
+
if (type.startsWith("image/")) return FileImage;
|
|
372
|
+
if (type.startsWith("video/")) return FileVideo;
|
|
373
|
+
if (type.startsWith("audio/")) return FileAudio;
|
|
374
|
+
if (type.includes("pdf")) return FileText;
|
|
375
|
+
if (type.includes("zip") || type.includes("rar")) return FileArchive;
|
|
376
|
+
if (type.includes("word") || type.includes("document") || type.includes("doc")) return FileText;
|
|
377
|
+
if (type.includes("sheet") || type.includes("excel") || type.includes("xls")) return FileSpreadsheet;
|
|
378
|
+
if (type.includes("presentation") || type.includes("powerpoint") || type.includes("ppt")) return Presentation;
|
|
379
|
+
return File;
|
|
380
|
+
}
|
|
381
|
+
export {
|
|
382
|
+
flexRender,
|
|
383
|
+
formatDate,
|
|
384
|
+
formatDateForDisplay,
|
|
385
|
+
formatDateToString,
|
|
386
|
+
formatFileSize,
|
|
387
|
+
generateFileId,
|
|
388
|
+
getCellKey,
|
|
389
|
+
getColumnBorderVisibility,
|
|
390
|
+
getColumnPinningStyle,
|
|
391
|
+
getColumnVariant,
|
|
392
|
+
getEmptyCellValue,
|
|
393
|
+
getFileIcon,
|
|
394
|
+
getIsFileCellData,
|
|
395
|
+
getIsInPopover,
|
|
396
|
+
getLineCount,
|
|
397
|
+
getRowHeightValue,
|
|
398
|
+
getScrollDirection,
|
|
399
|
+
getUrlHref,
|
|
400
|
+
matchSelectOption,
|
|
401
|
+
parseCellKey,
|
|
402
|
+
parseLocalDate,
|
|
403
|
+
parseTsv,
|
|
404
|
+
readClipboardText,
|
|
405
|
+
scrollCellIntoView,
|
|
406
|
+
writeClipboardText
|
|
407
|
+
};
|
|
408
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/utils.ts"],"sourcesContent":["import type { Column, Table } from \"@tanstack/react-table\";\nimport { format } from \"date-fns\";\nimport {\n BaselineIcon,\n CalendarIcon,\n CheckSquareIcon,\n File,\n FileArchive,\n FileAudio,\n FileIcon,\n FileImage,\n FileSpreadsheet,\n FileText,\n FileVideo,\n HashIcon,\n LinkIcon,\n ListChecksIcon,\n ListIcon,\n Presentation,\n WrapTextIcon\n} from \"lucide-react\";\nimport type * as React from \"react\";\nimport { msg } from \"./messages.js\";\nimport type { CellOpts, CellPosition, Direction, FileCellData, RowHeightValue } from \"./types.js\";\n\nexport function flexRender<TProps extends object>(\n Comp: ((props: TProps) => React.ReactNode) | string | undefined,\n props: TProps\n): React.ReactNode {\n if (typeof Comp === \"string\") {\n return Comp;\n }\n return Comp?.(props);\n}\n\nexport function getIsFileCellData(item: unknown): item is FileCellData {\n return !!item && typeof item === \"object\" && \"id\" in item && \"name\" in item && \"size\" in item && \"type\" in item;\n}\n\nexport function matchSelectOption(value: string, options: { value: string; label: string }[]): string | undefined {\n return options.find(\n (o) =>\n o.value === value ||\n o.value.toLowerCase() === value.toLowerCase() ||\n o.label.toLowerCase() === value.toLowerCase()\n )?.value;\n}\n\nexport function getCellKey(rowIndex: number, columnId: string) {\n return `${rowIndex}:${columnId}`;\n}\n\nexport function parseCellKey(cellKey: string): Required<CellPosition> {\n const parts = cellKey.split(\":\");\n const rowIndexStr = parts[0];\n const columnId = parts[1];\n if (rowIndexStr && columnId) {\n const rowIndex = parseInt(rowIndexStr, 10);\n if (!Number.isNaN(rowIndex)) {\n return { rowIndex, columnId };\n }\n }\n return { rowIndex: 0, columnId: \"\" };\n}\n\nexport function getRowHeightValue(rowHeight: RowHeightValue): number {\n const rowHeightMap: Record<RowHeightValue, number> = {\n short: 36,\n medium: 56,\n tall: 76,\n \"extra-tall\": 96\n };\n\n return rowHeightMap[rowHeight];\n}\n\nexport function getLineCount(rowHeight: RowHeightValue): number {\n const lineCountMap: Record<RowHeightValue, number> = {\n short: 1,\n medium: 2,\n tall: 3,\n \"extra-tall\": 4\n };\n\n return lineCountMap[rowHeight];\n}\n\nexport function getColumnBorderVisibility<TData>(params: {\n column: Column<TData>;\n nextColumn?: Column<TData>;\n isLastColumn: boolean;\n}): {\n showEndBorder: boolean;\n showStartBorder: boolean;\n} {\n const { column, nextColumn, isLastColumn } = params;\n\n const isPinned = column.getIsPinned();\n const isFirstRightPinnedColumn = isPinned === \"right\" && column.getIsFirstColumn(\"right\");\n const isLastRightPinnedColumn = isPinned === \"right\" && column.getIsLastColumn(\"right\");\n\n const nextIsPinned = nextColumn?.getIsPinned();\n const isBeforeRightPinned = nextIsPinned === \"right\" && nextColumn?.getIsFirstColumn(\"right\");\n\n const showEndBorder = !isBeforeRightPinned && (isLastColumn || !isLastRightPinnedColumn);\n\n const showStartBorder = isFirstRightPinnedColumn;\n\n return {\n showEndBorder,\n showStartBorder\n };\n}\n\nexport function getColumnPinningStyle<TData>(params: {\n column: Column<TData>;\n withBorder?: boolean;\n dir?: Direction;\n}): React.CSSProperties {\n const { column, dir = \"ltr\", withBorder = false } = params;\n\n const isPinned = column.getIsPinned();\n const isLastLeftPinnedColumn = isPinned === \"left\" && column.getIsLastColumn(\"left\");\n const isFirstRightPinnedColumn = isPinned === \"right\" && column.getIsFirstColumn(\"right\");\n\n const isRtl = dir === \"rtl\";\n\n const leftPosition = isPinned === \"left\" ? `${column.getStart(\"left\")}px` : undefined;\n const rightPosition = isPinned === \"right\" ? `${column.getAfter(\"right\")}px` : undefined;\n\n /*\n * ⚠ Token của gói này là MÀU ĐẦY ĐỦ (`--card: #ffffff`), KHÔNG phải bộ 3 kênh HSL — nên viết\n * `var(--card)` trần, đừng bọc `hsl()`. Bản gốc port từ một hệ token kiểu `\"150 20% 98%\"` nên\n * ở đó `hsl(var(--card))` mới đúng; bê nguyên sang đây thì `hsl(#ffffff)` là giá trị KHÔNG\n * HỢP LỆ, và hệ quả là cột ghim trong suốt — nội dung cuộn phía dưới lộ xuyên qua. Không có\n * lỗi nào được ném ra: CSS bỏ qua khai báo hỏng rồi rơi về `background: transparent`.\n *\n * Nền lấy theo `--card` vì hộp lưới dùng `bg-card` như mọi bảng khác của gói.\n */\n return {\n boxShadow: withBorder\n ? isLastLeftPinnedColumn\n ? isRtl\n ? \"4px 0 4px -4px var(--border) inset\"\n : \"-4px 0 4px -4px var(--border) inset\"\n : isFirstRightPinnedColumn\n ? isRtl\n ? \"-4px 0 4px -4px var(--border) inset\"\n : \"4px 0 4px -4px var(--border) inset\"\n : undefined\n : undefined,\n left: isRtl ? rightPosition : leftPosition,\n right: isRtl ? leftPosition : rightPosition,\n opacity: isPinned ? 0.97 : 1,\n position: isPinned ? \"sticky\" : \"relative\",\n background: \"var(--card)\",\n width: column.getSize(),\n zIndex: isPinned ? 1 : undefined\n };\n}\n\nexport function getScrollDirection(direction: string): \"left\" | \"right\" | \"home\" | \"end\" | undefined {\n if (direction === \"left\" || direction === \"right\" || direction === \"home\" || direction === \"end\") {\n return direction as \"left\" | \"right\" | \"home\" | \"end\";\n }\n if (direction === \"pageleft\") return \"left\";\n if (direction === \"pageright\") return \"right\";\n return undefined;\n}\n\nexport function scrollCellIntoView<TData>(params: {\n container: HTMLDivElement;\n targetCell: HTMLDivElement;\n tableRef: React.RefObject<Table<TData> | null>;\n viewportOffset: number;\n direction?: \"left\" | \"right\" | \"home\" | \"end\";\n isRtl: boolean;\n}): void {\n const { container, targetCell, tableRef, direction, viewportOffset, isRtl } = params;\n\n const containerRect = container.getBoundingClientRect();\n const cellRect = targetCell.getBoundingClientRect();\n\n const hasNegativeScroll = container.scrollLeft < 0;\n const isActuallyRtl = isRtl || hasNegativeScroll;\n\n const currentTable = tableRef.current;\n const leftPinnedColumns = currentTable?.getLeftVisibleLeafColumns() ?? [];\n const rightPinnedColumns = currentTable?.getRightVisibleLeafColumns() ?? [];\n\n const leftPinnedWidth = leftPinnedColumns.reduce((sum, c) => sum + c.getSize(), 0);\n const rightPinnedWidth = rightPinnedColumns.reduce((sum, c) => sum + c.getSize(), 0);\n\n const viewportLeft = isActuallyRtl\n ? containerRect.left + rightPinnedWidth + viewportOffset\n : containerRect.left + leftPinnedWidth + viewportOffset;\n const viewportRight = isActuallyRtl\n ? containerRect.right - leftPinnedWidth - viewportOffset\n : containerRect.right - rightPinnedWidth - viewportOffset;\n\n const isFullyVisible = cellRect.left >= viewportLeft && cellRect.right <= viewportRight;\n\n if (isFullyVisible) return;\n\n const isClippedLeft = cellRect.left < viewportLeft;\n const isClippedRight = cellRect.right > viewportRight;\n\n let scrollDelta = 0;\n\n if (!direction) {\n if (isClippedRight) {\n scrollDelta = cellRect.right - viewportRight;\n } else if (isClippedLeft) {\n scrollDelta = -(viewportLeft - cellRect.left);\n }\n } else {\n const shouldScrollRight = isActuallyRtl\n ? direction === \"right\" || direction === \"home\"\n : direction === \"right\" || direction === \"end\";\n\n if (shouldScrollRight) {\n scrollDelta = cellRect.right - viewportRight;\n } else {\n scrollDelta = -(viewportLeft - cellRect.left);\n }\n }\n\n container.scrollLeft += scrollDelta;\n}\n\nfunction countTabs(s: string): number {\n let n = 0;\n for (let i = 0; i < s.length; i++) if (s[i] === \"\\t\") n++;\n return n;\n}\n\nexport function parseTsv(text: string, fallbackColumnCount: number): string[][] {\n if (text.startsWith('\"') || text.includes('\\t\"')) {\n const rows: string[][] = [];\n let currentRow: string[] = [];\n let currentField = \"\";\n let inQuotes = false;\n let i = 0;\n\n while (i < text.length) {\n const char = text[i];\n const nextChar = text[i + 1];\n\n if (inQuotes) {\n if (char === '\"' && nextChar === '\"') {\n currentField += '\"';\n i += 2;\n } else if (char === '\"') {\n inQuotes = false;\n i++;\n } else {\n currentField += char;\n i++;\n }\n } else {\n if (char === '\"' && currentField === \"\") {\n inQuotes = true;\n i++;\n } else if (char === \"\\t\") {\n currentRow.push(currentField);\n currentField = \"\";\n i++;\n } else if (char === \"\\n\") {\n currentRow.push(currentField);\n if (currentRow.length > 1 || currentRow.some((f) => f.length > 0)) {\n rows.push(currentRow);\n }\n currentRow = [];\n currentField = \"\";\n i++;\n } else if (char === \"\\r\" && nextChar === \"\\n\") {\n currentRow.push(currentField);\n if (currentRow.length > 1 || currentRow.some((f) => f.length > 0)) {\n rows.push(currentRow);\n }\n currentRow = [];\n currentField = \"\";\n i += 2;\n } else {\n currentField += char;\n i++;\n }\n }\n }\n\n currentRow.push(currentField);\n if (currentRow.length > 1 || currentRow.some((f) => f.length > 0)) {\n rows.push(currentRow);\n }\n\n return rows;\n }\n\n const lines = text.split(\"\\n\").map((l) => l.replace(/\\r$/, \"\"));\n let maxTabCount = 0;\n for (const line of lines) {\n const n = countTabs(line);\n if (n > maxTabCount) maxTabCount = n;\n }\n const columnCount = maxTabCount > 0 ? maxTabCount + 1 : fallbackColumnCount;\n if (columnCount <= 0) return [];\n\n const expectedTabCount = columnCount - 1;\n const rows: string[][] = [];\n let buf = \"\";\n let bufTabCount = 0;\n\n for (const line of lines) {\n const tc = countTabs(line);\n\n if (tc === expectedTabCount) {\n if (buf && bufTabCount === expectedTabCount) rows.push(buf.split(\"\\t\"));\n buf = \"\";\n bufTabCount = 0;\n rows.push(line.split(\"\\t\"));\n } else {\n buf = buf ? `${buf}\\n${line}` : line;\n bufTabCount += tc;\n if (bufTabCount === expectedTabCount) {\n rows.push(buf.split(\"\\t\"));\n buf = \"\";\n bufTabCount = 0;\n }\n }\n }\n\n if (buf && bufTabCount === expectedTabCount) rows.push(buf.split(\"\\t\"));\n\n return rows.length > 0 ? rows : lines.filter((l) => l.length > 0).map((l) => l.split(\"\\t\"));\n}\n\n/**\n * Phần tử có đang nằm trong một lớp nổi không? Dùng để lưới KHÔNG coi thao tác\n * trong popover/menu/hộp thoại là \"bấm ra ngoài\" (sẽ mất focus ô đang sửa).\n *\n * Primitive của package không gắn `data-slot`, nên bắt theo wrapper của Radix Popper\n * (bao Popover/DropdownMenu/Select/Tooltip) và theo role — kể cả Select \"item-aligned\".\n */\nexport function getIsInPopover(element: unknown): boolean {\n if (!(element instanceof Element)) return false;\n\n return (\n element.closest(\"[data-grid-cell-editor]\") !== null ||\n element.closest(\"[data-grid-popover]\") !== null ||\n element.closest(\"[data-radix-popper-content-wrapper]\") !== null ||\n element.closest(\"[role='dialog']\") !== null ||\n element.closest(\"[role='menu']\") !== null ||\n element.closest(\"[role='listbox']\") !== null\n );\n}\n\nexport function getColumnVariant(variant?: CellOpts[\"variant\"]): {\n icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;\n label: string;\n} | null {\n switch (variant) {\n case \"short-text\":\n return { label: msg.column.variant.shortText, icon: BaselineIcon };\n case \"long-text\":\n return { label: msg.column.variant.longText, icon: WrapTextIcon };\n case \"number\":\n return { label: msg.column.variant.number, icon: HashIcon };\n case \"url\":\n return { label: msg.column.variant.url, icon: LinkIcon };\n case \"checkbox\":\n return { label: msg.column.variant.checkbox, icon: CheckSquareIcon };\n case \"select\":\n return { label: msg.column.variant.select, icon: ListIcon };\n case \"multi-select\":\n return { label: msg.column.variant.multiSelect, icon: ListChecksIcon };\n case \"date\":\n return { label: msg.column.variant.date, icon: CalendarIcon };\n case \"file\":\n return { label: msg.column.variant.file, icon: FileIcon };\n default:\n return null;\n }\n}\n\nexport function getEmptyCellValue(variant: CellOpts[\"variant\"] | undefined): unknown {\n if (variant === \"multi-select\" || variant === \"file\") return [];\n if (variant === \"number\" || variant === \"date\" || variant === \"select\") return null;\n if (variant === \"checkbox\") return false;\n return \"\";\n}\n\nexport function getUrlHref(urlString: string): string {\n if (!urlString || urlString.trim() === \"\") return \"\";\n\n const trimmed = urlString.trim();\n\n // Reject dangerous protocols (extra safety, though our http:// prefix would neutralize them)\n if (/^(javascript|data|vbscript|file):/i.test(trimmed)) {\n return \"\";\n }\n\n if (trimmed.startsWith(\"http://\") || trimmed.startsWith(\"https://\")) {\n return trimmed;\n }\n\n return `http://${trimmed}`;\n}\n\nexport function parseLocalDate(dateStr: unknown): Date | null {\n if (!dateStr) return null;\n if (dateStr instanceof Date) return dateStr;\n if (typeof dateStr !== \"string\") return null;\n const [year, month, day] = dateStr.split(\"-\").map(Number);\n if (!year || !month || !day) return null;\n const date = new Date(year, month - 1, day);\n // Verify date wasn't auto-corrected (e.g. Feb 30 -> Mar 1)\n if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {\n return null;\n }\n return date;\n}\n\nexport function formatDateToString(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\n/** Hiển thị ngày theo chuẩn Việt Nam dd/MM/yyyy (dùng cho ô ngày, bộ lọc ngày) */\nexport function formatDate(date: Date | string | number | null | undefined): string {\n if (!date) return \"\";\n const value = date instanceof Date ? date : new Date(date);\n if (Number.isNaN(value.getTime())) return \"\";\n return format(value, \"dd/MM/yyyy\");\n}\n\nexport function formatDateForDisplay(dateStr: unknown): string {\n if (!dateStr) return \"\";\n const date = parseLocalDate(dateStr);\n if (!date) return typeof dateStr === \"string\" ? dateStr : \"\";\n return formatDate(date);\n}\n\n/**\n * Id cho tệp đính kèm. `crypto.randomUUID` chỉ có ở secure context (https/localhost) —\n * app nội bộ chạy http trong mạng bệnh viện sẽ không có, nên phải có đường lui.\n */\nexport function generateFileId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n return `file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Chép text vào clipboard. `navigator.clipboard` cũng chỉ có ở secure context,\n * nên rơi về `document.execCommand(\"copy\")` (đã deprecated nhưng vẫn chạy mọi trình duyệt).\n * Ném lỗi khi cả hai đường đều không dùng được để phía gọi báo toast.\n */\nexport async function writeClipboardText(text: string): Promise<void> {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n try {\n await navigator.clipboard.writeText(text);\n return;\n } catch {\n // Bị chặn quyền → thử đường lui bên dưới\n }\n }\n\n if (!copyWithExecCommand(text)) {\n throw new Error(\"Clipboard không khả dụng\");\n }\n}\n\nfunction copyWithExecCommand(text: string): boolean {\n if (typeof document === \"undefined\") return false;\n\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"fixed\";\n textarea.style.top = \"0\";\n textarea.style.insetInlineStart = \"-9999px\";\n document.body.appendChild(textarea);\n\n const previouslyFocused = document.activeElement;\n textarea.select();\n\n let copied = false;\n try {\n copied = document.execCommand(\"copy\");\n } catch {\n copied = false;\n }\n\n document.body.removeChild(textarea);\n if (previouslyFocused instanceof HTMLElement) {\n previouslyFocused.focus();\n }\n\n return copied;\n}\n\n/** Đọc clipboard khi có quyền; trả `null` nếu trình duyệt/ngữ cảnh không cho đọc. */\nexport async function readClipboardText(): Promise<string | null> {\n if (typeof navigator === \"undefined\" || !navigator.clipboard?.readText) return null;\n try {\n return await navigator.clipboard.readText();\n } catch {\n return null;\n }\n}\n\nexport function formatFileSize(bytes: number): string {\n if (bytes <= 0 || !Number.isFinite(bytes)) return \"0 B\";\n const k = 1024;\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\"];\n const i = Math.min(sizes.length - 1, Math.floor(Math.log(bytes) / Math.log(k)));\n return `${Number.parseFloat((bytes / k ** i).toFixed(1))} ${sizes[i]}`;\n}\n\nexport function getFileIcon(type: string): React.ComponentType<React.SVGProps<SVGSVGElement>> {\n if (type.startsWith(\"image/\")) return FileImage;\n if (type.startsWith(\"video/\")) return FileVideo;\n if (type.startsWith(\"audio/\")) return FileAudio;\n if (type.includes(\"pdf\")) return FileText;\n if (type.includes(\"zip\") || type.includes(\"rar\")) return FileArchive;\n if (type.includes(\"word\") || type.includes(\"document\") || type.includes(\"doc\")) return FileText;\n if (type.includes(\"sheet\") || type.includes(\"excel\") || type.includes(\"xls\")) return FileSpreadsheet;\n if (type.includes(\"presentation\") || type.includes(\"powerpoint\") || type.includes(\"ppt\")) return Presentation;\n return File;\n}\n"],"mappings":"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","names":["rows"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comitor/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Comitor design system — Shadcn/UI tùy biến theo brand Comitor + component dùng chung cho hệ sinh thái SaaS (Tasks, Chat, CRM, HR…)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
"types": "./dist/chart/index.d.ts",
|
|
43
43
|
"import": "./dist/chart/index.js"
|
|
44
44
|
},
|
|
45
|
+
"./data-grid": {
|
|
46
|
+
"types": "./dist/data-grid/index.d.ts",
|
|
47
|
+
"import": "./dist/data-grid/index.js"
|
|
48
|
+
},
|
|
45
49
|
"./uploader": {
|
|
46
50
|
"types": "./dist/uploader/index.d.ts",
|
|
47
51
|
"import": "./dist/uploader/index.js"
|
|
@@ -57,7 +61,24 @@
|
|
|
57
61
|
"./styles.css": "./styles.css",
|
|
58
62
|
"./package.json": "./package.json"
|
|
59
63
|
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "tsup",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"version:check": "node scripts/check-version.mjs",
|
|
68
|
+
"lint": "biome check --error-on-warnings .",
|
|
69
|
+
"lint:fix": "biome check --write .",
|
|
70
|
+
"lint:a11y": "node scripts/check-contrast.mjs",
|
|
71
|
+
"test:a11y-gate": "node scripts/a11y/self-test.mjs",
|
|
72
|
+
"test:nav-active": "node scripts/check-nav-active.mjs",
|
|
73
|
+
"test:grid-render": "node scripts/check-data-grid-render.mjs",
|
|
74
|
+
"verify:directives": "node scripts/verify-directives.mjs",
|
|
75
|
+
"smoke:entries": "node scripts/smoke-entries.mjs",
|
|
76
|
+
"check:exports": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css",
|
|
77
|
+
"prepublishOnly": "pnpm run typecheck && pnpm run build && pnpm run verify:directives && pnpm run smoke:entries && pnpm run check:exports && pnpm run test:nav-active && pnpm run test:grid-contract && pnpm run test:grid-render && pnpm run test:a11y-gate && pnpm run lint:a11y",
|
|
78
|
+
"test:grid-contract": "node scripts/check-grid-contract.mjs"
|
|
79
|
+
},
|
|
60
80
|
"peerDependencies": {
|
|
81
|
+
"@tanstack/react-table": ">=8.21.0 <9",
|
|
61
82
|
"@uppy/core": "^6.0.0",
|
|
62
83
|
"@uppy/xhr-upload": "^6.0.0",
|
|
63
84
|
"lucide-react": ">=0.540.0",
|
|
@@ -70,6 +91,9 @@
|
|
|
70
91
|
"tailwindcss": "^4.1.0"
|
|
71
92
|
},
|
|
72
93
|
"peerDependenciesMeta": {
|
|
94
|
+
"@tanstack/react-table": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
73
97
|
"@uppy/core": {
|
|
74
98
|
"optional": true
|
|
75
99
|
},
|
|
@@ -90,6 +114,10 @@
|
|
|
90
114
|
}
|
|
91
115
|
},
|
|
92
116
|
"dependencies": {
|
|
117
|
+
"@dnd-kit/core": "^6.3.1",
|
|
118
|
+
"@dnd-kit/modifiers": "^9.0.0",
|
|
119
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
120
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
93
121
|
"@radix-ui/react-accordion": "1.2.12",
|
|
94
122
|
"@radix-ui/react-alert-dialog": "1.1.15",
|
|
95
123
|
"@radix-ui/react-aspect-ratio": "1.1.8",
|
|
@@ -98,6 +126,7 @@
|
|
|
98
126
|
"@radix-ui/react-collapsible": "1.1.12",
|
|
99
127
|
"@radix-ui/react-context-menu": "2.2.16",
|
|
100
128
|
"@radix-ui/react-dialog": "1.1.15",
|
|
129
|
+
"@radix-ui/react-direction": "1.1.1",
|
|
101
130
|
"@radix-ui/react-dropdown-menu": "2.1.16",
|
|
102
131
|
"@radix-ui/react-hover-card": "1.1.15",
|
|
103
132
|
"@radix-ui/react-label": "2.1.8",
|
|
@@ -116,6 +145,7 @@
|
|
|
116
145
|
"@radix-ui/react-toggle": "1.1.10",
|
|
117
146
|
"@radix-ui/react-toggle-group": "1.1.11",
|
|
118
147
|
"@radix-ui/react-tooltip": "1.2.8",
|
|
148
|
+
"@tanstack/react-virtual": "^3.14.13",
|
|
119
149
|
"class-variance-authority": "^0.7.1",
|
|
120
150
|
"clsx": "^2.1.1",
|
|
121
151
|
"cmdk": "1.1.1",
|
|
@@ -132,6 +162,7 @@
|
|
|
132
162
|
"devDependencies": {
|
|
133
163
|
"@arethetypeswrong/cli": "^0.18.4",
|
|
134
164
|
"@biomejs/biome": "^2.4.11",
|
|
165
|
+
"@tanstack/react-table": "^8.21.3",
|
|
135
166
|
"@types/node": "^22.0.0",
|
|
136
167
|
"@types/react": "^19.0.0",
|
|
137
168
|
"@types/react-dom": "^19.0.0",
|
|
@@ -148,18 +179,5 @@
|
|
|
148
179
|
"tailwindcss": "^4.2.0",
|
|
149
180
|
"tsup": "^8.3.5",
|
|
150
181
|
"typescript": "^5.7.0"
|
|
151
|
-
},
|
|
152
|
-
"scripts": {
|
|
153
|
-
"build": "tsup",
|
|
154
|
-
"typecheck": "tsc --noEmit",
|
|
155
|
-
"lint": "biome check --error-on-warnings .",
|
|
156
|
-
"lint:fix": "biome check --write .",
|
|
157
|
-
"lint:a11y": "node scripts/check-contrast.mjs",
|
|
158
|
-
"test:a11y-gate": "node scripts/a11y/self-test.mjs",
|
|
159
|
-
"test:nav-active": "node scripts/check-nav-active.mjs",
|
|
160
|
-
"verify:directives": "node scripts/verify-directives.mjs",
|
|
161
|
-
"smoke:entries": "node scripts/smoke-entries.mjs",
|
|
162
|
-
"check:exports": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css",
|
|
163
|
-
"test:grid-contract": "node scripts/check-grid-contract.mjs"
|
|
164
182
|
}
|
|
165
|
-
}
|
|
183
|
+
}
|