@trebco/treb 31.7.8 → 31.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/treb-export-worker.mjs +2 -2
- package/dist/treb-spreadsheet.mjs +8 -8
- package/dist/treb.d.ts +1 -1
- package/package.json +2 -2
- package/treb-data-model/src/annotation.ts +1 -1
- package/treb-embed/markup/toolbar.html +5 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +8 -1
- package/treb-embed/src/embedded-spreadsheet.ts +89 -28
- package/treb-embed/style/autocomplete.scss +4 -0
- package/treb-embed/style/dropdown-select.scss +3 -0
- package/treb-embed/style/font-stacks.scss +2 -0
- package/treb-embed/style/grid.scss +11 -11
- package/treb-embed/style/layout.scss +12 -9
- package/treb-embed/style/mouse-mask.scss +3 -0
- package/treb-embed/style/note.scss +4 -0
- package/treb-embed/style/overlay-editor.scss +3 -0
- package/treb-embed/style/tab-bar.scss +4 -0
- package/treb-embed/style/table.scss +3 -0
- package/treb-embed/style/theme-defaults.scss +5 -3
- package/treb-embed/style/toolbar.scss +17 -5
- package/treb-embed/style/tooltip.scss +4 -0
- package/treb-embed/style/treb-spreadsheet-element.scss +1 -1
- package/treb-export/src/import.ts +9 -3
- package/treb-export/src/workbook-style2.ts +0 -39
- package/treb-export/src/workbook2.ts +103 -79
- package/treb-export/tsconfig.json +1 -0
- package/treb-grid/src/layout/base_layout.ts +21 -0
- package/treb-grid/src/render/svg_selection_block.ts +4 -40
- package/treb-grid/src/types/grid.ts +37 -2
|
@@ -36,7 +36,7 @@ import { Theme } from './workbook-theme2';
|
|
|
36
36
|
import { Sheet, VisibleState } from './workbook-sheet2';
|
|
37
37
|
import type { RelationshipMap } from './relationship';
|
|
38
38
|
import { ZipWrapper } from './zip-wrapper';
|
|
39
|
-
import type { CellStyle, ThemeColor } from 'treb-base-types';
|
|
39
|
+
import type { CellStyle, ICellAddress, ThemeColor } from 'treb-base-types';
|
|
40
40
|
import type { SerializedNamed } from 'treb-data-model';
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -86,11 +86,13 @@ export interface AnchoredChartDescription {
|
|
|
86
86
|
export interface AnchoredTextBoxDescription {
|
|
87
87
|
type: 'textbox';
|
|
88
88
|
style?: CellStyle;
|
|
89
|
+
reference?: string;
|
|
89
90
|
paragraphs: {
|
|
90
91
|
style?: CellStyle,
|
|
91
92
|
content: {
|
|
92
93
|
text: string,
|
|
93
94
|
style?: CellStyle
|
|
95
|
+
reference?: boolean,
|
|
94
96
|
}[],
|
|
95
97
|
}[];
|
|
96
98
|
anchor: TwoCellAnchor,
|
|
@@ -397,100 +399,122 @@ export class Workbook {
|
|
|
397
399
|
|
|
398
400
|
let style: CellStyle|undefined;
|
|
399
401
|
|
|
400
|
-
const
|
|
401
|
-
if (
|
|
402
|
-
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
402
|
+
const sp = XMLUtils.FindAll(anchor_node, 'xdr:sp')[0];
|
|
403
|
+
if (sp) {
|
|
404
|
+
|
|
405
|
+
const reference = sp.a$?.textlink || undefined;
|
|
406
|
+
|
|
407
|
+
const sppr = XMLUtils.FindAll(sp, 'xdr:spPr')[0];
|
|
408
|
+
if (sppr) {
|
|
409
|
+
style = {};
|
|
410
|
+
const fill = sppr['a:solidFill'];
|
|
411
|
+
if (fill) {
|
|
412
|
+
if (fill['a:schemeClr']?.a$?.val) {
|
|
413
|
+
const m = (fill['a:schemeClr'].a$.val).match(/accent(\d+)/);
|
|
414
|
+
if (m) {
|
|
415
|
+
style.fill = { theme: Number(m[1]) + 3 }
|
|
416
|
+
if (fill['a:schemeClr']['a:lumOff']?.a$?.val) {
|
|
417
|
+
const num = Number(fill['a:schemeClr']['a:lumOff'].a$.val);
|
|
418
|
+
if (!isNaN(num)) {
|
|
419
|
+
(style.fill as ThemeColor).tint = num / 1e5;
|
|
420
|
+
}
|
|
413
421
|
}
|
|
414
422
|
}
|
|
415
|
-
}
|
|
416
423
|
|
|
424
|
+
}
|
|
417
425
|
}
|
|
418
426
|
}
|
|
419
|
-
}
|
|
420
427
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
428
|
+
const tx = XMLUtils.FindAll(sp, 'xdr:txBody')[0];
|
|
429
|
+
if (tx) {
|
|
430
|
+
|
|
431
|
+
const paragraphs: {
|
|
432
|
+
style?: CellStyle,
|
|
433
|
+
content: {
|
|
434
|
+
text: string,
|
|
435
|
+
style?: CellStyle
|
|
436
|
+
reference?: boolean;
|
|
437
|
+
}[],
|
|
438
|
+
}[] = [];
|
|
439
|
+
|
|
440
|
+
const p_list = XMLUtils.FindAll(tx, 'a:p');
|
|
441
|
+
for (const paragraph of p_list) {
|
|
442
|
+
const para: { text: string, style?: CellStyle, reference?: boolean }[] = [];
|
|
443
|
+
let style: CellStyle|undefined;
|
|
444
|
+
|
|
445
|
+
const fld = paragraph['a:fld'];
|
|
446
|
+
if (fld) {
|
|
447
|
+
if (fld.a$?.type === 'TxLink') {
|
|
448
|
+
const entry: {text: string, reference?: boolean, style?: CellStyle } = { text: `{${reference}}`, reference: true };
|
|
449
|
+
|
|
450
|
+
// format
|
|
451
|
+
const fmt = fld['a:rPr'];
|
|
452
|
+
if (fmt) {
|
|
453
|
+
entry.style = {};
|
|
454
|
+
if (fmt.a$?.b === '1') {
|
|
455
|
+
entry.style.bold = true;
|
|
456
|
+
}
|
|
457
|
+
if (fmt.a$?.i === '1') {
|
|
458
|
+
entry.style.italic = true;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
para.push(entry);
|
|
463
|
+
}
|
|
449
464
|
}
|
|
450
|
-
|
|
451
|
-
|
|
465
|
+
|
|
466
|
+
const appr = paragraph['a:pPr'];
|
|
467
|
+
if (appr) {
|
|
468
|
+
style = {};
|
|
469
|
+
if (appr.a$?.algn === 'r') {
|
|
470
|
+
style.horizontal_align = 'right';
|
|
471
|
+
}
|
|
472
|
+
else if (appr.a$?.algn === 'ctr') {
|
|
473
|
+
style.horizontal_align = 'center';
|
|
474
|
+
}
|
|
452
475
|
}
|
|
453
|
-
}
|
|
454
476
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
for (const line of ar) {
|
|
461
|
-
|
|
462
|
-
const entry: { text: string, style?: CellStyle } = {
|
|
463
|
-
text: line['a:t'] || '',
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
// format
|
|
467
|
-
const fmt = line['a:rPr'];
|
|
468
|
-
if (fmt) {
|
|
469
|
-
entry.style = {};
|
|
470
|
-
if (fmt.a$?.b === '1') {
|
|
471
|
-
entry.style.bold = true;
|
|
472
|
-
}
|
|
473
|
-
if (fmt.a$?.i === '1') {
|
|
474
|
-
entry.style.italic = true;
|
|
475
|
-
}
|
|
477
|
+
let ar = paragraph['a:r'];
|
|
478
|
+
if (ar) {
|
|
479
|
+
if (!Array.isArray(ar)) {
|
|
480
|
+
ar = [ar];
|
|
476
481
|
}
|
|
482
|
+
for (const line of ar) {
|
|
483
|
+
|
|
484
|
+
const entry: { text: string, style?: CellStyle } = {
|
|
485
|
+
text: line['a:t'] || '',
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// format
|
|
489
|
+
const fmt = line['a:rPr'];
|
|
490
|
+
if (fmt) {
|
|
491
|
+
entry.style = {};
|
|
492
|
+
if (fmt.a$?.b === '1') {
|
|
493
|
+
entry.style.bold = true;
|
|
494
|
+
}
|
|
495
|
+
if (fmt.a$?.i === '1') {
|
|
496
|
+
entry.style.italic = true;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
477
499
|
|
|
478
|
-
|
|
500
|
+
para.push(entry);
|
|
479
501
|
|
|
502
|
+
}
|
|
480
503
|
}
|
|
481
|
-
}
|
|
482
504
|
|
|
483
|
-
|
|
505
|
+
paragraphs.push({ content: para, style });
|
|
484
506
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
results.push({
|
|
510
|
+
type: 'textbox',
|
|
511
|
+
style,
|
|
512
|
+
paragraphs,
|
|
513
|
+
anchor,
|
|
514
|
+
reference,
|
|
515
|
+
});
|
|
493
516
|
|
|
517
|
+
}
|
|
494
518
|
}
|
|
495
519
|
|
|
496
520
|
}
|
|
@@ -730,6 +730,27 @@ export abstract class BaseLayout {
|
|
|
730
730
|
view.node.style.fontVariant = '';
|
|
731
731
|
}
|
|
732
732
|
|
|
733
|
+
if (annotation.data.style?.bold) {
|
|
734
|
+
view.node.style.fontWeight = '600';
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
view.node.style.fontWeight = '400';
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
if (annotation.data.style?.italic) {
|
|
741
|
+
view.node.style.fontStyle = 'italic';
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
view.node.style.fontStyle = '';
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
if (annotation.data.style?.underline) {
|
|
748
|
+
view.node.style.textDecoration = 'underline';
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
view.node.style.textDecoration = '';
|
|
752
|
+
}
|
|
753
|
+
|
|
733
754
|
view.node.style.fontSize = `${font_size_pt}pt`;
|
|
734
755
|
|
|
735
756
|
// update the layout here if necessary. after that it should
|
|
@@ -52,7 +52,7 @@ export class SVGSelectionBlock {
|
|
|
52
52
|
this.g = DOM.SVG('g');
|
|
53
53
|
this.g.setAttribute('transform', `translate(${offset.x}, ${offset.y})`);
|
|
54
54
|
|
|
55
|
-
this.outline = DOM.SVG('rect', 'outline');
|
|
55
|
+
this.outline = DOM.SVG('rect', 'treb-selection-outline');
|
|
56
56
|
|
|
57
57
|
if (primary) {
|
|
58
58
|
|
|
@@ -61,8 +61,8 @@ export class SVGSelectionBlock {
|
|
|
61
61
|
// primary selections have a separate fill, plus the nub. separate
|
|
62
62
|
// fill because the "target" is unfilled.
|
|
63
63
|
|
|
64
|
-
this.fill = DOM.SVG('path', 'fill');
|
|
65
|
-
this.nub = DOM.SVG('rect', 'nub');
|
|
64
|
+
this.fill = DOM.SVG('path', 'treb-selection-fill');
|
|
65
|
+
this.nub = DOM.SVG('rect', 'treb-selection-nub');
|
|
66
66
|
|
|
67
67
|
this.g.appendChild(this.fill);
|
|
68
68
|
this.g.appendChild(this.outline);
|
|
@@ -78,7 +78,7 @@ export class SVGSelectionBlock {
|
|
|
78
78
|
// and use currentColor, but we can't set opacity separately so we
|
|
79
79
|
// need another node. which is a waste, but ergonomics ftw!
|
|
80
80
|
|
|
81
|
-
this.fill = DOM.SVG('rect', 'fill');
|
|
81
|
+
this.fill = DOM.SVG('rect', 'treb-selection-fill');
|
|
82
82
|
|
|
83
83
|
// this.SetThemeColor(0);
|
|
84
84
|
// if (theme.additional_selection_line_dash_array) {
|
|
@@ -95,42 +95,6 @@ export class SVGSelectionBlock {
|
|
|
95
95
|
this.g.setAttribute('transform', `translate(${offset.x}, ${offset.y})`);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
/*
|
|
99
|
-
public SetThemeColor(index = 0) {
|
|
100
|
-
|
|
101
|
-
if (Array.isArray(this.theme.additional_selection_color)) {
|
|
102
|
-
if (index >= this.theme.additional_selection_color.length) {
|
|
103
|
-
index = index % this.theme.additional_selection_color.length;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (this.theme.additional_selection_overlay_color) {
|
|
108
|
-
if (typeof this.theme.additional_selection_overlay_color === 'string') {
|
|
109
|
-
this.outline.setAttribute('fill', this.theme.additional_selection_overlay_color);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
this.outline.setAttribute('fill', this.theme.additional_selection_overlay_color[index] || '');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
this.outline.setAttribute('fill', '');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (this.theme.additional_selection_color) {
|
|
120
|
-
if (typeof this.theme.additional_selection_color === 'string') {
|
|
121
|
-
this.outline.setAttribute('stroke', this.theme.additional_selection_color);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
this.outline.setAttribute('stroke', this.theme.additional_selection_color[index] || '');
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
this.outline.setAttribute('stroke', '');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
*/
|
|
133
|
-
|
|
134
98
|
public Show(show = true) {
|
|
135
99
|
this.g.style.display = show ? 'block' : 'none';
|
|
136
100
|
}
|
|
@@ -956,6 +956,33 @@ export class Grid extends GridBase {
|
|
|
956
956
|
|
|
957
957
|
const elements = [node, ...this.layout.GetFrozenAnnotations(annotation)];
|
|
958
958
|
|
|
959
|
+
if (event.ctrlKey || (UA.is_mac && event.metaKey)) {
|
|
960
|
+
|
|
961
|
+
const annotation_style = annotation.data.style ? { ...annotation.data.style } : {};
|
|
962
|
+
let handled = true;
|
|
963
|
+
|
|
964
|
+
switch (event.key) {
|
|
965
|
+
case 'b':
|
|
966
|
+
this.ApplyAnnotationStyle({bold: !annotation_style.bold});
|
|
967
|
+
break;
|
|
968
|
+
case 'i':
|
|
969
|
+
this.ApplyAnnotationStyle({italic: !annotation_style.italic});
|
|
970
|
+
break;
|
|
971
|
+
case 'u':
|
|
972
|
+
this.ApplyAnnotationStyle({underline: !annotation_style.underline});
|
|
973
|
+
break;
|
|
974
|
+
default:
|
|
975
|
+
handled = false;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if (handled) {
|
|
979
|
+
event.stopPropagation();
|
|
980
|
+
event.preventDefault();
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
}
|
|
985
|
+
|
|
959
986
|
const target = { x: rect.left, y: rect.top };
|
|
960
987
|
switch (event.key) {
|
|
961
988
|
case 'ArrowUp':
|
|
@@ -1773,9 +1800,17 @@ export class Grid extends GridBase {
|
|
|
1773
1800
|
if (this.selected_annotation) {
|
|
1774
1801
|
|
|
1775
1802
|
const annotation = this.selected_annotation;
|
|
1803
|
+
|
|
1804
|
+
// we need to adjust textbox paragraph styles so they don't
|
|
1805
|
+
// override the annotation style. OR, we need to apply this
|
|
1806
|
+
// styling to the paragraphs. the former sounds better to me,
|
|
1807
|
+
// but then if we allow you to edit the paragraphs we'll have
|
|
1808
|
+
// to adjust the annotation style later. not sure which is
|
|
1809
|
+
// preferable.
|
|
1810
|
+
|
|
1776
1811
|
annotation.data.style = JSON.parse(JSON.stringify(
|
|
1777
|
-
delta ? Style.Composite([annotation.data.style || {}, style]) : style
|
|
1778
|
-
|
|
1812
|
+
delta ? Style.Composite([annotation.data.style || {}, style]) : style));
|
|
1813
|
+
|
|
1779
1814
|
const node = annotation.view[this.view_index]?.node;
|
|
1780
1815
|
|
|
1781
1816
|
this.layout.UpdateAnnotation(annotation, this.theme);
|