@rowsncolumns/spreadsheet 10.5.14 → 10.5.15
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/cjs/api/selections.d.ts +1 -1
- package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
- package/dist/cjs/components/canvas-grid/index.js +37 -7
- package/dist/cjs/components/canvas-grid/typings.d.ts +11 -0
- package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
- package/dist/cjs/hooks/use-editor-submit.d.ts +3 -2
- package/dist/cjs/hooks/use-editor-submit.d.ts.map +1 -1
- package/dist/cjs/hooks/use-editor-submit.js +30 -20
- package/dist/cjs/hooks/use-get-values-from-range.d.ts +6 -1
- package/dist/cjs/hooks/use-get-values-from-range.d.ts.map +1 -1
- package/dist/cjs/hooks/use-get-values-from-range.js +89 -77
- package/dist/cjs/hooks/use-structured-reference-selection.d.ts +1 -1
- package/dist/cjs/release-date.js +1 -1
- package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
- package/dist/esm/components/canvas-grid/index.js +34 -4
- package/dist/esm/components/canvas-grid/typings.d.ts +11 -0
- package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
- package/dist/esm/hooks/use-editor-submit.d.ts +3 -2
- package/dist/esm/hooks/use-editor-submit.d.ts.map +1 -1
- package/dist/esm/hooks/use-editor-submit.js +5 -1
- package/dist/esm/hooks/use-get-values-from-range.d.ts +6 -1
- package/dist/esm/hooks/use-get-values-from-range.d.ts.map +1 -1
- package/dist/esm/hooks/use-get-values-from-range.js +70 -41
- package/dist/esm/release-date.js +1 -1
- package/package.json +1 -1
|
@@ -143,7 +143,11 @@ export const useEditorSubmit = ({ sheetId, onChangeActiveSheet, setActiveCell, o
|
|
|
143
143
|
* actually changed and a rule with an error alert rejects it.
|
|
144
144
|
*/
|
|
145
145
|
if (value !== previousValue && getCommitValidation) {
|
|
146
|
-
|
|
146
|
+
// Only a list (`ONE_OF_RANGE`) rule resolves asynchronously; every other
|
|
147
|
+
// decision stays synchronous so an ordinary commit still lands in the
|
|
148
|
+
// same tick as the keystroke.
|
|
149
|
+
const pending = getCommitValidation(editingSheetId, activeCell.rowIndex, activeCell.columnIndex, value, previousValue);
|
|
150
|
+
const enforcement = pending instanceof Promise ? await pending : pending;
|
|
147
151
|
if (enforcement) {
|
|
148
152
|
const { decision, alert } = enforcement;
|
|
149
153
|
const request = {
|
|
@@ -32,6 +32,11 @@ type UseGetValuesFromRangeProps<T extends CellData> = {
|
|
|
32
32
|
* `CanvasGridProps["getValidationSourceValue"]`. Defaults to `getFormattedValue`.
|
|
33
33
|
*/
|
|
34
34
|
getValidationSourceValue?: CanvasGridProps["getValidationSourceValue"];
|
|
35
|
+
/**
|
|
36
|
+
* Optional engine-side resolver for the list sources the tokenizer cannot resolve — see
|
|
37
|
+
* `CanvasGridProps["resolveValidationSourceValues"]`.
|
|
38
|
+
*/
|
|
39
|
+
resolveValidationSourceValues?: CanvasGridProps["resolveValidationSourceValues"];
|
|
35
40
|
};
|
|
36
41
|
/**
|
|
37
42
|
* Get all user entered values from a range
|
|
@@ -39,6 +44,6 @@ type UseGetValuesFromRangeProps<T extends CellData> = {
|
|
|
39
44
|
* @param param0
|
|
40
45
|
* @returns
|
|
41
46
|
*/
|
|
42
|
-
export declare const useGetValuesFromRange: <T extends CellData>({ sheetId, getFormattedValue, getValidationValue, getSheetId, getSelectionsFromFormula, onRequestCalculate, getValidationSourceValue, }: UseGetValuesFromRangeProps<T>) => readonly [(address: string) => ConditionValue[], (address: string) => ConditionValue[], (address: string, rowIndex: number, columnIndex: number, targetSheetId?: number) => Promise<ConditionValue[]>];
|
|
47
|
+
export declare const useGetValuesFromRange: <T extends CellData>({ sheetId, getFormattedValue, getValidationValue, getSheetId, getSelectionsFromFormula, onRequestCalculate, getValidationSourceValue, resolveValidationSourceValues, }: UseGetValuesFromRangeProps<T>) => readonly [(address: string) => ConditionValue[], (address: string) => ConditionValue[], (address: string, rowIndex: number, columnIndex: number, targetSheetId?: number) => Promise<ConditionValue[]>];
|
|
43
48
|
export {};
|
|
44
49
|
//# sourceMappingURL=use-get-values-from-range.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-get-values-from-range.d.ts","sourceRoot":"","sources":["../../../hooks/use-get-values-from-range.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,QAAQ,EACR,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,KAAK,0BAA0B,CAAC,CAAC,SAAS,QAAQ,IAAI;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,SAAS,CAAC;IACtB;;;;;;OAMG;IACH,kBAAkB,EAAE,CAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,qBAAqB,KACzB,mBAAmB,CAAC;IACzB;;;OAGG;IACH,wBAAwB,CACtB,OAAO,EAAE,MAAM,GACd,aAAa,CAAC,mBAAmB,CAAC,EAAE,CAAC;IACxC;;OAEG;IACH,UAAU,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC1C,kBAAkB,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAC;IAC3D;;;OAGG;IACH,wBAAwB,CAAC,EAAE,eAAe,CAAC,0BAA0B,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"use-get-values-from-range.d.ts","sourceRoot":"","sources":["../../../hooks/use-get-values-from-range.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,QAAQ,EACR,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,KAAK,0BAA0B,CAAC,CAAC,SAAS,QAAQ,IAAI;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,SAAS,CAAC;IACtB;;;;;;OAMG;IACH,kBAAkB,EAAE,CAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,qBAAqB,KACzB,mBAAmB,CAAC;IACzB;;;OAGG;IACH,wBAAwB,CACtB,OAAO,EAAE,MAAM,GACd,aAAa,CAAC,mBAAmB,CAAC,EAAE,CAAC;IACxC;;OAEG;IACH,UAAU,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC1C,kBAAkB,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAC;IAC3D;;;OAGG;IACH,wBAAwB,CAAC,EAAE,eAAe,CAAC,0BAA0B,CAAC,CAAC;IACvE;;;OAGG;IACH,6BAA6B,CAAC,EAAE,eAAe,CAAC,+BAA+B,CAAC,CAAC;CAClF,CAAC;AA0BF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,QAAQ,EAAE,wKASvD,0BAA0B,CAAC,CAAC,CAAC,yBAqDhB,MAAM,KAAG,cAAc,EAAE,YASzB,MAAM,KAAG,cAAc,EAAE,YAoBxB,MAAM,YACL,MAAM,eACH,MAAM,kBACJ,MAAM,KACpB,OAAO,CAAC,cAAc,EAAE,CAAC,CAkFjC,CAAC"}
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
import { checkIfStringIsReference, iterateCells } from "@rowsncolumns/utils";
|
|
2
2
|
import { useCallback } from "react";
|
|
3
3
|
import { useCallbackRef } from "./use-callback-ref";
|
|
4
|
+
/**
|
|
5
|
+
* The reference / array functions the LEGACY calculator previews as an array through
|
|
6
|
+
* `onRequestCalculate(…, { isArray: true })` — the only sources it can resolve beyond plain
|
|
7
|
+
* ranges. The engine resolver (`resolveValidationSourceValues`) takes any function call.
|
|
8
|
+
*/
|
|
9
|
+
const LEGACY_CALC_SOURCE = /(OFFSET|INDIRECT|FILTER|UNIQUE|SORT|SEQUENCE)\s*\(/i;
|
|
10
|
+
/** Any function call — `OFFSET(`, `INDEX(`, `_xlfn.XLOOKUP(`, `CHOOSE(` — in a list source. */
|
|
11
|
+
const FUNCTION_CALL = /[A-Z_\\][A-Z0-9_.]*\s*\(/i;
|
|
12
|
+
/**
|
|
13
|
+
* Dropdown options from a resolver's display texts: blanks dropped, duplicates collapsed,
|
|
14
|
+
* first-seen order kept — the same shape `getValuesFromRange` builds from cells.
|
|
15
|
+
*/
|
|
16
|
+
const conditionValuesFromTexts = (texts) => {
|
|
17
|
+
const userEnteredValues = new Map();
|
|
18
|
+
for (const userEnteredValue of texts) {
|
|
19
|
+
if (userEnteredValue) {
|
|
20
|
+
userEnteredValues.set(userEnteredValue, { userEnteredValue });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return [...userEnteredValues.values()];
|
|
24
|
+
};
|
|
4
25
|
/**
|
|
5
26
|
* Get all user entered values from a range
|
|
6
27
|
* used in data validation
|
|
7
28
|
* @param param0
|
|
8
29
|
* @returns
|
|
9
30
|
*/
|
|
10
|
-
export const useGetValuesFromRange = ({ sheetId, getFormattedValue, getValidationValue, getSheetId, getSelectionsFromFormula, onRequestCalculate, getValidationSourceValue, }) => {
|
|
31
|
+
export const useGetValuesFromRange = ({ sheetId, getFormattedValue, getValidationValue, getSheetId, getSelectionsFromFormula, onRequestCalculate, getValidationSourceValue, resolveValidationSourceValues, }) => {
|
|
11
32
|
// Windowed hosts supply an off-window-safe reader for validation source ranges
|
|
12
33
|
// (dropdown options + commit checks) — the plain `getFormattedValue` only sees the
|
|
13
34
|
// loaded viewport there. Defaults to `getFormattedValue`.
|
|
@@ -40,64 +61,72 @@ export const useGetValuesFromRange = ({ sheetId, getFormattedValue, getValidatio
|
|
|
40
61
|
const getEffectiveValuesFromRange = useCallbackRef(useCallback((address) => {
|
|
41
62
|
return [...getValuesFromRange(address, getValidationValue).values()];
|
|
42
63
|
}, [getValidationValue, getValuesFromRange]));
|
|
64
|
+
/**
|
|
65
|
+
* The options a list (`ONE_OF_RANGE`) source denotes at a cell — the dropdown's items and
|
|
66
|
+
* the commit gate's accept list. A plain or sheet-qualified range, a range-type name and a
|
|
67
|
+
* structured reference resolve locally from the tokenizer's selections (off-window-safe
|
|
68
|
+
* through `readSourceValue`). Anything else — a formula-valued name (`=RegionList` defined
|
|
69
|
+
* as `=Table1[Region]` / `=OFFSET(…,COUNTA(…),1)`), any function call, a source the
|
|
70
|
+
* tokenizer found nothing in — goes through the engine resolver when the host supplies
|
|
71
|
+
* one; the legacy calculator previews its reference/array functions as an array; the
|
|
72
|
+
* tokenizer's selections are the last resort. An empty list means "nothing resolvable".
|
|
73
|
+
*/
|
|
43
74
|
const getFormattedValuesFromRangeAsync = useCallbackRef(useCallback(async (address, rowIndex, columnIndex, targetSheetId = sheetId) => {
|
|
44
75
|
const trimmedAddress = address?.trim() ?? "";
|
|
76
|
+
if (!trimmedAddress) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
45
79
|
const isFormula = trimmedAddress.startsWith("=");
|
|
46
80
|
const formulaBody = isFormula ? trimmedAddress.slice(1) : trimmedAddress;
|
|
47
81
|
const hasDirectReference = checkIfStringIsReference(formulaBody);
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
return [];
|
|
82
|
+
const isFunctionCall = FUNCTION_CALL.test(formulaBody);
|
|
83
|
+
const selections = hasDirectReference
|
|
84
|
+
? []
|
|
85
|
+
: getSelectionsFromFormula(address);
|
|
86
|
+
if (hasDirectReference || (selections.length && !isFunctionCall)) {
|
|
87
|
+
return [...getValuesFromRange(address, readSourceValue).values()];
|
|
56
88
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return;
|
|
89
|
+
if (resolveValidationSourceValues) {
|
|
90
|
+
const texts = await resolveValidationSourceValues(trimmedAddress, targetSheetId, rowIndex, columnIndex);
|
|
91
|
+
if (texts) {
|
|
92
|
+
return conditionValuesFromTexts(texts);
|
|
62
93
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
94
|
+
}
|
|
95
|
+
if (onRequestCalculate && isFormula && LEGACY_CALC_SOURCE.test(formulaBody)) {
|
|
96
|
+
const result = await onRequestCalculate(trimmedAddress, targetSheetId, rowIndex, columnIndex, { isArray: true, disablePreview: true });
|
|
97
|
+
const userEnteredValues = new Map();
|
|
98
|
+
const pushValue = (value) => {
|
|
99
|
+
if (value === null || value === undefined) {
|
|
100
|
+
return;
|
|
66
101
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const userEnteredValue = value instanceof Date
|
|
70
|
-
? value.toISOString()
|
|
71
|
-
: typeof value === "boolean"
|
|
72
|
-
? value
|
|
73
|
-
? "TRUE"
|
|
74
|
-
: "FALSE"
|
|
75
|
-
: String(value);
|
|
76
|
-
userEnteredValues.set(userEnteredValue, { userEnteredValue });
|
|
77
|
-
};
|
|
78
|
-
if (Array.isArray(result)) {
|
|
79
|
-
if (Array.isArray(result[0])) {
|
|
80
|
-
for (const row of result) {
|
|
81
|
-
for (const entry of row) {
|
|
102
|
+
if (Array.isArray(value)) {
|
|
103
|
+
for (const entry of value) {
|
|
82
104
|
pushValue(entry);
|
|
83
105
|
}
|
|
106
|
+
return;
|
|
84
107
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
const userEnteredValue = value instanceof Date
|
|
109
|
+
? value.toISOString()
|
|
110
|
+
: typeof value === "boolean"
|
|
111
|
+
? value
|
|
112
|
+
? "TRUE"
|
|
113
|
+
: "FALSE"
|
|
114
|
+
: String(value);
|
|
115
|
+
userEnteredValues.set(userEnteredValue, { userEnteredValue });
|
|
116
|
+
};
|
|
93
117
|
pushValue(result);
|
|
118
|
+
return [...userEnteredValues.values()];
|
|
119
|
+
}
|
|
120
|
+
if (selections.length) {
|
|
121
|
+
return [...getValuesFromRange(address, readSourceValue).values()];
|
|
94
122
|
}
|
|
95
|
-
return [
|
|
123
|
+
return [];
|
|
96
124
|
}, [
|
|
97
125
|
readSourceValue,
|
|
98
126
|
getSelectionsFromFormula,
|
|
99
127
|
getValuesFromRange,
|
|
100
128
|
onRequestCalculate,
|
|
129
|
+
resolveValidationSourceValues,
|
|
101
130
|
sheetId,
|
|
102
131
|
]));
|
|
103
132
|
return [
|
package/dist/esm/release-date.js
CHANGED