@ultraviolet/ui 1.82.0 → 1.82.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Checkbox/index.cjs +14 -20
- package/dist/components/Checkbox/index.d.ts +1 -1
- package/dist/components/Checkbox/index.js +15 -21
- package/dist/components/Chip/index.d.ts +1 -1
- package/dist/components/Dialog/index.cjs +3 -3
- package/dist/components/Dialog/index.js +3 -3
- package/dist/components/List/Cell.cjs +1 -1
- package/dist/components/List/Cell.js +1 -1
- package/dist/components/List/HeaderRow.cjs +4 -5
- package/dist/components/List/HeaderRow.js +4 -5
- package/dist/components/List/ListContext.cjs +105 -104
- package/dist/components/List/ListContext.d.ts +14 -11
- package/dist/components/List/ListContext.js +105 -104
- package/dist/components/List/Row.cjs +33 -26
- package/dist/components/List/Row.js +33 -26
- package/dist/components/List/index.cjs +2 -2
- package/dist/components/List/index.d.ts +1 -22
- package/dist/components/List/index.js +2 -2
- package/dist/components/Radio/index.cjs +11 -11
- package/dist/components/Radio/index.d.ts +1 -2
- package/dist/components/Radio/index.js +11 -11
- package/dist/components/SearchInput/index.cjs +2 -2
- package/dist/components/SearchInput/index.js +2 -2
- package/dist/components/SelectInput/index.cjs +8 -8
- package/dist/components/SelectInput/index.js +8 -8
- package/dist/components/SwitchButton/index.cjs +3 -3
- package/dist/components/SwitchButton/index.js +3 -3
- package/dist/components/Table/HeaderRow.cjs +2 -3
- package/dist/components/Table/HeaderRow.js +2 -3
- package/dist/components/Table/Row.cjs +29 -22
- package/dist/components/Table/Row.js +29 -22
- package/dist/components/Table/TableContext.cjs +19 -157
- package/dist/components/Table/TableContext.d.ts +5 -30
- package/dist/components/Table/TableContext.js +20 -158
- package/dist/components/Table/index.cjs +2 -2
- package/dist/components/Table/index.d.ts +26 -33
- package/dist/components/Table/index.js +2 -2
- package/package.json +4 -4
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { ComponentProps, Dispatch, ReactNode,
|
|
1
|
+
import type { ChangeEvent, ComponentProps, Dispatch, ReactNode, SetStateAction } from 'react';
|
|
2
2
|
import type { Checkbox } from '../Checkbox';
|
|
3
3
|
import type { ColumnProps } from './types';
|
|
4
|
-
type RowState = Record<string, boolean>;
|
|
5
|
-
type
|
|
4
|
+
type RowState = Record<string | number, boolean>;
|
|
5
|
+
type MapCheckbox = Map<string | number, HTMLInputElement>;
|
|
6
|
+
export type ListContextValue = {
|
|
6
7
|
/**
|
|
7
8
|
* @returns an unregister function
|
|
8
9
|
* */
|
|
@@ -15,18 +16,20 @@ type ListContextValue = {
|
|
|
15
16
|
* @returns an unregister function
|
|
16
17
|
* */
|
|
17
18
|
registerSelectableRow: (rowId: string) => () => void;
|
|
18
|
-
selectedRowIds: RowState;
|
|
19
|
-
selectRow: (rowId: string) => void;
|
|
20
|
-
unselectRow: (rowId: string) => void;
|
|
21
|
-
selectable: boolean;
|
|
22
19
|
allRowSelectValue: ComponentProps<typeof Checkbox>['checked'];
|
|
20
|
+
selectAllHandler: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
21
|
+
subscribeHandler: () => void;
|
|
22
|
+
columns: ColumnProps[];
|
|
23
|
+
inRange: Set<number | string>;
|
|
24
|
+
mapCheckbox: MapCheckbox;
|
|
25
|
+
selectable: boolean;
|
|
23
26
|
selectAll: () => void;
|
|
27
|
+
selectedRowIds: RowState;
|
|
28
|
+
selectRow: (rowId: string) => void;
|
|
24
29
|
unselectAll: () => void;
|
|
25
|
-
|
|
26
|
-
inRange: string[];
|
|
27
|
-
columns: ColumnProps[];
|
|
30
|
+
unselectRow: (rowId: string) => void;
|
|
28
31
|
};
|
|
29
|
-
type ListProviderProps = {
|
|
32
|
+
export type ListProviderProps = {
|
|
30
33
|
children: ReactNode;
|
|
31
34
|
autoCollapse: boolean;
|
|
32
35
|
selectable: boolean;
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { jsx } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { createContext, useState, useRef, useCallback, useMemo, useEffect, useContext } from "react";
|
|
3
3
|
const ListContext = createContext(void 0);
|
|
4
|
+
const checkStateOfCheckboxs = (ids) => {
|
|
5
|
+
const selectableRowCount = Object.keys(ids).length;
|
|
6
|
+
const selectableValuesCount = new Set(Object.values(ids));
|
|
7
|
+
if (!selectableRowCount) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
if (selectableValuesCount.size === 1) {
|
|
11
|
+
return [...selectableValuesCount][0];
|
|
12
|
+
}
|
|
13
|
+
return "indeterminate";
|
|
14
|
+
};
|
|
4
15
|
const ListProvider = ({
|
|
5
16
|
children,
|
|
6
17
|
autoCollapse,
|
|
@@ -11,7 +22,9 @@ const ListProvider = ({
|
|
|
11
22
|
}) => {
|
|
12
23
|
const [expandedRowIds, setExpandedRowIds] = useState({});
|
|
13
24
|
const [selectedRowIds, setSelectedRowIds] = useState({});
|
|
14
|
-
const
|
|
25
|
+
const [lastCheckedIndex, setLastCheckedIndex] = useState(null);
|
|
26
|
+
const [inRange, setInRange] = useState(/* @__PURE__ */ new Set([]));
|
|
27
|
+
const refList = useRef(/* @__PURE__ */ new Map());
|
|
15
28
|
const registerExpandableRow = useCallback((rowId, expanded = false) => {
|
|
16
29
|
setExpandedRowIds((current) => ({
|
|
17
30
|
...current,
|
|
@@ -54,142 +67,130 @@ const ListProvider = ({
|
|
|
54
67
|
[rowId]: false
|
|
55
68
|
}));
|
|
56
69
|
}, []);
|
|
57
|
-
const allRowSelectValue = useMemo(() =>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
const selectedRowCount = Object.values(selectedRowIds).reduce((acc, isSelected) => acc + (isSelected ? 1 : 0), 0);
|
|
63
|
-
if (selectedRowCount === 0) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
if (selectableRowCount === selectedRowCount) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
return "indeterminate";
|
|
70
|
-
}, [selectedRowIds]);
|
|
71
|
-
const selectAll = useCallback(() => {
|
|
72
|
-
const newSelectedRowIds = Object.keys(selectedRowIds).reduce((acc, rowId) => ({
|
|
70
|
+
const allRowSelectValue = useMemo(() => checkStateOfCheckboxs(selectedRowIds), [selectedRowIds]);
|
|
71
|
+
const selectRows = useCallback((rowIds, state) => {
|
|
72
|
+
const newSelectedRowIds = rowIds.reduce((acc, rowId) => ({
|
|
73
73
|
...acc,
|
|
74
|
-
[rowId]:
|
|
75
|
-
}),
|
|
74
|
+
[rowId]: state
|
|
75
|
+
}), selectedRowIds);
|
|
76
76
|
setSelectedRowIds(newSelectedRowIds);
|
|
77
77
|
if (onSelectedChange) {
|
|
78
78
|
onSelectedChange(Object.keys(newSelectedRowIds).filter((row) => newSelectedRowIds[row]));
|
|
79
79
|
}
|
|
80
80
|
}, [onSelectedChange, selectedRowIds]);
|
|
81
|
+
const selectAll = useCallback(() => {
|
|
82
|
+
selectRows(Object.keys(selectedRowIds), true);
|
|
83
|
+
}, [selectRows, selectedRowIds]);
|
|
81
84
|
const unselectAll = useCallback(() => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
[rowId]: false
|
|
85
|
-
}), {});
|
|
86
|
-
setSelectedRowIds(newSelectedRowIds);
|
|
87
|
-
if (onSelectedChange) {
|
|
88
|
-
onSelectedChange(Object.keys(newSelectedRowIds).filter((row) => newSelectedRowIds[row]));
|
|
89
|
-
}
|
|
90
|
-
}, [onSelectedChange, selectedRowIds]);
|
|
85
|
+
selectRows(Object.keys(selectedRowIds), false);
|
|
86
|
+
}, [selectRows, selectedRowIds]);
|
|
91
87
|
const selectRow = useCallback((rowId) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
[rowId]: true
|
|
95
|
-
};
|
|
96
|
-
setSelectedRowIds(newSelectedRowIds);
|
|
97
|
-
if (onSelectedChange) {
|
|
98
|
-
onSelectedChange(Object.keys(newSelectedRowIds).filter((row) => newSelectedRowIds[row]));
|
|
99
|
-
}
|
|
100
|
-
}, [onSelectedChange, selectedRowIds]);
|
|
88
|
+
selectRows([rowId], true);
|
|
89
|
+
}, [selectRows]);
|
|
101
90
|
const unselectRow = useCallback((rowId) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (onSelectedChange) {
|
|
108
|
-
onSelectedChange(Object.keys(newSelectedRowIds).filter((row) => newSelectedRowIds[row]));
|
|
91
|
+
selectRows([rowId], false);
|
|
92
|
+
}, [selectRows]);
|
|
93
|
+
const selectAllHandler = useCallback(() => {
|
|
94
|
+
if (allRowSelectValue && [true, "indeterminate"].includes(allRowSelectValue)) {
|
|
95
|
+
unselectAll();
|
|
109
96
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
if (allRowSelectValue === false) {
|
|
98
|
+
selectAll();
|
|
99
|
+
}
|
|
100
|
+
}, [allRowSelectValue, unselectAll, selectAll]);
|
|
101
|
+
const subscribeHandler = useCallback(() => {
|
|
114
102
|
const handlers = [];
|
|
115
103
|
if (refList.current) {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
for (let i = start; i <= end; i += 1) {
|
|
126
|
-
const checkbox = refList.current[i];
|
|
127
|
-
const checkboxValue = checkbox.value;
|
|
128
|
-
if (!checkbox.disabled) {
|
|
129
|
-
if (checked) {
|
|
130
|
-
newSelectedRowIds[checkboxValue] = false;
|
|
131
|
-
} else {
|
|
132
|
-
newSelectedRowIds[checkboxValue] = true;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
setSelectedRowIds(newSelectedRowIds);
|
|
137
|
-
if (onSelectedChange) {
|
|
138
|
-
onSelectedChange(Object.keys(newSelectedRowIds).filter((row) => newSelectedRowIds[row]));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
} else setLastCheckedIndex(null);
|
|
104
|
+
const handleHover = (checkbox, event) => {
|
|
105
|
+
const isShiftPressed = event.shiftKey;
|
|
106
|
+
const isHoverActive = isShiftPressed && lastCheckedIndex !== null && !checkbox.disabled;
|
|
107
|
+
if (isHoverActive) {
|
|
108
|
+
setInRange((prev) => /* @__PURE__ */ new Set([...prev, checkbox.value]));
|
|
109
|
+
}
|
|
110
|
+
if (!lastCheckedIndex && !checkbox.disabled) {
|
|
111
|
+
setLastCheckedIndex(checkbox.value);
|
|
112
|
+
}
|
|
142
113
|
};
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
114
|
+
const handleClickRange = (checkbox) => {
|
|
115
|
+
const shouldShiftEvent = inRange.size > 0;
|
|
116
|
+
const isClickInsideRange = inRange.has(checkbox.value);
|
|
117
|
+
if (shouldShiftEvent && isClickInsideRange) {
|
|
118
|
+
let checkboxRows = {};
|
|
119
|
+
refList.current.forEach((value2, key) => {
|
|
120
|
+
if (inRange.has(key)) {
|
|
121
|
+
checkboxRows = {
|
|
122
|
+
...checkboxRows,
|
|
123
|
+
// handle the conflict event ( click and onChange in the same time on the last checkbox click)
|
|
124
|
+
[key]: key === checkbox.value ? !value2.checked : value2.checked
|
|
125
|
+
};
|
|
152
126
|
}
|
|
127
|
+
});
|
|
128
|
+
const state = checkStateOfCheckboxs(checkboxRows);
|
|
129
|
+
const checkboxIds = Object.keys(checkboxRows);
|
|
130
|
+
if (state === true) {
|
|
131
|
+
selectRows(checkboxIds, false);
|
|
132
|
+
}
|
|
133
|
+
if ([false, "indeterminate"].includes(state)) {
|
|
134
|
+
selectRows(checkboxIds, true);
|
|
153
135
|
}
|
|
154
136
|
}
|
|
155
|
-
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
setInRange(/* @__PURE__ */ new Set([]));
|
|
139
|
+
setLastCheckedIndex(checkbox.value);
|
|
140
|
+
}, 1);
|
|
141
|
+
};
|
|
142
|
+
const handleOnChange = (checkbox) => {
|
|
143
|
+
const shouldHandleEvent = inRange.size === 0;
|
|
144
|
+
if (shouldHandleEvent) {
|
|
145
|
+
selectRows([checkbox.value], !checkbox.checked);
|
|
146
|
+
}
|
|
147
|
+
setLastCheckedIndex(checkbox.value);
|
|
156
148
|
};
|
|
157
|
-
refList.current.forEach((checkbox
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
149
|
+
refList.current.forEach((checkbox) => {
|
|
150
|
+
function clickHandler() {
|
|
151
|
+
handleClickRange(this);
|
|
152
|
+
}
|
|
153
|
+
function hoverHandler(event) {
|
|
154
|
+
handleHover(this, event);
|
|
155
|
+
}
|
|
156
|
+
function changeHandler() {
|
|
157
|
+
handleOnChange(this);
|
|
158
|
+
}
|
|
159
|
+
checkbox.addEventListener("change", changeHandler);
|
|
161
160
|
checkbox.addEventListener("click", clickHandler);
|
|
162
|
-
checkbox.addEventListener("
|
|
163
|
-
checkbox.addEventListener("mouseout", hoverLeavingHandler);
|
|
161
|
+
checkbox.addEventListener("mouseover", hoverHandler);
|
|
164
162
|
handlers.push(() => {
|
|
163
|
+
checkbox.removeEventListener("change", changeHandler);
|
|
165
164
|
checkbox.removeEventListener("click", clickHandler);
|
|
166
|
-
checkbox.removeEventListener("
|
|
167
|
-
checkbox.removeEventListener("mousemove", hoverLeavingHandler);
|
|
165
|
+
checkbox.removeEventListener("mouseover", hoverHandler);
|
|
168
166
|
});
|
|
169
167
|
});
|
|
170
168
|
}
|
|
171
169
|
return () => {
|
|
172
170
|
handlers.forEach((cleanup) => cleanup());
|
|
173
171
|
};
|
|
174
|
-
}, [
|
|
172
|
+
}, [inRange, lastCheckedIndex, selectRows]);
|
|
173
|
+
useEffect(subscribeHandler, [subscribeHandler]);
|
|
175
174
|
const value = useMemo(() => ({
|
|
176
|
-
|
|
175
|
+
allRowSelectValue,
|
|
176
|
+
selectAllHandler,
|
|
177
|
+
subscribeHandler,
|
|
178
|
+
collapseRow,
|
|
179
|
+
columns,
|
|
180
|
+
expandButton,
|
|
177
181
|
expandedRowIds,
|
|
178
182
|
expandRow,
|
|
179
|
-
|
|
183
|
+
inRange,
|
|
184
|
+
mapCheckbox: refList.current,
|
|
185
|
+
registerExpandableRow,
|
|
180
186
|
registerSelectableRow,
|
|
181
|
-
selectedRowIds,
|
|
182
|
-
selectRow,
|
|
183
|
-
unselectRow,
|
|
184
187
|
selectable,
|
|
185
188
|
selectAll,
|
|
189
|
+
selectedRowIds,
|
|
190
|
+
selectRow,
|
|
186
191
|
unselectAll,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
refList,
|
|
190
|
-
inRange,
|
|
191
|
-
columns
|
|
192
|
-
}), [registerExpandableRow, expandedRowIds, expandRow, collapseRow, registerSelectableRow, selectedRowIds, selectRow, unselectRow, selectable, selectAll, unselectAll, allRowSelectValue, expandButton, refList, inRange, columns]);
|
|
192
|
+
unselectRow
|
|
193
|
+
}), [allRowSelectValue, selectAllHandler, subscribeHandler, collapseRow, columns, expandButton, expandedRowIds, expandRow, inRange, refList, registerExpandableRow, registerSelectableRow, selectable, selectAll, selectedRowIds, selectRow, unselectAll, unselectRow]);
|
|
193
194
|
return /* @__PURE__ */ jsx(ListContext.Provider, { value, children });
|
|
194
195
|
};
|
|
195
196
|
const useListContext = () => {
|