@vuu-ui/vuu-utils 2.1.19-beta.1 → 2.1.19-beta.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/package.json +8 -9
- package/src/Clock.js +43 -0
- package/src/PageVisibilityObserver.js +42 -0
- package/src/ScaledDecimal.js +32 -0
- package/src/ShellContext.js +5 -0
- package/src/ThemeProvider.js +56 -0
- package/src/array-utils.js +51 -0
- package/src/box-utils.js +51 -0
- package/src/broadcast-channel.js +0 -0
- package/src/column-utils.js +790 -0
- package/src/common-types.js +11 -0
- package/src/component-registry.js +83 -0
- package/src/context-definitions/DataContext.js +15 -0
- package/src/context-definitions/DataProvider.js +13 -0
- package/src/context-definitions/DataSourceProvider.js +18 -0
- package/src/context-definitions/WorkspaceContext.js +14 -0
- package/src/cookie-utils.js +15 -0
- package/src/css-utils.js +5 -0
- package/src/data-editing/DataEditingProvider.js +13 -0
- package/src/data-editing/EditButtons.js +32 -0
- package/src/data-editing/EditModeProvider.js +18 -0
- package/src/data-editing/EditSession.js +149 -0
- package/src/data-editing/edit-utils.js +37 -0
- package/src/data-editing/useEditableTable.js +76 -0
- package/src/data-utils.js +55 -0
- package/src/datasource/BaseDataSource.js +233 -0
- package/src/datasource/datasource-action-utils.js +6 -0
- package/src/datasource/datasource-filter-utils.js +27 -0
- package/src/datasource/datasource-utils.js +148 -0
- package/src/date/date-utils.js +80 -0
- package/src/date/dateTimePattern.js +17 -0
- package/src/date/formatter.js +101 -0
- package/src/date/index.js +4 -0
- package/src/date/types.js +27 -0
- package/src/debug-utils.js +25 -0
- package/src/event-emitter.js +78 -0
- package/src/feature-utils.js +86 -0
- package/src/filters/filter-utils.js +136 -0
- package/src/filters/filterAsQuery.js +70 -0
- package/src/filters/index.js +2 -0
- package/src/form-utils.js +69 -0
- package/src/formatting-utils.js +42 -0
- package/src/getUniqueId.js +2 -0
- package/src/group-utils.js +16 -0
- package/src/html-utils.js +108 -0
- package/src/index.js +77 -0
- package/src/input-utils.js +3 -0
- package/src/invariant.js +9 -0
- package/src/itemToString.js +9 -0
- package/src/json-types.js +0 -0
- package/src/json-utils.js +108 -0
- package/src/keyboard-utils.js +14 -0
- package/src/keyset.js +57 -0
- package/src/layout-types.js +0 -0
- package/src/list-utils.js +5 -0
- package/src/local-storage-utils.js +23 -0
- package/src/logging-utils.js +52 -0
- package/src/module-utils.js +2 -0
- package/src/nanoid/index.js +13 -0
- package/src/perf-utils.js +28 -0
- package/src/promise-utils.js +26 -0
- package/src/protocol-message-utils.js +68 -0
- package/src/range-utils.js +109 -0
- package/src/react-utils.js +64 -0
- package/src/round-decimal.js +83 -0
- package/src/row-utils.js +43 -0
- package/src/selection-utils.js +25 -0
- package/src/shell-layout-types.js +9 -0
- package/src/sort-utils.js +75 -0
- package/src/table-schema-utils.js +11 -0
- package/src/text-utils.js +13 -0
- package/src/theme-utils.js +21 -0
- package/src/tree-types.js +0 -0
- package/src/tree-utils.js +96 -0
- package/src/ts-utils.js +6 -0
- package/src/typeahead-utils.js +4 -0
- package/src/url-utils.js +12 -0
- package/src/useId.js +6 -0
- package/src/useLayoutEffectSkipFirst.js +9 -0
- package/src/useResizeObserver.js +122 -0
- package/src/useStateRef.js +21 -0
- package/src/user-types.js +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Children, isValidElement, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
const EMPTY_ARRAY = [];
|
|
3
|
+
const asReactElements = (children)=>{
|
|
4
|
+
const isArray = Array.isArray(children);
|
|
5
|
+
const count = isArray ? children.length : Children.count(children);
|
|
6
|
+
if (isArray && children.every(isValidElement)) return children;
|
|
7
|
+
if (1 === count && !isArray && isValidElement(children)) return [
|
|
8
|
+
children
|
|
9
|
+
];
|
|
10
|
+
if (count > 1) return children;
|
|
11
|
+
return EMPTY_ARRAY;
|
|
12
|
+
};
|
|
13
|
+
const useIsMounted = (id = "")=>{
|
|
14
|
+
const isMountedRef = useRef(false);
|
|
15
|
+
useEffect(()=>{
|
|
16
|
+
console.log(`is MOUNTED ${id}`);
|
|
17
|
+
isMountedRef.current = true;
|
|
18
|
+
return ()=>{
|
|
19
|
+
console.log(`is UNMOUNTED ${id}`);
|
|
20
|
+
isMountedRef.current = false;
|
|
21
|
+
};
|
|
22
|
+
}, [
|
|
23
|
+
id
|
|
24
|
+
]);
|
|
25
|
+
return isMountedRef;
|
|
26
|
+
};
|
|
27
|
+
const isSimpleStateValue = (arg)=>"function" != typeof arg;
|
|
28
|
+
const createSyntheticEvent = (event)=>{
|
|
29
|
+
let isDefaultPrevented = false;
|
|
30
|
+
let isPropagationStopped = false;
|
|
31
|
+
const preventDefault = ()=>{
|
|
32
|
+
isDefaultPrevented = true;
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
};
|
|
35
|
+
const stopPropagation = ()=>{
|
|
36
|
+
isPropagationStopped = true;
|
|
37
|
+
event.stopPropagation();
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
nativeEvent: event,
|
|
41
|
+
currentTarget: event.currentTarget,
|
|
42
|
+
target: event.target,
|
|
43
|
+
bubbles: event.bubbles,
|
|
44
|
+
cancelable: event.cancelable,
|
|
45
|
+
defaultPrevented: event.defaultPrevented,
|
|
46
|
+
eventPhase: event.eventPhase,
|
|
47
|
+
isTrusted: event.isTrusted,
|
|
48
|
+
preventDefault,
|
|
49
|
+
isDefaultPrevented: ()=>isDefaultPrevented,
|
|
50
|
+
stopPropagation,
|
|
51
|
+
isPropagationStopped: ()=>isPropagationStopped,
|
|
52
|
+
persist: ()=>void 0,
|
|
53
|
+
timeStamp: event.timeStamp,
|
|
54
|
+
type: event.type
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
const useStableReference = (value)=>{
|
|
58
|
+
const referenceToProp = useRef(value);
|
|
59
|
+
useMemo(()=>referenceToProp.current = value, [
|
|
60
|
+
value
|
|
61
|
+
]);
|
|
62
|
+
return referenceToProp;
|
|
63
|
+
};
|
|
64
|
+
export { asReactElements, createSyntheticEvent, isSimpleStateValue, useIsMounted, useStableReference };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const PUNCTUATION_STR = String.fromCharCode(8200);
|
|
2
|
+
const DIGIT_STR = String.fromCharCode(8199);
|
|
3
|
+
const DECIMALS_AUTO = -1;
|
|
4
|
+
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER.toString();
|
|
5
|
+
const MAX_INTEGER_DIGITS = MAX_SAFE_INTEGER.length;
|
|
6
|
+
const exceedsMaxSafeInteger = (value)=>value.length > MAX_INTEGER_DIGITS || value.length === MAX_INTEGER_DIGITS && value > MAX_SAFE_INTEGER;
|
|
7
|
+
const Space = {
|
|
8
|
+
DIGIT: DIGIT_STR,
|
|
9
|
+
TWO_DIGITS: DIGIT_STR + DIGIT_STR,
|
|
10
|
+
THREE_DIGITS: DIGIT_STR + DIGIT_STR + DIGIT_STR,
|
|
11
|
+
FULL_PADDING: [
|
|
12
|
+
null,
|
|
13
|
+
PUNCTUATION_STR + DIGIT_STR,
|
|
14
|
+
PUNCTUATION_STR + DIGIT_STR + DIGIT_STR,
|
|
15
|
+
PUNCTUATION_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR,
|
|
16
|
+
PUNCTUATION_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
const Zero = {
|
|
20
|
+
DIGIT: "0",
|
|
21
|
+
TWO_DIGITS: "00",
|
|
22
|
+
THREE_DIGITS: "000",
|
|
23
|
+
FULL_PADDING: [
|
|
24
|
+
null,
|
|
25
|
+
"0",
|
|
26
|
+
"00",
|
|
27
|
+
"000",
|
|
28
|
+
"0000"
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
function padLeft(value, maxLength = 6) {
|
|
32
|
+
return (LEADING_FILL + value).slice(-maxLength);
|
|
33
|
+
}
|
|
34
|
+
const LEADING_FILL = DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR;
|
|
35
|
+
const Align = {
|
|
36
|
+
Right: "right",
|
|
37
|
+
Center: "center",
|
|
38
|
+
Left: "left"
|
|
39
|
+
};
|
|
40
|
+
function pad(n, dp, Pad) {
|
|
41
|
+
let len = n.length;
|
|
42
|
+
const diff = dp - len;
|
|
43
|
+
if (diff > 0) {
|
|
44
|
+
if (1 === diff) n += Pad.DIGIT;
|
|
45
|
+
else if (2 === diff) n += Pad.TWO_DIGITS;
|
|
46
|
+
else if (3 === diff) n += Pad.THREE_DIGITS;
|
|
47
|
+
} else {
|
|
48
|
+
if (diff < 0) {
|
|
49
|
+
n = n.slice(0, dp);
|
|
50
|
+
len = dp;
|
|
51
|
+
}
|
|
52
|
+
if (Pad === Space && "0" === n.charAt(len - 1)) {
|
|
53
|
+
n = n.replace(/0+$/, "");
|
|
54
|
+
return pad(n, dp, Pad);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return n;
|
|
58
|
+
}
|
|
59
|
+
function roundDecimal(value, align = Align.Right, decimals = 4, zeroPad, alignOnDecimals, useLocaleString = true, roundingRule = "round") {
|
|
60
|
+
if (void 0 === value || "number" != typeof value || isNaN(value)) return "";
|
|
61
|
+
let integral;
|
|
62
|
+
let fraction;
|
|
63
|
+
let Pad;
|
|
64
|
+
const [part1, part2 = ""] = value.toString().split(".");
|
|
65
|
+
const actualDecimals = part2.length;
|
|
66
|
+
integral = "-0" === part1 ? "-0" : useLocaleString ? parseFloat(part1).toLocaleString() : parseFloat(part1).toString();
|
|
67
|
+
if (align === Align.Left && alignOnDecimals) integral = padLeft(integral);
|
|
68
|
+
fraction = decimals === DECIMALS_AUTO || actualDecimals === decimals ? part2 : actualDecimals > decimals ? "round" === roundingRule ? parseFloat("0." + part2).toFixed(decimals).slice(2) : part2.slice(0, decimals) : (Pad = zeroPad ? Zero : alignOnDecimals && align !== Align.Left ? Space : null) ? 0 === actualDecimals ? Pad.FULL_PADDING[decimals] ?? "" : pad(part2, decimals, Pad) : part2;
|
|
69
|
+
return integral + (fraction ? "." + fraction : "");
|
|
70
|
+
}
|
|
71
|
+
function roundScaledDecimal(value, align = Align.Right, decimals = 4, zeroPad, alignOnDecimals, useLocaleString = true, roundingRule = "round") {
|
|
72
|
+
let integral;
|
|
73
|
+
let fraction;
|
|
74
|
+
let Pad;
|
|
75
|
+
if ("" === value) return "";
|
|
76
|
+
const [part1, part2 = ""] = value.split(".");
|
|
77
|
+
const actualDecimals = part2.length;
|
|
78
|
+
integral = "" === part1 ? "0" : "-0" === part1 ? "-0" : useLocaleString ? exceedsMaxSafeInteger(value) ? BigInt(part1).toLocaleString() : parseFloat(part1).toLocaleString() : part1;
|
|
79
|
+
if (align === Align.Left && alignOnDecimals) integral = padLeft(integral);
|
|
80
|
+
fraction = decimals === DECIMALS_AUTO || actualDecimals === decimals ? part2 : actualDecimals > decimals ? "round" === roundingRule ? parseFloat("0." + part2).toFixed(decimals).slice(2) : part2.slice(0, decimals) : (Pad = zeroPad ? Zero : alignOnDecimals && align !== Align.Left ? Space : null) ? 0 === actualDecimals ? Pad.FULL_PADDING[decimals] ?? "" : pad(part2, decimals, Pad) : part2;
|
|
81
|
+
return integral + (fraction ? "." + fraction : "");
|
|
82
|
+
}
|
|
83
|
+
export { exceedsMaxSafeInteger, roundDecimal, roundScaledDecimal };
|
package/src/row-utils.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { metadataKeys } from "./column-utils.js";
|
|
2
|
+
const { IS_LEAF: IS_LEAF, KEY: KEY, IDX: IDX, SELECTED: SELECTED } = metadataKeys;
|
|
3
|
+
const actualRowPositioning = (rowHeight)=>[
|
|
4
|
+
(dataRow)=>dataRow.index * rowHeight,
|
|
5
|
+
(position)=>Math.floor(position / rowHeight),
|
|
6
|
+
false
|
|
7
|
+
];
|
|
8
|
+
const virtualRowPositioning = (rowHeight, virtualisedExtent, pctScrollTop)=>[
|
|
9
|
+
(dataRow, offset = 0)=>{
|
|
10
|
+
const rowOffset = pctScrollTop.current * virtualisedExtent;
|
|
11
|
+
return (dataRow.index - offset) * rowHeight - rowOffset;
|
|
12
|
+
},
|
|
13
|
+
(position)=>{
|
|
14
|
+
const rowOffset = pctScrollTop.current * virtualisedExtent;
|
|
15
|
+
return Math.round((position + rowOffset) / rowHeight);
|
|
16
|
+
},
|
|
17
|
+
true
|
|
18
|
+
];
|
|
19
|
+
const asDataSourceRowObject = (row, columnMap)=>{
|
|
20
|
+
const { [IS_LEAF]: isLeaf, [KEY]: key, [IDX]: index } = row;
|
|
21
|
+
const rowObject = {
|
|
22
|
+
key,
|
|
23
|
+
index,
|
|
24
|
+
isGroupRow: !isLeaf,
|
|
25
|
+
isSelected: 0 !== row[SELECTED],
|
|
26
|
+
data: {}
|
|
27
|
+
};
|
|
28
|
+
for (const [colName, colIdx] of Object.entries(columnMap))rowObject.data[colName] = row[colIdx];
|
|
29
|
+
return rowObject;
|
|
30
|
+
};
|
|
31
|
+
const vuuRowToDataSourceRow = ({ rowIndex, rowKey, sel: isSelected = 0, ts, data }, keys)=>[
|
|
32
|
+
rowIndex,
|
|
33
|
+
keys.keyFor(rowIndex),
|
|
34
|
+
true,
|
|
35
|
+
false,
|
|
36
|
+
0,
|
|
37
|
+
0,
|
|
38
|
+
rowKey,
|
|
39
|
+
isSelected,
|
|
40
|
+
ts,
|
|
41
|
+
false
|
|
42
|
+
].concat(data);
|
|
43
|
+
export { actualRowPositioning, asDataSourceRowObject, virtualRowPositioning, vuuRowToDataSourceRow };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const deselectItem = (selectionModel, rowKey, rangeSelect, preserveExistingSelection = false)=>({
|
|
2
|
+
preserveExistingSelection,
|
|
3
|
+
rowKey,
|
|
4
|
+
type: "DESELECT_ROW"
|
|
5
|
+
});
|
|
6
|
+
const selectItem = (selectionModel, rowKey, rangeSelect, preserveExistingSelection = false, activeRowKey)=>{
|
|
7
|
+
const singleSelect = "single" === selectionModel || "single-no-deselect" === selectionModel;
|
|
8
|
+
const actsLikeSingleSelect = singleSelect || void 0 === activeRowKey;
|
|
9
|
+
if ("none" === selectionModel) return;
|
|
10
|
+
if (actsLikeSingleSelect) {
|
|
11
|
+
const preserveSelection = singleSelect ? false : preserveExistingSelection;
|
|
12
|
+
return {
|
|
13
|
+
preserveExistingSelection: preserveSelection,
|
|
14
|
+
rowKey,
|
|
15
|
+
type: "SELECT_ROW"
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (rangeSelect) return {
|
|
19
|
+
preserveExistingSelection,
|
|
20
|
+
fromRowKey: rowKey,
|
|
21
|
+
toRowKey: activeRowKey,
|
|
22
|
+
type: "SELECT_ROW_RANGE"
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export { deselectItem, selectItem };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const VuuShellLocation = {
|
|
2
|
+
ContextPanel: "context-panel",
|
|
3
|
+
MultiWorkspaceContainer: "vuu-multi-workspace-container",
|
|
4
|
+
SidePanel: "vuu-side-panel",
|
|
5
|
+
SideToolbar: "vuu-side-toolbar",
|
|
6
|
+
Workspace: "vuu-workspace",
|
|
7
|
+
WorkspaceContainer: "vuu-workspace-container"
|
|
8
|
+
};
|
|
9
|
+
export { VuuShellLocation };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const cycleSortType = (sortType)=>"A" === sortType ? "D" : "D" === sortType ? void 0 : "A";
|
|
2
|
+
const NO_SORT = {
|
|
3
|
+
sortDefs: []
|
|
4
|
+
};
|
|
5
|
+
const toggleOrApplySort = ({ sortDefs }, { name: column }, extendSort = false, sortType)=>{
|
|
6
|
+
if (extendSort) {
|
|
7
|
+
const existingDef = sortDefs.find((sortDef)=>sortDef.column === column);
|
|
8
|
+
if (existingDef) return {
|
|
9
|
+
sortDefs: sortDefs.map((sortDef)=>sortDef.column === column ? {
|
|
10
|
+
column,
|
|
11
|
+
sortType: "A" === sortDef.sortType ? "D" : "A"
|
|
12
|
+
} : sortDef)
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
sortDefs: sortDefs.concat({
|
|
16
|
+
column,
|
|
17
|
+
sortType: sortType ?? "A"
|
|
18
|
+
})
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const newSortType = "string" == typeof sortType ? sortType : 1 === sortDefs.length && sortDefs[0].column === column ? cycleSortType(sortDefs[0].sortType) : "A";
|
|
22
|
+
return newSortType ? {
|
|
23
|
+
sortDefs: [
|
|
24
|
+
{
|
|
25
|
+
column,
|
|
26
|
+
sortType: newSortType
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
} : NO_SORT;
|
|
30
|
+
};
|
|
31
|
+
const setSortColumn = ({ sortDefs }, column, sortType)=>{
|
|
32
|
+
if (void 0 === sortType) {
|
|
33
|
+
const columnSort = sortDefs.find((item)=>item.column === column.name);
|
|
34
|
+
if (columnSort) return {
|
|
35
|
+
sortDefs: [
|
|
36
|
+
{
|
|
37
|
+
column: column.name,
|
|
38
|
+
sortType: "A" === columnSort.sortType ? "D" : "A"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
sortDefs: [
|
|
45
|
+
{
|
|
46
|
+
column: column.name,
|
|
47
|
+
sortType: sortType ?? "A"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const addSortColumn = ({ sortDefs }, column, sortType = "A")=>{
|
|
53
|
+
const sortEntry = {
|
|
54
|
+
column: column.name,
|
|
55
|
+
sortType
|
|
56
|
+
};
|
|
57
|
+
if (sortDefs.length > 0) return {
|
|
58
|
+
sortDefs: sortDefs.concat(sortEntry)
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
sortDefs: [
|
|
62
|
+
sortEntry
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
const getSortStatus = (columnName, vuuSort)=>{
|
|
67
|
+
if (void 0 === vuuSort || 0 === vuuSort.sortDefs.length) return "no-sort";
|
|
68
|
+
{
|
|
69
|
+
const sortDef = vuuSort.sortDefs.find((sd)=>sd.column === columnName);
|
|
70
|
+
if (!sortDef) return "sort-other-column";
|
|
71
|
+
if (1 === vuuSort.sortDefs.length) return "A" === sortDef.sortType ? "single-sort-asc" : "single-sort-desc";
|
|
72
|
+
return "A" === sortDef.sortType ? "multi-sort-includes-column-asc" : "multi-sort-includes-column-desc";
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
export { addSortColumn, getSortStatus, setSortColumn, toggleOrApplySort };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const lastWord = (text)=>{
|
|
2
|
+
const trimmedText = text.trim();
|
|
3
|
+
const pos = trimmedText.lastIndexOf(" ");
|
|
4
|
+
if (-1 === pos) return trimmedText;
|
|
5
|
+
return trimmedText.slice(pos + 1);
|
|
6
|
+
};
|
|
7
|
+
const capitalize = (text)=>0 === text.length ? "" : text[0].toUpperCase() + text.slice(1);
|
|
8
|
+
const regexp_worfify = /(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])/;
|
|
9
|
+
const wordify = (text)=>{
|
|
10
|
+
const [firstWord, ...rest] = text.split(regexp_worfify);
|
|
11
|
+
return `${capitalize(firstWord)} ${rest.join(" ")}`;
|
|
12
|
+
};
|
|
13
|
+
export { lastWord, wordify };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
const checkCssToken = (tokenName)=>new Promise((resolve)=>{
|
|
3
|
+
requestAnimationFrame(()=>{
|
|
4
|
+
const saltSpacing100 = getComputedStyle(document.documentElement).getPropertyValue(tokenName);
|
|
5
|
+
resolve("" !== saltSpacing100);
|
|
6
|
+
});
|
|
7
|
+
});
|
|
8
|
+
const ThemeLoadChecker = ({ children, cssToken = "--salt-spacing-100", theme })=>{
|
|
9
|
+
const [ready, setReady] = useState(false);
|
|
10
|
+
useMemo(async ()=>{
|
|
11
|
+
let ready = await checkCssToken(cssToken);
|
|
12
|
+
while(!ready)ready = await checkCssToken(cssToken);
|
|
13
|
+
setReady(true);
|
|
14
|
+
}, [
|
|
15
|
+
cssToken
|
|
16
|
+
]);
|
|
17
|
+
if ("no-theme" === theme) return children;
|
|
18
|
+
if (false === ready) return null;
|
|
19
|
+
return children;
|
|
20
|
+
};
|
|
21
|
+
export { ThemeLoadChecker };
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { metadataKeys } from "./column-utils.js";
|
|
2
|
+
const { COUNT: COUNT, DEPTH: DEPTH, IDX: IDX, KEY: KEY } = metadataKeys;
|
|
3
|
+
const timestamp = 0;
|
|
4
|
+
const isNew = false;
|
|
5
|
+
const treeToDataSourceRows = (treeSourceNodes, iconProvider)=>{
|
|
6
|
+
const columns = [];
|
|
7
|
+
columns.push({
|
|
8
|
+
hidden: true,
|
|
9
|
+
name: "nodeData",
|
|
10
|
+
type: "json"
|
|
11
|
+
}, {
|
|
12
|
+
getIcon: iconProvider?.getIcon,
|
|
13
|
+
name: "Level 1",
|
|
14
|
+
type: "string"
|
|
15
|
+
}, {
|
|
16
|
+
getIcon: iconProvider?.getIcon,
|
|
17
|
+
name: "Level 2",
|
|
18
|
+
type: "string"
|
|
19
|
+
});
|
|
20
|
+
const rows = [];
|
|
21
|
+
addChildValues(rows, treeSourceNodes, columns, iconProvider);
|
|
22
|
+
return [
|
|
23
|
+
columns,
|
|
24
|
+
rows
|
|
25
|
+
];
|
|
26
|
+
};
|
|
27
|
+
const addChildValues = (rows, treeSourceNodes, cols, iconProvider, index = {
|
|
28
|
+
value: 0
|
|
29
|
+
}, keyBase = "$root", depth = 1)=>{
|
|
30
|
+
let leafCount = 0;
|
|
31
|
+
let rowCount = 0;
|
|
32
|
+
if (depth === cols.length - 1) cols.push({
|
|
33
|
+
getIcon: iconProvider?.getIcon,
|
|
34
|
+
name: `Level ${cols.length}`,
|
|
35
|
+
type: "string"
|
|
36
|
+
});
|
|
37
|
+
for(let i = 0; i < treeSourceNodes.length; i++, index.value += 1){
|
|
38
|
+
const { childNodes, icon, label, nodeData } = treeSourceNodes[i];
|
|
39
|
+
const blanks = Array(depth - 1).fill("");
|
|
40
|
+
const fullKey = `${keyBase}|${label}`;
|
|
41
|
+
const row = [
|
|
42
|
+
index.value,
|
|
43
|
+
index.value,
|
|
44
|
+
false,
|
|
45
|
+
false,
|
|
46
|
+
depth,
|
|
47
|
+
0,
|
|
48
|
+
fullKey,
|
|
49
|
+
0,
|
|
50
|
+
timestamp,
|
|
51
|
+
isNew,
|
|
52
|
+
nodeData,
|
|
53
|
+
...blanks,
|
|
54
|
+
label
|
|
55
|
+
];
|
|
56
|
+
if (icon) iconProvider?.setIcon(fullKey, icon);
|
|
57
|
+
rows.push(row);
|
|
58
|
+
rowCount += 1;
|
|
59
|
+
if (childNodes && childNodes.length > 0) {
|
|
60
|
+
const [nestedLeafCount, nestedRowCount] = addChildValues(rows, childNodes, cols, iconProvider, {
|
|
61
|
+
value: index.value + 1
|
|
62
|
+
}, fullKey, depth + 1);
|
|
63
|
+
row[COUNT] = nestedLeafCount;
|
|
64
|
+
leafCount += nestedLeafCount;
|
|
65
|
+
rowCount += nestedRowCount;
|
|
66
|
+
index.value += nestedRowCount;
|
|
67
|
+
} else leafCount += 1;
|
|
68
|
+
}
|
|
69
|
+
return [
|
|
70
|
+
leafCount,
|
|
71
|
+
rowCount
|
|
72
|
+
];
|
|
73
|
+
};
|
|
74
|
+
const lastPathSegment = (path, separator = "/")=>{
|
|
75
|
+
const root = path.endsWith(separator) ? path.slice(0, -1) : path;
|
|
76
|
+
return root.slice(root.lastIndexOf(separator) + 1);
|
|
77
|
+
};
|
|
78
|
+
const dropLastPathSegment = (path, separator = "/")=>path.slice(0, path.lastIndexOf(separator));
|
|
79
|
+
const getParentRow = (rows, row)=>{
|
|
80
|
+
const { [IDX]: idx, [DEPTH]: depth } = row;
|
|
81
|
+
for(let i = idx - 1; i >= 0; i--){
|
|
82
|
+
const nextRow = rows[i];
|
|
83
|
+
if (nextRow[DEPTH] === depth - 1) return nextRow;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const rowsAreSiblings = (key1, key2)=>dropLastPathSegment(key1, "|") === dropLastPathSegment(key2, "|");
|
|
87
|
+
const missingAncestor = (row, previousRow)=>{
|
|
88
|
+
if (previousRow) {
|
|
89
|
+
const prevKey = previousRow[KEY];
|
|
90
|
+
const key = row[KEY];
|
|
91
|
+
if (key.startsWith(prevKey)) ;
|
|
92
|
+
else if (!rowsAreSiblings(prevKey, key)) return true;
|
|
93
|
+
} else if (row[DEPTH] > 1) return true;
|
|
94
|
+
return false;
|
|
95
|
+
};
|
|
96
|
+
export { dropLastPathSegment, getParentRow, lastPathSegment, missingAncestor, treeToDataSourceRows };
|
package/src/ts-utils.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
function isNotNullOrUndefined(value) {
|
|
2
|
+
return null != value;
|
|
3
|
+
}
|
|
4
|
+
const isObject = (o)=>"object" == typeof o && null !== o;
|
|
5
|
+
const elementImplementsJSONSerialization = (element)=>"function" == typeof element.type.toJSON;
|
|
6
|
+
export { elementImplementsJSONSerialization, isNotNullOrUndefined, isObject };
|
package/src/url-utils.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function getUrlParameter(paramName, defaultValue) {
|
|
2
|
+
const url = new URL(document.location.href);
|
|
3
|
+
const parameter = url.searchParams.get(paramName);
|
|
4
|
+
if (parameter) return parameter;
|
|
5
|
+
const hashParams = url.hash;
|
|
6
|
+
const regex = new RegExp(`${paramName}=([a-zA-Z]*)`);
|
|
7
|
+
const result = regex.exec(hashParams);
|
|
8
|
+
if (result) return result[1];
|
|
9
|
+
return defaultValue;
|
|
10
|
+
}
|
|
11
|
+
const hasUrlParameter = (paramName)=>new URL(document.location.href).searchParams.has(paramName);
|
|
12
|
+
export { getUrlParameter, hasUrlParameter };
|
package/src/useId.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useLayoutEffect, useRef } from "react";
|
|
2
|
+
const useLayoutEffectSkipFirst = (func, deps)=>{
|
|
3
|
+
const goodToGo = useRef(false);
|
|
4
|
+
useLayoutEffect(()=>{
|
|
5
|
+
if (goodToGo.current) func();
|
|
6
|
+
else goodToGo.current = true;
|
|
7
|
+
}, deps);
|
|
8
|
+
};
|
|
9
|
+
export { useLayoutEffectSkipFirst };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
const WidthHeight = [
|
|
3
|
+
"height",
|
|
4
|
+
"width"
|
|
5
|
+
];
|
|
6
|
+
const WidthOnly = [
|
|
7
|
+
"width"
|
|
8
|
+
];
|
|
9
|
+
const observedMap = new Map();
|
|
10
|
+
const getTargetSize = (element, size, dimension)=>{
|
|
11
|
+
switch(dimension){
|
|
12
|
+
case "height":
|
|
13
|
+
return size.height;
|
|
14
|
+
case "clientHeight":
|
|
15
|
+
return Math.floor(element.clientHeight);
|
|
16
|
+
case "clientWidth":
|
|
17
|
+
return Math.floor(element.clientWidth);
|
|
18
|
+
case "contentHeight":
|
|
19
|
+
return size.contentHeight;
|
|
20
|
+
case "contentWidth":
|
|
21
|
+
return size.contentWidth;
|
|
22
|
+
case "scrollHeight":
|
|
23
|
+
return Math.ceil(Math.floor(element.scrollHeight));
|
|
24
|
+
case "scrollWidth":
|
|
25
|
+
return Math.ceil(Math.floor(element.scrollWidth));
|
|
26
|
+
case "width":
|
|
27
|
+
return size.width;
|
|
28
|
+
default:
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const resizeObserver = new ResizeObserver((entries)=>{
|
|
33
|
+
for (const entry of entries){
|
|
34
|
+
const { target, borderBoxSize, contentBoxSize } = entry;
|
|
35
|
+
const observedTarget = observedMap.get(target);
|
|
36
|
+
if (observedTarget) {
|
|
37
|
+
const [{ blockSize: height, inlineSize: width }] = borderBoxSize;
|
|
38
|
+
const [{ blockSize: contentHeight, inlineSize: contentWidth }] = contentBoxSize;
|
|
39
|
+
const { onResize, measurements } = observedTarget;
|
|
40
|
+
let sizeChanged = false;
|
|
41
|
+
for (const [dimension, size] of Object.entries(measurements)){
|
|
42
|
+
const newSize = getTargetSize(target, {
|
|
43
|
+
height,
|
|
44
|
+
width,
|
|
45
|
+
contentHeight,
|
|
46
|
+
contentWidth
|
|
47
|
+
}, dimension);
|
|
48
|
+
if (newSize !== size) {
|
|
49
|
+
sizeChanged = true;
|
|
50
|
+
measurements[dimension] = newSize;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (sizeChanged) onResize && onResize(measurements);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false) {
|
|
58
|
+
const dimensionsRef = useRef(dimensions);
|
|
59
|
+
const measure = useCallback((target)=>{
|
|
60
|
+
const { width, height } = target.getBoundingClientRect();
|
|
61
|
+
const { clientWidth: contentWidth, clientHeight: contentHeight } = target;
|
|
62
|
+
const flooredHeight = Math.floor(height);
|
|
63
|
+
const flooredWidth = Math.floor(width);
|
|
64
|
+
return dimensionsRef.current.reduce((map, dim)=>{
|
|
65
|
+
map[dim] = getTargetSize(target, {
|
|
66
|
+
width: flooredWidth,
|
|
67
|
+
height: flooredHeight,
|
|
68
|
+
contentHeight,
|
|
69
|
+
contentWidth
|
|
70
|
+
}, dim);
|
|
71
|
+
return map;
|
|
72
|
+
}, {});
|
|
73
|
+
}, []);
|
|
74
|
+
useEffect(()=>{
|
|
75
|
+
const target = ref.current;
|
|
76
|
+
async function registerObserver() {
|
|
77
|
+
observedMap.set(target, {
|
|
78
|
+
measurements: {}
|
|
79
|
+
});
|
|
80
|
+
const observedTarget = observedMap.get(target);
|
|
81
|
+
if (observedTarget) {
|
|
82
|
+
const measurements = measure(target);
|
|
83
|
+
observedTarget.measurements = measurements;
|
|
84
|
+
resizeObserver.observe(target);
|
|
85
|
+
if (reportInitialSize) onResize(measurements);
|
|
86
|
+
} else console.log("%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation", "font-weight:bold; color:red;");
|
|
87
|
+
}
|
|
88
|
+
if (target) {
|
|
89
|
+
if (observedMap.has(target)) console.log("useResizeObserver attemping to observe same element twice", {
|
|
90
|
+
target
|
|
91
|
+
});
|
|
92
|
+
registerObserver();
|
|
93
|
+
}
|
|
94
|
+
return ()=>{
|
|
95
|
+
if (target && observedMap.has(target)) {
|
|
96
|
+
resizeObserver.unobserve(target);
|
|
97
|
+
observedMap.delete(target);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}, [
|
|
101
|
+
measure,
|
|
102
|
+
ref
|
|
103
|
+
]);
|
|
104
|
+
useEffect(()=>{
|
|
105
|
+
const target = ref.current;
|
|
106
|
+
const record = observedMap.get(target);
|
|
107
|
+
if (record) {
|
|
108
|
+
if (dimensionsRef.current !== dimensions) {
|
|
109
|
+
dimensionsRef.current = dimensions;
|
|
110
|
+
const measurements = measure(target);
|
|
111
|
+
record.measurements = measurements;
|
|
112
|
+
}
|
|
113
|
+
record.onResize = onResize;
|
|
114
|
+
}
|
|
115
|
+
}, [
|
|
116
|
+
dimensions,
|
|
117
|
+
measure,
|
|
118
|
+
ref,
|
|
119
|
+
onResize
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
export { WidthHeight, WidthOnly, useResizeObserver };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
const isSimpleStateValue = (arg)=>"function" != typeof arg;
|
|
3
|
+
const useStateRef = (initialValue)=>{
|
|
4
|
+
const [value, _setValue] = useState(initialValue);
|
|
5
|
+
const ref = useRef(value);
|
|
6
|
+
const setValue = useCallback((arg)=>{
|
|
7
|
+
if (isSimpleStateValue(arg)) {
|
|
8
|
+
ref.current = arg;
|
|
9
|
+
_setValue(arg);
|
|
10
|
+
} else {
|
|
11
|
+
const { current: prev } = ref;
|
|
12
|
+
ref.current = arg(prev);
|
|
13
|
+
_setValue(ref.current);
|
|
14
|
+
}
|
|
15
|
+
}, []);
|
|
16
|
+
return [
|
|
17
|
+
ref,
|
|
18
|
+
setValue
|
|
19
|
+
];
|
|
20
|
+
};
|
|
21
|
+
export { useStateRef };
|
|
File without changes
|