@trebco/treb 30.8.2 → 30.9.2
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-export-worker.mjs +2 -2
- package/dist/treb-spreadsheet.mjs +9 -9
- package/dist/treb.d.ts +4 -1
- package/package.json +1 -1
- package/treb-base-types/src/color.ts +32 -0
- package/treb-base-types/src/import.ts +3 -4
- package/treb-base-types/src/theme.ts +34 -7
- package/treb-data-model/src/sheet.ts +11 -1
- package/treb-data-model/src/sheet_types.ts +4 -1
- package/treb-embed/style/theme-defaults.scss +16 -0
- package/treb-export/src/export.ts +40 -7
- package/treb-export/src/{import2.ts → import.ts} +51 -16
- package/treb-export/src/index.worker.ts +1 -1
- package/treb-export/src/workbook2.ts +2 -2
- package/treb-grid/src/types/grid.ts +9 -5
- package/treb-grid/src/types/tab_bar.ts +38 -1
package/dist/treb.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! API v30.
|
|
1
|
+
/*! API v30.9. Copyright 2018-2024 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* add our tag to the map
|
|
@@ -1779,6 +1779,9 @@ export interface SerializedSheet {
|
|
|
1779
1779
|
/** sheet name */
|
|
1780
1780
|
name?: string;
|
|
1781
1781
|
|
|
1782
|
+
/** tab color */
|
|
1783
|
+
tab_color?: Color;
|
|
1784
|
+
|
|
1782
1785
|
/** current active selection */
|
|
1783
1786
|
selection: SerializedGridSelection;
|
|
1784
1787
|
|
package/package.json
CHANGED
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
|
|
23
|
+
|
|
22
24
|
/**
|
|
23
25
|
* utility functions, primarily for adjusting lightness. since we generally
|
|
24
26
|
* traffic in RGB (or symbolic colors) that requires translating to/from HSL.
|
|
@@ -120,5 +122,35 @@ export const ColorFunctions = {
|
|
|
120
122
|
return p;
|
|
121
123
|
},
|
|
122
124
|
|
|
125
|
+
////////////////
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
GetLuminance: (r: number, g: number, b: number): number => {
|
|
129
|
+
const a = [r, g, b].map(v => {
|
|
130
|
+
v /= 255;
|
|
131
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
132
|
+
});
|
|
133
|
+
return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
GetContrastRatio: (data: [number, number]): number => {
|
|
137
|
+
data.sort((a, b) => b - a);
|
|
138
|
+
return (data[0] + 0.05) / (data[1] + 0.05);
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
GetTextColor: (background: [number, number, number], a: [number, number, number], b: [number, number, number]) => {
|
|
142
|
+
|
|
143
|
+
const luminance = ColorFunctions.GetLuminance(...background);
|
|
144
|
+
const luminance_a = ColorFunctions.GetLuminance(...a);
|
|
145
|
+
const luminance_b = ColorFunctions.GetLuminance(...b);
|
|
146
|
+
|
|
147
|
+
const contrast_a = ColorFunctions.GetContrastRatio([luminance_a, luminance]);
|
|
148
|
+
const contrast_b = ColorFunctions.GetContrastRatio([luminance_b, luminance]);
|
|
149
|
+
|
|
150
|
+
return contrast_a > contrast_b ? a : b;
|
|
151
|
+
},
|
|
152
|
+
|
|
123
153
|
};
|
|
124
154
|
|
|
155
|
+
|
|
156
|
+
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { CellStyle } from './style';
|
|
22
|
+
import type { CellStyle, Color } from './style';
|
|
23
23
|
import type { SerializedValueType } from './value-type';
|
|
24
24
|
import type { IArea } from './area';
|
|
25
25
|
import type { AnnotationLayout } from './layout';
|
|
@@ -64,14 +64,13 @@ export interface ImportedSheetData {
|
|
|
64
64
|
// optional, for backcompat
|
|
65
65
|
sheet_style?: number;
|
|
66
66
|
column_styles?: number[];
|
|
67
|
-
|
|
68
67
|
row_styles?: number[];
|
|
69
68
|
|
|
70
|
-
// new
|
|
71
69
|
annotations?: AnchoredAnnotation[];
|
|
70
|
+
outline?: number[];
|
|
72
71
|
|
|
73
72
|
// new
|
|
74
|
-
|
|
73
|
+
tab_color?: Color;
|
|
75
74
|
|
|
76
75
|
hidden?: boolean;
|
|
77
76
|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { type Color, type CellStyle, IsHTMLColor, IsThemeColor, ThemeColorIndex, type ThemeColor } from './style';
|
|
23
23
|
import { ColorFunctions } from './color';
|
|
24
24
|
import { DOMContext } from './dom-utilities';
|
|
25
|
+
import { Measurement } from 'treb-utils';
|
|
25
26
|
|
|
26
27
|
/*
|
|
27
28
|
* so this is a little strange. we use CSS to populate a theme object,
|
|
@@ -242,7 +243,15 @@ export const ResolveThemeColor = (theme: Theme, color?: Color, default_index?: n
|
|
|
242
243
|
return '';
|
|
243
244
|
}
|
|
244
245
|
|
|
245
|
-
|
|
246
|
+
let resolved = '';
|
|
247
|
+
|
|
248
|
+
if (IsHTMLColor(color.offset)) {
|
|
249
|
+
const clamped = Measurement.MeasureColor(color.offset.text);
|
|
250
|
+
resolved = `rgb(${clamped[0]}, ${clamped[1]}, ${clamped[2]})`;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
resolved = ResolveThemeColor(theme, color.offset, undefined);
|
|
254
|
+
}
|
|
246
255
|
|
|
247
256
|
// check cache
|
|
248
257
|
if (theme.offset_cache && theme.offset_cache[resolved]) {
|
|
@@ -253,17 +262,35 @@ export const ResolveThemeColor = (theme: Theme, color?: Color, default_index?: n
|
|
|
253
262
|
|
|
254
263
|
if (resolved) {
|
|
255
264
|
// ok figure it out?
|
|
256
|
-
const match = resolved.match(/rgb\((\d+)
|
|
265
|
+
const match = resolved.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
|
|
257
266
|
if (match) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
267
|
+
|
|
268
|
+
type ColorTuple = [number, number, number];
|
|
269
|
+
|
|
270
|
+
const background: ColorTuple = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
// const hsl = ColorFunctions.RGBToHSL(r, g, b);
|
|
274
|
+
// const check = ColorFunctions.GetLuminance(r, g, b);
|
|
275
|
+
|
|
276
|
+
const a = Array.from(Measurement.MeasureColor(theme.offset_dark)) as ColorTuple;
|
|
277
|
+
const b = Array.from(Measurement.MeasureColor(theme.offset_light)) as ColorTuple;
|
|
278
|
+
|
|
279
|
+
const tc = ColorFunctions.GetTextColor(background, a, b);
|
|
280
|
+
|
|
281
|
+
offset = `rgb(${tc[0]}, ${tc[1]}, ${tc[2]})`;
|
|
282
|
+
|
|
283
|
+
/*
|
|
284
|
+
if (hsl.l >.65)) {
|
|
261
285
|
offset = theme.offset_dark;
|
|
262
286
|
}
|
|
287
|
+
*/
|
|
288
|
+
|
|
289
|
+
|
|
263
290
|
}
|
|
264
291
|
else {
|
|
265
292
|
// ...
|
|
266
|
-
console.warn(`can't offset against color`, resolved);
|
|
293
|
+
console.warn(`can't offset against color`, resolved, '(1)');
|
|
267
294
|
}
|
|
268
295
|
|
|
269
296
|
if (!theme.offset_cache) {
|
|
@@ -272,7 +299,7 @@ export const ResolveThemeColor = (theme: Theme, color?: Color, default_index?: n
|
|
|
272
299
|
theme.offset_cache[resolved] = offset;
|
|
273
300
|
}
|
|
274
301
|
else {
|
|
275
|
-
console.warn(`can't resolve offset color`, color.offset);
|
|
302
|
+
console.warn(`can't resolve offset color`, color.offset, '(2)');
|
|
276
303
|
}
|
|
277
304
|
|
|
278
305
|
return offset;
|
|
@@ -145,6 +145,8 @@ export class Sheet {
|
|
|
145
145
|
|
|
146
146
|
public name = Sheet.default_sheet_name;
|
|
147
147
|
|
|
148
|
+
public tab_color?: Color;
|
|
149
|
+
|
|
148
150
|
public background_image?: string;
|
|
149
151
|
|
|
150
152
|
protected _image: HTMLImageElement|undefined = undefined;
|
|
@@ -403,6 +405,9 @@ export class Sheet {
|
|
|
403
405
|
if (source.name) {
|
|
404
406
|
sheet.name = source.name;
|
|
405
407
|
}
|
|
408
|
+
if (source.tab_color) {
|
|
409
|
+
sheet.tab_color = source.tab_color;
|
|
410
|
+
}
|
|
406
411
|
|
|
407
412
|
if (source.background_image) {
|
|
408
413
|
sheet.background_image = source.background_image;
|
|
@@ -2744,6 +2749,7 @@ export class Sheet {
|
|
|
2744
2749
|
|
|
2745
2750
|
id: this.id,
|
|
2746
2751
|
name: this.name,
|
|
2752
|
+
tab_color: this.tab_color,
|
|
2747
2753
|
|
|
2748
2754
|
data,
|
|
2749
2755
|
sheet_style,
|
|
@@ -2915,7 +2921,11 @@ export class Sheet {
|
|
|
2915
2921
|
// this.cells.FromJSON(cell_data);
|
|
2916
2922
|
this.cells.FromJSON(data.cells);
|
|
2917
2923
|
if (data.name) {
|
|
2918
|
-
this.name = data.name || '';
|
|
2924
|
+
this.name = data.name || ''; // wtf is this?
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
if (data.tab_color) {
|
|
2928
|
+
this.tab_color = data.tab_color;
|
|
2919
2929
|
}
|
|
2920
2930
|
|
|
2921
2931
|
// 0 is implicitly just a general style
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { IArea, SerializedCellData, CellStyle } from 'treb-base-types';
|
|
22
|
+
import type { IArea, SerializedCellData, CellStyle, Color } from 'treb-base-types';
|
|
23
23
|
import type { AnnotationData } from './annotation';
|
|
24
24
|
import type { GridSelection, SerializedGridSelection } from './sheet_selection';
|
|
25
25
|
import type { ConditionalFormatList } from './conditional_format';
|
|
@@ -126,6 +126,9 @@ export interface SerializedSheet {
|
|
|
126
126
|
/** sheet name */
|
|
127
127
|
name?: string;
|
|
128
128
|
|
|
129
|
+
/** tab color */
|
|
130
|
+
tab_color?: Color;
|
|
131
|
+
|
|
129
132
|
/** current active selection */
|
|
130
133
|
selection: SerializedGridSelection;
|
|
131
134
|
|
|
@@ -437,6 +437,22 @@ $text-reference-color-5: rgb(254, 47, 1);
|
|
|
437
437
|
&[selected] {
|
|
438
438
|
background: var(--treb-tab-bar-active-tab-background, #fff);
|
|
439
439
|
color: var(--treb-tab-bar-active-tab-color, var(--treb-ui-color, inherit));
|
|
440
|
+
|
|
441
|
+
border-bottom-color: var(--treb-tab-bar-active-tab-border-color, currentColor);
|
|
442
|
+
|
|
443
|
+
/*
|
|
444
|
+
position: relative;
|
|
445
|
+
&::after {
|
|
446
|
+
content: '';
|
|
447
|
+
position: absolute;
|
|
448
|
+
bottom: 0px;
|
|
449
|
+
left: 0px;
|
|
450
|
+
width: 100%;
|
|
451
|
+
height: 1px;
|
|
452
|
+
background: currentColor;
|
|
453
|
+
}
|
|
454
|
+
*/
|
|
455
|
+
|
|
440
456
|
}
|
|
441
457
|
}
|
|
442
458
|
|
|
@@ -439,13 +439,7 @@ export class Exporter {
|
|
|
439
439
|
|
|
440
440
|
const dxf: DOMContent[] = style_cache.dxf_styles.map(style => {
|
|
441
441
|
|
|
442
|
-
const entry: DOMContent = {
|
|
443
|
-
fill: style.fill ? {
|
|
444
|
-
patternFill: {
|
|
445
|
-
bgColor: ColorAttrs(style.fill),
|
|
446
|
-
},
|
|
447
|
-
} : undefined,
|
|
448
|
-
};
|
|
442
|
+
const entry: DOMContent = {};
|
|
449
443
|
|
|
450
444
|
if (style.text || style.bold || style.italic || style.underline) {
|
|
451
445
|
entry.font = {
|
|
@@ -457,6 +451,14 @@ export class Exporter {
|
|
|
457
451
|
};
|
|
458
452
|
}
|
|
459
453
|
|
|
454
|
+
if (style.fill) {
|
|
455
|
+
entry.fill = {
|
|
456
|
+
patternFill: {
|
|
457
|
+
bgColor: ColorAttrs(style.fill),
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
460
462
|
return entry;
|
|
461
463
|
|
|
462
464
|
});
|
|
@@ -2214,6 +2216,34 @@ export class Exporter {
|
|
|
2214
2216
|
// delete dom.worksheet.drawing;
|
|
2215
2217
|
}
|
|
2216
2218
|
|
|
2219
|
+
// --- tab color ---------------------------------------------------------
|
|
2220
|
+
|
|
2221
|
+
const tab_color_block: DOMContent = {};
|
|
2222
|
+
if (sheet.tab_color) {
|
|
2223
|
+
if (IsThemeColor(sheet.tab_color)) {
|
|
2224
|
+
tab_color_block.sheetPr = {
|
|
2225
|
+
tabColor: {
|
|
2226
|
+
a$: {
|
|
2227
|
+
theme: sheet.tab_color.theme,
|
|
2228
|
+
tint: sheet.tab_color.tint,
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
2233
|
+
else if (IsHTMLColor(sheet.tab_color)) {
|
|
2234
|
+
const color = sheet.tab_color.text || '';
|
|
2235
|
+
if (/^#[0-9a-fA-F]*$/.test(color)) {
|
|
2236
|
+
tab_color_block.sheetPr = {
|
|
2237
|
+
tabColor: {
|
|
2238
|
+
a$: {
|
|
2239
|
+
rgb: `FF` + color.substring(1)
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2217
2247
|
// --- move page margins -------------------------------------------------
|
|
2218
2248
|
|
|
2219
2249
|
// const margins = dom.worksheet.pageMargins;
|
|
@@ -2242,6 +2272,9 @@ export class Exporter {
|
|
|
2242
2272
|
|
|
2243
2273
|
worksheet: {
|
|
2244
2274
|
a$: { ...sheet_attributes },
|
|
2275
|
+
|
|
2276
|
+
...tab_color_block,
|
|
2277
|
+
|
|
2245
2278
|
dimension: {
|
|
2246
2279
|
a$: {
|
|
2247
2280
|
ref: new Area(extent.start, extent.end).spreadsheet_label,
|
|
@@ -166,20 +166,26 @@ export class Importer {
|
|
|
166
166
|
// doing it like this is sloppy (also does not work properly).
|
|
167
167
|
value = '=' + formula.replace(/^_xll\./g, '');
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
169
|
+
// drop the formula if it's a ref error, we can't handle this
|
|
170
|
+
if (/#REF/.test(formula)) {
|
|
171
|
+
value = formula;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const parse_result = this.parser.Parse(formula); // l10n?
|
|
175
|
+
if (parse_result.expression) {
|
|
176
|
+
this.parser.Walk(parse_result.expression, (unit) => {
|
|
177
|
+
if (unit.type === 'call') {
|
|
178
|
+
if (/^_xll\./.test(unit.name)) {
|
|
179
|
+
unit.name = unit.name.substring(5);
|
|
180
|
+
}
|
|
181
|
+
else if (/^_xlfn\./.test(unit.name)) {
|
|
182
|
+
unit.name = unit.name.substring(6);
|
|
183
|
+
}
|
|
178
184
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
185
|
+
return true;
|
|
186
|
+
});
|
|
187
|
+
value = '=' + this.parser.Render(parse_result.expression, { missing: '' });
|
|
188
|
+
}
|
|
183
189
|
}
|
|
184
190
|
|
|
185
191
|
if (typeof element.f !== 'string') {
|
|
@@ -591,6 +597,33 @@ export class Importer {
|
|
|
591
597
|
|
|
592
598
|
const FindAll: (path: string) => any[] = XMLUtils.FindAll.bind(XMLUtils, sheet.sheet_data);
|
|
593
599
|
|
|
600
|
+
// tab color
|
|
601
|
+
|
|
602
|
+
const tab_color_element = FindAll('worksheet/sheetPr/tabColor');
|
|
603
|
+
|
|
604
|
+
let tab_color: Color|undefined;
|
|
605
|
+
|
|
606
|
+
if (tab_color_element?.[0]) {
|
|
607
|
+
|
|
608
|
+
const element = tab_color_element[0];
|
|
609
|
+
if (element.a$?.theme) {
|
|
610
|
+
tab_color = { theme: Number(element.a$.theme) };
|
|
611
|
+
if (element.a$?.tint) {
|
|
612
|
+
tab_color.tint = Number(element.a$.tint);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (element.a$?.rgb) {
|
|
616
|
+
const argb = element.a$.rgb;
|
|
617
|
+
tab_color = {
|
|
618
|
+
text: '#' + (
|
|
619
|
+
argb.length > 6 ?
|
|
620
|
+
argb.substr(argb.length - 6) :
|
|
621
|
+
argb),
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
}
|
|
626
|
+
|
|
594
627
|
// conditionals
|
|
595
628
|
|
|
596
629
|
const conditional_formatting = FindAll('worksheet/conditionalFormatting');
|
|
@@ -1120,7 +1153,8 @@ export class Importer {
|
|
|
1120
1153
|
type = 'treb-chart';
|
|
1121
1154
|
func = 'Box.Plot';
|
|
1122
1155
|
if (series?.length) {
|
|
1123
|
-
args[0] = `Group(${series.map(s => `Series(${s.title || ''},,${s.values||''})`
|
|
1156
|
+
args[0] = `Group(${series.map(s => `Series(${s.title || ''},,${s.values||''})`).join(', ')})`;
|
|
1157
|
+
console.info("S?", {series}, args[0])
|
|
1124
1158
|
}
|
|
1125
1159
|
args[1] = descriptor.chart.title;
|
|
1126
1160
|
break;
|
|
@@ -1129,7 +1163,7 @@ export class Importer {
|
|
|
1129
1163
|
type = 'treb-chart';
|
|
1130
1164
|
func = 'Scatter.Line';
|
|
1131
1165
|
if (series && series.length) {
|
|
1132
|
-
args[0] = `Group(${series.map(s => `Series(${s.title || ''},${s.categories||''},${s.values||''})`
|
|
1166
|
+
args[0] = `Group(${series.map(s => `Series(${s.title || ''},${s.categories||''},${s.values||''})`).join(', ')})`;
|
|
1133
1167
|
}
|
|
1134
1168
|
args[1] = descriptor.chart.title;
|
|
1135
1169
|
break;
|
|
@@ -1165,7 +1199,7 @@ export class Importer {
|
|
|
1165
1199
|
|
|
1166
1200
|
if (series) {
|
|
1167
1201
|
if (series.length > 1) {
|
|
1168
|
-
args[0] = `Group(${series.map(s => `Series(${s.title || ''},,${s.values||''})`
|
|
1202
|
+
args[0] = `Group(${series.map(s => `Series(${s.title || ''},,${s.values||''})`).join(', ')})`;
|
|
1169
1203
|
}
|
|
1170
1204
|
else if (series.length === 1) {
|
|
1171
1205
|
if (series[0].title) {
|
|
@@ -1289,6 +1323,7 @@ export class Importer {
|
|
|
1289
1323
|
default_column_width,
|
|
1290
1324
|
column_widths,
|
|
1291
1325
|
row_heights,
|
|
1326
|
+
tab_color,
|
|
1292
1327
|
row_styles,
|
|
1293
1328
|
annotations,
|
|
1294
1329
|
conditional_formats,
|
|
@@ -23,7 +23,7 @@ import type { ImportedSheetData } from 'treb-base-types';
|
|
|
23
23
|
import type { SerializedModel } from 'treb-data-model';
|
|
24
24
|
|
|
25
25
|
import { Exporter } from './export';
|
|
26
|
-
import { Importer } from './
|
|
26
|
+
import { Importer } from './import';
|
|
27
27
|
|
|
28
28
|
const ctx: Worker = self as unknown as Worker;
|
|
29
29
|
const exporter = new Exporter();
|
|
@@ -45,10 +45,10 @@ import type { SerializedNamed } from 'treb-data-model';
|
|
|
45
45
|
export const ConditionalFormatOperators: Record<string, string> = {
|
|
46
46
|
greaterThan: '>',
|
|
47
47
|
greaterThanOrEqual: '>=',
|
|
48
|
-
greaterThanOrEquals: '>=',
|
|
48
|
+
// greaterThanOrEquals: '>=',
|
|
49
49
|
lessThan: '<',
|
|
50
50
|
lessThanOrEqual: '<=',
|
|
51
|
-
lessThanOrEquals: '<=',
|
|
51
|
+
// lessThanOrEquals: '<=',
|
|
52
52
|
equal: '=',
|
|
53
53
|
notEqual: '<>',
|
|
54
54
|
};
|
|
@@ -967,7 +967,7 @@ export class Grid extends GridBase {
|
|
|
967
967
|
if (add_to_layout) {
|
|
968
968
|
this.layout.AddAnnotation(annotation);
|
|
969
969
|
if (annotation.data.layout) {
|
|
970
|
-
this.EnsureAddress(annotation.data.layout.br.address, 1);
|
|
970
|
+
this.EnsureAddress(annotation.data.layout.br.address, 1, toll_events);
|
|
971
971
|
}
|
|
972
972
|
}
|
|
973
973
|
else {
|
|
@@ -1190,7 +1190,7 @@ export class Grid extends GridBase {
|
|
|
1190
1190
|
this.QueueLayoutUpdate();
|
|
1191
1191
|
|
|
1192
1192
|
this.StyleDefaultFromTheme();
|
|
1193
|
-
|
|
1193
|
+
|
|
1194
1194
|
if (render) {
|
|
1195
1195
|
this.Repaint(false, false); // true, true);
|
|
1196
1196
|
}
|
|
@@ -1403,6 +1403,10 @@ export class Grid extends GridBase {
|
|
|
1403
1403
|
|
|
1404
1404
|
// this.tile_renderer.UpdateTheme(); // has reference
|
|
1405
1405
|
|
|
1406
|
+
if (this.tab_bar) {
|
|
1407
|
+
this.tab_bar.UpdateTheme();
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1406
1410
|
if (!initial) {
|
|
1407
1411
|
|
|
1408
1412
|
this.UpdateLayout(); // in case we have changed font size
|
|
@@ -1454,7 +1458,7 @@ export class Grid extends GridBase {
|
|
|
1454
1458
|
|
|
1455
1459
|
if (this.options.tab_bar) {
|
|
1456
1460
|
|
|
1457
|
-
this.tab_bar = new TabBar(this.layout, this.model, this.view, this.options, view_node);
|
|
1461
|
+
this.tab_bar = new TabBar(this.layout, this.model, this.view, this.options, this.theme, view_node);
|
|
1458
1462
|
this.tab_bar.Subscribe((event) => {
|
|
1459
1463
|
switch (event.type) {
|
|
1460
1464
|
case 'cancel':
|
|
@@ -5936,7 +5940,7 @@ export class Grid extends GridBase {
|
|
|
5936
5940
|
/**
|
|
5937
5941
|
* if the address is outside of current extent, expand
|
|
5938
5942
|
*/
|
|
5939
|
-
private EnsureAddress(address: ICellAddress, step = 8): boolean {
|
|
5943
|
+
private EnsureAddress(address: ICellAddress, step = 8, toll_layout = false): boolean {
|
|
5940
5944
|
|
|
5941
5945
|
let expanded = false;
|
|
5942
5946
|
|
|
@@ -5959,7 +5963,7 @@ export class Grid extends GridBase {
|
|
|
5959
5963
|
expanded = true;
|
|
5960
5964
|
}
|
|
5961
5965
|
|
|
5962
|
-
if (expanded) {
|
|
5966
|
+
if (expanded && !toll_layout) {
|
|
5963
5967
|
this.layout.UpdateTiles();
|
|
5964
5968
|
this.layout.UpdateContentsSize();
|
|
5965
5969
|
this.Repaint(true, true);
|
|
@@ -25,7 +25,7 @@ import type { BaseLayout } from '../layout/base_layout';
|
|
|
25
25
|
import { MouseDrag } from './drag_mask';
|
|
26
26
|
import type { GridOptions } from './grid_options';
|
|
27
27
|
import { type ScaleEvent, ScaleControl } from './scale-control';
|
|
28
|
-
import { DOMContext } from 'treb-base-types';
|
|
28
|
+
import { DOMContext, ResolveThemeColor, type Theme } from 'treb-base-types';
|
|
29
29
|
|
|
30
30
|
export interface ActivateSheetEvent {
|
|
31
31
|
type: 'activate-sheet';
|
|
@@ -100,6 +100,8 @@ export class TabBar extends EventSource<TabEvent> {
|
|
|
100
100
|
timeout?: number;
|
|
101
101
|
} = {};
|
|
102
102
|
|
|
103
|
+
private tab_color_cache: Map<number, { background: string, foreground: string }> = new Map();
|
|
104
|
+
|
|
103
105
|
// tslint:disable-next-line: variable-name
|
|
104
106
|
private _visible = false;
|
|
105
107
|
|
|
@@ -133,6 +135,7 @@ export class TabBar extends EventSource<TabEvent> {
|
|
|
133
135
|
private model: DataModel,
|
|
134
136
|
private view: ViewModel,
|
|
135
137
|
private options: GridOptions,
|
|
138
|
+
private theme: Theme,
|
|
136
139
|
// private container: HTMLElement,
|
|
137
140
|
view_node: HTMLElement,
|
|
138
141
|
) {
|
|
@@ -236,10 +239,21 @@ export class TabBar extends EventSource<TabEvent> {
|
|
|
236
239
|
if (active) {
|
|
237
240
|
// tab.classList.add('treb-selected');
|
|
238
241
|
tab.setAttribute('selected', '');
|
|
242
|
+
|
|
243
|
+
if (tab.dataset.background_color) {
|
|
244
|
+
tab.style.backgroundColor = `color-mix(in srgb, ${tab.dataset.background_color} 20%, var(--treb-tab-bar-active-tab-background, #fff))`;
|
|
245
|
+
tab.style.color = '';
|
|
246
|
+
}
|
|
239
247
|
}
|
|
240
248
|
else {
|
|
241
249
|
// tab.classList.remove('treb-selected');
|
|
242
250
|
tab.removeAttribute('selected');
|
|
251
|
+
if (tab.dataset.background_color) {
|
|
252
|
+
tab.style.backgroundColor = tab.dataset.background_color;
|
|
253
|
+
}
|
|
254
|
+
if (tab.dataset.foreground_color) {
|
|
255
|
+
tab.style.color = tab.dataset.foreground_color;
|
|
256
|
+
}
|
|
243
257
|
}
|
|
244
258
|
}
|
|
245
259
|
|
|
@@ -419,6 +433,11 @@ export class TabBar extends EventSource<TabEvent> {
|
|
|
419
433
|
|
|
420
434
|
}
|
|
421
435
|
|
|
436
|
+
public UpdateTheme() {
|
|
437
|
+
this.tab_color_cache.clear();
|
|
438
|
+
this.Update();
|
|
439
|
+
}
|
|
440
|
+
|
|
422
441
|
/**
|
|
423
442
|
* update tabs from model.
|
|
424
443
|
*/
|
|
@@ -464,6 +483,24 @@ export class TabBar extends EventSource<TabEvent> {
|
|
|
464
483
|
const tab = this.DOM.Create('li');
|
|
465
484
|
tab.setAttribute('tabindex', '0');
|
|
466
485
|
|
|
486
|
+
if (sheet.tab_color) {
|
|
487
|
+
const id = sheet.id;
|
|
488
|
+
if (!this.tab_color_cache.has(id)) {
|
|
489
|
+
const background = ResolveThemeColor(this.theme, sheet.tab_color);
|
|
490
|
+
const foreground = ResolveThemeColor(this.theme, { offset: sheet.tab_color });
|
|
491
|
+
if (background && foreground) {
|
|
492
|
+
this.tab_color_cache.set(id, { background, foreground });
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
const color = this.tab_color_cache.get(id);
|
|
496
|
+
if (color) {
|
|
497
|
+
tab.style.backgroundColor = color.background;
|
|
498
|
+
tab.style.color = color.foreground;
|
|
499
|
+
tab.dataset.background_color = color.background;
|
|
500
|
+
tab.dataset.foreground_color = color.foreground;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
467
504
|
// tab.classList.add('tab');
|
|
468
505
|
tab.style.order = (index * 2).toString();
|
|
469
506
|
tab.role = 'tab';
|