@trebco/treb 27.7.6 → 27.11.1
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/treb-spreadsheet.mjs +14 -14
- package/dist/treb.d.ts +28 -26
- package/notes/conditional-fomratring.md +29 -0
- package/package.json +1 -1
- package/treb-base-types/src/area.ts +181 -0
- package/{treb-grid/src/util/dom_utilities.ts → treb-base-types/src/dom-utilities.ts} +29 -20
- package/treb-base-types/src/evaluate-options.ts +21 -0
- package/treb-base-types/src/gradient.ts +97 -0
- package/treb-base-types/src/import.ts +2 -1
- package/treb-base-types/src/index.ts +3 -0
- package/treb-base-types/src/theme.ts +3 -5
- package/treb-calculator/src/calculator.ts +190 -28
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +97 -0
- package/treb-calculator/src/dag/graph.ts +10 -22
- package/treb-calculator/src/dag/{leaf_vertex.ts → state_leaf_vertex.ts} +3 -3
- package/treb-calculator/src/descriptors.ts +10 -3
- package/treb-calculator/src/expression-calculator.ts +1 -1
- package/treb-calculator/src/function-library.ts +25 -22
- package/treb-calculator/src/functions/base-functions.ts +166 -5
- package/treb-calculator/src/index.ts +6 -6
- package/treb-calculator/src/notifier-types.ts +1 -1
- package/treb-calculator/src/utilities.ts +2 -2
- package/treb-charts/src/util.ts +2 -2
- package/treb-embed/src/custom-element/global.d.ts +3 -1
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +13 -19
- package/treb-embed/src/embedded-spreadsheet.ts +378 -132
- package/treb-embed/src/spinner.ts +3 -3
- package/treb-embed/style/layout.scss +1 -1
- package/treb-export/src/drawing2/chart2.ts +11 -2
- package/treb-export/src/export-worker/export-worker.ts +0 -13
- package/treb-export/src/export2.ts +197 -2
- package/treb-export/src/import2.ts +169 -4
- package/treb-export/src/workbook-style2.ts +59 -10
- package/treb-export/src/workbook2.ts +10 -1
- package/treb-grid/src/editors/autocomplete.ts +28 -24
- package/treb-grid/src/editors/editor.ts +3 -4
- package/treb-grid/src/editors/formula_bar.ts +1 -1
- package/treb-grid/src/index.ts +2 -1
- package/treb-grid/src/layout/base_layout.ts +34 -31
- package/treb-grid/src/layout/grid_layout.ts +17 -28
- package/treb-grid/src/render/selection-renderer.ts +2 -3
- package/treb-grid/src/render/svg_header_overlay.ts +4 -11
- package/treb-grid/src/render/svg_selection_block.ts +27 -34
- package/treb-grid/src/render/tile_renderer.ts +8 -6
- package/treb-grid/src/types/conditional_format.ts +168 -0
- package/treb-grid/src/types/grid.ts +37 -47
- package/treb-grid/src/types/grid_base.ts +188 -33
- package/treb-grid/src/types/scale-control.ts +2 -2
- package/treb-grid/src/types/sheet.ts +332 -28
- package/treb-grid/src/types/sheet_types.ts +4 -0
- package/treb-grid/src/types/tab_bar.ts +4 -8
- package/treb-utils/src/index.ts +0 -1
- package/treb-utils/src/resizable.ts +26 -27
- package/treb-utils/src/template.ts +0 -70
- /package/{README-shadow-DOM.md → notes/shadow-DOM.md} +0 -0
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
|
|
22
22
|
import type { FunctionMap } from '../descriptors';
|
|
23
23
|
import * as Utils from '../utilities';
|
|
24
|
-
import { ReferenceError, NotImplError, NAError, ArgumentError, DivideByZeroError, ValueError } from '../function-error';
|
|
24
|
+
import { ReferenceError, NotImplError, NAError, ArgumentError, DivideByZeroError, ValueError, NameError } from '../function-error';
|
|
25
25
|
import type { UnionValue,
|
|
26
26
|
RenderFunctionResult, RenderFunctionOptions, Complex } from 'treb-base-types';
|
|
27
|
-
import { Box, ValueType, GetValueType, ComplexOrReal } from 'treb-base-types';
|
|
27
|
+
import { Box, ValueType, GetValueType, ComplexOrReal, IsComplex } from 'treb-base-types';
|
|
28
28
|
import { Sparkline } from './sparkline';
|
|
29
29
|
import { LotusDate, UnlotusDate } from 'treb-format';
|
|
30
30
|
|
|
@@ -427,7 +427,7 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
427
427
|
description: 'Counts cells that contain numbers',
|
|
428
428
|
fn: (...args: unknown[]): UnionValue => {
|
|
429
429
|
return Box(Utils.FlattenUnboxed(args).reduce((a: number, b: unknown) => {
|
|
430
|
-
if (typeof b === 'number') return a + 1;
|
|
430
|
+
if (typeof b === 'number' || IsComplex(b)) return a + 1;
|
|
431
431
|
return a;
|
|
432
432
|
}, 0));
|
|
433
433
|
},
|
|
@@ -456,7 +456,7 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
456
456
|
},
|
|
457
457
|
|
|
458
458
|
Not: {
|
|
459
|
-
fn: (...args: unknown[]): UnionValue => {
|
|
459
|
+
fn: Utils.ApplyAsArray((...args: unknown[]): UnionValue => {
|
|
460
460
|
if (args.length === 0) {
|
|
461
461
|
return ArgumentError();
|
|
462
462
|
}
|
|
@@ -464,7 +464,7 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
464
464
|
return Box(!args[0]);
|
|
465
465
|
}
|
|
466
466
|
return Box(true);
|
|
467
|
-
}
|
|
467
|
+
})
|
|
468
468
|
},
|
|
469
469
|
|
|
470
470
|
If: {
|
|
@@ -1126,6 +1126,167 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
1126
1126
|
fn: (...args: unknown[]): UnionValue => {
|
|
1127
1127
|
return { type: ValueType.object, value: args, key: 'sparkline-data' };
|
|
1128
1128
|
},
|
|
1129
|
+
},
|
|
1130
|
+
|
|
1131
|
+
UniqueValues: {
|
|
1132
|
+
arguments: [
|
|
1133
|
+
{ name: 'range', boxed: true },
|
|
1134
|
+
],
|
|
1135
|
+
visibility: 'internal',
|
|
1136
|
+
fn: (area: UnionValue): UnionValue => {
|
|
1137
|
+
|
|
1138
|
+
if (area.type === ValueType.array) {
|
|
1139
|
+
|
|
1140
|
+
const cols = area.value.length;
|
|
1141
|
+
const rows = area.value[0]?.length;
|
|
1142
|
+
|
|
1143
|
+
// how is uniqueness defined in this context? (...)
|
|
1144
|
+
|
|
1145
|
+
const Normalize = (cell?: UnionValue): string|number|boolean => {
|
|
1146
|
+
|
|
1147
|
+
if (!cell) {
|
|
1148
|
+
return '';
|
|
1149
|
+
}
|
|
1150
|
+
else switch (cell.type) {
|
|
1151
|
+
case ValueType.string:
|
|
1152
|
+
case ValueType.number:
|
|
1153
|
+
case ValueType.boolean:
|
|
1154
|
+
return cell.value;
|
|
1155
|
+
|
|
1156
|
+
case ValueType.undefined:
|
|
1157
|
+
return '';
|
|
1158
|
+
|
|
1159
|
+
default:
|
|
1160
|
+
console.info("check", cell, cell.value)
|
|
1161
|
+
return cell.value?.toString() || '';
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
};
|
|
1165
|
+
|
|
1166
|
+
const set: Set<number|string|boolean> = new Set();
|
|
1167
|
+
const duplicates: Set<number|string|boolean> = new Set();
|
|
1168
|
+
|
|
1169
|
+
for (const column of area.value) {
|
|
1170
|
+
for (const cell of column) {
|
|
1171
|
+
const normalized = Normalize(cell);
|
|
1172
|
+
if (set.has(normalized)) {
|
|
1173
|
+
duplicates.add(normalized);
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
set.add(normalized);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
const result: UnionValue[][] = [];
|
|
1182
|
+
for (const column of area.value) {
|
|
1183
|
+
const column_result: UnionValue[] = [];
|
|
1184
|
+
for (const cell of column) {
|
|
1185
|
+
const value = Normalize(cell);
|
|
1186
|
+
column_result.push({
|
|
1187
|
+
type: ValueType.boolean,
|
|
1188
|
+
value: !duplicates.has(value),
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
result.push(column_result);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
return {
|
|
1195
|
+
type: ValueType.array,
|
|
1196
|
+
value: result,
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// if it's not an array, by definition it's unique
|
|
1202
|
+
|
|
1203
|
+
return {
|
|
1204
|
+
type: ValueType.boolean,
|
|
1205
|
+
value: true,
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
},
|
|
1209
|
+
},
|
|
1210
|
+
|
|
1211
|
+
Gradient: {
|
|
1212
|
+
arguments: [
|
|
1213
|
+
{ name: 'range', boxed: true },
|
|
1214
|
+
{ name: 'min', },
|
|
1215
|
+
{ name: 'max', },
|
|
1216
|
+
],
|
|
1217
|
+
visibility: 'internal',
|
|
1218
|
+
fn: (area: UnionValue, static_min?: number, static_max?: number): UnionValue => {
|
|
1219
|
+
|
|
1220
|
+
const tmp = Utils.FlattenBoxed([area]);
|
|
1221
|
+
|
|
1222
|
+
let sum = 0;
|
|
1223
|
+
let count = 0;
|
|
1224
|
+
let min = 0;
|
|
1225
|
+
let max = 0;
|
|
1226
|
+
|
|
1227
|
+
for (const ref of tmp as UnionValue[]) {
|
|
1228
|
+
if (ref.type === ValueType.error) {
|
|
1229
|
+
return ref;
|
|
1230
|
+
}
|
|
1231
|
+
if (ref.type === ValueType.number) {
|
|
1232
|
+
if (count === 0) {
|
|
1233
|
+
min = ref.value;
|
|
1234
|
+
max = ref.value;
|
|
1235
|
+
}
|
|
1236
|
+
else {
|
|
1237
|
+
min = Math.min(min, ref.value);
|
|
1238
|
+
max = Math.max(max, ref.value);
|
|
1239
|
+
}
|
|
1240
|
+
count++;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
if (typeof static_max === 'number') {
|
|
1245
|
+
max = static_max;
|
|
1246
|
+
}
|
|
1247
|
+
if (typeof static_min === 'number') {
|
|
1248
|
+
min = static_min;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
let range = max - min;
|
|
1252
|
+
|
|
1253
|
+
let rows = 1;
|
|
1254
|
+
let columns = 1;
|
|
1255
|
+
|
|
1256
|
+
if (area.type === ValueType.array) {
|
|
1257
|
+
|
|
1258
|
+
rows = area.value.length;
|
|
1259
|
+
columns = area.value[0]?.length || 0;
|
|
1260
|
+
|
|
1261
|
+
const result: UnionValue[][] = [];
|
|
1262
|
+
for (let r = 0; r < rows; r++) {
|
|
1263
|
+
const row: UnionValue[] = [];
|
|
1264
|
+
for (let c = 0; c < columns; c++) {
|
|
1265
|
+
const src = area.value[r][c];
|
|
1266
|
+
if (src.type === ValueType.number) {
|
|
1267
|
+
let calc = 0;
|
|
1268
|
+
if (range > 0) {
|
|
1269
|
+
calc = (src.value - min) / range;
|
|
1270
|
+
}
|
|
1271
|
+
row.push({ type: ValueType.number, value: calc });
|
|
1272
|
+
}
|
|
1273
|
+
else {
|
|
1274
|
+
row.push({ type: ValueType.undefined });
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
}
|
|
1278
|
+
result.push(row);
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
return { type: ValueType.array, value: result };
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
}
|
|
1285
|
+
else {
|
|
1286
|
+
return ArgumentError();
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
},
|
|
1129
1290
|
}
|
|
1130
1291
|
|
|
1131
1292
|
};
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
export * from './calculator';
|
|
23
|
-
// export * from './pack-results';
|
|
24
|
-
|
|
25
|
-
// for annotations that have dependencies
|
|
26
|
-
|
|
27
|
-
export {LeafVertex} from './dag/
|
|
22
|
+
export * from './calculator';
|
|
23
|
+
// export * from './pack-results';
|
|
24
|
+
|
|
25
|
+
// for annotations that have dependencies
|
|
26
|
+
|
|
27
|
+
export type { LeafVertex } from './dag/graph';
|
|
@@ -180,10 +180,10 @@ export const UndefinedToEmptyString = (args: any[]): any[] => {
|
|
|
180
180
|
export const ApplyArrayFunc = (base: (...args: any[]) => any) => {
|
|
181
181
|
return (a: any) => {
|
|
182
182
|
if (Array.isArray(a)) {
|
|
183
|
-
const tmp = [];
|
|
183
|
+
const tmp: any[] = [];
|
|
184
184
|
const rows = a[0].length;
|
|
185
185
|
for (let c = 0; c < a.length; c++) {
|
|
186
|
-
const col = [];
|
|
186
|
+
const col: any[] = [];
|
|
187
187
|
for (let r = 0; r < rows; r++) col[r] = base(a[c][r]);
|
|
188
188
|
tmp.push(col);
|
|
189
189
|
}
|
package/treb-charts/src/util.ts
CHANGED
|
@@ -38,7 +38,7 @@ export class Util {
|
|
|
38
38
|
* given a passed range, find the best scale range. count is just a
|
|
39
39
|
* suggestion -- we try to get as close as possible.
|
|
40
40
|
*/
|
|
41
|
-
public static Scale(min: number, max: number, count = 6.5): RangeScale {
|
|
41
|
+
public static Scale(min: number, max: number, count = 6.5, limit_count?: boolean, discrete?: boolean): RangeScale {
|
|
42
42
|
|
|
43
43
|
/*
|
|
44
44
|
const range = max - min;
|
|
@@ -71,7 +71,7 @@ export class Util {
|
|
|
71
71
|
|
|
72
72
|
return { scale, step, count, min, max };
|
|
73
73
|
*/
|
|
74
|
-
return Scale(min, max, count);
|
|
74
|
+
return Scale(min, max, count, limit_count, discrete);
|
|
75
75
|
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -19,8 +19,11 @@ interface ElementOptions {
|
|
|
19
19
|
classes: string|string[];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* FIXME: unify this with DOMUtils
|
|
24
|
+
*/
|
|
25
|
+
const Element = <K extends keyof HTMLElementTagNameMap>(tag: K, parent?: HTMLElement|DocumentFragment, options: Partial<ElementOptions> = {}, attrs: Record<string, string> = {}): HTMLElementTagNameMap[K] => {
|
|
26
|
+
const element = document.createElement(tag);
|
|
24
27
|
if (options.classes) {
|
|
25
28
|
|
|
26
29
|
// you can't use an array destructure in a ternary expression? TIL
|
|
@@ -105,21 +108,12 @@ export class SpreadsheetConstructor {
|
|
|
105
108
|
|
|
106
109
|
const style_node = document.head.querySelector('style[treb-stylesheet]');
|
|
107
110
|
if (!style_node) {
|
|
108
|
-
const style =
|
|
111
|
+
const style = Element('style');
|
|
109
112
|
style.setAttribute('treb-stylesheet', '');
|
|
110
113
|
style.textContent = css;
|
|
111
114
|
document.head.prepend(style);
|
|
112
115
|
}
|
|
113
116
|
|
|
114
|
-
/*
|
|
115
|
-
if (!SpreadsheetConstructor.stylesheets_attached) {
|
|
116
|
-
const style = document.createElement('style');
|
|
117
|
-
style.textContent = css;
|
|
118
|
-
document.head.prepend(style);
|
|
119
|
-
SpreadsheetConstructor.stylesheets_attached = true;
|
|
120
|
-
}
|
|
121
|
-
*/
|
|
122
|
-
|
|
123
117
|
}
|
|
124
118
|
|
|
125
119
|
}
|
|
@@ -509,9 +503,9 @@ export class SpreadsheetConstructor {
|
|
|
509
503
|
|
|
510
504
|
const resize_parent = root.querySelector('.treb-main') as HTMLElement; // was document.body
|
|
511
505
|
|
|
512
|
-
resizer = Element
|
|
506
|
+
resizer = Element('div', resize_parent, { classes: 'treb-resize-rect' });
|
|
513
507
|
|
|
514
|
-
mask = Element
|
|
508
|
+
mask = Element('div', resize_parent, {
|
|
515
509
|
classes: 'treb-resize-mask',
|
|
516
510
|
style: 'cursor: nw-resize;',
|
|
517
511
|
});
|
|
@@ -724,7 +718,7 @@ export class SpreadsheetConstructor {
|
|
|
724
718
|
}
|
|
725
719
|
|
|
726
720
|
}
|
|
727
|
-
Element
|
|
721
|
+
Element('button', fragment, { style, title, data: { command: 'set-color', color: JSON.stringify(entry.color) } });
|
|
728
722
|
}
|
|
729
723
|
}
|
|
730
724
|
|
|
@@ -733,7 +727,7 @@ export class SpreadsheetConstructor {
|
|
|
733
727
|
this.swatch_lists.theme?.replaceChildren(fragment);
|
|
734
728
|
|
|
735
729
|
fragment = document.createDocumentFragment();
|
|
736
|
-
Element
|
|
730
|
+
Element('button', fragment, {
|
|
737
731
|
classes: 'treb-default-color',
|
|
738
732
|
title: 'Default color',
|
|
739
733
|
data: { command: 'set-color', color: JSON.stringify({}) },
|
|
@@ -748,7 +742,7 @@ export class SpreadsheetConstructor {
|
|
|
748
742
|
|
|
749
743
|
for (const text of [...colors, ...additional_colors]) {
|
|
750
744
|
const style = `background: ${text.toLowerCase()};`;
|
|
751
|
-
Element
|
|
745
|
+
Element('button', fragment, { style, title: text, data: { command: 'set-color', color: JSON.stringify({text: text.toLowerCase()})}});
|
|
752
746
|
}
|
|
753
747
|
|
|
754
748
|
this.swatch_lists.other?.replaceChildren(fragment);
|
|
@@ -777,7 +771,7 @@ export class SpreadsheetConstructor {
|
|
|
777
771
|
}
|
|
778
772
|
|
|
779
773
|
const Button = (format: string) => {
|
|
780
|
-
return Element
|
|
774
|
+
return Element('button', undefined, {
|
|
781
775
|
text: format, data: { format, command: 'number-format' },
|
|
782
776
|
});
|
|
783
777
|
};
|
|
@@ -785,7 +779,7 @@ export class SpreadsheetConstructor {
|
|
|
785
779
|
const fragment = document.createDocumentFragment();
|
|
786
780
|
fragment.append(...number_formats.map(format => Button(format)));
|
|
787
781
|
|
|
788
|
-
fragment.append(Element
|
|
782
|
+
fragment.append(Element('div', undefined, {}, {separator: ''}));
|
|
789
783
|
fragment.append(...date_formats.map(format => Button(format)));
|
|
790
784
|
|
|
791
785
|
format_menu.textContent = '';
|