@trebco/treb 27.12.2 → 28.0.5

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.
Files changed (37) hide show
  1. package/README.md +6 -0
  2. package/dist/treb-spreadsheet-light.mjs +16 -0
  3. package/dist/treb-spreadsheet.mjs +14 -12
  4. package/dist/treb.d.ts +31 -3
  5. package/esbuild-custom-element.mjs +3 -1
  6. package/package.json +4 -4
  7. package/treb-base-types/src/dom-utilities.ts +157 -19
  8. package/treb-base-types/src/theme.ts +5 -4
  9. package/treb-charts/src/renderer.ts +4 -58
  10. package/treb-embed/markup/layout.html +4 -0
  11. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +131 -87
  12. package/treb-embed/src/embedded-spreadsheet.ts +146 -111
  13. package/treb-embed/src/options.ts +9 -0
  14. package/treb-embed/src/spinner.ts +5 -3
  15. package/treb-embed/src/toolbar-message.ts +5 -0
  16. package/treb-embed/style/layout.scss +65 -1
  17. package/treb-grid/src/editors/autocomplete.ts +24 -13
  18. package/treb-grid/src/editors/editor.ts +43 -139
  19. package/treb-grid/src/editors/external_editor.ts +1 -1
  20. package/treb-grid/src/editors/formula_bar.ts +24 -24
  21. package/treb-grid/src/editors/overlay_editor.ts +1 -1
  22. package/treb-grid/src/layout/base_layout.ts +34 -25
  23. package/treb-grid/src/layout/grid_layout.ts +20 -20
  24. package/treb-grid/src/render/selection-renderer.ts +3 -3
  25. package/treb-grid/src/render/svg_header_overlay.ts +6 -4
  26. package/treb-grid/src/render/svg_selection_block.ts +10 -7
  27. package/treb-grid/src/types/grid.ts +80 -81
  28. package/treb-grid/src/types/scale-control.ts +69 -81
  29. package/treb-grid/src/types/sheet.ts +3 -52
  30. package/treb-grid/src/types/tab_bar.ts +27 -13
  31. package/treb-grid/src/util/fontmetrics2.ts +24 -21
  32. package/treb-utils/src/event_source.ts +23 -23
  33. package/treb-utils/src/index.ts +2 -2
  34. package/treb-utils/src/measurement.ts +24 -24
  35. package/treb-utils/src/serialize_html.ts +25 -21
  36. package/treb-utils/src/dispatch.ts +0 -57
  37. package/treb-utils/src/resizable.ts +0 -159
@@ -26,7 +26,7 @@ import type { BaseLayout } from '../layout/base_layout';
26
26
  import { MouseDrag } from './drag_mask';
27
27
  import type { GridOptions } from './grid_options';
28
28
  import { type ScaleEvent, ScaleControl } from './scale-control';
29
- import { DOMUtilities } from 'treb-base-types';
29
+ import { DOMContext } from 'treb-base-types';
30
30
 
31
31
  export interface ActivateSheetEvent {
32
32
  type: 'activate-sheet';
@@ -113,17 +113,22 @@ export class TabBar extends EventSource<TabEvent> {
113
113
  this.stats_panel.innerText = ''; // clear
114
114
  for (const entry of value) {
115
115
 
116
- const label = DOMUtilities.Create('span', 'treb-stats-label', this.stats_panel);
117
- label.textContent = entry.label;
116
+ this.DOM.Create('span', 'treb-stats-label', this.stats_panel, {
117
+ text: entry.label
118
+ });
119
+
120
+ this.DOM.Create('span', 'treb-stats-value', this.stats_panel, {
121
+ text: entry.value,
122
+ });
118
123
 
119
- const figure = DOMUtilities.Create('span', 'treb-stats-value', this.stats_panel);
120
- figure.textContent = entry.value;
121
124
  }
122
125
  }
123
126
  }
124
127
 
125
128
  private container: HTMLElement;
126
129
 
