@expressivecss/expressive 0.13.1 → 0.14.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/CHANGELOG.md +109 -1
- package/README.md +2 -1
- package/dist/css/expressive.css +234 -72
- package/dist/css/expressive.css.map +1 -1
- package/dist/css/expressive.min.css +1 -1
- package/dist/css/expressive.min.css.map +1 -1
- package/dist/js/chunks/{chunk-55IA2XUC.mjs → chunk-3GVFZ4XO.mjs} +3 -3
- package/dist/js/chunks/{chunk-3CLXLPYS.mjs → chunk-4HZMB7LI.mjs} +22 -8
- package/dist/js/chunks/chunk-4HZMB7LI.mjs.map +7 -0
- package/dist/js/chunks/{chunk-DTKR54I6.mjs → chunk-4KMNFIFZ.mjs} +2 -2
- package/dist/js/chunks/{chunk-K4CJCRGE.mjs → chunk-4TKTLGEM.mjs} +2 -2
- package/dist/js/chunks/{chunk-3VOK6J7U.mjs → chunk-5BKHWHYY.mjs} +13 -6
- package/dist/js/chunks/chunk-5BKHWHYY.mjs.map +7 -0
- package/dist/js/chunks/{chunk-PLYXLSH3.mjs → chunk-5HQSGDZ5.mjs} +18 -9
- package/dist/js/chunks/chunk-5HQSGDZ5.mjs.map +7 -0
- package/dist/js/chunks/{chunk-LWBQIX5J.mjs → chunk-A7ALMYUR.mjs} +41 -44
- package/dist/js/chunks/chunk-A7ALMYUR.mjs.map +7 -0
- package/dist/js/chunks/chunk-BG6ZRB5H.mjs +154 -0
- package/dist/js/chunks/chunk-BG6ZRB5H.mjs.map +7 -0
- package/dist/js/chunks/{chunk-DLWYKFEI.mjs → chunk-CUQPB25U.mjs} +3 -3
- package/dist/js/chunks/{chunk-6WLSDZ4O.mjs → chunk-DAIU5SLG.mjs} +2 -2
- package/dist/js/chunks/{chunk-VTLBW7QS.mjs → chunk-FS7XY3HT.mjs} +2 -2
- package/dist/js/chunks/{chunk-WJXDBPXQ.mjs → chunk-GIW4K4SE.mjs} +8 -12
- package/dist/js/chunks/chunk-GIW4K4SE.mjs.map +7 -0
- package/dist/js/chunks/{chunk-LNCCYGPC.mjs → chunk-GUB3TNO2.mjs} +6 -5
- package/dist/js/chunks/chunk-GUB3TNO2.mjs.map +7 -0
- package/dist/js/chunks/{chunk-XH6BEEMY.mjs → chunk-GZKEFWPM.mjs} +39 -31
- package/dist/js/chunks/chunk-GZKEFWPM.mjs.map +7 -0
- package/dist/js/chunks/{chunk-QKWPQK5N.mjs → chunk-ILP3PDTL.mjs} +11 -3
- package/dist/js/chunks/chunk-ILP3PDTL.mjs.map +7 -0
- package/dist/js/chunks/{chunk-U2OTHOTI.mjs → chunk-JIDMQGK6.mjs} +3 -2
- package/dist/js/chunks/{chunk-U2OTHOTI.mjs.map → chunk-JIDMQGK6.mjs.map} +2 -2
- package/dist/js/chunks/chunk-KBNN3QDH.mjs +7 -0
- package/dist/js/chunks/{chunk-4PWAPV6F.mjs.map → chunk-KBNN3QDH.mjs.map} +1 -1
- package/dist/js/chunks/{chunk-NNYP33NB.mjs → chunk-KHV6DZXX.mjs} +5 -4
- package/dist/js/chunks/chunk-KHV6DZXX.mjs.map +7 -0
- package/dist/js/chunks/{chunk-XGHORT7J.mjs → chunk-KY6U46SM.mjs} +3 -3
- package/dist/js/chunks/{chunk-CKQP6P76.mjs → chunk-LRZMJZ3T.mjs} +4 -3
- package/dist/js/chunks/chunk-LRZMJZ3T.mjs.map +7 -0
- package/dist/js/chunks/{chunk-6OMRGML6.mjs → chunk-MNPROCZF.mjs} +4 -4
- package/dist/js/chunks/{chunk-6OMRGML6.mjs.map → chunk-MNPROCZF.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-QV2JAWIZ.mjs → chunk-MZ6Z24BX.mjs} +3 -2
- package/dist/js/chunks/{chunk-QV2JAWIZ.mjs.map → chunk-MZ6Z24BX.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-CCWDV5CR.mjs → chunk-NS2UMNZV.mjs} +2 -2
- package/dist/js/chunks/{chunk-UBLRRJ7N.mjs → chunk-PM655FXL.mjs} +2 -2
- package/dist/js/chunks/{chunk-IFXVDDDH.mjs → chunk-QERLECVU.mjs} +3 -3
- package/dist/js/chunks/{chunk-GZWPXXY6.mjs → chunk-QJABDLSD.mjs} +5 -2
- package/dist/js/chunks/chunk-QJABDLSD.mjs.map +7 -0
- package/dist/js/chunks/{chunk-UNEMYWEW.mjs → chunk-S3XDFGSZ.mjs} +2 -2
- package/dist/js/chunks/chunk-TBM3FT7G.mjs +398 -0
- package/dist/js/chunks/chunk-TBM3FT7G.mjs.map +7 -0
- package/dist/js/chunks/chunk-UEXCIMJZ.mjs +214 -0
- package/dist/js/chunks/chunk-UEXCIMJZ.mjs.map +7 -0
- package/dist/js/chunks/{chunk-P3G3QHII.mjs → chunk-VGZSAFTX.mjs} +11 -4
- package/dist/js/chunks/{chunk-P3G3QHII.mjs.map → chunk-VGZSAFTX.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-UAEAQBRC.mjs → chunk-X7OCHZVF.mjs} +2 -2
- package/dist/js/chunks/{chunk-EC63CHXU.mjs → chunk-YMSXJON6.mjs} +7 -6
- package/dist/js/chunks/chunk-YMSXJON6.mjs.map +7 -0
- package/dist/js/chunks/{chunk-QVVEWBOF.mjs → chunk-Z2NRKI7R.mjs} +2 -2
- package/dist/js/chunks/{chunk-PIJ2TAR3.mjs → chunk-ZAS25YFD.mjs} +2 -2
- package/dist/js/chunks/chunk-ZKZKNSLC.mjs +1 -0
- package/dist/js/expressive.cjs +905 -117
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +905 -117
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +10 -10
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +57 -45
- package/dist/js/expressive.mjs.map +1 -1
- package/dist/js/internal/behaviors/bottomSheets.mjs +3 -3
- package/dist/js/internal/behaviors/dialogs.mjs +2 -2
- package/dist/js/internal/behaviors/forms.mjs +2 -2
- package/dist/js/internal/behaviors/sheetDrag.mjs +2 -2
- package/dist/js/internal/behaviors/sideSheets.mjs +3 -3
- package/dist/js/internal/components/autocomplete.mjs +3 -3
- package/dist/js/internal/components/buttons.mjs +2 -2
- package/dist/js/internal/components/cards.mjs +2 -2
- package/dist/js/internal/components/carousel.mjs +2 -2
- package/dist/js/internal/components/chips.mjs +4 -4
- package/dist/js/internal/components/commandPalette.mjs +2 -2
- package/dist/js/internal/components/confetti.mjs +8 -0
- package/dist/js/internal/components/confetti.mjs.map +7 -0
- package/dist/js/internal/components/datepicker.mjs +5 -5
- package/dist/js/internal/components/expandingCard.mjs +2 -2
- package/dist/js/internal/components/heatmapChart.mjs +1 -1
- package/dist/js/internal/components/index.mjs +50 -38
- package/dist/js/internal/components/lightbox.mjs +2 -2
- package/dist/js/internal/components/mapView.mjs +9 -0
- package/dist/js/internal/components/mapView.mjs.map +7 -0
- package/dist/js/internal/components/menu.mjs +2 -2
- package/dist/js/internal/components/messageScroller.mjs +2 -2
- package/dist/js/internal/components/particles.mjs +8 -0
- package/dist/js/internal/components/particles.mjs.map +7 -0
- package/dist/js/internal/components/pieChart.mjs +1 -1
- package/dist/js/internal/components/questionnaire.mjs +2 -2
- package/dist/js/internal/components/registry.mjs +31 -28
- package/dist/js/internal/components/richTextEditor.mjs +2 -2
- package/dist/js/internal/components/scrollspy.mjs +1 -1
- package/dist/js/internal/components/select.mjs +3 -3
- package/dist/js/internal/components/slider.mjs +2 -2
- package/dist/js/internal/components/snackbar.mjs +2 -2
- package/dist/js/internal/components/tabs.mjs +3 -3
- package/dist/js/internal/components/timepicker.mjs +3 -3
- package/dist/js/internal/components/tooltip.mjs +2 -2
- package/dist/js/internal/core/utils.mjs +1 -1
- package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
- package/dist/js/modular.mjs +57 -45
- package/dist/types/behaviors/forms.d.ts +5 -0
- package/dist/types/components/carousel.d.ts +2 -0
- package/dist/types/components/confetti.d.ts +103 -0
- package/dist/types/components/datepicker.d.ts +2 -0
- package/dist/types/components/index.d.ts +3 -0
- package/dist/types/components/mapView.d.ts +151 -0
- package/dist/types/components/particles.d.ts +72 -0
- package/dist/types/components/pieChart.d.ts +3 -0
- package/dist/types/components/registry.d.ts +8 -0
- package/dist/types/components/slider.d.ts +1 -1
- package/dist/types/components/snackbar.d.ts +2 -0
- package/dist/types/components/tabs.d.ts +1 -1
- package/dist/types/modular.d.ts +1 -1
- package/dist/types/plugins/dockedDisplayPlugin.d.ts +3 -3
- package/package.json +2 -1
- package/src/sass/components/_buttons.scss +1 -1
- package/src/sass/components/_confetti.scss +14 -0
- package/src/sass/components/_index.scss +3 -0
- package/src/sass/components/_map.scss +188 -0
- package/src/sass/components/_particles.scss +14 -0
- package/src/sass/components/_table_of_contents.scss +3 -1
- package/src/sass/components/forms/_checkboxes.scss +7 -2
- package/dist/js/chunks/chunk-3CLXLPYS.mjs.map +0 -7
- package/dist/js/chunks/chunk-3VOK6J7U.mjs.map +0 -7
- package/dist/js/chunks/chunk-4PWAPV6F.mjs +0 -7
- package/dist/js/chunks/chunk-CKQP6P76.mjs.map +0 -7
- package/dist/js/chunks/chunk-EC63CHXU.mjs.map +0 -7
- package/dist/js/chunks/chunk-GZWPXXY6.mjs.map +0 -7
- package/dist/js/chunks/chunk-LNCCYGPC.mjs.map +0 -7
- package/dist/js/chunks/chunk-LWBQIX5J.mjs.map +0 -7
- package/dist/js/chunks/chunk-NNYP33NB.mjs.map +0 -7
- package/dist/js/chunks/chunk-NQLC3YMW.mjs +0 -1
- package/dist/js/chunks/chunk-PLYXLSH3.mjs.map +0 -7
- package/dist/js/chunks/chunk-QKWPQK5N.mjs.map +0 -7
- package/dist/js/chunks/chunk-WJXDBPXQ.mjs.map +0 -7
- package/dist/js/chunks/chunk-XH6BEEMY.mjs.map +0 -7
- /package/dist/js/chunks/{chunk-55IA2XUC.mjs.map → chunk-3GVFZ4XO.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-DTKR54I6.mjs.map → chunk-4KMNFIFZ.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-K4CJCRGE.mjs.map → chunk-4TKTLGEM.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-DLWYKFEI.mjs.map → chunk-CUQPB25U.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-6WLSDZ4O.mjs.map → chunk-DAIU5SLG.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-VTLBW7QS.mjs.map → chunk-FS7XY3HT.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-XGHORT7J.mjs.map → chunk-KY6U46SM.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-CCWDV5CR.mjs.map → chunk-NS2UMNZV.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-UBLRRJ7N.mjs.map → chunk-PM655FXL.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-IFXVDDDH.mjs.map → chunk-QERLECVU.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-UNEMYWEW.mjs.map → chunk-S3XDFGSZ.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-UAEAQBRC.mjs.map → chunk-X7OCHZVF.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-QVVEWBOF.mjs.map → chunk-Z2NRKI7R.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-PIJ2TAR3.mjs.map → chunk-ZAS25YFD.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-NQLC3YMW.mjs.map → chunk-ZKZKNSLC.mjs.map} +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component
|
|
3
|
+
} from "./chunk-LTWPGFBR.mjs";
|
|
4
|
+
|
|
5
|
+
// src/ts/components/confetti.ts
|
|
6
|
+
var _defaults = {
|
|
7
|
+
particleCount: 50,
|
|
8
|
+
angle: 90,
|
|
9
|
+
spread: 45,
|
|
10
|
+
startVelocity: 45,
|
|
11
|
+
decay: 0.9,
|
|
12
|
+
gravity: 1,
|
|
13
|
+
drift: 0,
|
|
14
|
+
ticks: 200,
|
|
15
|
+
origin: { x: 0.5, y: 0.5 },
|
|
16
|
+
colors: [],
|
|
17
|
+
shapes: ["square", "circle"],
|
|
18
|
+
scalar: 1,
|
|
19
|
+
manualStart: false
|
|
20
|
+
};
|
|
21
|
+
var THEME_COLORS = ["primary", "secondary", "tertiary", "primary-container", "secondary-container", "tertiary-container"];
|
|
22
|
+
var FALLBACK_COLORS = ["#26ccff", "#a25afd", "#ff5e7e", "#88ff5a", "#fcff42", "#ffa62d", "#ff36ff"];
|
|
23
|
+
var RAD = Math.PI / 180;
|
|
24
|
+
var scenes = /* @__PURE__ */ new Map();
|
|
25
|
+
var overlay = null;
|
|
26
|
+
var Confetti = class _Confetti extends Component {
|
|
27
|
+
constructor(el, options) {
|
|
28
|
+
super(el, options, _Confetti);
|
|
29
|
+
this._onClick = () => {
|
|
30
|
+
this.fire();
|
|
31
|
+
};
|
|
32
|
+
this.el["Expressive_Confetti"] = this;
|
|
33
|
+
this.options = { ..._Confetti.defaults, ...options };
|
|
34
|
+
if (!(el instanceof HTMLCanvasElement)) el.addEventListener("click", this._onClick);
|
|
35
|
+
else if (!this.options.manualStart) this.fire();
|
|
36
|
+
}
|
|
37
|
+
static get defaults() {
|
|
38
|
+
return _defaults;
|
|
39
|
+
}
|
|
40
|
+
static init(els, options = {}) {
|
|
41
|
+
return super.init(els, options, _Confetti);
|
|
42
|
+
}
|
|
43
|
+
static getInstance(el) {
|
|
44
|
+
return el["Expressive_Confetti"];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Bursts over the whole viewport. Resolves when the last piece is gone.
|
|
48
|
+
*/
|
|
49
|
+
static fire(options = {}) {
|
|
50
|
+
return burst(viewportCanvas, document.body, { ..._Confetti.defaults, ...options });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Bursts on this canvas, or from this element's center over the viewport.
|
|
54
|
+
* Resolves when the last piece is gone.
|
|
55
|
+
*/
|
|
56
|
+
fire(options = {}) {
|
|
57
|
+
const merged = { ...this.options, ...options };
|
|
58
|
+
if (this.el instanceof HTMLCanvasElement) {
|
|
59
|
+
const canvas = this.el;
|
|
60
|
+
return burst(() => canvas, canvas.parentElement ?? document.body, merged);
|
|
61
|
+
}
|
|
62
|
+
const r = this.el.getBoundingClientRect();
|
|
63
|
+
merged.origin = { x: (r.left + r.width / 2) / innerWidth, y: (r.top + r.height / 2) / innerHeight };
|
|
64
|
+
return burst(viewportCanvas, this.el.parentElement ?? document.body, merged);
|
|
65
|
+
}
|
|
66
|
+
destroy() {
|
|
67
|
+
this.el.removeEventListener("click", this._onClick);
|
|
68
|
+
if (this.el instanceof HTMLCanvasElement) stop(this.el);
|
|
69
|
+
this.el["Expressive_Confetti"] = void 0;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
function burst(getCanvas, themed, o) {
|
|
73
|
+
if (typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches) return Promise.resolve();
|
|
74
|
+
const canvas = getCanvas();
|
|
75
|
+
let scene = scenes.get(canvas);
|
|
76
|
+
if (!scene) {
|
|
77
|
+
const ctx = canvas.getContext("2d");
|
|
78
|
+
if (!ctx) return Promise.resolve();
|
|
79
|
+
scene = { ctx, pieces: [], frame: 0, last: 0, done: [], overlay: canvas === overlay };
|
|
80
|
+
scenes.set(canvas, scene);
|
|
81
|
+
}
|
|
82
|
+
const { width, height } = fit(canvas);
|
|
83
|
+
const colors = o.colors.length ? o.colors : themeColors(themed);
|
|
84
|
+
const x = (o.origin.x ?? 0.5) * width;
|
|
85
|
+
const y = (o.origin.y ?? 0.5) * height;
|
|
86
|
+
for (let i = 0; i < o.particleCount; i++) {
|
|
87
|
+
scene.pieces.push({
|
|
88
|
+
x,
|
|
89
|
+
y,
|
|
90
|
+
velocity: o.startVelocity * (0.5 + Math.random()),
|
|
91
|
+
angle: -o.angle * RAD + (0.5 - Math.random()) * o.spread * RAD,
|
|
92
|
+
wobble: Math.random() * 10,
|
|
93
|
+
wobbleSpeed: 0.05 + Math.random() * 0.05,
|
|
94
|
+
tilt: (0.25 + Math.random() / 2) * Math.PI,
|
|
95
|
+
tick: 0,
|
|
96
|
+
color: colors[i % colors.length],
|
|
97
|
+
shape: o.shapes[Math.floor(Math.random() * o.shapes.length)] ?? "square",
|
|
98
|
+
options: o
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const s = scene;
|
|
102
|
+
if (!s.frame) s.frame = requestAnimationFrame((now) => {
|
|
103
|
+
s.last = now;
|
|
104
|
+
draw(canvas, s, now);
|
|
105
|
+
});
|
|
106
|
+
return new Promise((resolve) => s.done.push(resolve));
|
|
107
|
+
}
|
|
108
|
+
function draw(canvas, scene, now) {
|
|
109
|
+
const step = Math.min((now - scene.last) / (1e3 / 60), 4);
|
|
110
|
+
scene.last = now;
|
|
111
|
+
const { width, height } = fit(canvas);
|
|
112
|
+
const { ctx } = scene;
|
|
113
|
+
const dpr = canvas.width / (width || 1);
|
|
114
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
115
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
116
|
+
scene.pieces = scene.pieces.filter((p) => {
|
|
117
|
+
const o = p.options;
|
|
118
|
+
p.x += (Math.cos(p.angle) * p.velocity + o.drift) * step;
|
|
119
|
+
p.y += (Math.sin(p.angle) * p.velocity + o.gravity * 3) * step;
|
|
120
|
+
p.velocity *= o.decay ** step;
|
|
121
|
+
p.wobble += p.wobbleSpeed * step;
|
|
122
|
+
p.tilt += 0.1 * step;
|
|
123
|
+
p.tick += step;
|
|
124
|
+
if (p.tick >= o.ticks) return false;
|
|
125
|
+
const size = 8 * o.scalar;
|
|
126
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
127
|
+
ctx.translate(p.x + 10 * o.scalar * Math.cos(p.wobble), p.y + 10 * o.scalar * Math.sin(p.wobble));
|
|
128
|
+
ctx.rotate(p.tilt);
|
|
129
|
+
ctx.scale(1, Math.cos(p.wobble));
|
|
130
|
+
ctx.globalAlpha = 1 - p.tick / o.ticks;
|
|
131
|
+
ctx.fillStyle = p.color;
|
|
132
|
+
ctx.beginPath();
|
|
133
|
+
if (p.shape === "circle") ctx.arc(0, 0, size / 2, 0, 2 * Math.PI);
|
|
134
|
+
else if (p.shape === "star") star(ctx, size * 0.75);
|
|
135
|
+
else ctx.rect(-size / 2, -size / 2, size, size);
|
|
136
|
+
ctx.fill();
|
|
137
|
+
return true;
|
|
138
|
+
});
|
|
139
|
+
if (scene.pieces.length) scene.frame = requestAnimationFrame((t) => draw(canvas, scene, t));
|
|
140
|
+
else stop(canvas);
|
|
141
|
+
}
|
|
142
|
+
function stop(canvas) {
|
|
143
|
+
const scene = scenes.get(canvas);
|
|
144
|
+
if (!scene) return;
|
|
145
|
+
cancelAnimationFrame(scene.frame);
|
|
146
|
+
scenes.delete(canvas);
|
|
147
|
+
scene.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
148
|
+
scene.ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
149
|
+
if (scene.overlay) {
|
|
150
|
+
canvas.remove();
|
|
151
|
+
overlay = null;
|
|
152
|
+
}
|
|
153
|
+
for (const resolve of scene.done) resolve();
|
|
154
|
+
}
|
|
155
|
+
function star(ctx, r) {
|
|
156
|
+
for (let i = 0; i < 10; i++) {
|
|
157
|
+
const a = i * Math.PI / 5 - Math.PI / 2;
|
|
158
|
+
const d = i % 2 ? r / 2 : r;
|
|
159
|
+
ctx.lineTo(Math.cos(a) * d, Math.sin(a) * d);
|
|
160
|
+
}
|
|
161
|
+
ctx.closePath();
|
|
162
|
+
}
|
|
163
|
+
function fit(canvas) {
|
|
164
|
+
const width = canvas.clientWidth;
|
|
165
|
+
const height = canvas.clientHeight;
|
|
166
|
+
const w = Math.round(width * devicePixelRatio);
|
|
167
|
+
const h = Math.round(height * devicePixelRatio);
|
|
168
|
+
if (canvas.width !== w || canvas.height !== h) {
|
|
169
|
+
canvas.width = w;
|
|
170
|
+
canvas.height = h;
|
|
171
|
+
}
|
|
172
|
+
return { width, height };
|
|
173
|
+
}
|
|
174
|
+
function viewportCanvas() {
|
|
175
|
+
if (overlay?.isConnected) return overlay;
|
|
176
|
+
overlay = document.createElement("canvas");
|
|
177
|
+
overlay.className = "confetti-overlay";
|
|
178
|
+
overlay.setAttribute("aria-hidden", "true");
|
|
179
|
+
Object.assign(overlay.style, {
|
|
180
|
+
position: "fixed",
|
|
181
|
+
inset: "0",
|
|
182
|
+
width: "100%",
|
|
183
|
+
height: "100%",
|
|
184
|
+
margin: "0",
|
|
185
|
+
padding: "0",
|
|
186
|
+
border: "0",
|
|
187
|
+
background: "transparent",
|
|
188
|
+
pointerEvents: "none",
|
|
189
|
+
zIndex: "10001"
|
|
190
|
+
});
|
|
191
|
+
document.body.append(overlay);
|
|
192
|
+
if (typeof overlay.showPopover === "function") {
|
|
193
|
+
overlay.popover = "manual";
|
|
194
|
+
overlay.showPopover();
|
|
195
|
+
}
|
|
196
|
+
return overlay;
|
|
197
|
+
}
|
|
198
|
+
function themeColors(themed) {
|
|
199
|
+
const probe = document.createElement("span");
|
|
200
|
+
probe.hidden = true;
|
|
201
|
+
themed.append(probe);
|
|
202
|
+
const style = getComputedStyle(probe);
|
|
203
|
+
const colors = THEME_COLORS.filter((role) => style.getPropertyValue(`--md-sys-color-${role}`).trim()).map((role) => {
|
|
204
|
+
probe.style.color = `var(--md-sys-color-${role})`;
|
|
205
|
+
return getComputedStyle(probe).color;
|
|
206
|
+
});
|
|
207
|
+
probe.remove();
|
|
208
|
+
return colors.length ? colors : FALLBACK_COLORS;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export {
|
|
212
|
+
Confetti
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=chunk-UEXCIMJZ.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/confetti.ts"],
|
|
4
|
+
"sourcesContent": ["import { Component, BaseOptions, InitElements, InitElement } from '../core/component';\n\nexport type ConfettiShape = 'square' | 'circle' | 'star';\n\nexport interface ConfettiOptions extends BaseOptions {\n /**\n * Pieces per burst.\n * @default 50\n */\n particleCount: number;\n /**\n * Launch direction in degrees. 90 is straight up, 0 is right.\n * @default 90\n */\n angle: number;\n /**\n * How far the pieces fan out from the angle, in degrees.\n * @default 45\n */\n spread: number;\n /**\n * Launch speed in pixels per frame.\n * @default 45\n */\n startVelocity: number;\n /**\n * Share of its speed a piece keeps each frame.\n * @default 0.9\n */\n decay: number;\n /**\n * Pull toward the bottom. 0 floats, 1 is normal.\n * @default 1\n */\n gravity: number;\n /**\n * Sideways push per frame. Negative drifts left.\n * @default 0\n */\n drift: number;\n /**\n * Frames a piece lives while it fades out.\n * @default 200\n */\n ticks: number;\n /**\n * Launch point as fractions of the canvas, 0 to 1. A missing side is\n * 0.5. A trigger element ignores it and launches from its own center.\n * @default { x: 0.5, y: 0.5 }\n */\n origin: { x?: number; y?: number };\n /**\n * CSS colors. Empty uses the theme's primary, secondary and tertiary\n * colors and their containers.\n * @default []\n */\n colors: string[];\n /**\n * @default ['square', 'circle']\n */\n shapes: ConfettiShape[];\n /**\n * Piece size multiplier.\n * @default 1\n */\n scalar: number;\n /**\n * On a canvas, wait for `fire()` instead of bursting once at init.\n * @default false\n */\n manualStart: boolean;\n}\n\nconst _defaults: ConfettiOptions = {\n particleCount: 50,\n angle: 90,\n spread: 45,\n startVelocity: 45,\n decay: 0.9,\n gravity: 1,\n drift: 0,\n ticks: 200,\n origin: { x: 0.5, y: 0.5 },\n colors: [],\n shapes: ['square', 'circle'],\n scalar: 1,\n manualStart: false\n};\n\nconst THEME_COLORS = ['primary', 'secondary', 'tertiary', 'primary-container', 'secondary-container', 'tertiary-container'];\n// Used when the page has no theme tokens.\nconst FALLBACK_COLORS = ['#26ccff', '#a25afd', '#ff5e7e', '#88ff5a', '#fcff42', '#ffa62d', '#ff36ff'];\nconst RAD = Math.PI / 180;\n\ninterface Piece {\n x: number;\n y: number;\n velocity: number;\n angle: number;\n wobble: number;\n wobbleSpeed: number;\n tilt: number;\n tick: number;\n color: string;\n shape: ConfettiShape;\n options: ConfettiOptions;\n}\n\ninterface Scene {\n ctx: CanvasRenderingContext2D;\n pieces: Piece[];\n frame: number;\n last: number;\n done: (() => void)[];\n overlay: boolean;\n}\n\nconst scenes = new Map<HTMLCanvasElement, Scene>();\nlet overlay: HTMLCanvasElement | null = null;\n\n/**\n * Confetti. Bursts of theme-colored pieces drawn on a canvas.\n *\n * - `Confetti.fire(options)` bursts over the whole viewport.\n * - Any other `.confetti` element bursts from its center when clicked.\n * - A `<canvas class=\"confetti\">` bursts inside its own box, once at init\n * unless `manualStart`, and again on each `fire()`.\n *\n * The viewport canvas is a manual popover, so it draws above an open modal\n * dialog, and it ignores the pointer. Nothing is drawn when the reader\n * prefers reduced motion.\n */\nexport class Confetti extends Component<ConfettiOptions> {\n private _onClick = () => { this.fire(); };\n\n constructor(el: HTMLElement, options: Partial<ConfettiOptions>) {\n super(el, options, Confetti);\n this.el['Expressive_Confetti'] = this;\n this.options = { ...Confetti.defaults, ...options };\n if (!(el instanceof HTMLCanvasElement)) el.addEventListener('click', this._onClick);\n else if (!this.options.manualStart) this.fire();\n }\n\n static get defaults(): ConfettiOptions {\n return _defaults;\n }\n\n static init(el: HTMLElement, options?: Partial<ConfettiOptions>): Confetti;\n static init(els: InitElements<InitElement>, options?: Partial<ConfettiOptions>): Confetti[];\n static init(\n els: HTMLElement | InitElements<InitElement>,\n options: Partial<ConfettiOptions> = {}\n ): Confetti | Confetti[] {\n return super.init(els, options, Confetti);\n }\n\n static getInstance(el: HTMLElement): Confetti {\n return el['Expressive_Confetti'];\n }\n\n /**\n * Bursts over the whole viewport. Resolves when the last piece is gone.\n */\n static fire(options: Partial<ConfettiOptions> = {}): Promise<void> {\n return burst(viewportCanvas, document.body, { ...Confetti.defaults, ...options });\n }\n\n /**\n * Bursts on this canvas, or from this element's center over the viewport.\n * Resolves when the last piece is gone.\n */\n fire(options: Partial<ConfettiOptions> = {}): Promise<void> {\n const merged = { ...this.options, ...options };\n if (this.el instanceof HTMLCanvasElement) {\n const canvas = this.el;\n return burst(() => canvas, canvas.parentElement ?? document.body, merged);\n }\n const r = this.el.getBoundingClientRect();\n merged.origin = { x: (r.left + r.width / 2) / innerWidth, y: (r.top + r.height / 2) / innerHeight };\n return burst(viewportCanvas, this.el.parentElement ?? document.body, merged);\n }\n\n destroy() {\n this.el.removeEventListener('click', this._onClick);\n if (this.el instanceof HTMLCanvasElement) stop(this.el);\n this.el['Expressive_Confetti'] = undefined;\n }\n}\n\n// `themed` is where the theme colors are read, so a scoped theme applies.\nfunction burst(getCanvas: () => HTMLCanvasElement, themed: Element, o: ConfettiOptions): Promise<void> {\n if (typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches) return Promise.resolve();\n const canvas = getCanvas();\n let scene = scenes.get(canvas);\n if (!scene) {\n const ctx = canvas.getContext('2d');\n if (!ctx) return Promise.resolve();\n scene = { ctx, pieces: [], frame: 0, last: 0, done: [], overlay: canvas === overlay };\n scenes.set(canvas, scene);\n }\n const { width, height } = fit(canvas);\n const colors = o.colors.length ? o.colors : themeColors(themed);\n const x = (o.origin.x ?? 0.5) * width;\n const y = (o.origin.y ?? 0.5) * height;\n for (let i = 0; i < o.particleCount; i++) {\n scene.pieces.push({\n x, y,\n velocity: o.startVelocity * (0.5 + Math.random()),\n angle: -o.angle * RAD + (0.5 - Math.random()) * o.spread * RAD,\n wobble: Math.random() * 10,\n wobbleSpeed: 0.05 + Math.random() * 0.05,\n tilt: (0.25 + Math.random() / 2) * Math.PI,\n tick: 0,\n color: colors[i % colors.length],\n shape: o.shapes[Math.floor(Math.random() * o.shapes.length)] ?? 'square',\n options: o\n });\n }\n const s = scene;\n if (!s.frame) s.frame = requestAnimationFrame((now) => { s.last = now; draw(canvas, s, now); });\n return new Promise((resolve) => s.done.push(resolve));\n}\n\nfunction draw(canvas: HTMLCanvasElement, scene: Scene, now: number) {\n // Frames are counted at 60 per second whatever the display rate.\n const step = Math.min((now - scene.last) / (1000 / 60), 4);\n scene.last = now;\n const { width, height } = fit(canvas);\n const { ctx } = scene;\n const dpr = canvas.width / (width || 1);\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n scene.pieces = scene.pieces.filter((p) => {\n const o = p.options;\n p.x += (Math.cos(p.angle) * p.velocity + o.drift) * step;\n p.y += (Math.sin(p.angle) * p.velocity + o.gravity * 3) * step;\n p.velocity *= o.decay ** step;\n p.wobble += p.wobbleSpeed * step;\n p.tilt += 0.1 * step;\n p.tick += step;\n if (p.tick >= o.ticks) return false;\n const size = 8 * o.scalar;\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.translate(p.x + 10 * o.scalar * Math.cos(p.wobble), p.y + 10 * o.scalar * Math.sin(p.wobble));\n ctx.rotate(p.tilt);\n ctx.scale(1, Math.cos(p.wobble));\n ctx.globalAlpha = 1 - p.tick / o.ticks;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n if (p.shape === 'circle') ctx.arc(0, 0, size / 2, 0, 2 * Math.PI);\n else if (p.shape === 'star') star(ctx, size * 0.75);\n else ctx.rect(-size / 2, -size / 2, size, size);\n ctx.fill();\n return true;\n });\n if (scene.pieces.length) scene.frame = requestAnimationFrame((t) => draw(canvas, scene, t));\n else stop(canvas);\n}\n\nfunction stop(canvas: HTMLCanvasElement) {\n const scene = scenes.get(canvas);\n if (!scene) return;\n cancelAnimationFrame(scene.frame);\n scenes.delete(canvas);\n scene.ctx.setTransform(1, 0, 0, 1, 0, 0);\n scene.ctx.clearRect(0, 0, canvas.width, canvas.height);\n if (scene.overlay) {\n canvas.remove();\n overlay = null;\n }\n for (const resolve of scene.done) resolve();\n}\n\nfunction star(ctx: CanvasRenderingContext2D, r: number) {\n for (let i = 0; i < 10; i++) {\n const a = (i * Math.PI) / 5 - Math.PI / 2;\n const d = i % 2 ? r / 2 : r;\n ctx.lineTo(Math.cos(a) * d, Math.sin(a) * d);\n }\n ctx.closePath();\n}\n\n// Matches the canvas's pixel buffer to its box and the screen's pixel ratio.\nfunction fit(canvas: HTMLCanvasElement) {\n const width = canvas.clientWidth;\n const height = canvas.clientHeight;\n const w = Math.round(width * devicePixelRatio);\n const h = Math.round(height * devicePixelRatio);\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n return { width, height };\n}\n\nfunction viewportCanvas(): HTMLCanvasElement {\n if (overlay?.isConnected) return overlay;\n overlay = document.createElement('canvas');\n overlay.className = 'confetti-overlay';\n overlay.setAttribute('aria-hidden', 'true');\n // Inline, so the overlay works even where the stylesheet does not reach.\n Object.assign(overlay.style, {\n position: 'fixed', inset: '0', width: '100%', height: '100%', margin: '0', padding: '0',\n border: '0', background: 'transparent', pointerEvents: 'none', zIndex: '10001'\n });\n document.body.append(overlay);\n if (typeof overlay.showPopover === 'function') {\n overlay.popover = 'manual';\n overlay.showPopover();\n }\n return overlay;\n}\n\n// Resolves each theme color token through `color`, so light-dark() and\n// relative colors reach the canvas as plain colors.\nfunction themeColors(themed: Element): string[] {\n const probe = document.createElement('span');\n probe.hidden = true;\n themed.append(probe);\n const style = getComputedStyle(probe);\n const colors = THEME_COLORS.filter((role) => style.getPropertyValue(`--md-sys-color-${role}`).trim()).map((role) => {\n probe.style.color = `var(--md-sys-color-${role})`;\n return getComputedStyle(probe).color;\n });\n probe.remove();\n return colors.length ? colors : FALLBACK_COLORS;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -50,18 +50,25 @@ var PieChart = class extends LineChart {
|
|
|
50
50
|
}
|
|
51
51
|
/** The row's share of the whole as a percentage, or '' for none. */
|
|
52
52
|
_share(index) {
|
|
53
|
+
var _a;
|
|
53
54
|
const [start, end] = this._turns[index];
|
|
54
55
|
if (end <= start) return "";
|
|
55
56
|
const share = end - start;
|
|
56
|
-
const
|
|
57
|
+
const digits = share < 0.1 ? 1 : 0;
|
|
58
|
+
(_a = this._percents ?? (this._percents = []))[digits] ?? (_a[digits] = this._percent(digits));
|
|
59
|
+
return this._percents[digits].format(share);
|
|
60
|
+
}
|
|
61
|
+
_percent(digits) {
|
|
62
|
+
const options = { style: "percent", maximumFractionDigits: digits };
|
|
57
63
|
try {
|
|
58
|
-
return
|
|
64
|
+
return new Intl.NumberFormat(this.el.closest("[lang]")?.lang || void 0, options);
|
|
59
65
|
} catch {
|
|
60
|
-
return
|
|
66
|
+
return new Intl.NumberFormat(void 0, options);
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
/** The legend: every row with its color, its cell and its share. */
|
|
64
70
|
_guides() {
|
|
71
|
+
this._percents = [];
|
|
65
72
|
const legend = document.createElement("ul");
|
|
66
73
|
legend.className = "pie-chart-legend";
|
|
67
74
|
legend.setAttribute("aria-hidden", "true");
|
|
@@ -163,4 +170,4 @@ var PieChart = class extends LineChart {
|
|
|
163
170
|
export {
|
|
164
171
|
PieChart
|
|
165
172
|
};
|
|
166
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-VGZSAFTX.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/ts/components/pieChart.ts"],
|
|
4
|
-
"sourcesContent": ["import { InitElements, InitElement } from '../core/component';\nimport { LineChart, LineChartOptions, svgNode as node } from './lineChart';\n\nexport type PieChartOptions = LineChartOptions;\n\n// ponytail: rows past six repeat the colors; group small parts as \"Other\".\nconst COLORS = 6;\n/** The pie's radius in a 100-unit box, leaving room for the active slice to grow. */\nconst RADIUS = 46;\n/** The active slice's scale, as in _pie-chart.scss. */\nconst GROWN = 1.06;\n/** Slices smaller than this share get no .values label. */\nconst LABEL_SHARE = 0.05;\nlet _maskId = 0;\n\n/**\n * Pie chart. It reads its <table> like LineChart, but draws each row of the\n * first value column as a slice of the whole, clockwise from the top, with\n * a legend of every row and its share. With `.donut`, a <tfoot> row is the\n * total in the middle. Further columns show in the tooltip.\n *\n * Re-run `PieChart.init(el)` after changing the table.\n */\nexport class PieChart extends LineChart {\n // No initializers: LineChart's constructor draws before they would run.\n /** Each row's start and end, as fractions of a turn clockwise from the top. */\n private _turns: [number, number][];\n /** Each row's color, or undefined for a row with no slice. */\n private _colors: (string | undefined)[];\n private _slices: (SVGPathElement | null)[];\n\n protected get _type() {\n return 'pie-chart';\n }\n\n protected get _key() {\n return 'Expressive_PieChart';\n }\n\n protected get _points() {\n return false;\n }\n\n protected get _circular() {\n return true;\n }\n\n static init(el: HTMLElement, options?: Partial<PieChartOptions>): PieChart;\n static init(els: InitElements<InitElement>, options?: Partial<PieChartOptions>): PieChart[];\n static init(\n els: HTMLElement | InitElements<InitElement>,\n options: Partial<PieChartOptions> = {}\n ): PieChart | PieChart[] {\n return super.init(els as HTMLElement, options) as PieChart | PieChart[];\n }\n\n static getInstance(el: HTMLElement): PieChart {\n return el['Expressive_PieChart'];\n }\n\n show(index: number) {\n if (!this._tooltip || index === this.activeIndex) return;\n super.show(index);\n this._slices.forEach((slice, i) => slice?.classList.toggle('active', i === index));\n // LineChart hides the tooltip for -1 and for an index past the last row.\n if (this._tooltip.hidden) return;\n\n const color = this._colors[index];\n this._tooltip.querySelectorAll<HTMLElement>('[data-series]').forEach((span) => {\n if (color) span.dataset.series = color;\n else delete span.dataset.series;\n });\n const share = this._share(index);\n const value = this._tooltip.querySelector('span:nth-of-type(2)');\n if (share && value) value.textContent += ` (${share})`;\n }\n\n /** CSS places the tooltip on the slice's middle from --turn. */\n protected _place(index: number) {\n const middle = (this._turns[index][0] + this._turns[index][1]) / 2;\n this._tooltip.style.setProperty('--turn', String(middle));\n // On the right half it opens leftwards, over the pie.\n this._tooltip.classList.toggle('end', middle < 0.5);\n }\n\n /** The row's share of the whole as a percentage, or '' for none. */\n private _share(index: number) {\n const [start, end] = this._turns[index];\n if (end <= start) return '';\n const share = end - start;\n // Whole percentages, with a tenth below 10% so a small part is not 0%.\n const
|
|
5
|
-
"mappings": ";;;;;;AAMA,IAAM,SAAS;AAEf,IAAM,SAAS;AAEf,IAAM,QAAQ;AAEd,IAAM,cAAc;AACpB,IAAI,UAAU;AAUP,IAAM,WAAN,cAAuB,UAAU;AAAA,
|
|
4
|
+
"sourcesContent": ["import { InitElements, InitElement } from '../core/component';\nimport { LineChart, LineChartOptions, svgNode as node } from './lineChart';\n\nexport type PieChartOptions = LineChartOptions;\n\n// ponytail: rows past six repeat the colors; group small parts as \"Other\".\nconst COLORS = 6;\n/** The pie's radius in a 100-unit box, leaving room for the active slice to grow. */\nconst RADIUS = 46;\n/** The active slice's scale, as in _pie-chart.scss. */\nconst GROWN = 1.06;\n/** Slices smaller than this share get no .values label. */\nconst LABEL_SHARE = 0.05;\nlet _maskId = 0;\n\n/**\n * Pie chart. It reads its <table> like LineChart, but draws each row of the\n * first value column as a slice of the whole, clockwise from the top, with\n * a legend of every row and its share. With `.donut`, a <tfoot> row is the\n * total in the middle. Further columns show in the tooltip.\n *\n * Re-run `PieChart.init(el)` after changing the table.\n */\nexport class PieChart extends LineChart {\n // No initializers: LineChart's constructor draws before they would run.\n /** Each row's start and end, as fractions of a turn clockwise from the top. */\n private _turns: [number, number][];\n /** Each row's color, or undefined for a row with no slice. */\n private _colors: (string | undefined)[];\n private _slices: (SVGPathElement | null)[];\n /** Percent formatters by fraction digits, rebuilt once per legend. */\n private _percents: Intl.NumberFormat[];\n\n protected get _type() {\n return 'pie-chart';\n }\n\n protected get _key() {\n return 'Expressive_PieChart';\n }\n\n protected get _points() {\n return false;\n }\n\n protected get _circular() {\n return true;\n }\n\n static init(el: HTMLElement, options?: Partial<PieChartOptions>): PieChart;\n static init(els: InitElements<InitElement>, options?: Partial<PieChartOptions>): PieChart[];\n static init(\n els: HTMLElement | InitElements<InitElement>,\n options: Partial<PieChartOptions> = {}\n ): PieChart | PieChart[] {\n return super.init(els as HTMLElement, options) as PieChart | PieChart[];\n }\n\n static getInstance(el: HTMLElement): PieChart {\n return el['Expressive_PieChart'];\n }\n\n show(index: number) {\n if (!this._tooltip || index === this.activeIndex) return;\n super.show(index);\n this._slices.forEach((slice, i) => slice?.classList.toggle('active', i === index));\n // LineChart hides the tooltip for -1 and for an index past the last row.\n if (this._tooltip.hidden) return;\n\n const color = this._colors[index];\n this._tooltip.querySelectorAll<HTMLElement>('[data-series]').forEach((span) => {\n if (color) span.dataset.series = color;\n else delete span.dataset.series;\n });\n const share = this._share(index);\n const value = this._tooltip.querySelector('span:nth-of-type(2)');\n if (share && value) value.textContent += ` (${share})`;\n }\n\n /** CSS places the tooltip on the slice's middle from --turn. */\n protected _place(index: number) {\n const middle = (this._turns[index][0] + this._turns[index][1]) / 2;\n this._tooltip.style.setProperty('--turn', String(middle));\n // On the right half it opens leftwards, over the pie.\n this._tooltip.classList.toggle('end', middle < 0.5);\n }\n\n /** The row's share of the whole as a percentage, or '' for none. */\n private _share(index: number) {\n const [start, end] = this._turns[index];\n if (end <= start) return '';\n const share = end - start;\n // Whole percentages, with a tenth below 10% so a small part is not 0%.\n const digits = share < 0.1 ? 1 : 0;\n (this._percents ??= [])[digits] ??= this._percent(digits);\n return this._percents[digits].format(share);\n }\n\n private _percent(digits: number) {\n const options = { style: 'percent', maximumFractionDigits: digits } as const;\n try {\n return new Intl.NumberFormat(this.el.closest<HTMLElement>('[lang]')?.lang || undefined, options);\n } catch {\n // An invalid lang attribute.\n return new Intl.NumberFormat(undefined, options);\n }\n }\n\n /** The legend: every row with its color, its cell and its share. */\n protected _guides(): Element[] {\n // A redraw picks up a changed lang attribute.\n this._percents = [];\n const legend = document.createElement('ul');\n legend.className = 'pie-chart-legend';\n legend.setAttribute('aria-hidden', 'true');\n const text = this.series[0].text;\n legend.append(...this.labels.map((label, i) => {\n const li = document.createElement('li');\n if (this._colors[i]) li.dataset.series = this._colors[i];\n const [name, value, share] = [label, text[i], this._share(i)].map((content) => {\n const span = document.createElement('span');\n span.textContent = content;\n return span;\n });\n li.append(name, value, share);\n return li;\n }));\n return [legend];\n }\n\n /** The row under the pointer by its angle from the middle, or -1 off the slices. */\n protected _indexAt(e: PointerEvent) {\n const [turn, share] = this._polarAt(e);\n // The distance in the SVG's 100-unit box.\n const distance = share * 100;\n const hole = this.el.classList.contains('donut')\n ? parseFloat(getComputedStyle(this.el).getPropertyValue('--md-comp-pie-chart-hole')) || 0\n : 0;\n if (distance < RADIUS * hole) return -1;\n const index = this._turns.findIndex(([start, end]) => start <= turn && turn < end);\n // The active slice is drawn larger, so the pointer stays on it to its edge.\n return distance > RADIUS * (index === this.activeIndex ? GROWN : 1) ? -1 : index;\n }\n\n /**\n * An SVG of slices in a -50 to 50 box, under a mask that cuts the gaps\n * between them and the donut's hole, which CSS sizes. The values and the\n * total are HTML over it.\n */\n protected _draw(): Element {\n const values = this.series[0].values.map((value) => Math.max(0, value ?? 0));\n const total = values.reduce((sum, value) => sum + value, 0);\n let turn = 0;\n this._turns = values.map((value) => [turn, (turn += total ? value / total : 0)]);\n // Colors go round the drawn slices; the last skips the first's color beside it.\n const drawn = this._turns.filter(([start, end]) => end > start).length;\n let slice = 0;\n this._colors = this._turns.map(([start, end]) => {\n if (end <= start) return undefined;\n const index = slice++;\n return String(index === drawn - 1 && index > 0 && index % COLORS === 0 ? 2 : (index % COLORS) + 1);\n });\n const at = (t: number, r = RADIUS) => {\n const angle = t * 2 * Math.PI;\n return `${(r * Math.sin(angle)).toFixed(3)},${(-r * Math.cos(angle)).toFixed(3)}`;\n };\n\n const pie = document.createElement('div');\n pie.className = 'pie-chart-pie';\n pie.setAttribute('aria-hidden', 'true');\n const svg = node('svg', { viewBox: '-50 -50 100 100', focusable: 'false' });\n const id = `pie-chart-mask-${++_maskId}`;\n const area = { x: '-50', y: '-50', width: '100', height: '100' };\n const mask = node('mask', { id, maskUnits: 'userSpaceOnUse', ...area });\n const edges = this._turns.filter(([start, end]) => end > start);\n mask.append(\n node('rect', { ...area, fill: 'white' }),\n node('path', {\n class: 'pie-chart-gaps',\n stroke: 'black',\n d: edges.length > 1 ? edges.map(([start]) => `M0,0L${at(start, 50)}`).join('') : ''\n }),\n node('circle', { class: 'pie-chart-hole', r: String(RADIUS), fill: 'black' })\n );\n\n const slices = node('g', { mask: `url(#${id})` });\n const arc = `A${RADIUS},${RADIUS} 0`;\n this._slices = this._turns.map(([start, end], i) => {\n if (end <= start) return null;\n const slice = node('path', {\n class: 'pie-chart-slice',\n 'data-series': this._colors[i],\n // A whole circle is two half arcs; one arc cannot end where it starts.\n d: end - start >= 1\n ? `M0,${-RADIUS}${arc} 1 1 0,${RADIUS}${arc} 1 1 0,${-RADIUS}Z`\n : `M0,0L${at(start)}${arc} ${end - start > 0.5 ? 1 : 0} 1 ${at(end)}Z`\n }) as SVGPathElement;\n slices.append(slice);\n return slice;\n });\n svg.append(mask, slices);\n pie.append(svg);\n\n if (this.el.classList.contains('values')) {\n const labels = document.createElement('div');\n labels.className = 'pie-chart-values';\n this._turns.forEach(([start, end], i) => {\n if (end - start < LABEL_SHARE) return;\n const label = document.createElement('span');\n label.dataset.series = this._colors[i];\n label.style.setProperty('--turn', String((start + end) / 2));\n label.textContent = this._share(i);\n labels.append(label);\n });\n pie.append(labels);\n }\n\n const middle = this._total('pie-chart-total');\n if (middle) pie.append(middle);\n return pie;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["slice"]
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Utils
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MNPROCZF.mjs";
|
|
4
4
|
|
|
5
5
|
// src/ts/behaviors/dialogs.ts
|
|
6
6
|
var _Dialogs = class _Dialogs {
|
|
@@ -73,4 +73,4 @@ var Dialogs = _Dialogs;
|
|
|
73
73
|
export {
|
|
74
74
|
Dialogs
|
|
75
75
|
};
|
|
76
|
-
//# sourceMappingURL=chunk-
|
|
76
|
+
//# sourceMappingURL=chunk-X7OCHZVF.mjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Utils
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MNPROCZF.mjs";
|
|
4
4
|
|
|
5
5
|
// src/ts/plugins/dockedDisplayPlugin.ts
|
|
6
6
|
var _defaults = {
|
|
@@ -17,9 +17,9 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
* Tears the plugin down.
|
|
21
|
-
* instance - and through it the whole picker subtree - so
|
|
22
|
-
* component must call this from its own destroy().
|
|
20
|
+
* Tears the plugin down. While shown, the document listener holds a
|
|
21
|
+
* reference to this instance - and through it the whole picker subtree - so
|
|
22
|
+
* the owning component must call this from its own destroy().
|
|
23
23
|
*/
|
|
24
24
|
this.destroy = () => {
|
|
25
25
|
document.removeEventListener("click", this._handleDocumentClick);
|
|
@@ -28,6 +28,7 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
|
|
|
28
28
|
this.show = () => {
|
|
29
29
|
if (this.visible) return;
|
|
30
30
|
this.visible = true;
|
|
31
|
+
document.addEventListener("click", this._handleDocumentClick);
|
|
31
32
|
const coordinates = Utils._setAbsolutePosition(this.el, this.container, "bottom", this.options.margin, this.options.transition, this.options.align);
|
|
32
33
|
this.container.style.visibility = "visible";
|
|
33
34
|
this.container.style.transition = `
|
|
@@ -41,6 +42,7 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
|
|
|
41
42
|
this.hide = () => {
|
|
42
43
|
if (!this.visible) return;
|
|
43
44
|
this.visible = false;
|
|
45
|
+
document.removeEventListener("click", this._handleDocumentClick);
|
|
44
46
|
this.container.removeAttribute("style");
|
|
45
47
|
this.container.style.transition = `
|
|
46
48
|
transform ${this.options.duration}ms ease-out,
|
|
@@ -59,7 +61,6 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
|
|
|
59
61
|
this.container.classList.add("display-docked");
|
|
60
62
|
this.container.append(container);
|
|
61
63
|
el.parentElement.append(this.container);
|
|
62
|
-
document.addEventListener("click", this._handleDocumentClick);
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* Initializes instance of DockedDisplayPlugin
|
|
@@ -75,4 +76,4 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
|
|
|
75
76
|
export {
|
|
76
77
|
DockedDisplayPlugin
|
|
77
78
|
};
|
|
78
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-YMSXJON6.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/plugins/dockedDisplayPlugin.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils } from '../core/utils';\n\nexport interface DockedDisplayPluginOptions {\n /**\n * Margin between element and docked container\n */\n margin: number,\n /**\n * Transition movement\n */\n transition: number,\n /**\n * Transition duration\n */\n duration: number,\n /**\n * The alignment of the docked container\n */\n align: string\n}\n\nconst _defaults: DockedDisplayPluginOptions = {\n margin: 5,\n transition: 10,\n duration: 250,\n align: 'left'\n}\n\nexport class DockedDisplayPlugin {\n private readonly el: HTMLElement;\n private readonly container: HTMLDivElement;\n private options: Partial<DockedDisplayPluginOptions>;\n private visible: boolean;\n\n constructor(el: HTMLElement, container: HTMLElement, options: Partial<DockedDisplayPluginOptions>) {\n this.el = el;\n this.options = {\n ..._defaults,\n ...options\n };\n\n this.container = document.createElement('div');\n this.container.classList.add('display-docked');\n this.container.append(container);\n el.parentElement.append(this.container);\n }\n\n private _handleDocumentClick = (e: MouseEvent) => {\n if (this.visible && !e.composedPath().includes(this.el) && !e.composedPath().includes(this.container)) {\n this.hide();\n }\n };\n\n /**\n * Tears the plugin down. While shown, the document listener holds a\n * reference to this instance - and through it the whole picker subtree - so\n * the owning component must call this from its own destroy().\n */\n destroy = () => {\n document.removeEventListener('click', this._handleDocumentClick);\n this.container.remove();\n };\n\n /**\n * Initializes instance of DockedDisplayPlugin\n * @param el HTMLElement to position to\n * @param container HTMLElement to be positioned\n * @param options Plugin options\n */\n static init(el: HTMLElement, container: HTMLElement, options?: Partial<DockedDisplayPluginOptions>): DockedDisplayPlugin {\n return new DockedDisplayPlugin(el, container, options);\n }\n\n show = () => {\n if (this.visible) return;\n this.visible = true;\n document.addEventListener('click', this._handleDocumentClick);\n const coordinates = Utils._setAbsolutePosition(this.el, this.container, 'bottom', this.options.margin, this.options.transition, this.options.align);\n\n // @todo move to Util? -> duplicate code fragment with tooltip\n // easeOutCubic\n this.container.style.visibility = 'visible';\n this.container.style.transition = `\n transform ${this.options.duration}ms ease-out,\n opacity ${this.options.duration}ms ease-out`;\n setTimeout(() => {\n this.container.style.transform = `translateX(${coordinates.x}px) translateY(${coordinates.y}px)`;\n this.container.style.opacity = (1).toString();\n }, 1);\n };\n\n hide = () => {\n if (!this.visible) return;\n this.visible = false;\n document.removeEventListener('click', this._handleDocumentClick);\n // @todo move to Util? -> duplicate code fragment with tooltip\n this.container.removeAttribute('style');\n this.container.style.transition = `\n transform ${this.options.duration}ms ease-out,\n opacity ${this.options.duration}ms ease-out`;\n setTimeout(() => {\n this.container.style.transform = `translateX(0px) translateY(0px)`;\n this.container.style.opacity = '0';\n }, 1);\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAqBA,IAAM,YAAwC;AAAA,EAC5C,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,OAAO;AACT;AAEO,IAAM,sBAAN,MAAM,qBAAoB;AAAA,EAM/B,YAAY,IAAiB,WAAwB,SAA8C;AAanG,SAAQ,uBAAuB,CAAC,MAAkB;AAChD,UAAI,KAAK,WAAW,CAAC,EAAE,aAAa,EAAE,SAAS,KAAK,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,SAAS,KAAK,SAAS,GAAG;AACrG,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAOA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAU,MAAM;AACd,eAAS,oBAAoB,SAAS,KAAK,oBAAoB;AAC/D,WAAK,UAAU,OAAO;AAAA,IACxB;AAYA,gBAAO,MAAM;AACX,UAAI,KAAK,QAAS;AAClB,WAAK,UAAU;AACf,eAAS,iBAAiB,SAAS,KAAK,oBAAoB;AAC5D,YAAM,cAAc,MAAM,qBAAqB,KAAK,IAAI,KAAK,WAAW,UAAU,KAAK,QAAQ,QAAQ,KAAK,QAAQ,YAAY,KAAK,QAAQ,KAAK;AAIlJ,WAAK,UAAU,MAAM,aAAa;AAClC,WAAK,UAAU,MAAM,aAAa;AAAA,kBACpB,KAAK,QAAQ,QAAQ;AAAA,gBACvB,KAAK,QAAQ,QAAQ;AACjC,iBAAW,MAAM;AACf,aAAK,UAAU,MAAM,YAAY,cAAc,YAAY,CAAC,kBAAkB,YAAY,CAAC;AAC3F,aAAK,UAAU,MAAM,UAAW,GAAG,SAAS;AAAA,MAC9C,GAAG,CAAC;AAAA,IACN;AAEA,gBAAO,MAAM;AACX,UAAI,CAAC,KAAK,QAAS;AACnB,WAAK,UAAU;AACf,eAAS,oBAAoB,SAAS,KAAK,oBAAoB;AAE/D,WAAK,UAAU,gBAAgB,OAAO;AACtC,WAAK,UAAU,MAAM,aAAa;AAAA,kBACpB,KAAK,QAAQ,QAAQ;AAAA,gBACvB,KAAK,QAAQ,QAAQ;AACjC,iBAAW,MAAM;AACf,aAAK,UAAU,MAAM,YAAY;AACjC,aAAK,UAAU,MAAM,UAAU;AAAA,MACjC,GAAG,CAAC;AAAA,IACN;AArEE,SAAK,KAAK;AACV,SAAK,UAAU;AAAA,MACb,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAEA,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,UAAU,IAAI,gBAAgB;AAC7C,SAAK,UAAU,OAAO,SAAS;AAC/B,OAAG,cAAc,OAAO,KAAK,SAAS;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,OAAO,KAAK,IAAiB,WAAwB,SAAoE;AACvH,WAAO,IAAI,qBAAoB,IAAI,WAAW,OAAO;AAAA,EACvD;AAkCF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Utils
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MNPROCZF.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Component
|
|
6
6
|
} from "./chunk-LTWPGFBR.mjs";
|
|
@@ -172,4 +172,4 @@ export {
|
|
|
172
172
|
EXPANDING_CARD_SELECTOR,
|
|
173
173
|
ExpandingCard
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
175
|
+
//# sourceMappingURL=chunk-Z2NRKI7R.mjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Utils
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MNPROCZF.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Component
|
|
6
6
|
} from "./chunk-LTWPGFBR.mjs";
|
|
@@ -91,4 +91,4 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
|
|
|
91
91
|
export {
|
|
92
92
|
FloatingActionButton
|
|
93
93
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
94
|
+
//# sourceMappingURL=chunk-ZAS25YFD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-ZKZKNSLC.mjs.map
|