@yewdiel21/motion-kit 0.15.0 → 0.17.0
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 +25 -0
- package/dist/auto/index.d.ts +8 -3
- package/dist/auto/index.js +13 -3
- package/dist/auto/index.js.map +1 -1
- package/dist/{chunk-A6QQCF6V.js → chunk-7IQTMF7Y.js} +1542 -54
- package/dist/chunk-7IQTMF7Y.js.map +1 -0
- package/dist/{chunk-6IRJYXJU.js → chunk-BZLMCHUD.js} +2 -2
- package/dist/{chunk-JXRS3OEA.js → chunk-VJFPTLAK.js} +29 -7
- package/dist/chunk-VJFPTLAK.js.map +1 -0
- package/dist/css/components/chart.css +7 -0
- package/dist/css/components/drilldown-menu.css +130 -0
- package/dist/css/components/heatmap-chart.css +7 -0
- package/dist/css/components/pie-chart.css +7 -0
- package/dist/css/components/radar-chart.css +7 -0
- package/dist/css/components/radial-chart.css +16 -2
- package/dist/css/components/sankey-chart.css +7 -0
- package/dist/css/components/scroll-island.css +3 -0
- package/dist/css/components/signature-pad.css +104 -0
- package/dist/css/components/voice-message-bubble.css +50 -0
- package/dist/css/components/waveform-player.css +36 -0
- package/dist/css/components/wheel-picker.css +17 -0
- package/dist/elements/index.d.ts +90 -4
- package/dist/elements/index.js +290 -8
- package/dist/elements/index.js.map +1 -1
- package/dist/{reveal-BfyKKsw4.d.ts → engine-Bn6hC87X.d.ts} +206 -1
- package/dist/index.css +324 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +48 -10
- package/dist/react/index.js +240 -10
- package/dist/react/index.js.map +1 -1
- package/dist/{reduced-6X_bns60.d.ts → reduced-YS6TZjpa.d.ts} +1 -1
- package/dist/{store-CA2Qcun_.d.ts → store-CZ6vdtIE.d.ts} +5 -1
- package/package.json +110 -110
- package/registry.json +64 -0
- package/src/auto/auto-init.ts +308 -293
- package/src/components/add-to-cart/README.md +49 -34
- package/src/components/add-to-cart/react.tsx +4 -0
- package/src/components/chart/README.md +49 -34
- package/src/components/chart/chart.css +7 -0
- package/src/components/chart/element.ts +2 -1
- package/src/components/chart/engine.ts +105 -13
- package/src/components/chart/react.tsx +2 -2
- package/src/components/drilldown-menu/README.md +163 -0
- package/src/components/drilldown-menu/drilldown-menu.css +129 -0
- package/src/components/drilldown-menu/element.ts +59 -0
- package/src/components/drilldown-menu/engine.ts +338 -0
- package/src/components/drilldown-menu/react.tsx +76 -0
- package/src/components/radial-chart/README.md +10 -0
- package/src/components/radial-chart/element.ts +2 -2
- package/src/components/radial-chart/engine.ts +33 -6
- package/src/components/radial-chart/radial-chart.css +9 -2
- package/src/components/radial-chart/react.tsx +2 -2
- package/src/components/scroll-island/README.md +44 -34
- package/src/components/scroll-island/element.ts +1 -1
- package/src/components/scroll-island/engine.ts +25 -3
- package/src/components/scroll-island/react.tsx +3 -3
- package/src/components/scroll-island/scroll-island.css +3 -0
- package/src/components/signature-pad/README.md +97 -0
- package/src/components/signature-pad/element.ts +57 -0
- package/src/components/signature-pad/engine.ts +437 -0
- package/src/components/signature-pad/react.tsx +56 -0
- package/src/components/signature-pad/signature-pad.css +103 -0
- package/src/components/voice-message-bubble/README.md +31 -0
- package/src/components/voice-message-bubble/element.ts +20 -0
- package/src/components/voice-message-bubble/engine.ts +68 -0
- package/src/components/voice-message-bubble/react.tsx +27 -0
- package/src/components/voice-message-bubble/voice-message-bubble.css +12 -0
- package/src/components/waveform-player/README.md +30 -0
- package/src/components/waveform-player/element.ts +21 -0
- package/src/components/waveform-player/engine.ts +261 -0
- package/src/components/waveform-player/react.tsx +27 -0
- package/src/components/waveform-player/waveform-player.css +35 -0
- package/src/components/wheel-picker/README.md +33 -0
- package/src/components/wheel-picker/element.ts +18 -0
- package/src/components/wheel-picker/engine.ts +210 -0
- package/src/components/wheel-picker/react.tsx +32 -0
- package/src/components/wheel-picker/wheel-picker.css +16 -0
- package/src/elements/index.ts +273 -258
- package/src/index.ts +295 -290
- package/src/react/index.ts +176 -171
- package/dist/chunk-A6QQCF6V.js.map +0 -1
- package/dist/chunk-JXRS3OEA.js.map +0 -1
- /package/dist/{chunk-6IRJYXJU.js.map → chunk-BZLMCHUD.js.map} +0 -0
|
@@ -2578,9 +2578,9 @@ function createSteps(root, options = {}) {
|
|
|
2578
2578
|
registerMotion();
|
|
2579
2579
|
const scope = createScope();
|
|
2580
2580
|
const { duration = TIMING.onboarding.step, animateFirst = true, target = "[data-mk-flow-item]" } = options;
|
|
2581
|
-
const
|
|
2581
|
+
const clamp5 = (value) => Math.min(steps.length - 1, Math.max(0, Math.round(value)));
|
|
2582
2582
|
const marked3 = steps.findIndex((step) => step.hasAttribute("data-mk-current"));
|
|
2583
|
-
let index =
|
|
2583
|
+
let index = clamp5(options.index ?? (marked3 >= 0 ? marked3 : 0));
|
|
2584
2584
|
let wanted = index;
|
|
2585
2585
|
let running2 = null;
|
|
2586
2586
|
let stopCounter = () => {
|
|
@@ -2633,7 +2633,7 @@ function createSteps(root, options = {}) {
|
|
|
2633
2633
|
}
|
|
2634
2634
|
};
|
|
2635
2635
|
const goTo = (to) => {
|
|
2636
|
-
wanted =
|
|
2636
|
+
wanted = clamp5(to);
|
|
2637
2637
|
if (wanted === index && !running2) return Promise.resolve();
|
|
2638
2638
|
running2 ??= change();
|
|
2639
2639
|
return running2;
|
|
@@ -2700,7 +2700,7 @@ function createQuantity(root, options = {}) {
|
|
|
2700
2700
|
const step = Number.isFinite(options.step) && options.step > 0 ? options.step : 1;
|
|
2701
2701
|
const steps = Math.floor((max - min) / step + 1e-9);
|
|
2702
2702
|
const upper = Math.min(max, Number((min + steps * step).toFixed(10)));
|
|
2703
|
-
const
|
|
2703
|
+
const normalize2 = (n) => Math.max(min, Math.min(upper, Number((min + Math.round((n - min) / step) * step).toFixed(10))));
|
|
2704
2704
|
const original = input.value;
|
|
2705
2705
|
const disabled = options.disabled ?? input.disabled;
|
|
2706
2706
|
const decrease = root.querySelector("[data-mk-quantity-decrease]");
|
|
@@ -2711,13 +2711,13 @@ function createQuantity(root, options = {}) {
|
|
|
2711
2711
|
scope.attr(input, "disabled", disabled ? "" : null);
|
|
2712
2712
|
scope.attr(root, "data-mk-ready", "");
|
|
2713
2713
|
const initial = input.value.trim() ? Number(input.value) : NaN;
|
|
2714
|
-
let value =
|
|
2714
|
+
let value = normalize2(Number.isFinite(options.value) ? options.value : Number.isFinite(initial) ? initial : min);
|
|
2715
2715
|
let pendingReset = null;
|
|
2716
2716
|
const typed = () => input.value.trim() && Number.isFinite(input.valueAsNumber) ? input.valueAsNumber : NaN;
|
|
2717
2717
|
const render = (syncInput = true) => {
|
|
2718
2718
|
if (pendingReset) {
|
|
2719
2719
|
if (pendingReset.eventPhase !== 0) return;
|
|
2720
|
-
if (!pendingReset.defaultPrevented) value =
|
|
2720
|
+
if (!pendingReset.defaultPrevented) value = normalize2(Number.isFinite(typed()) ? typed() : min);
|
|
2721
2721
|
pendingReset = null;
|
|
2722
2722
|
}
|
|
2723
2723
|
if (syncInput) input.value = String(value);
|
|
@@ -2728,7 +2728,7 @@ function createQuantity(root, options = {}) {
|
|
|
2728
2728
|
if (scope.disposed || !Number.isFinite(next)) return;
|
|
2729
2729
|
if (pendingReset?.eventPhase === 0) pendingReset = null;
|
|
2730
2730
|
const previous = value;
|
|
2731
|
-
value =
|
|
2731
|
+
value = normalize2(next);
|
|
2732
2732
|
render(syncInput);
|
|
2733
2733
|
if (notify && value !== previous) {
|
|
2734
2734
|
options.onChange?.(value);
|
|
@@ -2744,7 +2744,7 @@ function createQuantity(root, options = {}) {
|
|
|
2744
2744
|
});
|
|
2745
2745
|
scope.on(input, "input", () => {
|
|
2746
2746
|
const n = typed();
|
|
2747
|
-
if (Number.isFinite(n) &&
|
|
2747
|
+
if (Number.isFinite(n) && normalize2(n) === n) commit(n, true, false);
|
|
2748
2748
|
});
|
|
2749
2749
|
scope.on(input, "change", () => {
|
|
2750
2750
|
if (Number.isFinite(typed())) setValue(typed());
|
|
@@ -5905,8 +5905,8 @@ function createProgress(root, options = {}) {
|
|
|
5905
5905
|
const max = finite(options.max) && options.max > min ? options.max : Math.max(min + 1, 100);
|
|
5906
5906
|
const variant = options.variant === "ring" ? "ring" : "linear";
|
|
5907
5907
|
const duration = finite(options.duration) ? Math.max(0, options.duration) : 0.7;
|
|
5908
|
-
const
|
|
5909
|
-
let value = options.value === null ? null :
|
|
5908
|
+
const clamp5 = (n) => Math.min(max, Math.max(min, n));
|
|
5909
|
+
let value = options.value === null ? null : clamp5(finite(options.value) ? options.value : min);
|
|
5910
5910
|
const visual = document.createElement("span");
|
|
5911
5911
|
visual.dataset.mkProgressVisual = "";
|
|
5912
5912
|
visual.setAttribute("aria-hidden", "true");
|
|
@@ -6007,7 +6007,7 @@ function createProgress(root, options = {}) {
|
|
|
6007
6007
|
if (scope.disposed) return;
|
|
6008
6008
|
const previous = value;
|
|
6009
6009
|
if (next === null) value = null;
|
|
6010
|
-
else if (finite(next)) value =
|
|
6010
|
+
else if (finite(next)) value = clamp5(next);
|
|
6011
6011
|
else return;
|
|
6012
6012
|
render(previous, true);
|
|
6013
6013
|
},
|
|
@@ -6055,13 +6055,13 @@ function createRangeSlider(root, options = {}) {
|
|
|
6055
6055
|
const places = Math.min(10, Math.max(decimals(step), decimals(min)));
|
|
6056
6056
|
const fix = (n) => Number(n.toFixed(places));
|
|
6057
6057
|
const upper = Math.min(max, fix(min + Math.floor((max - min) / step + 1e-9) * step));
|
|
6058
|
-
const
|
|
6058
|
+
const normalize2 = (n) => Math.max(min, Math.min(upper, fix(min + Math.round((n - min) / step) * step)));
|
|
6059
6059
|
const disabled = options.disabled ?? inputs.some((input) => input.disabled);
|
|
6060
6060
|
const output = root.querySelector("[data-mk-range-output]");
|
|
6061
6061
|
const format = (n) => options.formatValue ? options.formatValue(n) : String(n);
|
|
6062
6062
|
const originals = inputs.map((input) => input.value);
|
|
6063
6063
|
const ordered = (list3) => pair ? [...list3].sort((a, b) => a - b) : list3;
|
|
6064
|
-
const read = () => inputs.map((input) => input.value.trim() !== "" && Number.isFinite(Number(input.value)) ?
|
|
6064
|
+
const read = () => inputs.map((input) => input.value.trim() !== "" && Number.isFinite(Number(input.value)) ? normalize2(Number(input.value)) : NaN);
|
|
6065
6065
|
const authored = () => {
|
|
6066
6066
|
const current4 = read();
|
|
6067
6067
|
return inputs.map((input, i) => {
|
|
@@ -6069,7 +6069,7 @@ function createRangeSlider(root, options = {}) {
|
|
|
6069
6069
|
if (written === void 0) return current4[i];
|
|
6070
6070
|
const low = attrNumber(input, "min") ?? 0;
|
|
6071
6071
|
const high = Math.max(low, attrNumber(input, "max") ?? 100);
|
|
6072
|
-
return Number(input.value) === Math.min(high, Math.max(low, written)) ?
|
|
6072
|
+
return Number(input.value) === Math.min(high, Math.max(low, written)) ? normalize2(written) : current4[i];
|
|
6073
6073
|
});
|
|
6074
6074
|
};
|
|
6075
6075
|
const initial = (() => {
|
|
@@ -6078,7 +6078,7 @@ function createRangeSlider(root, options = {}) {
|
|
|
6078
6078
|
const fromInputs = authored();
|
|
6079
6079
|
return inputs.map((_, i) => {
|
|
6080
6080
|
const candidate = fromOption?.[i];
|
|
6081
|
-
if (finite2(candidate)) return
|
|
6081
|
+
if (finite2(candidate)) return normalize2(candidate);
|
|
6082
6082
|
return Number.isFinite(fromInputs[i]) ? fromInputs[i] : i === 0 ? min : upper;
|
|
6083
6083
|
});
|
|
6084
6084
|
})();
|
|
@@ -6188,7 +6188,7 @@ function createRangeSlider(root, options = {}) {
|
|
|
6188
6188
|
};
|
|
6189
6189
|
const take = (i) => {
|
|
6190
6190
|
const raw = inputs[i].value;
|
|
6191
|
-
const n = raw.trim() !== "" && Number.isFinite(Number(raw)) ?
|
|
6191
|
+
const n = raw.trim() !== "" && Number.isFinite(Number(raw)) ? normalize2(Number(raw)) : NaN;
|
|
6192
6192
|
if (!Number.isFinite(n)) return false;
|
|
6193
6193
|
let next = n;
|
|
6194
6194
|
if (pair) next = i === 0 ? Math.min(next, values[1]) : Math.max(next, values[0]);
|
|
@@ -6257,7 +6257,7 @@ function createRangeSlider(root, options = {}) {
|
|
|
6257
6257
|
setValue(next, notify = true) {
|
|
6258
6258
|
if (scope.disposed) return;
|
|
6259
6259
|
const list3 = Array.isArray(next) ? next : [next, next];
|
|
6260
|
-
const candidate = inputs.map((_, i) => finite2(list3[i]) ?
|
|
6260
|
+
const candidate = inputs.map((_, i) => finite2(list3[i]) ? normalize2(list3[i]) : values[i]);
|
|
6261
6261
|
values = ordered(candidate);
|
|
6262
6262
|
render(dragging >= 0 ? "drag" : "glide");
|
|
6263
6263
|
if (notify) commit(true);
|
|
@@ -6288,13 +6288,29 @@ function niceStep(raw) {
|
|
|
6288
6288
|
const fraction = raw / power;
|
|
6289
6289
|
return (fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10) * power;
|
|
6290
6290
|
}
|
|
6291
|
-
function barPath(x, width, base, end,
|
|
6291
|
+
function barPath(x, width, base, end, rounded2) {
|
|
6292
6292
|
const height = Math.abs(base - end);
|
|
6293
|
-
const r =
|
|
6293
|
+
const r = rounded2 ? Math.min(END_RADIUS, width / 2, height) : 0;
|
|
6294
6294
|
const dir = end < base ? 1 : -1;
|
|
6295
6295
|
if (!r) return `M${round(x)},${round(base)}V${round(end)}H${round(x + width)}V${round(base)}Z`;
|
|
6296
6296
|
return `M${round(x)},${round(base)}V${round(end + dir * r)}Q${round(x)},${round(end)} ${round(x + r)},${round(end)}H${round(x + width - r)}Q${round(x + width)},${round(end)} ${round(x + width)},${round(end + dir * r)}V${round(base)}Z`;
|
|
6297
6297
|
}
|
|
6298
|
+
function pillPath(x, width, a, b) {
|
|
6299
|
+
const top = Math.min(a, b), bottom = Math.max(a, b);
|
|
6300
|
+
const r = Math.min(width / 2, (bottom - top) / 2);
|
|
6301
|
+
return `M${round(x + r)},${round(top)}H${round(x + width - r)}Q${round(x + width)},${round(top)} ${round(x + width)},${round(top + r)}V${round(bottom - r)}Q${round(x + width)},${round(bottom)} ${round(x + width - r)},${round(bottom)}H${round(x + r)}Q${round(x)},${round(bottom)} ${round(x)},${round(bottom - r)}V${round(top + r)}Q${round(x)},${round(top)} ${round(x + r)},${round(top)}Z`;
|
|
6302
|
+
}
|
|
6303
|
+
function linePath(points, smooth) {
|
|
6304
|
+
if (!points.length) return "";
|
|
6305
|
+
let path = `M${round(points[0][0])},${round(points[0][1])}`;
|
|
6306
|
+
const slopes = points.slice(1).map((point, i) => (point[1] - points[i][1]) / (point[0] - points[i][0] || 1));
|
|
6307
|
+
const tangents = points.map((_, i) => i === 0 ? slopes[0] : i === points.length - 1 ? slopes[i - 1] : slopes[i - 1] * slopes[i] <= 0 ? 0 : 2 * slopes[i - 1] * slopes[i] / (slopes[i - 1] + slopes[i]));
|
|
6308
|
+
for (let i = 1; i < points.length; i++) {
|
|
6309
|
+
const [x0, y0] = points[i - 1], [x, y] = points[i], dx = (x - x0) / 3;
|
|
6310
|
+
path += smooth ? `C${round(x0 + dx)},${round(y0 + tangents[i - 1] * dx)} ${round(x - dx)},${round(y - tangents[i] * dx)} ${round(x)},${round(y)}` : `L${round(x)},${round(y)}`;
|
|
6311
|
+
}
|
|
6312
|
+
return path;
|
|
6313
|
+
}
|
|
6298
6314
|
function modelOf(options) {
|
|
6299
6315
|
const fromPoints = options.points?.length ? { labels: options.points.map((point) => String(point.label)), series: [{ name: options.label ?? "", values: options.points.map((point) => point.value) }] } : null;
|
|
6300
6316
|
const labels = fromPoints?.labels ?? (options.labels ?? []).map(String);
|
|
@@ -6532,6 +6548,7 @@ function createChart(root, initial = {}) {
|
|
|
6532
6548
|
const slot = plotW / n;
|
|
6533
6549
|
const xs = model.labels.map((_, i) => bar ? left + slot * (i + 0.5) : n === 1 ? left + plotW / 2 : left + plotW * i / (n - 1));
|
|
6534
6550
|
geometry = { width, height, top, bottom: top + plotH, left, right: width - right, xs, y, base };
|
|
6551
|
+
shown4 = { values, lower, lo, hi, type: type(), stacked: stacked() };
|
|
6535
6552
|
const grid = svg("g", { "data-mk-part": "grid" });
|
|
6536
6553
|
if (!axis) {
|
|
6537
6554
|
const zero = svg("line", { x1: left, x2: width - right, y1: round(base), y2: round(base) });
|
|
@@ -6570,10 +6587,53 @@ function createChart(root, initial = {}) {
|
|
|
6570
6587
|
if (bar) {
|
|
6571
6588
|
const barIndices = model.series.flatMap((_, index) => seriesType(index) === "bar" ? [index] : []);
|
|
6572
6589
|
const groups = stacked() ? 1 : barIndices.length;
|
|
6573
|
-
const
|
|
6590
|
+
const maxWidth = finite3(options.barWidth) ? Math.max(2, Math.min(96, options.barWidth)) : BAR_MAX;
|
|
6591
|
+
const barWidth = Math.max(2, Math.min(maxWidth, (slot * 0.62 - GAP3 * (groups - 1)) / groups));
|
|
6592
|
+
const pill2 = options.barStyle === "pill";
|
|
6593
|
+
const trackLayer = svg("g", { "data-mk-part": "bar-tracks" });
|
|
6594
|
+
canvas.append(trackLayer);
|
|
6595
|
+
if (options.barFill && options.barFill !== "solid") {
|
|
6596
|
+
model.series.forEach((series, k) => {
|
|
6597
|
+
const gradient = svg("linearGradient", { id: `${uid2}-bar-${k}`, x1: 0, y1: 0, x2: 0, y2: 1 });
|
|
6598
|
+
for (const [offset, opacity] of [["0", "1"], ["1", "0.4"]]) {
|
|
6599
|
+
const stop2 = svg("stop", { offset });
|
|
6600
|
+
stop2.style.stopColor = series.color;
|
|
6601
|
+
stop2.style.stopOpacity = opacity;
|
|
6602
|
+
gradient.append(stop2);
|
|
6603
|
+
}
|
|
6604
|
+
defs.append(gradient);
|
|
6605
|
+
});
|
|
6606
|
+
const hatch = svg("pattern", { id: `${uid2}-hatch`, patternUnits: "userSpaceOnUse", width: 6, height: 6, patternTransform: "rotate(35)" });
|
|
6607
|
+
const ground = svg("rect", { width: 6, height: 6 });
|
|
6608
|
+
ground.style.fill = "var(--mk-chart-track)";
|
|
6609
|
+
const stripe = svg("line", { x1: 0, x2: 0, y1: 0, y2: 6 });
|
|
6610
|
+
stripe.style.stroke = "var(--mk-chart-grid)";
|
|
6611
|
+
stripe.style.strokeWidth = "2";
|
|
6612
|
+
hatch.append(ground, stripe);
|
|
6613
|
+
defs.append(hatch);
|
|
6614
|
+
}
|
|
6615
|
+
const fillBar = (path, k, index) => {
|
|
6616
|
+
const fill = options.barFill && options.barFill !== "solid" ? `url(#${uid2}-bar-${k})` : model.series[k].color;
|
|
6617
|
+
path.style.setProperty("--mk-bar-fill", fill);
|
|
6618
|
+
path.style.fill = options.barFill === "spotlight" && index !== (selected ?? n - 1) ? `url(#${uid2}-hatch)` : fill;
|
|
6619
|
+
};
|
|
6620
|
+
const addTrack = (x) => {
|
|
6621
|
+
if (!options.barTrack) return;
|
|
6622
|
+
const path = svg("path", { d: pillPath(x, barWidth, top, base), "data-mk-part": "bar-track" });
|
|
6623
|
+
trackLayer.append(path);
|
|
6624
|
+
};
|
|
6574
6625
|
const totalsLayer = svg("g", { "data-mk-part": "totals" });
|
|
6575
6626
|
model.labels.forEach((_, i) => {
|
|
6576
6627
|
if (stacked()) {
|
|
6628
|
+
const clipId = `${uid2}-stack-${i}`;
|
|
6629
|
+
if (pill2) {
|
|
6630
|
+
const sum = totalsOf(values, i);
|
|
6631
|
+
const clip = svg("clipPath", { id: clipId });
|
|
6632
|
+
if (sum.up) clip.append(svg("path", { d: pillPath(xs[i] - barWidth / 2, barWidth, base, y(sum.up)) }));
|
|
6633
|
+
if (sum.down) clip.append(svg("path", { d: pillPath(xs[i] - barWidth / 2, barWidth, base, y(sum.down)) }));
|
|
6634
|
+
defs.append(clip);
|
|
6635
|
+
}
|
|
6636
|
+
addTrack(xs[i] - barWidth / 2);
|
|
6577
6637
|
let up = 0;
|
|
6578
6638
|
let down = 0;
|
|
6579
6639
|
const outer = { up: -1, down: -1 };
|
|
@@ -6592,8 +6652,9 @@ function createChart(root, initial = {}) {
|
|
|
6592
6652
|
const start = y(from) + (from !== 0 ? value > 0 ? -GAP3 : GAP3 : 0);
|
|
6593
6653
|
const end = y(to);
|
|
6594
6654
|
if (value > 0 && end >= start || value < 0 && end <= start) return;
|
|
6595
|
-
const path = svg("path", { d: barPath(xs[i] - barWidth / 2, barWidth, start, end, k === (value > 0 ? outer.up : outer.down)), "data-mk-index": i, "data-mk-series": k });
|
|
6596
|
-
path.
|
|
6655
|
+
const path = svg("path", { d: barPath(xs[i] - barWidth / 2, barWidth, start, end, !pill2 && k === (value > 0 ? outer.up : outer.down)), "data-mk-part": "bar", "data-mk-index": i, "data-mk-series": k });
|
|
6656
|
+
if (pill2) path.setAttribute("clip-path", `url(#${clipId})`);
|
|
6657
|
+
fillBar(path, k, i);
|
|
6597
6658
|
marks.append(path);
|
|
6598
6659
|
});
|
|
6599
6660
|
if (slot >= 22 && up > 0) {
|
|
@@ -6607,10 +6668,11 @@ function createChart(root, initial = {}) {
|
|
|
6607
6668
|
values.forEach((list3, k) => {
|
|
6608
6669
|
if (seriesType(k) !== "bar") return;
|
|
6609
6670
|
const value = list3[i];
|
|
6610
|
-
if (!finite3(value) || value === 0) return;
|
|
6611
6671
|
const x = xs[i] - groupWidth / 2 + barIndices.indexOf(k) * (barWidth + GAP3);
|
|
6612
|
-
|
|
6613
|
-
|
|
6672
|
+
addTrack(x);
|
|
6673
|
+
if (!finite3(value) || value === 0) return;
|
|
6674
|
+
const path = svg("path", { d: pill2 ? pillPath(x, barWidth, base, y(value)) : barPath(x, barWidth, base, y(value), true), "data-mk-part": "bar", "data-mk-index": i, "data-mk-series": k });
|
|
6675
|
+
fillBar(path, k, i);
|
|
6614
6676
|
marks.append(path);
|
|
6615
6677
|
});
|
|
6616
6678
|
}
|
|
@@ -6644,7 +6706,9 @@ function createChart(root, initial = {}) {
|
|
|
6644
6706
|
defs.append(gradient);
|
|
6645
6707
|
for (const points of runs2) {
|
|
6646
6708
|
if (points.length < 2) continue;
|
|
6647
|
-
const
|
|
6709
|
+
const upper = linePath(points, options.curve === "smooth");
|
|
6710
|
+
const bottom2 = linePath([...points].reverse().map(([px, , py]) => [px, py]), options.curve === "smooth");
|
|
6711
|
+
const d = `${upper}${bottom2.replace(/^M/, "L")}Z`;
|
|
6648
6712
|
const area = svg("path", { d, "data-mk-part": "area", "data-mk-series": k });
|
|
6649
6713
|
area.style.fill = `url(#${uid2}-fill-${k})`;
|
|
6650
6714
|
marks.append(area);
|
|
@@ -6657,7 +6721,7 @@ function createChart(root, initial = {}) {
|
|
|
6657
6721
|
marks.append(dot);
|
|
6658
6722
|
continue;
|
|
6659
6723
|
}
|
|
6660
|
-
const line = svg("path", { d:
|
|
6724
|
+
const line = svg("path", { d: linePath(points, options.curve === "smooth"), "data-mk-part": "line" });
|
|
6661
6725
|
line.style.stroke = series.color;
|
|
6662
6726
|
const dotted = Boolean(series.dash) && Number(series.dash.trim().split(/[\s,]+/)[0]) <= 1;
|
|
6663
6727
|
line.style.strokeWidth = dotted ? "2.5" : series.dash ? "1.5" : k === 0 ? "2.5" : "2";
|
|
@@ -6692,6 +6756,11 @@ function createChart(root, initial = {}) {
|
|
|
6692
6756
|
cursor.replaceChildren();
|
|
6693
6757
|
if (band) band.style.display = "none";
|
|
6694
6758
|
for (const mark of canvas.querySelectorAll("[data-mk-index]")) mark.removeAttribute("data-mk-dim");
|
|
6759
|
+
for (const mark of canvas.querySelectorAll('[data-mk-part="bar"]')) {
|
|
6760
|
+
const index = Number(mark.dataset.mkIndex);
|
|
6761
|
+
mark.toggleAttribute("data-mk-active", index === selected);
|
|
6762
|
+
if (options.barFill === "spotlight") mark.style.fill = index === (selected ?? model.labels.length - 1) ? mark.style.getPropertyValue("--mk-bar-fill") : `url(#${uid2}-hatch)`;
|
|
6763
|
+
}
|
|
6695
6764
|
if (selected === null || !hasData()) {
|
|
6696
6765
|
if (!tooltip.hidden && !reduced()) {
|
|
6697
6766
|
gsap.killTweensOf(tooltip, "opacity,scale");
|
|
@@ -6716,6 +6785,24 @@ function createChart(root, initial = {}) {
|
|
|
6716
6785
|
for (const mark of canvas.querySelectorAll("[data-mk-index]")) if (mark.getAttribute("data-mk-index") !== String(i)) mark.setAttribute("data-mk-dim", "");
|
|
6717
6786
|
const { up, down } = totals(i);
|
|
6718
6787
|
anchorY = stacked() ? geometry.y(up || down) : Math.min(...model.series.map((series) => finite3(series.values[i]) ? geometry.y(series.values[i]) : geometry.bottom));
|
|
6788
|
+
if (options.barStyle === "pill") {
|
|
6789
|
+
const amount = stacked() ? up + down : model.series[0]?.values[i];
|
|
6790
|
+
if (finite3(amount)) {
|
|
6791
|
+
const label = format(amount), width = Math.max(40, label.length * 7 + 18);
|
|
6792
|
+
const bx = Math.max(0, Math.min(geometry.width - width, x - width / 2));
|
|
6793
|
+
const by = Math.max(0, anchorY - 32);
|
|
6794
|
+
const group = svg("g", { "data-mk-part": "bar-value" });
|
|
6795
|
+
group.append(svg("rect", { x: round(bx), y: round(by), width, height: 24, rx: 12 }));
|
|
6796
|
+
const text = svg("text", { x: round(bx + width / 2), y: round(by + 12), "text-anchor": "middle", "dominant-baseline": "middle" });
|
|
6797
|
+
text.textContent = label;
|
|
6798
|
+
group.append(text);
|
|
6799
|
+
cursor.append(group);
|
|
6800
|
+
const marker = svg("circle", { cx: round(x), cy: round(anchorY), r: 4, "data-mk-part": "marker" });
|
|
6801
|
+
marker.style.fill = model.series[0]?.color ?? "var(--mk-text)";
|
|
6802
|
+
cursor.append(marker);
|
|
6803
|
+
if (fresh && !reduced()) keep(gsap.fromTo(group, { opacity: 0, y: 6 }, { opacity: 1, y: 0, duration: 0.3, ease: EASE.pop }));
|
|
6804
|
+
}
|
|
6805
|
+
}
|
|
6719
6806
|
} else {
|
|
6720
6807
|
cursor.append(svg("line", { x1: round(x), x2: round(x), y1: geometry.top, y2: geometry.bottom, "data-mk-part": "guide" }));
|
|
6721
6808
|
model.series.forEach((series) => {
|
|
@@ -6798,6 +6885,7 @@ function createChart(root, initial = {}) {
|
|
|
6798
6885
|
glide?.kill();
|
|
6799
6886
|
canvas.setAttribute("aria-label", describe());
|
|
6800
6887
|
scope.attr(root, "data-mk-chart-type", type());
|
|
6888
|
+
scope.attr(root, "data-mk-bar-style", options.barStyle ?? "rounded");
|
|
6801
6889
|
renderTable();
|
|
6802
6890
|
renderLegend();
|
|
6803
6891
|
const ok = hasData();
|
|
@@ -6852,12 +6940,14 @@ function createChart(root, initial = {}) {
|
|
|
6852
6940
|
}
|
|
6853
6941
|
finish();
|
|
6854
6942
|
if (type() === "bar") {
|
|
6855
|
-
const
|
|
6943
|
+
const stagger = Math.min(0.045, 0.22 / Math.max(1, model.labels.length - 1));
|
|
6944
|
+
const length = 0.7 + stagger * (model.labels.length - 1);
|
|
6945
|
+
const state = { t: 0 }, ease = gsap.parseEase(EASE.swatch);
|
|
6856
6946
|
glide = gsap.to(state, {
|
|
6857
|
-
t:
|
|
6858
|
-
duration:
|
|
6859
|
-
ease:
|
|
6860
|
-
onUpdate: () => paint(target.map((list3) => list3.map((value) => finite3(value) ? value * state.t : value)), domain.lo, domain.hi, domain.step),
|
|
6947
|
+
t: length,
|
|
6948
|
+
duration: length,
|
|
6949
|
+
ease: "none",
|
|
6950
|
+
onUpdate: () => paint(target.map((list3) => list3.map((value, i) => finite3(value) ? value * Math.max(0, ease(Math.min(1, Math.max(0, (state.t - i * stagger) / 0.7)))) : value)), domain.lo, domain.hi, domain.step),
|
|
6861
6951
|
onComplete: () => {
|
|
6862
6952
|
finish();
|
|
6863
6953
|
settle();
|
|
@@ -8892,8 +8982,8 @@ function createStarRating(root, options = {}) {
|
|
|
8892
8982
|
const scope = createScope();
|
|
8893
8983
|
const max = Math.max(1, Math.min(10, Math.round(Number.isFinite(options.max) ? options.max : 5)));
|
|
8894
8984
|
const texts = options.labels ?? (max === 5 ? LABELS2 : []);
|
|
8895
|
-
const
|
|
8896
|
-
let value =
|
|
8985
|
+
const clamp5 = (n) => Math.max(0, Math.min(max, n));
|
|
8986
|
+
let value = clamp5(Number.isFinite(options.value) ? options.value : 0);
|
|
8897
8987
|
const name = options.name ?? `rating-${++sequence10}`;
|
|
8898
8988
|
const group = document.createElement("div");
|
|
8899
8989
|
group.dataset.mkStars = "";
|
|
@@ -8981,7 +9071,7 @@ function createStarRating(root, options = {}) {
|
|
|
8981
9071
|
};
|
|
8982
9072
|
const choose = (next, notify, animate) => {
|
|
8983
9073
|
if (scope.disposed) return;
|
|
8984
|
-
const target =
|
|
9074
|
+
const target = clamp5(Math.round(next));
|
|
8985
9075
|
if (target === value) return;
|
|
8986
9076
|
value = target;
|
|
8987
9077
|
paint();
|
|
@@ -13688,8 +13778,8 @@ function createDateTimePicker(root, options = {}) {
|
|
|
13688
13778
|
const segmentsOf2 = (date) => {
|
|
13689
13779
|
if (!date) return { day: null, month: null, year: null, hour: null, minute: null, dayPeriod: null };
|
|
13690
13780
|
const hour = date.getHours();
|
|
13691
|
-
const
|
|
13692
|
-
return { day: date.getDate(), month: date.getMonth() + 1, year: date.getFullYear(), hour:
|
|
13781
|
+
const clock2 = twelve ? to12(hour) : { hour, period: null };
|
|
13782
|
+
return { day: date.getDate(), month: date.getMonth() + 1, year: date.getFullYear(), hour: clock2.hour, minute: date.getMinutes(), dayPeriod: clock2.period };
|
|
13693
13783
|
};
|
|
13694
13784
|
const dateOf2 = (values) => {
|
|
13695
13785
|
const { day: day2, month, year, hour, minute } = values;
|
|
@@ -13738,18 +13828,18 @@ function createDateTimePicker(root, options = {}) {
|
|
|
13738
13828
|
scope.on(box, "focusout", (event) => {
|
|
13739
13829
|
if (!box.contains(event.relatedTarget) && field.element.hasAttribute("aria-invalid")) keep(shake(box));
|
|
13740
13830
|
});
|
|
13741
|
-
const
|
|
13831
|
+
const rounded2 = (date) => {
|
|
13742
13832
|
const result = new Date(date.getTime());
|
|
13743
13833
|
result.setSeconds(0, 0);
|
|
13744
13834
|
result.setMinutes(Math.round(result.getMinutes() / step) * step);
|
|
13745
13835
|
return result;
|
|
13746
13836
|
};
|
|
13747
|
-
const
|
|
13837
|
+
const clamp5 = (date) => min && date < min ? new Date(min.getTime()) : max && date > max ? new Date(max.getTime()) : date;
|
|
13748
13838
|
const timeOfDay = () => {
|
|
13749
13839
|
if (value) return { hour: value.getHours(), minute: value.getMinutes() };
|
|
13750
13840
|
const time2 = timeField.value?.split(":").map(Number);
|
|
13751
13841
|
if (time2 && time2.length >= 2) return { hour: time2[0], minute: time2[1] };
|
|
13752
|
-
const current3 =
|
|
13842
|
+
const current3 = rounded2(/* @__PURE__ */ new Date());
|
|
13753
13843
|
return { hour: current3.getHours(), minute: current3.getMinutes() };
|
|
13754
13844
|
};
|
|
13755
13845
|
const calendar = createRangeCalendar(calendarHost, {
|
|
@@ -13765,7 +13855,7 @@ function createDateTimePicker(root, options = {}) {
|
|
|
13765
13855
|
const { hour, minute } = timeOfDay();
|
|
13766
13856
|
const next = new Date(range.start.getTime());
|
|
13767
13857
|
next.setHours(hour, minute, 0, 0);
|
|
13768
|
-
commit(
|
|
13858
|
+
commit(clamp5(next), true);
|
|
13769
13859
|
}
|
|
13770
13860
|
});
|
|
13771
13861
|
scope.add(() => calendar.destroy());
|
|
@@ -13781,7 +13871,7 @@ function createDateTimePicker(root, options = {}) {
|
|
|
13781
13871
|
const base = value ?? toDate(options.today ?? /* @__PURE__ */ new Date());
|
|
13782
13872
|
const next = new Date(base.getTime());
|
|
13783
13873
|
next.setHours(hour, minute, 0, 0);
|
|
13784
|
-
commit(
|
|
13874
|
+
commit(clamp5(next), true);
|
|
13785
13875
|
}
|
|
13786
13876
|
});
|
|
13787
13877
|
scope.add(() => timeField.destroy());
|
|
@@ -13815,7 +13905,7 @@ function createDateTimePicker(root, options = {}) {
|
|
|
13815
13905
|
});
|
|
13816
13906
|
scope.on(now2, "click", () => {
|
|
13817
13907
|
keep(press(now2));
|
|
13818
|
-
const current3 =
|
|
13908
|
+
const current3 = rounded2(/* @__PURE__ */ new Date());
|
|
13819
13909
|
commit(problem(current3) ? value : current3, true);
|
|
13820
13910
|
calendar.focusDay(current3, false);
|
|
13821
13911
|
});
|
|
@@ -15303,15 +15393,15 @@ function createTreeView(root, options = {}) {
|
|
|
15303
15393
|
item.setAttribute("aria-posinset", String(index + 1));
|
|
15304
15394
|
item.tabIndex = -1;
|
|
15305
15395
|
if (node.disabled) item.setAttribute("aria-disabled", "true");
|
|
15306
|
-
const
|
|
15307
|
-
if (
|
|
15396
|
+
const branch2 = isBranch(node);
|
|
15397
|
+
if (branch2) item.setAttribute("aria-expanded", String(expanded.has(node.id)));
|
|
15308
15398
|
if (!options.checkable && selected === node.id) item.setAttribute("aria-selected", "true");
|
|
15309
15399
|
const line = document.createElement("div");
|
|
15310
15400
|
line.dataset.mkTreeRow = "";
|
|
15311
15401
|
line.style.setProperty("--mk-tree-depth", String(depth));
|
|
15312
15402
|
const chevron2 = document.createElement("span");
|
|
15313
15403
|
chevron2.dataset.mkTreeChevron = "";
|
|
15314
|
-
if (
|
|
15404
|
+
if (branch2) chevron2.innerHTML = CHEVRON3;
|
|
15315
15405
|
line.append(chevron2);
|
|
15316
15406
|
if (options.checkable) {
|
|
15317
15407
|
const check2 = document.createElement("span");
|
|
@@ -15327,9 +15417,9 @@ function createTreeView(root, options = {}) {
|
|
|
15327
15417
|
line.append(icon2);
|
|
15328
15418
|
} else if (options.icons) {
|
|
15329
15419
|
const icon2 = document.createElement("span");
|
|
15330
|
-
if (
|
|
15420
|
+
if (branch2) icon2.dataset.mkTreeFolder = "";
|
|
15331
15421
|
else icon2.dataset.mkTreePage = "";
|
|
15332
|
-
icon2.innerHTML =
|
|
15422
|
+
icon2.innerHTML = branch2 ? FOLDER : PAGE;
|
|
15333
15423
|
line.append(icon2);
|
|
15334
15424
|
}
|
|
15335
15425
|
const label = document.createElement("span");
|
|
@@ -15337,7 +15427,7 @@ function createTreeView(root, options = {}) {
|
|
|
15337
15427
|
fillLabel(node, label);
|
|
15338
15428
|
line.append(label);
|
|
15339
15429
|
item.append(line);
|
|
15340
|
-
if (
|
|
15430
|
+
if (branch2) {
|
|
15341
15431
|
const group = document.createElement("ul");
|
|
15342
15432
|
group.setAttribute("role", "group");
|
|
15343
15433
|
group.hidden = !expanded.has(node.id);
|
|
@@ -20932,6 +21022,7 @@ function createScrollIsland(root, options = {}) {
|
|
|
20932
21022
|
const idle2 = Number.isFinite(options.idle) ? Math.max(0, options.idle) : 900;
|
|
20933
21023
|
const marked3 = page ? document.documentElement : root;
|
|
20934
21024
|
scope.attr(marked3, "data-mk-scroll-island-host", "");
|
|
21025
|
+
scope.attr(root, "data-mk-ready", "");
|
|
20935
21026
|
const island = document.createElement("div");
|
|
20936
21027
|
island.dataset.mkScrollIsland = "";
|
|
20937
21028
|
island.dataset.mkState = "hidden";
|
|
@@ -20973,6 +21064,16 @@ function createScrollIsland(root, options = {}) {
|
|
|
20973
21064
|
let section;
|
|
20974
21065
|
let hideTimer;
|
|
20975
21066
|
let dragging = null;
|
|
21067
|
+
let scrollBehavior = null;
|
|
21068
|
+
const restoreBehavior = () => {
|
|
21069
|
+
if (!scrollBehavior) return;
|
|
21070
|
+
const previous = scrollBehavior;
|
|
21071
|
+
if (previous.value) scroller.style.setProperty("scroll-behavior", previous.value, previous.priority);
|
|
21072
|
+
else scroller.style.removeProperty("scroll-behavior");
|
|
21073
|
+
if (!previous.hadStyle && !scroller.getAttribute("style")) scroller.removeAttribute("style");
|
|
21074
|
+
scrollBehavior = null;
|
|
21075
|
+
};
|
|
21076
|
+
scope.add(restoreBehavior);
|
|
20976
21077
|
scope.add(() => clearTimeout(hideTimer));
|
|
20977
21078
|
const headings = () => options.sections === false ? [] : [...(page ? document.body : root).querySelectorAll(options.sections ?? "h2, h3")];
|
|
20978
21079
|
const currentSection = () => {
|
|
@@ -20987,7 +21088,7 @@ function createScrollIsland(root, options = {}) {
|
|
|
20987
21088
|
const size = as === "island" ? ISLAND_HEIGHT : Math.max(MIN_BAR, Math.min(height, height * (scroller.clientHeight / Math.max(1, scroller.scrollHeight))));
|
|
20988
21089
|
const top = (height - size) * progress();
|
|
20989
21090
|
if (as !== "island") return { top, height: size, width: BAR_WIDTH, borderRadius: BAR_WIDTH / 2 };
|
|
20990
|
-
return { top, height: size, width: Math.max(ISLAND_HEIGHT, content.scrollWidth + 28), borderRadius: size / 2 };
|
|
21091
|
+
return { top, height: size, width: Math.min(Math.max(ISLAND_HEIGHT, track().right - track().left - INSET * 2), Math.max(ISLAND_HEIGHT, content.scrollWidth + 28)), borderRadius: size / 2 };
|
|
20991
21092
|
};
|
|
20992
21093
|
const place3 = () => {
|
|
20993
21094
|
const box = track();
|
|
@@ -21024,7 +21125,7 @@ function createScrollIsland(root, options = {}) {
|
|
|
21024
21125
|
const settleLater = () => {
|
|
21025
21126
|
clearTimeout(hideTimer);
|
|
21026
21127
|
hideTimer = setTimeout(() => {
|
|
21027
|
-
if (state === "bar" && !dragging) go("hidden");
|
|
21128
|
+
if (state === "bar" && !dragging && !options.persistent) go("hidden");
|
|
21028
21129
|
}, idle2);
|
|
21029
21130
|
};
|
|
21030
21131
|
const onScroll = () => {
|
|
@@ -21073,6 +21174,8 @@ function createScrollIsland(root, options = {}) {
|
|
|
21073
21174
|
if (state !== "island" || down.button !== 0) return;
|
|
21074
21175
|
down.preventDefault();
|
|
21075
21176
|
down.stopPropagation();
|
|
21177
|
+
if (!scrollBehavior) scrollBehavior = { value: scroller.style.getPropertyValue("scroll-behavior"), priority: scroller.style.getPropertyPriority("scroll-behavior"), hadStyle: scroller.hasAttribute("style") };
|
|
21178
|
+
scroller.style.setProperty("scroll-behavior", "auto", "important");
|
|
21076
21179
|
const box = thumb.getBoundingClientRect();
|
|
21077
21180
|
dragging = { id: down.pointerId, offset: down.clientY - box.top || ISLAND_HEIGHT / 2 };
|
|
21078
21181
|
island.setAttribute("data-mk-dragging", "");
|
|
@@ -21084,6 +21187,7 @@ function createScrollIsland(root, options = {}) {
|
|
|
21084
21187
|
const release = (event) => {
|
|
21085
21188
|
if (!dragging || event.pointerId !== dragging.id) return;
|
|
21086
21189
|
dragging = null;
|
|
21190
|
+
restoreBehavior();
|
|
21087
21191
|
island.removeAttribute("data-mk-dragging");
|
|
21088
21192
|
};
|
|
21089
21193
|
scope.on(window, "pointerup", release);
|
|
@@ -21098,7 +21202,15 @@ function createScrollIsland(root, options = {}) {
|
|
|
21098
21202
|
scroller.scrollTo({ top: Math.round(Math.min(1, Math.max(0, ratio)) * range()), behavior: reduced() ? "auto" : "smooth" });
|
|
21099
21203
|
});
|
|
21100
21204
|
paintText();
|
|
21101
|
-
go("hidden");
|
|
21205
|
+
go(options.persistent ? "bar" : "hidden");
|
|
21206
|
+
if (typeof ResizeObserver === "function") {
|
|
21207
|
+
const observer = scope.observe(new ResizeObserver(() => {
|
|
21208
|
+
paintText();
|
|
21209
|
+
go(state, true);
|
|
21210
|
+
}));
|
|
21211
|
+
observer.observe(root);
|
|
21212
|
+
for (const child of root.children) observer.observe(child);
|
|
21213
|
+
}
|
|
21102
21214
|
return {
|
|
21103
21215
|
refresh: () => {
|
|
21104
21216
|
paintText();
|
|
@@ -21108,6 +21220,1377 @@ function createScrollIsland(root, options = {}) {
|
|
|
21108
21220
|
};
|
|
21109
21221
|
}
|
|
21110
21222
|
|
|
21223
|
+
// src/components/signature-pad/engine.ts
|
|
21224
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
21225
|
+
var MAX_STROKES = 500;
|
|
21226
|
+
var MAX_POINTS = 5e4;
|
|
21227
|
+
var emptyData = () => ({ version: 1, strokes: [] });
|
|
21228
|
+
var cloneStrokes = (strokes) => strokes.map((stroke) => ({ ...stroke, points: stroke.points.map((point) => ({ ...point })) }));
|
|
21229
|
+
var sameStrokes = (left, right) => left.length === right.length && left.every((stroke, index) => {
|
|
21230
|
+
const other = right[index];
|
|
21231
|
+
return stroke.color === other.color && stroke.width === other.width && stroke.points.length === other.points.length && stroke.points.every((point, index2) => point.x === other.points[index2].x && point.y === other.points[index2].y);
|
|
21232
|
+
});
|
|
21233
|
+
var finite5 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
21234
|
+
var clamp4 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
21235
|
+
function validColor(value) {
|
|
21236
|
+
if (typeof value !== "string" || value.length > 100) return false;
|
|
21237
|
+
if (/^#(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i.test(value)) return true;
|
|
21238
|
+
if (!/^(?:rgba?|hsla?)\([\d\s.,%/+\-degratun]+\)$/i.test(value) && !/^[a-z]+$/i.test(value)) return false;
|
|
21239
|
+
if (/^(?:inherit|initial|unset|revert|revertlayer|currentcolor)$/i.test(value)) return false;
|
|
21240
|
+
if (typeof document === "undefined") return /^(?:black|white|transparent)$/i.test(value);
|
|
21241
|
+
const probe = document.createElement("span");
|
|
21242
|
+
probe.style.color = value;
|
|
21243
|
+
return probe.style.color !== "";
|
|
21244
|
+
}
|
|
21245
|
+
function validatedData(value) {
|
|
21246
|
+
if (!value || typeof value !== "object") return null;
|
|
21247
|
+
const data = value;
|
|
21248
|
+
if (data.version !== 1 || !Array.isArray(data.strokes) || data.strokes.length > MAX_STROKES) return null;
|
|
21249
|
+
const strokes = [];
|
|
21250
|
+
let count = 0;
|
|
21251
|
+
for (const candidate of data.strokes) {
|
|
21252
|
+
if (!candidate || typeof candidate !== "object") return null;
|
|
21253
|
+
const stroke = candidate;
|
|
21254
|
+
if (!validColor(stroke.color) || !finite5(stroke.width) || stroke.width < 0.1 || stroke.width > 64 || !Array.isArray(stroke.points) || !stroke.points.length) return null;
|
|
21255
|
+
count += stroke.points.length;
|
|
21256
|
+
if (count > MAX_POINTS) return null;
|
|
21257
|
+
const points = [];
|
|
21258
|
+
for (const candidate2 of stroke.points) {
|
|
21259
|
+
if (!candidate2 || typeof candidate2 !== "object") return null;
|
|
21260
|
+
const point = candidate2;
|
|
21261
|
+
if (!finite5(point.x) || !finite5(point.y) || point.x < 0 || point.x > 1 || point.y < 0 || point.y > 1) return null;
|
|
21262
|
+
points.push({ x: point.x, y: point.y });
|
|
21263
|
+
}
|
|
21264
|
+
strokes.push({ color: stroke.color, width: stroke.width, points });
|
|
21265
|
+
}
|
|
21266
|
+
return { version: 1, strokes };
|
|
21267
|
+
}
|
|
21268
|
+
var rounded = (value) => Number(value.toFixed(3));
|
|
21269
|
+
function strokePath(points, width, height) {
|
|
21270
|
+
const coordinates = points.map((point) => [rounded(point.x * width), rounded(point.y * height)]);
|
|
21271
|
+
const first = coordinates[0];
|
|
21272
|
+
let path = `M ${first[0]} ${first[1]}`;
|
|
21273
|
+
if (coordinates.length === 1) return `${path} l 0.001 0`;
|
|
21274
|
+
for (let i = 1; i < coordinates.length - 1; i++) {
|
|
21275
|
+
const current3 = coordinates[i];
|
|
21276
|
+
const next = coordinates[i + 1];
|
|
21277
|
+
path += ` Q ${current3[0]} ${current3[1]} ${rounded((current3[0] + next[0]) / 2)} ${rounded((current3[1] + next[1]) / 2)}`;
|
|
21278
|
+
}
|
|
21279
|
+
const last = coordinates[coordinates.length - 1];
|
|
21280
|
+
return `${path} L ${last[0]} ${last[1]}`;
|
|
21281
|
+
}
|
|
21282
|
+
function makePath(stroke, width, height) {
|
|
21283
|
+
const path = document.createElementNS(SVG_NS, "path");
|
|
21284
|
+
path.setAttribute("d", strokePath(stroke.points, width, height));
|
|
21285
|
+
path.setAttribute("fill", "none");
|
|
21286
|
+
path.setAttribute("stroke", stroke.color);
|
|
21287
|
+
path.setAttribute("stroke-width", String(stroke.width));
|
|
21288
|
+
path.setAttribute("stroke-linecap", "round");
|
|
21289
|
+
path.setAttribute("stroke-linejoin", "round");
|
|
21290
|
+
return path;
|
|
21291
|
+
}
|
|
21292
|
+
var nextId2 = 0;
|
|
21293
|
+
function createSignaturePad(root, options = {}) {
|
|
21294
|
+
if (!root) return inert({
|
|
21295
|
+
data: emptyData(),
|
|
21296
|
+
isEmpty: true,
|
|
21297
|
+
canUndo: false,
|
|
21298
|
+
canRedo: false,
|
|
21299
|
+
undo() {
|
|
21300
|
+
},
|
|
21301
|
+
redo() {
|
|
21302
|
+
},
|
|
21303
|
+
clear() {
|
|
21304
|
+
},
|
|
21305
|
+
importData: () => false,
|
|
21306
|
+
exportData: emptyData,
|
|
21307
|
+
exportSVG: () => "",
|
|
21308
|
+
exportPNG: async () => null,
|
|
21309
|
+
setDisabled() {
|
|
21310
|
+
},
|
|
21311
|
+
setReadOnly() {
|
|
21312
|
+
}
|
|
21313
|
+
});
|
|
21314
|
+
registerMotion();
|
|
21315
|
+
const scope = createScope();
|
|
21316
|
+
let strokes = validatedData(options.data)?.strokes ?? [];
|
|
21317
|
+
const initialStrokes = cloneStrokes(strokes);
|
|
21318
|
+
let disabled = Boolean(options.disabled);
|
|
21319
|
+
let readOnly = Boolean(options.readOnly);
|
|
21320
|
+
let undoStack = [];
|
|
21321
|
+
let redoStack = [];
|
|
21322
|
+
const historyLimit = finite5(options.historyLimit) ? clamp4(Math.floor(options.historyLimit), 1, 100) : 50;
|
|
21323
|
+
const inkWidth = finite5(options.width) ? clamp4(options.width, 0.1, 64) : 2.4;
|
|
21324
|
+
const exportData = () => ({ version: 1, strokes: cloneStrokes(strokes) });
|
|
21325
|
+
const wrapper = document.createElement("div");
|
|
21326
|
+
wrapper.dataset.mkSignatureBody = "";
|
|
21327
|
+
const surface = document.createElement("div");
|
|
21328
|
+
surface.dataset.mkSignatureSurface = "";
|
|
21329
|
+
const svg2 = document.createElementNS(SVG_NS, "svg");
|
|
21330
|
+
svg2.dataset.mkSignatureDrawing = "";
|
|
21331
|
+
svg2.setAttribute("role", "img");
|
|
21332
|
+
svg2.setAttribute("aria-label", options.label ?? "\xC1rea de firma");
|
|
21333
|
+
svg2.setAttribute("preserveAspectRatio", "none");
|
|
21334
|
+
const placeholder2 = document.createElement("span");
|
|
21335
|
+
placeholder2.dataset.mkSignaturePlaceholder = "";
|
|
21336
|
+
placeholder2.setAttribute("aria-hidden", "true");
|
|
21337
|
+
placeholder2.textContent = options.placeholder ?? "Firma aqu\xED";
|
|
21338
|
+
surface.append(svg2, placeholder2);
|
|
21339
|
+
const footer = document.createElement("div");
|
|
21340
|
+
footer.dataset.mkSignatureFooter = "";
|
|
21341
|
+
const toolbar = document.createElement("div");
|
|
21342
|
+
toolbar.dataset.mkSignatureToolbar = "";
|
|
21343
|
+
toolbar.setAttribute("role", "group");
|
|
21344
|
+
toolbar.setAttribute("aria-label", "Herramientas de firma");
|
|
21345
|
+
const makeButton = (action, text) => {
|
|
21346
|
+
const button2 = document.createElement("button");
|
|
21347
|
+
button2.type = "button";
|
|
21348
|
+
button2.dataset.mkSignatureAction = action;
|
|
21349
|
+
button2.textContent = text;
|
|
21350
|
+
toolbar.append(button2);
|
|
21351
|
+
return button2;
|
|
21352
|
+
};
|
|
21353
|
+
const undoButton = makeButton("undo", "Deshacer");
|
|
21354
|
+
const redoButton = makeButton("redo", "Rehacer");
|
|
21355
|
+
const clearButton = makeButton("clear", "Limpiar");
|
|
21356
|
+
if (options.toolbar !== false) footer.append(toolbar);
|
|
21357
|
+
const status = document.createElement("span");
|
|
21358
|
+
status.dataset.mkSignatureStatus = "";
|
|
21359
|
+
status.setAttribute("role", "status");
|
|
21360
|
+
status.setAttribute("aria-live", "polite");
|
|
21361
|
+
footer.append(status);
|
|
21362
|
+
const hint = document.createElement("p");
|
|
21363
|
+
hint.dataset.mkSignatureHint = "";
|
|
21364
|
+
hint.id = `mk-signature-hint-${++nextId2}`;
|
|
21365
|
+
hint.textContent = options.hint ?? "Dibuja con el rat\xF3n, el dedo o un l\xE1piz. Puedes deshacer cada trazo.";
|
|
21366
|
+
svg2.setAttribute("aria-describedby", hint.id);
|
|
21367
|
+
wrapper.append(surface, footer, hint);
|
|
21368
|
+
let hidden = null;
|
|
21369
|
+
if (options.name) {
|
|
21370
|
+
hidden = document.createElement("input");
|
|
21371
|
+
hidden.type = "hidden";
|
|
21372
|
+
hidden.name = options.name;
|
|
21373
|
+
wrapper.append(hidden);
|
|
21374
|
+
}
|
|
21375
|
+
root.append(wrapper);
|
|
21376
|
+
scope.add(() => wrapper.remove());
|
|
21377
|
+
for (const name of ["data-mk-disabled", "data-mk-readonly", "data-mk-drawing", "data-mk-empty"]) scope.attr(root, name, null);
|
|
21378
|
+
scope.attr(root, "data-mk-ready", "");
|
|
21379
|
+
let dimensions = { width: 640, height: 240 };
|
|
21380
|
+
let active = null;
|
|
21381
|
+
let feedback = null;
|
|
21382
|
+
const locked = () => disabled || readOnly;
|
|
21383
|
+
const update = () => {
|
|
21384
|
+
root.toggleAttribute("data-mk-empty", !strokes.length && !active);
|
|
21385
|
+
root.toggleAttribute("data-mk-disabled", disabled);
|
|
21386
|
+
root.toggleAttribute("data-mk-readonly", readOnly);
|
|
21387
|
+
svg2.setAttribute("aria-disabled", String(disabled));
|
|
21388
|
+
placeholder2.hidden = strokes.length > 0 || active !== null;
|
|
21389
|
+
undoButton.disabled = locked() || !undoStack.length;
|
|
21390
|
+
redoButton.disabled = locked() || !redoStack.length;
|
|
21391
|
+
clearButton.disabled = locked() || !strokes.length;
|
|
21392
|
+
status.textContent = strokes.length ? `${strokes.length} ${strokes.length === 1 ? "trazo" : "trazos"} \xB7 ${readOnly ? "Solo lectura" : "Firma capturada"}` : "Sin firma";
|
|
21393
|
+
if (hidden) {
|
|
21394
|
+
hidden.disabled = disabled;
|
|
21395
|
+
hidden.value = JSON.stringify(exportData());
|
|
21396
|
+
}
|
|
21397
|
+
};
|
|
21398
|
+
const render = () => {
|
|
21399
|
+
const rect = surface.getBoundingClientRect();
|
|
21400
|
+
if (rect.width > 0 && rect.height > 0) dimensions = { width: rect.width, height: rect.height };
|
|
21401
|
+
svg2.setAttribute("viewBox", `0 0 ${dimensions.width} ${dimensions.height}`);
|
|
21402
|
+
svg2.replaceChildren(...strokes.map((stroke) => makePath(stroke, dimensions.width, dimensions.height)));
|
|
21403
|
+
if (active) {
|
|
21404
|
+
active.path = makePath(active.stroke, dimensions.width, dimensions.height);
|
|
21405
|
+
svg2.append(active.path);
|
|
21406
|
+
}
|
|
21407
|
+
};
|
|
21408
|
+
const emit = (reason) => {
|
|
21409
|
+
const detail = { data: exportData(), reason, isEmpty: !strokes.length, canUndo: !!undoStack.length, canRedo: !!redoStack.length };
|
|
21410
|
+
options.onChange?.(exportData(), { ...detail, data: exportData() });
|
|
21411
|
+
if (scope.disposed) return;
|
|
21412
|
+
root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail }));
|
|
21413
|
+
};
|
|
21414
|
+
const release = (pointerId) => {
|
|
21415
|
+
try {
|
|
21416
|
+
surface.releasePointerCapture?.(pointerId);
|
|
21417
|
+
} catch {
|
|
21418
|
+
}
|
|
21419
|
+
};
|
|
21420
|
+
const cancel = () => {
|
|
21421
|
+
if (!active) return;
|
|
21422
|
+
const pointerId = active.pointerId;
|
|
21423
|
+
active = null;
|
|
21424
|
+
root.removeAttribute("data-mk-drawing");
|
|
21425
|
+
release(pointerId);
|
|
21426
|
+
render();
|
|
21427
|
+
update();
|
|
21428
|
+
};
|
|
21429
|
+
const remember = () => {
|
|
21430
|
+
undoStack.push(strokes);
|
|
21431
|
+
if (undoStack.length > historyLimit) undoStack.shift();
|
|
21432
|
+
redoStack = [];
|
|
21433
|
+
};
|
|
21434
|
+
const pulse = (button2) => {
|
|
21435
|
+
feedback?.progress(1).kill();
|
|
21436
|
+
if (reduced()) return;
|
|
21437
|
+
feedback = gsap.fromTo(button2, { scale: 0.95 }, { scale: 1, duration: 0.24, ease: EASE.click });
|
|
21438
|
+
};
|
|
21439
|
+
const undo = () => {
|
|
21440
|
+
if (scope.disposed) return;
|
|
21441
|
+
cancel();
|
|
21442
|
+
if (!undoStack.length) return;
|
|
21443
|
+
redoStack.push(strokes);
|
|
21444
|
+
strokes = undoStack.pop();
|
|
21445
|
+
render();
|
|
21446
|
+
update();
|
|
21447
|
+
emit("undo");
|
|
21448
|
+
};
|
|
21449
|
+
const redo = () => {
|
|
21450
|
+
if (scope.disposed) return;
|
|
21451
|
+
cancel();
|
|
21452
|
+
if (!redoStack.length) return;
|
|
21453
|
+
undoStack.push(strokes);
|
|
21454
|
+
strokes = redoStack.pop();
|
|
21455
|
+
render();
|
|
21456
|
+
update();
|
|
21457
|
+
emit("redo");
|
|
21458
|
+
};
|
|
21459
|
+
const clear = () => {
|
|
21460
|
+
if (scope.disposed) return;
|
|
21461
|
+
cancel();
|
|
21462
|
+
if (!strokes.length) return;
|
|
21463
|
+
remember();
|
|
21464
|
+
strokes = [];
|
|
21465
|
+
render();
|
|
21466
|
+
update();
|
|
21467
|
+
emit("clear");
|
|
21468
|
+
};
|
|
21469
|
+
const form = hidden?.form;
|
|
21470
|
+
if (form) scope.on(form, "reset", (event) => {
|
|
21471
|
+
scope.timeout(() => {
|
|
21472
|
+
if (scope.disposed || event.defaultPrevented || hidden?.form !== form) return;
|
|
21473
|
+
const changed = !sameStrokes(strokes, initialStrokes);
|
|
21474
|
+
cancel();
|
|
21475
|
+
strokes = cloneStrokes(initialStrokes);
|
|
21476
|
+
undoStack = [];
|
|
21477
|
+
redoStack = [];
|
|
21478
|
+
render();
|
|
21479
|
+
update();
|
|
21480
|
+
if (changed) emit("reset");
|
|
21481
|
+
}, 0);
|
|
21482
|
+
});
|
|
21483
|
+
const pointFrom = (event) => {
|
|
21484
|
+
const rect = surface.getBoundingClientRect();
|
|
21485
|
+
if (!rect.width || !rect.height || !finite5(event.clientX) || !finite5(event.clientY)) return null;
|
|
21486
|
+
return { x: clamp4((event.clientX - rect.left) / rect.width, 0, 1), y: clamp4((event.clientY - rect.top) / rect.height, 0, 1) };
|
|
21487
|
+
};
|
|
21488
|
+
const addPoint = (event) => {
|
|
21489
|
+
if (!active) return;
|
|
21490
|
+
const point = pointFrom(event);
|
|
21491
|
+
if (!point || active.stroke.points.length >= MAX_POINTS - strokes.reduce((sum, stroke) => sum + stroke.points.length, 0)) return;
|
|
21492
|
+
const last = active.stroke.points[active.stroke.points.length - 1];
|
|
21493
|
+
if (point.x === last.x && point.y === last.y) return;
|
|
21494
|
+
active.stroke.points.push(point);
|
|
21495
|
+
active.path.setAttribute("d", strokePath(active.stroke.points, dimensions.width, dimensions.height));
|
|
21496
|
+
};
|
|
21497
|
+
scope.on(surface, "pointerdown", (event) => {
|
|
21498
|
+
const pointer2 = event;
|
|
21499
|
+
if (locked() || active || pointer2.button !== 0 || pointer2.isPrimary === false || strokes.length >= MAX_STROKES || strokes.reduce((sum, stroke2) => sum + stroke2.points.length, 0) >= MAX_POINTS) return;
|
|
21500
|
+
const point = pointFrom(pointer2);
|
|
21501
|
+
if (!point) return;
|
|
21502
|
+
pointer2.preventDefault();
|
|
21503
|
+
const themed = getComputedStyle(root).getPropertyValue("--mk-signature-ink").trim() || getComputedStyle(root).color;
|
|
21504
|
+
const color = validColor(options.color) ? options.color : validColor(themed) ? themed : "#252735";
|
|
21505
|
+
const stroke = { points: [point], color, width: inkWidth };
|
|
21506
|
+
active = { pointerId: pointer2.pointerId, stroke, path: makePath(stroke, dimensions.width, dimensions.height) };
|
|
21507
|
+
render();
|
|
21508
|
+
update();
|
|
21509
|
+
root.setAttribute("data-mk-drawing", "");
|
|
21510
|
+
try {
|
|
21511
|
+
surface.setPointerCapture?.(pointer2.pointerId);
|
|
21512
|
+
} catch {
|
|
21513
|
+
}
|
|
21514
|
+
});
|
|
21515
|
+
scope.on(window, "pointermove", (event) => {
|
|
21516
|
+
const pointer2 = event;
|
|
21517
|
+
if (!active || pointer2.pointerId !== active.pointerId) return;
|
|
21518
|
+
pointer2.preventDefault();
|
|
21519
|
+
const samples = typeof pointer2.getCoalescedEvents === "function" ? pointer2.getCoalescedEvents() : [];
|
|
21520
|
+
for (const sample of samples) addPoint(sample);
|
|
21521
|
+
addPoint(pointer2);
|
|
21522
|
+
}, { passive: false });
|
|
21523
|
+
scope.on(window, "pointerup", (event) => {
|
|
21524
|
+
const pointer2 = event;
|
|
21525
|
+
if (!active || pointer2.pointerId !== active.pointerId) return;
|
|
21526
|
+
addPoint(pointer2);
|
|
21527
|
+
const completed = active;
|
|
21528
|
+
active = null;
|
|
21529
|
+
root.removeAttribute("data-mk-drawing");
|
|
21530
|
+
release(completed.pointerId);
|
|
21531
|
+
remember();
|
|
21532
|
+
strokes = [...strokes, completed.stroke];
|
|
21533
|
+
update();
|
|
21534
|
+
emit("draw");
|
|
21535
|
+
});
|
|
21536
|
+
for (const type of ["pointercancel", "lostpointercapture"]) scope.on(type === "pointercancel" ? window : surface, type, (event) => {
|
|
21537
|
+
if (active?.pointerId === event.pointerId) cancel();
|
|
21538
|
+
});
|
|
21539
|
+
scope.on(window, "blur", cancel);
|
|
21540
|
+
scope.on(document, "visibilitychange", () => {
|
|
21541
|
+
if (document.hidden) cancel();
|
|
21542
|
+
});
|
|
21543
|
+
for (const [button2, action] of [[undoButton, undo], [redoButton, redo], [clearButton, clear]]) scope.on(button2, "click", () => {
|
|
21544
|
+
if (locked() || button2.disabled) return;
|
|
21545
|
+
pulse(button2);
|
|
21546
|
+
action();
|
|
21547
|
+
});
|
|
21548
|
+
if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(render)).observe(surface);
|
|
21549
|
+
scope.on(window, "resize", render);
|
|
21550
|
+
scope.add(() => {
|
|
21551
|
+
cancel();
|
|
21552
|
+
feedback?.kill();
|
|
21553
|
+
});
|
|
21554
|
+
render();
|
|
21555
|
+
update();
|
|
21556
|
+
const exportSVG = (settings = {}) => {
|
|
21557
|
+
const width = finite5(settings.width) ? clamp4(settings.width, 1, 4096) : dimensions.width;
|
|
21558
|
+
const height = finite5(settings.height) ? clamp4(settings.height, 1, 4096) : dimensions.height;
|
|
21559
|
+
const output = document.createElementNS(SVG_NS, "svg");
|
|
21560
|
+
output.setAttribute("width", String(rounded(width)));
|
|
21561
|
+
output.setAttribute("height", String(rounded(height)));
|
|
21562
|
+
output.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
21563
|
+
if (validColor(settings.background)) {
|
|
21564
|
+
const background = document.createElementNS(SVG_NS, "rect");
|
|
21565
|
+
background.setAttribute("width", "100%");
|
|
21566
|
+
background.setAttribute("height", "100%");
|
|
21567
|
+
background.setAttribute("fill", settings.background);
|
|
21568
|
+
output.append(background);
|
|
21569
|
+
}
|
|
21570
|
+
output.append(...strokes.map((stroke) => makePath(stroke, width, height)));
|
|
21571
|
+
return new XMLSerializer().serializeToString(output);
|
|
21572
|
+
};
|
|
21573
|
+
const pending = /* @__PURE__ */ new Set();
|
|
21574
|
+
scope.add(() => {
|
|
21575
|
+
for (const cancelExport of pending) cancelExport();
|
|
21576
|
+
pending.clear();
|
|
21577
|
+
});
|
|
21578
|
+
return {
|
|
21579
|
+
get data() {
|
|
21580
|
+
return exportData();
|
|
21581
|
+
},
|
|
21582
|
+
get isEmpty() {
|
|
21583
|
+
return !strokes.length;
|
|
21584
|
+
},
|
|
21585
|
+
get canUndo() {
|
|
21586
|
+
return !!undoStack.length;
|
|
21587
|
+
},
|
|
21588
|
+
get canRedo() {
|
|
21589
|
+
return !!redoStack.length;
|
|
21590
|
+
},
|
|
21591
|
+
undo,
|
|
21592
|
+
redo,
|
|
21593
|
+
clear,
|
|
21594
|
+
exportData,
|
|
21595
|
+
importData(value, notify = true) {
|
|
21596
|
+
if (scope.disposed) return false;
|
|
21597
|
+
const next = validatedData(value);
|
|
21598
|
+
if (!next) return false;
|
|
21599
|
+
if (sameStrokes(next.strokes, strokes)) return true;
|
|
21600
|
+
cancel();
|
|
21601
|
+
strokes = next.strokes;
|
|
21602
|
+
undoStack = [];
|
|
21603
|
+
redoStack = [];
|
|
21604
|
+
render();
|
|
21605
|
+
update();
|
|
21606
|
+
if (notify) emit("import");
|
|
21607
|
+
return true;
|
|
21608
|
+
},
|
|
21609
|
+
exportSVG: (settings) => scope.disposed ? "" : exportSVG(settings),
|
|
21610
|
+
exportPNG(settings = {}) {
|
|
21611
|
+
if (scope.disposed) return Promise.resolve(null);
|
|
21612
|
+
const canvas = document.createElement("canvas");
|
|
21613
|
+
let context;
|
|
21614
|
+
try {
|
|
21615
|
+
context = canvas.getContext("2d");
|
|
21616
|
+
} catch {
|
|
21617
|
+
return Promise.resolve(null);
|
|
21618
|
+
}
|
|
21619
|
+
if (!context || typeof canvas.toBlob !== "function") return Promise.resolve(null);
|
|
21620
|
+
const scale = finite5(settings.scale) ? clamp4(settings.scale, 1, 4) : 2;
|
|
21621
|
+
canvas.width = Math.round((finite5(settings.width) ? clamp4(settings.width, 1, 4096) : dimensions.width) * scale);
|
|
21622
|
+
canvas.height = Math.round((finite5(settings.height) ? clamp4(settings.height, 1, 4096) : dimensions.height) * scale);
|
|
21623
|
+
return new Promise((resolve2) => {
|
|
21624
|
+
const image = new Image();
|
|
21625
|
+
let finished = false;
|
|
21626
|
+
const done = (blob) => {
|
|
21627
|
+
if (finished) return;
|
|
21628
|
+
finished = true;
|
|
21629
|
+
image.onload = null;
|
|
21630
|
+
image.onerror = null;
|
|
21631
|
+
pending.delete(cancelExport);
|
|
21632
|
+
clearTimeout(timer2);
|
|
21633
|
+
resolve2(scope.disposed ? null : blob);
|
|
21634
|
+
};
|
|
21635
|
+
const cancelExport = () => {
|
|
21636
|
+
done(null);
|
|
21637
|
+
image.src = "";
|
|
21638
|
+
};
|
|
21639
|
+
const timer2 = setTimeout(cancelExport, 1e4);
|
|
21640
|
+
pending.add(cancelExport);
|
|
21641
|
+
image.onerror = () => done(null);
|
|
21642
|
+
image.onload = () => {
|
|
21643
|
+
try {
|
|
21644
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
21645
|
+
canvas.toBlob(done, "image/png");
|
|
21646
|
+
} catch {
|
|
21647
|
+
done(null);
|
|
21648
|
+
}
|
|
21649
|
+
};
|
|
21650
|
+
image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(exportSVG(settings))}`;
|
|
21651
|
+
});
|
|
21652
|
+
},
|
|
21653
|
+
setDisabled(value) {
|
|
21654
|
+
if (!scope.disposed) {
|
|
21655
|
+
cancel();
|
|
21656
|
+
disabled = Boolean(value);
|
|
21657
|
+
update();
|
|
21658
|
+
}
|
|
21659
|
+
},
|
|
21660
|
+
setReadOnly(value) {
|
|
21661
|
+
if (!scope.disposed) {
|
|
21662
|
+
cancel();
|
|
21663
|
+
readOnly = Boolean(value);
|
|
21664
|
+
update();
|
|
21665
|
+
}
|
|
21666
|
+
},
|
|
21667
|
+
destroy: () => scope.dispose()
|
|
21668
|
+
};
|
|
21669
|
+
}
|
|
21670
|
+
|
|
21671
|
+
// src/components/waveform-player/engine.ts
|
|
21672
|
+
var initialState = () => ({ status: "idle", currentTime: 0, duration: 0, playbackRate: 1, error: null });
|
|
21673
|
+
var finite6 = (n) => Number.isFinite(n) && n >= 0;
|
|
21674
|
+
var clock = (n) => `${Math.floor(n / 60)}:${String(Math.floor(n % 60)).padStart(2, "0")}`;
|
|
21675
|
+
var playIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m9 6 9 6-9 6Z"/></svg>';
|
|
21676
|
+
var pauseIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M8 6v12M16 6v12"/></svg>';
|
|
21677
|
+
function createWaveformPlayer(root, options = {}) {
|
|
21678
|
+
if (!root) return inert({ play: async () => false, pause() {
|
|
21679
|
+
}, seek() {
|
|
21680
|
+
}, update() {
|
|
21681
|
+
}, state: initialState(), audio: null });
|
|
21682
|
+
registerMotion();
|
|
21683
|
+
const scope = createScope();
|
|
21684
|
+
let opts = { ...options };
|
|
21685
|
+
let state = initialState();
|
|
21686
|
+
let source = "";
|
|
21687
|
+
let request = 0;
|
|
21688
|
+
let requested = false;
|
|
21689
|
+
let pending = null;
|
|
21690
|
+
const make = (tag, part3, parent = root) => {
|
|
21691
|
+
const el5 = document.createElement(tag);
|
|
21692
|
+
el5.setAttribute(`data-mk-wave-${part3}`, "");
|
|
21693
|
+
parent.append(el5);
|
|
21694
|
+
return el5;
|
|
21695
|
+
};
|
|
21696
|
+
const container = make("div", "content");
|
|
21697
|
+
scope.add(() => container.remove());
|
|
21698
|
+
const audio = make("audio", "audio", container);
|
|
21699
|
+
audio.preload = "metadata";
|
|
21700
|
+
audio.hidden = true;
|
|
21701
|
+
const toggle = make("button", "toggle", container);
|
|
21702
|
+
toggle.type = "button";
|
|
21703
|
+
const body = make("div", "body", container);
|
|
21704
|
+
const track = make("div", "track", body);
|
|
21705
|
+
const bars = make("div", "bars", track);
|
|
21706
|
+
bars.setAttribute("aria-hidden", "true");
|
|
21707
|
+
const range = make("input", "seek", track);
|
|
21708
|
+
range.type = "range";
|
|
21709
|
+
range.min = "0";
|
|
21710
|
+
range.max = "0";
|
|
21711
|
+
range.step = "0.1";
|
|
21712
|
+
const footer = make("div", "footer", body);
|
|
21713
|
+
const time2 = make("span", "time", footer);
|
|
21714
|
+
const rate = make("button", "rate", footer);
|
|
21715
|
+
rate.type = "button";
|
|
21716
|
+
const message = make("span", "message", container);
|
|
21717
|
+
message.setAttribute("role", "status");
|
|
21718
|
+
message.setAttribute("aria-live", "polite");
|
|
21719
|
+
scope.attr(root, "data-mk-ready", "");
|
|
21720
|
+
scope.attr(root, "data-mk-wave-state", "idle");
|
|
21721
|
+
let barNodes = [];
|
|
21722
|
+
let effect;
|
|
21723
|
+
const snapshot = () => ({ ...state });
|
|
21724
|
+
const rates = () => {
|
|
21725
|
+
const values = opts.playbackRates === false ? [] : opts.playbackRates ?? [1, 1.5, 2];
|
|
21726
|
+
return Array.isArray(values) ? [...new Set(values.filter((n) => typeof n === "number" && Number.isFinite(n) && n >= 0.25 && n <= 4))] : [];
|
|
21727
|
+
};
|
|
21728
|
+
const paint = () => {
|
|
21729
|
+
const playing = state.status === "playing";
|
|
21730
|
+
toggle.innerHTML = playing || requested ? pauseIcon : playIcon;
|
|
21731
|
+
toggle.setAttribute("aria-label", `${playing || requested ? "Pausar" : "Reproducir"} ${opts.label ?? "audio"}`);
|
|
21732
|
+
toggle.disabled = !!opts.disabled || !source;
|
|
21733
|
+
range.disabled = !!opts.disabled || !state.duration;
|
|
21734
|
+
range.max = String(state.duration);
|
|
21735
|
+
range.value = String(state.currentTime);
|
|
21736
|
+
range.setAttribute("aria-label", `Posici\xF3n de ${opts.label ?? "audio"}`);
|
|
21737
|
+
range.setAttribute("aria-valuetext", `${clock(state.currentTime)} de ${clock(state.duration)}`);
|
|
21738
|
+
time2.textContent = `${clock(state.currentTime)} / ${clock(state.duration)}`;
|
|
21739
|
+
rate.hidden = rates().length < 2;
|
|
21740
|
+
rate.disabled = !!opts.disabled;
|
|
21741
|
+
rate.textContent = `${state.playbackRate}\xD7`;
|
|
21742
|
+
rate.setAttribute("aria-label", `Velocidad ${state.playbackRate}\xD7. Cambiar velocidad`);
|
|
21743
|
+
const progress = state.duration ? state.currentTime / state.duration : 0;
|
|
21744
|
+
barNodes.forEach((bar, i) => bar.toggleAttribute("data-mk-played", (i + 0.5) / barNodes.length <= progress));
|
|
21745
|
+
root.setAttribute("data-mk-wave-state", state.status);
|
|
21746
|
+
message.textContent = state.error ?? (state.status === "loading" ? "Cargando audio\u2026" : state.status === "ended" ? "Audio finalizado" : "");
|
|
21747
|
+
};
|
|
21748
|
+
const emit = (patch, event) => {
|
|
21749
|
+
if (scope.disposed) return;
|
|
21750
|
+
const previous = state.status;
|
|
21751
|
+
state = { ...state, ...patch };
|
|
21752
|
+
paint();
|
|
21753
|
+
const next = snapshot();
|
|
21754
|
+
if (event === "timeupdate") opts.onTimeUpdate?.(next);
|
|
21755
|
+
if (previous !== state.status) opts.onStateChange?.(snapshot());
|
|
21756
|
+
if (event === "play") opts.onPlay?.(snapshot());
|
|
21757
|
+
if (event === "pause") opts.onPause?.(snapshot());
|
|
21758
|
+
if (event === "ended") opts.onEnded?.(snapshot());
|
|
21759
|
+
if (event === "error") opts.onError?.(snapshot());
|
|
21760
|
+
if (previous !== state.status) root.dispatchEvent(new CustomEvent("mk:audio-statechange", { bubbles: true, detail: snapshot() }));
|
|
21761
|
+
if (event) root.dispatchEvent(new CustomEvent(`mk:audio-${event}`, { bubbles: true, detail: snapshot() }));
|
|
21762
|
+
};
|
|
21763
|
+
const bounce = (target) => {
|
|
21764
|
+
if (reduced()) return;
|
|
21765
|
+
effect?.progress(1);
|
|
21766
|
+
effect?.kill();
|
|
21767
|
+
effect = gsap.fromTo(target, { scale: 0.88 }, { scale: 1, duration: 0.4, ease: EASE.swatch, clearProps: "transform" });
|
|
21768
|
+
};
|
|
21769
|
+
const fail = (message2) => {
|
|
21770
|
+
requested = false;
|
|
21771
|
+
emit({ status: "error", error: message2 }, "error");
|
|
21772
|
+
};
|
|
21773
|
+
const pause = () => {
|
|
21774
|
+
if (scope.disposed) return;
|
|
21775
|
+
request++;
|
|
21776
|
+
requested = false;
|
|
21777
|
+
pending = null;
|
|
21778
|
+
audio.pause();
|
|
21779
|
+
if (state.status !== "idle" && state.status !== "error" && state.status !== "ended" && state.status !== "paused") emit({ status: "paused" }, "pause");
|
|
21780
|
+
else paint();
|
|
21781
|
+
};
|
|
21782
|
+
const seek = (seconds) => {
|
|
21783
|
+
if (scope.disposed || !state.duration || !Number.isFinite(seconds)) return;
|
|
21784
|
+
const next = Math.max(0, Math.min(state.duration, seconds));
|
|
21785
|
+
try {
|
|
21786
|
+
audio.currentTime = next;
|
|
21787
|
+
} catch {
|
|
21788
|
+
return;
|
|
21789
|
+
}
|
|
21790
|
+
emit({ currentTime: next, ...state.status === "ended" && next < state.duration ? { status: "paused" } : {} }, "timeupdate");
|
|
21791
|
+
};
|
|
21792
|
+
const play = () => {
|
|
21793
|
+
if (scope.disposed || opts.disabled || !source) return Promise.resolve(false);
|
|
21794
|
+
if (pending) return pending;
|
|
21795
|
+
if (state.status === "playing") return Promise.resolve(true);
|
|
21796
|
+
if (state.status === "ended") seek(0);
|
|
21797
|
+
const token = ++request;
|
|
21798
|
+
requested = true;
|
|
21799
|
+
emit({ status: "loading", error: null });
|
|
21800
|
+
let started;
|
|
21801
|
+
try {
|
|
21802
|
+
started = Promise.resolve(audio.play());
|
|
21803
|
+
} catch (error) {
|
|
21804
|
+
started = Promise.reject(error);
|
|
21805
|
+
}
|
|
21806
|
+
const result = started.then(() => {
|
|
21807
|
+
if (scope.disposed || token !== request) return false;
|
|
21808
|
+
requested = false;
|
|
21809
|
+
if (audio.paused) {
|
|
21810
|
+
emit({ status: "paused" });
|
|
21811
|
+
return false;
|
|
21812
|
+
}
|
|
21813
|
+
if (state.status !== "playing") emit({ status: "playing", error: null }, "play");
|
|
21814
|
+
return true;
|
|
21815
|
+
}).catch((error) => {
|
|
21816
|
+
if (!scope.disposed && token === request) {
|
|
21817
|
+
requested = false;
|
|
21818
|
+
if (error instanceof Error && error.name === "AbortError") emit({ status: "paused" });
|
|
21819
|
+
else fail("No se pudo reproducir el audio. Vuelve a intentarlo.");
|
|
21820
|
+
}
|
|
21821
|
+
return false;
|
|
21822
|
+
}).finally(() => {
|
|
21823
|
+
if (token === request) pending = null;
|
|
21824
|
+
});
|
|
21825
|
+
pending = result;
|
|
21826
|
+
return result;
|
|
21827
|
+
};
|
|
21828
|
+
const renderPeaks = () => {
|
|
21829
|
+
const supplied = Array.isArray(opts.peaks) ? opts.peaks : [];
|
|
21830
|
+
const values = supplied.length ? supplied : Array(48).fill(0.24);
|
|
21831
|
+
bars.replaceChildren();
|
|
21832
|
+
barNodes = values.slice(0, 256).map((value) => {
|
|
21833
|
+
const bar = make("i", "bar", bars);
|
|
21834
|
+
const peak = typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.min(1, value)) : 0;
|
|
21835
|
+
bar.style.height = `${8 + peak * 92}%`;
|
|
21836
|
+
return bar;
|
|
21837
|
+
});
|
|
21838
|
+
};
|
|
21839
|
+
const update = (next) => {
|
|
21840
|
+
if (scope.disposed) return;
|
|
21841
|
+
const previousPeaks = opts.peaks;
|
|
21842
|
+
opts = { ...opts, ...next };
|
|
21843
|
+
const nextSource = typeof opts.src === "string" ? opts.src : "";
|
|
21844
|
+
if (source !== nextSource) {
|
|
21845
|
+
request++;
|
|
21846
|
+
pending = null;
|
|
21847
|
+
requested = false;
|
|
21848
|
+
audio.pause();
|
|
21849
|
+
source = nextSource;
|
|
21850
|
+
if (source) audio.setAttribute("src", source);
|
|
21851
|
+
else audio.removeAttribute("src");
|
|
21852
|
+
audio.load();
|
|
21853
|
+
audio.playbackRate = state.playbackRate;
|
|
21854
|
+
emit({ ...initialState(), playbackRate: state.playbackRate, status: source ? "loading" : "idle" });
|
|
21855
|
+
}
|
|
21856
|
+
if (opts.disabled && (requested || state.status === "playing")) pause();
|
|
21857
|
+
if (previousPeaks !== opts.peaks || !barNodes.length) renderPeaks();
|
|
21858
|
+
paint();
|
|
21859
|
+
};
|
|
21860
|
+
scope.on(toggle, "click", () => {
|
|
21861
|
+
bounce(toggle);
|
|
21862
|
+
if (requested || state.status === "playing") pause();
|
|
21863
|
+
else void play();
|
|
21864
|
+
});
|
|
21865
|
+
scope.on(range, "input", () => seek(Number(range.value)));
|
|
21866
|
+
scope.on(rate, "click", () => {
|
|
21867
|
+
const available = rates();
|
|
21868
|
+
const index = available.indexOf(state.playbackRate);
|
|
21869
|
+
const next = available[(index + 1) % available.length];
|
|
21870
|
+
if (next === void 0) return;
|
|
21871
|
+
audio.playbackRate = next;
|
|
21872
|
+
emit({ playbackRate: next });
|
|
21873
|
+
bounce(rate);
|
|
21874
|
+
});
|
|
21875
|
+
const metadata = () => {
|
|
21876
|
+
const duration = finite6(audio.duration) ? audio.duration : 0;
|
|
21877
|
+
emit({
|
|
21878
|
+
duration,
|
|
21879
|
+
currentTime: duration ? Math.min(duration, Math.max(0, audio.currentTime || 0)) : 0,
|
|
21880
|
+
...state.status === "loading" && !requested ? { status: "ready" } : {}
|
|
21881
|
+
});
|
|
21882
|
+
};
|
|
21883
|
+
scope.on(audio, "loadedmetadata", metadata);
|
|
21884
|
+
scope.on(audio, "durationchange", metadata);
|
|
21885
|
+
scope.on(audio, "timeupdate", () => emit({ currentTime: finite6(audio.currentTime) ? audio.currentTime : 0 }, "timeupdate"));
|
|
21886
|
+
scope.on(audio, "playing", () => {
|
|
21887
|
+
if (!source || opts.disabled || !requested && state.status !== "playing") {
|
|
21888
|
+
audio.pause();
|
|
21889
|
+
return;
|
|
21890
|
+
}
|
|
21891
|
+
requested = false;
|
|
21892
|
+
if (state.status !== "playing") emit({ status: "playing", error: null }, "play");
|
|
21893
|
+
});
|
|
21894
|
+
scope.on(audio, "pause", () => {
|
|
21895
|
+
if (state.status === "playing" || requested) {
|
|
21896
|
+
requested = false;
|
|
21897
|
+
emit({ status: "paused" }, "pause");
|
|
21898
|
+
}
|
|
21899
|
+
});
|
|
21900
|
+
scope.on(audio, "waiting", () => {
|
|
21901
|
+
if (state.status === "playing") {
|
|
21902
|
+
requested = true;
|
|
21903
|
+
emit({ status: "loading" });
|
|
21904
|
+
}
|
|
21905
|
+
});
|
|
21906
|
+
scope.on(audio, "ended", () => {
|
|
21907
|
+
request++;
|
|
21908
|
+
pending = null;
|
|
21909
|
+
requested = false;
|
|
21910
|
+
emit({ status: "ended", currentTime: state.duration || state.currentTime }, "ended");
|
|
21911
|
+
});
|
|
21912
|
+
scope.on(audio, "error", () => {
|
|
21913
|
+
request++;
|
|
21914
|
+
pending = null;
|
|
21915
|
+
fail("No se pudo cargar el audio. Comprueba el archivo.");
|
|
21916
|
+
});
|
|
21917
|
+
scope.on(audio, "ratechange", () => {
|
|
21918
|
+
if (audio.playbackRate !== state.playbackRate) emit({ playbackRate: audio.playbackRate });
|
|
21919
|
+
});
|
|
21920
|
+
scope.add(() => {
|
|
21921
|
+
request++;
|
|
21922
|
+
requested = false;
|
|
21923
|
+
pending = null;
|
|
21924
|
+
effect?.kill();
|
|
21925
|
+
audio.pause();
|
|
21926
|
+
audio.removeAttribute("src");
|
|
21927
|
+
audio.load();
|
|
21928
|
+
});
|
|
21929
|
+
update(options);
|
|
21930
|
+
return { play, pause, seek, update, get state() {
|
|
21931
|
+
return snapshot();
|
|
21932
|
+
}, get audio() {
|
|
21933
|
+
return scope.disposed ? null : audio;
|
|
21934
|
+
}, destroy: () => scope.dispose() };
|
|
21935
|
+
}
|
|
21936
|
+
|
|
21937
|
+
// src/components/voice-message-bubble/engine.ts
|
|
21938
|
+
var statusLabels = { sending: "Enviando", sent: "Enviado", delivered: "Entregado", read: "Le\xEDdo", failed: "No enviado" };
|
|
21939
|
+
function createVoiceMessageBubble(root, options = {}) {
|
|
21940
|
+
if (!root) return createWaveformPlayer(null, options);
|
|
21941
|
+
const scope = createScope();
|
|
21942
|
+
let opts = { ...options };
|
|
21943
|
+
const content = document.createElement("div");
|
|
21944
|
+
content.setAttribute("data-mk-voice-message-content", "");
|
|
21945
|
+
const header = document.createElement("div");
|
|
21946
|
+
header.setAttribute("data-mk-voice-message-header", "");
|
|
21947
|
+
const author = document.createElement("span");
|
|
21948
|
+
author.setAttribute("data-mk-voice-message-author", "");
|
|
21949
|
+
const caption = document.createElement("span");
|
|
21950
|
+
caption.setAttribute("data-mk-voice-message-caption", "");
|
|
21951
|
+
caption.textContent = "Mensaje de voz";
|
|
21952
|
+
header.append(author, caption);
|
|
21953
|
+
const playerRoot = document.createElement("div");
|
|
21954
|
+
playerRoot.className = "mk-waveform-player";
|
|
21955
|
+
const footer = document.createElement("div");
|
|
21956
|
+
footer.setAttribute("data-mk-voice-message-footer", "");
|
|
21957
|
+
const timestamp = document.createElement("time");
|
|
21958
|
+
const status = document.createElement("span");
|
|
21959
|
+
status.setAttribute("data-mk-voice-message-status", "");
|
|
21960
|
+
footer.append(timestamp, status);
|
|
21961
|
+
content.append(header, playerRoot, footer);
|
|
21962
|
+
root.append(content);
|
|
21963
|
+
scope.add(() => content.remove());
|
|
21964
|
+
scope.attr(root, "data-mk-ready", "");
|
|
21965
|
+
scope.attr(root, "data-mk-direction", "incoming");
|
|
21966
|
+
const player = createWaveformPlayer(playerRoot);
|
|
21967
|
+
scope.add(() => player.destroy());
|
|
21968
|
+
const update = (next) => {
|
|
21969
|
+
if (scope.disposed) return;
|
|
21970
|
+
opts = { ...opts, ...next };
|
|
21971
|
+
author.textContent = opts.author ?? "";
|
|
21972
|
+
author.hidden = !opts.author;
|
|
21973
|
+
timestamp.textContent = opts.timestamp ?? "";
|
|
21974
|
+
timestamp.hidden = !opts.timestamp;
|
|
21975
|
+
if (opts.dateTime) timestamp.dateTime = opts.dateTime;
|
|
21976
|
+
else timestamp.removeAttribute("datetime");
|
|
21977
|
+
status.textContent = opts.status && statusLabels[opts.status] || "";
|
|
21978
|
+
status.hidden = !status.textContent;
|
|
21979
|
+
root.setAttribute("data-mk-direction", opts.direction === "outgoing" ? "outgoing" : "incoming");
|
|
21980
|
+
const { direction: _direction, author: _author, timestamp: _timestamp, dateTime: _dateTime, status: _status, ...audio } = opts;
|
|
21981
|
+
player.update({ ...audio, label: opts.label ?? (opts.author ? `mensaje de voz de ${opts.author}` : "mensaje de voz") });
|
|
21982
|
+
};
|
|
21983
|
+
update(options);
|
|
21984
|
+
return {
|
|
21985
|
+
play: () => player.play(),
|
|
21986
|
+
pause: () => player.pause(),
|
|
21987
|
+
seek: (n) => player.seek(n),
|
|
21988
|
+
update,
|
|
21989
|
+
get state() {
|
|
21990
|
+
return player.state;
|
|
21991
|
+
},
|
|
21992
|
+
get audio() {
|
|
21993
|
+
return player.audio;
|
|
21994
|
+
},
|
|
21995
|
+
destroy: () => scope.dispose()
|
|
21996
|
+
};
|
|
21997
|
+
}
|
|
21998
|
+
|
|
21999
|
+
// src/components/drilldown-menu/engine.ts
|
|
22000
|
+
var CHEVRON5 = '<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 6 6 6-6 6"/></svg>';
|
|
22001
|
+
var sequence24 = 0;
|
|
22002
|
+
var samePath = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
|
|
22003
|
+
var branch = (item) => Array.isArray(item.children);
|
|
22004
|
+
var copyItems = (items) => items.map((item) => ({ ...item, ...branch(item) ? { children: copyItems(item.children) } : {} }));
|
|
22005
|
+
function createDrilldownMenu(root, options = {}) {
|
|
22006
|
+
if (!root) return inert({ open: () => false, back: () => false, root() {
|
|
22007
|
+
}, reset() {
|
|
22008
|
+
}, setPath() {
|
|
22009
|
+
}, setItems() {
|
|
22010
|
+
}, update() {
|
|
22011
|
+
}, focusItem() {
|
|
22012
|
+
}, path: [], items: [], element: null });
|
|
22013
|
+
registerMotion();
|
|
22014
|
+
const scope = createScope();
|
|
22015
|
+
const uid2 = `mk-drilldown-${++sequence24}`;
|
|
22016
|
+
const authored = [...root.childNodes];
|
|
22017
|
+
const holder = document.createDocumentFragment();
|
|
22018
|
+
holder.append(...authored);
|
|
22019
|
+
let config = { ...options };
|
|
22020
|
+
let data = copyItems(options.items ?? []);
|
|
22021
|
+
let path = [];
|
|
22022
|
+
let focused = null;
|
|
22023
|
+
const remembered = /* @__PURE__ */ new Map();
|
|
22024
|
+
let animation = null;
|
|
22025
|
+
const header = document.createElement("div");
|
|
22026
|
+
header.dataset.mkDrilldownHeader = "";
|
|
22027
|
+
const backButton = document.createElement("button");
|
|
22028
|
+
backButton.type = "button";
|
|
22029
|
+
backButton.dataset.mkDrilldownBack = "";
|
|
22030
|
+
backButton.innerHTML = CHEVRON5;
|
|
22031
|
+
const heading = document.createElement("span");
|
|
22032
|
+
heading.id = `${uid2}-heading`;
|
|
22033
|
+
heading.dataset.mkDrilldownHeading = "";
|
|
22034
|
+
header.append(backButton, heading);
|
|
22035
|
+
const breadcrumb = document.createElement("nav");
|
|
22036
|
+
breadcrumb.dataset.mkDrilldownBreadcrumb = "";
|
|
22037
|
+
const crumbs = document.createElement("ol");
|
|
22038
|
+
breadcrumb.append(crumbs);
|
|
22039
|
+
const viewport = document.createElement("div");
|
|
22040
|
+
viewport.dataset.mkDrilldownViewport = "";
|
|
22041
|
+
const menu = document.createElement("div");
|
|
22042
|
+
menu.dataset.mkDrilldownLevel = "";
|
|
22043
|
+
menu.id = `${uid2}-level`;
|
|
22044
|
+
menu.setAttribute("role", "menu");
|
|
22045
|
+
menu.setAttribute("aria-labelledby", heading.id);
|
|
22046
|
+
const empty = document.createElement("p");
|
|
22047
|
+
empty.dataset.mkDrilldownEmpty = "";
|
|
22048
|
+
empty.setAttribute("role", "status");
|
|
22049
|
+
viewport.append(menu, empty);
|
|
22050
|
+
backButton.setAttribute("aria-controls", menu.id);
|
|
22051
|
+
root.append(header, breadcrumb, viewport);
|
|
22052
|
+
scope.attr(root, "data-mk-ready", "");
|
|
22053
|
+
const levelAt = (requested) => {
|
|
22054
|
+
const valid2 = [];
|
|
22055
|
+
const ancestors = [];
|
|
22056
|
+
let items = data;
|
|
22057
|
+
for (const id of requested) {
|
|
22058
|
+
const item = items.find((entry) => entry.id === id);
|
|
22059
|
+
if (!item || item.disabled || !branch(item)) break;
|
|
22060
|
+
valid2.push(id);
|
|
22061
|
+
ancestors.push(item);
|
|
22062
|
+
items = item.children;
|
|
22063
|
+
}
|
|
22064
|
+
return { valid: valid2, ancestors, items };
|
|
22065
|
+
};
|
|
22066
|
+
const level = () => levelAt(path);
|
|
22067
|
+
const enabled = () => [...menu.querySelectorAll("[data-mk-drilldown-item]")].filter((item) => !item.disabled);
|
|
22068
|
+
const buttonOf = (id) => enabled().find((item) => item.dataset.mkDrilldownItem === id);
|
|
22069
|
+
const cancelMotion = () => {
|
|
22070
|
+
animation?.kill();
|
|
22071
|
+
animation = null;
|
|
22072
|
+
gsap.set(menu, { clearProps: "transform,opacity,filter" });
|
|
22073
|
+
gsap.set(viewport, { clearProps: "height" });
|
|
22074
|
+
};
|
|
22075
|
+
const roving = (id, focus = false) => {
|
|
22076
|
+
const items = enabled();
|
|
22077
|
+
const target = items.find((item) => item.dataset.mkDrilldownItem === id) ?? items[0];
|
|
22078
|
+
focused = target?.dataset.mkDrilldownItem ?? null;
|
|
22079
|
+
for (const item of menu.querySelectorAll("[data-mk-drilldown-item]")) item.tabIndex = item === target ? 0 : -1;
|
|
22080
|
+
menu.tabIndex = target ? -1 : 0;
|
|
22081
|
+
if (focused) remembered.set(JSON.stringify(path), focused);
|
|
22082
|
+
if (focus) (target ?? menu).focus({ preventScroll: true });
|
|
22083
|
+
};
|
|
22084
|
+
const notifyPath = () => {
|
|
22085
|
+
const next = [...path];
|
|
22086
|
+
root.dispatchEvent(new CustomEvent("mk:path-change", { bubbles: true, detail: { path: [...next] } }));
|
|
22087
|
+
config.onPathChange?.(next);
|
|
22088
|
+
};
|
|
22089
|
+
const render = (direction, focus, preferred) => {
|
|
22090
|
+
const oldHeight = viewport.getBoundingClientRect().height;
|
|
22091
|
+
cancelMotion();
|
|
22092
|
+
const current3 = level();
|
|
22093
|
+
const label = config.label ?? "Actions";
|
|
22094
|
+
const title = current3.ancestors.at(-1)?.label ?? label;
|
|
22095
|
+
heading.textContent = title;
|
|
22096
|
+
backButton.hidden = path.length === 0;
|
|
22097
|
+
backButton.setAttribute("aria-label", config.backLabel ?? "Back");
|
|
22098
|
+
breadcrumb.setAttribute("aria-label", `${label} path`);
|
|
22099
|
+
const labels = [label, ...current3.ancestors.map((item) => item.label)];
|
|
22100
|
+
crumbs.replaceChildren(...labels.map((text, index) => {
|
|
22101
|
+
const li = document.createElement("li");
|
|
22102
|
+
if (index === labels.length - 1) {
|
|
22103
|
+
const span = document.createElement("span");
|
|
22104
|
+
span.setAttribute("aria-current", "location");
|
|
22105
|
+
span.textContent = text;
|
|
22106
|
+
li.append(span);
|
|
22107
|
+
} else {
|
|
22108
|
+
const button2 = document.createElement("button");
|
|
22109
|
+
button2.type = "button";
|
|
22110
|
+
button2.dataset.mkDrilldownCrumb = String(index);
|
|
22111
|
+
button2.textContent = text;
|
|
22112
|
+
button2.setAttribute("aria-controls", menu.id);
|
|
22113
|
+
li.append(button2);
|
|
22114
|
+
}
|
|
22115
|
+
return li;
|
|
22116
|
+
}));
|
|
22117
|
+
menu.replaceChildren(...current3.items.map((item, index) => {
|
|
22118
|
+
const button2 = document.createElement("button");
|
|
22119
|
+
button2.type = "button";
|
|
22120
|
+
button2.dataset.mkDrilldownItem = item.id;
|
|
22121
|
+
button2.setAttribute("role", "menuitem");
|
|
22122
|
+
button2.disabled = Boolean(item.disabled);
|
|
22123
|
+
if (item.disabled) button2.setAttribute("aria-disabled", "true");
|
|
22124
|
+
const text = document.createElement("span");
|
|
22125
|
+
text.dataset.mkDrilldownText = "";
|
|
22126
|
+
const name = document.createElement("span");
|
|
22127
|
+
name.id = `${uid2}-item-${index}`;
|
|
22128
|
+
name.dataset.mkDrilldownLabel = "";
|
|
22129
|
+
name.textContent = item.label;
|
|
22130
|
+
button2.setAttribute("aria-labelledby", name.id);
|
|
22131
|
+
text.append(name);
|
|
22132
|
+
if (item.description) {
|
|
22133
|
+
const description = document.createElement("span");
|
|
22134
|
+
description.id = `${uid2}-description-${index}`;
|
|
22135
|
+
description.dataset.mkDrilldownDescription = "";
|
|
22136
|
+
description.textContent = item.description;
|
|
22137
|
+
button2.setAttribute("aria-describedby", description.id);
|
|
22138
|
+
text.append(description);
|
|
22139
|
+
}
|
|
22140
|
+
button2.append(text);
|
|
22141
|
+
if (branch(item)) {
|
|
22142
|
+
button2.setAttribute("aria-haspopup", "menu");
|
|
22143
|
+
const arrow = document.createElement("span");
|
|
22144
|
+
arrow.dataset.mkDrilldownArrow = "";
|
|
22145
|
+
arrow.innerHTML = CHEVRON5;
|
|
22146
|
+
button2.append(arrow);
|
|
22147
|
+
}
|
|
22148
|
+
return button2;
|
|
22149
|
+
}));
|
|
22150
|
+
empty.textContent = config.emptyText ?? "No actions available";
|
|
22151
|
+
empty.hidden = current3.items.length !== 0;
|
|
22152
|
+
roving(preferred ?? remembered.get(JSON.stringify(path)) ?? null);
|
|
22153
|
+
if (direction && !reduced()) {
|
|
22154
|
+
animation = gsap.timeline({ onComplete: () => {
|
|
22155
|
+
animation = null;
|
|
22156
|
+
} }).fromTo(menu, { x: 28 * direction, opacity: 0, filter: "blur(6px)" }, { x: 0, opacity: 1, filter: "blur(0px)", duration: 0.36, ease: EASE.signature, clearProps: "transform,opacity,filter" });
|
|
22157
|
+
const nextHeight = viewport.getBoundingClientRect().height;
|
|
22158
|
+
if (oldHeight > 0 && nextHeight > 0 && oldHeight !== nextHeight) {
|
|
22159
|
+
animation.fromTo(viewport, { height: oldHeight }, { height: nextHeight, duration: 0.36, ease: EASE.signature, clearProps: "height" }, 0);
|
|
22160
|
+
}
|
|
22161
|
+
}
|
|
22162
|
+
if (focus) roving(focused, true);
|
|
22163
|
+
};
|
|
22164
|
+
const navigate = (requested, notify, focus, preferred) => {
|
|
22165
|
+
if (scope.disposed) return false;
|
|
22166
|
+
const next = levelAt(requested).valid;
|
|
22167
|
+
if (samePath(path, next)) return false;
|
|
22168
|
+
const previous = path;
|
|
22169
|
+
if (focused) remembered.set(JSON.stringify(previous), focused);
|
|
22170
|
+
const direction = next.length > path.length ? 1 : -1;
|
|
22171
|
+
path = next;
|
|
22172
|
+
render(direction, focus, preferred);
|
|
22173
|
+
if (notify) notifyPath();
|
|
22174
|
+
return true;
|
|
22175
|
+
};
|
|
22176
|
+
const open = (id) => {
|
|
22177
|
+
if (scope.disposed) return false;
|
|
22178
|
+
const item = level().items.find((entry) => entry.id === id);
|
|
22179
|
+
if (!item || item.disabled || !branch(item)) return false;
|
|
22180
|
+
return navigate([...path, id], true, true);
|
|
22181
|
+
};
|
|
22182
|
+
const back = () => path.length ? navigate(path.slice(0, -1), true, true, path.at(-1)) : false;
|
|
22183
|
+
const reset = () => navigate([], true, root.contains(document.activeElement), path[0]);
|
|
22184
|
+
const activate = (id) => {
|
|
22185
|
+
const item = level().items.find((entry) => entry.id === id);
|
|
22186
|
+
if (!item || item.disabled) return;
|
|
22187
|
+
if (branch(item)) return void open(id);
|
|
22188
|
+
const selected = copyItems([item])[0];
|
|
22189
|
+
const selectedPath = [...path, item.id];
|
|
22190
|
+
root.dispatchEvent(new CustomEvent("mk:select", { bubbles: true, detail: { item: selected, path: [...selectedPath] } }));
|
|
22191
|
+
config.onSelect?.(copyItems([item])[0], [...selectedPath]);
|
|
22192
|
+
};
|
|
22193
|
+
scope.on(menu, "click", (event) => {
|
|
22194
|
+
const button2 = event.target?.closest("[data-mk-drilldown-item]");
|
|
22195
|
+
if (!button2 || !menu.contains(button2) || button2.disabled) return;
|
|
22196
|
+
roving(button2.dataset.mkDrilldownItem, false);
|
|
22197
|
+
activate(button2.dataset.mkDrilldownItem);
|
|
22198
|
+
});
|
|
22199
|
+
scope.on(menu, "focusin", (event) => {
|
|
22200
|
+
const button2 = event.target?.closest("[data-mk-drilldown-item]");
|
|
22201
|
+
if (button2 && !button2.disabled) roving(button2.dataset.mkDrilldownItem, false);
|
|
22202
|
+
});
|
|
22203
|
+
scope.on(root, "keydown", (event) => {
|
|
22204
|
+
const key2 = event.key;
|
|
22205
|
+
if ((key2 === "ArrowLeft" || key2 === "Escape") && path.length) {
|
|
22206
|
+
event.preventDefault();
|
|
22207
|
+
event.stopPropagation();
|
|
22208
|
+
back();
|
|
22209
|
+
return;
|
|
22210
|
+
}
|
|
22211
|
+
if (!menu.contains(event.target)) return;
|
|
22212
|
+
const items = enabled();
|
|
22213
|
+
const at = items.indexOf(document.activeElement);
|
|
22214
|
+
const moves = { ArrowDown: (at + 1) % items.length, ArrowUp: at < 0 ? items.length - 1 : (at - 1 + items.length) % items.length, Home: 0, End: items.length - 1 };
|
|
22215
|
+
if (key2 in moves && items.length) {
|
|
22216
|
+
event.preventDefault();
|
|
22217
|
+
roving(items[moves[key2]].dataset.mkDrilldownItem, true);
|
|
22218
|
+
return;
|
|
22219
|
+
}
|
|
22220
|
+
const button2 = event.target?.closest("[data-mk-drilldown-item]");
|
|
22221
|
+
if (!button2 || button2.disabled || !menu.contains(button2)) return;
|
|
22222
|
+
if (key2 === "Enter" || key2 === " " || key2 === "ArrowRight") {
|
|
22223
|
+
const item = level().items.find((entry) => entry.id === button2.dataset.mkDrilldownItem);
|
|
22224
|
+
if (key2 === "ArrowRight" && (!item || !branch(item))) return;
|
|
22225
|
+
event.preventDefault();
|
|
22226
|
+
activate(button2.dataset.mkDrilldownItem);
|
|
22227
|
+
}
|
|
22228
|
+
});
|
|
22229
|
+
scope.on(backButton, "click", () => back());
|
|
22230
|
+
scope.on(breadcrumb, "click", (event) => {
|
|
22231
|
+
const button2 = event.target?.closest("[data-mk-drilldown-crumb]");
|
|
22232
|
+
if (!button2 || !breadcrumb.contains(button2)) return;
|
|
22233
|
+
const depth = Number(button2.dataset.mkDrilldownCrumb);
|
|
22234
|
+
navigate(path.slice(0, depth), true, true, path[depth]);
|
|
22235
|
+
});
|
|
22236
|
+
scope.add(() => {
|
|
22237
|
+
cancelMotion();
|
|
22238
|
+
remembered.clear();
|
|
22239
|
+
header.remove();
|
|
22240
|
+
breadcrumb.remove();
|
|
22241
|
+
viewport.remove();
|
|
22242
|
+
root.append(holder);
|
|
22243
|
+
});
|
|
22244
|
+
path = levelAt(options.path ?? []).valid;
|
|
22245
|
+
render(0, false);
|
|
22246
|
+
const update = (next) => {
|
|
22247
|
+
if (scope.disposed) return;
|
|
22248
|
+
const active = document.activeElement;
|
|
22249
|
+
const hadFocus = root.contains(active);
|
|
22250
|
+
const backFocused = active === backButton;
|
|
22251
|
+
const crumbFocused = active?.dataset.mkDrilldownCrumb;
|
|
22252
|
+
const previousPath = path;
|
|
22253
|
+
const previousFocus = focused;
|
|
22254
|
+
config = { ...config, ...next };
|
|
22255
|
+
if (next.items !== void 0) data = copyItems(next.items);
|
|
22256
|
+
path = levelAt(next.path ?? path).valid;
|
|
22257
|
+
const changed = !samePath(previousPath, path);
|
|
22258
|
+
const preferred = changed ? previousPath[path.length] : previousFocus;
|
|
22259
|
+
render(0, hadFocus, preferred);
|
|
22260
|
+
if (hadFocus && !changed) {
|
|
22261
|
+
if (backFocused && !backButton.hidden) backButton.focus({ preventScroll: true });
|
|
22262
|
+
else if (crumbFocused !== void 0) {
|
|
22263
|
+
[...crumbs.querySelectorAll("[data-mk-drilldown-crumb]")].find((button2) => button2.dataset.mkDrilldownCrumb === crumbFocused)?.focus({ preventScroll: true });
|
|
22264
|
+
}
|
|
22265
|
+
}
|
|
22266
|
+
if (changed && next.path === void 0) notifyPath();
|
|
22267
|
+
};
|
|
22268
|
+
return {
|
|
22269
|
+
open,
|
|
22270
|
+
back,
|
|
22271
|
+
root: reset,
|
|
22272
|
+
reset,
|
|
22273
|
+
setPath: (next, notify = false) => {
|
|
22274
|
+
navigate(next, notify, root.contains(document.activeElement));
|
|
22275
|
+
},
|
|
22276
|
+
setItems: (items) => update({ items }),
|
|
22277
|
+
update,
|
|
22278
|
+
focusItem(id) {
|
|
22279
|
+
if (!scope.disposed && buttonOf(id)) roving(id, true);
|
|
22280
|
+
},
|
|
22281
|
+
get path() {
|
|
22282
|
+
return [...path];
|
|
22283
|
+
},
|
|
22284
|
+
get items() {
|
|
22285
|
+
return copyItems(level().items);
|
|
22286
|
+
},
|
|
22287
|
+
element: root,
|
|
22288
|
+
destroy: () => scope.dispose()
|
|
22289
|
+
};
|
|
22290
|
+
}
|
|
22291
|
+
|
|
22292
|
+
// src/components/wheel-picker/engine.ts
|
|
22293
|
+
var sequence25 = 0;
|
|
22294
|
+
function normalize(items) {
|
|
22295
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22296
|
+
return items.flatMap((item) => {
|
|
22297
|
+
const row = typeof item === "string" ? { value: item, label: item } : item;
|
|
22298
|
+
if (!row || typeof row !== "object" || row.value == null) return [];
|
|
22299
|
+
const value = String(row.value);
|
|
22300
|
+
if (seen.has(value)) return [];
|
|
22301
|
+
seen.add(value);
|
|
22302
|
+
return [{ value, label: String(row.label ?? value), disabled: Boolean(row.disabled) }];
|
|
22303
|
+
});
|
|
22304
|
+
}
|
|
22305
|
+
function createWheelPicker(root, options = {}) {
|
|
22306
|
+
if (!root) return inert({ setValue() {
|
|
22307
|
+
}, setItems() {
|
|
22308
|
+
}, value: "" });
|
|
22309
|
+
const scope = createScope(), uid2 = `mk-wheel-${++sequence25}`;
|
|
22310
|
+
let items = normalize(Array.isArray(options.items) ? options.items : []);
|
|
22311
|
+
const rawRows = Number.isFinite(options.visibleItems) ? Math.round(options.visibleItems) : 5;
|
|
22312
|
+
const rows = Math.min(9, Math.max(3, rawRows % 2 ? rawRows : rawRows + 1));
|
|
22313
|
+
const height = Number.isFinite(options.itemHeight) ? Math.max(44, Math.min(96, options.itemHeight)) : 44;
|
|
22314
|
+
const disabled = Boolean(options.disabled);
|
|
22315
|
+
const originalStyle = root.getAttribute("style");
|
|
22316
|
+
root.style.setProperty("--mk-wheel-row", `${height}px`);
|
|
22317
|
+
root.style.setProperty("--mk-wheel-rows", String(rows));
|
|
22318
|
+
scope.add(() => {
|
|
22319
|
+
if (originalStyle === null) root.removeAttribute("style");
|
|
22320
|
+
else root.setAttribute("style", originalStyle);
|
|
22321
|
+
});
|
|
22322
|
+
scope.attr(root, "data-mk-ready", "");
|
|
22323
|
+
scope.attr(root, "data-mk-disabled", disabled ? "" : null);
|
|
22324
|
+
const label = document.createElement("span");
|
|
22325
|
+
label.id = `${uid2}-label`;
|
|
22326
|
+
label.dataset.mkWheelLabel = "";
|
|
22327
|
+
label.textContent = options.label ?? root.getAttribute("aria-label") ?? "Seleccionar";
|
|
22328
|
+
const frame = document.createElement("div");
|
|
22329
|
+
frame.dataset.mkWheelFrame = "";
|
|
22330
|
+
const highlight = document.createElement("span");
|
|
22331
|
+
highlight.dataset.mkWheelHighlight = "";
|
|
22332
|
+
highlight.setAttribute("aria-hidden", "true");
|
|
22333
|
+
const viewport = document.createElement("div");
|
|
22334
|
+
viewport.dataset.mkWheelViewport = "";
|
|
22335
|
+
viewport.setAttribute("role", "listbox");
|
|
22336
|
+
viewport.setAttribute("aria-labelledby", label.id);
|
|
22337
|
+
viewport.setAttribute("aria-orientation", "vertical");
|
|
22338
|
+
viewport.setAttribute("aria-disabled", String(disabled));
|
|
22339
|
+
viewport.tabIndex = disabled ? -1 : 0;
|
|
22340
|
+
const list3 = document.createElement("div");
|
|
22341
|
+
list3.dataset.mkWheelList = "";
|
|
22342
|
+
viewport.append(list3);
|
|
22343
|
+
frame.append(highlight, viewport);
|
|
22344
|
+
const input = document.createElement("input");
|
|
22345
|
+
input.type = "hidden";
|
|
22346
|
+
if (options.name) input.name = options.name;
|
|
22347
|
+
input.disabled = disabled;
|
|
22348
|
+
const status = document.createElement("span");
|
|
22349
|
+
status.className = "mk-sr-only";
|
|
22350
|
+
status.setAttribute("role", "status");
|
|
22351
|
+
root.append(label, frame, input, status);
|
|
22352
|
+
scope.add(() => {
|
|
22353
|
+
label.remove();
|
|
22354
|
+
frame.remove();
|
|
22355
|
+
input.remove();
|
|
22356
|
+
status.remove();
|
|
22357
|
+
});
|
|
22358
|
+
const enabled = () => items.flatMap((item, index) => item.disabled ? [] : [index]);
|
|
22359
|
+
const find = (value) => items.findIndex((item) => value !== void 0 && item.value === String(value) && !item.disabled);
|
|
22360
|
+
let current3 = find(options.value);
|
|
22361
|
+
if (current3 < 0) current3 = enabled()[0] ?? -1;
|
|
22362
|
+
const initial = items[current3]?.value ?? "";
|
|
22363
|
+
let committed = initial;
|
|
22364
|
+
let nodes = [];
|
|
22365
|
+
let timer2;
|
|
22366
|
+
let typing;
|
|
22367
|
+
let prefix = "";
|
|
22368
|
+
let programmatic = null;
|
|
22369
|
+
let dragging = null;
|
|
22370
|
+
let suppressClick = false;
|
|
22371
|
+
scope.add(() => {
|
|
22372
|
+
clearTimeout(timer2);
|
|
22373
|
+
clearTimeout(typing);
|
|
22374
|
+
});
|
|
22375
|
+
const paint = () => {
|
|
22376
|
+
const offset = viewport.scrollTop / height;
|
|
22377
|
+
nodes.forEach((node, index) => {
|
|
22378
|
+
const distance = Math.max(-3, Math.min(3, index - offset));
|
|
22379
|
+
node.style.transform = reduced() ? "" : `perspective(600px) rotateX(${-distance * 14}deg) scale(${1 - Math.abs(distance) * 0.055})`;
|
|
22380
|
+
node.setAttribute("aria-selected", String(index === current3));
|
|
22381
|
+
});
|
|
22382
|
+
input.value = items[current3]?.value ?? "";
|
|
22383
|
+
if (current3 >= 0) viewport.setAttribute("aria-activedescendant", `${uid2}-${current3}`);
|
|
22384
|
+
else viewport.removeAttribute("aria-activedescendant");
|
|
22385
|
+
};
|
|
22386
|
+
const announce = (kind) => {
|
|
22387
|
+
const value = items[current3]?.value ?? "";
|
|
22388
|
+
if (kind === "input") options.onInput?.(value);
|
|
22389
|
+
else {
|
|
22390
|
+
options.onChange?.(value);
|
|
22391
|
+
status.textContent = items[current3]?.label ?? "";
|
|
22392
|
+
}
|
|
22393
|
+
input.dispatchEvent(new Event(kind, { bubbles: true }));
|
|
22394
|
+
root.dispatchEvent(new CustomEvent(`mk:${kind}`, { bubbles: true, detail: { value, item: current3 >= 0 ? { ...items[current3] } : null } }));
|
|
22395
|
+
};
|
|
22396
|
+
const align = (animate) => {
|
|
22397
|
+
const top = Math.max(0, current3) * height;
|
|
22398
|
+
if (animate && !reduced() && typeof viewport.scrollTo === "function") {
|
|
22399
|
+
programmatic = top;
|
|
22400
|
+
viewport.scrollTo({ top, behavior: "smooth" });
|
|
22401
|
+
} else {
|
|
22402
|
+
programmatic = null;
|
|
22403
|
+
viewport.scrollTop = top;
|
|
22404
|
+
paint();
|
|
22405
|
+
}
|
|
22406
|
+
};
|
|
22407
|
+
const select = (index, notify, animate = true) => {
|
|
22408
|
+
if (scope.disposed || index < 0 || index >= items.length || items[index].disabled) return;
|
|
22409
|
+
const previous = items[current3]?.value ?? "";
|
|
22410
|
+
current3 = index;
|
|
22411
|
+
paint();
|
|
22412
|
+
align(animate);
|
|
22413
|
+
const value = items[current3].value;
|
|
22414
|
+
committed = value;
|
|
22415
|
+
if (notify && value !== previous) {
|
|
22416
|
+
announce("input");
|
|
22417
|
+
announce("change");
|
|
22418
|
+
}
|
|
22419
|
+
};
|
|
22420
|
+
const nearest = () => {
|
|
22421
|
+
const at = viewport.scrollTop / height;
|
|
22422
|
+
return enabled().reduce((best, index) => best < 0 || Math.abs(index - at) < Math.abs(best - at) ? index : best, -1);
|
|
22423
|
+
};
|
|
22424
|
+
const settle = () => {
|
|
22425
|
+
if (scope.disposed || dragging) return;
|
|
22426
|
+
clearTimeout(timer2);
|
|
22427
|
+
if (programmatic !== null) {
|
|
22428
|
+
programmatic = null;
|
|
22429
|
+
viewport.scrollTop = Math.max(0, current3) * height;
|
|
22430
|
+
paint();
|
|
22431
|
+
return;
|
|
22432
|
+
}
|
|
22433
|
+
const index = nearest();
|
|
22434
|
+
if (index < 0) return;
|
|
22435
|
+
current3 = index;
|
|
22436
|
+
align(false);
|
|
22437
|
+
paint();
|
|
22438
|
+
const value = items[current3].value;
|
|
22439
|
+
if (value !== committed) {
|
|
22440
|
+
committed = value;
|
|
22441
|
+
announce("change");
|
|
22442
|
+
}
|
|
22443
|
+
};
|
|
22444
|
+
const build = () => {
|
|
22445
|
+
list3.replaceChildren();
|
|
22446
|
+
nodes = items.map((item, index) => {
|
|
22447
|
+
const node = document.createElement("div");
|
|
22448
|
+
node.id = `${uid2}-${index}`;
|
|
22449
|
+
node.dataset.mkWheelOption = String(index);
|
|
22450
|
+
node.setAttribute("role", "option");
|
|
22451
|
+
node.setAttribute("aria-disabled", String(item.disabled));
|
|
22452
|
+
node.textContent = item.label;
|
|
22453
|
+
list3.append(node);
|
|
22454
|
+
return node;
|
|
22455
|
+
});
|
|
22456
|
+
if (!items.length) {
|
|
22457
|
+
const empty = document.createElement("span");
|
|
22458
|
+
empty.dataset.mkWheelEmpty = "";
|
|
22459
|
+
empty.textContent = "Sin opciones";
|
|
22460
|
+
list3.append(empty);
|
|
22461
|
+
}
|
|
22462
|
+
align(false);
|
|
22463
|
+
paint();
|
|
22464
|
+
};
|
|
22465
|
+
const interrupt = () => {
|
|
22466
|
+
if (programmatic !== null && typeof viewport.scrollTo === "function") viewport.scrollTo({ top: viewport.scrollTop, behavior: "instant" });
|
|
22467
|
+
programmatic = null;
|
|
22468
|
+
};
|
|
22469
|
+
scope.on(viewport, "pointerdown", (event) => {
|
|
22470
|
+
interrupt();
|
|
22471
|
+
const pointer2 = event;
|
|
22472
|
+
if (disabled || pointer2.pointerType === "touch" || pointer2.button !== 0) return;
|
|
22473
|
+
dragging = { id: pointer2.pointerId, y: pointer2.clientY, top: viewport.scrollTop, moved: false };
|
|
22474
|
+
viewport.focus({ preventScroll: true });
|
|
22475
|
+
});
|
|
22476
|
+
scope.on(window, "pointermove", (event) => {
|
|
22477
|
+
const pointer2 = event;
|
|
22478
|
+
if (!dragging || pointer2.pointerId !== dragging.id) return;
|
|
22479
|
+
const delta = pointer2.clientY - dragging.y;
|
|
22480
|
+
if (Math.abs(delta) > 4 && !dragging.moved) {
|
|
22481
|
+
dragging.moved = true;
|
|
22482
|
+
viewport.style.scrollSnapType = "none";
|
|
22483
|
+
try {
|
|
22484
|
+
viewport.setPointerCapture(pointer2.pointerId);
|
|
22485
|
+
} catch {
|
|
22486
|
+
}
|
|
22487
|
+
}
|
|
22488
|
+
if (!dragging.moved) return;
|
|
22489
|
+
event.preventDefault();
|
|
22490
|
+
viewport.scrollTop = Math.max(0, Math.min(Math.max(0, (items.length - 1) * height), dragging.top - delta));
|
|
22491
|
+
});
|
|
22492
|
+
const release = (event) => {
|
|
22493
|
+
if (!dragging || dragging.id !== event.pointerId) return;
|
|
22494
|
+
suppressClick = dragging.moved;
|
|
22495
|
+
dragging = null;
|
|
22496
|
+
viewport.style.removeProperty("scroll-snap-type");
|
|
22497
|
+
if (suppressClick) {
|
|
22498
|
+
settle();
|
|
22499
|
+
clearTimeout(timer2);
|
|
22500
|
+
timer2 = setTimeout(() => {
|
|
22501
|
+
suppressClick = false;
|
|
22502
|
+
}, 0);
|
|
22503
|
+
}
|
|
22504
|
+
};
|
|
22505
|
+
scope.on(window, "pointerup", release);
|
|
22506
|
+
scope.on(window, "pointercancel", release);
|
|
22507
|
+
scope.on(viewport, "lostpointercapture", release);
|
|
22508
|
+
scope.on(viewport, "wheel", interrupt, { passive: true });
|
|
22509
|
+
scope.on(viewport, "scroll", () => {
|
|
22510
|
+
if (disabled) return;
|
|
22511
|
+
if (programmatic === null) {
|
|
22512
|
+
const index = nearest();
|
|
22513
|
+
if (index >= 0 && index !== current3) {
|
|
22514
|
+
current3 = index;
|
|
22515
|
+
paint();
|
|
22516
|
+
announce("input");
|
|
22517
|
+
}
|
|
22518
|
+
}
|
|
22519
|
+
paint();
|
|
22520
|
+
clearTimeout(timer2);
|
|
22521
|
+
timer2 = setTimeout(settle, 100);
|
|
22522
|
+
}, { passive: true });
|
|
22523
|
+
scope.on(viewport, "scrollend", settle);
|
|
22524
|
+
scope.on(viewport, "click", (event) => {
|
|
22525
|
+
if (disabled) return;
|
|
22526
|
+
if (suppressClick) {
|
|
22527
|
+
event.preventDefault();
|
|
22528
|
+
suppressClick = false;
|
|
22529
|
+
return;
|
|
22530
|
+
}
|
|
22531
|
+
const row = event.target.closest("[data-mk-wheel-option]");
|
|
22532
|
+
if (!row || !list3.contains(row)) return;
|
|
22533
|
+
select(Number(row.dataset.mkWheelOption), true);
|
|
22534
|
+
viewport.focus({ preventScroll: true });
|
|
22535
|
+
});
|
|
22536
|
+
scope.on(viewport, "keydown", (event) => {
|
|
22537
|
+
if (disabled) return;
|
|
22538
|
+
const key2 = event.key, choices = enabled(), at = choices.indexOf(current3);
|
|
22539
|
+
if (key2 === "Enter" || key2 === " ") {
|
|
22540
|
+
event.preventDefault();
|
|
22541
|
+
return;
|
|
22542
|
+
}
|
|
22543
|
+
const move = key2 === "ArrowDown" ? 1 : key2 === "ArrowUp" ? -1 : key2 === "PageDown" ? rows - 1 : key2 === "PageUp" ? 1 - rows : 0;
|
|
22544
|
+
let next = key2 === "Home" ? choices[0] : key2 === "End" ? choices.at(-1) : move ? choices[Math.min(choices.length - 1, Math.max(0, at + move))] : void 0;
|
|
22545
|
+
if (next === void 0 && key2.length === 1 && !event.ctrlKey && !event.metaKey) {
|
|
22546
|
+
prefix += key2.toLocaleLowerCase();
|
|
22547
|
+
clearTimeout(typing);
|
|
22548
|
+
typing = setTimeout(() => {
|
|
22549
|
+
prefix = "";
|
|
22550
|
+
}, 600);
|
|
22551
|
+
next = choices.find((index) => items[index].label.toLocaleLowerCase().startsWith(prefix));
|
|
22552
|
+
}
|
|
22553
|
+
if (next === void 0) return;
|
|
22554
|
+
event.preventDefault();
|
|
22555
|
+
interrupt();
|
|
22556
|
+
select(next, true);
|
|
22557
|
+
});
|
|
22558
|
+
const form = root.closest("form");
|
|
22559
|
+
if (form) scope.on(form, "reset", (event) => queueMicrotask(() => {
|
|
22560
|
+
if (scope.disposed || event.defaultPrevented) return;
|
|
22561
|
+
const index = find(initial);
|
|
22562
|
+
select(index >= 0 ? index : enabled()[0] ?? -1, true, false);
|
|
22563
|
+
paint();
|
|
22564
|
+
}));
|
|
22565
|
+
build();
|
|
22566
|
+
input.defaultValue = initial;
|
|
22567
|
+
return {
|
|
22568
|
+
setValue(value, notify = false) {
|
|
22569
|
+
const next = find(value);
|
|
22570
|
+
if (next !== current3) select(next, notify);
|
|
22571
|
+
},
|
|
22572
|
+
setItems(next, notify = false) {
|
|
22573
|
+
if (scope.disposed) return;
|
|
22574
|
+
clearTimeout(timer2);
|
|
22575
|
+
programmatic = null;
|
|
22576
|
+
const before = items[current3]?.value ?? "";
|
|
22577
|
+
items = normalize(Array.isArray(next) ? next : []);
|
|
22578
|
+
current3 = find(before);
|
|
22579
|
+
if (current3 < 0) current3 = enabled()[0] ?? -1;
|
|
22580
|
+
build();
|
|
22581
|
+
committed = items[current3]?.value ?? "";
|
|
22582
|
+
if (notify && committed !== before) {
|
|
22583
|
+
announce("input");
|
|
22584
|
+
announce("change");
|
|
22585
|
+
}
|
|
22586
|
+
},
|
|
22587
|
+
get value() {
|
|
22588
|
+
return items[current3]?.value ?? "";
|
|
22589
|
+
},
|
|
22590
|
+
destroy: () => scope.dispose()
|
|
22591
|
+
};
|
|
22592
|
+
}
|
|
22593
|
+
|
|
21111
22594
|
export {
|
|
21112
22595
|
PATHS,
|
|
21113
22596
|
springPath,
|
|
@@ -21328,6 +22811,11 @@ export {
|
|
|
21328
22811
|
sanitizeHtml,
|
|
21329
22812
|
createRichTextEditor,
|
|
21330
22813
|
createAddToCart,
|
|
21331
|
-
createScrollIsland
|
|
22814
|
+
createScrollIsland,
|
|
22815
|
+
createSignaturePad,
|
|
22816
|
+
createWaveformPlayer,
|
|
22817
|
+
createVoiceMessageBubble,
|
|
22818
|
+
createDrilldownMenu,
|
|
22819
|
+
createWheelPicker
|
|
21332
22820
|
};
|
|
21333
|
-
//# sourceMappingURL=chunk-
|
|
22821
|
+
//# sourceMappingURL=chunk-7IQTMF7Y.js.map
|