@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
package/dist/treb.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! API
|
|
1
|
+
/*! API v28.0. Copyright 2018-2023 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* add our tag to the map
|
|
@@ -86,6 +86,9 @@ export interface EmbeddedSpreadsheetOptions {
|
|
|
86
86
|
/** add resizable wrapper */
|
|
87
87
|
resizable?: boolean;
|
|
88
88
|
|
|
89
|
+
/** even if we allow resizing, constrain width. this is to support fixed width columns. */
|
|
90
|
+
constrain_width?: boolean;
|
|
91
|
+
|
|
89
92
|
/** export to xlsx, now optional */
|
|
90
93
|
export?: boolean;
|
|
91
94
|
|
|
@@ -247,6 +250,12 @@ export interface EmbeddedSpreadsheetOptions {
|
|
|
247
250
|
* was renamed from `revert` to avoid any ambiguity.
|
|
248
251
|
*/
|
|
249
252
|
revert_button?: boolean;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* show the revert indicator. this is an indicator that shows on the
|
|
256
|
+
* top-left of the spreadsheet when a network document has local changes.
|
|
257
|
+
*/
|
|
258
|
+
revert_indicator?: boolean;
|
|
250
259
|
}
|
|
251
260
|
|
|
252
261
|
/**
|
|
@@ -302,6 +311,22 @@ export declare class EmbeddedSpreadsheet {
|
|
|
302
311
|
*/
|
|
303
312
|
get state(): number;
|
|
304
313
|
|
|
314
|
+
/**
|
|
315
|
+
* this flag indicates we can revert the document. what that means is
|
|
316
|
+
* we loaded a user-created version from localStorage, but there's a
|
|
317
|
+
* backing network or inline document. or we did load the original version
|
|
318
|
+
* but the user has made some document changes.
|
|
319
|
+
*
|
|
320
|
+
* it's like `dirty`, but that uses the load source as the ground truth,
|
|
321
|
+
* which means if you load a modified document from localStorage it's
|
|
322
|
+
* initially considered not-dirty (which is maybe just a bad design?)
|
|
323
|
+
*
|
|
324
|
+
* the intent of this field is to support enabling/disabling revert
|
|
325
|
+
* logic, or to add a visual indicator that you are not looking at the
|
|
326
|
+
* canonical version.
|
|
327
|
+
*/
|
|
328
|
+
get can_revert(): boolean;
|
|
329
|
+
|
|
305
330
|
/**
|
|
306
331
|
* indicates the current revision of the document is not equal to the
|
|
307
332
|
* last-saved revision of the document.
|
|
@@ -550,8 +575,11 @@ export declare class EmbeddedSpreadsheet {
|
|
|
550
575
|
UnmergeCells(range?: RangeReference): void;
|
|
551
576
|
|
|
552
577
|
/**
|
|
553
|
-
* revert to the network version of this document, if
|
|
554
|
-
* and `
|
|
578
|
+
* revert to the network version of this document, if `local_storage`
|
|
579
|
+
* is set and the create options had either `document` or `inline-document`
|
|
580
|
+
* set.
|
|
581
|
+
*
|
|
582
|
+
* FIXME: we should adjust for documents that fail to load.
|
|
555
583
|
*/
|
|
556
584
|
Revert(): void;
|
|
557
585
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as esbuild from 'esbuild';
|
|
4
4
|
|
|
5
5
|
import { SassPlugin, WorkerPlugin, NotifyPlugin, HTMLPlugin } from './esbuild-utils.mjs';
|
|
6
|
+
import { promises as fs } from 'fs';
|
|
6
7
|
|
|
7
8
|
import pkg from './package.json' assert { type: 'json' };
|
|
8
9
|
|
|
@@ -90,5 +91,6 @@ if (options.watch) {
|
|
|
90
91
|
await context.watch();
|
|
91
92
|
}
|
|
92
93
|
else {
|
|
93
|
-
await esbuild.build(build_options);
|
|
94
|
+
const result = await esbuild.build(build_options);
|
|
95
|
+
await fs.writeFile('esbuild-metafile.json', JSON.stringify(result.metafile), { encoding: 'utf-8' });
|
|
94
96
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trebco/treb",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "28.0.5",
|
|
4
4
|
"license": "LGPL-3.0-or-later",
|
|
5
5
|
"homepage": "https://treb.app",
|
|
6
6
|
"repository": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"type": "module",
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@types/html-minifier": "^4.0.2",
|
|
15
|
-
"@types/node": "^20.
|
|
15
|
+
"@types/node": "^20.8.5",
|
|
16
16
|
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
|
17
17
|
"@typescript-eslint/parser": "^6.1.0",
|
|
18
18
|
"archiver": "^6.0.1",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"fast-xml-parser": "^4.0.7",
|
|
23
23
|
"html-minifier": "^4.0.0",
|
|
24
24
|
"jszip": "^3.6.0",
|
|
25
|
-
"sass": "^1.
|
|
25
|
+
"sass": "^1.69.3",
|
|
26
26
|
"treb-base-types": "file:treb-base-types",
|
|
27
27
|
"treb-calculator": "file:treb-calculator",
|
|
28
28
|
"treb-charts": "file:treb-charts",
|
|
@@ -47,6 +47,6 @@
|
|
|
47
47
|
"watch-tsc": "tsc -b treb-embed/modern.tsconfig.json -w",
|
|
48
48
|
"watch-api": "ts-node-dev --respawn api-generator/api-generator.ts --config api-config.json",
|
|
49
49
|
"generate-api": "ts-node-dev api-generator/api-generator.ts --config api-config.json",
|
|
50
|
-
"release": "npm run rebuild-tsc && npm run build && npm run generate-api"
|
|
50
|
+
"release": "npm run rebuild-tsc && npm run build && npm run generate-api && npm run build-light"
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -21,24 +21,120 @@
|
|
|
21
21
|
|
|
22
22
|
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
type EventHandlerMap = {
|
|
25
|
+
[key in keyof HTMLElementEventMap]: (event: HTMLElementEventMap[key]) => any;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type StyleMap = {
|
|
29
|
+
[key in keyof CSSStyleDeclaration]: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface CreateElementOptions {
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* FIXME: can we lock this down a bit?
|
|
36
|
+
*
|
|
37
|
+
* actually that might not be wise since we sometimes use "scope" type
|
|
38
|
+
* attributes that are not standard (maybe we should fix that, instead?)
|
|
39
|
+
*/
|
|
40
|
+
attrs?: Record<string, string>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* optionally style as a map
|
|
44
|
+
*/
|
|
45
|
+
style?: Partial<StyleMap>;
|
|
46
|
+
|
|
47
|
+
/** dataset or data-* attributes */
|
|
48
|
+
data?: Record<string, string>;
|
|
49
|
+
|
|
50
|
+
/** innerText */
|
|
51
|
+
text?: string;
|
|
52
|
+
|
|
53
|
+
/** innerHTML */
|
|
54
|
+
html?: string;
|
|
55
|
+
|
|
56
|
+
/** event handlers */
|
|
57
|
+
events?: Partial<EventHandlerMap>;
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* we still need a good way to represent the 'no-DOM' context,
|
|
63
|
+
* ideally without throwing exceptions.
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
export class DOMContext {
|
|
67
|
+
|
|
68
|
+
protected static instances: DOMContext[] = [];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* FIXME: how about we default to document, so it won't break?
|
|
72
|
+
* that will make it harder to debug though.
|
|
73
|
+
*/
|
|
74
|
+
public static GetInstance(doc?: Document) {
|
|
75
|
+
|
|
76
|
+
for (const instance of this.instances) {
|
|
77
|
+
if (instance.doc === doc) {
|
|
78
|
+
return instance;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// not found, create
|
|
83
|
+
const instance = new DOMContext(doc);
|
|
84
|
+
this.instances.push(instance);
|
|
85
|
+
return instance;
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** ugh sloppy */
|
|
90
|
+
public doc?: Document; // placeholder temp
|
|
91
|
+
|
|
92
|
+
/** ugh sloppy */
|
|
93
|
+
public view?: (Window & typeof globalThis) | null;
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
public get document(): Document {
|
|
97
|
+
return this.doc;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public get window(): (Window & typeof globalThis) {
|
|
101
|
+
return this.view;
|
|
102
|
+
}
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/** class for `instanceof` comparison */
|
|
106
|
+
public get HTMLElement() {
|
|
107
|
+
return this.view?.HTMLElement;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected constructor(doc?: Document) {
|
|
111
|
+
if (doc) {
|
|
112
|
+
this.doc = doc;
|
|
113
|
+
this.view = doc?.defaultView;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** wrapper for window.getSelection */
|
|
118
|
+
public GetSelection() {
|
|
119
|
+
return this.view?.getSelection();
|
|
120
|
+
}
|
|
25
121
|
|
|
26
122
|
/** creates a div and assigns class name/names */
|
|
27
|
-
public
|
|
28
|
-
return this.Create('div', classes, parent,
|
|
123
|
+
public Div(classes?: string|string[], parent?: HTMLElement, options?: CreateElementOptions): HTMLDivElement {
|
|
124
|
+
return this.Create('div', classes, parent, options);
|
|
29
125
|
}
|
|
30
126
|
|
|
31
|
-
public
|
|
127
|
+
public ClassNames(element: HTMLElement|SVGElement, classes: string|string[]) {
|
|
32
128
|
element.classList.add(...(Array.isArray(classes) ? classes : [classes]).reduce((arr: string[], entry) => [...arr, ...entry.split(/\s+/g)], []));
|
|
33
129
|
}
|
|
34
130
|
|
|
35
|
-
public
|
|
131
|
+
public SVG<K extends keyof SVGElementTagNameMap>(
|
|
36
132
|
tag: K,
|
|
37
133
|
classes?: string|string[],
|
|
38
|
-
parent?: HTMLElement|SVGElement
|
|
134
|
+
parent?: HTMLElement|SVGElement|DocumentFragment
|
|
39
135
|
): SVGElementTagNameMap[K] {
|
|
40
136
|
|
|
41
|
-
const element =
|
|
137
|
+
const element = (this.doc as Document).createElementNS(SVGNS, tag);
|
|
42
138
|
|
|
43
139
|
if (classes) {
|
|
44
140
|
this.ClassNames(element, classes);
|
|
@@ -51,29 +147,71 @@ export class DOMUtilities {
|
|
|
51
147
|
return element;
|
|
52
148
|
}
|
|
53
149
|
|
|
150
|
+
/**
|
|
151
|
+
* this is a wrapper for createTextNode. but if we want to expose
|
|
152
|
+
* the element/node classes (@see HTMLElement, above) then this
|
|
153
|
+
* should properly be the Text class and not a method. So we should
|
|
154
|
+
* rename it.
|
|
155
|
+
*
|
|
156
|
+
* @param data
|
|
157
|
+
* @returns
|
|
158
|
+
*/
|
|
159
|
+
public Text(data: string) {
|
|
160
|
+
return (this.doc as Document).createTextNode(data);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public Fragment() {
|
|
164
|
+
return (this.doc as Document).createDocumentFragment();
|
|
165
|
+
}
|
|
166
|
+
|
|
54
167
|
/** better typing */
|
|
55
|
-
public
|
|
168
|
+
public Create<K extends keyof HTMLElementTagNameMap>(
|
|
56
169
|
tag: K,
|
|
57
170
|
classes?: string|string[],
|
|
58
|
-
parent?: HTMLElement,
|
|
59
|
-
|
|
60
|
-
|
|
171
|
+
parent?: HTMLElement|DocumentFragment,
|
|
172
|
+
options?: CreateElementOptions
|
|
173
|
+
): HTMLElementTagNameMap[K] {
|
|
61
174
|
|
|
62
|
-
const element =
|
|
175
|
+
const element = (this.doc as Document).createElement(tag);
|
|
63
176
|
|
|
64
177
|
if (classes) {
|
|
65
178
|
this.ClassNames(element, classes);
|
|
66
179
|
}
|
|
67
180
|
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
181
|
+
if (options) {
|
|
182
|
+
|
|
183
|
+
if (options.attrs) {
|
|
184
|
+
for (const [key, value] of Object.entries(options.attrs)) {
|
|
185
|
+
element.setAttribute(key, value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (options.data) {
|
|
190
|
+
for (const [key, value] of Object.entries(options.data)) {
|
|
191
|
+
element.dataset[key] = value;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (options.text) {
|
|
196
|
+
element.textContent = options.text;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (options.html) {
|
|
200
|
+
element.innerHTML = options.html;
|
|
201
|
+
}
|
|
71
202
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
203
|
+
if (options.events) {
|
|
204
|
+
for (const [key, value] of Object.entries(options.events)) {
|
|
205
|
+
element.addEventListener(key, value as any); // typing works well up until this point
|
|
206
|
+
}
|
|
76
207
|
}
|
|
208
|
+
|
|
209
|
+
if (options.style) {
|
|
210
|
+
for (const [key, value] of Object.entries(options.style)) {
|
|
211
|
+
(element.style as any)[key] = value; // more sloppy typing
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
77
215
|
}
|
|
78
216
|
|
|
79
217
|
if (parent) {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import type { Color, CellStyle } from './style';
|
|
23
23
|
import { ColorFunctions } from './color';
|
|
24
|
-
import {
|
|
24
|
+
import { DOMContext } from './dom-utilities';
|
|
25
25
|
|
|
26
26
|
/*
|
|
27
27
|
* so this is a little strange. we use CSS to populate a theme object,
|
|
@@ -493,13 +493,14 @@ export const ThemeColorTable = (theme_color: number, tint = .7): TableTheme => {
|
|
|
493
493
|
export const LoadThemeProperties = (container: HTMLElement): Theme => {
|
|
494
494
|
|
|
495
495
|
const theme: Theme = JSON.parse(JSON.stringify(DefaultTheme));
|
|
496
|
+
const DOM = DOMContext.GetInstance(container.ownerDocument);
|
|
496
497
|
|
|
497
498
|
const Append = (parent: HTMLElement, classes: string): HTMLDivElement => {
|
|
498
|
-
return
|
|
499
|
+
return DOM.Div(classes, parent);
|
|
499
500
|
}
|
|
500
501
|
|
|
501
502
|
const ElementCSS = (parent: HTMLElement, classes: string): CSSStyleDeclaration => {
|
|
502
|
-
return
|
|
503
|
+
return DOM.view?.getComputedStyle(Append(parent, classes)) as CSSStyleDeclaration;
|
|
503
504
|
}
|
|
504
505
|
|
|
505
506
|
const node = Append(container, '');
|
|
@@ -572,7 +573,7 @@ export const LoadThemeProperties = (container: HTMLElement): Theme => {
|
|
|
572
573
|
// we could just parse, we know the returned css format is going
|
|
573
574
|
// to be an rgb triple (I think?)
|
|
574
575
|
|
|
575
|
-
const canvas =
|
|
576
|
+
const canvas = DOM.Create('canvas');
|
|
576
577
|
|
|
577
578
|
canvas.width = 3;
|
|
578
579
|
canvas.height = 3;
|
|
@@ -33,33 +33,6 @@ export interface Metrics {
|
|
|
33
33
|
y_offset: number;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
// const trident = /trident/i.test(navigator?.userAgent || '');
|
|
37
|
-
|
|
38
|
-
/*
|
|
39
|
-
let dom_parser: DOMParser | undefined;
|
|
40
|
-
const SetSVG = trident ? (node: SVGElement, svg: string) => {
|
|
41
|
-
|
|
42
|
-
if (!dom_parser) {
|
|
43
|
-
dom_parser = new DOMParser();
|
|
44
|
-
(dom_parser as any).async = false;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const element = dom_parser.parseFromString(
|
|
48
|
-
'<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + svg + '</svg>',
|
|
49
|
-
'text/xml').documentElement;
|
|
50
|
-
|
|
51
|
-
node.textContent = '';
|
|
52
|
-
|
|
53
|
-
let child = element.firstChild;
|
|
54
|
-
|
|
55
|
-
while (child) {
|
|
56
|
-
node.appendChild(document.importNode(child, true));
|
|
57
|
-
child = child.nextSibling;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
} : (node: SVGElement, svg: string) => node.innerHTML = svg;
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
36
|
const SVGNode = (tag: string, attribute_map: {[index: string]: any} = {}, text?: string): SVGElement => {
|
|
64
37
|
const node = document.createElementNS(SVGNS, tag);
|
|
65
38
|
for (const key of Object.keys(attribute_map)) {
|
|
@@ -115,7 +88,6 @@ export class ChartRenderer {
|
|
|
115
88
|
this.svg_node.style.width = '100%';
|
|
116
89
|
this.svg_node.style.height = '100%';
|
|
117
90
|
|
|
118
|
-
// this.group = document.createElementNS(SVGNS, 'g');
|
|
119
91
|
this.svg_node.appendChild(this.container_group);
|
|
120
92
|
|
|
121
93
|
// FIXME: validate parent is relative/absolute
|
|
@@ -676,8 +648,6 @@ export class ChartRenderer {
|
|
|
676
648
|
titles?: string[],
|
|
677
649
|
classes?: string | string[]): void {
|
|
678
650
|
|
|
679
|
-
|
|
680
|
-
// const node = document.createElementNS(SVGNS, 'path');
|
|
681
651
|
const group = SVGNode('g');
|
|
682
652
|
|
|
683
653
|
const d1: string[] = [];
|
|
@@ -853,7 +823,7 @@ export class ChartRenderer {
|
|
|
853
823
|
// circles...
|
|
854
824
|
|
|
855
825
|
if (titles && circles.length) {
|
|
856
|
-
const circle_group =
|
|
826
|
+
const circle_group = SVGNode('g');
|
|
857
827
|
for (const circle of circles) {
|
|
858
828
|
|
|
859
829
|
const shape = SVGNode('circle', {cx: circle.x, cy: circle.y, r: step});
|
|
@@ -880,8 +850,7 @@ export class ChartRenderer {
|
|
|
880
850
|
titles?: string[],
|
|
881
851
|
classes?: string | string[]) {
|
|
882
852
|
|
|
883
|
-
|
|
884
|
-
const group = document.createElementNS(SVGNS, 'g');
|
|
853
|
+
const group = SVGNode('g');
|
|
885
854
|
|
|
886
855
|
const d1: string[] = [];
|
|
887
856
|
const d2: string[] = [];
|
|
@@ -952,18 +921,11 @@ export class ChartRenderer {
|
|
|
952
921
|
// circles...
|
|
953
922
|
|
|
954
923
|
if (titles && circles.length) {
|
|
955
|
-
const circle_group =
|
|
924
|
+
const circle_group = SVGNode('g');
|
|
956
925
|
for (const circle of circles) {
|
|
957
926
|
|
|
958
927
|
const shape = SVGNode('circle', { cx: circle.x, cy: circle.y, r: step });
|
|
959
928
|
|
|
960
|
-
/*
|
|
961
|
-
const shape = document.createElementNS(SVGNS, 'circle');
|
|
962
|
-
shape.setAttribute('cx', circle.x.toString());
|
|
963
|
-
shape.setAttribute('cy', circle.y.toString());
|
|
964
|
-
shape.setAttribute('r', (step).toString());
|
|
965
|
-
*/
|
|
966
|
-
|
|
967
929
|
shape.addEventListener('mouseenter', (event) => {
|
|
968
930
|
this.parent.setAttribute('title', titles[circle.i] || '');
|
|
969
931
|
});
|
|
@@ -1255,15 +1217,6 @@ export class ChartRenderer {
|
|
|
1255
1217
|
const d: string[] = [];
|
|
1256
1218
|
const areas: string[] = [];
|
|
1257
1219
|
|
|
1258
|
-
/*
|
|
1259
|
-
const group = document.createElementNS(SVGNS, 'g');
|
|
1260
|
-
if (typeof classes !== 'undefined') {
|
|
1261
|
-
if (typeof classes === 'string') {
|
|
1262
|
-
classes = [classes];
|
|
1263
|
-
}
|
|
1264
|
-
group.setAttribute('class', classes.join(' '));
|
|
1265
|
-
}
|
|
1266
|
-
*/
|
|
1267
1220
|
const group = SVGNode('g', {class: classes});
|
|
1268
1221
|
|
|
1269
1222
|
// if (title) node.setAttribute('title', title);
|
|
@@ -1392,7 +1345,6 @@ export class ChartRenderer {
|
|
|
1392
1345
|
|
|
1393
1346
|
public RenderPoints(area: Area, x: number[], y: number[], classes?: string | string[]) {
|
|
1394
1347
|
|
|
1395
|
-
// const node = document.createElementNS(SVGNS, 'path');
|
|
1396
1348
|
const d: string[] = [];
|
|
1397
1349
|
|
|
1398
1350
|
for (let i = 0; i < x.length; i++) {
|
|
@@ -1693,12 +1645,6 @@ export class ChartRenderer {
|
|
|
1693
1645
|
d.push(`M${PointOnCircle(center, inner_radius + (outer_radius - inner_radius) / 2, half_angle)}`);
|
|
1694
1646
|
d.push(`L${anchor}`);
|
|
1695
1647
|
|
|
1696
|
-
/*
|
|
1697
|
-
const callout = document.createElementNS(SVGNS, 'path');
|
|
1698
|
-
callout.setAttribute('d', d.join(' '));
|
|
1699
|
-
callout.setAttribute('class', 'callout');
|
|
1700
|
-
donut.appendChild(callout);
|
|
1701
|
-
*/
|
|
1702
1648
|
donut.appendChild(SVGNode('path', { d, class: 'callout' }));
|
|
1703
1649
|
|
|
1704
1650
|
const text_parts: string[] = [];
|
|
@@ -1793,7 +1739,7 @@ export class ChartRenderer {
|
|
|
1793
1739
|
|
|
1794
1740
|
callout_label.textContent = '';
|
|
1795
1741
|
for (const part of parts) {
|
|
1796
|
-
const tspan =
|
|
1742
|
+
const tspan = SVGNode('tspan');
|
|
1797
1743
|
tspan.textContent = part.text;
|
|
1798
1744
|
|
|
1799
1745
|
const part_x = (corrected > Math.PI) ?
|
|
@@ -121,6 +121,10 @@
|
|
|
121
121
|
|
|
122
122
|
<div class="treb-layout-resize-handle" data-conditional="resize"></div>
|
|
123
123
|
|
|
124
|
+
<div class="treb-revert-indicator"
|
|
125
|
+
data-command="revert-indicator"
|
|
126
|
+
title="This document has been modified from the original version."></div>
|
|
127
|
+
|
|
124
128
|
</div> <!-- /treb-view -->
|
|
125
129
|
</template>
|
|
126
130
|
|