@trebco/treb 27.12.1 → 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.
- package/README.md +6 -0
- package/dist/treb-spreadsheet-light.mjs +16 -0
- package/dist/treb-spreadsheet.mjs +14 -12
- package/dist/treb.d.ts +31 -3
- package/esbuild-custom-element.mjs +3 -1
- package/package.json +4 -4
- package/treb-base-types/src/dom-utilities.ts +157 -19
- package/treb-base-types/src/theme.ts +5 -4
- package/treb-charts/src/renderer.ts +4 -58
- package/treb-embed/markup/layout.html +4 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +131 -87
- package/treb-embed/src/embedded-spreadsheet.ts +146 -111
- package/treb-embed/src/options.ts +9 -0
- package/treb-embed/src/spinner.ts +5 -3
- package/treb-embed/src/toolbar-message.ts +5 -0
- package/treb-embed/style/layout.scss +65 -1
- package/treb-grid/src/editors/autocomplete.ts +24 -13
- package/treb-grid/src/editors/editor.ts +43 -139
- package/treb-grid/src/editors/external_editor.ts +1 -1
- package/treb-grid/src/editors/formula_bar.ts +24 -24
- package/treb-grid/src/editors/overlay_editor.ts +6 -2
- package/treb-grid/src/layout/base_layout.ts +34 -25
- package/treb-grid/src/layout/grid_layout.ts +20 -20
- package/treb-grid/src/render/selection-renderer.ts +3 -3
- package/treb-grid/src/render/svg_header_overlay.ts +6 -4
- package/treb-grid/src/render/svg_selection_block.ts +10 -7
- package/treb-grid/src/types/grid.ts +80 -81
- package/treb-grid/src/types/scale-control.ts +69 -81
- package/treb-grid/src/types/sheet.ts +3 -52
- package/treb-grid/src/types/tab_bar.ts +27 -13
- package/treb-grid/src/util/fontmetrics2.ts +24 -21
- package/treb-utils/src/event_source.ts +23 -23
- package/treb-utils/src/index.ts +2 -2
- package/treb-utils/src/measurement.ts +24 -24
- package/treb-utils/src/serialize_html.ts +25 -21
- package/treb-utils/src/dispatch.ts +0 -57
- package/treb-utils/src/resizable.ts +0 -159
|
@@ -65,10 +65,10 @@ import type {
|
|
|
65
65
|
|
|
66
66
|
import {
|
|
67
67
|
IsArea, ThemeColorTable, ComplexToString, Rectangle, IsComplex, type CellStyle,
|
|
68
|
-
Localization, Style, type Color, ThemeColor2, IsCellAddress, Area, IsFlatData, IsFlatDataArray, Gradient, ValueType,
|
|
68
|
+
Localization, Style, type Color, ThemeColor2, IsCellAddress, Area, IsFlatData, IsFlatDataArray, Gradient, ValueType, DOMContext,
|
|
69
69
|
} from 'treb-base-types';
|
|
70
70
|
|
|
71
|
-
import { EventSource,
|
|
71
|
+
import { EventSource, ValidateURI } from 'treb-utils';
|
|
72
72
|
import { NumberFormatCache, ValueParser, NumberFormat } from 'treb-format';
|
|
73
73
|
|
|
74
74
|
|
|
@@ -232,15 +232,17 @@ export class EmbeddedSpreadsheet {
|
|
|
232
232
|
/** @internal */
|
|
233
233
|
public static treb_embedded_script_path = '';
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
public static enable_engine = false;
|
|
235
|
+
/* * @internal */
|
|
236
|
+
// public static enable_engine = false;
|
|
237
237
|
|
|
238
|
-
|
|
239
|
-
public static enable_formatter = false;
|
|
238
|
+
/* * @internal */
|
|
239
|
+
// public static enable_formatter = false;
|
|
240
240
|
|
|
241
241
|
/** @internal */
|
|
242
242
|
public static one_time_warnings: Record<string, boolean> = {};
|
|
243
243
|
|
|
244
|
+
protected DOM = DOMContext.GetInstance(); // default
|
|
245
|
+
|
|
244
246
|
/**
|
|
245
247
|
* this flag will be set on LoadDocument. the intent is to be able to
|
|
246
248
|
* know if you have loaded a network document, which may happen before you
|
|
@@ -253,10 +255,10 @@ export class EmbeddedSpreadsheet {
|
|
|
253
255
|
*/
|
|
254
256
|
public loaded = false;
|
|
255
257
|
|
|
256
|
-
|
|
258
|
+
/* *
|
|
257
259
|
* @internal
|
|
258
260
|
*/
|
|
259
|
-
public toolbar_ctl?: ToolbarCtl;
|
|
261
|
+
// public toolbar_ctl?: ToolbarCtl;
|
|
260
262
|
|
|
261
263
|
/**
|
|
262
264
|
* this is a cache of number formats and colors used in the document. it's
|
|
@@ -334,6 +336,39 @@ export class EmbeddedSpreadsheet {
|
|
|
334
336
|
*/
|
|
335
337
|
protected last_save_version = 0;
|
|
336
338
|
|
|
339
|
+
/* *
|
|
340
|
+
* this is an attempt to improve our recordkeeping for stuff that
|
|
341
|
+
* has user-generated changes. it means "this is the version that
|
|
342
|
+
* was in the network document or inline document". it has no
|
|
343
|
+
* meaning in sheets that start empty.
|
|
344
|
+
*
|
|
345
|
+
* we use "network version" to mean both network documents and inline
|
|
346
|
+
* documents (Which technically come from the network).
|
|
347
|
+
*
|
|
348
|
+
* the problem with this is that the only way for it to work would
|
|
349
|
+
* be to store it in the document, but once we start storing this
|
|
350
|
+
* value it will get stuck and cause problems. there's no way to
|
|
351
|
+
* "only store it in some contexts". I guess in theory we could wipe
|
|
352
|
+
* it if necesssary, but that's weak... something like
|
|
353
|
+
*
|
|
354
|
+
* (1) if this document comes from anywhere but local storage,
|
|
355
|
+
* dump the value
|
|
356
|
+
*
|
|
357
|
+
* (2) never save this value unless you're writing to local storage
|
|
358
|
+
*
|
|
359
|
+
* it's still going to get stuck in places it shouldn't be but we can
|
|
360
|
+
* mitigate problems with it. I'll think about it. we can do the
|
|
361
|
+
* "can revert" thing in a different way.
|
|
362
|
+
*
|
|
363
|
+
* /
|
|
364
|
+
protected canonical_network_version = 0;
|
|
365
|
+
*/
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* simpler flag for testing if we can revert
|
|
369
|
+
*/
|
|
370
|
+
protected initial_load_source: LoadSource|undefined = undefined;
|
|
371
|
+
|
|
337
372
|
/**
|
|
338
373
|
* calculator instance. we may share this if we're in a split view.
|
|
339
374
|
*/
|
|
@@ -487,6 +522,50 @@ export class EmbeddedSpreadsheet {
|
|
|
487
522
|
return this.file_version;
|
|
488
523
|
}
|
|
489
524
|
|
|
525
|
+
/**
|
|
526
|
+
* this flag indicates we can revert the document. what that means is
|
|
527
|
+
* we loaded a user-created version from localStorage, but there's a
|
|
528
|
+
* backing network or inline document. or we did load the original version
|
|
529
|
+
* but the user has made some document changes.
|
|
530
|
+
*
|
|
531
|
+
* it's like `dirty`, but that uses the load source as the ground truth,
|
|
532
|
+
* which means if you load a modified document from localStorage it's
|
|
533
|
+
* initially considered not-dirty (which is maybe just a bad design?)
|
|
534
|
+
*
|
|
535
|
+
* the intent of this field is to support enabling/disabling revert
|
|
536
|
+
* logic, or to add a visual indicator that you are not looking at the
|
|
537
|
+
* canonical version.
|
|
538
|
+
*
|
|
539
|
+
* @privateRemarks
|
|
540
|
+
* for that to work we need to know that we loaded from localStorage --
|
|
541
|
+
* that's not something we're keeping track of at the moment.
|
|
542
|
+
*
|
|
543
|
+
* it might be good to include the "canonical version" when we put stuff
|
|
544
|
+
* in localStorage...
|
|
545
|
+
*
|
|
546
|
+
*/
|
|
547
|
+
public get can_revert(): boolean {
|
|
548
|
+
|
|
549
|
+
// first check we came from a network source.
|
|
550
|
+
|
|
551
|
+
if (!this.options.inline_document && !this.options.document) {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// next check if we actually loaded from localStorage. for the purposes
|
|
556
|
+
// of this state check we only care about the initial load, so we can
|
|
557
|
+
// store that.
|
|
558
|
+
|
|
559
|
+
if (this.initial_load_source === LoadSource.LOCAL_STORAGE) {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// last check dirty -- that's everything else
|
|
564
|
+
|
|
565
|
+
return this.dirty;
|
|
566
|
+
|
|
567
|
+
}
|
|
568
|
+
|
|
490
569
|
/**
|
|
491
570
|
* indicates the current revision of the document is not equal to the
|
|
492
571
|
* last-saved revision of the document.
|
|
@@ -672,6 +751,7 @@ export class EmbeddedSpreadsheet {
|
|
|
672
751
|
if (options.model) {
|
|
673
752
|
this.model = options.model.model;
|
|
674
753
|
this.calculator = options.model.calculator; // as CalcType;
|
|
754
|
+
this.DOM = options.model.DOM;
|
|
675
755
|
}
|
|
676
756
|
else {
|
|
677
757
|
|
|
@@ -692,11 +772,15 @@ export class EmbeddedSpreadsheet {
|
|
|
692
772
|
//this.extra_calculator = //new Calculator(this.model);
|
|
693
773
|
// this.CreateCalculator(this.model);
|
|
694
774
|
|
|
775
|
+
if (container) {
|
|
776
|
+
this.DOM = DOMContext.GetInstance(container.ownerDocument);
|
|
777
|
+
}
|
|
778
|
+
|
|
695
779
|
// update: tell the grid if we don't want to initialize the DOM,
|
|
696
780
|
// if we don't have a container. that's distinct (at the moment)
|
|
697
781
|
// from headless, which is a state that can change.
|
|
698
782
|
|
|
699
|
-
this.grid = new Grid(grid_options, this.model, undefined, !!container);
|
|
783
|
+
this.grid = new Grid(grid_options, this.model, undefined, !!container, this.DOM);
|
|
700
784
|
|
|
701
785
|
if (this.options.headless) {
|
|
702
786
|
this.grid.headless = true; // FIXME: move into grid options
|
|
@@ -706,6 +790,8 @@ export class EmbeddedSpreadsheet {
|
|
|
706
790
|
|
|
707
791
|
if (container) {
|
|
708
792
|
|
|
793
|
+
this.DOM = DOMContext.GetInstance(container.ownerDocument);
|
|
794
|
+
|
|
709
795
|
// if this is the first one, update UA classes (used to be in grid)
|
|
710
796
|
|
|
711
797
|
if (!this.parent_view) {
|
|
@@ -1003,80 +1089,6 @@ export class EmbeddedSpreadsheet {
|
|
|
1003
1089
|
|
|
1004
1090
|
}
|
|
1005
1091
|
|
|
1006
|
-
/**
|
|
1007
|
-
* we need to load relative resources. we can't access the path of this
|
|
1008
|
-
* script, but because it has to be added via a script tag -- either
|
|
1009
|
-
* statically or dynamically -- we should be able to get it.
|
|
1010
|
-
*
|
|
1011
|
-
* it is possible that the script tag goes away, but if we sniff on first
|
|
1012
|
-
* script execution, we can probably assume it's still there -- because the
|
|
1013
|
-
* client won't have had a chance to remove it yet.
|
|
1014
|
-
*
|
|
1015
|
-
* @internal
|
|
1016
|
-
*/
|
|
1017
|
-
public static BuildPath(): void {
|
|
1018
|
-
const tags = (typeof document === 'undefined') ? [] : document.querySelectorAll('script');
|
|
1019
|
-
|
|
1020
|
-
// FIXME: fragile!
|
|
1021
|
-
const default_script_name = process.env.BUILD_ENTRY_MAIN || '';
|
|
1022
|
-
let rex = new RegExp(default_script_name);
|
|
1023
|
-
|
|
1024
|
-
// tslint:disable-next-line:prefer-for-of
|
|
1025
|
-
for (let i = 0; i < tags.length; i++) {
|
|
1026
|
-
|
|
1027
|
-
const tag = tags[i];
|
|
1028
|
-
const src = tag.src; // fully-qualified here [FIXME: IE11?]
|
|
1029
|
-
|
|
1030
|
-
/*
|
|
1031
|
-
if (src && /\?.*?engine/i.test(src)) {
|
|
1032
|
-
console.info('s', src);
|
|
1033
|
-
this.enable_engine = true;
|
|
1034
|
-
}
|
|
1035
|
-
*/
|
|
1036
|
-
|
|
1037
|
-
if (src && rex.test(src)) {
|
|
1038
|
-
|
|
1039
|
-
/*
|
|
1040
|
-
if (src && /\?.*?utils/i.test(src)) {
|
|
1041
|
-
this.enable_utils = true;
|
|
1042
|
-
}
|
|
1043
|
-
*/
|
|
1044
|
-
|
|
1045
|
-
if (src && /\?.*?engine/i.test(src)) {
|
|
1046
|
-
this.enable_engine = true;
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
if (src && /\?.*?format/i.test(src)) {
|
|
1050
|
-
this.enable_formatter = true;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
this.treb_embedded_script_path = src;
|
|
1054
|
-
this.treb_base_path = src.replace(new RegExp(default_script_name + '.*$'), '');
|
|
1055
|
-
|
|
1056
|
-
return;
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
// to support .mjs imports, look for the import line
|
|
1062
|
-
|
|
1063
|
-
rex = new RegExp(`import.*?from.*?['"](.*?${default_script_name}.*?)['"]`);
|
|
1064
|
-
for (let i = 0; i < tags.length; i++) {
|
|
1065
|
-
const tag = tags[i];
|
|
1066
|
-
if (!tag.src) {
|
|
1067
|
-
const text = tag.textContent;
|
|
1068
|
-
const match = (text||'').match(rex);
|
|
1069
|
-
if (match) {
|
|
1070
|
-
const src = match[1];
|
|
1071
|
-
this.treb_embedded_script_path = src;
|
|
1072
|
-
this.treb_base_path = src.replace(new RegExp(default_script_name + '.*$'), '');
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
1092
|
/**
|
|
1081
1093
|
* update autocomplete functions. we're breaking this out into a
|
|
1082
1094
|
* separate method so we can better manage language translation.
|
|
@@ -1872,6 +1884,17 @@ export class EmbeddedSpreadsheet {
|
|
|
1872
1884
|
this.ShowSidebar(event.command === 'toggle-sidebar' ? undefined : event.command === 'show-sidebar');
|
|
1873
1885
|
break;
|
|
1874
1886
|
|
|
1887
|
+
case 'revert-indicator':
|
|
1888
|
+
this.dialog?.ShowDialog({
|
|
1889
|
+
title: `This is a modified version of the document.\n` +
|
|
1890
|
+
`You can revert to the original or save your\n` +
|
|
1891
|
+
`changes in the sidebar.`,
|
|
1892
|
+
close_box: true,
|
|
1893
|
+
timeout: 5000,
|
|
1894
|
+
type: DialogType.info,
|
|
1895
|
+
});
|
|
1896
|
+
break;
|
|
1897
|
+
|
|
1875
1898
|
default:
|
|
1876
1899
|
console.info('unhandled', event.command);
|
|
1877
1900
|
break;
|
|
@@ -2676,13 +2699,18 @@ export class EmbeddedSpreadsheet {
|
|
|
2676
2699
|
}
|
|
2677
2700
|
|
|
2678
2701
|
/**
|
|
2679
|
-
* revert to the network version of this document, if
|
|
2680
|
-
* and `
|
|
2702
|
+
* revert to the network version of this document, if `local_storage`
|
|
2703
|
+
* is set and the create options had either `document` or `inline-document`
|
|
2704
|
+
* set.
|
|
2705
|
+
*
|
|
2706
|
+
* FIXME: we should adjust for documents that fail to load.
|
|
2681
2707
|
*/
|
|
2682
2708
|
public Revert(): void {
|
|
2683
2709
|
|
|
2684
2710
|
if (this.options.inline_document) {
|
|
2685
2711
|
this.LoadDocument(this.options.inline_document);
|
|
2712
|
+
this.initial_load_source = LoadSource.INLINE_DOCUMENT; // update this flag, even though it's not "initial"
|
|
2713
|
+
|
|
2686
2714
|
if (this.options.local_storage) {
|
|
2687
2715
|
this.SaveLocalStorage('reverted_backup');
|
|
2688
2716
|
localStorage.removeItem(this.options.local_storage);
|
|
@@ -2704,6 +2732,7 @@ export class EmbeddedSpreadsheet {
|
|
|
2704
2732
|
*/
|
|
2705
2733
|
|
|
2706
2734
|
this.LoadNetworkDocument(canonical);
|
|
2735
|
+
this.initial_load_source = LoadSource.NETWORK_FILE; // update this flag, even though it's not "initial"
|
|
2707
2736
|
|
|
2708
2737
|
// flush storage? what about mistakes? maybe we should
|
|
2709
2738
|
// back it up somewhere? (...)
|
|
@@ -3203,6 +3232,10 @@ export class EmbeddedSpreadsheet {
|
|
|
3203
3232
|
return this.parent_view.LoadDocument(data, options);
|
|
3204
3233
|
}
|
|
3205
3234
|
|
|
3235
|
+
if (!this.initial_load_source) {
|
|
3236
|
+
this.initial_load_source = options.source;
|
|
3237
|
+
}
|
|
3238
|
+
|
|
3206
3239
|
// API v1 OK
|
|
3207
3240
|
|
|
3208
3241
|
/*
|
|
@@ -3298,7 +3331,7 @@ export class EmbeddedSpreadsheet {
|
|
|
3298
3331
|
|
|
3299
3332
|
if (options.scroll) {
|
|
3300
3333
|
const scroll = options.scroll;
|
|
3301
|
-
|
|
3334
|
+
Promise.resolve().then(() => this.ScrollTo(scroll));
|
|
3302
3335
|
}
|
|
3303
3336
|
|
|
3304
3337
|
}
|
|
@@ -4343,7 +4376,7 @@ export class EmbeddedSpreadsheet {
|
|
|
4343
4376
|
*/
|
|
4344
4377
|
protected SaveAs(blob: Blob, filename: string) {
|
|
4345
4378
|
|
|
4346
|
-
const a =
|
|
4379
|
+
const a = this.DOM.Create('a');
|
|
4347
4380
|
a.href = URL.createObjectURL(blob);
|
|
4348
4381
|
a.download = filename;
|
|
4349
4382
|
a.click();
|
|
@@ -4468,7 +4501,7 @@ export class EmbeddedSpreadsheet {
|
|
|
4468
4501
|
return;
|
|
4469
4502
|
}
|
|
4470
4503
|
|
|
4471
|
-
const a =
|
|
4504
|
+
const a = this.DOM.Create('a');
|
|
4472
4505
|
a.setAttribute('target', this.options.hyperlinks);
|
|
4473
4506
|
a.setAttribute('href', data);
|
|
4474
4507
|
a.setAttribute('noreferrer', 'true');
|
|
@@ -4609,27 +4642,29 @@ export class EmbeddedSpreadsheet {
|
|
|
4609
4642
|
protected SelectFile2(accept: string, operation: FileChooserOperation) {
|
|
4610
4643
|
|
|
4611
4644
|
if (!this.file_chooser) {
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4645
|
+
const file_chooser = this.DOM.Create('input', undefined, undefined, {
|
|
4646
|
+
attrs: { type: 'file' },
|
|
4647
|
+
events: {
|
|
4648
|
+
change: () => {
|
|
4649
|
+
if (file_chooser.files && file_chooser.files[0]) {
|
|
4650
|
+
const file = file_chooser.files[0];
|
|
4651
|
+
file_chooser.value = '';
|
|
4652
|
+
switch (this.file_chooser_operation) {
|
|
4653
|
+
case FileChooserOperation.InsertImage:
|
|
4654
|
+
this.InsertImageInternal(file);
|
|
4655
|
+
break;
|
|
4656
|
+
case FileChooserOperation.LoadFile:
|
|
4657
|
+
this.LoadFileInternal(file, LoadSource.LOCAL_FILE, true);
|
|
4658
|
+
break;
|
|
4659
|
+
default:
|
|
4660
|
+
console.warn('file chooser: no operation');
|
|
4661
|
+
break;
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4664
|
+
},
|
|
4665
|
+
},
|
|
4632
4666
|
});
|
|
4667
|
+
this.file_chooser = file_chooser;
|
|
4633
4668
|
}
|
|
4634
4669
|
|
|
4635
4670
|
if (!this.file_chooser) {
|
|
@@ -4686,7 +4721,7 @@ export class EmbeddedSpreadsheet {
|
|
|
4686
4721
|
}
|
|
4687
4722
|
}
|
|
4688
4723
|
|
|
4689
|
-
const img =
|
|
4724
|
+
const img = this.DOM.Create('img');
|
|
4690
4725
|
img.src = contents;
|
|
4691
4726
|
|
|
4692
4727
|
// this is to let the browser figure out the image size.
|
|
@@ -5051,7 +5086,7 @@ export class EmbeddedSpreadsheet {
|
|
|
5051
5086
|
const reference = ValidateURI(annotation.data.data.src);
|
|
5052
5087
|
if (reference) {
|
|
5053
5088
|
|
|
5054
|
-
const img =
|
|
5089
|
+
const img = this.DOM.Create('img');
|
|
5055
5090
|
img.src = reference;
|
|
5056
5091
|
|
|
5057
5092
|
if (annotation.data.data.scale === 'fixed') {
|
|
@@ -5081,7 +5116,7 @@ export class EmbeddedSpreadsheet {
|
|
|
5081
5116
|
*/
|
|
5082
5117
|
protected DocumentChange(undo_selection?: string): void {
|
|
5083
5118
|
|
|
5084
|
-
|
|
5119
|
+
Promise.resolve().then(() => {
|
|
5085
5120
|
|
|
5086
5121
|
// console.info('serializing');
|
|
5087
5122
|
|
|
@@ -94,6 +94,9 @@ export interface EmbeddedSpreadsheetOptions {
|
|
|
94
94
|
/** add resizable wrapper */
|
|
95
95
|
resizable?: boolean;
|
|
96
96
|
|
|
97
|
+
/** even if we allow resizing, constrain width. this is to support fixed width columns. */
|
|
98
|
+
constrain_width?: boolean;
|
|
99
|
+
|
|
97
100
|
/** export to xlsx, now optional */
|
|
98
101
|
export?: boolean;
|
|
99
102
|
|
|
@@ -266,6 +269,12 @@ export interface EmbeddedSpreadsheetOptions {
|
|
|
266
269
|
*/
|
|
267
270
|
revert_button?: boolean;
|
|
268
271
|
|
|
272
|
+
/**
|
|
273
|
+
* show the revert indicator. this is an indicator that shows on the
|
|
274
|
+
* top-left of the spreadsheet when a network document has local changes.
|
|
275
|
+
*/
|
|
276
|
+
revert_indicator?: boolean;
|
|
277
|
+
|
|
269
278
|
}
|
|
270
279
|
|
|
271
280
|
/**
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import { DOMContext } from 'treb-base-types';
|
|
23
23
|
|
|
24
24
|
export class Spinner {
|
|
25
25
|
|
|
@@ -27,8 +27,10 @@ export class Spinner {
|
|
|
27
27
|
private visible = false;
|
|
28
28
|
|
|
29
29
|
constructor(public container: HTMLElement) {
|
|
30
|
-
|
|
31
|
-
this.node
|
|
30
|
+
const DOM = DOMContext.GetInstance(container.ownerDocument);
|
|
31
|
+
this.node = DOM.Div('treb-spinner', container, {
|
|
32
|
+
html: `<div><div></div><div></div><div></div><div></div></div>`,
|
|
33
|
+
});
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
public Show(): void {
|
|
@@ -76,6 +76,10 @@ export interface UIToolbarMessage {
|
|
|
76
76
|
command: 'toggle-toolbar'|'show-toolbar'|'hide-toolbar'|'toggle-sidebar'|'show-sidebar'|'hide-sidebar';
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
export interface RevertIndicatorMessage {
|
|
80
|
+
command: 'revert-indicator';
|
|
81
|
+
}
|
|
82
|
+
|
|
79
83
|
export type ToolbarMessage
|
|
80
84
|
= SetColorToolbarMessage
|
|
81
85
|
| CommentToolbarMessage
|
|
@@ -87,6 +91,7 @@ export type ToolbarMessage
|
|
|
87
91
|
| AnnotationToolbarMessage
|
|
88
92
|
| PrecisionToolbarMessage
|
|
89
93
|
| JustifyToolbarMessage
|
|
94
|
+
| RevertIndicatorMessage
|
|
90
95
|
| AlignToolbarMessage
|
|
91
96
|
| TableToolbarMessage
|
|
92
97
|
| CommandToolbarMessage
|
|
@@ -187,6 +187,13 @@
|
|
|
187
187
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
.treb-views.treb-can-revert .treb-view {
|
|
191
|
+
.treb-revert-indicator {
|
|
192
|
+
opacity: 1;
|
|
193
|
+
pointer-events: initial;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
190
197
|
.treb-view {
|
|
191
198
|
|
|
192
199
|
position: relative;
|
|
@@ -219,6 +226,50 @@
|
|
|
219
226
|
display: none;
|
|
220
227
|
}
|
|
221
228
|
|
|
229
|
+
.treb-revert-indicator {
|
|
230
|
+
display: none;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
&:first-of-type {
|
|
234
|
+
|
|
235
|
+
.treb-revert-indicator {
|
|
236
|
+
display: block;
|
|
237
|
+
grid-area: 2/1/3/2; // overlap the grid body
|
|
238
|
+
justify-self: start;
|
|
239
|
+
align-self: start;
|
|
240
|
+
width: 1rem;
|
|
241
|
+
height: 1rem;
|
|
242
|
+
position: relative;
|
|
243
|
+
overflow: hidden;
|
|
244
|
+
opacity: 0;
|
|
245
|
+
transition: opacity .125s ease;
|
|
246
|
+
pointer-events: none;
|
|
247
|
+
|
|
248
|
+
/* rounded style
|
|
249
|
+
&::after {
|
|
250
|
+
content: '';
|
|
251
|
+
position: absolute;
|
|
252
|
+
display: block;
|
|
253
|
+
top: -1rem;
|
|
254
|
+
left: -1rem;
|
|
255
|
+
border-radius: 1rem;
|
|
256
|
+
border: 1rem solid orange;
|
|
257
|
+
}
|
|
258
|
+
*/
|
|
259
|
+
|
|
260
|
+
/* triangular style */
|
|
261
|
+
|
|
262
|
+
border: .5em solid orange;
|
|
263
|
+
border-right-color: transparent;
|
|
264
|
+
border-bottom-color: transparent;
|
|
265
|
+
|
|
266
|
+
/* end styles */
|
|
267
|
+
|
|
268
|
+
z-index: 20; // FIXME: use stack
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
|
|
222
273
|
&:last-of-type {
|
|
223
274
|
|
|
224
275
|
.treb-layout-resize-handle {
|
|
@@ -331,8 +382,21 @@
|
|
|
331
382
|
-webkit-mask-image: var(--icon);
|
|
332
383
|
}
|
|
333
384
|
|
|
385
|
+
// working on how to alter the revert button depending on state...
|
|
386
|
+
// remove hover effect? remove the button? (...)
|
|
387
|
+
|
|
388
|
+
/*
|
|
389
|
+
&:not(.sidebar-disabled):hover::after{
|
|
390
|
+
background: #666; // FIXME
|
|
391
|
+
}
|
|
392
|
+
*/
|
|
393
|
+
|
|
394
|
+
&[data-can-revert=false] {
|
|
395
|
+
display: none;
|
|
396
|
+
}
|
|
397
|
+
|
|
334
398
|
&:hover::after {
|
|
335
|
-
background: #666;
|
|
399
|
+
background: #666; // FIXME
|
|
336
400
|
}
|
|
337
401
|
|
|
338
402
|
&[data-command=recalculate] {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import { DOMContext } from 'treb-base-types';
|
|
23
23
|
import type { Theme, Rectangle } from 'treb-base-types';
|
|
24
24
|
import type { AutocompleteExecResult, DescriptorType } from './autocomplete_matcher';
|
|
25
25
|
|
|
@@ -72,26 +72,37 @@ export class Autocomplete {
|
|
|
72
72
|
|
|
73
73
|
private active_element?: HTMLElement;
|
|
74
74
|
|
|
75
|
+
private DOM: DOMContext;
|
|
76
|
+
|
|
75
77
|
constructor(private options: AutocompleteOptions = {}){
|
|
76
78
|
|
|
79
|
+
this.DOM = DOMContext.GetInstance(options.container?.ownerDocument);
|
|
80
|
+
if (!this.DOM.doc) {
|
|
81
|
+
throw new Error('invalid context');
|
|
82
|
+
}
|
|
83
|
+
|
|
77
84
|
// this.scope = 'AC' + Math.round(Math.random() * Math.pow(10, 10)).toString(16);
|
|
78
85
|
|
|
79
|
-
this.completion_list =
|
|
86
|
+
this.completion_list = this.DOM.Div(
|
|
80
87
|
'treb-cell-editor-ac-list treb-autocomplete',
|
|
81
|
-
options.container ||
|
|
82
|
-
|
|
88
|
+
options.container || this.DOM.doc.body,
|
|
89
|
+
{
|
|
90
|
+
events: {
|
|
91
|
+
mousedown: (event) => this.ListMouseDown(event),
|
|
92
|
+
mousemove: (event) => this.ListMouseMove(event)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
);
|
|
83
96
|
|
|
84
|
-
this.completion_list.addEventListener('mousedown', (event) => this.ListMouseDown(event));
|
|
97
|
+
// this.completion_list.addEventListener('mousedown', (event) => this.ListMouseDown(event));
|
|
85
98
|
|
|
86
99
|
// FIXME: should we add/remove listener based on visibility? (...)
|
|
87
100
|
|
|
88
|
-
this.completion_list.addEventListener('mousemove', (event) => this.ListMouseMove(event));
|
|
89
|
-
|
|
90
|
-
this.tooltip = DOMUtilities.Div('treb-cell-editor-ac-tooltip treb-autocomplete-tooltip',
|
|
91
|
-
options.container || document.body,
|
|
92
|
-
); // this.scope);
|
|
101
|
+
// this.completion_list.addEventListener('mousemove', (event) => this.ListMouseMove(event));
|
|
93
102
|
|
|
94
|
-
|
|
103
|
+
this.tooltip = this.DOM.Div(
|
|
104
|
+
'treb-cell-editor-ac-tooltip treb-autocomplete-tooltip',
|
|
105
|
+
options.container || this.DOM.doc.body);
|
|
95
106
|
|
|
96
107
|
}
|
|
97
108
|
|
|
@@ -360,8 +371,8 @@ export class Autocomplete {
|
|
|
360
371
|
// compiler thinks this is possibly undefined, but vs code does
|
|
361
372
|
// not -- I thought vs code used the same tsc we use to compile?
|
|
362
373
|
|
|
363
|
-
if (
|
|
364
|
-
const viewport_height = Math.max(
|
|
374
|
+
if (this.DOM.doc?.documentElement) {
|
|
375
|
+
const viewport_height = Math.max(this.DOM.doc.documentElement.clientHeight, this.DOM.view?.innerHeight || 0);
|
|
365
376
|
if (viewport_height - position.bottom < 200 ){
|
|
366
377
|
layout_top = true;
|
|
367
378
|
}
|