130
+ private DOM: DOMContext;
131
+
127
132
  constructor(
128
133
  private layout: BaseLayout,
129
134
  private model: DataModel,
@@ -135,6 +140,8 @@ export class TabBar extends EventSource<TabEvent> {
135
140
 
136
141
  super();
137
142
 
143
+ this.DOM = DOMContext.GetInstance(view_node.ownerDocument);
144
+
138
145
  this.container = view_node.querySelector('.treb-spreadsheet-footer') as HTMLElement;
139
146
  if (!this.container) {
140
147
  throw new Error('missing container for tab bar');
@@ -195,6 +202,10 @@ export class TabBar extends EventSource<TabEvent> {
195
202
  clearTimeout(this.double_click_data.timeout);
196
203
  }
197
204
  this.double_click_data.index = index;
205
+
206
+ // I don't think the window instance matters for this,
207
+ // but perhaps it's worth using DOM just for consistency
208
+
198
209
  this.double_click_data.timeout = window.setTimeout(() => {
199
210
  this.double_click_data.index = undefined;
200
211
  this.double_click_data.timeout = undefined;
@@ -242,14 +253,17 @@ export class TabBar extends EventSource<TabEvent> {
242
253
 
243
254
  tab.contentEditable = 'true';
244
255
 
245
- // OK for shadow, seems to work as expected in all browsers
246
- const selection = window.getSelection(); // OK for shadow
256
+ if (this.DOM.doc) {
257
+
258
+ const selection = this.DOM.GetSelection();
259
+
260
+ if (selection) {
261
+ selection.removeAllRanges();
262
+ const range = this.DOM.doc.createRange();
263
+ range.selectNodeContents(tab);
264
+ selection.addRange(range);
265
+ }
247
266
 
248
- if (selection) {
249
- selection.removeAllRanges();
250
- const range = document.createRange();
251
- range.selectNodeContents(tab);
252
- selection.addRange(range);
253
267
  }
254
268
 
255
269
  tab.addEventListener('keydown', (inner_event: KeyboardEvent) => {
@@ -448,7 +462,7 @@ export class TabBar extends EventSource<TabEvent> {
448
462
  if (!sheet.visible) { continue; }
449
463
 
450
464
  const index = tabs.length;
451
- const tab = DOMUtilities.Create('li');
465
+ const tab = this.DOM.Create('li');
452
466
  tab.setAttribute('tabindex', '0');
453
467
 
454
468
  // tab.classList.add('tab');
@@ -1,24 +1,24 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
22
  export interface FontMetrics2 {
23
23
  ascender: number;
24
24
  descender: number;
@@ -63,6 +63,9 @@ export class FontMetricsFactory {
63
63
  // what we're doing now is calculating -- we get the base size
64
64
  // from theme and if we see em or % we scale manually.
65
65
 
66
+ // based on the above, we don't need to worry about which
67
+ // document we're using. but we probably should just to be consistent.
68
+
66
69
  }
67
70
 
68
71
  /* *
@@ -1,25 +1,25 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
22
- import { Yield } from './dispatch';
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ // import { Yield } from './dispatch';
23
23
  // import { IEventSource } from './ievent_source';
24
24
 
25
25
  let subscription_token_generator = 1000;
@@ -90,7 +90,7 @@ export class EventSource<T> { // implements IEventSource<T> {
90
90
  if (!this.dispatched) {
91
91
  this.dispatched = true;
92
92
 
93
- Yield().then(() => {
93
+ Promise.resolve().then(() => {
94
94
 
95
95
  const events = this.queue.slice(0);
96
96
  this.dispatched = false;
@@ -19,10 +19,10 @@
19
19
  *
20
20
  */
21
21
 
22
- export * from './dispatch';
22
+ // export * from './dispatch';
23
23
  export * from './event_source';
24
24
  export * from './ievent_source';
25
- export * from './resizable';
25
+ // export * from './resizable';
26
26
  export * from './measurement';
27
27
  // export * from './color';
28
28
  export * from './serialize_html';
@@ -1,24 +1,24 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
22
  /** size, really */
23
23
  export interface Metrics {
24
24
  width: number;
@@ -120,7 +120,7 @@ export class Measurement {
120
120
 
121
121
  }
122
122
 
123
- /**
123
+ /* *
124
124
  * check if font is loaded, based on the theory that the alternatives
125
125
  * will be different sizes. note that this probably doesn't test weights
126
126
  * or italics properly, as those can be emulated without the specific face.
@@ -131,7 +131,7 @@ export class Measurement {
131
131
  * @param font_face
132
132
  * @param italic
133
133
  * @param bold
134
- */
134
+ * /
135
135
  public static FontLoaded(font_face: string, italic = false, weight = 400): boolean {
136
136
  const face = `${italic ? 'italic' : ''} ${weight} 20pt ${font_face}`;
137
137
  const m1 = this.MeasureText(`${face}, sans-serif`, `check font`);
@@ -139,6 +139,7 @@ export class Measurement {
139
139
  const m3 = this.MeasureText(`${face}, monospace`, `check font`);
140
140
  return (m1.width === m2.width && m2.width === m3.width);
141
141
  }
142
+ */
142
143
 
143
144
  /**
144
145
  * measure width, height of text, accounting for rotation
@@ -169,6 +170,5 @@ export class Measurement {
169
170
 
170
171
  }
171
172
 
172
-
173
173
  }
174
174
 
@@ -1,24 +1,24 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
22
  interface StringMap {
23
23
  [index: string]: string;
24
24
  }
@@ -95,6 +95,10 @@ export const SerializeHTML = (node: Element) => {
95
95
 
96
96
  const defaults: StringMap = {};
97
97
 
98
+ // regarding document, in this case we're creating an iframe
99
+ // specifically for isolation, and adding it to "document".
100
+ // there's no reason to require the context document here (I think).
101
+
98
102
  const iframe = document.createElement('iframe');
99
103
  iframe.style.width = '10px';
100
104
  iframe.style.height = '10px';
@@ -1,57 +0,0 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
22
- /**
23
- * UPDATE: dropping dispatch altogether. there were really very few
24
- * cases where queue length > 1, so it seems like unecessary overhead.
25
- *
26
- * it's still somewhat useful to have an interface, in the event we
27
- * change this again, so keep using the Yield() function.
28
- *
29
- * TODO: is anyone using the callback version? could drop...
30
- *
31
- * I'm guessing no one uses it, because it's broken amd we never noticed
32
- */
33
-
34
- /* *
35
- * yield and then call the passed function
36
- * /
37
- export function Yield(fn: () => void): void;
38
-
39
- / * *
40
- * returns a promise that resolves after yield
41
- * /
42
- export function Yield(): Promise<void>;
43
-
44
- / * * implementation * /
45
- export function Yield(fn?: () => void) {
46
- return fn ? Promise.resolve().then(fn) : Promise.resolve();
47
- }
48
- */
49
-
50
- /* for perf testing, we don't need this anymore
51
- (self as any).__dispatcher_instance = {
52
- Call: Yield
53
- }
54
- */
55
-
56
- export const Yield = () => Promise.resolve();
57
-
@@ -1,159 +0,0 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
22
- import { DOMUtilities } from 'treb-base-types';
23
-
24
- /**
25
- * support for resizable node, drag handle, drag rect, mask
26
- * FIXME: make this composable (decorator?)
27
- * FIXME: make this generic, we can use it for some other stuff (charts?)
28
- */
29
- export class Resizable {
30
-
31
- private static resize_mask: HTMLElement;
32
- private static resize_rect: HTMLElement;
33
-
34
- /**
35
- * adding layout_reference to move the handle. to keep this backwards
36
- * compatible, we add it as a last, optional parameter. at some point
37
- * we can create a replacement class and migrate.
38
- *
39
- * this is a weird pattern, we don't need an instance of this class...
40
- * goint to refactor
41
- *
42
- */
43
- constructor(container: HTMLElement, node: HTMLElement, resize_callback: () => void,
44
- layout_reference: HTMLElement = container) {
45
-
46
- Resizable.Create({
47
- container,
48
- node,
49
- resize_callback,
50
- layout_reference});
51
-
52
- }
53
-
54
- public static Create(options: {
55
- container: HTMLElement;
56
- node: HTMLElement;
57
- resize_callback?: () => void;
58
- layout_reference?: HTMLElement;
59
- }): void {
60
-
61
- const resize_handle = DOMUtilities.Div('treb-embed-resize-handle');
62
-
63
- (options.layout_reference || options.container).appendChild(resize_handle);
64
-
65
- if (!Resizable.resize_mask) {
66
- let mask = document.querySelector('.treb-embed-mouse-mask');
67
- if (!mask) {
68
- mask = DOMUtilities.Div('treb-embed-mouse-mask');
69
- document.body.appendChild(mask);
70
- }
71
- Resizable.resize_mask = mask as HTMLElement;
72
- }
73
-
74
- if (!Resizable.resize_rect) {
75
- let rect = document.querySelector('.treb-embed-resize-rect');
76
- if (!rect) {
77
- rect = DOMUtilities.Div('treb-embed-resize-rect');
78
- Resizable.resize_mask.appendChild(rect);
79
- }
80
- Resizable.resize_rect = rect as HTMLElement;
81
- }
82
-
83
- // eslint-disable-next-line prefer-const
84
- let mouseup: () => void;
85
-
86
- // eslint-disable-next-line prefer-const
87
- let mousemove: (event: MouseEvent) => void;
88
-
89
- let container_rect = { width: 0, height: 0 };
90
- let offset = { x: 0, y: 0 };
91
- let delta = { x: 0, y: 0 };
92
-
93
- const cleanup = () => {
94
-
95
- Resizable.resize_mask.removeEventListener('mousemove', mousemove);
96
- Resizable.resize_mask.removeEventListener('mouseup', mouseup);
97
- Resizable.resize_mask.style.display = 'none';
98
-
99
- if (delta.x || delta.y) {
100
- const bounding_rect = options.container.getBoundingClientRect();
101
- const width = bounding_rect.width + delta.x;
102
- const height = bounding_rect.height + delta.y;
103
- options.container.style.width = `${width}px`;
104
- options.container.style.height = `${height}px`;
105
- if (options.resize_callback) {
106
- options.resize_callback();
107
- }
108
- }
109
-
110
- };
111
-
112
- mousemove = (event: MouseEvent) => {
113
-
114
- if (!event.buttons) {
115
- cleanup();
116
- return;
117
- }
118
-
119
- if (delta.x !== event.clientX - offset.x) {
120
- delta.x = event.clientX - offset.x;
121
- Resizable.resize_rect.style.width = `${container_rect.width + delta.x + 4}px`;
122
- }
123
- if (delta.y !== event.clientY - offset.y) {
124
- delta.y = event.clientY - offset.y;
125
- Resizable.resize_rect.style.height = `${container_rect.height + delta.y + 4}px`;
126
- }
127
- };
128
-
129
- mouseup = () => {
130
- cleanup();
131
- };
132
-
133
- resize_handle.addEventListener('mousedown', (event) => {
134
-
135
- event.stopPropagation();
136
- event.preventDefault();
137
-
138
- const bounding_rect = options.node.getBoundingClientRect();
139
- container_rect = { width: bounding_rect.width, height: bounding_rect.height };
140
-
141
- if (Resizable.resize_rect) {
142
- Resizable.resize_rect.style.top = `${bounding_rect.top - 2}px`;
143
- Resizable.resize_rect.style.left = `${bounding_rect.left - 2}px`;
144
- Resizable.resize_rect.style.width = `${bounding_rect.width + 4}px`;
145
- Resizable.resize_rect.style.height = `${bounding_rect.height + 4}px`;
146
- }
147
-
148
- offset = { x: event.clientX, y: event.clientY };
149
- delta = { x: 0, y: 0 };
150
-
151
- Resizable.resize_mask.style.display = 'block';
152
- Resizable.resize_mask.addEventListener('mousemove', mousemove);
153
- Resizable.resize_mask.addEventListener('mouseup', mouseup);
154
-
155
- });
156
-
157
- }
158
-
159
- }