@comitor/ui 1.11.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +35 -0
- package/README.md +23 -7
- package/dist/components/ui/action-bar-constants.d.ts +31 -0
- package/dist/components/ui/action-bar-constants.js +9 -0
- package/dist/components/ui/action-bar-constants.js.map +1 -0
- package/dist/components/ui/action-bar.d.ts +67 -0
- package/dist/components/ui/action-bar.js +522 -0
- package/dist/components/ui/action-bar.js.map +1 -0
- package/dist/components/ui/badge-overflow.d.ts +30 -0
- package/dist/components/ui/badge-overflow.js +179 -0
- package/dist/components/ui/badge-overflow.js.map +1 -0
- package/dist/components/ui/banner.d.ts +79 -0
- package/dist/components/ui/banner.js +518 -0
- package/dist/components/ui/banner.js.map +1 -0
- package/dist/components/ui/circular-progress.d.ts +50 -0
- package/dist/components/ui/circular-progress.js +266 -0
- package/dist/components/ui/circular-progress.js.map +1 -0
- package/dist/components/ui/cropper-constants.d.ts +34 -0
- package/dist/components/ui/cropper-constants.js +10 -0
- package/dist/components/ui/cropper-constants.js.map +1 -0
- package/dist/components/ui/cropper.d.ts +106 -0
- package/dist/components/ui/cropper.js +1269 -0
- package/dist/components/ui/cropper.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +1 -1
- package/dist/components/ui/drawer.js +2 -2
- package/dist/components/ui/drawer.js.map +1 -1
- package/dist/components/ui/kanban-constants.d.ts +61 -0
- package/dist/components/ui/kanban-constants.js +21 -0
- package/dist/components/ui/kanban-constants.js.map +1 -0
- package/dist/components/ui/kanban.d.ts +72 -0
- package/dist/components/ui/kanban.js +787 -0
- package/dist/components/ui/kanban.js.map +1 -0
- package/dist/components/ui/key-value-constants.d.ts +33 -0
- package/dist/components/ui/key-value-constants.js +11 -0
- package/dist/components/ui/key-value-constants.js.map +1 -0
- package/dist/components/ui/key-value.d.ts +96 -0
- package/dist/components/ui/key-value.js +641 -0
- package/dist/components/ui/key-value.js.map +1 -0
- package/dist/components/ui/mask-input-constants.d.ts +99 -0
- package/dist/components/ui/mask-input-constants.js +601 -0
- package/dist/components/ui/mask-input-constants.js.map +1 -0
- package/dist/components/ui/mask-input.d.ts +36 -0
- package/dist/components/ui/mask-input.js +558 -0
- package/dist/components/ui/mask-input.js.map +1 -0
- package/dist/components/ui/mention.d.ts +31 -0
- package/dist/components/ui/mention.js +128 -0
- package/dist/components/ui/mention.js.map +1 -0
- package/dist/components/ui/phone-input-constants.d.ts +54 -0
- package/dist/components/ui/phone-input-constants.js +9 -0
- package/dist/components/ui/phone-input-constants.js.map +1 -0
- package/dist/components/ui/phone-input.d.ts +85 -0
- package/dist/components/ui/phone-input.js +743 -0
- package/dist/components/ui/phone-input.js.map +1 -0
- package/dist/components/ui/rating.d.ts +56 -0
- package/dist/components/ui/rating.js +646 -0
- package/dist/components/ui/rating.js.map +1 -0
- package/dist/components/ui/responsive-dialog.d.ts +35 -0
- package/dist/components/ui/responsive-dialog.js +193 -0
- package/dist/components/ui/responsive-dialog.js.map +1 -0
- package/dist/components/ui/scroll-spy.d.ts +42 -0
- package/dist/components/ui/scroll-spy.js +334 -0
- package/dist/components/ui/scroll-spy.js.map +1 -0
- package/dist/components/ui/stepper-constants.d.ts +29 -0
- package/dist/components/ui/stepper-constants.js +9 -0
- package/dist/components/ui/stepper-constants.js.map +1 -0
- package/dist/components/ui/stepper.d.ts +80 -0
- package/dist/components/ui/stepper.js +902 -0
- package/dist/components/ui/stepper.js.map +1 -0
- package/dist/components/ui/tags-input.d.ts +41 -0
- package/dist/components/ui/tags-input.js +127 -0
- package/dist/components/ui/tags-input.js.map +1 -0
- package/dist/components/ui/time-picker-constants.d.ts +48 -0
- package/dist/components/ui/time-picker-constants.js +14 -0
- package/dist/components/ui/time-picker-constants.js.map +1 -0
- package/dist/components/ui/time-picker.d.ts +115 -0
- package/dist/components/ui/time-picker.js +1620 -0
- package/dist/components/ui/time-picker.js.map +1 -0
- package/dist/components/ui/timeline.d.ts +32 -0
- package/dist/components/ui/timeline.js +559 -0
- package/dist/components/ui/timeline.js.map +1 -0
- package/dist/components/ui/tour-constants.d.ts +39 -0
- package/dist/components/ui/tour-constants.js +12 -0
- package/dist/components/ui/tour-constants.js.map +1 -0
- package/dist/components/ui/tour.d.ts +124 -0
- package/dist/components/ui/tour.js +1207 -0
- package/dist/components/ui/tour.js.map +1 -0
- package/dist/data-grid/data-grid-cell-variants.js +10 -6
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
- package/dist/data-grid/data-grid-cell-wrapper.js +1 -1
- package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -1
- package/dist/data-grid/data-grid-column-header.js +4 -2
- package/dist/data-grid/data-grid-column-header.js.map +1 -1
- package/dist/data-grid/data-grid-context-menu.js +5 -4
- package/dist/data-grid/data-grid-context-menu.js.map +1 -1
- package/dist/data-grid/data-grid-filter-menu.d.ts +12 -1
- package/dist/data-grid/data-grid-filter-menu.js +28 -17
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +12 -1
- package/dist/data-grid/data-grid-keyboard-shortcuts.js +7 -5
- package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
- 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.js +3 -2
- package/dist/data-grid/data-grid-paste-dialog.js.map +1 -1
- package/dist/data-grid/data-grid-row-height-menu.d.ts +11 -1
- package/dist/data-grid/data-grid-row-height-menu.js +25 -28
- package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
- package/dist/data-grid/data-grid-row.js +1 -1
- package/dist/data-grid/data-grid-row.js.map +1 -1
- package/dist/data-grid/data-grid-search.js +6 -5
- package/dist/data-grid/data-grid-search.js.map +1 -1
- package/dist/data-grid/data-grid-select-column.js +3 -1
- package/dist/data-grid/data-grid-select-column.js.map +1 -1
- package/dist/data-grid/data-grid-sort-menu.d.ts +12 -1
- package/dist/data-grid/data-grid-sort-menu.js +25 -13
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
- package/dist/data-grid/data-grid-view-menu.d.ts +12 -1
- package/dist/data-grid/data-grid-view-menu.js +12 -4
- package/dist/data-grid/data-grid-view-menu.js.map +1 -1
- package/dist/data-grid/data-grid.d.ts +14 -2
- package/dist/data-grid/data-grid.js +7 -4
- package/dist/data-grid/data-grid.js.map +1 -1
- package/dist/data-grid/filters.d.ts +17 -21
- package/dist/data-grid/filters.js +73 -52
- package/dist/data-grid/filters.js.map +1 -1
- package/dist/data-grid/index.d.ts +4 -1
- package/dist/data-grid/index.js +20 -2
- package/dist/data-grid/index.js.map +1 -1
- 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 +549 -262
- package/dist/data-grid/messages.js +16 -275
- package/dist/data-grid/messages.js.map +1 -1
- package/dist/data-grid/sortable.js +1 -1
- package/dist/data-grid/sortable.js.map +1 -1
- package/dist/data-grid/use-data-grid-undo-redo.d.ts +13 -1
- package/dist/data-grid/use-data-grid-undo-redo.js +13 -10
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
- package/dist/data-grid/use-data-grid.d.ts +281 -1
- package/dist/data-grid/use-data-grid.js +24 -19
- package/dist/data-grid/use-data-grid.js.map +1 -1
- package/dist/data-grid/utils.d.ts +9 -1
- package/dist/data-grid/utils.js +3 -2
- package/dist/data-grid/utils.js.map +1 -1
- package/dist/index.d.ts +31 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/compose-refs.js.map +1 -0
- package/dist/lib/use-as-ref.js.map +1 -0
- package/dist/lib/use-is-mobile.d.ts +10 -0
- package/dist/lib/use-is-mobile.js +21 -0
- package/dist/lib/use-is-mobile.js.map +1 -0
- package/dist/lib/use-isomorphic-layout-effect.js.map +1 -0
- package/dist/lib/use-lazy-ref.js.map +1 -0
- package/dist/lib/visually-hidden-input.d.ts +12 -0
- package/dist/lib/visually-hidden-input.js +105 -0
- package/dist/lib/visually-hidden-input.js.map +1 -0
- package/package.json +5 -1
- package/styles.css +19 -0
- package/dist/data-grid/compose-refs.js.map +0 -1
- package/dist/data-grid/use-as-ref.js.map +0 -1
- package/dist/data-grid/use-isomorphic-layout-effect.js.map +0 -1
- package/dist/data-grid/use-lazy-ref.js.map +0 -1
- /package/dist/{data-grid → lib}/compose-refs.d.ts +0 -0
- /package/dist/{data-grid → lib}/compose-refs.js +0 -0
- /package/dist/{data-grid → lib}/use-as-ref.d.ts +0 -0
- /package/dist/{data-grid → lib}/use-as-ref.js +0 -0
- /package/dist/{data-grid → lib}/use-isomorphic-layout-effect.d.ts +0 -0
- /package/dist/{data-grid → lib}/use-isomorphic-layout-effect.js +0 -0
- /package/dist/{data-grid → lib}/use-lazy-ref.d.ts +0 -0
- /package/dist/{data-grid → lib}/use-lazy-ref.js +0 -0
|
@@ -1,279 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
},
|
|
7
|
-
search: {
|
|
8
|
-
placeholder: "T\xECm trong b\u1EA3ng...",
|
|
9
|
-
label: "T\xECm trong b\u1EA3ng",
|
|
10
|
-
prevMatch: "K\u1EBFt qu\u1EA3 tr\u01B0\u1EDBc",
|
|
11
|
-
nextMatch: "K\u1EBFt qu\u1EA3 sau",
|
|
12
|
-
close: "\u0110\xF3ng t\xECm ki\u1EBFm",
|
|
13
|
-
matchPosition: (index, total) => `${index} / ${total}`,
|
|
14
|
-
noResults: "Kh\xF4ng c\xF3 k\u1EBFt qu\u1EA3",
|
|
15
|
-
typeToSearch: "G\xF5 \u0111\u1EC3 t\xECm"
|
|
16
|
-
},
|
|
17
|
-
column: {
|
|
18
|
-
sortAsc: "S\u1EAFp x\u1EBFp t\u0103ng d\u1EA7n",
|
|
19
|
-
sortDesc: "S\u1EAFp x\u1EBFp gi\u1EA3m d\u1EA7n",
|
|
20
|
-
removeSort: "B\u1ECF s\u1EAFp x\u1EBFp",
|
|
21
|
-
pinLeft: "Ghim sang tr\xE1i",
|
|
22
|
-
unpinLeft: "B\u1ECF ghim tr\xE1i",
|
|
23
|
-
pinRight: "Ghim sang ph\u1EA3i",
|
|
24
|
-
unpinRight: "B\u1ECF ghim ph\u1EA3i",
|
|
25
|
-
hide: "\u1EA8n c\u1ED9t",
|
|
26
|
-
resize: (label) => `\u0110\u1ED5i \u0111\u1ED9 r\u1ED9ng c\u1ED9t ${label}`,
|
|
27
|
-
/** Tên kiểu dữ liệu của cột, hiện trong tooltip ở tiêu đề cột */
|
|
28
|
-
variant: {
|
|
29
|
-
shortText: "V\u0103n b\u1EA3n ng\u1EAFn",
|
|
30
|
-
longText: "V\u0103n b\u1EA3n d\xE0i",
|
|
31
|
-
number: "S\u1ED1",
|
|
32
|
-
url: "Li\xEAn k\u1EBFt",
|
|
33
|
-
checkbox: "\xD4 \u0111\xE1nh d\u1EA5u",
|
|
34
|
-
select: "Ch\u1ECDn m\u1ED9t",
|
|
35
|
-
multiSelect: "Ch\u1ECDn nhi\u1EC1u",
|
|
36
|
-
date: "Ng\xE0y",
|
|
37
|
-
file: "T\u1EC7p"
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
select: {
|
|
41
|
-
all: "Ch\u1ECDn t\u1EA5t c\u1EA3",
|
|
42
|
-
row: "Ch\u1ECDn d\xF2ng",
|
|
43
|
-
rowNumber: (rowNumber) => `Ch\u1ECDn d\xF2ng ${rowNumber}`
|
|
44
|
-
},
|
|
45
|
-
contextMenu: {
|
|
46
|
-
copy: "Sao ch\xE9p",
|
|
47
|
-
cut: "C\u1EAFt",
|
|
48
|
-
clear: "Xo\xE1 n\u1ED9i dung",
|
|
49
|
-
deleteRows: "Xo\xE1 d\xF2ng"
|
|
50
|
-
},
|
|
51
|
-
pasteDialog: {
|
|
52
|
-
title: "Th\xEAm d\xF2ng \u0111\u1EC3 d\xE1n h\u1EBFt d\u1EEF li\u1EC7u?",
|
|
53
|
-
description: (rowsNeeded) => `C\u1EA7n th\xEAm ${rowsNeeded} d\xF2ng n\u1EEFa \u0111\u1EC3 d\xE1n h\u1EBFt n\u1ED9i dung \u0111ang c\xF3 trong clipboard.`,
|
|
54
|
-
expandTitle: "T\u1EA1o d\xF2ng m\u1EDBi",
|
|
55
|
-
expandDescription: (rowsNeeded) => `Th\xEAm ${rowsNeeded} d\xF2ng v\xE0o b\u1EA3ng r\u1ED3i d\xE1n to\xE0n b\u1ED9 d\u1EEF li\u1EC7u`,
|
|
56
|
-
keepTitle: "Gi\u1EEF nguy\xEAn s\u1ED1 d\xF2ng",
|
|
57
|
-
keepDescription: "Ch\u1EC9 d\xE1n ph\u1EA7n v\u1EEBa v\u1EDBi c\xE1c d\xF2ng hi\u1EC7n c\xF3",
|
|
58
|
-
cancel: "Hu\u1EF7",
|
|
59
|
-
confirm: "Ti\u1EBFp t\u1EE5c"
|
|
60
|
-
},
|
|
61
|
-
rowHeight: {
|
|
62
|
-
label: "Chi\u1EC1u cao d\xF2ng",
|
|
63
|
-
short: "Th\u1EA5p",
|
|
64
|
-
medium: "V\u1EEBa",
|
|
65
|
-
tall: "Cao",
|
|
66
|
-
extraTall: "R\u1EA5t cao"
|
|
67
|
-
},
|
|
68
|
-
view: {
|
|
69
|
-
trigger: "Hi\u1EC3n th\u1ECB",
|
|
70
|
-
toggleColumns: "\u1EA8n/hi\u1EC7n c\u1ED9t",
|
|
71
|
-
searchPlaceholder: "T\xECm c\u1ED9t...",
|
|
72
|
-
empty: "Kh\xF4ng c\xF3 c\u1ED9t ph\xF9 h\u1EE3p."
|
|
73
|
-
},
|
|
74
|
-
sort: {
|
|
75
|
-
trigger: "S\u1EAFp x\u1EBFp",
|
|
76
|
-
title: "S\u1EAFp x\u1EBFp theo",
|
|
77
|
-
emptyTitle: "Ch\u01B0a s\u1EAFp x\u1EBFp",
|
|
78
|
-
description: "\u0110\u1ED5i ti\xEAu ch\xED s\u1EAFp x\u1EBFp cho danh s\xE1ch.",
|
|
79
|
-
emptyDescription: "Th\xEAm ti\xEAu ch\xED \u0111\u1EC3 s\u1EAFp x\u1EBFp danh s\xE1ch.",
|
|
80
|
-
add: "Th\xEAm s\u1EAFp x\u1EBFp",
|
|
81
|
-
reset: "B\u1ECF s\u1EAFp x\u1EBFp",
|
|
82
|
-
remove: "Xo\xE1 ti\xEAu ch\xED",
|
|
83
|
-
drag: "K\xE9o \u0111\u1EC3 \u0111\u1ED5i th\u1EE9 t\u1EF1",
|
|
84
|
-
fieldPlaceholder: "T\xECm tr\u01B0\u1EDDng...",
|
|
85
|
-
fieldEmpty: "Kh\xF4ng c\xF3 tr\u01B0\u1EDDng ph\xF9 h\u1EE3p.",
|
|
86
|
-
asc: "T\u0103ng d\u1EA7n",
|
|
87
|
-
desc: "Gi\u1EA3m d\u1EA7n"
|
|
88
|
-
},
|
|
89
|
-
filter: {
|
|
90
|
-
trigger: "L\u1ECDc",
|
|
91
|
-
title: "L\u1ECDc theo",
|
|
92
|
-
emptyTitle: "Ch\u01B0a c\xF3 b\u1ED9 l\u1ECDc",
|
|
93
|
-
description: "\u0110\u1ED5i \u0111i\u1EC1u ki\u1EC7n l\u1ECDc \u0111\u1EC3 thu h\u1EB9p d\u1EEF li\u1EC7u.",
|
|
94
|
-
emptyDescription: "Th\xEAm \u0111i\u1EC1u ki\u1EC7n l\u1ECDc \u0111\u1EC3 thu h\u1EB9p d\u1EEF li\u1EC7u.",
|
|
95
|
-
add: "Th\xEAm b\u1ED9 l\u1ECDc",
|
|
96
|
-
reset: "Xo\xE1 b\u1ED9 l\u1ECDc",
|
|
97
|
-
remove: "Xo\xE1 \u0111i\u1EC1u ki\u1EC7n",
|
|
98
|
-
drag: "K\xE9o \u0111\u1EC3 \u0111\u1ED5i th\u1EE9 t\u1EF1",
|
|
99
|
-
where: "Khi",
|
|
100
|
-
and: "V\xE0",
|
|
101
|
-
fieldPlaceholder: "T\xECm tr\u01B0\u1EDDng...",
|
|
102
|
-
fieldEmpty: "Kh\xF4ng c\xF3 tr\u01B0\u1EDDng ph\xF9 h\u1EE3p.",
|
|
103
|
-
valuePlaceholder: "Gi\xE1 tr\u1ECB",
|
|
104
|
-
rangeStart: "T\u1EEB",
|
|
105
|
-
rangeEnd: "\u0110\u1EBFn",
|
|
106
|
-
pickDate: "Ch\u1ECDn ng\xE0y",
|
|
107
|
-
pickRange: "Ch\u1ECDn kho\u1EA3ng ng\xE0y",
|
|
108
|
-
optionPlaceholder: "T\xECm l\u1EF1a ch\u1ECDn...",
|
|
109
|
-
optionEmpty: "Kh\xF4ng c\xF3 l\u1EF1a ch\u1ECDn ph\xF9 h\u1EE3p.",
|
|
110
|
-
selectedCount: (count) => `\u0110\xE3 ch\u1ECDn ${count}`,
|
|
111
|
-
emptyValue: (label) => `B\u1ED9 l\u1ECDc ${label} ch\u01B0a c\u1EA7n gi\xE1 tr\u1ECB`,
|
|
112
|
-
/** Nhãn toán tử lọc — xem `filters.ts` để biết toán tử nào dùng cho kiểu ô nào */
|
|
113
|
-
operators: {
|
|
114
|
-
contains: "Ch\u1EE9a",
|
|
115
|
-
notContains: "Kh\xF4ng ch\u1EE9a",
|
|
116
|
-
equals: "B\u1EB1ng",
|
|
117
|
-
notEquals: "Kh\xE1c",
|
|
118
|
-
startsWith: "B\u1EAFt \u0111\u1EA7u b\u1EB1ng",
|
|
119
|
-
endsWith: "K\u1EBFt th\xFAc b\u1EB1ng",
|
|
120
|
-
isEmpty: "\u0110ang tr\u1ED1ng",
|
|
121
|
-
isNotEmpty: "Kh\xF4ng tr\u1ED1ng",
|
|
122
|
-
lessThan: "Nh\u1ECF h\u01A1n",
|
|
123
|
-
lessThanOrEqual: "Nh\u1ECF h\u01A1n ho\u1EB7c b\u1EB1ng",
|
|
124
|
-
greaterThan: "L\u1EDBn h\u01A1n",
|
|
125
|
-
greaterThanOrEqual: "L\u1EDBn h\u01A1n ho\u1EB7c b\u1EB1ng",
|
|
126
|
-
isBetween: "Trong kho\u1EA3ng",
|
|
127
|
-
dateEquals: "\u0110\xFAng ng\xE0y",
|
|
128
|
-
dateNotEquals: "Kh\xE1c ng\xE0y",
|
|
129
|
-
before: "Tr\u01B0\u1EDBc ng\xE0y",
|
|
130
|
-
after: "Sau ng\xE0y",
|
|
131
|
-
onOrBefore: "V\xE0o ho\u1EB7c tr\u01B0\u1EDBc ng\xE0y",
|
|
132
|
-
onOrAfter: "V\xE0o ho\u1EB7c sau ng\xE0y",
|
|
133
|
-
is: "L\xE0",
|
|
134
|
-
isNot: "Kh\xF4ng l\xE0",
|
|
135
|
-
isAnyOf: "L\xE0 m\u1ED9t trong",
|
|
136
|
-
isNoneOf: "Kh\xF4ng l\xE0 b\u1EA5t k\u1EF3",
|
|
137
|
-
isTrue: "C\xF3 \u0111\xE1nh d\u1EA5u",
|
|
138
|
-
isFalse: "Kh\xF4ng \u0111\xE1nh d\u1EA5u"
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
cell: {
|
|
142
|
-
longTextPlaceholder: "Nh\u1EADp n\u1ED9i dung...",
|
|
143
|
-
optionSearchPlaceholder: "T\xECm...",
|
|
144
|
-
optionEmpty: "Kh\xF4ng c\xF3 l\u1EF1a ch\u1ECDn ph\xF9 h\u1EE3p.",
|
|
145
|
-
clearAll: "B\u1ECF ch\u1ECDn h\u1EBFt",
|
|
146
|
-
invalidUrlTitle: "Li\xEAn k\u1EBFt kh\xF4ng h\u1EE3p l\u1EC7",
|
|
147
|
-
invalidUrlDescription: "Li\xEAn k\u1EBFt ch\u1EE9a giao th\u1EE9c nguy hi\u1EC3m (javascript:, data:, vbscript: ho\u1EB7c file:)"
|
|
148
|
-
},
|
|
149
|
-
file: {
|
|
150
|
-
uploadLabel: "T\u1EA3i t\u1EC7p l\xEAn",
|
|
151
|
-
dropHere: "Th\u1EA3 t\u1EC7p v\xE0o \u0111\xE2y",
|
|
152
|
-
dragHere: "K\xE9o t\u1EC7p v\xE0o \u0111\xE2y",
|
|
153
|
-
browse: "ho\u1EB7c b\u1EA5m \u0111\u1EC3 ch\u1ECDn t\u1EC7p",
|
|
154
|
-
limits: (maxSize, maxFiles) => {
|
|
155
|
-
if (maxSize && maxFiles) return `T\u1ED1i \u0111a ${maxSize} \u2022 T\u1ED1i \u0111a ${maxFiles} t\u1EC7p`;
|
|
156
|
-
if (maxSize) return `T\u1ED1i \u0111a ${maxSize}`;
|
|
157
|
-
if (maxFiles) return `T\u1ED1i \u0111a ${maxFiles} t\u1EC7p`;
|
|
158
|
-
return "Ch\u1ECDn t\u1EC7p \u0111\u1EC3 t\u1EA3i l\xEAn";
|
|
159
|
-
},
|
|
160
|
-
count: (count) => `${count} t\u1EC7p`,
|
|
161
|
-
clearAll: "Xo\xE1 h\u1EBFt",
|
|
162
|
-
remove: "Xo\xE1 t\u1EC7p",
|
|
163
|
-
uploading: "\u0110ang t\u1EA3i l\xEAn...",
|
|
164
|
-
deleting: "\u0110ang xo\xE1...",
|
|
165
|
-
tooMany: (maxFiles) => `Ch\u1EC9 cho ph\xE9p t\u1ED1i \u0111a ${maxFiles} t\u1EC7p`,
|
|
166
|
-
tooLarge: (maxSize) => `T\u1EC7p v\u01B0\u1EE3t qu\xE1 ${maxSize}`,
|
|
167
|
-
wrongType: "Kh\xF4ng ch\u1EA5p nh\u1EADn \u0111\u1ECBnh d\u1EA1ng t\u1EC7p n\xE0y",
|
|
168
|
-
rejectedOne: (name) => `\u0110\xE3 b\u1ECF qua "${name}"`,
|
|
169
|
-
rejectedMany: (name, others) => `\u0110\xE3 b\u1ECF qua "${name}" v\xE0 ${others} t\u1EC7p kh\xE1c`,
|
|
170
|
-
uploadFailed: (count) => `Kh\xF4ng t\u1EA3i l\xEAn \u0111\u01B0\u1EE3c ${count} t\u1EC7p`,
|
|
171
|
-
deleteFailed: (name) => `Kh\xF4ng xo\xE1 \u0111\u01B0\u1EE3c ${name}`,
|
|
172
|
-
deleteFailedMany: "Kh\xF4ng xo\xE1 \u0111\u01B0\u1EE3c t\u1EC7p"
|
|
173
|
-
},
|
|
174
|
-
toast: {
|
|
175
|
-
cellsCopied: (count) => `\u0110\xE3 sao ch\xE9p ${count} \xF4`,
|
|
176
|
-
copyFailed: "Kh\xF4ng sao ch\xE9p \u0111\u01B0\u1EE3c v\xE0o clipboard",
|
|
177
|
-
cellsCut: (count) => `\u0110\xE3 c\u1EAFt ${count} \xF4`,
|
|
178
|
-
cutFailed: "Kh\xF4ng c\u1EAFt \u0111\u01B0\u1EE3c v\xE0o clipboard",
|
|
179
|
-
cellsPasted: (count) => `\u0110\xE3 d\xE1n ${count} \xF4`,
|
|
180
|
-
cellsPastedWithSkipped: (count, skipped) => `\u0110\xE3 d\xE1n ${count} \xF4, b\u1ECF qua ${skipped} \xF4`,
|
|
181
|
-
pasteSkipped: (skipped) => `B\u1ECF qua ${skipped} \xF4 do d\u1EEF li\u1EC7u kh\xF4ng h\u1EE3p l\u1EC7`,
|
|
182
|
-
pasteFailed: "Kh\xF4ng d\xE1n \u0111\u01B0\u1EE3c. Vui l\xF2ng th\u1EED l\u1EA1i.",
|
|
183
|
-
cellsCleared: (count) => `\u0110\xE3 xo\xE1 n\u1ED9i dung ${count} \xF4`,
|
|
184
|
-
rowsDeleted: (count) => `\u0110\xE3 xo\xE1 ${count} d\xF2ng`,
|
|
185
|
-
nothingToUndo: "Kh\xF4ng c\xF2n thao t\xE1c \u0111\u1EC3 ho\xE0n t\xE1c",
|
|
186
|
-
nothingToRedo: "Kh\xF4ng c\xF2n thao t\xE1c \u0111\u1EC3 l\xE0m l\u1EA1i",
|
|
187
|
-
undone: (count) => `\u0110\xE3 ho\xE0n t\xE1c ${count} thao t\xE1c`,
|
|
188
|
-
redone: (count) => `\u0110\xE3 l\xE0m l\u1EA1i ${count} thao t\xE1c`
|
|
189
|
-
},
|
|
190
|
-
/** Giá trị văn bản khi dán boolean vào ô văn bản */
|
|
191
|
-
booleanText: {
|
|
192
|
-
checked: "C\xF3",
|
|
193
|
-
unchecked: "Kh\xF4ng"
|
|
194
|
-
},
|
|
195
|
-
shortcuts: {
|
|
196
|
-
trigger: "Ph\xEDm t\u1EAFt",
|
|
197
|
-
title: "Ph\xEDm t\u1EAFt",
|
|
198
|
-
description: "Danh s\xE1ch ph\xEDm t\u1EAFt \u0111\u1EC3 thao t\xE1c nhanh v\u1EDBi b\u1EA3ng d\u1EEF li\u1EC7u.",
|
|
199
|
-
searchPlaceholder: "T\xECm ph\xEDm t\u1EAFt...",
|
|
200
|
-
emptyTitle: "Kh\xF4ng t\xECm th\u1EA5y ph\xEDm t\u1EAFt",
|
|
201
|
-
emptyDescription: "Th\u1EED t\xECm v\u1EDBi t\u1EEB kho\xE1 kh\xE1c.",
|
|
202
|
-
close: "\u0110\xF3ng",
|
|
203
|
-
groups: {
|
|
204
|
-
navigation: "Di chuy\u1EC3n",
|
|
205
|
-
selection: "Ch\u1ECDn \xF4",
|
|
206
|
-
editing: "S\u1EEDa d\u1EEF li\u1EC7u",
|
|
207
|
-
search: "T\xECm ki\u1EBFm",
|
|
208
|
-
filtering: "L\u1ECDc",
|
|
209
|
-
sorting: "S\u1EAFp x\u1EBFp",
|
|
210
|
-
general: "Chung"
|
|
211
|
-
},
|
|
212
|
-
keys: {
|
|
213
|
-
click: "Nh\u1EA5p chu\u1ED9t",
|
|
214
|
-
doubleClick: "Nh\u1EA5p \u0111\xFAp"
|
|
215
|
-
},
|
|
216
|
-
navigation: {
|
|
217
|
-
move: "Di chuy\u1EC3n gi\u1EEFa c\xE1c \xF4",
|
|
218
|
-
nextCell: "Sang \xF4 k\u1EBF ti\u1EBFp",
|
|
219
|
-
prevCell: "V\u1EC1 \xF4 tr\u01B0\u1EDBc \u0111\xF3",
|
|
220
|
-
firstColumn: "V\u1EC1 c\u1ED9t \u0111\u1EA7u",
|
|
221
|
-
lastColumn: "T\u1EDBi c\u1ED9t cu\u1ED1i",
|
|
222
|
-
firstRowSameColumn: "V\u1EC1 d\xF2ng \u0111\u1EA7u (c\xF9ng c\u1ED9t)",
|
|
223
|
-
lastRowSameColumn: "T\u1EDBi d\xF2ng cu\u1ED1i (c\xF9ng c\u1ED9t)",
|
|
224
|
-
firstColumnSameRow: "V\u1EC1 c\u1ED9t \u0111\u1EA7u (c\xF9ng d\xF2ng)",
|
|
225
|
-
lastColumnSameRow: "T\u1EDBi c\u1ED9t cu\u1ED1i (c\xF9ng d\xF2ng)",
|
|
226
|
-
firstCell: "V\u1EC1 \xF4 \u0111\u1EA7u b\u1EA3ng",
|
|
227
|
-
lastCell: "T\u1EDBi \xF4 cu\u1ED1i b\u1EA3ng",
|
|
228
|
-
pageUp: "L\xEAn m\u1ED9t trang",
|
|
229
|
-
pageDown: "Xu\u1ED1ng m\u1ED9t trang",
|
|
230
|
-
scrollUp: "Cu\u1ED9n l\xEAn m\u1ED9t trang",
|
|
231
|
-
scrollDown: "Cu\u1ED9n xu\u1ED1ng m\u1ED9t trang",
|
|
232
|
-
scrollLeft: "Cu\u1ED9n sang tr\xE1i m\u1ED9t trang c\u1ED9t",
|
|
233
|
-
scrollRight: "Cu\u1ED9n sang ph\u1EA3i m\u1ED9t trang c\u1ED9t"
|
|
234
|
-
},
|
|
235
|
-
selection: {
|
|
236
|
-
extend: "M\u1EDF r\u1ED9ng v\xF9ng ch\u1ECDn",
|
|
237
|
-
toTop: "Ch\u1ECDn t\u1EDBi \u0111\u1EA7u b\u1EA3ng",
|
|
238
|
-
toBottom: "Ch\u1ECDn t\u1EDBi cu\u1ED1i b\u1EA3ng",
|
|
239
|
-
toFirstColumn: "Ch\u1ECDn t\u1EDBi c\u1ED9t \u0111\u1EA7u",
|
|
240
|
-
toLastColumn: "Ch\u1ECDn t\u1EDBi c\u1ED9t cu\u1ED1i",
|
|
241
|
-
all: "Ch\u1ECDn to\xE0n b\u1ED9 \xF4",
|
|
242
|
-
toggle: "Th\xEAm/b\u1EDBt m\u1ED9t \xF4 kh\u1ECFi v\xF9ng ch\u1ECDn",
|
|
243
|
-
range: "Ch\u1ECDn c\u1EA3 v\xF9ng",
|
|
244
|
-
clear: "B\u1ECF ch\u1ECDn"
|
|
245
|
-
},
|
|
246
|
-
editing: {
|
|
247
|
-
start: "B\u1EAFt \u0111\u1EA7u s\u1EEDa \xF4",
|
|
248
|
-
insertRow: "Ch\xE8n d\xF2ng b\xEAn d\u01B0\u1EDBi",
|
|
249
|
-
copy: "Sao ch\xE9p \xF4 \u0111ang ch\u1ECDn",
|
|
250
|
-
cut: "C\u1EAFt \xF4 \u0111ang ch\u1ECDn",
|
|
251
|
-
paste: "D\xE1n v\xE0o \xF4",
|
|
252
|
-
clear: "Xo\xE1 n\u1ED9i dung \xF4 \u0111ang ch\u1ECDn",
|
|
253
|
-
deleteRows: "Xo\xE1 d\xF2ng \u0111ang ch\u1ECDn",
|
|
254
|
-
undo: "Ho\xE0n t\xE1c",
|
|
255
|
-
redo: "L\xE0m l\u1EA1i"
|
|
256
|
-
},
|
|
257
|
-
search: {
|
|
258
|
-
open: "M\u1EDF \xF4 t\xECm ki\u1EBFm",
|
|
259
|
-
next: "K\u1EBFt qu\u1EA3 k\u1EBF ti\u1EBFp",
|
|
260
|
-
prev: "K\u1EBFt qu\u1EA3 tr\u01B0\u1EDBc \u0111\xF3",
|
|
261
|
-
close: "\u0110\xF3ng t\xECm ki\u1EBFm"
|
|
262
|
-
},
|
|
263
|
-
filtering: {
|
|
264
|
-
toggle: "M\u1EDF/\u0111\xF3ng menu l\u1ECDc",
|
|
265
|
-
remove: "Xo\xE1 \u0111i\u1EC1u ki\u1EC7n l\u1ECDc (khi \u0111ang ch\u1ECDn)"
|
|
266
|
-
},
|
|
267
|
-
sorting: {
|
|
268
|
-
toggle: "M\u1EDF/\u0111\xF3ng menu s\u1EAFp x\u1EBFp",
|
|
269
|
-
remove: "Xo\xE1 ti\xEAu ch\xED s\u1EAFp x\u1EBFp (khi \u0111ang ch\u1ECDn)"
|
|
270
|
-
},
|
|
271
|
-
general: {
|
|
272
|
-
shortcuts: "Xem danh s\xE1ch ph\xEDm t\u1EAFt"
|
|
273
|
-
}
|
|
274
|
-
}
|
|
1
|
+
import { messagesEn } from "./messages-en.js";
|
|
2
|
+
import { messagesVi } from "./messages-vi.js";
|
|
3
|
+
const DATA_GRID_MESSAGES = {
|
|
4
|
+
en: messagesEn,
|
|
5
|
+
vi: messagesVi
|
|
275
6
|
};
|
|
7
|
+
const DEFAULT_DATA_GRID_LOCALE = "en";
|
|
8
|
+
function getDataGridMessages(locale) {
|
|
9
|
+
if (!locale) return DATA_GRID_MESSAGES[DEFAULT_DATA_GRID_LOCALE];
|
|
10
|
+
if (typeof locale === "string") return DATA_GRID_MESSAGES[locale] ?? DATA_GRID_MESSAGES[DEFAULT_DATA_GRID_LOCALE];
|
|
11
|
+
return locale;
|
|
12
|
+
}
|
|
276
13
|
export {
|
|
277
|
-
|
|
14
|
+
DATA_GRID_MESSAGES,
|
|
15
|
+
DEFAULT_DATA_GRID_LOCALE,
|
|
16
|
+
getDataGridMessages,
|
|
17
|
+
messagesEn,
|
|
18
|
+
messagesVi
|
|
278
19
|
};
|
|
279
20
|
//# sourceMappingURL=messages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data-grid/messages.ts"],"sourcesContent":["/**\n * Toàn bộ chuỗi hiển thị của DataGrid (tiếng Việt) — gom một chỗ để dễ rà soát,\n * đổi từ ngữ theo nghiệp vụ, hoặc dịch sang ngôn ngữ khác sau này.\n *\n * Quy ước: chuỗi cố định để nguyên; chuỗi có tham số viết thành hàm.\n * KHÔNG đặt JSX ở đây — chỉ chuỗi thuần.\n */\nexport const msg = {\n grid: {\n /** Nhãn mặc định của vùng `role=\"grid\"` (ghi đè bằng prop `aria-label`) */\n label: \"Bảng dữ liệu\",\n addRow: \"Thêm dòng\"\n },\n\n search: {\n placeholder: \"Tìm trong bảng...\",\n label: \"Tìm trong bảng\",\n prevMatch: \"Kết quả trước\",\n nextMatch: \"Kết quả sau\",\n close: \"Đóng tìm kiếm\",\n matchPosition: (index: number, total: number) => `${index} / ${total}`,\n noResults: \"Không có kết quả\",\n typeToSearch: \"Gõ để tìm\"\n },\n\n column: {\n sortAsc: \"Sắp xếp tăng dần\",\n sortDesc: \"Sắp xếp giảm dần\",\n removeSort: \"Bỏ sắp xếp\",\n pinLeft: \"Ghim sang trái\",\n unpinLeft: \"Bỏ ghim trái\",\n pinRight: \"Ghim sang phải\",\n unpinRight: \"Bỏ ghim phải\",\n hide: \"Ẩn cột\",\n resize: (label: string) => `Đổi độ rộng cột ${label}`,\n /** Tên kiểu dữ liệu của cột, hiện trong tooltip ở tiêu đề cột */\n variant: {\n shortText: \"Văn bản ngắn\",\n longText: \"Văn bản dài\",\n number: \"Số\",\n url: \"Liên kết\",\n checkbox: \"Ô đánh dấu\",\n select: \"Chọn một\",\n multiSelect: \"Chọn nhiều\",\n date: \"Ngày\",\n file: \"Tệp\"\n }\n },\n\n select: {\n all: \"Chọn tất cả\",\n row: \"Chọn dòng\",\n rowNumber: (rowNumber: number) => `Chọn dòng ${rowNumber}`\n },\n\n contextMenu: {\n copy: \"Sao chép\",\n cut: \"Cắt\",\n clear: \"Xoá nội dung\",\n deleteRows: \"Xoá dòng\"\n },\n\n pasteDialog: {\n title: \"Thêm dòng để dán hết dữ liệu?\",\n description: (rowsNeeded: number) => `Cần thêm ${rowsNeeded} dòng nữa để dán hết nội dung đang có trong clipboard.`,\n expandTitle: \"Tạo dòng mới\",\n expandDescription: (rowsNeeded: number) => `Thêm ${rowsNeeded} dòng vào bảng rồi dán toàn bộ dữ liệu`,\n keepTitle: \"Giữ nguyên số dòng\",\n keepDescription: \"Chỉ dán phần vừa với các dòng hiện có\",\n cancel: \"Huỷ\",\n confirm: \"Tiếp tục\"\n },\n\n rowHeight: {\n label: \"Chiều cao dòng\",\n short: \"Thấp\",\n medium: \"Vừa\",\n tall: \"Cao\",\n extraTall: \"Rất cao\"\n },\n\n view: {\n trigger: \"Hiển thị\",\n toggleColumns: \"Ẩn/hiện cột\",\n searchPlaceholder: \"Tìm cột...\",\n empty: \"Không có cột phù hợp.\"\n },\n\n sort: {\n trigger: \"Sắp xếp\",\n title: \"Sắp xếp theo\",\n emptyTitle: \"Chưa sắp xếp\",\n description: \"Đổi tiêu chí sắp xếp cho danh sách.\",\n emptyDescription: \"Thêm tiêu chí để sắp xếp danh sách.\",\n add: \"Thêm sắp xếp\",\n reset: \"Bỏ sắp xếp\",\n remove: \"Xoá tiêu chí\",\n drag: \"Kéo để đổi thứ tự\",\n fieldPlaceholder: \"Tìm trường...\",\n fieldEmpty: \"Không có trường phù hợp.\",\n asc: \"Tăng dần\",\n desc: \"Giảm dần\"\n },\n\n filter: {\n trigger: \"Lọc\",\n title: \"Lọc theo\",\n emptyTitle: \"Chưa có bộ lọc\",\n description: \"Đổi điều kiện lọc để thu hẹp dữ liệu.\",\n emptyDescription: \"Thêm điều kiện lọc để thu hẹp dữ liệu.\",\n add: \"Thêm bộ lọc\",\n reset: \"Xoá bộ lọc\",\n remove: \"Xoá điều kiện\",\n drag: \"Kéo để đổi thứ tự\",\n where: \"Khi\",\n and: \"Và\",\n fieldPlaceholder: \"Tìm trường...\",\n fieldEmpty: \"Không có trường phù hợp.\",\n valuePlaceholder: \"Giá trị\",\n rangeStart: \"Từ\",\n rangeEnd: \"Đến\",\n pickDate: \"Chọn ngày\",\n pickRange: \"Chọn khoảng ngày\",\n optionPlaceholder: \"Tìm lựa chọn...\",\n optionEmpty: \"Không có lựa chọn phù hợp.\",\n selectedCount: (count: number) => `Đã chọn ${count}`,\n emptyValue: (label: string) => `Bộ lọc ${label} chưa cần giá trị`,\n /** Nhãn toán tử lọc — xem `filters.ts` để biết toán tử nào dùng cho kiểu ô nào */\n operators: {\n contains: \"Chứa\",\n notContains: \"Không chứa\",\n equals: \"Bằng\",\n notEquals: \"Khác\",\n startsWith: \"Bắt đầu bằng\",\n endsWith: \"Kết thúc bằng\",\n isEmpty: \"Đang trống\",\n isNotEmpty: \"Không trống\",\n lessThan: \"Nhỏ hơn\",\n lessThanOrEqual: \"Nhỏ hơn hoặc bằng\",\n greaterThan: \"Lớn hơn\",\n greaterThanOrEqual: \"Lớn hơn hoặc bằng\",\n isBetween: \"Trong khoảng\",\n dateEquals: \"Đúng ngày\",\n dateNotEquals: \"Khác ngày\",\n before: \"Trước ngày\",\n after: \"Sau ngày\",\n onOrBefore: \"Vào hoặc trước ngày\",\n onOrAfter: \"Vào hoặc sau ngày\",\n is: \"Là\",\n isNot: \"Không là\",\n isAnyOf: \"Là một trong\",\n isNoneOf: \"Không là bất kỳ\",\n isTrue: \"Có đánh dấu\",\n isFalse: \"Không đánh dấu\"\n }\n },\n\n cell: {\n longTextPlaceholder: \"Nhập nội dung...\",\n optionSearchPlaceholder: \"Tìm...\",\n optionEmpty: \"Không có lựa chọn phù hợp.\",\n clearAll: \"Bỏ chọn hết\",\n invalidUrlTitle: \"Liên kết không hợp lệ\",\n invalidUrlDescription: \"Liên kết chứa giao thức nguy hiểm (javascript:, data:, vbscript: hoặc file:)\"\n },\n\n file: {\n uploadLabel: \"Tải tệp lên\",\n dropHere: \"Thả tệp vào đây\",\n dragHere: \"Kéo tệp vào đây\",\n browse: \"hoặc bấm để chọn tệp\",\n limits: (maxSize?: string, maxFiles?: number) => {\n if (maxSize && maxFiles) return `Tối đa ${maxSize} • Tối đa ${maxFiles} tệp`;\n if (maxSize) return `Tối đa ${maxSize}`;\n if (maxFiles) return `Tối đa ${maxFiles} tệp`;\n return \"Chọn tệp để tải lên\";\n },\n count: (count: number) => `${count} tệp`,\n clearAll: \"Xoá hết\",\n remove: \"Xoá tệp\",\n uploading: \"Đang tải lên...\",\n deleting: \"Đang xoá...\",\n tooMany: (maxFiles: number) => `Chỉ cho phép tối đa ${maxFiles} tệp`,\n tooLarge: (maxSize: string) => `Tệp vượt quá ${maxSize}`,\n wrongType: \"Không chấp nhận định dạng tệp này\",\n rejectedOne: (name: string) => `Đã bỏ qua \"${name}\"`,\n rejectedMany: (name: string, others: number) => `Đã bỏ qua \"${name}\" và ${others} tệp khác`,\n uploadFailed: (count: number) => `Không tải lên được ${count} tệp`,\n deleteFailed: (name: string) => `Không xoá được ${name}`,\n deleteFailedMany: \"Không xoá được tệp\"\n },\n\n toast: {\n cellsCopied: (count: number) => `Đã sao chép ${count} ô`,\n copyFailed: \"Không sao chép được vào clipboard\",\n cellsCut: (count: number) => `Đã cắt ${count} ô`,\n cutFailed: \"Không cắt được vào clipboard\",\n cellsPasted: (count: number) => `Đã dán ${count} ô`,\n cellsPastedWithSkipped: (count: number, skipped: number) => `Đã dán ${count} ô, bỏ qua ${skipped} ô`,\n pasteSkipped: (skipped: number) => `Bỏ qua ${skipped} ô do dữ liệu không hợp lệ`,\n pasteFailed: \"Không dán được. Vui lòng thử lại.\",\n cellsCleared: (count: number) => `Đã xoá nội dung ${count} ô`,\n rowsDeleted: (count: number) => `Đã xoá ${count} dòng`,\n nothingToUndo: \"Không còn thao tác để hoàn tác\",\n nothingToRedo: \"Không còn thao tác để làm lại\",\n undone: (count: number) => `Đã hoàn tác ${count} thao tác`,\n redone: (count: number) => `Đã làm lại ${count} thao tác`\n },\n\n /** Giá trị văn bản khi dán boolean vào ô văn bản */\n booleanText: {\n checked: \"Có\",\n unchecked: \"Không\"\n },\n\n shortcuts: {\n trigger: \"Phím tắt\",\n title: \"Phím tắt\",\n description: \"Danh sách phím tắt để thao tác nhanh với bảng dữ liệu.\",\n searchPlaceholder: \"Tìm phím tắt...\",\n emptyTitle: \"Không tìm thấy phím tắt\",\n emptyDescription: \"Thử tìm với từ khoá khác.\",\n close: \"Đóng\",\n groups: {\n navigation: \"Di chuyển\",\n selection: \"Chọn ô\",\n editing: \"Sửa dữ liệu\",\n search: \"Tìm kiếm\",\n filtering: \"Lọc\",\n sorting: \"Sắp xếp\",\n general: \"Chung\"\n },\n keys: {\n click: \"Nhấp chuột\",\n doubleClick: \"Nhấp đúp\"\n },\n navigation: {\n move: \"Di chuyển giữa các ô\",\n nextCell: \"Sang ô kế tiếp\",\n prevCell: \"Về ô trước đó\",\n firstColumn: \"Về cột đầu\",\n lastColumn: \"Tới cột cuối\",\n firstRowSameColumn: \"Về dòng đầu (cùng cột)\",\n lastRowSameColumn: \"Tới dòng cuối (cùng cột)\",\n firstColumnSameRow: \"Về cột đầu (cùng dòng)\",\n lastColumnSameRow: \"Tới cột cuối (cùng dòng)\",\n firstCell: \"Về ô đầu bảng\",\n lastCell: \"Tới ô cuối bảng\",\n pageUp: \"Lên một trang\",\n pageDown: \"Xuống một trang\",\n scrollUp: \"Cuộn lên một trang\",\n scrollDown: \"Cuộn xuống một trang\",\n scrollLeft: \"Cuộn sang trái một trang cột\",\n scrollRight: \"Cuộn sang phải một trang cột\"\n },\n selection: {\n extend: \"Mở rộng vùng chọn\",\n toTop: \"Chọn tới đầu bảng\",\n toBottom: \"Chọn tới cuối bảng\",\n toFirstColumn: \"Chọn tới cột đầu\",\n toLastColumn: \"Chọn tới cột cuối\",\n all: \"Chọn toàn bộ ô\",\n toggle: \"Thêm/bớt một ô khỏi vùng chọn\",\n range: \"Chọn cả vùng\",\n clear: \"Bỏ chọn\"\n },\n editing: {\n start: \"Bắt đầu sửa ô\",\n insertRow: \"Chèn dòng bên dưới\",\n copy: \"Sao chép ô đang chọn\",\n cut: \"Cắt ô đang chọn\",\n paste: \"Dán vào ô\",\n clear: \"Xoá nội dung ô đang chọn\",\n deleteRows: \"Xoá dòng đang chọn\",\n undo: \"Hoàn tác\",\n redo: \"Làm lại\"\n },\n search: {\n open: \"Mở ô tìm kiếm\",\n next: \"Kết quả kế tiếp\",\n prev: \"Kết quả trước đó\",\n close: \"Đóng tìm kiếm\"\n },\n filtering: {\n toggle: \"Mở/đóng menu lọc\",\n remove: \"Xoá điều kiện lọc (khi đang chọn)\"\n },\n sorting: {\n toggle: \"Mở/đóng menu sắp xếp\",\n remove: \"Xoá tiêu chí sắp xếp (khi đang chọn)\"\n },\n general: {\n shortcuts: \"Xem danh sách phím tắt\"\n }\n }\n} as const;\n\nexport type DataGridMessages = typeof msg;\n"],"mappings":"AAOO,MAAM,MAAM;AAAA,EACjB,MAAM;AAAA;AAAA,IAEJ,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EAEA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,IACP,eAAe,CAAC,OAAe,UAAkB,GAAG,KAAK,MAAM,KAAK;AAAA,IACpE,WAAW;AAAA,IACX,cAAc;AAAA,EAChB;AAAA,EAEA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,QAAQ,CAAC,UAAkB,iDAAmB,KAAK;AAAA;AAAA,IAEnD,SAAS;AAAA,MACP,WAAW;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,WAAW,CAAC,cAAsB,qBAAa,SAAS;AAAA,EAC1D;AAAA,EAEA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,KAAK;AAAA,IACL,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AAAA,EAEA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,aAAa,CAAC,eAAuB,oBAAY,UAAU;AAAA,IAC3D,aAAa;AAAA,IACb,mBAAmB,CAAC,eAAuB,WAAQ,UAAU;AAAA,IAC7D,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAAA,EAEA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,WAAW;AAAA,EACb;AAAA,EAEA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,OAAO;AAAA,EACT;AAAA,EAEA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,eAAe,CAAC,UAAkB,wBAAW,KAAK;AAAA,IAClD,YAAY,CAAC,UAAkB,oBAAU,KAAK;AAAA;AAAA,IAE9C,WAAW;AAAA,MACT,UAAU;AAAA,MACV,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM;AAAA,IACJ,qBAAqB;AAAA,IACrB,yBAAyB;AAAA,IACzB,aAAa;AAAA,IACb,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,uBAAuB;AAAA,EACzB;AAAA,EAEA,MAAM;AAAA,IACJ,aAAa;AAAA,IACb,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ,CAAC,SAAkB,aAAsB;AAC/C,UAAI,WAAW,SAAU,QAAO,oBAAU,OAAO,4BAAa,QAAQ;AACtE,UAAI,QAAS,QAAO,oBAAU,OAAO;AACrC,UAAI,SAAU,QAAO,oBAAU,QAAQ;AACvC,aAAO;AAAA,IACT;AAAA,IACA,OAAO,CAAC,UAAkB,GAAG,KAAK;AAAA,IAClC,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,SAAS,CAAC,aAAqB,yCAAuB,QAAQ;AAAA,IAC9D,UAAU,CAAC,YAAoB,kCAAgB,OAAO;AAAA,IACtD,WAAW;AAAA,IACX,aAAa,CAAC,SAAiB,2BAAc,IAAI;AAAA,IACjD,cAAc,CAAC,MAAc,WAAmB,2BAAc,IAAI,WAAQ,MAAM;AAAA,IAChF,cAAc,CAAC,UAAkB,gDAAsB,KAAK;AAAA,IAC5D,cAAc,CAAC,SAAiB,uCAAkB,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACpB;AAAA,EAEA,OAAO;AAAA,IACL,aAAa,CAAC,UAAkB,0BAAe,KAAK;AAAA,IACpD,YAAY;AAAA,IACZ,UAAU,CAAC,UAAkB,uBAAU,KAAK;AAAA,IAC5C,WAAW;AAAA,IACX,aAAa,CAAC,UAAkB,qBAAU,KAAK;AAAA,IAC/C,wBAAwB,CAAC,OAAe,YAAoB,qBAAU,KAAK,sBAAc,OAAO;AAAA,IAChG,cAAc,CAAC,YAAoB,eAAU,OAAO;AAAA,IACpD,aAAa;AAAA,IACb,cAAc,CAAC,UAAkB,mCAAmB,KAAK;AAAA,IACzD,aAAa,CAAC,UAAkB,qBAAU,KAAK;AAAA,IAC/C,eAAe;AAAA,IACf,eAAe;AAAA,IACf,QAAQ,CAAC,UAAkB,6BAAe,KAAK;AAAA,IAC/C,QAAQ,CAAC,UAAkB,8BAAc,KAAK;AAAA,EAChD;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EAEA,WAAW;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,OAAO;AAAA,IACP,QAAQ;AAAA,MACN,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,IACA,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,MACnB,WAAW;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,aAAa;AAAA,IACf;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,UAAU;AAAA,MACV,eAAe;AAAA,MACf,cAAc;AAAA,MACd,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,IACA,SAAS;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,MAAM;AAAA,MACN,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,SAAS;AAAA,MACP,WAAW;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/messages.ts"],"sourcesContent":["/**\n * Sổ đăng ký ngôn ngữ của DataGrid. Module THUẦN — không directive, không hook — nên Server\n * Component đọc thẳng được (xem `verify:directives`, phép kiểm 2 và 3).\n *\n * Hai ngôn ngữ, và cố ý dừng ở hai: tiếng Anh là bản gốc định nghĩa hình dạng\n * ({@link DataGridMessages}), tiếng Việt là bản dịch đủ. Thêm ngôn ngữ thứ ba thì thêm một file\n * `messages-<mã>.ts` chú thích `: DataGridMessages`, ghi vào `DATA_GRID_MESSAGES` bên dưới, và\n * `DataGridLocale` tự rộng ra theo — không có danh sách thứ hai nào phải nhớ cập nhật.\n *\n * ⚠ Mặc định là **tiếng Anh**, ngược với phần còn lại của gói (README §5). Đây là ngoại lệ có chủ\n * ý của riêng `DataGrid`, chốt ở `2.0.0` — lý do đầy đủ ở đầu `messages-en.ts`.\n */\nimport { type DataGridMessages, messagesEn } from \"./messages-en.js\";\nimport { messagesVi } from \"./messages-vi.js\";\n\nexport type { DataGridMessages };\nexport { messagesEn, messagesVi };\n\n/** Mọi bảng ngôn ngữ dựng sẵn, tra theo mã. */\nexport const DATA_GRID_MESSAGES = {\n en: messagesEn,\n vi: messagesVi\n};\n\n/** Mã ngôn ngữ mà `DataGrid` nhận. Suy từ `DATA_GRID_MESSAGES`, không viết tay lần hai. */\nexport type DataGridLocale = keyof typeof DATA_GRID_MESSAGES;\n\n/** Mặc định khi không ai truyền gì — xem ghi chú đầu file về vì sao là `\"en\"`. */\nexport const DEFAULT_DATA_GRID_LOCALE: DataGridLocale = \"en\";\n\n/**\n * Bảng chuỗi cho một ngôn ngữ, hoặc bảng do app tự truyền vào.\n *\n * Nhận cả mã lẫn cả object để app không phải chọn giữa \"dùng bản dựng sẵn\" và \"sửa vài chữ\":\n * truyền `\"vi\"` là xong, còn muốn đổi từ ngữ theo nghiệp vụ thì trải bảng ra rồi ghi đè khoá cần\n * đổi. Mã lạ rơi về mặc định thay vì ném lỗi — một chữ sai chính tả trong prop không đáng làm\n * trắng cả màn hình.\n */\nexport function getDataGridMessages(locale?: DataGridLocale | DataGridMessages): DataGridMessages {\n if (!locale) return DATA_GRID_MESSAGES[DEFAULT_DATA_GRID_LOCALE];\n if (typeof locale === \"string\") return DATA_GRID_MESSAGES[locale] ?? DATA_GRID_MESSAGES[DEFAULT_DATA_GRID_LOCALE];\n return locale;\n}\n"],"mappings":"AAYA,SAAgC,kBAAkB;AAClD,SAAS,kBAAkB;AAMpB,MAAM,qBAAqB;AAAA,EAChC,IAAI;AAAA,EACJ,IAAI;AACN;AAMO,MAAM,2BAA2C;AAUjD,SAAS,oBAAoB,QAA8D;AAChG,MAAI,CAAC,OAAQ,QAAO,mBAAmB,wBAAwB;AAC/D,MAAI,OAAO,WAAW,SAAU,QAAO,mBAAmB,MAAM,KAAK,mBAAmB,wBAAwB;AAChH,SAAO;AACT;","names":[]}
|
|
@@ -26,7 +26,7 @@ import { Slot } from "@radix-ui/react-slot";
|
|
|
26
26
|
import * as React from "react";
|
|
27
27
|
import * as ReactDOM from "react-dom";
|
|
28
28
|
import { cn } from "../lib/cn.js";
|
|
29
|
-
import { useComposedRefs } from "
|
|
29
|
+
import { useComposedRefs } from "../lib/compose-refs.js";
|
|
30
30
|
const orientationConfig = {
|
|
31
31
|
vertical: {
|
|
32
32
|
modifiers: [restrictToVerticalAxis, restrictToParentElement],
|
|
@@ -1 +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":[]}
|
|
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 \"../lib/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":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { DataGridLocale } from './messages.js';
|
|
2
|
+
import { DataGridMessages } from './messages-en.js';
|
|
3
|
+
import './messages-vi.js';
|
|
4
|
+
|
|
1
5
|
interface UndoRedoCellUpdate {
|
|
2
6
|
rowId: string;
|
|
3
7
|
columnId: string;
|
|
@@ -17,6 +21,14 @@ interface UseDataGridUndoRedoProps<TData> {
|
|
|
17
21
|
/** Số thao tác giữ trong lịch sử (mặc định 100) */
|
|
18
22
|
maxHistory?: number;
|
|
19
23
|
enabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Ngôn ngữ của toast mà hook bắn ra (`"en"` mặc định · `"vi"`, hoặc cả bảng chuỗi tự soạn).
|
|
26
|
+
*
|
|
27
|
+
* Hook giữ bảng chuỗi của RIÊNG nó chứ không đọc `DataGridLocaleProvider`: toast render ở gốc
|
|
28
|
+
* app qua `<Toaster />`, ngoài hẳn cây DOM của lưới, nên không có context nào để đọc. Truyền
|
|
29
|
+
* cùng giá trị đã truyền cho `useDataGrid`.
|
|
30
|
+
*/
|
|
31
|
+
locale?: DataGridLocale | DataGridMessages;
|
|
20
32
|
}
|
|
21
33
|
interface UseDataGridUndoRedoReturn<TData> {
|
|
22
34
|
canUndo: boolean;
|
|
@@ -28,6 +40,6 @@ interface UseDataGridUndoRedoReturn<TData> {
|
|
|
28
40
|
trackRowsAdd: (rows: TData[]) => void;
|
|
29
41
|
trackRowsDelete: (rows: TData[]) => void;
|
|
30
42
|
}
|
|
31
|
-
declare function useDataGridUndoRedo<TData>({ data, onDataChange, getRowId, maxHistory, enabled }: UseDataGridUndoRedoProps<TData>): UseDataGridUndoRedoReturn<TData>;
|
|
43
|
+
declare function useDataGridUndoRedo<TData>({ data, onDataChange, getRowId, maxHistory, enabled, locale }: UseDataGridUndoRedoProps<TData>): UseDataGridUndoRedoReturn<TData>;
|
|
32
44
|
|
|
33
45
|
export { type UndoRedoCellUpdate, useDataGridUndoRedo };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { useAsRef } from "../lib/use-as-ref.js";
|
|
4
|
+
import { useLazyRef } from "../lib/use-lazy-ref.js";
|
|
5
|
+
import { getDataGridMessages } from "./messages.js";
|
|
4
6
|
import { toastInfo, toastSuccess } from "./toast.js";
|
|
5
|
-
import { useAsRef } from "./use-as-ref.js";
|
|
6
|
-
import { useLazyRef } from "./use-lazy-ref.js";
|
|
7
7
|
import { getIsInPopover } from "./utils.js";
|
|
8
8
|
const DEFAULT_MAX_HISTORY = 100;
|
|
9
9
|
const BATCH_TIMEOUT = 300;
|
|
@@ -29,8 +29,11 @@ function useDataGridUndoRedo({
|
|
|
29
29
|
onDataChange,
|
|
30
30
|
getRowId,
|
|
31
31
|
maxHistory = DEFAULT_MAX_HISTORY,
|
|
32
|
-
enabled = true
|
|
32
|
+
enabled = true,
|
|
33
|
+
locale
|
|
33
34
|
}) {
|
|
35
|
+
const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);
|
|
36
|
+
const msgRef = useAsRef(msg);
|
|
34
37
|
const propsRef = useAsRef({
|
|
35
38
|
data,
|
|
36
39
|
onDataChange,
|
|
@@ -179,25 +182,25 @@ function useDataGridUndoRedo({
|
|
|
179
182
|
onCommit();
|
|
180
183
|
const entry = store.undo();
|
|
181
184
|
if (!entry) {
|
|
182
|
-
toastInfo(
|
|
185
|
+
toastInfo(msgRef.current.toast.nothingToUndo);
|
|
183
186
|
return;
|
|
184
187
|
}
|
|
185
188
|
const newData = entry.undo(propsRef.current.data);
|
|
186
189
|
propsRef.current.onDataChange(newData);
|
|
187
|
-
toastSuccess(
|
|
188
|
-
}, [store, propsRef, onCommit]);
|
|
190
|
+
toastSuccess(msgRef.current.toast.undone(entry.count));
|
|
191
|
+
}, [store, propsRef, onCommit, msgRef]);
|
|
189
192
|
const onRedo = React.useCallback(() => {
|
|
190
193
|
if (!propsRef.current.enabled) return;
|
|
191
194
|
onCommit();
|
|
192
195
|
const entry = store.redo();
|
|
193
196
|
if (!entry) {
|
|
194
|
-
toastInfo(
|
|
197
|
+
toastInfo(msgRef.current.toast.nothingToRedo);
|
|
195
198
|
return;
|
|
196
199
|
}
|
|
197
200
|
const newData = entry.redo(propsRef.current.data);
|
|
198
201
|
propsRef.current.onDataChange(newData);
|
|
199
|
-
toastSuccess(
|
|
200
|
-
}, [store, propsRef, onCommit]);
|
|
202
|
+
toastSuccess(msgRef.current.toast.redone(entry.count));
|
|
203
|
+
}, [store, propsRef, onCommit, msgRef]);
|
|
201
204
|
const onClear = React.useCallback(() => {
|
|
202
205
|
const pending = pendingBatchRef.current;
|
|
203
206
|
if (pending.timeoutId) {
|