@dodlhuat/basix 1.4.2 → 1.4.3
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 +13 -1
- package/css/calendar.scss +4 -3
- package/css/code-viewer.scss +1 -1
- package/css/datepicker.scss +83 -70
- package/css/editor.scss +2 -1
- package/css/flyout-menu.scss +2 -1
- package/css/form.scss +11 -32
- package/css/mixins.scss +25 -0
- package/css/range-slider.scss +7 -6
- package/css/stepper.scss +2 -1
- package/css/style.css +84 -71
- package/css/style.css.map +1 -1
- package/css/style.min.css +1 -1
- package/css/style.min.css.map +1 -1
- package/css/timepicker.scss +1 -1
- package/css/virtual-dropdown.scss +6 -16
- package/js/bottom-sheet.d.ts +3 -5
- package/js/bottom-sheet.js +39 -58
- package/js/calendar.d.ts +1 -2
- package/js/calendar.js +77 -84
- package/js/carousel.d.ts +1 -1
- package/js/carousel.js +22 -14
- package/js/chart.d.ts +1 -1
- package/js/chart.js +104 -65
- package/js/code-viewer.d.ts +1 -1
- package/js/code-viewer.js +7 -18
- package/js/color-picker.d.ts +2 -2
- package/js/color-picker.js +20 -22
- package/js/context-menu.d.ts +1 -1
- package/js/context-menu.js +10 -12
- package/js/datepicker.d.ts +14 -3
- package/js/datepicker.js +180 -99
- package/js/dropdown.d.ts +1 -1
- package/js/dropdown.js +4 -5
- package/js/editor.d.ts +1 -1
- package/js/editor.js +30 -34
- package/js/file-uploader.d.ts +2 -9
- package/js/file-uploader.js +57 -86
- package/js/flyout-menu.d.ts +3 -3
- package/js/flyout-menu.js +20 -22
- package/js/gallery.d.ts +1 -2
- package/js/gallery.js +14 -20
- package/js/group-picker.d.ts +1 -1
- package/js/group-picker.js +22 -29
- package/js/lightbox.d.ts +2 -2
- package/js/lightbox.js +28 -27
- package/js/listeners.d.ts +7 -0
- package/js/listeners.js +14 -0
- package/js/modal.d.ts +2 -1
- package/js/modal.js +13 -20
- package/js/popover.d.ts +2 -2
- package/js/popover.js +42 -37
- package/js/position.js +3 -5
- package/js/push-menu.d.ts +2 -0
- package/js/push-menu.js +21 -15
- package/js/range-slider.d.ts +2 -2
- package/js/range-slider.js +7 -6
- package/js/scroll.js +4 -7
- package/js/scrollbar.d.ts +3 -3
- package/js/scrollbar.js +39 -42
- package/js/select.d.ts +1 -1
- package/js/select.js +19 -23
- package/js/sidebar-nav.d.ts +1 -1
- package/js/sidebar-nav.js +13 -9
- package/js/stepper.d.ts +1 -1
- package/js/stepper.js +9 -11
- package/js/table.d.ts +1 -1
- package/js/table.js +24 -23
- package/js/tabs.d.ts +1 -1
- package/js/tabs.js +10 -17
- package/js/theme.d.ts +1 -0
- package/js/theme.js +6 -15
- package/js/timepicker.d.ts +8 -6
- package/js/timepicker.js +36 -36
- package/js/toast.d.ts +2 -1
- package/js/toast.js +8 -4
- package/js/tooltip.d.ts +1 -4
- package/js/tooltip.js +14 -23
- package/js/tree.d.ts +0 -1
- package/js/tree.js +6 -11
- package/js/utils.js +7 -8
- package/js/virtual-dropdown.d.ts +1 -1
- package/js/virtual-dropdown.js +26 -28
- package/package.json +1 -1
- package/css/calendar.css +0 -928
- package/css/guitar-chords.css +0 -251
- package/js/form-builder.js +0 -107
- package/js/guitar-chords.js +0 -268
- package/js/lazy-loader.js +0 -121
- package/js/request.js +0 -51
package/js/chart.js
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
import { escapeHtml } from './utils.js';
|
|
2
|
+
import { ListenerGroup } from './listeners.js';
|
|
2
3
|
const MARGIN_XY = { top: 16, right: 24, bottom: 44, left: 52 };
|
|
3
4
|
const MARGIN_BAR = { top: 8, right: 52, bottom: 24, left: 120 };
|
|
4
5
|
const MARGIN_PIE = { top: 8, right: 8, bottom: 8, left: 8 };
|
|
5
|
-
const FALLBACK_COLORS = [
|
|
6
|
-
'#3D63DD', '#2E8B57', '#C28A00', '#D64545',
|
|
7
|
-
'#8B5CF6', '#06B6D4', '#F97316', '#EC4899',
|
|
8
|
-
];
|
|
6
|
+
const FALLBACK_COLORS = ['#3D63DD', '#2E8B57', '#C28A00', '#D64545', '#8B5CF6', '#06B6D4', '#F97316', '#EC4899'];
|
|
9
7
|
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
10
8
|
class Chart {
|
|
11
9
|
container;
|
|
12
10
|
opts;
|
|
13
11
|
tooltip;
|
|
14
12
|
colors = [];
|
|
15
|
-
|
|
13
|
+
listeners = new ListenerGroup();
|
|
16
14
|
resizeTimer = null;
|
|
17
15
|
resizeObserver = null;
|
|
18
16
|
constructor(selector, options) {
|
|
19
|
-
const el = typeof selector === 'string'
|
|
20
|
-
? document.querySelector(selector)
|
|
21
|
-
: selector;
|
|
17
|
+
const el = typeof selector === 'string' ? document.querySelector(selector) : selector;
|
|
22
18
|
if (!el)
|
|
23
19
|
throw new Error(`Chart: element not found for "${selector}"`);
|
|
24
20
|
this.container = el;
|
|
@@ -40,8 +36,7 @@ class Chart {
|
|
|
40
36
|
this.attachResizeObserver();
|
|
41
37
|
}
|
|
42
38
|
render() {
|
|
43
|
-
this.
|
|
44
|
-
this.abortController = new AbortController();
|
|
39
|
+
this.listeners.reset();
|
|
45
40
|
this.container.innerHTML = '';
|
|
46
41
|
this.container.classList.add('chart');
|
|
47
42
|
this.resolveColors();
|
|
@@ -82,12 +77,12 @@ class Chart {
|
|
|
82
77
|
const svgH = height + m.top + m.bottom;
|
|
83
78
|
const w = svgW - m.left - m.right;
|
|
84
79
|
const h = height;
|
|
85
|
-
const allValues = series.flatMap(s => s.data.map(d => d.value));
|
|
80
|
+
const allValues = series.flatMap((s) => s.data.map((d) => d.value));
|
|
86
81
|
const yMax = this.opts.yMax ?? Math.max(...allValues) * 1.1;
|
|
87
|
-
const labels = series[0].data.map(d => d.label);
|
|
82
|
+
const labels = series[0].data.map((d) => d.label);
|
|
88
83
|
const svg = this.createSVG(canvas, svgW, svgH);
|
|
89
84
|
if (showGrid)
|
|
90
|
-
this.renderHGrid(svg, m, w, h
|
|
85
|
+
this.renderHGrid(svg, m, w, h);
|
|
91
86
|
this.renderXAxisLine(svg, m, w, h);
|
|
92
87
|
this.renderXLabels(svg, m, w, h, labels);
|
|
93
88
|
this.renderYLabels(svg, m, h, yMin, yMax);
|
|
@@ -101,15 +96,20 @@ class Chart {
|
|
|
101
96
|
if (isArea) {
|
|
102
97
|
const areaD = `${this.buildPath(pts)} L ${pts[pts.length - 1].x} ${m.top + h} L ${pts[0].x} ${m.top + h} Z`;
|
|
103
98
|
svg.appendChild(this.svgEl('path', {
|
|
104
|
-
d: areaD,
|
|
105
|
-
|
|
99
|
+
d: areaD,
|
|
100
|
+
fill: color,
|
|
101
|
+
'fill-opacity': '0.12',
|
|
102
|
+
stroke: 'none',
|
|
106
103
|
class: 'chart-area',
|
|
107
104
|
}));
|
|
108
105
|
}
|
|
109
106
|
const linePath = this.svgEl('path', {
|
|
110
|
-
d: this.buildPath(pts),
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
d: this.buildPath(pts),
|
|
108
|
+
fill: 'none',
|
|
109
|
+
stroke: color,
|
|
110
|
+
'stroke-width': '2.5',
|
|
111
|
+
'stroke-linecap': 'round',
|
|
112
|
+
'stroke-linejoin': 'round',
|
|
113
113
|
class: 'chart-line',
|
|
114
114
|
});
|
|
115
115
|
if (animate) {
|
|
@@ -126,17 +126,28 @@ class Chart {
|
|
|
126
126
|
});
|
|
127
127
|
const { x, y } = pts[i];
|
|
128
128
|
g.appendChild(this.svgEl('circle', {
|
|
129
|
-
cx: x,
|
|
130
|
-
|
|
129
|
+
cx: x,
|
|
130
|
+
cy: y,
|
|
131
|
+
r: 14,
|
|
132
|
+
fill: 'transparent',
|
|
133
|
+
class: 'chart-hit',
|
|
131
134
|
}));
|
|
132
135
|
g.appendChild(this.svgEl('circle', {
|
|
133
|
-
cx: x,
|
|
134
|
-
|
|
136
|
+
cx: x,
|
|
137
|
+
cy: y,
|
|
138
|
+
r: 7,
|
|
139
|
+
fill: 'none',
|
|
140
|
+
stroke: color,
|
|
141
|
+
'stroke-width': '2',
|
|
135
142
|
class: 'chart-point-ring',
|
|
136
143
|
}));
|
|
137
144
|
g.appendChild(this.svgEl('circle', {
|
|
138
|
-
cx: x,
|
|
139
|
-
|
|
145
|
+
cx: x,
|
|
146
|
+
cy: y,
|
|
147
|
+
r: 4,
|
|
148
|
+
fill: color,
|
|
149
|
+
stroke: 'var(--background)',
|
|
150
|
+
'stroke-width': '2',
|
|
140
151
|
class: 'chart-point-dot',
|
|
141
152
|
}));
|
|
142
153
|
this.onPoint(g, s, d, i);
|
|
@@ -153,14 +164,14 @@ class Chart {
|
|
|
153
164
|
const svgH = height + m.top + m.bottom;
|
|
154
165
|
const w = svgW - m.left - m.right;
|
|
155
166
|
const h = height;
|
|
156
|
-
const allValues = series.flatMap(s => s.data.map(d => d.value));
|
|
167
|
+
const allValues = series.flatMap((s) => s.data.map((d) => d.value));
|
|
157
168
|
const yMax = this.opts.yMax ?? Math.max(...allValues) * 1.1;
|
|
158
|
-
const labels = series[0].data.map(d => d.label);
|
|
169
|
+
const labels = series[0].data.map((d) => d.label);
|
|
159
170
|
const numPts = labels.length;
|
|
160
171
|
const numSeries = series.length;
|
|
161
172
|
const svg = this.createSVG(canvas, svgW, svgH);
|
|
162
173
|
if (showGrid)
|
|
163
|
-
this.renderHGrid(svg, m, w, h
|
|
174
|
+
this.renderHGrid(svg, m, w, h);
|
|
164
175
|
this.renderXAxisLine(svg, m, w, h);
|
|
165
176
|
this.renderXLabels(svg, m, w, h, labels);
|
|
166
177
|
this.renderYLabels(svg, m, h, yMin, yMax);
|
|
@@ -174,8 +185,12 @@ class Chart {
|
|
|
174
185
|
const x = m.left + i * groupW + innerPad / 2 + si * (barW + 2);
|
|
175
186
|
const y = m.top + h - barH;
|
|
176
187
|
const rect = this.svgEl('rect', {
|
|
177
|
-
x,
|
|
178
|
-
|
|
188
|
+
x,
|
|
189
|
+
y,
|
|
190
|
+
width: barW,
|
|
191
|
+
height: barH,
|
|
192
|
+
fill: color,
|
|
193
|
+
rx: 3,
|
|
179
194
|
class: 'chart-bar chart-bar--vertical',
|
|
180
195
|
});
|
|
181
196
|
if (animate) {
|
|
@@ -197,9 +212,9 @@ class Chart {
|
|
|
197
212
|
const svgH = height + m.top + m.bottom;
|
|
198
213
|
const w = svgW - m.left - m.right;
|
|
199
214
|
const h = height;
|
|
200
|
-
const allValues = series.flatMap(s => s.data.map(d => d.value));
|
|
201
|
-
const xMax = this.opts.yMax
|
|
202
|
-
const labels = series[0].data.map(d => d.label);
|
|
215
|
+
const allValues = series.flatMap((s) => s.data.map((d) => d.value));
|
|
216
|
+
const xMax = this.opts.yMax ?? Math.max(...allValues) * 1.1;
|
|
217
|
+
const labels = series[0].data.map((d) => d.label);
|
|
203
218
|
const numPts = labels.length;
|
|
204
219
|
const numSeries = series.length;
|
|
205
220
|
const svg = this.createSVG(canvas, svgW, svgH);
|
|
@@ -207,24 +222,32 @@ class Chart {
|
|
|
207
222
|
for (let t = 0; t <= numTicks; t++) {
|
|
208
223
|
const x = m.left + (t / numTicks) * w;
|
|
209
224
|
svg.appendChild(this.svgEl('line', {
|
|
210
|
-
x1: x,
|
|
211
|
-
|
|
225
|
+
x1: x,
|
|
226
|
+
x2: x,
|
|
227
|
+
y1: m.top,
|
|
228
|
+
y2: m.top + h,
|
|
229
|
+
stroke: 'var(--divider)',
|
|
230
|
+
'stroke-width': '1',
|
|
212
231
|
'stroke-dasharray': t === 0 ? 'none' : '3 4',
|
|
213
232
|
class: 'chart-grid-line',
|
|
214
233
|
}));
|
|
215
234
|
const label = this.svgEl('text', {
|
|
216
|
-
x,
|
|
217
|
-
|
|
235
|
+
x,
|
|
236
|
+
y: m.top + h + 14,
|
|
237
|
+
'text-anchor': 'middle',
|
|
238
|
+
class: 'chart-axis-label',
|
|
218
239
|
});
|
|
219
|
-
label.textContent = this.fmt(xMax * t / numTicks);
|
|
240
|
+
label.textContent = this.fmt((xMax * t) / numTicks);
|
|
220
241
|
svg.appendChild(label);
|
|
221
242
|
}
|
|
222
243
|
const groupH = h / numPts;
|
|
223
244
|
labels.forEach((label, i) => {
|
|
224
245
|
const y = m.top + i * groupH + groupH / 2;
|
|
225
246
|
const text = this.svgEl('text', {
|
|
226
|
-
x: m.left - 10,
|
|
227
|
-
|
|
247
|
+
x: m.left - 10,
|
|
248
|
+
y,
|
|
249
|
+
'text-anchor': 'end',
|
|
250
|
+
'dominant-baseline': 'middle',
|
|
228
251
|
class: 'chart-axis-label',
|
|
229
252
|
});
|
|
230
253
|
text.textContent = label;
|
|
@@ -239,8 +262,12 @@ class Chart {
|
|
|
239
262
|
const x = m.left;
|
|
240
263
|
const y = m.top + i * groupH + innerPad / 2 + si * (barH + 2);
|
|
241
264
|
const rect = this.svgEl('rect', {
|
|
242
|
-
x,
|
|
243
|
-
|
|
265
|
+
x,
|
|
266
|
+
y,
|
|
267
|
+
width: barW,
|
|
268
|
+
height: barH,
|
|
269
|
+
fill: color,
|
|
270
|
+
rx: 3,
|
|
244
271
|
class: 'chart-bar chart-bar--horizontal',
|
|
245
272
|
});
|
|
246
273
|
if (animate) {
|
|
@@ -284,17 +311,18 @@ class Chart {
|
|
|
284
311
|
path.style.animationDelay = `${delay}ms`;
|
|
285
312
|
}
|
|
286
313
|
const { x: dx, y: dy } = this.polar(0, 0, 8, midAngle);
|
|
314
|
+
const sig = { signal: this.listeners.signal };
|
|
315
|
+
const tipHtml = `<strong>${escapeHtml(d.label)}</strong>${this.fmt(d.value)} · ${((d.value / total) * 100).toFixed(1)}%`;
|
|
287
316
|
path.addEventListener('mouseenter', (e) => {
|
|
288
317
|
path.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
289
|
-
this.showTooltip(e,
|
|
290
|
-
},
|
|
318
|
+
this.showTooltip(e, tipHtml);
|
|
319
|
+
}, sig);
|
|
320
|
+
path.addEventListener('mousemove', (e) => this.moveTooltip(e), sig);
|
|
291
321
|
path.addEventListener('mouseleave', () => {
|
|
292
322
|
path.style.transform = '';
|
|
293
323
|
this.hideTooltip();
|
|
294
|
-
},
|
|
295
|
-
path.addEventListener('click', () =>
|
|
296
|
-
this.opts.onPointClick(s, d, i);
|
|
297
|
-
}, { signal: this.abortController.signal });
|
|
324
|
+
}, sig);
|
|
325
|
+
path.addEventListener('click', () => this.opts.onPointClick(s, d, i), sig);
|
|
298
326
|
svg.appendChild(path);
|
|
299
327
|
startAngle = endAngle;
|
|
300
328
|
});
|
|
@@ -302,20 +330,25 @@ class Chart {
|
|
|
302
330
|
this.container.appendChild(this.buildPieLegend(s, total));
|
|
303
331
|
}
|
|
304
332
|
}
|
|
305
|
-
renderHGrid(svg, m, w, h
|
|
333
|
+
renderHGrid(svg, m, w, h) {
|
|
306
334
|
const numTicks = 5;
|
|
307
335
|
for (let i = 0; i <= numTicks; i++) {
|
|
308
336
|
const y = m.top + h - (i / numTicks) * h;
|
|
309
337
|
svg.appendChild(this.svgEl('line', {
|
|
310
|
-
x1: m.left,
|
|
338
|
+
x1: m.left,
|
|
339
|
+
x2: m.left + w,
|
|
340
|
+
y1: y,
|
|
341
|
+
y2: y,
|
|
311
342
|
class: i === 0 ? 'chart-axis-line' : 'chart-grid-line',
|
|
312
343
|
}));
|
|
313
344
|
}
|
|
314
345
|
}
|
|
315
346
|
renderXAxisLine(svg, m, w, h) {
|
|
316
347
|
svg.appendChild(this.svgEl('line', {
|
|
317
|
-
x1: m.left,
|
|
318
|
-
|
|
348
|
+
x1: m.left,
|
|
349
|
+
x2: m.left + w,
|
|
350
|
+
y1: m.top + h,
|
|
351
|
+
y2: m.top + h,
|
|
319
352
|
class: 'chart-axis-line',
|
|
320
353
|
}));
|
|
321
354
|
}
|
|
@@ -325,8 +358,10 @@ class Chart {
|
|
|
325
358
|
labels.forEach((label, i) => {
|
|
326
359
|
const x = m.left + (n > 1 ? i * step : w / 2);
|
|
327
360
|
const text = this.svgEl('text', {
|
|
328
|
-
x,
|
|
329
|
-
|
|
361
|
+
x,
|
|
362
|
+
y: m.top + h + 18,
|
|
363
|
+
'text-anchor': 'middle',
|
|
364
|
+
class: 'chart-axis-label',
|
|
330
365
|
});
|
|
331
366
|
text.textContent = label;
|
|
332
367
|
svg.appendChild(text);
|
|
@@ -338,8 +373,10 @@ class Chart {
|
|
|
338
373
|
const val = yMin + (yMax - yMin) * (i / numTicks);
|
|
339
374
|
const y = m.top + h - (i / numTicks) * h;
|
|
340
375
|
const text = this.svgEl('text', {
|
|
341
|
-
x: m.left - 8,
|
|
342
|
-
|
|
376
|
+
x: m.left - 8,
|
|
377
|
+
y,
|
|
378
|
+
'text-anchor': 'end',
|
|
379
|
+
'dominant-baseline': 'middle',
|
|
343
380
|
class: 'chart-axis-label',
|
|
344
381
|
});
|
|
345
382
|
text.textContent = this.fmt(val);
|
|
@@ -348,9 +385,12 @@ class Chart {
|
|
|
348
385
|
}
|
|
349
386
|
buildPath(pts) {
|
|
350
387
|
switch (this.opts.curve) {
|
|
351
|
-
case 'linear':
|
|
352
|
-
|
|
353
|
-
|
|
388
|
+
case 'linear':
|
|
389
|
+
return this.linearPath(pts);
|
|
390
|
+
case 'step':
|
|
391
|
+
return this.stepPath(pts);
|
|
392
|
+
default:
|
|
393
|
+
return this.smoothPath(pts);
|
|
354
394
|
}
|
|
355
395
|
}
|
|
356
396
|
linearPath(pts) {
|
|
@@ -392,11 +432,11 @@ class Chart {
|
|
|
392
432
|
arcPath(cx, cy, r, startDeg, endDeg) {
|
|
393
433
|
const start = this.polar(cx, cy, r, startDeg);
|
|
394
434
|
const end = this.polar(cx, cy, r, endDeg);
|
|
395
|
-
const large =
|
|
435
|
+
const large = endDeg - startDeg > 180 ? 1 : 0;
|
|
396
436
|
return `M ${cx} ${cy} L ${start.x.toFixed(2)} ${start.y.toFixed(2)} A ${r} ${r} 0 ${large} 1 ${end.x.toFixed(2)} ${end.y.toFixed(2)} Z`;
|
|
397
437
|
}
|
|
398
438
|
polar(cx, cy, r, deg) {
|
|
399
|
-
const rad = deg * Math.PI / 180;
|
|
439
|
+
const rad = (deg * Math.PI) / 180;
|
|
400
440
|
return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };
|
|
401
441
|
}
|
|
402
442
|
buildHeader() {
|
|
@@ -466,7 +506,7 @@ class Chart {
|
|
|
466
506
|
this.tooltip.classList.remove('is-visible');
|
|
467
507
|
}
|
|
468
508
|
onPoint(g, s, d, i) {
|
|
469
|
-
const sig = { signal: this.
|
|
509
|
+
const sig = { signal: this.listeners.signal };
|
|
470
510
|
g.addEventListener('mouseenter', (e) => {
|
|
471
511
|
this.showTooltip(e, `<strong>${escapeHtml(d.label)}</strong>${escapeHtml(s.name)}: ${this.fmt(d.value)}`);
|
|
472
512
|
}, sig);
|
|
@@ -475,7 +515,7 @@ class Chart {
|
|
|
475
515
|
g.addEventListener('click', () => this.opts.onPointClick(s, d, i), sig);
|
|
476
516
|
}
|
|
477
517
|
onBar(rect, s, d, i) {
|
|
478
|
-
const sig = { signal: this.
|
|
518
|
+
const sig = { signal: this.listeners.signal };
|
|
479
519
|
rect.style.cursor = 'pointer';
|
|
480
520
|
rect.addEventListener('mouseenter', (e) => {
|
|
481
521
|
this.showTooltip(e, `<strong>${escapeHtml(d.label)}</strong>${escapeHtml(s.name)}: ${this.fmt(d.value)}`);
|
|
@@ -486,8 +526,7 @@ class Chart {
|
|
|
486
526
|
}
|
|
487
527
|
resolveColors() {
|
|
488
528
|
const style = getComputedStyle(this.container);
|
|
489
|
-
this.colors = (this.opts.type === 'pie' ? this.opts.series[0]?.data ?? [] : this.opts.series)
|
|
490
|
-
.map((_, i) => {
|
|
529
|
+
this.colors = (this.opts.type === 'pie' ? (this.opts.series[0]?.data ?? []) : this.opts.series).map((_, i) => {
|
|
491
530
|
const css = style.getPropertyValue(`--chart-color-${i + 1}`).trim();
|
|
492
531
|
return css || FALLBACK_COLORS[i % FALLBACK_COLORS.length];
|
|
493
532
|
});
|
|
@@ -542,7 +581,7 @@ class Chart {
|
|
|
542
581
|
this.render();
|
|
543
582
|
}
|
|
544
583
|
destroy() {
|
|
545
|
-
this.
|
|
584
|
+
this.listeners.destroy();
|
|
546
585
|
this.resizeObserver?.disconnect();
|
|
547
586
|
if (this.resizeTimer)
|
|
548
587
|
clearTimeout(this.resizeTimer);
|
package/js/code-viewer.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ declare class CodeViewer {
|
|
|
3
3
|
private container;
|
|
4
4
|
private code;
|
|
5
5
|
private language;
|
|
6
|
+
private listeners;
|
|
6
7
|
constructor(elementOrSelector: string | HTMLElement, code: string, language?: SupportedLanguage);
|
|
7
8
|
private highlight;
|
|
8
9
|
private escape;
|
|
@@ -11,7 +12,6 @@ declare class CodeViewer {
|
|
|
11
12
|
private highlightCSS;
|
|
12
13
|
private copyCode;
|
|
13
14
|
private render;
|
|
14
|
-
private handleCopy;
|
|
15
15
|
destroy(): void;
|
|
16
16
|
}
|
|
17
17
|
export { CodeViewer };
|
package/js/code-viewer.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { ListenerGroup } from './listeners.js';
|
|
1
2
|
class CodeViewer {
|
|
2
3
|
container;
|
|
3
4
|
code;
|
|
4
5
|
language;
|
|
6
|
+
listeners = new ListenerGroup();
|
|
5
7
|
constructor(elementOrSelector, code, language = 'javascript') {
|
|
6
|
-
const element = typeof elementOrSelector === 'string'
|
|
7
|
-
? document.querySelector(elementOrSelector)
|
|
8
|
-
: elementOrSelector;
|
|
8
|
+
const element = typeof elementOrSelector === 'string' ? document.querySelector(elementOrSelector) : elementOrSelector;
|
|
9
9
|
if (!element) {
|
|
10
10
|
throw new Error(`CodeViewer: Element not found for selector "${elementOrSelector}"`);
|
|
11
11
|
}
|
|
@@ -28,12 +28,7 @@ class CodeViewer {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
escape(str) {
|
|
31
|
-
return str
|
|
32
|
-
.replace(/&/g, '&')
|
|
33
|
-
.replace(/</g, '<')
|
|
34
|
-
.replace(/>/g, '>')
|
|
35
|
-
.replace(/"/g, '"')
|
|
36
|
-
.replace(/'/g, ''');
|
|
31
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
37
32
|
}
|
|
38
33
|
highlightJavaScript(code) {
|
|
39
34
|
const strings = [];
|
|
@@ -88,7 +83,6 @@ class CodeViewer {
|
|
|
88
83
|
return code;
|
|
89
84
|
}
|
|
90
85
|
highlightCSS(code) {
|
|
91
|
-
code = this.escape(code);
|
|
92
86
|
const comments = [];
|
|
93
87
|
code = code.replace(/(\/\*[\s\S]*?\*\/)/g, (match) => {
|
|
94
88
|
comments.push(match);
|
|
@@ -99,6 +93,7 @@ class CodeViewer {
|
|
|
99
93
|
strings.push(match);
|
|
100
94
|
return `###STRING${strings.length - 1}###`;
|
|
101
95
|
});
|
|
96
|
+
code = this.escape(code);
|
|
102
97
|
code = code.replace(/^([^{]+)(?={)/gm, (match) => {
|
|
103
98
|
return '<span class="selector">' + match.trim() + '</span>';
|
|
104
99
|
});
|
|
@@ -143,16 +138,10 @@ class CodeViewer {
|
|
|
143
138
|
</div>
|
|
144
139
|
`;
|
|
145
140
|
const copyButton = this.container.querySelector('.copy-button');
|
|
146
|
-
|
|
147
|
-
copyButton.addEventListener('click', this.handleCopy);
|
|
148
|
-
}
|
|
141
|
+
copyButton?.addEventListener('click', () => this.copyCode(), { signal: this.listeners.signal });
|
|
149
142
|
}
|
|
150
|
-
handleCopy = () => {
|
|
151
|
-
this.copyCode();
|
|
152
|
-
};
|
|
153
143
|
destroy() {
|
|
154
|
-
|
|
155
|
-
copyButton?.removeEventListener('click', this.handleCopy);
|
|
144
|
+
this.listeners.destroy();
|
|
156
145
|
}
|
|
157
146
|
}
|
|
158
147
|
export { CodeViewer };
|
package/js/color-picker.d.ts
CHANGED
|
@@ -23,8 +23,8 @@ declare class ColorPicker {
|
|
|
23
23
|
private saturation;
|
|
24
24
|
private brightness;
|
|
25
25
|
private isDragging;
|
|
26
|
-
private
|
|
27
|
-
private
|
|
26
|
+
private listeners;
|
|
27
|
+
private resizeObserver;
|
|
28
28
|
constructor(elementOrSelector: string | HTMLElement, options?: ColorPickerOptions);
|
|
29
29
|
private build;
|
|
30
30
|
private bindEvents;
|
package/js/color-picker.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ListenerGroup } from './listeners.js';
|
|
1
2
|
class ColorPicker {
|
|
2
3
|
container;
|
|
3
4
|
onChange;
|
|
@@ -14,20 +15,18 @@ class ColorPicker {
|
|
|
14
15
|
saturation = 100;
|
|
15
16
|
brightness = 100;
|
|
16
17
|
isDragging = false;
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
listeners = new ListenerGroup();
|
|
19
|
+
resizeObserver;
|
|
19
20
|
constructor(elementOrSelector, options = {}) {
|
|
20
|
-
const el = typeof elementOrSelector === 'string'
|
|
21
|
-
? document.querySelector(elementOrSelector)
|
|
22
|
-
: elementOrSelector;
|
|
21
|
+
const el = typeof elementOrSelector === 'string' ? document.querySelector(elementOrSelector) : elementOrSelector;
|
|
23
22
|
if (!el)
|
|
24
23
|
throw new Error(`ColorPicker: element not found for "${elementOrSelector}"`);
|
|
25
24
|
this.container = el;
|
|
26
25
|
this.onChange = options.onChange;
|
|
27
26
|
this.build();
|
|
28
27
|
this.bindEvents();
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
28
|
+
this.resizeObserver = new ResizeObserver(() => this.resizeCanvas());
|
|
29
|
+
this.resizeObserver.observe(this.canvas.parentElement);
|
|
31
30
|
this.resizeCanvas();
|
|
32
31
|
if (options.value) {
|
|
33
32
|
this.setValue(options.value);
|
|
@@ -83,7 +82,7 @@ class ColorPicker {
|
|
|
83
82
|
this.preview = this.container.querySelector('.color-picker__preview');
|
|
84
83
|
}
|
|
85
84
|
bindEvents() {
|
|
86
|
-
const sig = { signal: this.
|
|
85
|
+
const sig = { signal: this.listeners.signal };
|
|
87
86
|
this.canvas.addEventListener('pointerdown', (e) => {
|
|
88
87
|
e.preventDefault();
|
|
89
88
|
this.canvas.setPointerCapture(e.pointerId);
|
|
@@ -95,12 +94,11 @@ class ColorPicker {
|
|
|
95
94
|
return;
|
|
96
95
|
this.handleFieldInteraction(e);
|
|
97
96
|
}, sig);
|
|
98
|
-
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}, sig);
|
|
97
|
+
for (const type of ['pointerup', 'pointercancel']) {
|
|
98
|
+
this.canvas.addEventListener(type, () => {
|
|
99
|
+
this.isDragging = false;
|
|
100
|
+
}, sig);
|
|
101
|
+
}
|
|
104
102
|
this.hueSlider.addEventListener('input', () => {
|
|
105
103
|
this.hue = +this.hueSlider.value;
|
|
106
104
|
this.drawField();
|
|
@@ -144,13 +142,13 @@ class ColorPicker {
|
|
|
144
142
|
const y = Math.max(0, Math.min(e.clientY - rect.top, rect.height));
|
|
145
143
|
this.saturation = (x / rect.width) * 100;
|
|
146
144
|
this.brightness = 100 - (y / rect.height) * 100;
|
|
147
|
-
this.updateCursor();
|
|
145
|
+
this.updateCursor(rect);
|
|
148
146
|
this.updateFromHSB();
|
|
149
147
|
}
|
|
150
|
-
updateCursor() {
|
|
151
|
-
const
|
|
152
|
-
const x = (this.saturation / 100) *
|
|
153
|
-
const y = (1 - this.brightness / 100) *
|
|
148
|
+
updateCursor(rect) {
|
|
149
|
+
const r = rect ?? this.canvas.getBoundingClientRect();
|
|
150
|
+
const x = (this.saturation / 100) * r.width;
|
|
151
|
+
const y = (1 - this.brightness / 100) * r.height;
|
|
154
152
|
this.cursor.style.left = `${x}px`;
|
|
155
153
|
this.cursor.style.top = `${y}px`;
|
|
156
154
|
this.cursor.classList.toggle('color-picker__cursor--dark', this.brightness > 50 && this.saturation < 80);
|
|
@@ -207,8 +205,8 @@ class ColorPicker {
|
|
|
207
205
|
this.setFromRGB(this.hexToRgb(hex));
|
|
208
206
|
}
|
|
209
207
|
destroy() {
|
|
210
|
-
this.
|
|
211
|
-
this.
|
|
208
|
+
this.listeners.destroy();
|
|
209
|
+
this.resizeObserver.disconnect();
|
|
212
210
|
this.container.classList.remove('color-picker');
|
|
213
211
|
this.container.innerHTML = '';
|
|
214
212
|
}
|
|
@@ -281,7 +279,7 @@ class ColorPicker {
|
|
|
281
279
|
};
|
|
282
280
|
}
|
|
283
281
|
rgbToHex({ r, g, b }) {
|
|
284
|
-
return '#' + [r, g, b].map(c => c.toString(16).padStart(2, '0')).join('');
|
|
282
|
+
return '#' + [r, g, b].map((c) => c.toString(16).padStart(2, '0')).join('');
|
|
285
283
|
}
|
|
286
284
|
hexToRgb(hex) {
|
|
287
285
|
const m = hex.match(/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
|
package/js/context-menu.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ declare class ContextMenu {
|
|
|
18
18
|
private targets;
|
|
19
19
|
private menuEl;
|
|
20
20
|
private currentTarget;
|
|
21
|
-
private
|
|
21
|
+
private listeners;
|
|
22
22
|
private spritePath;
|
|
23
23
|
constructor(selectorOrElement: string | HTMLElement | HTMLElement[], items: ContextMenuInput[], options?: ContextMenuOptions);
|
|
24
24
|
private init;
|
package/js/context-menu.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { ListenerGroup } from './listeners.js';
|
|
1
2
|
class ContextMenu {
|
|
2
3
|
items;
|
|
3
4
|
targets;
|
|
4
5
|
menuEl = null;
|
|
5
6
|
currentTarget = null;
|
|
6
|
-
|
|
7
|
+
listeners = new ListenerGroup();
|
|
7
8
|
spritePath;
|
|
8
9
|
constructor(selectorOrElement, items, options = {}) {
|
|
9
10
|
this.items = items;
|
|
@@ -20,7 +21,7 @@ class ContextMenu {
|
|
|
20
21
|
this.init();
|
|
21
22
|
}
|
|
22
23
|
init() {
|
|
23
|
-
const { signal } = this.
|
|
24
|
+
const { signal } = this.listeners;
|
|
24
25
|
this.targets.forEach((target) => {
|
|
25
26
|
target.addEventListener('contextmenu', (e) => {
|
|
26
27
|
e.preventDefault();
|
|
@@ -40,15 +41,15 @@ class ContextMenu {
|
|
|
40
41
|
if (e.key === 'Escape') {
|
|
41
42
|
this.close();
|
|
42
43
|
}
|
|
43
|
-
if (e.key === 'ArrowDown') {
|
|
44
|
+
else if (e.key === 'ArrowDown') {
|
|
44
45
|
e.preventDefault();
|
|
45
46
|
this.moveFocus(1);
|
|
46
47
|
}
|
|
47
|
-
if (e.key === 'ArrowUp') {
|
|
48
|
+
else if (e.key === 'ArrowUp') {
|
|
48
49
|
e.preventDefault();
|
|
49
50
|
this.moveFocus(-1);
|
|
50
51
|
}
|
|
51
|
-
if (e.key === 'Enter') {
|
|
52
|
+
else if (e.key === 'Enter') {
|
|
52
53
|
e.preventDefault();
|
|
53
54
|
this.activateFocused();
|
|
54
55
|
}
|
|
@@ -187,26 +188,23 @@ class ContextMenu {
|
|
|
187
188
|
getFocusableItems() {
|
|
188
189
|
if (!this.menuEl)
|
|
189
190
|
return [];
|
|
190
|
-
return Array.from(this.menuEl.children).filter((el) => el.classList.contains('context-menu-item') &&
|
|
191
|
-
!el.classList.contains('is-disabled'));
|
|
191
|
+
return Array.from(this.menuEl.children).filter((el) => el.classList.contains('context-menu-item') && !el.classList.contains('is-disabled'));
|
|
192
192
|
}
|
|
193
193
|
moveFocus(direction) {
|
|
194
194
|
const items = this.getFocusableItems();
|
|
195
195
|
if (!items.length)
|
|
196
196
|
return;
|
|
197
197
|
const currentIndex = items.findIndex((el) => el.classList.contains('is-focused'));
|
|
198
|
-
const nextIndex = (currentIndex + direction + items.length) % items.length;
|
|
198
|
+
const nextIndex = currentIndex === -1 ? (direction === 1 ? 0 : items.length - 1) : (currentIndex + direction + items.length) % items.length;
|
|
199
199
|
items[currentIndex]?.classList.remove('is-focused');
|
|
200
200
|
items[nextIndex].classList.add('is-focused');
|
|
201
201
|
}
|
|
202
202
|
activateFocused() {
|
|
203
|
-
this.menuEl
|
|
204
|
-
?.querySelector('.context-menu-item.is-focused')
|
|
205
|
-
?.click();
|
|
203
|
+
this.menuEl?.querySelector('.context-menu-item.is-focused')?.click();
|
|
206
204
|
}
|
|
207
205
|
destroy() {
|
|
208
206
|
this.close();
|
|
209
|
-
this.
|
|
207
|
+
this.listeners.destroy();
|
|
210
208
|
}
|
|
211
209
|
}
|
|
212
210
|
export { ContextMenu };
|
package/js/datepicker.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ interface DateRange {
|
|
|
15
15
|
end: Date | null;
|
|
16
16
|
}
|
|
17
17
|
declare class DatePicker {
|
|
18
|
+
private static readonly CLOCK_OUTER_RADIUS_PERCENT;
|
|
19
|
+
private static readonly CLOCK_INNER_RADIUS_PERCENT;
|
|
18
20
|
private input;
|
|
19
21
|
private options;
|
|
20
22
|
private currentDate;
|
|
@@ -29,8 +31,10 @@ declare class DatePicker {
|
|
|
29
31
|
private selectedMinutes;
|
|
30
32
|
private calendar;
|
|
31
33
|
private backdrop;
|
|
32
|
-
private
|
|
33
|
-
private
|
|
34
|
+
private clockMode;
|
|
35
|
+
private listeners;
|
|
36
|
+
private showListeners;
|
|
37
|
+
private clockListeners;
|
|
34
38
|
constructor(elementOrSelector: string | HTMLInputElement, options?: DatePickerOptions);
|
|
35
39
|
private init;
|
|
36
40
|
private createCalendarElement;
|
|
@@ -38,13 +42,20 @@ declare class DatePicker {
|
|
|
38
42
|
private show;
|
|
39
43
|
private hide;
|
|
40
44
|
private render;
|
|
45
|
+
private renderTimePicker;
|
|
41
46
|
private createHeader;
|
|
42
47
|
private navigate;
|
|
43
48
|
private createMonthGrid;
|
|
44
49
|
private createYearGrid;
|
|
45
50
|
private createGrid;
|
|
46
51
|
private createTimePicker;
|
|
47
|
-
private
|
|
52
|
+
private createClockHeader;
|
|
53
|
+
private createClockFace;
|
|
54
|
+
private createClockNumber;
|
|
55
|
+
private clockPosition;
|
|
56
|
+
private positionHand;
|
|
57
|
+
private bindClockDrag;
|
|
58
|
+
private selectClockValue;
|
|
48
59
|
private applyTimeToSelection;
|
|
49
60
|
private changeMonth;
|
|
50
61
|
private handleDateClick;
|