@trebco/treb 30.2.4 → 30.2.14
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-light.mjs +11 -11
- package/dist/treb-spreadsheet.mjs +11 -11
- package/dist/treb.d.ts +1 -1
- package/esbuild-custom-element.mjs +2 -0
- package/esbuild-utils.mjs +2 -0
- package/package.json +6 -7
- package/treb-calculator/src/calculator.ts +41 -0
- package/treb-calculator/src/expression-calculator.ts +30 -1
- package/treb-calculator/src/functions/base-functions.ts +164 -1
- package/treb-calculator/src/functions/statistics-functions.ts +134 -0
- package/treb-calculator/src/functions/text-functions.ts +46 -1
- package/treb-calculator/src/primitives.ts +3 -1
- package/treb-calculator/src/utilities.ts +5 -1
- package/treb-data-model/src/data_model.ts +227 -2
- package/treb-data-model/src/index.ts +1 -0
- package/{treb-embed → treb-data-model}/src/language-model.ts +3 -0
- package/treb-data-model/src/sheet.ts +0 -13
- package/treb-embed/src/embedded-spreadsheet.ts +22 -39
- package/treb-embed/style/autocomplete.scss +2 -18
- package/treb-embed/style/dialog.scss +1 -1
- package/treb-embed/style/dropdown-select.scss +5 -6
- package/treb-embed/style/formula-bar.scss +5 -3
- package/treb-embed/style/grid.scss +7 -4
- package/treb-embed/style/layout.scss +23 -18
- package/treb-embed/style/tab-bar.scss +2 -2
- package/treb-embed/style/theme-defaults.scss +4 -4
- package/treb-embed/style/toolbar.scss +1 -1
- package/treb-grid/src/render/tile_renderer.ts +14 -0
- package/treb-grid/src/types/grid.ts +25 -139
- package/treb-parser/src/parser-types.ts +12 -0
- package/treb-parser/src/parser.ts +43 -2
- package/tsproject.json +1 -1
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
import type { Sheet } from './sheet';
|
|
23
23
|
import { SheetCollection } from './sheet_collection';
|
|
24
24
|
import { type UnitAddress, type UnitStructuredReference, type UnitRange, Parser, QuotedSheetNameRegex, DecimalMarkType, ArgumentSeparatorType } from 'treb-parser';
|
|
25
|
-
import type { IArea, ICellAddress, Table, CellStyle } from 'treb-base-types';
|
|
25
|
+
import type { IArea, ICellAddress, Table, CellStyle, CellValue } from 'treb-base-types';
|
|
26
|
+
import { Is2DArray } from 'treb-base-types';
|
|
26
27
|
import { Area, IsCellAddress, Style } from 'treb-base-types';
|
|
27
28
|
import type { SerializedNamed } from './named';
|
|
28
29
|
import { NamedRangeManager } from './named';
|
|
29
30
|
import type { ConnectedElementType, MacroFunction } from './types';
|
|
30
|
-
|
|
31
|
+
import type { LanguageModel } from './language-model';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
*
|
|
@@ -36,6 +37,9 @@ export class DataModel {
|
|
|
36
37
|
|
|
37
38
|
public readonly parser: Parser = new Parser();
|
|
38
39
|
|
|
40
|
+
/** moved from embedded spreadsheet */
|
|
41
|
+
public language_model?: LanguageModel;
|
|
42
|
+
|
|
39
43
|
/** document metadata */
|
|
40
44
|
public document_name?: string;
|
|
41
45
|
|
|
@@ -523,5 +527,226 @@ export class DataModel {
|
|
|
523
527
|
*/
|
|
524
528
|
public connected_elements: Map<number, ConnectedElementType> = new Map();
|
|
525
529
|
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
// --- moving translation here ----------------------------------------------
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* maps common language (english) -> local language. this should
|
|
537
|
+
* be passed in (actually set via a function).
|
|
538
|
+
*/
|
|
539
|
+
private language_map?: Record<string, string>;
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* maps local language -> common (english). this should be constructed
|
|
543
|
+
* when the forward function is passed in, so there's a 1-1 correspondence.
|
|
544
|
+
*/
|
|
545
|
+
private reverse_language_map?: Record<string, string>;
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* set the language translation map. this is a set of function names
|
|
550
|
+
* (in english) -> the local equivalent. both should be in canonical form,
|
|
551
|
+
* as that will be used when we translate one way or the other.
|
|
552
|
+
*/
|
|
553
|
+
public SetLanguageMap(language_map?: Record<string, string>) {
|
|
554
|
+
|
|
555
|
+
if (!language_map) {
|
|
556
|
+
this.language_map = this.reverse_language_map = undefined;
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
|
|
560
|
+
const keys = Object.keys(language_map);
|
|
561
|
+
|
|
562
|
+
// normalize forward
|
|
563
|
+
this.language_map = {};
|
|
564
|
+
for (const key of keys) {
|
|
565
|
+
this.language_map[key.toUpperCase()] = language_map[key];
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// normalize backward
|
|
569
|
+
this.reverse_language_map = {};
|
|
570
|
+
for (const key of keys) {
|
|
571
|
+
const value = language_map[key];
|
|
572
|
+
this.reverse_language_map[value.toUpperCase()] = key;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/*
|
|
578
|
+
// we might need to update the current displayed selection. depends
|
|
579
|
+
// on when we expect languages to be set.
|
|
580
|
+
|
|
581
|
+
if (!this.primary_selection.empty) {
|
|
582
|
+
this.Select(this.primary_selection, this.primary_selection.area, this.primary_selection.target);
|
|
583
|
+
}
|
|
584
|
+
*/
|
|
585
|
+
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* translate function from common (english) -> local language. this could
|
|
590
|
+
* be inlined (assuming it's only called in one place), but we are breaking
|
|
591
|
+
* it out so we can develop/test/manage it.
|
|
592
|
+
*/
|
|
593
|
+
public TranslateFunction(value: string): string {
|
|
594
|
+
if (this.language_map) {
|
|
595
|
+
return this.TranslateInternal(value, this.language_map, this.language_model?.boolean_true, this.language_model?.boolean_false);
|
|
596
|
+
}
|
|
597
|
+
return value;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* translate from local language -> common (english).
|
|
602
|
+
* @see TranslateFunction
|
|
603
|
+
*/
|
|
604
|
+
public UntranslateFunction(value: string): string {
|
|
605
|
+
if (this.reverse_language_map) {
|
|
606
|
+
return this.TranslateInternal(value, this.reverse_language_map, 'TRUE', 'FALSE');
|
|
607
|
+
}
|
|
608
|
+
return value;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
public UntranslateData(value: CellValue|CellValue[]|CellValue[][]): CellValue|CellValue[]|CellValue[][] {
|
|
612
|
+
|
|
613
|
+
if (Array.isArray(value)) {
|
|
614
|
+
|
|
615
|
+
// could be 1d or 2d. typescript is complaining, not sure why...
|
|
616
|
+
|
|
617
|
+
if (Is2DArray(value)) {
|
|
618
|
+
return value.map(row => row.map(entry => {
|
|
619
|
+
if (entry && typeof entry === 'string' && entry[0] === '=') {
|
|
620
|
+
return this.UntranslateFunction(entry);
|
|
621
|
+
}
|
|
622
|
+
return entry;
|
|
623
|
+
}));
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
return value.map(entry => {
|
|
627
|
+
if (entry && typeof entry === 'string' && entry[0] === '=') {
|
|
628
|
+
return this.UntranslateFunction(entry);
|
|
629
|
+
}
|
|
630
|
+
return entry;
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
}
|
|
635
|
+
else if (value && typeof value === 'string' && value[0] === '=') {
|
|
636
|
+
|
|
637
|
+
// single value
|
|
638
|
+
value = this.UntranslateFunction(value);
|
|
639
|
+
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
return value;
|
|
643
|
+
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* translation back and forth is the same operation, with a different
|
|
649
|
+
* (inverted) map. although it still might be worth inlining depending
|
|
650
|
+
* on cost.
|
|
651
|
+
*
|
|
652
|
+
* FIXME: it's about time we started using proper maps, we dropped
|
|
653
|
+
* support for IE11 some time ago.
|
|
654
|
+
*/
|
|
655
|
+
private TranslateInternal(value: string, map: Record<string, string>, boolean_true?: string, boolean_false?: string): string {
|
|
656
|
+
|
|
657
|
+
const parse_result = this.parser.Parse(value);
|
|
658
|
+
|
|
659
|
+
if (parse_result.expression) {
|
|
660
|
+
|
|
661
|
+
let modified = false;
|
|
662
|
+
this.parser.Walk(parse_result.expression, unit => {
|
|
663
|
+
if (unit.type === 'call') {
|
|
664
|
+
const replacement = map[unit.name.toUpperCase()];
|
|
665
|
+
if (replacement) {
|
|
666
|
+
modified = true;
|
|
667
|
+
unit.name = replacement;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
else if (unit.type === 'literal' && typeof unit.value === 'boolean') {
|
|
671
|
+
|
|
672
|
+
// to/from english/locale depends on the direction, but we're not
|
|
673
|
+
// passing that in? FIXME, pass it as a parameter. it doesn't matter
|
|
674
|
+
// here, but later when we render.
|
|
675
|
+
|
|
676
|
+
modified = true;
|
|
677
|
+
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return true;
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
if (modified) {
|
|
684
|
+
return '=' + this.parser.Render(parse_result.expression, {
|
|
685
|
+
missing: '', boolean_true, boolean_false,
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
return value;
|
|
691
|
+
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* this is not public _yet_
|
|
697
|
+
*
|
|
698
|
+
* @internal
|
|
699
|
+
*/
|
|
700
|
+
public SetLanguage(model?: LanguageModel): void {
|
|
701
|
+
|
|
702
|
+
this.language_model = model;
|
|
703
|
+
|
|
704
|
+
if (!model) {
|
|
705
|
+
this.SetLanguageMap(); // clear
|
|
706
|
+
|
|
707
|
+
// set defaults for parsing.
|
|
708
|
+
|
|
709
|
+
this.parser.flags.boolean_true = 'TRUE';
|
|
710
|
+
this.parser.flags.boolean_false = 'FALSE';
|
|
711
|
+
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
714
|
+
|
|
715
|
+
// create a name map for grid
|
|
716
|
+
|
|
717
|
+
const map: Record< string, string > = {};
|
|
718
|
+
|
|
719
|
+
if (model.functions) {
|
|
720
|
+
for (const entry of model.functions || []) {
|
|
721
|
+
map[entry.base.toUpperCase()] = entry.name; // toUpperCase because of a data error -- fix at the source
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
this.SetLanguageMap(map);
|
|
726
|
+
|
|
727
|
+
// console.info({map});
|
|
728
|
+
|
|
729
|
+
if (!model.boolean_false) {
|
|
730
|
+
model.boolean_false = map['FALSE'];
|
|
731
|
+
}
|
|
732
|
+
if (!model.boolean_true) {
|
|
733
|
+
model.boolean_true = map['TRUE'];
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// set defaults for parsing.
|
|
737
|
+
|
|
738
|
+
this.parser.flags.boolean_true = model.boolean_true || 'TRUE';
|
|
739
|
+
this.parser.flags.boolean_false = model.boolean_false || 'FALSE';
|
|
740
|
+
|
|
741
|
+
// console.info("booleans:", this.model.parser.flags.boolean_true, ",", this.model.parser.flags.boolean_false)
|
|
742
|
+
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
for (const sheet of this.sheets.list) {
|
|
746
|
+
sheet.FlushCellStyles();
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
}
|
|
750
|
+
|
|
526
751
|
}
|
|
527
752
|
|
|
@@ -807,19 +807,6 @@ export class Sheet {
|
|
|
807
807
|
}
|
|
808
808
|
}
|
|
809
809
|
|
|
810
|
-
/* *
|
|
811
|
-
* factory method creates a sheet from a 2D array.
|
|
812
|
-
*
|
|
813
|
-
* /
|
|
814
|
-
public static FromArray(data: any[] = [], transpose = false): Sheet {
|
|
815
|
-
const sheet = new Sheet();
|
|
816
|
-
sheet.cells.FromArray(data, transpose);
|
|
817
|
-
|
|
818
|
-
return sheet;
|
|
819
|
-
}
|
|
820
|
-
*/
|
|
821
|
-
|
|
822
|
-
|
|
823
810
|
// --- public methods -------------------------------------------------------
|
|
824
811
|
|
|
825
812
|
public MergeCells(area: Area): void {
|
|
@@ -49,7 +49,10 @@ import type {
|
|
|
49
49
|
CondifionalFormatExpressionOptions,
|
|
50
50
|
ConditionalFormatCellMatchOptions,
|
|
51
51
|
ConditionalFormatCellMatch,
|
|
52
|
-
|
|
52
|
+
|
|
53
|
+
LanguageModel,
|
|
54
|
+
TranslatedFunctionDescriptor,
|
|
55
|
+
|
|
53
56
|
} from 'treb-data-model';
|
|
54
57
|
|
|
55
58
|
|
|
@@ -88,7 +91,6 @@ import { Spinner } from './spinner';
|
|
|
88
91
|
import { type EmbeddedSpreadsheetOptions, DefaultOptions, type ExportOptions } from './options';
|
|
89
92
|
import { type TREBDocument, SaveFileType, LoadSource, type EmbeddedSheetEvent, type InsertTableOptions } from './types';
|
|
90
93
|
|
|
91
|
-
import type { LanguageModel, TranslatedFunctionDescriptor } from './language-model';
|
|
92
94
|
import type { SelectionState } from './selection-state';
|
|
93
95
|
import type { BorderToolbarMessage, ToolbarMessage } from './toolbar-message';
|
|
94
96
|
|
|
@@ -341,8 +343,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
341
343
|
return Localization;
|
|
342
344
|
}
|
|
343
345
|
|
|
344
|
-
|
|
346
|
+
/* * loaded language model, if any (moved to data model) * /
|
|
345
347
|
protected language_model?: LanguageModel;
|
|
348
|
+
*/
|
|
346
349
|
|
|
347
350
|
/** FIXME: fix type (needs to be extensible) */
|
|
348
351
|
protected events = new EventSource<{ type: string }>();
|
|
@@ -800,7 +803,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
800
803
|
const obj = JSON.parse(json);
|
|
801
804
|
grid_options.initial_scale = obj.scale || 1;
|
|
802
805
|
}
|
|
803
|
-
catch
|
|
806
|
+
catch {
|
|
804
807
|
console.warn('parsing persisted scale failed');
|
|
805
808
|
}
|
|
806
809
|
}
|
|
@@ -1204,10 +1207,10 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
1204
1207
|
|
|
1205
1208
|
let list: FunctionDescriptor[] = this.calculator.SupportedFunctions();
|
|
1206
1209
|
|
|
1207
|
-
if (this.language_model?.functions) {
|
|
1210
|
+
if (this.model.language_model?.functions) {
|
|
1208
1211
|
|
|
1209
1212
|
const map: Record<string, TranslatedFunctionDescriptor> = {};
|
|
1210
|
-
for (const entry of this.language_model.functions || []) {
|
|
1213
|
+
for (const entry of this.model.language_model.functions || []) {
|
|
1211
1214
|
map[entry.base.toUpperCase()] = entry;
|
|
1212
1215
|
}
|
|
1213
1216
|
|
|
@@ -2002,13 +2005,18 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2002
2005
|
language = parts[0];
|
|
2003
2006
|
}
|
|
2004
2007
|
|
|
2005
|
-
this.SetLanguage(); // clear
|
|
2006
|
-
|
|
2007
2008
|
language = language.toLowerCase();
|
|
2008
|
-
|
|
2009
2009
|
let mod: { LanguageMap: LanguageModel } | undefined;
|
|
2010
2010
|
|
|
2011
|
-
|
|
2011
|
+
// FIXME: this should be generated and included, to allow for changes.
|
|
2012
|
+
// for the time being hardcoding as a quick fix
|
|
2013
|
+
|
|
2014
|
+
const supported_languages = [
|
|
2015
|
+
'es', 'fr', 'pt', 'nl', 'de',
|
|
2016
|
+
'pl', 'sv', 'no', 'da', 'it',
|
|
2017
|
+
];
|
|
2018
|
+
|
|
2019
|
+
if (language && supported_languages.includes(language)) {
|
|
2012
2020
|
|
|
2013
2021
|
// FIXME: even though we now have a dynamic import
|
|
2014
2022
|
// working, we still probably want to use a filter
|
|
@@ -2029,39 +2037,14 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2029
2037
|
}
|
|
2030
2038
|
|
|
2031
2039
|
if (mod) {
|
|
2032
|
-
this.SetLanguage(mod.LanguageMap);
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
}
|
|
2036
|
-
|
|
2037
|
-
/**
|
|
2038
|
-
* this is not public _yet_
|
|
2039
|
-
*
|
|
2040
|
-
* @internal
|
|
2041
|
-
*/
|
|
2042
|
-
public SetLanguage(model?: LanguageModel): void {
|
|
2043
|
-
|
|
2044
|
-
this.language_model = model;
|
|
2045
|
-
|
|
2046
|
-
if (!model) {
|
|
2047
|
-
this.grid.SetLanguageMap(); // clear
|
|
2040
|
+
this.model.SetLanguage(mod.LanguageMap);
|
|
2048
2041
|
}
|
|
2049
2042
|
else {
|
|
2050
|
-
|
|
2051
|
-
// create a name map for grid
|
|
2052
|
-
|
|
2053
|
-
const map: Record< string, string > = {};
|
|
2054
|
-
|
|
2055
|
-
if (model.functions) {
|
|
2056
|
-
for (const entry of model.functions || []) {
|
|
2057
|
-
map[entry.base] = entry.name;
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
|
|
2061
|
-
this.grid.SetLanguageMap(map);
|
|
2062
|
-
|
|
2043
|
+
this.model.SetLanguage();
|
|
2063
2044
|
}
|
|
2064
2045
|
|
|
2046
|
+
this.grid.Reselect();
|
|
2047
|
+
this.grid.Update(true);
|
|
2065
2048
|
this.UpdateAC();
|
|
2066
2049
|
|
|
2067
2050
|
}
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
box-sizing: border-box;
|
|
36
|
-
* { box-sizing: border-box; }
|
|
37
36
|
|
|
38
37
|
position: fixed;
|
|
39
38
|
top: -1000px;
|
|
@@ -46,6 +45,8 @@
|
|
|
46
45
|
overflow-y: auto;
|
|
47
46
|
z-index: $z-index-autocomplete;
|
|
48
47
|
|
|
48
|
+
* { box-sizing: border-box; }
|
|
49
|
+
|
|
49
50
|
ul {
|
|
50
51
|
|
|
51
52
|
font-size: inherit;
|
|
@@ -73,23 +74,6 @@
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
/*
|
|
77
|
-
here we unwind the selected style if there's a hover,
|
|
78
|
-
unless you're hovering over the selection. and so on.
|
|
79
|
-
* /
|
|
80
|
-
|
|
81
|
-
&:hover li a.selected {
|
|
82
|
-
background: inherit;
|
|
83
|
-
color: inherit;
|
|
84
|
-
|
|
85
|
-
&:hover {
|
|
86
|
-
background: #339966;
|
|
87
|
-
color: #fff;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
*/
|
|
92
|
-
|
|
93
77
|
}
|
|
94
78
|
}
|
|
95
79
|
|
|
@@ -56,6 +56,11 @@
|
|
|
56
56
|
color: var(--treb-dropdown-color, inherit);
|
|
57
57
|
border: 1px solid var(--treb-dropdown-border-color, unset);
|
|
58
58
|
|
|
59
|
+
text-align: left;
|
|
60
|
+
max-height: 10em;
|
|
61
|
+
overflow-y: auto;
|
|
62
|
+
outline: none;
|
|
63
|
+
|
|
59
64
|
& div {
|
|
60
65
|
padding: 2px;
|
|
61
66
|
cursor: default;
|
|
@@ -66,12 +71,6 @@
|
|
|
66
71
|
color: var(--treb-dropdown-selected-color, #fff);
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
text-align: left;
|
|
70
|
-
|
|
71
|
-
max-height: 10em;
|
|
72
|
-
overflow-y: auto;
|
|
73
|
-
outline: none;
|
|
74
|
-
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
.treb-dropdown-caret.active {
|
|
@@ -30,15 +30,17 @@
|
|
|
30
30
|
text-align: left;
|
|
31
31
|
gap: .5em;
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
display: none;
|
|
35
|
-
}
|
|
33
|
+
|
|
36
34
|
|
|
37
35
|
padding: 0px 2px 12px 2px; // FIXME: use ems?
|
|
38
36
|
|
|
39
37
|
max-width: 100%;
|
|
40
38
|
overflow-x: hidden;
|
|
41
39
|
|
|
40
|
+
&[hidden] {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
42
44
|
/** label for selection address */
|
|
43
45
|
.treb-address-label {
|
|
44
46
|
|
|
@@ -207,23 +207,25 @@
|
|
|
207
207
|
/** specific layout for column header cover */
|
|
208
208
|
&.column-header-cover {
|
|
209
209
|
|
|
210
|
+
z-index: $z-index-header-tile-cover;
|
|
211
|
+
|
|
210
212
|
/** style is attached when mousing over a column boundary */
|
|
211
213
|
&.resize {
|
|
212
214
|
cursor: col-resize;
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
z-index: $z-index-header-tile-cover;
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
/** specific layout for row header cover */
|
|
219
220
|
&.row-header-cover {
|
|
220
221
|
|
|
222
|
+
z-index: $z-index-header-tile-cover;
|
|
223
|
+
|
|
221
224
|
/** style is attached when mousing over a row boundary */
|
|
222
225
|
&.resize {
|
|
223
226
|
cursor: row-resize;
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
z-index: $z-index-header-tile-cover;
|
|
227
229
|
}
|
|
228
230
|
|
|
229
231
|
}
|
|
@@ -234,6 +236,9 @@
|
|
|
234
236
|
top: 0px;
|
|
235
237
|
left: 0px;
|
|
236
238
|
|
|
239
|
+
z-index: $z-index-annotations;
|
|
240
|
+
pointer-events: none;
|
|
241
|
+
|
|
237
242
|
.annotation {
|
|
238
243
|
position: absolute;
|
|
239
244
|
overflow: hidden;
|
|
@@ -297,8 +302,6 @@
|
|
|
297
302
|
cursor: move;
|
|
298
303
|
}
|
|
299
304
|
|
|
300
|
-
z-index: $z-index-annotations;
|
|
301
|
-
pointer-events: none;
|
|
302
305
|
}
|
|
303
306
|
|
|
304
307
|
/** selection stacks over the grid but under the cover */
|
|
@@ -68,6 +68,28 @@
|
|
|
68
68
|
|
|
69
69
|
line-height: normal;
|
|
70
70
|
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
color-scheme: var(--treb-color-scheme, unset);
|
|
74
|
+
|
|
75
|
+
font-family: $font-stack;
|
|
76
|
+
|
|
77
|
+
font-style: normal;
|
|
78
|
+
font-weight: normal;
|
|
79
|
+
color: inherit;
|
|
80
|
+
font-size: 14px; // ?
|
|
81
|
+
|
|
82
|
+
height: 100%;
|
|
83
|
+
width: 100%;
|
|
84
|
+
|
|
85
|
+
position: relative;
|
|
86
|
+
display: grid;
|
|
87
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
88
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
89
|
+
// gap: 1em;
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
71
93
|
div, button, input, ul, ol, li, a, textarea, svg {
|
|
72
94
|
|
|
73
95
|
// maybe this is being too aggressive. we could be a little
|
|
@@ -110,23 +132,6 @@
|
|
|
110
132
|
|
|
111
133
|
// ---------------------------------------------------------------------------
|
|
112
134
|
|
|
113
|
-
color-scheme: var(--treb-color-scheme, unset);
|
|
114
|
-
|
|
115
|
-
font-family: $font-stack;
|
|
116
|
-
|
|
117
|
-
font-style: normal;
|
|
118
|
-
font-weight: normal;
|
|
119
|
-
color: inherit;
|
|
120
|
-
font-size: 14px; // ?
|
|
121
|
-
|
|
122
|
-
height: 100%;
|
|
123
|
-
width: 100%;
|
|
124
|
-
|
|
125
|
-
position: relative;
|
|
126
|
-
display: grid;
|
|
127
|
-
grid-template-rows: auto minmax(0, 1fr);
|
|
128
|
-
grid-template-columns: minmax(0, 1fr) auto;
|
|
129
|
-
// gap: 1em;
|
|
130
135
|
|
|
131
136
|
&[animate] {
|
|
132
137
|
.treb-layout-header {
|
|
@@ -354,11 +359,11 @@
|
|
|
354
359
|
right: 0px;
|
|
355
360
|
border-top-right-radius: 0px;
|
|
356
361
|
border-bottom-right-radius: 0px;
|
|
362
|
+
background: var(--treb-toolbar-button-background, #fff);
|
|
357
363
|
&::after {
|
|
358
364
|
mask-image: var(--icon-chevron-left);
|
|
359
365
|
-webkit-mask-image: var(--icon-chevron-left);
|
|
360
366
|
}
|
|
361
|
-
background: var(--treb-toolbar-button-background, #fff);
|
|
362
367
|
|
|
363
368
|
}
|
|
364
369
|
}
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
grid-area: 3/1/4/2;
|
|
31
31
|
|
|
32
|
+
align-items: center;
|
|
33
|
+
|
|
32
34
|
.treb-spreadsheet-tab-container {
|
|
33
35
|
align-self: flex-start;
|
|
34
36
|
overflow: hidden;
|
|
@@ -59,8 +61,6 @@
|
|
|
59
61
|
display: none;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
align-items: center;
|
|
63
|
-
|
|
64
64
|
& .treb-spreadsheet-tabs>li {
|
|
65
65
|
display: inline-block;
|
|
66
66
|
position: relative;
|
|
@@ -234,6 +234,10 @@ $text-reference-color-5: rgb(254, 47, 1);
|
|
|
234
234
|
color: var(--treb-autocomplete-tooltip-color, inherit);
|
|
235
235
|
border: 1px solid var(--treb-autocomplete-tooltip-border-color, unset);
|
|
236
236
|
|
|
237
|
+
padding: 3px 8px;
|
|
238
|
+
margin: 4px 0px;
|
|
239
|
+
line-height: normal;
|
|
240
|
+
|
|
237
241
|
& .active-argument {
|
|
238
242
|
font-weight: 700;
|
|
239
243
|
}
|
|
@@ -242,10 +246,6 @@ $text-reference-color-5: rgb(254, 47, 1);
|
|
|
242
246
|
font-style: italic;
|
|
243
247
|
}
|
|
244
248
|
|
|
245
|
-
padding: 3px 8px;
|
|
246
|
-
margin: 4px 0px;
|
|
247
|
-
line-height: normal;
|
|
248
|
-
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
/**
|
|
@@ -727,6 +727,20 @@ export class TileRenderer {
|
|
|
727
727
|
let pad_entry: RenderTextPart | undefined;
|
|
728
728
|
let composite_width = 0;
|
|
729
729
|
|
|
730
|
+
// -------------------------------------------------------------------------
|
|
731
|
+
|
|
732
|
+
// moved translated boolean formatting here. I don't like this. it
|
|
733
|
+
// should be in sheet (at least that's where the rest of formatting
|
|
734
|
+
// is), but sheet doesn't have a reference to data model (and because
|
|
735
|
+
// sheets are owned by data model, I don't want to add a circular ref).
|
|
736
|
+
|
|
737
|
+
if (cell.rendered_type === ValueType.boolean) {
|
|
738
|
+
const value = cell.calculated_type ? cell.calculated : cell.value;
|
|
739
|
+
cell.formatted = value ? (this.model.language_model?.boolean_true || 'TRUE') : (this.model.language_model?.boolean_false || 'FALSE');
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// -------------------------------------------------------------------------
|
|
743
|
+
|
|
730
744
|
let override_formatting: string | undefined;
|
|
731
745
|
let formatted = cell.editing ? '' : cell.formatted; // <-- empty on editing, to remove overflows
|
|
732
746
|
|