etudes 3.7.0 → 3.8.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/lib/Accordion.d.ts +61 -34
- package/lib/Accordion.js +89 -86
- package/lib/Accordion.js.map +1 -1
- package/lib/Dropdown.d.ts +24 -9
- package/lib/Dropdown.js +49 -34
- package/lib/Dropdown.js.map +1 -1
- package/lib/List.d.ts +35 -20
- package/lib/List.js +50 -45
- package/lib/List.js.map +1 -1
- package/lib/hooks/usePrevious.d.ts +16 -3
- package/lib/hooks/usePrevious.js +7 -5
- package/lib/hooks/usePrevious.js.map +1 -1
- package/package.json +10 -10
package/lib/List.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import React, { type ComponentType, type HTMLAttributes, type ReactElement, type Ref } from 'react';
|
|
2
|
-
type
|
|
2
|
+
export type ListOrientation = 'horizontal' | 'vertical';
|
|
3
|
+
export type ListLayout = 'list' | 'grid';
|
|
4
|
+
export type ListSelectionMode = 'none' | 'single' | 'multiple';
|
|
5
|
+
export type ListSelection = number[];
|
|
3
6
|
export type ListItemProps<T> = HTMLAttributes<HTMLElement> & {
|
|
4
7
|
data: T;
|
|
5
8
|
index: number;
|
|
6
9
|
isSelected: boolean;
|
|
7
|
-
orientation:
|
|
10
|
+
orientation: ListOrientation;
|
|
8
11
|
onCustomEvent?: (name: string, info?: any) => void;
|
|
9
12
|
};
|
|
10
13
|
export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
|
|
11
|
-
/**
|
|
12
|
-
* Thickness of item borders (in pixels). 0 indicates no borders.
|
|
13
|
-
*/
|
|
14
|
-
borderThickness?: number;
|
|
15
14
|
/**
|
|
16
15
|
* Generically typed data of each item.
|
|
17
16
|
*/
|
|
@@ -30,22 +29,32 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
|
|
|
30
29
|
* Padding between every item (in pixels).
|
|
31
30
|
*/
|
|
32
31
|
itemPadding?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Specifies the layout of this component.
|
|
34
|
+
*/
|
|
35
|
+
layout?: ListLayout;
|
|
36
|
+
/**
|
|
37
|
+
* This property is only used if the layout is set to `grid`. Specifies the
|
|
38
|
+
* number of columns if orientation is `vertical` or number of rows if
|
|
39
|
+
* orientation is `horizontal`.
|
|
40
|
+
*/
|
|
41
|
+
numSegments?: number;
|
|
33
42
|
/**
|
|
34
43
|
* Orientation of the component.
|
|
35
44
|
*/
|
|
36
|
-
orientation?:
|
|
45
|
+
orientation?: ListOrientation;
|
|
37
46
|
/**
|
|
38
47
|
* The selected indices. If `selectionMode` is `single`, only only the first
|
|
39
48
|
* value will be used.
|
|
40
49
|
*/
|
|
41
|
-
|
|
50
|
+
selection?: ListSelection;
|
|
42
51
|
/**
|
|
43
52
|
* Indicates the selection behavior:
|
|
44
53
|
* - `none`: No selection at all.
|
|
45
54
|
* - `single`: Only one item can be selected at a time.
|
|
46
55
|
* - `multiple`: Multiple items can be selected at the same time.
|
|
47
56
|
*/
|
|
48
|
-
selectionMode?:
|
|
57
|
+
selectionMode?: ListSelectionMode;
|
|
49
58
|
/**
|
|
50
59
|
* React component type to be used to generate items for this list.
|
|
51
60
|
*/
|
|
@@ -79,9 +88,9 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
|
|
|
79
88
|
/**
|
|
80
89
|
* Handler invoked when the selected items changed.
|
|
81
90
|
*
|
|
82
|
-
* @param
|
|
91
|
+
* @param selection Indices of selected items.
|
|
83
92
|
*/
|
|
84
|
-
onSelectionChange?: (
|
|
93
|
+
onSelectionChange?: (selection: ListSelection) => void;
|
|
85
94
|
};
|
|
86
95
|
/**
|
|
87
96
|
* A scrollable list of selectable items. Items are generated based on the
|
|
@@ -89,10 +98,6 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
|
|
|
89
98
|
* generic. This component supports both horizontal and vertical orientations.
|
|
90
99
|
*/
|
|
91
100
|
declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
|
|
92
|
-
/**
|
|
93
|
-
* Thickness of item borders (in pixels). 0 indicates no borders.
|
|
94
|
-
*/
|
|
95
|
-
borderThickness?: number | undefined;
|
|
96
101
|
/**
|
|
97
102
|
* Generically typed data of each item.
|
|
98
103
|
*/
|
|
@@ -111,22 +116,32 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
|
|
|
111
116
|
* Padding between every item (in pixels).
|
|
112
117
|
*/
|
|
113
118
|
itemPadding?: number | undefined;
|
|
119
|
+
/**
|
|
120
|
+
* Specifies the layout of this component.
|
|
121
|
+
*/
|
|
122
|
+
layout?: ListLayout | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* This property is only used if the layout is set to `grid`. Specifies the
|
|
125
|
+
* number of columns if orientation is `vertical` or number of rows if
|
|
126
|
+
* orientation is `horizontal`.
|
|
127
|
+
*/
|
|
128
|
+
numSegments?: number | undefined;
|
|
114
129
|
/**
|
|
115
130
|
* Orientation of the component.
|
|
116
131
|
*/
|
|
117
|
-
orientation?:
|
|
132
|
+
orientation?: ListOrientation | undefined;
|
|
118
133
|
/**
|
|
119
134
|
* The selected indices. If `selectionMode` is `single`, only only the first
|
|
120
135
|
* value will be used.
|
|
121
136
|
*/
|
|
122
|
-
|
|
137
|
+
selection?: ListSelection | undefined;
|
|
123
138
|
/**
|
|
124
139
|
* Indicates the selection behavior:
|
|
125
140
|
* - `none`: No selection at all.
|
|
126
141
|
* - `single`: Only one item can be selected at a time.
|
|
127
142
|
* - `multiple`: Multiple items can be selected at the same time.
|
|
128
143
|
*/
|
|
129
|
-
selectionMode?:
|
|
144
|
+
selectionMode?: ListSelectionMode | undefined;
|
|
130
145
|
/**
|
|
131
146
|
* React component type to be used to generate items for this list.
|
|
132
147
|
*/
|
|
@@ -160,9 +175,9 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
|
|
|
160
175
|
/**
|
|
161
176
|
* Handler invoked when the selected items changed.
|
|
162
177
|
*
|
|
163
|
-
* @param
|
|
178
|
+
* @param selection Indices of selected items.
|
|
164
179
|
*/
|
|
165
|
-
onSelectionChange?: ((
|
|
180
|
+
onSelectionChange?: ((selection: ListSelection) => void) | undefined;
|
|
166
181
|
} & {
|
|
167
182
|
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
168
183
|
}) => ReactElement;
|
package/lib/List.js
CHANGED
|
@@ -87,7 +87,7 @@ var styles_1 = __importDefault(require("./utils/styles"));
|
|
|
87
87
|
* generic. This component supports both horizontal and vertical orientations.
|
|
88
88
|
*/
|
|
89
89
|
exports.default = (0, react_2.forwardRef)(function (_a, ref) {
|
|
90
|
-
var className = _a.className, style = _a.style, _b = _a.
|
|
90
|
+
var className = _a.className, style = _a.style, data = _a.data, _b = _a.selectionMode, selectionMode = _b === void 0 ? 'none' : _b, _c = _a.isSelectionTogglable, isSelectionTogglable = _c === void 0 ? false : _c, _d = _a.itemLength, itemLength = _d === void 0 ? 50 : _d, _e = _a.itemPadding, itemPadding = _e === void 0 ? 0 : _e, _f = _a.layout, layout = _f === void 0 ? 'list' : _f, _g = _a.numSegments, numSegments = _g === void 0 ? 1 : _g, _h = _a.orientation, orientation = _h === void 0 ? 'vertical' : _h, _j = _a.selection, externalSelection = _j === void 0 ? [] : _j, ItemComponent = _a.itemComponentType, onActivateAt = _a.onActivateAt, onDeselectAt = _a.onDeselectAt, onItemCustomEvent = _a.onItemCustomEvent, onSelectAt = _a.onSelectAt, onSelectionChange = _a.onSelectionChange, props = __rest(_a, ["className", "style", "data", "selectionMode", "isSelectionTogglable", "itemLength", "itemPadding", "layout", "numSegments", "orientation", "selection", "itemComponentType", "onActivateAt", "onDeselectAt", "onItemCustomEvent", "onSelectAt", "onSelectionChange"]);
|
|
91
91
|
var isIndexOutOfRange = function (index) {
|
|
92
92
|
if (index >= data.length)
|
|
93
93
|
return true;
|
|
@@ -95,8 +95,8 @@ exports.default = (0, react_2.forwardRef)(function (_a, ref) {
|
|
|
95
95
|
return true;
|
|
96
96
|
return false;
|
|
97
97
|
};
|
|
98
|
-
var
|
|
99
|
-
var isSelectedAt = function (index) { return
|
|
98
|
+
var sanitizeSelection = function (indices) { return indices.sort().filter(function (t) { return !isIndexOutOfRange(t); }); };
|
|
99
|
+
var isSelectedAt = function (index) { return selection.indexOf(index) >= 0; };
|
|
100
100
|
var toggleAt = function (index) {
|
|
101
101
|
if (isSelectedAt(index)) {
|
|
102
102
|
deselectAt(index);
|
|
@@ -110,10 +110,10 @@ exports.default = (0, react_2.forwardRef)(function (_a, ref) {
|
|
|
110
110
|
return;
|
|
111
111
|
switch (selectionMode) {
|
|
112
112
|
case 'multiple':
|
|
113
|
-
|
|
113
|
+
setSelection(function (prev) { return __spreadArray(__spreadArray([], __read(prev.filter(function (t) { return t !== index; })), false), [index], false).sort(); });
|
|
114
114
|
break;
|
|
115
115
|
case 'single':
|
|
116
|
-
|
|
116
|
+
setSelection([index]);
|
|
117
117
|
break;
|
|
118
118
|
default:
|
|
119
119
|
break;
|
|
@@ -122,7 +122,7 @@ exports.default = (0, react_2.forwardRef)(function (_a, ref) {
|
|
|
122
122
|
var deselectAt = function (index) {
|
|
123
123
|
if (!isSelectedAt(index))
|
|
124
124
|
return;
|
|
125
|
-
|
|
125
|
+
setSelection(function (prev) { return prev.filter(function (t) { return t !== index; }); });
|
|
126
126
|
};
|
|
127
127
|
var activateAt = function (index) {
|
|
128
128
|
if (selectionMode !== 'none') {
|
|
@@ -135,62 +135,67 @@ exports.default = (0, react_2.forwardRef)(function (_a, ref) {
|
|
|
135
135
|
}
|
|
136
136
|
onActivateAt === null || onActivateAt === void 0 ? void 0 : onActivateAt(index);
|
|
137
137
|
};
|
|
138
|
-
var
|
|
139
|
-
var
|
|
140
|
-
var
|
|
138
|
+
var sanitizedExternalSelection = sanitizeSelection(externalSelection);
|
|
139
|
+
var _k = __read((0, react_2.useState)(sanitizedExternalSelection), 2), selection = _k[0], setSelection = _k[1];
|
|
140
|
+
var prevSelection = (0, usePrevious_1.default)(selection, { sanitizeDependency: JSON.stringify });
|
|
141
141
|
(0, react_2.useEffect)(function () {
|
|
142
|
-
if ((0, react_1.default)(
|
|
142
|
+
if ((0, react_1.default)(sanitizedExternalSelection, selection))
|
|
143
143
|
return;
|
|
144
|
-
|
|
145
|
-
}, [JSON.stringify(
|
|
144
|
+
setSelection(sanitizedExternalSelection);
|
|
145
|
+
}, [JSON.stringify(sanitizedExternalSelection)]);
|
|
146
146
|
(0, react_2.useEffect)(function () {
|
|
147
147
|
var _a;
|
|
148
148
|
if (selectionMode === 'none')
|
|
149
149
|
return;
|
|
150
|
-
if (
|
|
150
|
+
if (!prevSelection)
|
|
151
151
|
return;
|
|
152
|
-
var deselected = (_a =
|
|
153
|
-
var selected =
|
|
152
|
+
var deselected = (_a = prevSelection === null || prevSelection === void 0 ? void 0 : prevSelection.filter(function (t) { return selection.indexOf(t) === -1; })) !== null && _a !== void 0 ? _a : [];
|
|
153
|
+
var selected = selection.filter(function (t) { return (prevSelection === null || prevSelection === void 0 ? void 0 : prevSelection.indexOf(t)) === -1; });
|
|
154
154
|
deselected.map(function (t) { return onDeselectAt === null || onDeselectAt === void 0 ? void 0 : onDeselectAt(t); });
|
|
155
155
|
selected.map(function (t) { return onSelectAt === null || onSelectAt === void 0 ? void 0 : onSelectAt(t); });
|
|
156
|
-
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(
|
|
157
|
-
}, [JSON.stringify(
|
|
158
|
-
var fixedClassNames = (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
156
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(selection);
|
|
157
|
+
}, [JSON.stringify(selection)]);
|
|
158
|
+
var fixedClassNames = getFixedClassNames({ orientation: orientation });
|
|
159
|
+
var fixedStyles = getFixedStyles({ itemLength: itemLength, itemPadding: itemPadding, layout: layout, numSegments: numSegments, orientation: orientation });
|
|
160
|
+
return (react_2.default.createElement("div", __assign({}, props, { ref: ref, className: (0, classnames_1.default)(className, fixedClassNames.root), style: (0, styles_1.default)(style, fixedStyles.root) }), ItemComponent && (react_2.default.createElement(Each_1.default, { in: data }, function (val, idx) { return (react_2.default.createElement(ItemComponent, { className: (0, classnames_1.default)({
|
|
161
|
+
selected: isSelectedAt(idx),
|
|
162
|
+
}), style: (0, styles_1.default)(fixedStyles.item, __assign({ pointerEvents: isSelectionTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto' }, idx >= data.length - 1 ? {} : __assign({}, layout === 'list' ? __assign({}, orientation === 'vertical' ? {
|
|
163
|
+
marginBottom: "".concat(itemPadding, "px"),
|
|
164
|
+
} : {
|
|
165
|
+
marginRight: "".concat(itemPadding, "px"),
|
|
166
|
+
}) : {}))), "data-index": idx, data: val, index: idx, isSelected: isSelectedAt(idx), orientation: orientation, onCustomEvent: function (name, info) { return onItemCustomEvent === null || onItemCustomEvent === void 0 ? void 0 : onItemCustomEvent(idx, name, info); }, onClick: function () { return activateAt(idx); } })); }))));
|
|
167
|
+
});
|
|
168
|
+
function getFixedClassNames(_a) {
|
|
169
|
+
var orientation = _a.orientation;
|
|
170
|
+
return (0, asClassNameDict_1.default)({
|
|
171
|
+
root: (0, classnames_1.default)(orientation),
|
|
165
172
|
});
|
|
166
|
-
|
|
167
|
-
|
|
173
|
+
}
|
|
174
|
+
function getFixedStyles(_a) {
|
|
175
|
+
var itemLength = _a.itemLength, _b = _a.itemPadding, itemPadding = _b === void 0 ? 0 : _b, layout = _a.layout, _c = _a.numSegments, numSegments = _c === void 0 ? 1 : _c, orientation = _a.orientation;
|
|
176
|
+
return (0, asStyleDict_1.default)({
|
|
177
|
+
root: __assign({ counterReset: 'item-counter', listStyle: 'none' }, layout === 'list' ? {
|
|
168
178
|
alignItems: 'flex-start',
|
|
169
|
-
counterReset: 'item-counter',
|
|
170
179
|
display: 'flex',
|
|
171
180
|
flex: '0 0 auto',
|
|
172
181
|
flexDirection: orientation === 'horizontal' ? 'row' : 'column',
|
|
173
182
|
justifyContent: 'flex-start',
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
183
|
+
} : __assign({ display: 'grid', gap: "".concat(itemPadding, "px") }, orientation === 'vertical' ? {
|
|
184
|
+
gridAutoRows: itemLength !== undefined ? "".concat(itemLength, "px") : undefined,
|
|
185
|
+
gridTemplateColumns: "repeat(".concat(numSegments, ", 1fr)"),
|
|
186
|
+
gridAutoFlow: 'row',
|
|
178
187
|
} : {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
gridAutoColumns: itemLength !== undefined ? "".concat(itemLength, "px") : undefined,
|
|
189
|
+
gridTemplateRows: "repeat(".concat(numSegments, ", 1fr)"),
|
|
190
|
+
gridAutoFlow: 'column',
|
|
191
|
+
})),
|
|
192
|
+
item: __assign({ border: 'none', counterIncrement: 'item-counter', flex: '0 0 auto' }, layout === 'list' ? __assign({}, orientation === 'vertical' ? {
|
|
193
|
+
width: '100%',
|
|
185
194
|
height: itemLength !== undefined ? "".concat(itemLength, "px") : undefined,
|
|
186
|
-
marginTop: "".concat(idx === 0 ? 0 : -borderThickness, "px"),
|
|
187
195
|
} : {
|
|
188
|
-
marginLeft: "".concat(idx === 0 ? 0 : -borderThickness, "px"),
|
|
189
196
|
width: itemLength !== undefined ? "".concat(itemLength, "px") : undefined,
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}))), "data-index": idx, data: val, index: idx, isSelected: isSelectedAt(idx), orientation: orientation, onCustomEvent: function (name, info) { return onItemCustomEvent === null || onItemCustomEvent === void 0 ? void 0 : onItemCustomEvent(idx, name, info); }, onClick: function () { return activateAt(idx); } })); }))));
|
|
195
|
-
});
|
|
197
|
+
height: '100%',
|
|
198
|
+
}) : {}),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
196
201
|
//# sourceMappingURL=List.js.map
|
package/lib/List.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"List.js","sourceRoot":"/","sources":["List.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport isDeepEqual from 'fast-deep-equal/react'\nimport React, { forwardRef, useEffect, useState, type ComponentType, type HTMLAttributes, type ReactElement, type Ref } from 'react'\nimport Each from './Each'\nimport usePrevious from './hooks/usePrevious'\nimport asClassNameDict from './utils/asClassNameDict'\nimport asStyleDict from './utils/asStyleDict'\nimport styles from './utils/styles'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nexport type ListItemProps<T> = HTMLAttributes<HTMLElement> & {\n data: T\n index: number\n isSelected: boolean\n orientation: Orientation\n onCustomEvent?: (name: string, info?: any) => void\n}\n\nexport type ListProps<T> = HTMLAttributes<HTMLDivElement> & {\n /**\n * Thickness of item borders (in pixels). 0 indicates no borders.\n */\n borderThickness?: number\n\n /**\n * Generically typed data of each item.\n */\n data: T[]\n\n /**\n * Indicates if item selection can be toggled, i.e. they can be deselected if\n * selected again.\n */\n isSelectionTogglable?: boolean\n\n /**\n * Optional length (in pixels) of each item. Length refers to the height in\n * vertical orientation and width in horizontal orientation.\n */\n itemLength?: number\n\n /**\n * Padding between every item (in pixels).\n */\n itemPadding?: number\n\n /**\n * Orientation of the component.\n */\n orientation?: Orientation\n\n /**\n * The selected indices. If `selectionMode` is `single`, only only the first\n * value will be used.\n */\n selectedIndices?: number[]\n\n /**\n * Indicates the selection behavior:\n * - `none`: No selection at all.\n * - `single`: Only one item can be selected at a time.\n * - `multiple`: Multiple items can be selected at the same time.\n */\n selectionMode?: 'none' | 'single' | 'multiple'\n\n /**\n * React component type to be used to generate items for this list.\n */\n itemComponentType?: ComponentType<ListItemProps<T>>\n\n /**\n * Handler invoked when an item is activated.\n *\n * @param index Item index.\n */\n onActivateAt?: (index: number) => void\n\n /**\n * Handler invoked when an item is deselected.\n *\n * @param index Item index.\n */\n onDeselectAt?: (index: number) => void\n\n /**\n * Handler invoked when a custom event is dispatched from the item.\n *\n * @param index Index of the item.\n * @param eventName Name of the dispatched custom event.\n * @param eventInfo Optional info of the dispatched custom event.\n */\n onItemCustomEvent?: (index: number, eventName: string, eventInfo?: any) => void\n\n /**\n * Handler invoked when an item is selected.\n *\n * @param index Item index.\n */\n onSelectAt?: (index: number) => void\n\n /**\n * Handler invoked when the selected items changed.\n *\n * @param indices Indices of selected items.\n */\n onSelectionChange?: (indices: number[]) => void\n}\n\n/**\n * A scrollable list of selectable items. Items are generated based on the\n * provided React component type. The type of data passed to each item is\n * generic. This component supports both horizontal and vertical orientations.\n */\nexport default forwardRef(({\n className,\n style,\n borderThickness = 0,\n data,\n selectionMode = 'none',\n isSelectionTogglable = false,\n itemLength,\n itemPadding = 0,\n orientation = 'vertical',\n selectedIndices: externalSelectedIndices = [],\n itemComponentType: ItemComponent,\n onActivateAt,\n onDeselectAt,\n onItemCustomEvent,\n onSelectAt,\n onSelectionChange,\n ...props\n}, ref) => {\n const isIndexOutOfRange = (index: number) => {\n if (index >= data.length) return true\n if (index < 0) return true\n\n return false\n }\n\n const sanitizeSelectedIndices = (indices: number[]) => indices.sort().filter(t => !isIndexOutOfRange(t))\n\n const isSelectedAt = (index: number) => selectedIndices.indexOf(index) >= 0\n\n const toggleAt = (index: number) => {\n if (isSelectedAt(index)) {\n deselectAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n const selectAt = (index: number) => {\n if (isSelectedAt(index)) return\n\n switch (selectionMode) {\n case 'multiple':\n setSelectedIndices(prev => [...prev.filter(t => t !== index), index].sort())\n\n break\n case 'single':\n setSelectedIndices([index])\n\n break\n default:\n break\n }\n }\n\n const deselectAt = (index: number) => {\n if (!isSelectedAt(index)) return\n\n setSelectedIndices(prev => prev.filter(t => t !== index))\n }\n\n const activateAt = (index: number) => {\n if (selectionMode !== 'none') {\n if (isSelectionTogglable) {\n toggleAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n onActivateAt?.(index)\n }\n\n const sanitizedExternalSelectedIndices = sanitizeSelectedIndices(externalSelectedIndices)\n const [selectedIndices, setSelectedIndices] = useState(sanitizedExternalSelectedIndices)\n const prevSelectedIndices = usePrevious(selectedIndices)\n\n useEffect(() => {\n if (isDeepEqual(sanitizedExternalSelectedIndices, selectedIndices)) return\n\n setSelectedIndices(sanitizedExternalSelectedIndices)\n }, [JSON.stringify(sanitizedExternalSelectedIndices)])\n\n useEffect(() => {\n if (selectionMode === 'none') return\n if (prevSelectedIndices === undefined) return\n\n const deselected = prevSelectedIndices?.filter(t => selectedIndices.indexOf(t) === -1) ?? []\n const selected = selectedIndices.filter(t => prevSelectedIndices?.indexOf(t) === -1)\n\n deselected.map(t => onDeselectAt?.(t))\n selected.map(t => onSelectAt?.(t))\n\n onSelectionChange?.(selectedIndices)\n }, [JSON.stringify(selectedIndices)])\n\n const fixedClassNames = asClassNameDict({\n root: classNames(orientation, {\n togglable: isSelectionTogglable,\n }),\n item: classNames(orientation, {\n togglable: isSelectionTogglable,\n }),\n })\n\n const fixedStyles = asStyleDict({\n root: {\n alignItems: 'flex-start',\n counterReset: 'item-counter',\n display: 'flex',\n flex: '0 0 auto',\n flexDirection: orientation === 'horizontal' ? 'row' : 'column',\n justifyContent: 'flex-start',\n listStyle: 'none',\n },\n item: {\n borderWidth: `${borderThickness}px`,\n counterIncrement: 'item-counter',\n flex: '0 0 auto',\n ...orientation === 'vertical' ? {\n width: '100%',\n } : {\n height: '100%',\n },\n },\n })\n\n return (\n <div\n {...props}\n ref={ref}\n className={classNames(className, fixedClassNames.root)}\n style={styles(style, fixedStyles.root)}\n >\n {ItemComponent && (\n <Each in={data}>\n {(val, idx) => (\n <ItemComponent\n className={classNames(fixedClassNames.item, {\n selected: isSelectedAt(idx),\n })}\n style={styles(fixedStyles.item, {\n pointerEvents: isSelectionTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto',\n ...orientation === 'vertical' ? {\n height: itemLength !== undefined ? `${itemLength}px` : undefined,\n marginTop: `${idx === 0 ? 0 : -borderThickness}px`,\n } : {\n marginLeft: `${idx === 0 ? 0 : -borderThickness}px`,\n width: itemLength !== undefined ? `${itemLength}px` : undefined,\n },\n ...idx >= data.length - 1 ? {} : {\n ...orientation === 'vertical' ? {\n marginBottom: `${itemPadding}px`,\n } : {\n marginRight: `${itemPadding}px`,\n },\n },\n })}\n data-index={idx}\n data={val}\n index={idx}\n isSelected={isSelectedAt(idx)}\n orientation={orientation}\n onCustomEvent={(name, info) => onItemCustomEvent?.(idx, name, info)}\n onClick={() => activateAt(idx)}\n />\n )}\n </Each>\n )}\n </div>\n )\n}) as <T>(props: ListProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n"]}
|
|
1
|
+
{"version":3,"file":"List.js","sourceRoot":"/","sources":["List.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport isDeepEqual from 'fast-deep-equal/react'\nimport React, { forwardRef, useEffect, useState, type ComponentType, type HTMLAttributes, type ReactElement, type Ref } from 'react'\nimport Each from './Each'\nimport usePrevious from './hooks/usePrevious'\nimport asClassNameDict from './utils/asClassNameDict'\nimport asStyleDict from './utils/asStyleDict'\nimport styles from './utils/styles'\n\nexport type ListOrientation = 'horizontal' | 'vertical'\n\nexport type ListLayout = 'list' | 'grid'\n\nexport type ListSelectionMode = 'none' | 'single' | 'multiple'\n\nexport type ListSelection = number[]\n\nexport type ListItemProps<T> = HTMLAttributes<HTMLElement> & {\n data: T\n index: number\n isSelected: boolean\n orientation: ListOrientation\n onCustomEvent?: (name: string, info?: any) => void\n}\n\nexport type ListProps<T> = HTMLAttributes<HTMLDivElement> & {\n /**\n * Generically typed data of each item.\n */\n data: T[]\n\n /**\n * Indicates if item selection can be toggled, i.e. they can be deselected if\n * selected again.\n */\n isSelectionTogglable?: boolean\n\n /**\n * Optional length (in pixels) of each item. Length refers to the height in\n * vertical orientation and width in horizontal orientation.\n */\n itemLength?: number\n\n /**\n * Padding between every item (in pixels).\n */\n itemPadding?: number\n\n /**\n * Specifies the layout of this component.\n */\n layout?: ListLayout\n\n /**\n * This property is only used if the layout is set to `grid`. Specifies the\n * number of columns if orientation is `vertical` or number of rows if\n * orientation is `horizontal`.\n */\n numSegments?: number\n\n /**\n * Orientation of the component.\n */\n orientation?: ListOrientation\n\n /**\n * The selected indices. If `selectionMode` is `single`, only only the first\n * value will be used.\n */\n selection?: ListSelection\n\n /**\n * Indicates the selection behavior:\n * - `none`: No selection at all.\n * - `single`: Only one item can be selected at a time.\n * - `multiple`: Multiple items can be selected at the same time.\n */\n selectionMode?: ListSelectionMode\n\n /**\n * React component type to be used to generate items for this list.\n */\n itemComponentType?: ComponentType<ListItemProps<T>>\n\n /**\n * Handler invoked when an item is activated.\n *\n * @param index Item index.\n */\n onActivateAt?: (index: number) => void\n\n /**\n * Handler invoked when an item is deselected.\n *\n * @param index Item index.\n */\n onDeselectAt?: (index: number) => void\n\n /**\n * Handler invoked when a custom event is dispatched from the item.\n *\n * @param index Index of the item.\n * @param eventName Name of the dispatched custom event.\n * @param eventInfo Optional info of the dispatched custom event.\n */\n onItemCustomEvent?: (index: number, eventName: string, eventInfo?: any) => void\n\n /**\n * Handler invoked when an item is selected.\n *\n * @param index Item index.\n */\n onSelectAt?: (index: number) => void\n\n /**\n * Handler invoked when the selected items changed.\n *\n * @param selection Indices of selected items.\n */\n onSelectionChange?: (selection: ListSelection) => void\n}\n\n/**\n * A scrollable list of selectable items. Items are generated based on the\n * provided React component type. The type of data passed to each item is\n * generic. This component supports both horizontal and vertical orientations.\n */\nexport default forwardRef(({\n className,\n style,\n data,\n selectionMode = 'none',\n isSelectionTogglable = false,\n itemLength = 50,\n itemPadding = 0,\n layout = 'list',\n numSegments = 1,\n orientation = 'vertical',\n selection: externalSelection = [],\n itemComponentType: ItemComponent,\n onActivateAt,\n onDeselectAt,\n onItemCustomEvent,\n onSelectAt,\n onSelectionChange,\n ...props\n}, ref) => {\n const isIndexOutOfRange = (index: number) => {\n if (index >= data.length) return true\n if (index < 0) return true\n\n return false\n }\n\n const sanitizeSelection = (indices: ListSelection) => indices.sort().filter(t => !isIndexOutOfRange(t))\n\n const isSelectedAt = (index: number) => selection.indexOf(index) >= 0\n\n const toggleAt = (index: number) => {\n if (isSelectedAt(index)) {\n deselectAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n const selectAt = (index: number) => {\n if (isSelectedAt(index)) return\n\n switch (selectionMode) {\n case 'multiple':\n setSelection(prev => [...prev.filter(t => t !== index), index].sort())\n\n break\n case 'single':\n setSelection([index])\n\n break\n default:\n break\n }\n }\n\n const deselectAt = (index: number) => {\n if (!isSelectedAt(index)) return\n\n setSelection(prev => prev.filter(t => t !== index))\n }\n\n const activateAt = (index: number) => {\n if (selectionMode !== 'none') {\n if (isSelectionTogglable) {\n toggleAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n onActivateAt?.(index)\n }\n\n const sanitizedExternalSelection = sanitizeSelection(externalSelection)\n const [selection, setSelection] = useState(sanitizedExternalSelection)\n const prevSelection = usePrevious(selection, { sanitizeDependency: JSON.stringify })\n\n useEffect(() => {\n if (isDeepEqual(sanitizedExternalSelection, selection)) return\n\n setSelection(sanitizedExternalSelection)\n }, [JSON.stringify(sanitizedExternalSelection)])\n\n useEffect(() => {\n if (selectionMode === 'none') return\n if (!prevSelection) return\n\n const deselected = prevSelection?.filter(t => selection.indexOf(t) === -1) ?? []\n const selected = selection.filter(t => prevSelection?.indexOf(t) === -1)\n\n deselected.map(t => onDeselectAt?.(t))\n selected.map(t => onSelectAt?.(t))\n\n onSelectionChange?.(selection)\n }, [JSON.stringify(selection)])\n\n const fixedClassNames = getFixedClassNames({ orientation })\n const fixedStyles = getFixedStyles({ itemLength, itemPadding, layout, numSegments, orientation })\n\n return (\n <div\n {...props}\n ref={ref}\n className={classNames(className, fixedClassNames.root)}\n style={styles(style, fixedStyles.root)}\n >\n {ItemComponent && (\n <Each in={data}>\n {(val, idx) => (\n <ItemComponent\n className={classNames({\n selected: isSelectedAt(idx),\n })}\n style={styles(fixedStyles.item, {\n pointerEvents: isSelectionTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto',\n ...idx >= data.length - 1 ? {} : {\n ...layout === 'list' ? {\n ...orientation === 'vertical' ? {\n marginBottom: `${itemPadding}px`,\n } : {\n marginRight: `${itemPadding}px`,\n },\n } : {},\n },\n })}\n data-index={idx}\n data={val}\n index={idx}\n isSelected={isSelectedAt(idx)}\n orientation={orientation}\n onCustomEvent={(name, info) => onItemCustomEvent?.(idx, name, info)}\n onClick={() => activateAt(idx)}\n />\n )}\n </Each>\n )}\n </div>\n )\n}) as <T>(props: ListProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n\ntype StylesProps = {\n itemLength?: number\n itemPadding?: number\n layout?: ListLayout\n numSegments?: number\n orientation?: ListOrientation\n}\n\nfunction getFixedClassNames({ orientation }: StylesProps) {\n return asClassNameDict({\n root: classNames(orientation),\n })\n}\n\nfunction getFixedStyles({ itemLength, itemPadding = 0, layout, numSegments = 1, orientation }: StylesProps) {\n return asStyleDict({\n root: {\n counterReset: 'item-counter',\n listStyle: 'none',\n ...layout === 'list' ? {\n alignItems: 'flex-start',\n display: 'flex',\n flex: '0 0 auto',\n flexDirection: orientation === 'horizontal' ? 'row' : 'column',\n justifyContent: 'flex-start',\n } : {\n display: 'grid',\n gap: `${itemPadding}px`,\n ...orientation === 'vertical' ? {\n gridAutoRows: itemLength !== undefined ? `${itemLength}px` : undefined,\n gridTemplateColumns: `repeat(${numSegments}, 1fr)`,\n gridAutoFlow: 'row',\n } : {\n gridAutoColumns: itemLength !== undefined ? `${itemLength}px` : undefined,\n gridTemplateRows: `repeat(${numSegments}, 1fr)`,\n gridAutoFlow: 'column',\n },\n },\n },\n item: {\n border: 'none',\n counterIncrement: 'item-counter',\n flex: '0 0 auto',\n ...layout === 'list' ? {\n ...orientation === 'vertical' ? {\n width: '100%',\n height: itemLength !== undefined ? `${itemLength}px` : undefined,\n } : {\n width: itemLength !== undefined ? `${itemLength}px` : undefined,\n height: '100%',\n },\n } : {},\n },\n })\n}\n"]}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
type Options<T> = {
|
|
2
|
+
/**
|
|
3
|
+
* Function to transform the dependency value in the dependency list, useful
|
|
4
|
+
* if the value is a reference.
|
|
5
|
+
*
|
|
6
|
+
* @param dependency The dependency value.
|
|
7
|
+
*
|
|
8
|
+
* @returns The transformed value to be used as the dependency value instead.
|
|
9
|
+
*/
|
|
10
|
+
sanitizeDependency?: (dependency: T) => any;
|
|
11
|
+
};
|
|
1
12
|
/**
|
|
2
|
-
* Returns the previous value of a
|
|
13
|
+
* Returns the previous value of a value.
|
|
3
14
|
*
|
|
4
|
-
* @param
|
|
15
|
+
* @param value The value.
|
|
16
|
+
* @param options See {@link Options}.
|
|
5
17
|
*/
|
|
6
|
-
export default function usePrevious<T>(
|
|
18
|
+
export default function usePrevious<T>(value: T, { sanitizeDependency }?: Options<T>): T | undefined;
|
|
19
|
+
export {};
|
package/lib/hooks/usePrevious.js
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
var react_1 = require("react");
|
|
4
4
|
/**
|
|
5
|
-
* Returns the previous value of a
|
|
5
|
+
* Returns the previous value of a value.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
7
|
+
* @param value The value.
|
|
8
|
+
* @param options See {@link Options}.
|
|
8
9
|
*/
|
|
9
|
-
function usePrevious(
|
|
10
|
+
function usePrevious(value, _a) {
|
|
11
|
+
var _b = _a === void 0 ? {} : _a, _c = _b.sanitizeDependency, sanitizeDependency = _c === void 0 ? function (t) { return t; } : _c;
|
|
10
12
|
var ref = (0, react_1.useRef)();
|
|
11
13
|
(0, react_1.useEffect)(function () {
|
|
12
|
-
ref.current =
|
|
13
|
-
}, [
|
|
14
|
+
ref.current = value;
|
|
15
|
+
}, [sanitizeDependency(value)]);
|
|
14
16
|
return ref.current;
|
|
15
17
|
}
|
|
16
18
|
exports.default = usePrevious;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePrevious.js","sourceRoot":"/","sources":["hooks/usePrevious.ts"],"names":[],"mappings":";;AAAA,+BAAyC;
|
|
1
|
+
{"version":3,"file":"usePrevious.js","sourceRoot":"/","sources":["hooks/usePrevious.ts"],"names":[],"mappings":";;AAAA,+BAAyC;AAczC;;;;;GAKG;AACH,SAAwB,WAAW,CAAI,KAAQ,EAAE,EAAgD;QAAhD,qBAA8C,EAAE,KAAA,EAA9C,0BAA2B,EAA3B,kBAAkB,mBAAG,UAAA,CAAC,IAAI,OAAA,CAAC,EAAD,CAAC,KAAA;IAC5E,IAAM,GAAG,GAAG,IAAA,cAAM,GAAK,CAAA;IAEvB,IAAA,iBAAS,EAAC;QACR,GAAG,CAAC,OAAO,GAAG,KAAK,CAAA;IACrB,CAAC,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAE/B,OAAO,GAAG,CAAC,OAAO,CAAA;AACpB,CAAC;AARD,8BAQC","sourcesContent":["import { useEffect, useRef } from 'react'\n\ntype Options<T> = {\n /**\n * Function to transform the dependency value in the dependency list, useful\n * if the value is a reference.\n *\n * @param dependency The dependency value.\n *\n * @returns The transformed value to be used as the dependency value instead.\n */\n sanitizeDependency?: (dependency: T) => any\n}\n\n/**\n * Returns the previous value of a value.\n *\n * @param value The value.\n * @param options See {@link Options}.\n */\nexport default function usePrevious<T>(value: T, { sanitizeDependency = t => t }: Options<T> = {}): T | undefined {\n const ref = useRef<T>()\n\n useEffect(() => {\n ref.current = value\n }, [sanitizeDependency(value)])\n\n return ref.current\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "etudes",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "A study of headless React components",
|
|
5
5
|
"main": "lib",
|
|
6
6
|
"scripts": {
|
|
@@ -29,29 +29,29 @@
|
|
|
29
29
|
"lib"
|
|
30
30
|
],
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@babel/core": "^7.22.
|
|
32
|
+
"@babel/core": "^7.22.20",
|
|
33
33
|
"@babel/plugin-transform-runtime": "^7.22.15",
|
|
34
|
-
"@babel/preset-env": "^7.22.
|
|
34
|
+
"@babel/preset-env": "^7.22.20",
|
|
35
35
|
"@babel/preset-react": "^7.22.15",
|
|
36
36
|
"@babel/preset-typescript": "^7.22.15",
|
|
37
37
|
"@types/debug": "^4.1.8",
|
|
38
|
-
"@types/html-webpack-plugin": "^3.2.
|
|
38
|
+
"@types/html-webpack-plugin": "^3.2.7",
|
|
39
39
|
"@types/node-polyglot": "^2.4.2",
|
|
40
|
-
"@types/react": "^18.2.
|
|
40
|
+
"@types/react": "^18.2.22",
|
|
41
41
|
"@types/react-dom": "^18.2.7",
|
|
42
42
|
"@types/react-transition-group": "^4.4.6",
|
|
43
43
|
"@types/styled-components": "^5.1.27",
|
|
44
44
|
"@types/webpack": "^5.28.2",
|
|
45
45
|
"@types/webpack-env": "^1.18.1",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "^6.7.
|
|
47
|
-
"@typescript-eslint/parser": "^6.7.
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
|
47
|
+
"@typescript-eslint/parser": "^6.7.2",
|
|
48
48
|
"babel-loader": "^9.1.3",
|
|
49
49
|
"babel-plugin-styled-components": "^2.1.4",
|
|
50
50
|
"concurrently": "^8.2.1",
|
|
51
51
|
"cross-env": "^7.0.3",
|
|
52
52
|
"debug": "^4.3.4",
|
|
53
53
|
"eslint": "^8.49.0",
|
|
54
|
-
"fast-xml-parser": "^4.
|
|
54
|
+
"fast-xml-parser": "^4.3.0",
|
|
55
55
|
"html-webpack-plugin": "^5.5.3",
|
|
56
56
|
"react": "^18.2.0",
|
|
57
57
|
"react-dom": "^18.2.0",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"classnames": "^2.3.2",
|
|
71
71
|
"fast-deep-equal": "^3.1.3",
|
|
72
|
-
"interactjs": "^1.10.
|
|
72
|
+
"interactjs": "^1.10.19",
|
|
73
73
|
"react-transition-group": "^4.4.5",
|
|
74
74
|
"resize-observer-polyfill": "^1.5.1",
|
|
75
75
|
"spase": "^7.0.0"
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"react": "^18.2.0"
|
|
79
79
|
},
|
|
80
80
|
"optionalDependencies": {
|
|
81
|
-
"fast-xml-parser": "^4.
|
|
81
|
+
"fast-xml-parser": "^4.3.0",
|
|
82
82
|
"react-router": "^6.16.0",
|
|
83
83
|
"react-router-dom": "^6.16.0"
|
|
84
84
|
}
|