@yewdiel21/motion-kit 0.16.0 → 0.18.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.
Files changed (158) hide show
  1. package/README.md +44 -0
  2. package/dist/auto/index.d.ts +23 -3
  3. package/dist/auto/index.js +43 -3
  4. package/dist/auto/index.js.map +1 -1
  5. package/dist/{chunk-RBEKR5UZ.js → chunk-AWDEKDEJ.js} +2 -2
  6. package/dist/{chunk-NFZIX3IA.js → chunk-EDMXWUW3.js} +2 -2
  7. package/dist/{chunk-SDQ776LG.js → chunk-Q7IW4FV3.js} +3941 -43
  8. package/dist/chunk-Q7IW4FV3.js.map +1 -0
  9. package/dist/css/components/badge-button.css +16 -0
  10. package/dist/css/components/bento-grid.css +13 -0
  11. package/dist/css/components/drilldown-menu.css +134 -0
  12. package/dist/css/components/equalizer-slider.css +26 -0
  13. package/dist/css/components/handwriting-text.css +15 -0
  14. package/dist/css/components/magnetize-button.css +18 -0
  15. package/dist/css/components/morphing-page-dots.css +13 -0
  16. package/dist/css/components/not-found.css +22 -0
  17. package/dist/css/components/notification-stack.css +42 -0
  18. package/dist/css/components/particle-button.css +14 -0
  19. package/dist/css/components/radio-group.css +29 -0
  20. package/dist/css/components/rating-scale.css +23 -0
  21. package/dist/css/components/scroll-preview-dock.css +18 -0
  22. package/dist/css/components/select.css +16 -0
  23. package/dist/css/components/signature-pad.css +131 -0
  24. package/dist/css/components/stepper.css +36 -0
  25. package/dist/css/components/sticky-header.css +10 -0
  26. package/dist/css/components/temperature-slider.css +29 -0
  27. package/dist/css/components/voice-message-bubble.css +67 -0
  28. package/dist/css/components/waveform-player.css +51 -0
  29. package/dist/css/components/wheel-picker.css +18 -0
  30. package/dist/css/tokens.css +4 -0
  31. package/dist/elements/index.d.ts +292 -4
  32. package/dist/elements/index.js +856 -4
  33. package/dist/elements/index.js.map +1 -1
  34. package/dist/{reveal-DRpNO4KP.d.ts → engine-t8d7brjn.d.ts} +534 -1
  35. package/dist/index.css +713 -0
  36. package/dist/index.d.ts +23 -23
  37. package/dist/index.js +43 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/react/index.d.ts +151 -7
  40. package/dist/react/index.js +893 -3
  41. package/dist/react/index.js.map +1 -1
  42. package/dist/{reduced-DQwVXQYb.d.ts → reduced-dPsZYqtI.d.ts} +1 -1
  43. package/dist/{store-Da3zSh8Z.d.ts → store-6hZNKiee.d.ts} +1 -1
  44. package/package.json +110 -110
  45. package/registry.json +244 -0
  46. package/src/auto/auto-init.ts +339 -293
  47. package/src/components/badge-button/README.md +28 -0
  48. package/src/components/badge-button/badge-button.css +15 -0
  49. package/src/components/badge-button/element.ts +16 -0
  50. package/src/components/badge-button/engine.ts +85 -0
  51. package/src/components/badge-button/react.tsx +31 -0
  52. package/src/components/bento-grid/README.md +26 -0
  53. package/src/components/bento-grid/bento-grid.css +12 -0
  54. package/src/components/bento-grid/element.ts +22 -0
  55. package/src/components/bento-grid/engine.ts +153 -0
  56. package/src/components/bento-grid/react.tsx +25 -0
  57. package/src/components/drilldown-menu/README.md +163 -0
  58. package/src/components/drilldown-menu/drilldown-menu.css +133 -0
  59. package/src/components/drilldown-menu/element.ts +59 -0
  60. package/src/components/drilldown-menu/engine.ts +378 -0
  61. package/src/components/drilldown-menu/react.tsx +76 -0
  62. package/src/components/equalizer-slider/README.md +43 -0
  63. package/src/components/equalizer-slider/element.ts +41 -0
  64. package/src/components/equalizer-slider/engine.ts +32 -0
  65. package/src/components/equalizer-slider/equalizer-slider.css +26 -0
  66. package/src/components/equalizer-slider/react.tsx +60 -0
  67. package/src/components/equalizer-slider/shared.ts +161 -0
  68. package/src/components/handwriting-text/README.md +29 -0
  69. package/src/components/handwriting-text/element.ts +14 -0
  70. package/src/components/handwriting-text/engine.ts +108 -0
  71. package/src/components/handwriting-text/glyphs.ts +71 -0
  72. package/src/components/handwriting-text/handwriting-text.css +14 -0
  73. package/src/components/handwriting-text/react.tsx +23 -0
  74. package/src/components/magnetize-button/README.md +26 -0
  75. package/src/components/magnetize-button/element.ts +13 -0
  76. package/src/components/magnetize-button/engine.ts +84 -0
  77. package/src/components/magnetize-button/magnetize-button.css +17 -0
  78. package/src/components/magnetize-button/react.tsx +22 -0
  79. package/src/components/morphing-page-dots/README.md +28 -0
  80. package/src/components/morphing-page-dots/element.ts +16 -0
  81. package/src/components/morphing-page-dots/engine.ts +89 -0
  82. package/src/components/morphing-page-dots/morphing-page-dots.css +12 -0
  83. package/src/components/morphing-page-dots/react.tsx +32 -0
  84. package/src/components/not-found/README.md +26 -0
  85. package/src/components/not-found/element.ts +15 -0
  86. package/src/components/not-found/engine.ts +57 -0
  87. package/src/components/not-found/not-found.css +21 -0
  88. package/src/components/not-found/react.tsx +23 -0
  89. package/src/components/notification-stack/README.md +24 -0
  90. package/src/components/notification-stack/element.ts +26 -0
  91. package/src/components/notification-stack/engine.ts +329 -0
  92. package/src/components/notification-stack/notification-stack.css +41 -0
  93. package/src/components/notification-stack/react.tsx +28 -0
  94. package/src/components/particle-button/README.md +26 -0
  95. package/src/components/particle-button/element.ts +13 -0
  96. package/src/components/particle-button/engine.ts +52 -0
  97. package/src/components/particle-button/particle-button.css +13 -0
  98. package/src/components/particle-button/react.tsx +22 -0
  99. package/src/components/radio-group/README.md +43 -0
  100. package/src/components/radio-group/element.ts +41 -0
  101. package/src/components/radio-group/engine.ts +11 -0
  102. package/src/components/radio-group/radio-group.css +28 -0
  103. package/src/components/radio-group/react.tsx +60 -0
  104. package/src/components/radio-group/shared.ts +118 -0
  105. package/src/components/rating-scale/README.md +43 -0
  106. package/src/components/rating-scale/element.ts +41 -0
  107. package/src/components/rating-scale/engine.ts +63 -0
  108. package/src/components/rating-scale/rating-scale.css +22 -0
  109. package/src/components/rating-scale/react.tsx +60 -0
  110. package/src/components/scroll-preview-dock/README.md +24 -0
  111. package/src/components/scroll-preview-dock/element.ts +20 -0
  112. package/src/components/scroll-preview-dock/engine.ts +228 -0
  113. package/src/components/scroll-preview-dock/react.tsx +26 -0
  114. package/src/components/scroll-preview-dock/scroll-preview-dock.css +17 -0
  115. package/src/components/select/README.md +23 -9
  116. package/src/components/select/select.css +16 -0
  117. package/src/components/signature-pad/README.md +97 -0
  118. package/src/components/signature-pad/element.ts +57 -0
  119. package/src/components/signature-pad/engine.ts +550 -0
  120. package/src/components/signature-pad/react.tsx +56 -0
  121. package/src/components/signature-pad/signature-pad.css +130 -0
  122. package/src/components/stepper/README.md +46 -0
  123. package/src/components/stepper/element.ts +42 -0
  124. package/src/components/stepper/engine.ts +103 -0
  125. package/src/components/stepper/react.tsx +60 -0
  126. package/src/components/stepper/stepper.css +35 -0
  127. package/src/components/sticky-header/README.md +30 -0
  128. package/src/components/sticky-header/element.ts +19 -0
  129. package/src/components/sticky-header/engine.ts +95 -0
  130. package/src/components/sticky-header/react.tsx +25 -0
  131. package/src/components/sticky-header/sticky-header.css +9 -0
  132. package/src/components/temperature-slider/README.md +42 -0
  133. package/src/components/temperature-slider/element.ts +53 -0
  134. package/src/components/temperature-slider/engine.ts +44 -0
  135. package/src/components/temperature-slider/react.tsx +66 -0
  136. package/src/components/temperature-slider/temperature-slider.css +29 -0
  137. package/src/components/voice-message-bubble/README.md +31 -0
  138. package/src/components/voice-message-bubble/element.ts +20 -0
  139. package/src/components/voice-message-bubble/engine.ts +79 -0
  140. package/src/components/voice-message-bubble/react.tsx +27 -0
  141. package/src/components/voice-message-bubble/voice-message-bubble.css +14 -0
  142. package/src/components/waveform-player/README.md +30 -0
  143. package/src/components/waveform-player/element.ts +21 -0
  144. package/src/components/waveform-player/engine.ts +344 -0
  145. package/src/components/waveform-player/react.tsx +27 -0
  146. package/src/components/waveform-player/waveform-player.css +50 -0
  147. package/src/components/wheel-picker/README.md +35 -0
  148. package/src/components/wheel-picker/element.ts +25 -0
  149. package/src/components/wheel-picker/engine.ts +239 -0
  150. package/src/components/wheel-picker/react.tsx +32 -0
  151. package/src/components/wheel-picker/wheel-picker.css +17 -0
  152. package/src/css/tokens.css +4 -0
  153. package/src/elements/index.ts +318 -258
  154. package/src/index.ts +21 -0
  155. package/src/react/index.ts +192 -171
  156. package/dist/chunk-SDQ776LG.js.map +0 -1
  157. /package/dist/{chunk-RBEKR5UZ.js.map → chunk-AWDEKDEJ.js.map} +0 -0
  158. /package/dist/{chunk-NFZIX3IA.js.map → chunk-EDMXWUW3.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 clamp4 = (value) => Math.min(steps.length - 1, Math.max(0, Math.round(value)));
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 = clamp4(options.index ?? (marked3 >= 0 ? marked3 : 0));
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 = clamp4(to);
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 normalize = (n) => Math.max(min, Math.min(upper, Number((min + Math.round((n - min) / step) * step).toFixed(10))));
2703
+ const normalize3 = (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 = normalize(Number.isFinite(options.value) ? options.value : Number.isFinite(initial) ? initial : min);
2714
+ let value = normalize3(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 = normalize(Number.isFinite(typed()) ? typed() : min);
2720
+ if (!pendingReset.defaultPrevented) value = normalize3(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 = normalize(next);
2731
+ value = normalize3(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) && normalize(n) === n) commit(n, true, false);
2747
+ if (Number.isFinite(n) && normalize3(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 clamp4 = (n) => Math.min(max, Math.max(min, n));
5909
- let value = options.value === null ? null : clamp4(finite(options.value) ? options.value : min);
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 = clamp4(next);
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 normalize = (n) => Math.max(min, Math.min(upper, fix(min + Math.round((n - min) / step) * step)));
6058
+ const normalize3 = (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)) ? normalize(Number(input.value)) : NaN);
6064
+ const read = () => inputs.map((input) => input.value.trim() !== "" && Number.isFinite(Number(input.value)) ? normalize3(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)) ? normalize(written) : current4[i];
6072
+ return Number(input.value) === Math.min(high, Math.max(low, written)) ? normalize3(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 normalize(candidate);
6081
+ if (finite2(candidate)) return normalize3(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)) ? normalize(Number(raw)) : NaN;
6191
+ const n = raw.trim() !== "" && Number.isFinite(Number(raw)) ? normalize3(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]) ? normalize(list3[i]) : values[i]);
6260
+ const candidate = inputs.map((_, i) => finite2(list3[i]) ? normalize3(list3[i]) : values[i]);
6261
6261
  values = ordered(candidate);
6262
6262
  render(dragging >= 0 ? "drag" : "glide");
6263
6263
  if (notify) commit(true);
@@ -6288,9 +6288,9 @@ 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, rounded) {
6291
+ function barPath(x, width, base, end, rounded2) {
6292
6292
  const height = Math.abs(base - end);
6293
- const r = rounded ? Math.min(END_RADIUS, width / 2, height) : 0;
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`;
@@ -8684,13 +8684,13 @@ function createPasswordStrength(root, options = {}) {
8684
8684
  let lit = 0;
8685
8685
  const paint = (animate) => {
8686
8686
  const previous = lit;
8687
- const level = input.value ? Math.max(1, result.score) : 0;
8688
- lit = level;
8687
+ const level2 = input.value ? Math.max(1, result.score) : 0;
8688
+ lit = level2;
8689
8689
  scope.attr(root, "data-mk-score", input.value ? String(result.score) : null);
8690
8690
  const bars = segments.map((segment) => segment.firstElementChild);
8691
- if (!animate || reduced()) gsap.set(bars, { scaleX: (i) => i < level ? 1 : 0 });
8692
- else if (level > previous) keep(gsap.fromTo(bars.slice(previous, level), { scaleX: 0 }, { scaleX: 1, duration: 0.35, ease: EASE.swatch, stagger: 0.07 }));
8693
- else if (level < previous) keep(gsap.to(bars.slice(level, previous).reverse(), { scaleX: 0, duration: 0.2, ease: "power2.in", stagger: 0.04 }));
8691
+ if (!animate || reduced()) gsap.set(bars, { scaleX: (i) => i < level2 ? 1 : 0 });
8692
+ else if (level2 > previous) keep(gsap.fromTo(bars.slice(previous, level2), { scaleX: 0 }, { scaleX: 1, duration: 0.35, ease: EASE.swatch, stagger: 0.07 }));
8693
+ else if (level2 < previous) keep(gsap.to(bars.slice(level2, previous).reverse(), { scaleX: 0, duration: 0.2, ease: "power2.in", stagger: 0.04 }));
8694
8694
  if (label.textContent !== result.label) {
8695
8695
  if (!animate || reduced()) label.textContent = result.label;
8696
8696
  else {
@@ -8982,8 +8982,8 @@ function createStarRating(root, options = {}) {
8982
8982
  const scope = createScope();
8983
8983
  const max = Math.max(1, Math.min(10, Math.round(Number.isFinite(options.max) ? options.max : 5)));
8984
8984
  const texts = options.labels ?? (max === 5 ? LABELS2 : []);
8985
- const clamp4 = (n) => Math.max(0, Math.min(max, n));
8986
- let value = clamp4(Number.isFinite(options.value) ? options.value : 0);
8985
+ const clamp5 = (n) => Math.max(0, Math.min(max, n));
8986
+ let value = clamp5(Number.isFinite(options.value) ? options.value : 0);
8987
8987
  const name = options.name ?? `rating-${++sequence10}`;
8988
8988
  const group = document.createElement("div");
8989
8989
  group.dataset.mkStars = "";
@@ -9071,7 +9071,7 @@ function createStarRating(root, options = {}) {
9071
9071
  };
9072
9072
  const choose = (next, notify, animate) => {
9073
9073
  if (scope.disposed) return;
9074
- const target = clamp4(Math.round(next));
9074
+ const target = clamp5(Math.round(next));
9075
9075
  if (target === value) return;
9076
9076
  value = target;
9077
9077
  paint();
@@ -13778,8 +13778,8 @@ function createDateTimePicker(root, options = {}) {
13778
13778
  const segmentsOf2 = (date) => {
13779
13779
  if (!date) return { day: null, month: null, year: null, hour: null, minute: null, dayPeriod: null };
13780
13780
  const hour = date.getHours();
13781
- const clock = twelve ? to12(hour) : { hour, period: null };
13782
- return { day: date.getDate(), month: date.getMonth() + 1, year: date.getFullYear(), hour: clock.hour, minute: date.getMinutes(), dayPeriod: clock.period };
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 };
13783
13783
  };
13784
13784
  const dateOf2 = (values) => {
13785
13785
  const { day: day2, month, year, hour, minute } = values;
@@ -13828,18 +13828,18 @@ function createDateTimePicker(root, options = {}) {
13828
13828
  scope.on(box, "focusout", (event) => {
13829
13829
  if (!box.contains(event.relatedTarget) && field.element.hasAttribute("aria-invalid")) keep(shake(box));
13830
13830
  });
13831
- const rounded = (date) => {
13831
+ const rounded2 = (date) => {
13832
13832
  const result = new Date(date.getTime());
13833
13833
  result.setSeconds(0, 0);
13834
13834
  result.setMinutes(Math.round(result.getMinutes() / step) * step);
13835
13835
  return result;
13836
13836
  };
13837
- const clamp4 = (date) => min && date < min ? new Date(min.getTime()) : max && date > max ? new Date(max.getTime()) : date;
13837
+ const clamp5 = (date) => min && date < min ? new Date(min.getTime()) : max && date > max ? new Date(max.getTime()) : date;
13838
13838
  const timeOfDay = () => {
13839
13839
  if (value) return { hour: value.getHours(), minute: value.getMinutes() };
13840
13840
  const time2 = timeField.value?.split(":").map(Number);
13841
13841
  if (time2 && time2.length >= 2) return { hour: time2[0], minute: time2[1] };
13842
- const current3 = rounded(/* @__PURE__ */ new Date());
13842
+ const current3 = rounded2(/* @__PURE__ */ new Date());
13843
13843
  return { hour: current3.getHours(), minute: current3.getMinutes() };
13844
13844
  };
13845
13845
  const calendar = createRangeCalendar(calendarHost, {
@@ -13855,7 +13855,7 @@ function createDateTimePicker(root, options = {}) {
13855
13855
  const { hour, minute } = timeOfDay();
13856
13856
  const next = new Date(range.start.getTime());
13857
13857
  next.setHours(hour, minute, 0, 0);
13858
- commit(clamp4(next), true);
13858
+ commit(clamp5(next), true);
13859
13859
  }
13860
13860
  });
13861
13861
  scope.add(() => calendar.destroy());
@@ -13871,7 +13871,7 @@ function createDateTimePicker(root, options = {}) {
13871
13871
  const base = value ?? toDate(options.today ?? /* @__PURE__ */ new Date());
13872
13872
  const next = new Date(base.getTime());
13873
13873
  next.setHours(hour, minute, 0, 0);
13874
- commit(clamp4(next), true);
13874
+ commit(clamp5(next), true);
13875
13875
  }
13876
13876
  });
13877
13877
  scope.add(() => timeField.destroy());
@@ -13905,7 +13905,7 @@ function createDateTimePicker(root, options = {}) {
13905
13905
  });
13906
13906
  scope.on(now2, "click", () => {
13907
13907
  keep(press(now2));
13908
- const current3 = rounded(/* @__PURE__ */ new Date());
13908
+ const current3 = rounded2(/* @__PURE__ */ new Date());
13909
13909
  commit(problem(current3) ? value : current3, true);
13910
13910
  calendar.focusDay(current3, false);
13911
13911
  });
@@ -15393,15 +15393,15 @@ function createTreeView(root, options = {}) {
15393
15393
  item.setAttribute("aria-posinset", String(index + 1));
15394
15394
  item.tabIndex = -1;
15395
15395
  if (node.disabled) item.setAttribute("aria-disabled", "true");
15396
- const branch = isBranch(node);
15397
- if (branch) item.setAttribute("aria-expanded", String(expanded.has(node.id)));
15396
+ const branch2 = isBranch(node);
15397
+ if (branch2) item.setAttribute("aria-expanded", String(expanded.has(node.id)));
15398
15398
  if (!options.checkable && selected === node.id) item.setAttribute("aria-selected", "true");
15399
15399
  const line = document.createElement("div");
15400
15400
  line.dataset.mkTreeRow = "";
15401
15401
  line.style.setProperty("--mk-tree-depth", String(depth));
15402
15402
  const chevron2 = document.createElement("span");
15403
15403
  chevron2.dataset.mkTreeChevron = "";
15404
- if (branch) chevron2.innerHTML = CHEVRON3;
15404
+ if (branch2) chevron2.innerHTML = CHEVRON3;
15405
15405
  line.append(chevron2);
15406
15406
  if (options.checkable) {
15407
15407
  const check2 = document.createElement("span");
@@ -15417,9 +15417,9 @@ function createTreeView(root, options = {}) {
15417
15417
  line.append(icon2);
15418
15418
  } else if (options.icons) {
15419
15419
  const icon2 = document.createElement("span");
15420
- if (branch) icon2.dataset.mkTreeFolder = "";
15420
+ if (branch2) icon2.dataset.mkTreeFolder = "";
15421
15421
  else icon2.dataset.mkTreePage = "";
15422
- icon2.innerHTML = branch ? FOLDER : PAGE;
15422
+ icon2.innerHTML = branch2 ? FOLDER : PAGE;
15423
15423
  line.append(icon2);
15424
15424
  }
15425
15425
  const label = document.createElement("span");
@@ -15427,7 +15427,7 @@ function createTreeView(root, options = {}) {
15427
15427
  fillLabel(node, label);
15428
15428
  line.append(label);
15429
15429
  item.append(line);
15430
- if (branch) {
15430
+ if (branch2) {
15431
15431
  const group = document.createElement("ul");
15432
15432
  group.setAttribute("role", "group");
15433
15433
  group.hidden = !expanded.has(node.id);
@@ -21220,6 +21220,3884 @@ function createScrollIsland(root, options = {}) {
21220
21220
  };
21221
21221
  }
21222
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
+ const pen = document.createElement("span");
21339
+ pen.dataset.mkSignatureCursor = "";
21340
+ pen.setAttribute("aria-hidden", "true");
21341
+ const ghost = document.createElementNS(SVG_NS, "svg");
21342
+ ghost.setAttribute("data-mk-signature-ghost", "");
21343
+ ghost.setAttribute("aria-hidden", "true");
21344
+ ghost.setAttribute("preserveAspectRatio", "none");
21345
+ surface.append(svg2, ghost, placeholder2, pen);
21346
+ const footer = document.createElement("div");
21347
+ footer.dataset.mkSignatureFooter = "";
21348
+ const toolbar = document.createElement("div");
21349
+ toolbar.dataset.mkSignatureToolbar = "";
21350
+ toolbar.setAttribute("role", "group");
21351
+ toolbar.setAttribute("aria-label", "Herramientas de firma");
21352
+ const makeButton = (action, text) => {
21353
+ const button2 = document.createElement("button");
21354
+ button2.type = "button";
21355
+ button2.dataset.mkSignatureAction = action;
21356
+ const paths = { undo: "M9 5 4 10l5 5M4 10h9a6 6 0 0 1 6 6", redo: "m15 5 5 5-5 5m5-5h-9a6 6 0 0 0-6 6", clear: "m9 5 1-2h4l1 2M4 6h16M7 6l1 15h8l1-15M10 10v7m4-7v7" };
21357
+ button2.innerHTML = `<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="${paths[action]}"/></svg>`;
21358
+ const caption = document.createElement("span");
21359
+ caption.textContent = text;
21360
+ button2.append(caption);
21361
+ toolbar.append(button2);
21362
+ return button2;
21363
+ };
21364
+ const undoButton = makeButton("undo", "Deshacer");
21365
+ const redoButton = makeButton("redo", "Rehacer");
21366
+ const clearButton = makeButton("clear", "Limpiar");
21367
+ if (options.toolbar !== false) footer.append(toolbar);
21368
+ const status = document.createElement("span");
21369
+ status.dataset.mkSignatureStatus = "";
21370
+ status.setAttribute("role", "status");
21371
+ status.setAttribute("aria-live", "polite");
21372
+ const heading = document.createElement("div");
21373
+ heading.dataset.mkSignatureHeader = "";
21374
+ const title = document.createElement("span");
21375
+ title.textContent = options.label ?? "Tu firma";
21376
+ heading.append(title, status);
21377
+ const hint = document.createElement("p");
21378
+ hint.dataset.mkSignatureHint = "";
21379
+ hint.id = `mk-signature-hint-${++nextId2}`;
21380
+ hint.textContent = options.hint ?? "Dibuja con el rat\xF3n, el dedo o un l\xE1piz. Puedes deshacer cada trazo.";
21381
+ svg2.setAttribute("aria-describedby", hint.id);
21382
+ wrapper.append(heading, surface, footer, hint);
21383
+ let hidden = null;
21384
+ if (options.name) {
21385
+ hidden = document.createElement("input");
21386
+ hidden.type = "hidden";
21387
+ hidden.name = options.name;
21388
+ wrapper.append(hidden);
21389
+ }
21390
+ root.append(wrapper);
21391
+ scope.add(() => wrapper.remove());
21392
+ for (const name of ["data-mk-disabled", "data-mk-readonly", "data-mk-drawing", "data-mk-empty", "data-mk-pen-visible"]) scope.attr(root, name, null);
21393
+ scope.attr(root, "data-mk-ready", "");
21394
+ let dimensions = { width: 640, height: 240 };
21395
+ let active = null;
21396
+ const effects = /* @__PURE__ */ new Set();
21397
+ const statusCount = document.createElement("span");
21398
+ const statusLabel = document.createElement("span");
21399
+ let shown4 = null;
21400
+ const paintStatus = () => {
21401
+ const count = strokes.length;
21402
+ if (shown4 && shown4.count === count && shown4.readOnly === readOnly) return;
21403
+ const before = shown4;
21404
+ shown4 = { count, readOnly };
21405
+ const animate = before !== null && !reduced();
21406
+ if (!count) {
21407
+ status.textContent = "Sin firma";
21408
+ if (animate && before.count) keep(blurIn(status, { from: "soft", duration: 0.25 }));
21409
+ return;
21410
+ }
21411
+ statusLabel.replaceChildren(statusCount, ` ${count === 1 ? "trazo" : "trazos"} \xB7 ${readOnly ? "Solo lectura" : "Firma capturada"}`);
21412
+ status.replaceChildren(statusLabel);
21413
+ if (animate && before.count) keep(rollDigits(statusCount, String(count), count > before.count ? 1 : -1, 0.3));
21414
+ else {
21415
+ statusCount.textContent = String(count);
21416
+ if (animate) keep(blurIn(status, { from: "soft", duration: 0.25 }));
21417
+ }
21418
+ };
21419
+ const keep = (effect) => {
21420
+ for (const animation of effects) if (animation.totalProgress() === 1) effects.delete(animation);
21421
+ if (effect) effects.add(effect);
21422
+ };
21423
+ const locked = () => disabled || readOnly;
21424
+ const update = () => {
21425
+ root.toggleAttribute("data-mk-empty", !strokes.length && !active);
21426
+ root.toggleAttribute("data-mk-disabled", disabled);
21427
+ root.toggleAttribute("data-mk-readonly", readOnly);
21428
+ svg2.setAttribute("aria-disabled", String(disabled));
21429
+ placeholder2.hidden = strokes.length > 0 || active !== null;
21430
+ undoButton.disabled = locked() || !undoStack.length;
21431
+ redoButton.disabled = locked() || !redoStack.length;
21432
+ clearButton.disabled = locked() || !strokes.length;
21433
+ paintStatus();
21434
+ if (hidden) {
21435
+ hidden.disabled = disabled;
21436
+ hidden.value = JSON.stringify(exportData());
21437
+ }
21438
+ };
21439
+ const render = () => {
21440
+ const rect = surface.getBoundingClientRect();
21441
+ if (rect.width > 0 && rect.height > 0) dimensions = { width: rect.width, height: rect.height };
21442
+ svg2.setAttribute("viewBox", `0 0 ${dimensions.width} ${dimensions.height}`);
21443
+ svg2.replaceChildren(...strokes.map((stroke) => makePath(stroke, dimensions.width, dimensions.height)));
21444
+ if (active) {
21445
+ active.path = makePath(active.stroke, dimensions.width, dimensions.height);
21446
+ svg2.append(active.path);
21447
+ }
21448
+ };
21449
+ const emit = (reason) => {
21450
+ const detail = { data: exportData(), reason, isEmpty: !strokes.length, canUndo: !!undoStack.length, canRedo: !!redoStack.length };
21451
+ options.onChange?.(exportData(), { ...detail, data: exportData() });
21452
+ if (scope.disposed) return;
21453
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail }));
21454
+ };
21455
+ const release = (pointerId) => {
21456
+ try {
21457
+ surface.releasePointerCapture?.(pointerId);
21458
+ } catch {
21459
+ }
21460
+ };
21461
+ const cancel = () => {
21462
+ if (!active) return;
21463
+ const pointerId = active.pointerId;
21464
+ active = null;
21465
+ root.removeAttribute("data-mk-drawing");
21466
+ release(pointerId);
21467
+ render();
21468
+ update();
21469
+ };
21470
+ const remember = () => {
21471
+ undoStack.push(strokes);
21472
+ if (undoStack.length > historyLimit) undoStack.shift();
21473
+ redoStack = [];
21474
+ };
21475
+ const pulse = (button2) => {
21476
+ keep(press(button2));
21477
+ const icon2 = button2.querySelector("svg");
21478
+ const turn = button2 === undoButton ? -50 : button2 === redoButton ? 50 : -14;
21479
+ if (icon2 && !reduced()) keep(gsap.fromTo(icon2, { rotate: turn }, { rotate: 0, duration: 0.5, ease: EASE.click, overwrite: "auto", clearProps: "transform" }));
21480
+ };
21481
+ const wipeId = `mk-signature-wipe-${++nextId2}`;
21482
+ let wipes = 0;
21483
+ const animateInk = (before, reason) => {
21484
+ if (reduced()) return;
21485
+ const { width, height } = dimensions;
21486
+ const byX = (a, b) => (a.points[0]?.x ?? 0) - (b.points[0]?.x ?? 0);
21487
+ const removed = before.filter((stroke) => !strokes.includes(stroke)).sort(byX);
21488
+ const added = strokes.filter((stroke) => !before.includes(stroke)).sort(byX);
21489
+ ghost.setAttribute("viewBox", `0 0 ${width} ${height}`);
21490
+ if (removed.length && reason === "clear") {
21491
+ const svgNode = (tag, attributes) => {
21492
+ const node = document.createElementNS(SVG_NS, tag);
21493
+ for (const [name, value] of Object.entries(attributes)) node.setAttribute(name, String(value));
21494
+ return node;
21495
+ };
21496
+ const points = removed.flatMap((stroke) => stroke.points);
21497
+ const pad3 = inkWidth * 2 + 8;
21498
+ const left = Math.min(...points.map((point) => point.x)) * width - pad3;
21499
+ const right = Math.max(...points.map((point) => point.x)) * width + pad3;
21500
+ const top = Math.max(0, Math.min(...points.map((point) => point.y)) * height - pad3);
21501
+ const bottom = Math.min(height, Math.max(...points.map((point) => point.y)) * height + pad3);
21502
+ const id = `${wipeId}-${++wipes}`;
21503
+ const clip = svgNode("clipPath", { id });
21504
+ const reveal = svgNode("rect", { x: left, y: 0, width: width * 2, height });
21505
+ clip.append(reveal);
21506
+ const ink = svgNode("g", { "clip-path": `url(#${id})` });
21507
+ ink.append(...removed.map((stroke) => makePath(stroke, width, height)));
21508
+ const edge = svgNode("rect", { x: left, y: top, width: 2, height: Math.max(24, bottom - top), rx: 1, fill: "currentColor", opacity: 0 });
21509
+ ghost.append(clip, ink, edge);
21510
+ const done = () => {
21511
+ clip.remove();
21512
+ ink.remove();
21513
+ edge.remove();
21514
+ };
21515
+ const sweep = Math.min(0.6, Math.max(0.36, (right - left) / 900));
21516
+ keep(gsap.timeline({ onComplete: done, onInterrupt: done }).to([reveal, edge], { attr: { x: right }, duration: sweep, ease: "power2.inOut" }, 0).to(edge, { opacity: 0.3, duration: 0.08 }, 0).to(edge, { opacity: 0, duration: 0.14 }, sweep - 0.12));
21517
+ } else removed.forEach((stroke) => {
21518
+ const path = makePath(stroke, width, height);
21519
+ ghost.append(path);
21520
+ const length = path.getTotalLength?.() ?? 0;
21521
+ const done = () => path.remove();
21522
+ if (!length) {
21523
+ keep(gsap.to(path, { opacity: 0, duration: 0.25, onComplete: done }));
21524
+ return;
21525
+ }
21526
+ path.style.strokeDasharray = `${length} ${length}`;
21527
+ keep(gsap.timeline({ onComplete: done, onInterrupt: done }).fromTo(path, { strokeDashoffset: 0 }, { strokeDashoffset: length, duration: 0.5, ease: "power2.inOut" }, 0).to(path, { opacity: 0, duration: 0.16 }, 0.36));
21528
+ });
21529
+ const rendered = [...svg2.children];
21530
+ added.forEach((stroke, index) => {
21531
+ const path = rendered[strokes.indexOf(stroke)];
21532
+ const length = path?.getTotalLength?.() ?? 0;
21533
+ if (!path || !length) return;
21534
+ path.style.strokeDasharray = `${length} ${length}`;
21535
+ keep(gsap.fromTo(path, { strokeDashoffset: length }, { strokeDashoffset: 0, duration: 0.6, delay: Math.min(index * 0.08, 0.48), ease: EASE.wipe, clearProps: "strokeDasharray,strokeDashoffset" }));
21536
+ });
21537
+ };
21538
+ const undo = () => {
21539
+ if (scope.disposed) return;
21540
+ cancel();
21541
+ if (!undoStack.length) return;
21542
+ const before = strokes;
21543
+ redoStack.push(strokes);
21544
+ strokes = undoStack.pop();
21545
+ render();
21546
+ update();
21547
+ emit("undo");
21548
+ animateInk(before, "undo");
21549
+ };
21550
+ const redo = () => {
21551
+ if (scope.disposed) return;
21552
+ cancel();
21553
+ if (!redoStack.length) return;
21554
+ const before = strokes;
21555
+ undoStack.push(strokes);
21556
+ strokes = redoStack.pop();
21557
+ render();
21558
+ update();
21559
+ emit("redo");
21560
+ animateInk(before, "redo");
21561
+ };
21562
+ const clear = () => {
21563
+ if (scope.disposed) return;
21564
+ cancel();
21565
+ if (!strokes.length) return;
21566
+ const before = strokes;
21567
+ remember();
21568
+ strokes = [];
21569
+ render();
21570
+ update();
21571
+ emit("clear");
21572
+ animateInk(before, "clear");
21573
+ };
21574
+ const form = hidden?.form;
21575
+ if (form) scope.on(form, "reset", (event) => {
21576
+ scope.timeout(() => {
21577
+ if (scope.disposed || event.defaultPrevented || hidden?.form !== form) return;
21578
+ const changed = !sameStrokes(strokes, initialStrokes);
21579
+ cancel();
21580
+ strokes = cloneStrokes(initialStrokes);
21581
+ undoStack = [];
21582
+ redoStack = [];
21583
+ render();
21584
+ update();
21585
+ if (changed) emit("reset");
21586
+ }, 0);
21587
+ });
21588
+ const pointFrom = (event) => {
21589
+ const rect = surface.getBoundingClientRect();
21590
+ if (!rect.width || !rect.height || !finite5(event.clientX) || !finite5(event.clientY)) return null;
21591
+ return { x: clamp4((event.clientX - rect.left) / rect.width, 0, 1), y: clamp4((event.clientY - rect.top) / rect.height, 0, 1) };
21592
+ };
21593
+ const addPoint = (event) => {
21594
+ if (!active) return;
21595
+ const point = pointFrom(event);
21596
+ if (!point || active.stroke.points.length >= MAX_POINTS - strokes.reduce((sum, stroke) => sum + stroke.points.length, 0)) return;
21597
+ const last = active.stroke.points[active.stroke.points.length - 1];
21598
+ if (point.x === last.x && point.y === last.y) return;
21599
+ active.stroke.points.push(point);
21600
+ active.path.setAttribute("d", strokePath(active.stroke.points, dimensions.width, dimensions.height));
21601
+ };
21602
+ scope.on(surface, "pointerdown", (event) => {
21603
+ const pointer2 = event;
21604
+ 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;
21605
+ const point = pointFrom(pointer2);
21606
+ if (!point) return;
21607
+ pointer2.preventDefault();
21608
+ const themed = getComputedStyle(root).getPropertyValue("--mk-signature-ink").trim() || getComputedStyle(root).color;
21609
+ const color = validColor(options.color) ? options.color : validColor(themed) ? themed : "#252735";
21610
+ const stroke = { points: [point], color, width: inkWidth };
21611
+ active = { pointerId: pointer2.pointerId, stroke, path: makePath(stroke, dimensions.width, dimensions.height) };
21612
+ render();
21613
+ update();
21614
+ root.setAttribute("data-mk-drawing", "");
21615
+ try {
21616
+ surface.setPointerCapture?.(pointer2.pointerId);
21617
+ } catch {
21618
+ }
21619
+ });
21620
+ scope.on(window, "pointermove", (event) => {
21621
+ const pointer2 = event;
21622
+ if (!active || pointer2.pointerId !== active.pointerId) return;
21623
+ pointer2.preventDefault();
21624
+ const samples = typeof pointer2.getCoalescedEvents === "function" ? pointer2.getCoalescedEvents() : [];
21625
+ for (const sample of samples) addPoint(sample);
21626
+ addPoint(pointer2);
21627
+ }, { passive: false });
21628
+ scope.on(window, "pointerup", (event) => {
21629
+ const pointer2 = event;
21630
+ if (!active || pointer2.pointerId !== active.pointerId) return;
21631
+ addPoint(pointer2);
21632
+ const completed = active;
21633
+ active = null;
21634
+ root.removeAttribute("data-mk-drawing");
21635
+ release(completed.pointerId);
21636
+ remember();
21637
+ strokes = [...strokes, completed.stroke];
21638
+ update();
21639
+ emit("draw");
21640
+ });
21641
+ for (const type of ["pointercancel", "lostpointercapture"]) scope.on(type === "pointercancel" ? window : surface, type, (event) => {
21642
+ if (active?.pointerId === event.pointerId) cancel();
21643
+ });
21644
+ scope.on(window, "blur", cancel);
21645
+ const movePen = (event) => {
21646
+ const pointer2 = event;
21647
+ const rect = surface.getBoundingClientRect();
21648
+ root.toggleAttribute("data-mk-pen-visible", pointer2.pointerType !== "touch" && !locked());
21649
+ pen.style.left = `${pointer2.clientX - rect.left}px`;
21650
+ pen.style.top = `${pointer2.clientY - rect.top}px`;
21651
+ };
21652
+ scope.on(surface, "pointerenter", movePen);
21653
+ scope.on(surface, "pointermove", movePen);
21654
+ scope.on(surface, "pointerleave", () => root.removeAttribute("data-mk-pen-visible"));
21655
+ scope.on(document, "visibilitychange", () => {
21656
+ if (document.hidden) cancel();
21657
+ });
21658
+ for (const [button2, action] of [[undoButton, undo], [redoButton, redo], [clearButton, clear]]) scope.on(button2, "click", () => {
21659
+ if (locked() || button2.disabled) return;
21660
+ pulse(button2);
21661
+ action();
21662
+ });
21663
+ if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(render)).observe(surface);
21664
+ scope.on(window, "resize", render);
21665
+ scope.add(() => {
21666
+ cancel();
21667
+ for (const effect of effects) effect.kill();
21668
+ });
21669
+ render();
21670
+ update();
21671
+ const exportSVG = (settings = {}) => {
21672
+ const width = finite5(settings.width) ? clamp4(settings.width, 1, 4096) : dimensions.width;
21673
+ const height = finite5(settings.height) ? clamp4(settings.height, 1, 4096) : dimensions.height;
21674
+ const output = document.createElementNS(SVG_NS, "svg");
21675
+ output.setAttribute("width", String(rounded(width)));
21676
+ output.setAttribute("height", String(rounded(height)));
21677
+ output.setAttribute("viewBox", `0 0 ${width} ${height}`);
21678
+ if (validColor(settings.background)) {
21679
+ const background = document.createElementNS(SVG_NS, "rect");
21680
+ background.setAttribute("width", "100%");
21681
+ background.setAttribute("height", "100%");
21682
+ background.setAttribute("fill", settings.background);
21683
+ output.append(background);
21684
+ }
21685
+ output.append(...strokes.map((stroke) => makePath(stroke, width, height)));
21686
+ return new XMLSerializer().serializeToString(output);
21687
+ };
21688
+ const pending = /* @__PURE__ */ new Set();
21689
+ scope.add(() => {
21690
+ for (const cancelExport of pending) cancelExport();
21691
+ pending.clear();
21692
+ });
21693
+ return {
21694
+ get data() {
21695
+ return exportData();
21696
+ },
21697
+ get isEmpty() {
21698
+ return !strokes.length;
21699
+ },
21700
+ get canUndo() {
21701
+ return !!undoStack.length;
21702
+ },
21703
+ get canRedo() {
21704
+ return !!redoStack.length;
21705
+ },
21706
+ undo,
21707
+ redo,
21708
+ clear,
21709
+ exportData,
21710
+ importData(value, notify = true) {
21711
+ if (scope.disposed) return false;
21712
+ const next = validatedData(value);
21713
+ if (!next) return false;
21714
+ if (sameStrokes(next.strokes, strokes)) return true;
21715
+ cancel();
21716
+ strokes = next.strokes;
21717
+ undoStack = [];
21718
+ redoStack = [];
21719
+ render();
21720
+ update();
21721
+ if (notify) emit("import");
21722
+ return true;
21723
+ },
21724
+ exportSVG: (settings) => scope.disposed ? "" : exportSVG(settings),
21725
+ exportPNG(settings = {}) {
21726
+ if (scope.disposed) return Promise.resolve(null);
21727
+ const canvas = document.createElement("canvas");
21728
+ let context;
21729
+ try {
21730
+ context = canvas.getContext("2d");
21731
+ } catch {
21732
+ return Promise.resolve(null);
21733
+ }
21734
+ if (!context || typeof canvas.toBlob !== "function") return Promise.resolve(null);
21735
+ const scale = finite5(settings.scale) ? clamp4(settings.scale, 1, 4) : 2;
21736
+ canvas.width = Math.round((finite5(settings.width) ? clamp4(settings.width, 1, 4096) : dimensions.width) * scale);
21737
+ canvas.height = Math.round((finite5(settings.height) ? clamp4(settings.height, 1, 4096) : dimensions.height) * scale);
21738
+ return new Promise((resolve2) => {
21739
+ const image = new Image();
21740
+ let finished = false;
21741
+ const done = (blob) => {
21742
+ if (finished) return;
21743
+ finished = true;
21744
+ image.onload = null;
21745
+ image.onerror = null;
21746
+ pending.delete(cancelExport);
21747
+ clearTimeout(timer2);
21748
+ resolve2(scope.disposed ? null : blob);
21749
+ };
21750
+ const cancelExport = () => {
21751
+ done(null);
21752
+ image.src = "";
21753
+ };
21754
+ const timer2 = setTimeout(cancelExport, 1e4);
21755
+ pending.add(cancelExport);
21756
+ image.onerror = () => done(null);
21757
+ image.onload = () => {
21758
+ try {
21759
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
21760
+ canvas.toBlob(done, "image/png");
21761
+ } catch {
21762
+ done(null);
21763
+ }
21764
+ };
21765
+ image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(exportSVG(settings))}`;
21766
+ });
21767
+ },
21768
+ setDisabled(value) {
21769
+ if (!scope.disposed) {
21770
+ cancel();
21771
+ disabled = Boolean(value);
21772
+ update();
21773
+ }
21774
+ },
21775
+ setReadOnly(value) {
21776
+ if (!scope.disposed) {
21777
+ cancel();
21778
+ readOnly = Boolean(value);
21779
+ update();
21780
+ }
21781
+ },
21782
+ destroy: () => scope.dispose()
21783
+ };
21784
+ }
21785
+
21786
+ // src/components/waveform-player/engine.ts
21787
+ var initialState = () => ({ status: "idle", currentTime: 0, duration: 0, playbackRate: 1, error: null });
21788
+ var finite6 = (n) => Number.isFinite(n) && n >= 0;
21789
+ var clock = (n) => `${Math.floor(n / 60)}:${String(Math.floor(n % 60)).padStart(2, "0")}`;
21790
+ var playIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m9 6 9 6-9 6Z"/></svg>';
21791
+ var pauseIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M8 6v12M16 6v12"/></svg>';
21792
+ var level = (n) => typeof n === "number" && Number.isFinite(n) ? Math.max(0, Math.min(1, n)) : 0;
21793
+ var resample = (values, count) => count === values.length ? [...values] : Array.from({ length: count }, (_, k) => {
21794
+ const from = Math.floor(k * values.length / count);
21795
+ const slice = values.slice(from, Math.max(from + 1, Math.floor((k + 1) * values.length / count)));
21796
+ return slice.reduce((sum, n) => sum + n, 0) / slice.length;
21797
+ });
21798
+ function createWaveformPlayer(root, options = {}) {
21799
+ if (!root) return inert({ play: async () => false, pause() {
21800
+ }, seek() {
21801
+ }, update() {
21802
+ }, state: initialState(), audio: null });
21803
+ registerMotion();
21804
+ const scope = createScope();
21805
+ let opts = { ...options };
21806
+ let state = initialState();
21807
+ let source = "";
21808
+ let request = 0;
21809
+ let requested = false;
21810
+ let pending = null;
21811
+ const make = (tag, part3, parent = root) => {
21812
+ const el5 = document.createElement(tag);
21813
+ el5.setAttribute(`data-mk-wave-${part3}`, "");
21814
+ parent.append(el5);
21815
+ return el5;
21816
+ };
21817
+ const container = make("div", "content");
21818
+ scope.add(() => container.remove());
21819
+ const audio = make("audio", "audio", container);
21820
+ audio.preload = "metadata";
21821
+ audio.hidden = true;
21822
+ const toggle = make("button", "toggle", container);
21823
+ toggle.type = "button";
21824
+ const icon2 = make("span", "icon", toggle);
21825
+ const body = make("div", "body", container);
21826
+ const track = make("div", "track", body);
21827
+ const bars = make("div", "bars", track);
21828
+ bars.setAttribute("aria-hidden", "true");
21829
+ const head = make("span", "head", track);
21830
+ head.setAttribute("aria-hidden", "true");
21831
+ const preview = make("span", "preview", track);
21832
+ preview.setAttribute("aria-hidden", "true");
21833
+ preview.hidden = true;
21834
+ const range = make("input", "seek", track);
21835
+ range.type = "range";
21836
+ range.min = "0";
21837
+ range.max = "0";
21838
+ range.step = "0.1";
21839
+ const footer = make("div", "footer", body);
21840
+ const time2 = make("span", "time", footer);
21841
+ const rate = make("button", "rate", footer);
21842
+ rate.type = "button";
21843
+ const message = make("span", "message", container);
21844
+ message.setAttribute("role", "status");
21845
+ message.setAttribute("aria-live", "polite");
21846
+ scope.attr(root, "data-mk-ready", "");
21847
+ scope.attr(root, "data-mk-wave-state", "idle");
21848
+ scope.attr(root, "data-mk-wave-scrubbing", null);
21849
+ let barNodes = [];
21850
+ const effects = /* @__PURE__ */ new Set();
21851
+ const keep = (effect) => {
21852
+ for (const animation of effects) if (animation.totalProgress() === 1) effects.delete(animation);
21853
+ if (effect) effects.add(effect);
21854
+ };
21855
+ let iconMotion = null;
21856
+ let lastPlaying;
21857
+ let lastRate = "";
21858
+ let following = false;
21859
+ const scrubbing = () => root.hasAttribute("data-mk-wave-scrubbing");
21860
+ const paintProgress = (seconds, animate = true) => {
21861
+ const progress = state.duration ? Math.max(0, Math.min(1, seconds / state.duration)) : 0;
21862
+ track.style.setProperty("--mk-wave-progress", String(progress));
21863
+ barNodes.forEach((bar, i) => {
21864
+ const played = (i + 0.5) / barNodes.length <= progress;
21865
+ if (bar.hasAttribute("data-mk-played") === played) return;
21866
+ bar.toggleAttribute("data-mk-played", played);
21867
+ if (animate && !scrubbing() && !reduced()) keep(gsap.fromTo(bar, { scaleY: 0.72 }, { scaleY: 1, duration: 0.35, ease: EASE.swatch, overwrite: "auto", clearProps: "transform" }));
21868
+ });
21869
+ };
21870
+ const followPlayback = () => {
21871
+ if (!scope.disposed && state.status === "playing") paintProgress(audio.currentTime);
21872
+ };
21873
+ const showPreview = (seconds, ratio) => {
21874
+ preview.textContent = clock(seconds);
21875
+ preview.style.setProperty("--mk-wave-at", String(Math.max(0.04, Math.min(0.96, ratio))));
21876
+ preview.hidden = false;
21877
+ };
21878
+ const snapshot = () => ({ ...state });
21879
+ const rates = () => {
21880
+ const values = opts.playbackRates === false ? [] : opts.playbackRates ?? [1, 1.5, 2];
21881
+ return Array.isArray(values) ? [...new Set(values.filter((n) => typeof n === "number" && Number.isFinite(n) && n >= 0.25 && n <= 4))] : [];
21882
+ };
21883
+ const paint = () => {
21884
+ const playing = state.status === "playing";
21885
+ const nextPlaying = playing || requested;
21886
+ if (lastPlaying !== nextPlaying) {
21887
+ icon2.innerHTML = nextPlaying ? pauseIcon : playIcon;
21888
+ iconMotion?.kill();
21889
+ if (lastPlaying !== void 0 && !reduced()) iconMotion = gsap.fromTo(icon2, { scale: 0.55, opacity: 0.3, filter: "blur(5px)" }, { scale: 1, opacity: 1, filter: "blur(0px)", duration: 0.3, ease: EASE.pop, clearProps: "transform,opacity,filter" });
21890
+ lastPlaying = nextPlaying;
21891
+ }
21892
+ toggle.setAttribute("aria-label", `${playing || requested ? "Pausar" : "Reproducir"} ${opts.label ?? "audio"}`);
21893
+ toggle.disabled = !!opts.disabled || !source;
21894
+ range.disabled = !!opts.disabled || !state.duration;
21895
+ range.max = String(state.duration);
21896
+ range.value = String(state.currentTime);
21897
+ range.setAttribute("aria-label", `Posici\xF3n de ${opts.label ?? "audio"}`);
21898
+ range.setAttribute("aria-valuetext", `${clock(state.currentTime)} de ${clock(state.duration)}`);
21899
+ time2.textContent = `${clock(state.currentTime)} / ${clock(state.duration)}`;
21900
+ rate.hidden = rates().length < 2;
21901
+ rate.disabled = !!opts.disabled;
21902
+ const rateLabel = `${state.playbackRate}\xD7`;
21903
+ if (lastRate !== rateLabel) {
21904
+ if (lastRate) keep(rollDigits(rate, rateLabel, 1, 0.28));
21905
+ else rate.textContent = rateLabel;
21906
+ lastRate = rateLabel;
21907
+ }
21908
+ rate.setAttribute("aria-label", `Velocidad ${state.playbackRate}\xD7. Cambiar velocidad`);
21909
+ paintProgress(state.currentTime);
21910
+ if (document.activeElement === range) showPreview(state.currentTime, state.duration ? state.currentTime / state.duration : 0);
21911
+ if (playing && !following) {
21912
+ following = true;
21913
+ gsap.ticker.add(followPlayback);
21914
+ } else if (!playing && following) {
21915
+ following = false;
21916
+ gsap.ticker.remove(followPlayback);
21917
+ }
21918
+ root.setAttribute("data-mk-wave-state", state.status);
21919
+ message.textContent = state.error ?? (state.status === "loading" ? "Cargando audio\u2026" : state.status === "ended" ? "Audio finalizado" : "");
21920
+ };
21921
+ const emit = (patch, event) => {
21922
+ if (scope.disposed) return;
21923
+ const previous = state.status;
21924
+ state = { ...state, ...patch };
21925
+ paint();
21926
+ const next = snapshot();
21927
+ if (event === "timeupdate") opts.onTimeUpdate?.(next);
21928
+ if (previous !== state.status) opts.onStateChange?.(snapshot());
21929
+ if (event === "play") opts.onPlay?.(snapshot());
21930
+ if (event === "pause") opts.onPause?.(snapshot());
21931
+ if (event === "ended") opts.onEnded?.(snapshot());
21932
+ if (event === "error") opts.onError?.(snapshot());
21933
+ if (previous !== state.status) root.dispatchEvent(new CustomEvent("mk:audio-statechange", { bubbles: true, detail: snapshot() }));
21934
+ if (event) root.dispatchEvent(new CustomEvent(`mk:audio-${event}`, { bubbles: true, detail: snapshot() }));
21935
+ };
21936
+ const bounce = (target) => {
21937
+ keep(press(target));
21938
+ };
21939
+ const fail = (message2) => {
21940
+ requested = false;
21941
+ emit({ status: "error", error: message2 }, "error");
21942
+ };
21943
+ const pause = () => {
21944
+ if (scope.disposed) return;
21945
+ request++;
21946
+ requested = false;
21947
+ pending = null;
21948
+ audio.pause();
21949
+ if (state.status !== "idle" && state.status !== "error" && state.status !== "ended" && state.status !== "paused") emit({ status: "paused" }, "pause");
21950
+ else paint();
21951
+ };
21952
+ const seek = (seconds) => {
21953
+ if (scope.disposed || !state.duration || !Number.isFinite(seconds)) return;
21954
+ const next = Math.max(0, Math.min(state.duration, seconds));
21955
+ try {
21956
+ audio.currentTime = next;
21957
+ } catch {
21958
+ return;
21959
+ }
21960
+ emit({ currentTime: next, ...state.status === "ended" && next < state.duration ? { status: "paused" } : {} }, "timeupdate");
21961
+ };
21962
+ const play = () => {
21963
+ if (scope.disposed || opts.disabled || !source) return Promise.resolve(false);
21964
+ if (pending) return pending;
21965
+ if (state.status === "playing") return Promise.resolve(true);
21966
+ if (state.status === "ended") seek(0);
21967
+ const token = ++request;
21968
+ requested = true;
21969
+ emit({ status: "loading", error: null });
21970
+ let started;
21971
+ try {
21972
+ started = Promise.resolve(audio.play());
21973
+ } catch (error) {
21974
+ started = Promise.reject(error);
21975
+ }
21976
+ const result = started.then(() => {
21977
+ if (scope.disposed || token !== request) return false;
21978
+ requested = false;
21979
+ if (audio.paused) {
21980
+ emit({ status: "paused" });
21981
+ return false;
21982
+ }
21983
+ if (state.status !== "playing") emit({ status: "playing", error: null }, "play");
21984
+ return true;
21985
+ }).catch((error) => {
21986
+ if (!scope.disposed && token === request) {
21987
+ requested = false;
21988
+ if (error instanceof Error && error.name === "AbortError") emit({ status: "paused" });
21989
+ else fail("No se pudo reproducir el audio. Vuelve a intentarlo.");
21990
+ }
21991
+ return false;
21992
+ }).finally(() => {
21993
+ if (token === request) pending = null;
21994
+ });
21995
+ pending = result;
21996
+ return result;
21997
+ };
21998
+ const peakValues = () => {
21999
+ const supplied = Array.isArray(opts.peaks) ? opts.peaks : [];
22000
+ return supplied.length ? supplied.slice(0, 256).map(level) : Array(48).fill(0.24);
22001
+ };
22002
+ const barCount = (values) => {
22003
+ const width = bars.clientWidth;
22004
+ return width > 0 ? Math.max(12, Math.min(72, Math.floor((width + 3) / 8))) : values.length;
22005
+ };
22006
+ const renderPeaks = () => {
22007
+ const values = peakValues();
22008
+ bars.replaceChildren();
22009
+ barNodes = resample(values, barCount(values)).map((peak) => {
22010
+ const bar = make("i", "bar", bars);
22011
+ bar.style.height = `${8 + peak * 92}%`;
22012
+ return bar;
22013
+ });
22014
+ paintProgress(state.currentTime, false);
22015
+ };
22016
+ if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(() => {
22017
+ if (!scope.disposed && barCount(peakValues()) !== barNodes.length) renderPeaks();
22018
+ })).observe(bars);
22019
+ const update = (next) => {
22020
+ if (scope.disposed) return;
22021
+ const previousPeaks = opts.peaks;
22022
+ opts = { ...opts, ...next };
22023
+ const nextSource = typeof opts.src === "string" ? opts.src : "";
22024
+ if (source !== nextSource) {
22025
+ request++;
22026
+ pending = null;
22027
+ requested = false;
22028
+ audio.pause();
22029
+ source = nextSource;
22030
+ if (source) audio.setAttribute("src", source);
22031
+ else audio.removeAttribute("src");
22032
+ audio.load();
22033
+ audio.playbackRate = state.playbackRate;
22034
+ emit({ ...initialState(), playbackRate: state.playbackRate, status: source ? "loading" : "idle" });
22035
+ }
22036
+ if (opts.disabled && (requested || state.status === "playing")) pause();
22037
+ if (previousPeaks !== opts.peaks || !barNodes.length) renderPeaks();
22038
+ paint();
22039
+ };
22040
+ scope.on(toggle, "click", () => {
22041
+ bounce(toggle);
22042
+ if (requested || state.status === "playing") pause();
22043
+ else void play();
22044
+ });
22045
+ scope.on(range, "input", () => seek(Number(range.value)));
22046
+ scope.on(range, "pointermove", (event) => {
22047
+ if (!state.duration || opts.disabled) return;
22048
+ const rect = range.getBoundingClientRect();
22049
+ if (!rect.width) return;
22050
+ const inset = parseFloat(getComputedStyle(track).getPropertyValue("--mk-wave-inset")) || 0;
22051
+ const ratio = Math.max(0, Math.min(1, (event.clientX - rect.left - inset) / Math.max(1, rect.width - inset * 2)));
22052
+ showPreview(state.duration * ratio, ratio);
22053
+ });
22054
+ scope.on(range, "pointerleave", () => {
22055
+ if (document.activeElement !== range) preview.hidden = true;
22056
+ });
22057
+ scope.on(range, "focus", () => {
22058
+ if (state.duration) showPreview(state.currentTime, state.currentTime / state.duration);
22059
+ });
22060
+ scope.on(range, "blur", () => {
22061
+ preview.hidden = true;
22062
+ });
22063
+ scope.on(range, "pointerdown", () => {
22064
+ if (range.disabled) return;
22065
+ root.setAttribute("data-mk-wave-scrubbing", "");
22066
+ keep(press(head));
22067
+ });
22068
+ const release = () => {
22069
+ if (!scrubbing()) return;
22070
+ root.removeAttribute("data-mk-wave-scrubbing");
22071
+ if (!reduced()) keep(gsap.fromTo(head, { scale: 1.12 }, { scale: 1, duration: 0.4, ease: EASE.swatch, overwrite: "auto", clearProps: "transform" }));
22072
+ };
22073
+ scope.on(window, "pointerup", release);
22074
+ scope.on(window, "pointercancel", release);
22075
+ scope.on(rate, "click", () => {
22076
+ const available = rates();
22077
+ const index = available.indexOf(state.playbackRate);
22078
+ const next = available[(index + 1) % available.length];
22079
+ if (next === void 0) return;
22080
+ audio.playbackRate = next;
22081
+ emit({ playbackRate: next });
22082
+ bounce(rate);
22083
+ });
22084
+ const metadata = () => {
22085
+ const duration = finite6(audio.duration) ? audio.duration : 0;
22086
+ emit({
22087
+ duration,
22088
+ currentTime: duration ? Math.min(duration, Math.max(0, audio.currentTime || 0)) : 0,
22089
+ ...state.status === "loading" && !requested ? { status: "ready" } : {}
22090
+ });
22091
+ };
22092
+ scope.on(audio, "loadedmetadata", metadata);
22093
+ scope.on(audio, "durationchange", metadata);
22094
+ scope.on(audio, "timeupdate", () => emit({ currentTime: finite6(audio.currentTime) ? audio.currentTime : 0 }, "timeupdate"));
22095
+ scope.on(audio, "playing", () => {
22096
+ if (!source || opts.disabled || !requested && state.status !== "playing") {
22097
+ audio.pause();
22098
+ return;
22099
+ }
22100
+ requested = false;
22101
+ if (state.status !== "playing") emit({ status: "playing", error: null }, "play");
22102
+ });
22103
+ scope.on(audio, "pause", () => {
22104
+ if (state.status === "playing" || requested) {
22105
+ requested = false;
22106
+ emit({ status: "paused" }, "pause");
22107
+ }
22108
+ });
22109
+ scope.on(audio, "waiting", () => {
22110
+ if (state.status === "playing") {
22111
+ requested = true;
22112
+ emit({ status: "loading" });
22113
+ }
22114
+ });
22115
+ scope.on(audio, "ended", () => {
22116
+ request++;
22117
+ pending = null;
22118
+ requested = false;
22119
+ emit({ status: "ended", currentTime: state.duration || state.currentTime }, "ended");
22120
+ });
22121
+ scope.on(audio, "error", () => {
22122
+ request++;
22123
+ pending = null;
22124
+ fail("No se pudo cargar el audio. Comprueba el archivo.");
22125
+ });
22126
+ scope.on(audio, "ratechange", () => {
22127
+ if (audio.playbackRate !== state.playbackRate) emit({ playbackRate: audio.playbackRate });
22128
+ });
22129
+ scope.add(() => {
22130
+ request++;
22131
+ requested = false;
22132
+ pending = null;
22133
+ iconMotion?.kill();
22134
+ for (const effect of effects) effect.kill();
22135
+ gsap.ticker.remove(followPlayback);
22136
+ audio.pause();
22137
+ audio.removeAttribute("src");
22138
+ audio.load();
22139
+ });
22140
+ update(options);
22141
+ return { play, pause, seek, update, get state() {
22142
+ return snapshot();
22143
+ }, get audio() {
22144
+ return scope.disposed ? null : audio;
22145
+ }, destroy: () => scope.dispose() };
22146
+ }
22147
+
22148
+ // src/components/voice-message-bubble/engine.ts
22149
+ var statusLabels = { sending: "Enviando", sent: "Enviado", delivered: "Entregado", read: "Le\xEDdo", failed: "No enviado" };
22150
+ function createVoiceMessageBubble(root, options = {}) {
22151
+ if (!root) return createWaveformPlayer(null, options);
22152
+ registerMotion();
22153
+ const scope = createScope();
22154
+ let opts = { ...options };
22155
+ const content = document.createElement("div");
22156
+ content.setAttribute("data-mk-voice-message-content", "");
22157
+ const header = document.createElement("div");
22158
+ header.setAttribute("data-mk-voice-message-header", "");
22159
+ const author = document.createElement("span");
22160
+ author.setAttribute("data-mk-voice-message-author", "");
22161
+ const caption = document.createElement("span");
22162
+ caption.setAttribute("data-mk-voice-message-caption", "");
22163
+ caption.textContent = "Mensaje de voz";
22164
+ header.append(author, caption);
22165
+ const playerRoot = document.createElement("div");
22166
+ playerRoot.className = "mk-waveform-player";
22167
+ const footer = document.createElement("div");
22168
+ footer.setAttribute("data-mk-voice-message-footer", "");
22169
+ const timestamp = document.createElement("time");
22170
+ const status = document.createElement("span");
22171
+ status.setAttribute("data-mk-voice-message-status", "");
22172
+ footer.append(timestamp, status);
22173
+ content.append(header, playerRoot, footer);
22174
+ root.append(content);
22175
+ scope.add(() => content.remove());
22176
+ scope.attr(root, "data-mk-ready", "");
22177
+ scope.attr(root, "data-mk-direction", "incoming");
22178
+ const player = createWaveformPlayer(playerRoot);
22179
+ scope.add(() => player.destroy());
22180
+ const update = (next) => {
22181
+ if (scope.disposed) return;
22182
+ opts = { ...opts, ...next };
22183
+ author.textContent = opts.author ?? "";
22184
+ author.hidden = !opts.author;
22185
+ timestamp.textContent = opts.timestamp ?? "";
22186
+ timestamp.hidden = !opts.timestamp;
22187
+ if (opts.dateTime) timestamp.dateTime = opts.dateTime;
22188
+ else timestamp.removeAttribute("datetime");
22189
+ status.textContent = opts.status && statusLabels[opts.status] || "";
22190
+ status.hidden = !status.textContent;
22191
+ root.setAttribute("data-mk-direction", opts.direction === "outgoing" ? "outgoing" : "incoming");
22192
+ const { direction: _direction, author: _author, timestamp: _timestamp, dateTime: _dateTime, status: _status, ...audio } = opts;
22193
+ player.update({ ...audio, label: opts.label ?? (opts.author ? `mensaje de voz de ${opts.author}` : "mensaje de voz") });
22194
+ };
22195
+ update(options);
22196
+ let entrance = null;
22197
+ if (!reduced()) {
22198
+ content.style.transformOrigin = opts.direction === "outgoing" ? "right bottom" : "left bottom";
22199
+ entrance = gsap.fromTo(content, { scale: 0.88, opacity: 0, filter: "blur(12px)", y: 10 }, { scale: 1, opacity: 1, filter: "blur(0px)", y: 0, duration: 0.65, ease: EASE.signature, clearProps: "transform,opacity,filter" });
22200
+ }
22201
+ scope.add(() => entrance?.kill());
22202
+ return {
22203
+ play: () => player.play(),
22204
+ pause: () => player.pause(),
22205
+ seek: (n) => player.seek(n),
22206
+ update,
22207
+ get state() {
22208
+ return player.state;
22209
+ },
22210
+ get audio() {
22211
+ return player.audio;
22212
+ },
22213
+ destroy: () => scope.dispose()
22214
+ };
22215
+ }
22216
+
22217
+ // src/components/drilldown-menu/engine.ts
22218
+ 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>';
22219
+ var sequence24 = 0;
22220
+ var samePath = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
22221
+ var branch = (item) => Array.isArray(item.children);
22222
+ var copyItems = (items) => items.map((item) => ({ ...item, ...branch(item) ? { children: copyItems(item.children) } : {} }));
22223
+ function createDrilldownMenu(root, options = {}) {
22224
+ if (!root) return inert({ open: () => false, back: () => false, root() {
22225
+ }, reset() {
22226
+ }, setPath() {
22227
+ }, setItems() {
22228
+ }, update() {
22229
+ }, focusItem() {
22230
+ }, path: [], items: [], element: null });
22231
+ registerMotion();
22232
+ const scope = createScope();
22233
+ const uid2 = `mk-drilldown-${++sequence24}`;
22234
+ const authored = [...root.childNodes];
22235
+ const holder = document.createDocumentFragment();
22236
+ holder.append(...authored);
22237
+ let config = { ...options };
22238
+ let data = copyItems(options.items ?? []);
22239
+ let path = [];
22240
+ let focused = null;
22241
+ const remembered = /* @__PURE__ */ new Map();
22242
+ let animation = null;
22243
+ let hoverMotion = null;
22244
+ const effects = /* @__PURE__ */ new Set();
22245
+ const keep = (effect) => {
22246
+ for (const animation2 of effects) if (animation2.totalProgress() === 1) effects.delete(animation2);
22247
+ if (effect) effects.add(effect);
22248
+ };
22249
+ const header = document.createElement("div");
22250
+ header.dataset.mkDrilldownHeader = "";
22251
+ const backButton = document.createElement("button");
22252
+ backButton.type = "button";
22253
+ backButton.dataset.mkDrilldownBack = "";
22254
+ backButton.innerHTML = CHEVRON5;
22255
+ const heading = document.createElement("span");
22256
+ heading.id = `${uid2}-heading`;
22257
+ heading.dataset.mkDrilldownHeading = "";
22258
+ header.append(backButton, heading);
22259
+ const breadcrumb = document.createElement("nav");
22260
+ breadcrumb.dataset.mkDrilldownBreadcrumb = "";
22261
+ const crumbs = document.createElement("ol");
22262
+ breadcrumb.append(crumbs);
22263
+ const viewport = document.createElement("div");
22264
+ viewport.dataset.mkDrilldownViewport = "";
22265
+ const menu = document.createElement("div");
22266
+ menu.dataset.mkDrilldownLevel = "";
22267
+ menu.id = `${uid2}-level`;
22268
+ menu.setAttribute("role", "menu");
22269
+ menu.setAttribute("aria-labelledby", heading.id);
22270
+ const empty = document.createElement("p");
22271
+ empty.dataset.mkDrilldownEmpty = "";
22272
+ empty.setAttribute("role", "status");
22273
+ const highlight = document.createElement("span");
22274
+ highlight.dataset.mkDrilldownHighlight = "";
22275
+ highlight.setAttribute("aria-hidden", "true");
22276
+ viewport.append(highlight, menu, empty);
22277
+ backButton.setAttribute("aria-controls", menu.id);
22278
+ root.append(header, breadcrumb, viewport);
22279
+ scope.attr(root, "data-mk-ready", "");
22280
+ const levelAt = (requested) => {
22281
+ const valid2 = [];
22282
+ const ancestors = [];
22283
+ let items = data;
22284
+ for (const id of requested) {
22285
+ const item = items.find((entry) => entry.id === id);
22286
+ if (!item || item.disabled || !branch(item)) break;
22287
+ valid2.push(id);
22288
+ ancestors.push(item);
22289
+ items = item.children;
22290
+ }
22291
+ return { valid: valid2, ancestors, items };
22292
+ };
22293
+ const level2 = () => levelAt(path);
22294
+ const enabled = () => [...menu.querySelectorAll("[data-mk-drilldown-item]")].filter((item) => !item.disabled);
22295
+ const buttonOf = (id) => enabled().find((item) => item.dataset.mkDrilldownItem === id);
22296
+ const highlightItem = (button2) => {
22297
+ hoverMotion?.kill();
22298
+ for (const item of enabled()) item.toggleAttribute("data-mk-highlighted", item === button2);
22299
+ if (!button2) {
22300
+ highlight.style.opacity = "0";
22301
+ return;
22302
+ }
22303
+ const geometry = { x: button2.offsetLeft + menu.offsetLeft, y: button2.offsetTop + menu.offsetTop, width: button2.offsetWidth, height: button2.offsetHeight, opacity: 1 };
22304
+ if (reduced()) gsap.set(highlight, geometry);
22305
+ else hoverMotion = gsap.to(highlight, { ...geometry, duration: 0.35, ease: EASE.swatch });
22306
+ };
22307
+ const cancelMotion = () => {
22308
+ animation?.kill();
22309
+ hoverMotion?.kill();
22310
+ animation = null;
22311
+ gsap.set([menu, heading, breadcrumb, ...menu.children], { clearProps: "transform,opacity,filter" });
22312
+ gsap.set(viewport, { clearProps: "height" });
22313
+ };
22314
+ const roving = (id, focus = false) => {
22315
+ const items = enabled();
22316
+ const target = items.find((item) => item.dataset.mkDrilldownItem === id) ?? items[0];
22317
+ focused = target?.dataset.mkDrilldownItem ?? null;
22318
+ for (const item of menu.querySelectorAll("[data-mk-drilldown-item]")) item.tabIndex = item === target ? 0 : -1;
22319
+ menu.tabIndex = target ? -1 : 0;
22320
+ if (focused) remembered.set(JSON.stringify(path), focused);
22321
+ if (focus) (target ?? menu).focus({ preventScroll: true });
22322
+ if (focus) highlightItem(target);
22323
+ };
22324
+ const notifyPath = () => {
22325
+ const next = [...path];
22326
+ root.dispatchEvent(new CustomEvent("mk:path-change", { bubbles: true, detail: { path: [...next] } }));
22327
+ config.onPathChange?.(next);
22328
+ };
22329
+ const render = (direction, focus, preferred) => {
22330
+ const oldHeight = viewport.getBoundingClientRect().height;
22331
+ cancelMotion();
22332
+ highlightItem(null);
22333
+ const current3 = level2();
22334
+ const label = config.label ?? "Actions";
22335
+ const title = current3.ancestors.at(-1)?.label ?? label;
22336
+ heading.textContent = title;
22337
+ backButton.hidden = path.length === 0;
22338
+ backButton.setAttribute("aria-label", config.backLabel ?? "Back");
22339
+ breadcrumb.setAttribute("aria-label", `${label} path`);
22340
+ breadcrumb.hidden = path.length === 0;
22341
+ const labels = [label, ...current3.ancestors.map((item) => item.label)];
22342
+ crumbs.replaceChildren(...labels.map((text, index) => {
22343
+ const li = document.createElement("li");
22344
+ if (index === labels.length - 1) {
22345
+ const span = document.createElement("span");
22346
+ span.setAttribute("aria-current", "location");
22347
+ span.textContent = text;
22348
+ li.append(span);
22349
+ } else {
22350
+ const button2 = document.createElement("button");
22351
+ button2.type = "button";
22352
+ button2.dataset.mkDrilldownCrumb = String(index);
22353
+ button2.textContent = text;
22354
+ button2.setAttribute("aria-controls", menu.id);
22355
+ li.append(button2);
22356
+ }
22357
+ return li;
22358
+ }));
22359
+ menu.replaceChildren(...current3.items.map((item, index) => {
22360
+ const button2 = document.createElement("button");
22361
+ button2.type = "button";
22362
+ button2.dataset.mkDrilldownItem = item.id;
22363
+ button2.setAttribute("role", "menuitem");
22364
+ button2.disabled = Boolean(item.disabled);
22365
+ if (item.disabled) button2.setAttribute("aria-disabled", "true");
22366
+ const text = document.createElement("span");
22367
+ text.dataset.mkDrilldownText = "";
22368
+ const name = document.createElement("span");
22369
+ name.id = `${uid2}-item-${index}`;
22370
+ name.dataset.mkDrilldownLabel = "";
22371
+ name.textContent = item.label;
22372
+ button2.setAttribute("aria-labelledby", name.id);
22373
+ text.append(name);
22374
+ if (item.description) {
22375
+ const description = document.createElement("span");
22376
+ description.id = `${uid2}-description-${index}`;
22377
+ description.dataset.mkDrilldownDescription = "";
22378
+ description.textContent = item.description;
22379
+ button2.setAttribute("aria-describedby", description.id);
22380
+ text.append(description);
22381
+ }
22382
+ button2.append(text);
22383
+ if (branch(item)) {
22384
+ button2.setAttribute("aria-haspopup", "menu");
22385
+ const arrow = document.createElement("span");
22386
+ arrow.dataset.mkDrilldownArrow = "";
22387
+ arrow.innerHTML = CHEVRON5;
22388
+ button2.append(arrow);
22389
+ }
22390
+ return button2;
22391
+ }));
22392
+ empty.textContent = config.emptyText ?? "No actions available";
22393
+ empty.hidden = current3.items.length !== 0;
22394
+ roving(preferred ?? remembered.get(JSON.stringify(path)) ?? null);
22395
+ if (direction && !reduced()) {
22396
+ animation = gsap.timeline({ onComplete: () => {
22397
+ animation = null;
22398
+ } }).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" });
22399
+ animation.fromTo([heading, breadcrumb], { y: -6, opacity: 0.3, filter: "blur(6px)" }, { y: 0, opacity: 1, filter: "blur(0px)", duration: 0.3, ease: EASE.pop, clearProps: "transform,opacity,filter" }, 0).fromTo([...menu.children], { x: 12 * direction, opacity: 0 }, { x: 0, opacity: 1, duration: 0.3, stagger: 0.035, ease: EASE.swatchLight, clearProps: "transform,opacity" }, 0.04);
22400
+ const nextHeight = viewport.getBoundingClientRect().height;
22401
+ if (oldHeight > 0 && nextHeight > 0 && oldHeight !== nextHeight) {
22402
+ animation.fromTo(viewport, { height: oldHeight }, { height: nextHeight, duration: 0.36, ease: EASE.signature, clearProps: "height" }, 0);
22403
+ }
22404
+ }
22405
+ if (focus) roving(focused, true);
22406
+ };
22407
+ const navigate = (requested, notify, focus, preferred) => {
22408
+ if (scope.disposed) return false;
22409
+ const next = levelAt(requested).valid;
22410
+ if (samePath(path, next)) return false;
22411
+ const previous = path;
22412
+ if (focused) remembered.set(JSON.stringify(previous), focused);
22413
+ const direction = next.length > path.length ? 1 : -1;
22414
+ path = next;
22415
+ render(direction, focus, preferred);
22416
+ if (notify) notifyPath();
22417
+ return true;
22418
+ };
22419
+ const open = (id) => {
22420
+ if (scope.disposed) return false;
22421
+ const item = level2().items.find((entry) => entry.id === id);
22422
+ if (!item || item.disabled || !branch(item)) return false;
22423
+ return navigate([...path, id], true, true);
22424
+ };
22425
+ const back = () => path.length ? navigate(path.slice(0, -1), true, true, path.at(-1)) : false;
22426
+ const reset = () => navigate([], true, root.contains(document.activeElement), path[0]);
22427
+ const activate = (id) => {
22428
+ const item = level2().items.find((entry) => entry.id === id);
22429
+ if (!item || item.disabled) return;
22430
+ if (branch(item)) return void open(id);
22431
+ const button2 = buttonOf(id);
22432
+ if (button2) {
22433
+ for (const row of enabled()) row.toggleAttribute("data-mk-chosen", row === button2);
22434
+ keep(press(button2));
22435
+ keep(ringPulse(button2));
22436
+ }
22437
+ const selected = copyItems([item])[0];
22438
+ const selectedPath = [...path, item.id];
22439
+ root.dispatchEvent(new CustomEvent("mk:select", { bubbles: true, detail: { item: selected, path: [...selectedPath] } }));
22440
+ config.onSelect?.(copyItems([item])[0], [...selectedPath]);
22441
+ };
22442
+ scope.on(menu, "click", (event) => {
22443
+ const button2 = event.target?.closest("[data-mk-drilldown-item]");
22444
+ if (!button2 || !menu.contains(button2) || button2.disabled) return;
22445
+ roving(button2.dataset.mkDrilldownItem, false);
22446
+ activate(button2.dataset.mkDrilldownItem);
22447
+ });
22448
+ scope.on(menu, "focusin", (event) => {
22449
+ const button2 = event.target?.closest("[data-mk-drilldown-item]");
22450
+ if (button2 && !button2.disabled) {
22451
+ roving(button2.dataset.mkDrilldownItem, false);
22452
+ highlightItem(button2);
22453
+ }
22454
+ });
22455
+ scope.on(menu, "pointerover", (event) => {
22456
+ const button2 = event.target?.closest("[data-mk-drilldown-item]");
22457
+ if (button2 && !button2.disabled) highlightItem(button2);
22458
+ });
22459
+ scope.on(menu, "pointerleave", () => highlightItem(menu.contains(document.activeElement) ? buttonOf(focused ?? "") : null));
22460
+ if (typeof ResizeObserver === "function") scope.observe(new ResizeObserver(() => {
22461
+ const current3 = menu.querySelector("[data-mk-highlighted]");
22462
+ if (current3) highlightItem(current3);
22463
+ })).observe(menu);
22464
+ scope.on(root, "keydown", (event) => {
22465
+ const key2 = event.key;
22466
+ if ((key2 === "ArrowLeft" || key2 === "Escape") && path.length) {
22467
+ event.preventDefault();
22468
+ event.stopPropagation();
22469
+ back();
22470
+ return;
22471
+ }
22472
+ if (!menu.contains(event.target)) return;
22473
+ const items = enabled();
22474
+ const at = items.indexOf(document.activeElement);
22475
+ 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 };
22476
+ if (key2 in moves && items.length) {
22477
+ event.preventDefault();
22478
+ roving(items[moves[key2]].dataset.mkDrilldownItem, true);
22479
+ return;
22480
+ }
22481
+ const button2 = event.target?.closest("[data-mk-drilldown-item]");
22482
+ if (!button2 || button2.disabled || !menu.contains(button2)) return;
22483
+ if (key2 === "Enter" || key2 === " " || key2 === "ArrowRight") {
22484
+ const item = level2().items.find((entry) => entry.id === button2.dataset.mkDrilldownItem);
22485
+ if (key2 === "ArrowRight" && (!item || !branch(item))) return;
22486
+ event.preventDefault();
22487
+ activate(button2.dataset.mkDrilldownItem);
22488
+ }
22489
+ });
22490
+ scope.on(backButton, "click", () => {
22491
+ keep(press(backButton));
22492
+ back();
22493
+ });
22494
+ scope.on(breadcrumb, "click", (event) => {
22495
+ const button2 = event.target?.closest("[data-mk-drilldown-crumb]");
22496
+ if (!button2 || !breadcrumb.contains(button2)) return;
22497
+ const depth = Number(button2.dataset.mkDrilldownCrumb);
22498
+ navigate(path.slice(0, depth), true, true, path[depth]);
22499
+ });
22500
+ scope.add(() => {
22501
+ cancelMotion();
22502
+ for (const effect of effects) effect.kill();
22503
+ gsap.killTweensOf([heading, breadcrumb, highlight]);
22504
+ remembered.clear();
22505
+ header.remove();
22506
+ breadcrumb.remove();
22507
+ viewport.remove();
22508
+ root.append(holder);
22509
+ });
22510
+ path = levelAt(options.path ?? []).valid;
22511
+ render(0, false);
22512
+ const update = (next) => {
22513
+ if (scope.disposed) return;
22514
+ const active = document.activeElement;
22515
+ const hadFocus = root.contains(active);
22516
+ const backFocused = active === backButton;
22517
+ const crumbFocused = active?.dataset.mkDrilldownCrumb;
22518
+ const previousPath = path;
22519
+ const previousFocus = focused;
22520
+ config = { ...config, ...next };
22521
+ if (next.items !== void 0) data = copyItems(next.items);
22522
+ path = levelAt(next.path ?? path).valid;
22523
+ const changed = !samePath(previousPath, path);
22524
+ const preferred = changed ? previousPath[path.length] : previousFocus;
22525
+ render(0, hadFocus, preferred);
22526
+ if (hadFocus && !changed) {
22527
+ if (backFocused && !backButton.hidden) backButton.focus({ preventScroll: true });
22528
+ else if (crumbFocused !== void 0) {
22529
+ [...crumbs.querySelectorAll("[data-mk-drilldown-crumb]")].find((button2) => button2.dataset.mkDrilldownCrumb === crumbFocused)?.focus({ preventScroll: true });
22530
+ }
22531
+ }
22532
+ if (changed && next.path === void 0) notifyPath();
22533
+ };
22534
+ return {
22535
+ open,
22536
+ back,
22537
+ root: reset,
22538
+ reset,
22539
+ setPath: (next, notify = false) => {
22540
+ navigate(next, notify, root.contains(document.activeElement));
22541
+ },
22542
+ setItems: (items) => update({ items }),
22543
+ update,
22544
+ focusItem(id) {
22545
+ if (!scope.disposed && buttonOf(id)) roving(id, true);
22546
+ },
22547
+ get path() {
22548
+ return [...path];
22549
+ },
22550
+ get items() {
22551
+ return copyItems(level2().items);
22552
+ },
22553
+ element: root,
22554
+ destroy: () => scope.dispose()
22555
+ };
22556
+ }
22557
+
22558
+ // src/components/wheel-picker/engine.ts
22559
+ var sequence25 = 0;
22560
+ function normalize(items) {
22561
+ const seen = /* @__PURE__ */ new Set();
22562
+ return items.flatMap((item) => {
22563
+ const row = typeof item === "string" ? { value: item, label: item } : item;
22564
+ if (!row || typeof row !== "object" || row.value == null) return [];
22565
+ const value = String(row.value);
22566
+ if (seen.has(value)) return [];
22567
+ seen.add(value);
22568
+ return [{ value, label: String(row.label ?? value), disabled: Boolean(row.disabled) }];
22569
+ });
22570
+ }
22571
+ function createWheelPicker(root, options = {}) {
22572
+ if (!root) return inert({ setValue() {
22573
+ }, setItems() {
22574
+ }, value: "" });
22575
+ registerMotion();
22576
+ const scope = createScope(), uid2 = `mk-wheel-${++sequence25}`;
22577
+ let items = normalize(Array.isArray(options.items) ? options.items : []);
22578
+ const rawRows = Number.isFinite(options.visibleItems) ? Math.round(options.visibleItems) : 5;
22579
+ const rows = Math.min(9, Math.max(3, rawRows % 2 ? rawRows : rawRows + 1));
22580
+ const height = Number.isFinite(options.itemHeight) ? Math.max(44, Math.min(96, options.itemHeight)) : 44;
22581
+ const disabled = Boolean(options.disabled);
22582
+ const originalStyle = root.getAttribute("style");
22583
+ root.style.setProperty("--mk-wheel-row", `${height}px`);
22584
+ root.style.setProperty("--mk-wheel-rows", String(rows));
22585
+ scope.add(() => {
22586
+ if (originalStyle === null) root.removeAttribute("style");
22587
+ else root.setAttribute("style", originalStyle);
22588
+ });
22589
+ scope.attr(root, "data-mk-ready", "");
22590
+ scope.attr(root, "data-mk-disabled", disabled ? "" : null);
22591
+ const label = document.createElement("span");
22592
+ label.id = `${uid2}-label`;
22593
+ label.dataset.mkWheelLabel = "";
22594
+ label.textContent = options.label ?? root.getAttribute("aria-label") ?? "Seleccionar";
22595
+ const frame = document.createElement("div");
22596
+ frame.dataset.mkWheelFrame = "";
22597
+ const highlight = document.createElement("span");
22598
+ highlight.dataset.mkWheelHighlight = "";
22599
+ highlight.setAttribute("aria-hidden", "true");
22600
+ const viewport = document.createElement("div");
22601
+ viewport.dataset.mkWheelViewport = "";
22602
+ viewport.setAttribute("role", "listbox");
22603
+ viewport.setAttribute("aria-labelledby", label.id);
22604
+ viewport.setAttribute("aria-orientation", "vertical");
22605
+ viewport.setAttribute("aria-disabled", String(disabled));
22606
+ viewport.tabIndex = disabled ? -1 : 0;
22607
+ const list3 = document.createElement("div");
22608
+ list3.dataset.mkWheelList = "";
22609
+ viewport.append(list3);
22610
+ frame.append(highlight, viewport);
22611
+ const input = document.createElement("input");
22612
+ input.type = "hidden";
22613
+ if (options.name) input.name = options.name;
22614
+ input.disabled = disabled;
22615
+ const status = document.createElement("span");
22616
+ status.className = "mk-sr-only";
22617
+ status.setAttribute("role", "status");
22618
+ root.append(label, frame, input, status);
22619
+ scope.add(() => {
22620
+ label.remove();
22621
+ frame.remove();
22622
+ input.remove();
22623
+ status.remove();
22624
+ });
22625
+ const enabled = () => items.flatMap((item, index) => item.disabled ? [] : [index]);
22626
+ const find = (value) => items.findIndex((item) => value !== void 0 && item.value === String(value) && !item.disabled);
22627
+ let current3 = find(options.value);
22628
+ if (current3 < 0) current3 = enabled()[0] ?? -1;
22629
+ const initial = items[current3]?.value ?? "";
22630
+ let committed = initial;
22631
+ let nodes = [];
22632
+ let timer2;
22633
+ let typing;
22634
+ let prefix = "";
22635
+ let programmatic = null;
22636
+ let glide = null;
22637
+ let feedback = null;
22638
+ let dragging = null;
22639
+ let suppressClick = false;
22640
+ scope.add(() => {
22641
+ clearTimeout(timer2);
22642
+ clearTimeout(typing);
22643
+ glide?.kill();
22644
+ feedback?.kill();
22645
+ });
22646
+ const radius = height * rows / 2, step = height / radius, camera = radius * 3;
22647
+ const paint = () => {
22648
+ const offset = viewport.scrollTop / height, flat = reduced();
22649
+ nodes.forEach((node, index) => {
22650
+ const distance = index - offset;
22651
+ const angle2 = distance * step, hidden = Math.abs(angle2) >= Math.PI / 2;
22652
+ const depth = radius * (Math.cos(angle2) - 1);
22653
+ const cameraScale = camera / (camera - depth);
22654
+ const shiftY = (radius * Math.sin(angle2) - distance * height) / cameraScale;
22655
+ node.style.transform = flat || hidden ? "" : `perspective(${camera.toFixed(0)}px) translate3d(0, ${shiftY.toFixed(3)}px, ${depth.toFixed(3)}px) rotateX(${(-angle2 * 180 / Math.PI).toFixed(3)}deg)`;
22656
+ node.style.opacity = String((items[index].disabled ? 0.32 : 1) * (flat ? 1 : hidden ? 0 : Math.pow(Math.cos(angle2), 1.6)));
22657
+ node.style.visibility = !flat && hidden ? "hidden" : "";
22658
+ node.style.pointerEvents = !flat && Math.abs(angle2) > 1.2 ? "none" : "";
22659
+ node.setAttribute("aria-selected", String(index === current3));
22660
+ });
22661
+ input.value = items[current3]?.value ?? "";
22662
+ if (current3 >= 0) viewport.setAttribute("aria-activedescendant", `${uid2}-${current3}`);
22663
+ else viewport.removeAttribute("aria-activedescendant");
22664
+ };
22665
+ const announce = (kind) => {
22666
+ const value = items[current3]?.value ?? "";
22667
+ if (kind === "input") options.onInput?.(value);
22668
+ else {
22669
+ options.onChange?.(value);
22670
+ status.textContent = items[current3]?.label ?? "";
22671
+ feedback?.kill();
22672
+ if (!reduced()) feedback = gsap.fromTo(highlight, { scaleX: 0.94, scaleY: 0.82 }, { scaleX: 1, scaleY: 1, duration: 0.5, ease: EASE.click, clearProps: "transform" });
22673
+ }
22674
+ input.dispatchEvent(new Event(kind, { bubbles: true }));
22675
+ root.dispatchEvent(new CustomEvent(`mk:${kind}`, { bubbles: true, detail: { value, item: current3 >= 0 ? { ...items[current3] } : null } }));
22676
+ };
22677
+ const align = (animate) => {
22678
+ glide?.kill();
22679
+ glide = null;
22680
+ const top = Math.max(0, current3) * height;
22681
+ if (animate && !reduced()) {
22682
+ programmatic = top;
22683
+ const proxy = { top: viewport.scrollTop };
22684
+ glide = gsap.to(proxy, {
22685
+ top,
22686
+ duration: 0.55,
22687
+ ease: EASE.swatch,
22688
+ onUpdate: () => {
22689
+ viewport.scrollTop = proxy.top;
22690
+ paint();
22691
+ },
22692
+ onComplete: () => {
22693
+ glide = null;
22694
+ programmatic = null;
22695
+ viewport.scrollTop = top;
22696
+ paint();
22697
+ }
22698
+ });
22699
+ } else {
22700
+ programmatic = null;
22701
+ viewport.scrollTop = top;
22702
+ paint();
22703
+ }
22704
+ };
22705
+ const select = (index, notify, animate = true) => {
22706
+ if (scope.disposed || index < 0 || index >= items.length || items[index].disabled) return;
22707
+ const previous = items[current3]?.value ?? "";
22708
+ current3 = index;
22709
+ paint();
22710
+ align(animate);
22711
+ const value = items[current3].value;
22712
+ committed = value;
22713
+ if (notify && value !== previous) {
22714
+ announce("input");
22715
+ announce("change");
22716
+ }
22717
+ };
22718
+ const nearest = () => {
22719
+ const at = viewport.scrollTop / height;
22720
+ return enabled().reduce((best, index) => best < 0 || Math.abs(index - at) < Math.abs(best - at) ? index : best, -1);
22721
+ };
22722
+ const settle = () => {
22723
+ if (scope.disposed || dragging) return;
22724
+ if (glide?.isActive()) return;
22725
+ clearTimeout(timer2);
22726
+ if (programmatic !== null) {
22727
+ programmatic = null;
22728
+ viewport.scrollTop = Math.max(0, current3) * height;
22729
+ paint();
22730
+ return;
22731
+ }
22732
+ const index = nearest();
22733
+ if (index < 0) return;
22734
+ current3 = index;
22735
+ align(false);
22736
+ paint();
22737
+ const value = items[current3].value;
22738
+ if (value !== committed) {
22739
+ committed = value;
22740
+ announce("change");
22741
+ }
22742
+ };
22743
+ const build = () => {
22744
+ list3.replaceChildren();
22745
+ nodes = items.map((item, index) => {
22746
+ const node = document.createElement("div");
22747
+ node.id = `${uid2}-${index}`;
22748
+ node.dataset.mkWheelOption = String(index);
22749
+ node.setAttribute("role", "option");
22750
+ node.setAttribute("aria-disabled", String(item.disabled));
22751
+ node.textContent = item.label;
22752
+ list3.append(node);
22753
+ return node;
22754
+ });
22755
+ if (!items.length) {
22756
+ const empty = document.createElement("span");
22757
+ empty.dataset.mkWheelEmpty = "";
22758
+ empty.textContent = "Sin opciones";
22759
+ list3.append(empty);
22760
+ }
22761
+ align(false);
22762
+ paint();
22763
+ };
22764
+ const interrupt = () => {
22765
+ glide?.kill();
22766
+ glide = null;
22767
+ programmatic = null;
22768
+ };
22769
+ scope.on(viewport, "pointerdown", (event) => {
22770
+ interrupt();
22771
+ const pointer2 = event;
22772
+ if (disabled || pointer2.pointerType === "touch" || pointer2.button !== 0) return;
22773
+ dragging = { id: pointer2.pointerId, y: pointer2.clientY, top: viewport.scrollTop, moved: false };
22774
+ viewport.focus({ preventScroll: true });
22775
+ });
22776
+ scope.on(window, "pointermove", (event) => {
22777
+ const pointer2 = event;
22778
+ if (!dragging || pointer2.pointerId !== dragging.id) return;
22779
+ const delta = pointer2.clientY - dragging.y;
22780
+ if (Math.abs(delta) > 4 && !dragging.moved) {
22781
+ dragging.moved = true;
22782
+ viewport.style.scrollSnapType = "none";
22783
+ try {
22784
+ viewport.setPointerCapture(pointer2.pointerId);
22785
+ } catch {
22786
+ }
22787
+ }
22788
+ if (!dragging.moved) return;
22789
+ event.preventDefault();
22790
+ viewport.scrollTop = Math.max(0, Math.min(Math.max(0, (items.length - 1) * height), dragging.top - delta));
22791
+ });
22792
+ const release = (event) => {
22793
+ if (!dragging || dragging.id !== event.pointerId) return;
22794
+ suppressClick = dragging.moved;
22795
+ dragging = null;
22796
+ viewport.style.removeProperty("scroll-snap-type");
22797
+ if (suppressClick) {
22798
+ settle();
22799
+ clearTimeout(timer2);
22800
+ timer2 = setTimeout(() => {
22801
+ suppressClick = false;
22802
+ }, 0);
22803
+ }
22804
+ };
22805
+ scope.on(window, "pointerup", release);
22806
+ scope.on(window, "pointercancel", release);
22807
+ scope.on(viewport, "lostpointercapture", release);
22808
+ scope.on(viewport, "wheel", interrupt, { passive: true });
22809
+ scope.on(viewport, "scroll", () => {
22810
+ if (disabled) return;
22811
+ if (programmatic === null) {
22812
+ const index = nearest();
22813
+ if (index >= 0 && index !== current3) {
22814
+ current3 = index;
22815
+ paint();
22816
+ announce("input");
22817
+ }
22818
+ }
22819
+ paint();
22820
+ clearTimeout(timer2);
22821
+ timer2 = setTimeout(settle, 100);
22822
+ }, { passive: true });
22823
+ scope.on(viewport, "scrollend", settle);
22824
+ scope.on(viewport, "click", (event) => {
22825
+ if (disabled) return;
22826
+ if (suppressClick) {
22827
+ event.preventDefault();
22828
+ suppressClick = false;
22829
+ return;
22830
+ }
22831
+ const row = event.target.closest("[data-mk-wheel-option]");
22832
+ if (!row || !list3.contains(row)) return;
22833
+ select(Number(row.dataset.mkWheelOption), true);
22834
+ viewport.focus({ preventScroll: true });
22835
+ });
22836
+ scope.on(viewport, "keydown", (event) => {
22837
+ if (disabled) return;
22838
+ const key2 = event.key, choices = enabled(), at = choices.indexOf(current3);
22839
+ if (key2 === "Enter" || key2 === " ") {
22840
+ event.preventDefault();
22841
+ return;
22842
+ }
22843
+ const move = key2 === "ArrowDown" ? 1 : key2 === "ArrowUp" ? -1 : key2 === "PageDown" ? rows - 1 : key2 === "PageUp" ? 1 - rows : 0;
22844
+ 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;
22845
+ if (next === void 0 && key2.length === 1 && !event.ctrlKey && !event.metaKey) {
22846
+ prefix += key2.toLocaleLowerCase();
22847
+ clearTimeout(typing);
22848
+ typing = setTimeout(() => {
22849
+ prefix = "";
22850
+ }, 600);
22851
+ next = choices.find((index) => items[index].label.toLocaleLowerCase().startsWith(prefix));
22852
+ }
22853
+ if (next === void 0) return;
22854
+ event.preventDefault();
22855
+ interrupt();
22856
+ select(next, true);
22857
+ });
22858
+ const form = root.closest("form");
22859
+ if (form) scope.on(form, "reset", (event) => queueMicrotask(() => {
22860
+ if (scope.disposed || event.defaultPrevented) return;
22861
+ const index = find(initial);
22862
+ select(index >= 0 ? index : enabled()[0] ?? -1, true, false);
22863
+ paint();
22864
+ }));
22865
+ build();
22866
+ input.defaultValue = initial;
22867
+ return {
22868
+ setValue(value, notify = false) {
22869
+ const next = find(value);
22870
+ if (next !== current3) select(next, notify);
22871
+ },
22872
+ setItems(next, notify = false) {
22873
+ if (scope.disposed) return;
22874
+ clearTimeout(timer2);
22875
+ programmatic = null;
22876
+ const before = items[current3]?.value ?? "";
22877
+ items = normalize(Array.isArray(next) ? next : []);
22878
+ current3 = find(before);
22879
+ if (current3 < 0) current3 = enabled()[0] ?? -1;
22880
+ build();
22881
+ committed = items[current3]?.value ?? "";
22882
+ if (notify && committed !== before) {
22883
+ announce("input");
22884
+ announce("change");
22885
+ }
22886
+ },
22887
+ get value() {
22888
+ return items[current3]?.value ?? "";
22889
+ },
22890
+ destroy: () => scope.dispose()
22891
+ };
22892
+ }
22893
+
22894
+ // src/components/stepper/engine.ts
22895
+ function createStepper(root, options = {}) {
22896
+ if (!root) return inert({ value: 0, setValue() {
22897
+ }, next() {
22898
+ }, previous() {
22899
+ }, reset() {
22900
+ } });
22901
+ registerMotion();
22902
+ const scope = createScope();
22903
+ const effects = /* @__PURE__ */ new Set();
22904
+ const keep = (effect) => {
22905
+ for (const prior of effects) if (prior.totalProgress() === 1) effects.delete(prior);
22906
+ if (effect) effects.add(effect);
22907
+ };
22908
+ scope.add(() => {
22909
+ effects.forEach((effect) => effect.kill());
22910
+ effects.clear();
22911
+ });
22912
+ const items = (Array.isArray(options.items) ? options.items : []).filter((item) => item && typeof item.label === "string");
22913
+ const clamp5 = (n) => Math.max(0, Math.min(Math.max(0, items.length - 1), Number.isFinite(n) ? Math.round(n) : 0));
22914
+ const initial = clamp5(options.defaultValue ?? options.value ?? 0);
22915
+ let value = clamp5(options.value ?? initial);
22916
+ let furthest = value;
22917
+ let pending = null;
22918
+ const nav = document.createElement("nav");
22919
+ nav.dataset.mkStepperBody = "";
22920
+ nav.setAttribute("aria-label", options.label ?? "Progreso");
22921
+ const list3 = document.createElement("ol");
22922
+ list3.dataset.mkStepperList = "";
22923
+ nav.append(list3);
22924
+ const caption = document.createElement("span");
22925
+ caption.dataset.mkStepperCaption = "";
22926
+ caption.setAttribute("aria-live", "polite");
22927
+ nav.append(caption);
22928
+ root.append(nav);
22929
+ scope.add(() => nav.remove());
22930
+ const buttons = [];
22931
+ const rows = [];
22932
+ const marks = [];
22933
+ items.forEach((item, index) => {
22934
+ const row = document.createElement("li");
22935
+ row.dataset.mkStepperItem = "";
22936
+ const button2 = document.createElement("button");
22937
+ button2.type = "button";
22938
+ button2.dataset.mkStepperStep = String(index);
22939
+ const marker = document.createElement("span");
22940
+ marker.dataset.mkStepperMarker = "";
22941
+ marker.setAttribute("aria-hidden", "true");
22942
+ const copy = document.createElement("span");
22943
+ copy.dataset.mkStepperCopy = "";
22944
+ const title = document.createElement("span");
22945
+ title.dataset.mkStepperLabel = "";
22946
+ title.textContent = item.label;
22947
+ copy.append(title);
22948
+ if (item.description) {
22949
+ const description = document.createElement("span");
22950
+ description.dataset.mkStepperDescription = "";
22951
+ description.textContent = item.description;
22952
+ copy.append(description);
22953
+ }
22954
+ button2.append(marker, copy);
22955
+ row.append(button2);
22956
+ list3.append(row);
22957
+ buttons.push(button2);
22958
+ rows.push(row);
22959
+ marks.push(marker);
22960
+ scope.on(button2, "click", () => {
22961
+ if (!button2.disabled && !button2.matches(":disabled")) choose(index, true);
22962
+ });
22963
+ });
22964
+ const hidden = options.name ? document.createElement("input") : null;
22965
+ if (hidden) {
22966
+ hidden.type = "hidden";
22967
+ hidden.name = options.name;
22968
+ hidden.disabled = Boolean(options.disabled);
22969
+ nav.append(hidden);
22970
+ }
22971
+ scope.attr(root, "data-mk-ready", "");
22972
+ scope.attr(root, "data-mk-variant", options.variant ?? "horizontal");
22973
+ scope.attr(root, "data-mk-disabled", options.disabled ? "" : null);
22974
+ const paint = (animate, before) => {
22975
+ const nextEnabled = items.findIndex((item, index) => index > furthest && !item.disabled);
22976
+ const availableThrough = Math.max(furthest, nextEnabled);
22977
+ items.forEach((item, index) => {
22978
+ const selected = index === value;
22979
+ const complete = item.completed || index < value;
22980
+ rows[index].toggleAttribute("data-mk-current", selected);
22981
+ rows[index].toggleAttribute("data-mk-complete", Boolean(complete));
22982
+ rows[index].toggleAttribute("data-mk-error", Boolean(item.error));
22983
+ const button2 = buttons[index];
22984
+ button2.disabled = Boolean(options.disabled || item.disabled || options.linear && index > availableThrough);
22985
+ if (selected) button2.setAttribute("aria-current", "step");
22986
+ else button2.removeAttribute("aria-current");
22987
+ button2.setAttribute("aria-label", `${index + 1}. ${item.label}${item.error ? ", requiere atenci\xF3n" : complete ? ", completado" : ""}`);
22988
+ marks[index].textContent = item.error ? "!" : complete ? "\u2713" : String(index + 1);
22989
+ });
22990
+ if (hidden) hidden.value = String(value);
22991
+ const text = items.length ? `${value + 1} / ${items.length} \xB7 ${items[value]?.label ?? ""}` : "No hay pasos";
22992
+ if (animate && !reduced()) keep(rollDigits(caption, text, value >= before ? 1 : -1, 0.3));
22993
+ else caption.textContent = text;
22994
+ };
22995
+ const choose = (next, notify = false) => {
22996
+ if (scope.disposed) return;
22997
+ if (notify) pending = { value, furthest };
22998
+ const before = value;
22999
+ value = clamp5(next);
23000
+ furthest = Math.max(furthest, value);
23001
+ paint(before !== value, before);
23002
+ if (before === value) return;
23003
+ if (!reduced() && buttons[value]) {
23004
+ keep(press(buttons[value]));
23005
+ keep(gsap.fromTo(marks[value], { scale: 0.7, filter: "blur(4px)" }, { scale: 1, filter: "blur(0px)", duration: 0.4, ease: EASE.pop, overwrite: "auto", clearProps: "transform,filter" }));
23006
+ }
23007
+ if (notify) {
23008
+ const emitted = value;
23009
+ options.onChange?.(emitted);
23010
+ if (!scope.disposed) root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { value: emitted } }));
23011
+ }
23012
+ };
23013
+ const move = (direction, notify = true) => {
23014
+ if (options.disabled) return;
23015
+ for (let i = value + direction; i >= 0 && i < items.length; i += direction) if (!items[i]?.disabled) {
23016
+ choose(i, notify);
23017
+ break;
23018
+ }
23019
+ };
23020
+ const form = root.closest("form");
23021
+ if (form) scope.on(form, "reset", (event) => scope.timeout(() => {
23022
+ if (!scope.disposed && !event.defaultPrevented) {
23023
+ furthest = initial;
23024
+ choose(initial);
23025
+ }
23026
+ }, 0));
23027
+ paint(false, value);
23028
+ keep(blurIn(rows, { from: "soft", stagger: 0.04, duration: 0.35 }));
23029
+ return {
23030
+ get value() {
23031
+ return value;
23032
+ },
23033
+ setValue(next, notify = false) {
23034
+ const target = clamp5(next);
23035
+ if (!notify && pending && target === pending.value) furthest = pending.furthest;
23036
+ pending = null;
23037
+ choose(target, notify);
23038
+ },
23039
+ next: (notify = true) => move(1, notify),
23040
+ previous: (notify = true) => move(-1, notify),
23041
+ reset: (notify = false) => {
23042
+ pending = null;
23043
+ furthest = initial;
23044
+ choose(initial, notify);
23045
+ },
23046
+ destroy: () => scope.dispose()
23047
+ };
23048
+ }
23049
+
23050
+ // src/components/radio-group/shared.ts
23051
+ var sequence26 = 0;
23052
+ function createChoices(root, prefix, options) {
23053
+ if (!root) return inert({ value: null, setValue() {
23054
+ }, reset() {
23055
+ } });
23056
+ registerMotion();
23057
+ const scope = createScope();
23058
+ const effects = /* @__PURE__ */ new Set();
23059
+ const keep = (effect) => {
23060
+ for (const prior of effects) if (prior.totalProgress() === 1) effects.delete(prior);
23061
+ if (effect) effects.add(effect);
23062
+ };
23063
+ scope.add(() => {
23064
+ effects.forEach((effect) => effect.kill());
23065
+ effects.clear();
23066
+ });
23067
+ const part3 = (tag, parent, name2) => {
23068
+ const el5 = document.createElement(tag);
23069
+ el5.setAttribute(`data-mk-${prefix}-${name2}`, "");
23070
+ parent.append(el5);
23071
+ return el5;
23072
+ };
23073
+ const shell = part3("div", root, "body");
23074
+ scope.add(() => shell.remove());
23075
+ const group = part3("div", shell, "options");
23076
+ group.setAttribute("role", "radiogroup");
23077
+ group.setAttribute("aria-label", options.label ?? "Elige una opci\xF3n");
23078
+ group.setAttribute("aria-required", String(Boolean(options.required)));
23079
+ if (options.disabled) group.setAttribute("aria-disabled", "true");
23080
+ const message = part3("span", shell, "message");
23081
+ message.id = `mk-${prefix}-message-${++sequence26}`;
23082
+ message.setAttribute("aria-live", "polite");
23083
+ group.setAttribute("aria-describedby", message.id);
23084
+ if (options.error) group.setAttribute("aria-invalid", "true");
23085
+ const seen = /* @__PURE__ */ new Set();
23086
+ const items = (Array.isArray(options.items) ? options.items : []).filter((item) => {
23087
+ if (!item || typeof item.value !== "string" || seen.has(item.value)) return false;
23088
+ seen.add(item.value);
23089
+ return true;
23090
+ });
23091
+ const name = options.name ?? `mk-${prefix}-${sequence26}`;
23092
+ const valid2 = (candidate) => candidate != null && items.some((item) => item.value === candidate) ? candidate : null;
23093
+ const initial = valid2(options.defaultValue !== void 0 ? options.defaultValue : options.value);
23094
+ let value = valid2(options.value !== void 0 ? options.value : initial);
23095
+ const labels = [];
23096
+ const inputs = [];
23097
+ for (const item of items) {
23098
+ const label = part3("label", group, "option");
23099
+ const input = part3("input", label, "input");
23100
+ input.type = "radio";
23101
+ input.name = name;
23102
+ input.value = item.value;
23103
+ input.required = Boolean(options.required);
23104
+ input.disabled = Boolean(options.disabled || item.disabled);
23105
+ input.defaultChecked = item.value === initial;
23106
+ const mark = part3("span", label, "mark");
23107
+ mark.setAttribute("aria-hidden", "true");
23108
+ mark.textContent = item.symbol ?? "";
23109
+ const copy = part3("span", label, "copy");
23110
+ part3("span", copy, "label").textContent = item.label;
23111
+ if (item.description) part3("span", copy, "description").textContent = item.description;
23112
+ if (options.error) {
23113
+ input.setAttribute("aria-invalid", "true");
23114
+ input.setAttribute("aria-describedby", message.id);
23115
+ }
23116
+ labels.push(label);
23117
+ inputs.push(input);
23118
+ }
23119
+ scope.attr(root, "data-mk-ready", "");
23120
+ scope.attr(root, "data-mk-variant", options.variant ?? "pill");
23121
+ scope.attr(root, "data-mk-disabled", options.disabled ? "" : null);
23122
+ scope.attr(root, "data-mk-error", options.error ? "" : null);
23123
+ const paint = (animate, before) => {
23124
+ inputs.forEach((input, index) => {
23125
+ input.checked = input.value === value;
23126
+ labels[index].toggleAttribute("data-mk-selected", input.checked);
23127
+ });
23128
+ const caption = options.error ?? (items.length ? options.caption?.(value) ?? "" : "No hay opciones");
23129
+ if (animate && !reduced()) keep(rollDigits(message, caption, Number(value) >= Number(before) ? 1 : -1, 0.28));
23130
+ else message.textContent = caption;
23131
+ const at = (candidate) => items.findIndex((item) => item.value === candidate);
23132
+ options.decorate?.(labels, at(value), at(before), animate && before !== value && !reduced(), keep);
23133
+ };
23134
+ const choose = (next, notify = false, animate = true) => {
23135
+ if (scope.disposed) return;
23136
+ const target = valid2(next);
23137
+ const before = value;
23138
+ value = target;
23139
+ paint(animate, before);
23140
+ if (before === value) return;
23141
+ const index = items.findIndex((item) => item.value === value);
23142
+ if (animate && index >= 0 && !reduced()) {
23143
+ keep(press(labels[index]));
23144
+ keep(gsap.fromTo(labels[index].querySelector(`[data-mk-${prefix}-mark]`), { scale: 0.65, filter: "blur(4px)" }, { scale: 1, filter: "blur(0px)", duration: 0.4, ease: EASE.swatch, overwrite: "auto", clearProps: "transform,filter" }));
23145
+ }
23146
+ if (notify) {
23147
+ const emitted = value;
23148
+ options.onChange?.(emitted);
23149
+ if (!scope.disposed) root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { value: options.eventValue ? options.eventValue(emitted) : emitted } }));
23150
+ }
23151
+ };
23152
+ inputs.forEach((input) => scope.on(input, "change", () => {
23153
+ if (!input.disabled && !input.matches(":disabled") && input.checked) choose(input.value, true);
23154
+ else paint(false, value);
23155
+ }));
23156
+ const form = inputs[0]?.form;
23157
+ if (form) scope.on(form, "reset", (event) => {
23158
+ scope.timeout(() => {
23159
+ if (!scope.disposed && !event.defaultPrevented) choose(initial, false);
23160
+ }, 0);
23161
+ });
23162
+ paint(false, value);
23163
+ keep(blurIn(labels, { from: "soft", stagger: 0.035, duration: 0.35 }));
23164
+ return { get value() {
23165
+ return value;
23166
+ }, setValue: choose, reset: (notify = false) => choose(initial, notify), destroy: () => scope.dispose() };
23167
+ }
23168
+
23169
+ // src/components/radio-group/engine.ts
23170
+ function createRadioGroup(root, options = {}) {
23171
+ return createChoices(root, "radio", options);
23172
+ }
23173
+
23174
+ // src/components/equalizer-slider/shared.ts
23175
+ var finite7 = (n) => typeof n === "number" && Number.isFinite(n);
23176
+ var sequence27 = 0;
23177
+ function createNumericRange(root, options, design) {
23178
+ if (!root) return inert({ value: design.value, setValue() {
23179
+ }, reset() {
23180
+ }, configure() {
23181
+ } });
23182
+ registerMotion();
23183
+ const scope = createScope();
23184
+ const effects = /* @__PURE__ */ new Set();
23185
+ const keep = (effect) => {
23186
+ for (const prior of effects) if (prior.totalProgress() === 1) effects.delete(prior);
23187
+ if (effect) effects.add(effect);
23188
+ };
23189
+ scope.add(() => {
23190
+ effects.forEach((effect) => effect.kill());
23191
+ effects.clear();
23192
+ });
23193
+ let min = finite7(options.min) ? options.min : design.min;
23194
+ let max = finite7(options.max) && options.max > min ? options.max : Math.max(min + 1, design.max);
23195
+ let step = finite7(options.step) && options.step > 0 ? options.step : 1;
23196
+ let lastStep = Math.max(0, Math.floor((max - min) / step + 1e-8));
23197
+ let format = options.formatValue ?? design.format;
23198
+ const snap = (n) => Number((min + Math.max(0, Math.min(lastStep, Math.round((n - min) / step))) * step).toFixed(8));
23199
+ const initial = snap(finite7(options.defaultValue) ? options.defaultValue : finite7(options.value) ? options.value : design.value);
23200
+ let value = snap(finite7(options.value) ? options.value : initial);
23201
+ let committed = value;
23202
+ let held = false;
23203
+ const prefix = design.prefix;
23204
+ const part3 = (tag, parent, name) => {
23205
+ const el5 = document.createElement(tag);
23206
+ el5.setAttribute(`data-mk-${prefix}-${name}`, "");
23207
+ parent.append(el5);
23208
+ return el5;
23209
+ };
23210
+ const shell = part3("div", root, "body");
23211
+ scope.add(() => shell.remove());
23212
+ const header = part3("div", shell, "header");
23213
+ const label = part3("label", header, "label");
23214
+ label.textContent = options.label ?? design.label;
23215
+ const output = part3("output", header, "output");
23216
+ output.setAttribute("aria-hidden", "true");
23217
+ const track = part3("div", shell, "track");
23218
+ const thumb = part3("span", track, "thumb");
23219
+ thumb.setAttribute("aria-hidden", "true");
23220
+ const input = part3("input", track, "input");
23221
+ input.type = "range";
23222
+ input.min = String(min);
23223
+ input.max = String(max);
23224
+ input.step = String(step);
23225
+ input.defaultValue = String(initial);
23226
+ input.value = String(value);
23227
+ input.id = `mk-${prefix}-${++sequence27}`;
23228
+ label.htmlFor = input.id;
23229
+ input.disabled = Boolean(options.disabled);
23230
+ if (options.name) input.name = options.name;
23231
+ const message = part3("span", shell, "message");
23232
+ message.textContent = options.error ?? "";
23233
+ if (options.error) {
23234
+ message.id = `${input.id}-error`;
23235
+ input.setAttribute("aria-invalid", "true");
23236
+ input.setAttribute("aria-describedby", message.id);
23237
+ }
23238
+ const ends = part3("div", shell, "ends");
23239
+ ends.setAttribute("aria-hidden", "true");
23240
+ const minEnd = part3("span", ends, "min");
23241
+ minEnd.textContent = format(min);
23242
+ const maxEnd = part3("span", ends, "max");
23243
+ maxEnd.textContent = format(max);
23244
+ scope.attr(root, "data-mk-ready", "");
23245
+ scope.attr(root, "data-mk-disabled", options.disabled ? "" : null);
23246
+ scope.attr(root, "data-mk-error", options.error ? "" : null);
23247
+ scope.attr(root, "data-mk-held", null);
23248
+ scope.attr(root, "style", root.getAttribute("style"));
23249
+ const decorate = design.decorate?.({ root, track, thumb, scope, keep });
23250
+ let shown4 = null;
23251
+ let glide = null;
23252
+ scope.add(() => glide?.kill());
23253
+ const show = (ratio, animate) => {
23254
+ shown4 = ratio;
23255
+ root.style.setProperty(`--mk-${prefix}-ratio`, String(ratio));
23256
+ decorate?.(ratio, value, animate);
23257
+ };
23258
+ const paint = (animate, before) => {
23259
+ const ratio = (value - min) / (max - min);
23260
+ const text = format(value);
23261
+ input.value = String(value);
23262
+ input.setAttribute("aria-valuetext", text);
23263
+ if (animate && !held && !reduced()) keep(rollDigits(output, text, value >= before ? 1 : -1, 0.3));
23264
+ else {
23265
+ const roll = rollDigits(output, text, value >= before ? 1 : -1, 0);
23266
+ roll?.progress(1).kill();
23267
+ output.textContent = text;
23268
+ }
23269
+ glide?.kill();
23270
+ glide = null;
23271
+ if (animate && !held && !reduced() && shown4 !== null && Math.abs(ratio - shown4) > 1e-4) {
23272
+ const proxy = { ratio: shown4 };
23273
+ glide = gsap.to(proxy, { ratio, duration: 0.5, ease: EASE.swatch, onUpdate: () => show(Math.max(0, Math.min(1, proxy.ratio)), true) });
23274
+ } else show(ratio, animate && !held);
23275
+ };
23276
+ const emit = (type) => {
23277
+ if (scope.disposed) return;
23278
+ const emitted = value;
23279
+ (type === "input" ? options.onInput : options.onChange)?.(emitted);
23280
+ if (!scope.disposed) root.dispatchEvent(new CustomEvent(`mk:${type}`, { bubbles: true, detail: { value: emitted } }));
23281
+ };
23282
+ const set = (next, notify = false, animate = true) => {
23283
+ if (scope.disposed || !finite7(next)) return;
23284
+ const before = value;
23285
+ value = snap(next);
23286
+ paint(animate, before);
23287
+ if (notify && value !== before) {
23288
+ emit("input");
23289
+ committed = value;
23290
+ emit("change");
23291
+ } else if (!notify && value !== before) committed = value;
23292
+ };
23293
+ scope.on(input, "input", () => {
23294
+ if (input.disabled || input.matches(":disabled")) {
23295
+ input.value = String(value);
23296
+ return;
23297
+ }
23298
+ const before = value;
23299
+ value = snap(Number(input.value));
23300
+ paint(true, before);
23301
+ if (value !== before) emit("input");
23302
+ });
23303
+ scope.on(input, "change", () => {
23304
+ if (input.disabled || input.matches(":disabled")) return;
23305
+ const before = value;
23306
+ value = snap(Number(input.value));
23307
+ if (value !== before) paint(true, before);
23308
+ if (value !== committed) {
23309
+ committed = value;
23310
+ emit("change");
23311
+ }
23312
+ });
23313
+ scope.on(input, "pointerdown", () => {
23314
+ if (input.disabled || input.matches(":disabled")) return;
23315
+ held = true;
23316
+ root.setAttribute("data-mk-held", "");
23317
+ keep(press(thumb));
23318
+ });
23319
+ const release = () => {
23320
+ if (!held) return;
23321
+ held = false;
23322
+ root.removeAttribute("data-mk-held");
23323
+ if (!reduced()) keep(gsap.fromTo(thumb, { scale: 1.12 }, { scale: 1, duration: 0.4, ease: EASE.swatch, overwrite: "auto", clearProps: "transform" }));
23324
+ };
23325
+ scope.on(window, "pointerup", release);
23326
+ scope.on(window, "pointercancel", release);
23327
+ scope.on(input, "blur", release);
23328
+ if (input.form) scope.on(input.form, "reset", (event) => scope.timeout(() => {
23329
+ if (!scope.disposed && !event.defaultPrevented) set(initial);
23330
+ }, 0));
23331
+ const configure = (next, notify = false) => {
23332
+ if (scope.disposed) return;
23333
+ const before = value;
23334
+ if (finite7(next.min)) min = next.min;
23335
+ if (finite7(next.max)) max = next.max > min ? next.max : min + 1;
23336
+ if (finite7(next.step) && next.step > 0) step = next.step;
23337
+ if (next.format) format = next.format;
23338
+ lastStep = Math.max(0, Math.floor((max - min) / step + 1e-8));
23339
+ input.min = String(min);
23340
+ input.max = String(max);
23341
+ input.step = String(step);
23342
+ const ends2 = [[minEnd, format(min)], [maxEnd, format(max)]];
23343
+ for (const [end, text] of ends2) {
23344
+ if (reduced()) end.textContent = text;
23345
+ else keep(rollDigits(end, text, 1, 0.3));
23346
+ }
23347
+ value = snap(finite7(next.value) ? next.value : value);
23348
+ paint(true, before);
23349
+ if (value !== before) {
23350
+ committed = value;
23351
+ if (notify) {
23352
+ emit("input");
23353
+ emit("change");
23354
+ }
23355
+ }
23356
+ };
23357
+ paint(false, value);
23358
+ return { get value() {
23359
+ return value;
23360
+ }, setValue: set, reset: (notify = false) => set(initial, notify), configure, destroy: () => scope.dispose() };
23361
+ }
23362
+
23363
+ // src/components/equalizer-slider/engine.ts
23364
+ function createEqualizerSlider(root, options = {}) {
23365
+ return createNumericRange(root, options, {
23366
+ prefix: "equalizer",
23367
+ label: "Volumen",
23368
+ min: 0,
23369
+ max: 100,
23370
+ value: 60,
23371
+ format: (n) => `${n} %`,
23372
+ decorate({ track, keep }) {
23373
+ const wave = document.createElement("span");
23374
+ wave.dataset.mkEqualizerWave = "";
23375
+ wave.setAttribute("aria-hidden", "true");
23376
+ track.prepend(wave);
23377
+ const count = Math.max(12, Math.min(72, Math.round(Number.isFinite(options.bars) ? options.bars : 40)));
23378
+ const bars = Array.from({ length: count }, (_, i) => {
23379
+ const bar = document.createElement("span");
23380
+ const supplied = options.waveform?.[i % options.waveform.length];
23381
+ const height = Number.isFinite(supplied) ? Math.max(0.1, Math.min(1, supplied)) : 0.25 + 0.75 * Math.abs(Math.sin(i * 1.73) * Math.cos(i * 0.41));
23382
+ bar.style.height = `${height * 100}%`;
23383
+ wave.append(bar);
23384
+ return bar;
23385
+ });
23386
+ return (ratio, _value, animate) => bars.forEach((bar, i) => {
23387
+ const on = i / Math.max(1, count - 1) <= ratio;
23388
+ const changed = bar.hasAttribute("data-mk-on") !== on;
23389
+ bar.toggleAttribute("data-mk-on", on);
23390
+ if (animate && changed && !reduced()) keep(gsap.fromTo(bar, { scaleY: 0.72 }, { scaleY: 1, duration: 0.35, ease: EASE.swatch, overwrite: "auto", clearProps: "transform" }));
23391
+ });
23392
+ }
23393
+ });
23394
+ }
23395
+
23396
+ // src/components/temperature-slider/engine.ts
23397
+ var RANGE = { C: { min: 16, max: 30, value: 22 }, F: { min: 60, max: 86, value: 72 } };
23398
+ var convert = (value, from, to) => from === to ? value : to === "F" ? value * 9 / 5 + 32 : (value - 32) * 5 / 9;
23399
+ function createTemperatureSlider(root, options = {}) {
23400
+ let unit = options.unit === "F" ? "F" : "C";
23401
+ const formatFor = (next) => (n) => `${n}\xB0${next}`;
23402
+ const range = createNumericRange(root, options, {
23403
+ prefix: "temperature",
23404
+ label: "Temperatura",
23405
+ ...RANGE[unit],
23406
+ format: formatFor(unit),
23407
+ decorate({ track, thumb }) {
23408
+ const rail = document.createElement("span");
23409
+ rail.dataset.mkTemperatureRail = "";
23410
+ rail.setAttribute("aria-hidden", "true");
23411
+ track.prepend(rail);
23412
+ const fill = document.createElement("span");
23413
+ fill.dataset.mkTemperatureFill = "";
23414
+ rail.append(fill);
23415
+ const ticks = document.createElement("span");
23416
+ ticks.dataset.mkTemperatureTicks = "";
23417
+ ticks.setAttribute("aria-hidden", "true");
23418
+ for (let i = 0; i <= 14; i++) ticks.append(document.createElement("i"));
23419
+ track.prepend(ticks);
23420
+ thumb.textContent = "\xB7\xB7";
23421
+ return (ratio) => {
23422
+ root?.style.setProperty("--mk-temperature-warm", `${Math.round(ratio * 100)}%`);
23423
+ fill.style.width = `${ratio * 100}%`;
23424
+ };
23425
+ }
23426
+ });
23427
+ return {
23428
+ get value() {
23429
+ return range.value;
23430
+ },
23431
+ get unit() {
23432
+ return unit;
23433
+ },
23434
+ setValue: range.setValue,
23435
+ reset: range.reset,
23436
+ setUnit(next, limits = {}, notify = false) {
23437
+ const target = next === "F" ? "F" : "C";
23438
+ const value = Math.round(convert(range.value, unit, target));
23439
+ unit = target;
23440
+ range.configure({ min: limits.min ?? RANGE[target].min, max: limits.max ?? RANGE[target].max, step: limits.step, format: options.formatValue ?? formatFor(target), value }, notify);
23441
+ },
23442
+ destroy: range.destroy
23443
+ };
23444
+ }
23445
+
23446
+ // src/components/rating-scale/engine.ts
23447
+ var SENTIMENTS = ["Muy mal", "Mal", "Regular", "Bien", "Muy bien"];
23448
+ var SYMBOLS = ["\u2322", "\u2322", "\u2212", "\u2323", "\u2323"];
23449
+ function createRatingScale(root, options = {}) {
23450
+ if (!root) return inert({ value: null, setValue() {
23451
+ }, reset() {
23452
+ } });
23453
+ const sentiment = options.variant === "sentiment";
23454
+ const min = Number.isFinite(options.min) ? Math.round(options.min) : sentiment ? 1 : 0;
23455
+ const max = Number.isFinite(options.max) ? Math.max(min, Math.min(min + 20, Math.round(options.max))) : sentiment ? min + 4 : min + 10;
23456
+ const labels = options.labels ?? (sentiment ? SENTIMENTS : []);
23457
+ const items = Array.from({ length: max - min + 1 }, (_, i) => ({
23458
+ value: String(min + i),
23459
+ label: labels[i] ?? String(min + i),
23460
+ symbol: sentiment ? SYMBOLS[Math.min(4, Math.round(i / Math.max(1, max - min) * 4))] : String(min + i)
23461
+ }));
23462
+ const normalize3 = (value) => value != null && Number.isFinite(value) ? String(Math.max(min, Math.min(max, Math.round(value)))) : null;
23463
+ const instance = createChoices(root, "rating-scale", {
23464
+ ...options,
23465
+ variant: sentiment ? "sentiment" : "numbered",
23466
+ items,
23467
+ value: normalize3(options.value !== void 0 ? options.value : options.defaultValue),
23468
+ defaultValue: normalize3(options.defaultValue !== void 0 ? options.defaultValue : options.value),
23469
+ caption: (value) => value === null ? "Sin responder" : labels[Number(value) - min] ?? `${value} de ${max}`,
23470
+ eventValue: (value) => value === null ? null : Number(value),
23471
+ onChange: (value) => options.onChange?.(value === null ? null : Number(value)),
23472
+ decorate(labels2, index, previous, animate, keep) {
23473
+ labels2.forEach((label, i) => label.toggleAttribute("data-mk-in-range", !sentiment && index >= 0 && i < index));
23474
+ if (!animate || index < 0) return;
23475
+ if (sentiment) {
23476
+ const mood = index / Math.max(1, labels2.length - 1) * 2 - 1;
23477
+ const mark = labels2[index].querySelector("[data-mk-rating-scale-mark]");
23478
+ keep(gsap.timeline().to(mark, { y: mood > 0 ? -8 * mood : 4 * -mood, rotate: mood === 0 ? 8 : 12 * mood, duration: 0.14, ease: "power2.out" }).to(mark, { y: 0, rotate: 0, duration: 0.55, ease: EASE.click, clearProps: "y,rotate" }));
23479
+ return;
23480
+ }
23481
+ const from = previous >= 0 ? previous : 0, step = index >= from ? 1 : -1;
23482
+ for (let i = from, k = 0; i !== index; i += step, k++) {
23483
+ keep(gsap.timeline({ delay: Math.min(k * 0.03, 0.3) }).to(labels2[i], { y: -5, duration: 0.12, ease: "power2.out" }).to(labels2[i], { y: 0, duration: 0.4, ease: EASE.click, clearProps: "y" }));
23484
+ }
23485
+ }
23486
+ });
23487
+ return {
23488
+ get value() {
23489
+ return instance.value === null ? null : Number(instance.value);
23490
+ },
23491
+ setValue: (value, notify = false) => instance.setValue(normalize3(value), notify),
23492
+ reset: (notify = false) => instance.reset(notify),
23493
+ destroy: () => instance.destroy()
23494
+ };
23495
+ }
23496
+
23497
+ // src/components/notification-stack/engine.ts
23498
+ var sequence28 = 0;
23499
+ function createNotificationStack(root, options = {}) {
23500
+ if (!root) return inert({ push() {
23501
+ }, dismiss() {
23502
+ }, clear() {
23503
+ }, expand() {
23504
+ }, collapse() {
23505
+ }, toggle() {
23506
+ }, setOptions() {
23507
+ }, items: [], expanded: false });
23508
+ registerMotion();
23509
+ const scope = createScope();
23510
+ let opts = { ...options };
23511
+ let expanded = options.expanded ?? false;
23512
+ let hovered = false;
23513
+ let focused = false;
23514
+ let inviting = false;
23515
+ let resize = null;
23516
+ const heights = /* @__PURE__ */ new WeakMap();
23517
+ const original = [...root.childNodes];
23518
+ const entries = /* @__PURE__ */ new Map();
23519
+ const animations = /* @__PURE__ */ new Set();
23520
+ const track = (animation) => {
23521
+ for (const prior of animations) if (prior.totalProgress() === 1 || !prior.parent) animations.delete(prior);
23522
+ if (animation) animations.add(animation);
23523
+ };
23524
+ const deck = document.createElement("div");
23525
+ deck.className = "mk-notification-stack__deck";
23526
+ deck.id = `mk-notifications-${++sequence28}`;
23527
+ const empty = document.createElement("p");
23528
+ empty.className = "mk-notification-stack__empty";
23529
+ const toggle = document.createElement("button");
23530
+ toggle.type = "button";
23531
+ toggle.className = "mk-notification-stack__toggle";
23532
+ toggle.setAttribute("aria-controls", deck.id);
23533
+ const count = document.createElement("span");
23534
+ const toggleText = document.createElement("span");
23535
+ const chevron2 = document.createElement("span");
23536
+ chevron2.className = "mk-notification-stack__chevron";
23537
+ chevron2.setAttribute("aria-hidden", "true");
23538
+ chevron2.innerHTML = '<svg viewBox="0 0 16 16"><path d="m4 6 4 4 4-4"/></svg>';
23539
+ toggle.append(count, toggleText, chevron2);
23540
+ const live2 = document.createElement("span");
23541
+ live2.className = "mk-sr-only";
23542
+ live2.setAttribute("role", "status");
23543
+ live2.setAttribute("aria-live", "polite");
23544
+ root.replaceChildren(deck, empty, toggle, live2);
23545
+ scope.attr(root, "class", `${root.className} mk-notification-stack`.trim());
23546
+ scope.attr(root, "data-mk-ready", "");
23547
+ scope.attr(root, "role", "region");
23548
+ const pause = (entry) => {
23549
+ if (entry.timer !== void 0) {
23550
+ clearTimeout(entry.timer);
23551
+ entry.timer = void 0;
23552
+ entry.remaining = Math.max(0, entry.remaining - (Date.now() - entry.started));
23553
+ }
23554
+ };
23555
+ const paused = () => hovered || focused || opts.disabled || document.hidden;
23556
+ const start = (entry) => {
23557
+ if (paused() || entry.remaining === Infinity || entry.timer !== void 0) return;
23558
+ entry.started = Date.now();
23559
+ entry.timer = setTimeout(() => dismiss(entry.item.id), entry.remaining);
23560
+ };
23561
+ const syncTimers = () => entries.forEach((entry) => paused() ? pause(entry) : start(entry));
23562
+ const duration = (item) => {
23563
+ const ms = item.duration ?? opts.duration ?? 6e3;
23564
+ return Number.isFinite(ms) && ms > 0 ? ms : Infinity;
23565
+ };
23566
+ const layout = (motion) => {
23567
+ if (scope.disposed) return;
23568
+ const cards = [...entries.values()].reverse();
23569
+ const direction = opts.direction === "up" || opts.direction === "side" ? opts.direction : "down";
23570
+ scope.attr(root, "data-mk-direction", direction);
23571
+ scope.attr(root, "data-mk-expandable", !expanded && cards.length > 1 && !opts.disabled ? "" : null);
23572
+ const peek = inviting && !expanded && !reduced() ? 18 : 12;
23573
+ cards.forEach((entry, index) => {
23574
+ const visible = expanded || index === 0;
23575
+ entry.card.inert = !visible || !!opts.disabled;
23576
+ entry.card.setAttribute("aria-hidden", String(!visible));
23577
+ entry.card.toggleAttribute("data-mk-peek", !visible);
23578
+ });
23579
+ if (cards[0]) deck.style.setProperty("--mk-stack-front", `${cards[0].card.offsetHeight}px`);
23580
+ let offset = 0;
23581
+ let tallest = 0;
23582
+ cards.forEach((entry, index) => {
23583
+ entry.card.style.zIndex = String(cards.length - index);
23584
+ const layer = Math.min(index, 3);
23585
+ let x = 0, y = 0;
23586
+ if (expanded) {
23587
+ if (direction === "side") x = offset;
23588
+ else y = direction === "up" ? -offset : offset;
23589
+ offset += direction === "side" ? entry.card.offsetWidth + 12 : entry.card.offsetHeight + 8;
23590
+ } else if (direction === "side") x = layer * peek;
23591
+ else y = (direction === "up" ? -1 : 1) * layer * peek;
23592
+ tallest = Math.max(tallest, entry.card.offsetHeight);
23593
+ const delay = reduced() ? 0 : motion === "expand" ? index * 0.05 : motion === "collapse" ? Math.max(0, cards.length - 1 - index) * 0.03 : 0;
23594
+ entry.card.style.setProperty("--mk-stack-delay", `${delay}s`);
23595
+ track(gsap.to(entry.card, { x, y, scale: expanded ? 1 : Math.max(0.84, 1 - index * 0.045), opacity: expanded || index < 3 ? 1 : 0, duration: reduced() ? 0 : 0.45, delay, ease: EASE.swatch, overwrite: "auto" }));
23596
+ if (motion === "expand" && index > 0 && !reduced()) track(gsap.fromTo(entry.card, { filter: "blur(6px)" }, { filter: "blur(0px)", duration: 0.4, delay, ease: "power2.out", clearProps: "filter" }));
23597
+ });
23598
+ const front = cards[0]?.card.offsetHeight || 100;
23599
+ const height = !cards.length ? 0 : direction === "side" ? expanded ? tallest : front : expanded ? offset - 8 : front + Math.min(cards.length - 1, 2) * peek;
23600
+ if (!expanded && direction === "side" && deck.scrollLeft) deck.scrollTo({ left: 0, behavior: reduced() ? "auto" : "smooth" });
23601
+ track(gsap.to(deck, { height, duration: reduced() ? 0 : 0.4, ease: EASE.signature, overwrite: "auto" }));
23602
+ empty.hidden = cards.length > 0;
23603
+ empty.textContent = opts.labels?.empty ?? "Todo al d\xEDa. No hay notificaciones.";
23604
+ toggle.hidden = cards.length < 2;
23605
+ toggle.disabled = !!opts.disabled;
23606
+ toggle.setAttribute("aria-expanded", String(expanded));
23607
+ const toggleLabel = expanded ? opts.labels?.collapse ?? "Recoger" : opts.labels?.expand ?? "Ver todas";
23608
+ if (toggleText.textContent !== toggleLabel) {
23609
+ toggleText.textContent = toggleLabel;
23610
+ if (motion) track(blurIn(toggleText, { from: "soft", duration: 0.25 }));
23611
+ }
23612
+ track(rollDigits(count, String(cards.length)));
23613
+ scope.attr(root, "aria-label", opts.label ?? "Notificaciones");
23614
+ scope.attr(root, "data-mk-expanded", String(expanded));
23615
+ scope.attr(root, "data-mk-disabled", opts.disabled ? "" : null);
23616
+ };
23617
+ const dismiss = (id) => {
23618
+ if (scope.disposed || opts.disabled) return;
23619
+ const entry = entries.get(id);
23620
+ if (!entry) return;
23621
+ pause(entry);
23622
+ resize?.unobserve(entry.card);
23623
+ const hadFocus = entry.card.contains(document.activeElement);
23624
+ entries.delete(id);
23625
+ if (hadFocus) {
23626
+ const next = [...entries.values()].reverse()[0];
23627
+ const target = next?.card.querySelector("button");
23628
+ if (target) {
23629
+ next.card.inert = false;
23630
+ target.focus();
23631
+ } else {
23632
+ root.setAttribute("tabindex", "-1");
23633
+ root.focus();
23634
+ }
23635
+ }
23636
+ gsap.killTweensOf(entry.card);
23637
+ entry.card.inert = true;
23638
+ entry.card.setAttribute("aria-hidden", "true");
23639
+ if (reduced()) entry.card.remove();
23640
+ else track(gsap.to(entry.card, { y: "-=18", scale: 0.94, opacity: 0, filter: "blur(8px)", duration: 0.23, ease: EASE.close, onComplete: () => entry.card.remove() }));
23641
+ layout();
23642
+ opts.onDismiss?.(id);
23643
+ root.dispatchEvent(new CustomEvent("mk:dismiss", { bubbles: true, detail: { id } }));
23644
+ };
23645
+ const build = (item) => {
23646
+ const card = document.createElement("article");
23647
+ card.className = "mk-notification-stack__card";
23648
+ card.dataset.mkNotification = item.id;
23649
+ card.dataset.mkTone = item.tone ?? "neutral";
23650
+ const mark = document.createElement("span");
23651
+ mark.className = "mk-notification-stack__mark";
23652
+ mark.setAttribute("aria-hidden", "true");
23653
+ mark.textContent = item.tone === "success" ? "\u2713" : item.tone === "error" ? "!" : "\u2197";
23654
+ const body = document.createElement("div");
23655
+ body.className = "mk-notification-stack__body";
23656
+ const title = document.createElement("strong");
23657
+ title.textContent = item.title;
23658
+ body.append(title);
23659
+ if (item.description) {
23660
+ const description = document.createElement("p");
23661
+ description.textContent = item.description;
23662
+ body.append(description);
23663
+ }
23664
+ if (item.action) {
23665
+ const action = document.createElement("button");
23666
+ action.type = "button";
23667
+ action.className = "mk-notification-stack__action";
23668
+ action.dataset.mkNotificationAction = item.id;
23669
+ action.textContent = item.action.label;
23670
+ action.disabled = !!opts.disabled;
23671
+ body.append(action);
23672
+ }
23673
+ card.append(mark, body);
23674
+ if (item.dismissible !== false) {
23675
+ const close = document.createElement("button");
23676
+ close.type = "button";
23677
+ close.className = "mk-notification-stack__dismiss";
23678
+ close.dataset.mkNotificationDismiss = item.id;
23679
+ close.setAttribute("aria-label", `${opts.labels?.dismiss ?? "Cerrar"}: ${item.title}`);
23680
+ close.textContent = "\xD7";
23681
+ close.disabled = !!opts.disabled;
23682
+ card.append(close);
23683
+ }
23684
+ return { item: { ...item }, card, remaining: duration(item), started: 0 };
23685
+ };
23686
+ const push = (item) => {
23687
+ if (scope.disposed || !item.id || entries.has(item.id)) return;
23688
+ const entry = build(item);
23689
+ entries.set(item.id, entry);
23690
+ deck.append(entry.card);
23691
+ resize?.observe(entry.card);
23692
+ layout();
23693
+ track(blurIn(entry.card, { from: "pop", duration: 0.35 }));
23694
+ live2.textContent = `${item.title}${item.description ? `. ${item.description}` : ""}`;
23695
+ start(entry);
23696
+ };
23697
+ const setExpanded = (next, notify = true, allowDisabled = false) => {
23698
+ if (scope.disposed || expanded === next || opts.disabled && !allowDisabled) return;
23699
+ if (!next && [...entries.values()].slice(0, -1).some((entry) => entry.card.contains(document.activeElement))) {
23700
+ if (opts.disabled) {
23701
+ root.tabIndex = -1;
23702
+ root.focus();
23703
+ } else toggle.focus();
23704
+ }
23705
+ expanded = next;
23706
+ layout(next ? "expand" : "collapse");
23707
+ if (notify) {
23708
+ opts.onExpandedChange?.(expanded);
23709
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { expanded } }));
23710
+ }
23711
+ };
23712
+ scope.attr(root, "tabindex", root.getAttribute("tabindex"));
23713
+ scope.on(root, "pointerenter", () => {
23714
+ hovered = true;
23715
+ syncTimers();
23716
+ });
23717
+ scope.on(root, "pointerleave", () => {
23718
+ hovered = false;
23719
+ syncTimers();
23720
+ });
23721
+ scope.on(root, "focusin", () => {
23722
+ focused = true;
23723
+ syncTimers();
23724
+ });
23725
+ scope.on(root, "focusout", (event) => {
23726
+ focused = root.contains(event.relatedTarget);
23727
+ syncTimers();
23728
+ });
23729
+ scope.on(document, "visibilitychange", syncTimers);
23730
+ scope.on(deck, "pointerenter", () => {
23731
+ inviting = true;
23732
+ if (!expanded && entries.size > 1) layout();
23733
+ });
23734
+ scope.on(deck, "pointerleave", () => {
23735
+ inviting = false;
23736
+ if (!expanded && entries.size > 1) layout();
23737
+ });
23738
+ scope.on(root, "click", (event) => {
23739
+ if (opts.disabled) return;
23740
+ if (!expanded && entries.size > 1 && deck.contains(event.target) && !event.target.closest("button")) {
23741
+ setExpanded(true);
23742
+ return;
23743
+ }
23744
+ const button2 = event.target.closest("button");
23745
+ if (!button2 || !root.contains(button2) || button2.disabled) return;
23746
+ track(press(button2));
23747
+ if (button2 === toggle) setExpanded(!expanded);
23748
+ else if (button2.dataset.mkNotificationDismiss) dismiss(button2.dataset.mkNotificationDismiss);
23749
+ else if (button2.dataset.mkNotificationAction) {
23750
+ const id = button2.dataset.mkNotificationAction;
23751
+ entries.get(id)?.item.action?.onClick?.();
23752
+ opts.onAction?.(id);
23753
+ dismiss(id);
23754
+ }
23755
+ });
23756
+ if (typeof ResizeObserver === "function") {
23757
+ resize = scope.observe(new ResizeObserver((records) => {
23758
+ let changed = false;
23759
+ for (const record of records) {
23760
+ const card = record.target;
23761
+ if (heights.get(card) !== card.offsetHeight) {
23762
+ heights.set(card, card.offsetHeight);
23763
+ changed = true;
23764
+ }
23765
+ }
23766
+ if (changed) layout();
23767
+ }));
23768
+ }
23769
+ scope.on(window, "resize", () => layout(), { passive: true });
23770
+ const setOptions = (next) => {
23771
+ if (scope.disposed) return;
23772
+ opts = { ...opts, ...next };
23773
+ if (next.items) {
23774
+ const ids = new Set(next.items.map((item) => item.id));
23775
+ for (const [id, entry] of entries) if (!ids.has(id)) {
23776
+ pause(entry);
23777
+ resize?.unobserve(entry.card);
23778
+ if (entry.card.contains(document.activeElement)) {
23779
+ root.setAttribute("tabindex", "-1");
23780
+ root.focus();
23781
+ }
23782
+ gsap.killTweensOf(entry.card);
23783
+ entry.card.remove();
23784
+ entries.delete(id);
23785
+ }
23786
+ for (const item of next.items) {
23787
+ const existing = entries.get(item.id);
23788
+ if (!existing) {
23789
+ push(item);
23790
+ continue;
23791
+ }
23792
+ const replacement = build(item);
23793
+ if (existing.card.contains(document.activeElement)) {
23794
+ root.setAttribute("tabindex", "-1");
23795
+ root.focus();
23796
+ }
23797
+ pause(existing);
23798
+ replacement.remaining = existing.remaining;
23799
+ existing.card.replaceWith(replacement.card);
23800
+ gsap.killTweensOf(existing.card);
23801
+ entries.set(item.id, replacement);
23802
+ resize?.unobserve(existing.card);
23803
+ resize?.observe(replacement.card);
23804
+ }
23805
+ const ordered = next.items.map((item) => entries.get(item.id)).filter((entry) => !!entry);
23806
+ entries.clear();
23807
+ for (const entry of ordered) {
23808
+ entries.set(entry.item.id, entry);
23809
+ deck.append(entry.card);
23810
+ }
23811
+ }
23812
+ if (next.expanded !== void 0) setExpanded(next.expanded, false, true);
23813
+ for (const entry of entries.values()) entry.card.querySelectorAll("button").forEach((button2) => {
23814
+ button2.disabled = !!opts.disabled;
23815
+ if (button2.hasAttribute("data-mk-notification-dismiss")) button2.setAttribute("aria-label", `${opts.labels?.dismiss ?? "Cerrar"}: ${entry.item.title}`);
23816
+ });
23817
+ layout();
23818
+ syncTimers();
23819
+ };
23820
+ for (const item of options.items ?? []) push(item);
23821
+ layout();
23822
+ return {
23823
+ push,
23824
+ dismiss,
23825
+ clear() {
23826
+ for (const id of [...entries.keys()]) dismiss(id);
23827
+ },
23828
+ expand: () => setExpanded(true),
23829
+ collapse: () => setExpanded(false),
23830
+ toggle: () => setExpanded(!expanded),
23831
+ setOptions,
23832
+ get items() {
23833
+ return [...entries.values()].map((entry) => ({ ...entry.item }));
23834
+ },
23835
+ get expanded() {
23836
+ return expanded;
23837
+ },
23838
+ destroy() {
23839
+ if (scope.disposed) return;
23840
+ entries.forEach(pause);
23841
+ animations.forEach((animation) => animation.kill());
23842
+ gsap.killTweensOf([...root.querySelectorAll("*")]);
23843
+ scope.dispose();
23844
+ root.replaceChildren(...original);
23845
+ }
23846
+ };
23847
+ }
23848
+
23849
+ // src/components/bento-grid/engine.ts
23850
+ function createBentoGrid(root, options = {}) {
23851
+ if (!root) return inert({ refresh() {
23852
+ }, setFilter() {
23853
+ }, reorder() {
23854
+ }, mutate() {
23855
+ }, setOptions() {
23856
+ }, filter: null, keys: [] });
23857
+ registerMotion();
23858
+ const scope = createScope();
23859
+ let opts = { ...options };
23860
+ let filter = opts.filter ?? null;
23861
+ let animation = null;
23862
+ const micro = /* @__PURE__ */ new Set();
23863
+ const track = (value) => {
23864
+ if (value) micro.add(value);
23865
+ };
23866
+ const originals = [...root.childNodes];
23867
+ const originalItems = new Set(root.children);
23868
+ const remembered = /* @__PURE__ */ new Set();
23869
+ let queued = 0;
23870
+ scope.attr(root, "class", `${root.className} mk-bento-grid`.trim());
23871
+ scope.attr(root, "style", root.getAttribute("style"));
23872
+ scope.attr(root, "data-mk-ready", "");
23873
+ const items = () => [...root.children].filter((node) => node instanceof HTMLElement && node.hasAttribute("data-mk-bento-item"));
23874
+ const key2 = (item) => item.dataset.mkBentoItem;
23875
+ const visible = () => items().filter((item) => !item.hidden);
23876
+ const save = (item) => {
23877
+ if (remembered.has(item)) return;
23878
+ remembered.add(item);
23879
+ for (const attr of ["style", "hidden", "inert", "aria-hidden", "data-flip-id"]) scope.attr(item, attr, item.getAttribute(attr));
23880
+ };
23881
+ items().forEach(save);
23882
+ let last;
23883
+ const notify = () => {
23884
+ const keys = visible().map(key2);
23885
+ opts.onChange?.(keys);
23886
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { keys, filter } }));
23887
+ };
23888
+ const paint = () => {
23889
+ const desired = Number.isFinite(opts.columns) ? Math.max(1, Math.min(12, Math.round(opts.columns))) : 3;
23890
+ const cols = root.clientWidth > 0 && root.clientWidth < 280 ? 1 : root.clientWidth > 0 && root.clientWidth < 440 ? Math.min(2, desired) : desired;
23891
+ root.style.setProperty("--mk-bento-columns", String(cols));
23892
+ root.style.setProperty("--mk-bento-gap", `${Math.max(0, opts.gap ?? 12)}px`);
23893
+ items().forEach((item) => {
23894
+ save(item);
23895
+ item.style.setProperty("--mk-bento-col-span", String(Math.max(1, Math.min(cols, Number(item.dataset.mkColSpan) || 1))));
23896
+ item.style.setProperty("--mk-bento-row-span", String(Math.max(1, Math.min(8, Number(item.dataset.mkRowSpan) || 1))));
23897
+ const show = !filter || (item.dataset.mkCategory ?? "").split(/\s+/).includes(filter);
23898
+ if (!show && item.contains(document.activeElement)) {
23899
+ scope.attr(root, "tabindex", root.getAttribute("tabindex"));
23900
+ root.tabIndex = -1;
23901
+ root.focus();
23902
+ }
23903
+ item.hidden = !show;
23904
+ item.inert = !show;
23905
+ item.setAttribute("aria-hidden", String(!show));
23906
+ });
23907
+ scope.attr(root, "data-mk-empty", visible().length ? null : "");
23908
+ if (!root.hasAttribute("data-mk-empty-label")) scope.attr(root, "data-mk-empty-label", "No hay elementos en esta vista.");
23909
+ };
23910
+ const transition = (state = last, entering = []) => {
23911
+ if (scope.disposed) return;
23912
+ animation?.kill();
23913
+ paint();
23914
+ if (!reduced()) {
23915
+ animation = Flip.from(state ?? Flip.getState([]), { targets: visible(), duration: Math.max(0, opts.duration ?? 0.55), ease: EASE.signature, stagger: 0.025, absolute: false, scale: false, prune: true, onComplete: () => {
23916
+ if (!scope.disposed) last = Flip.getState(visible());
23917
+ } });
23918
+ track(blurIn(entering.filter((item) => !item.hidden), { from: "soft", stagger: 0.04, duration: 0.35 }));
23919
+ }
23920
+ if (!reduced()) last = Flip.getState(visible());
23921
+ };
23922
+ const capture = () => {
23923
+ animation?.kill();
23924
+ if (reduced()) return void 0;
23925
+ const focused = document.activeElement;
23926
+ Flip.killFlipsOf(items());
23927
+ const state = Flip.getState(visible());
23928
+ if (focused?.isConnected && focused !== document.activeElement) focused.focus({ preventScroll: true });
23929
+ return state;
23930
+ };
23931
+ const mutate = (change) => {
23932
+ if (scope.disposed) return;
23933
+ const focused = document.activeElement;
23934
+ const state = capture();
23935
+ const before = new Set(items());
23936
+ change();
23937
+ transition(state, items().filter((item) => !before.has(item)));
23938
+ if (focused && focused !== document.body && root.contains(focused) && !focused.closest("[hidden], [inert]")) focused.focus({ preventScroll: true });
23939
+ else if (focused && !focused.isConnected) {
23940
+ scope.attr(root, "tabindex", root.getAttribute("tabindex"));
23941
+ root.tabIndex = -1;
23942
+ root.focus();
23943
+ }
23944
+ observer?.takeRecords();
23945
+ notify();
23946
+ };
23947
+ const setFilter = (next) => {
23948
+ if (scope.disposed || next === filter) return;
23949
+ const state = capture();
23950
+ const before = new Set(visible());
23951
+ filter = next;
23952
+ paint();
23953
+ transition(state, visible().filter((item) => !before.has(item)));
23954
+ notify();
23955
+ };
23956
+ const refresh = () => {
23957
+ if (scope.disposed) return;
23958
+ transition(last, items().filter((item) => !remembered.has(item)));
23959
+ };
23960
+ const observer = typeof MutationObserver === "function" ? scope.observe(new MutationObserver((records) => {
23961
+ if (!records.some((record) => record.type === "childList" ? record.target === root : record.target instanceof HTMLElement && record.target.parentElement === root)) return;
23962
+ cancelAnimationFrame(queued);
23963
+ queued = requestAnimationFrame(refresh);
23964
+ })) : null;
23965
+ observer?.observe(root, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-mk-category", "data-mk-col-span", "data-mk-row-span"] });
23966
+ scope.on(root, "click", (event) => {
23967
+ const control = event.target.closest("button, a");
23968
+ if (control && root.contains(control) && !control.matches(':disabled, [aria-disabled="true"]')) {
23969
+ scope.attr(control, "style", control.getAttribute("style"));
23970
+ track(press(control));
23971
+ }
23972
+ });
23973
+ if (typeof ResizeObserver === "function") {
23974
+ let width = root.clientWidth;
23975
+ const resize = scope.observe(new ResizeObserver(() => {
23976
+ if (root.clientWidth !== width) {
23977
+ width = root.clientWidth;
23978
+ animation?.kill();
23979
+ paint();
23980
+ last = Flip.getState(visible());
23981
+ }
23982
+ }));
23983
+ resize.observe(root);
23984
+ }
23985
+ paint();
23986
+ if (!reduced()) last = Flip.getState(visible());
23987
+ track(blurIn(visible(), { from: "soft", stagger: 0.04 }));
23988
+ return {
23989
+ refresh,
23990
+ mutate,
23991
+ setFilter,
23992
+ reorder(keys) {
23993
+ mutate(() => {
23994
+ const byKey = new Map(items().map((item) => [key2(item), item]));
23995
+ for (const id of new Set(keys)) {
23996
+ const item = byKey.get(id);
23997
+ if (item) {
23998
+ root.append(item);
23999
+ byKey.delete(id);
24000
+ }
24001
+ }
24002
+ byKey.forEach((item) => root.append(item));
24003
+ });
24004
+ },
24005
+ setOptions(next) {
24006
+ if (scope.disposed) return;
24007
+ const state = capture();
24008
+ opts = { ...opts, ...next };
24009
+ if (next.filter !== void 0) filter = next.filter;
24010
+ transition(state);
24011
+ },
24012
+ get filter() {
24013
+ return filter;
24014
+ },
24015
+ get keys() {
24016
+ return visible().map(key2);
24017
+ },
24018
+ destroy() {
24019
+ if (scope.disposed) return;
24020
+ cancelAnimationFrame(queued);
24021
+ animation?.kill();
24022
+ micro.forEach((value) => value.kill());
24023
+ if (!reduced()) Flip.killFlipsOf(items());
24024
+ gsap.killTweensOf([...remembered]);
24025
+ scope.dispose();
24026
+ const added = [...root.childNodes].filter((node) => !originals.includes(node) && !(node instanceof Element && originalItems.has(node)));
24027
+ root.replaceChildren(...originals, ...added);
24028
+ }
24029
+ };
24030
+ }
24031
+
24032
+ // src/components/scroll-preview-dock/engine.ts
24033
+ function createScrollPreviewDock(root, options = {}) {
24034
+ if (!root) return inert({ select() {
24035
+ }, update() {
24036
+ }, setOptions() {
24037
+ }, value: "" });
24038
+ registerMotion();
24039
+ const scope = createScope();
24040
+ let opts = { ...options };
24041
+ let current3 = "";
24042
+ let previewed = "";
24043
+ let frame = 0;
24044
+ let scrolling = null;
24045
+ let unbindScroller = () => {
24046
+ };
24047
+ let scroller = null;
24048
+ const original = [...root.childNodes];
24049
+ const animations = /* @__PURE__ */ new Set();
24050
+ const track = (animation) => {
24051
+ if (animation) animations.add(animation);
24052
+ };
24053
+ const panel = document.createElement("div");
24054
+ panel.className = "mk-scroll-preview-dock__preview";
24055
+ panel.setAttribute("aria-hidden", "true");
24056
+ const image = document.createElement("span");
24057
+ image.className = "mk-scroll-preview-dock__image";
24058
+ const copy = document.createElement("span");
24059
+ const title = document.createElement("strong");
24060
+ const description = document.createElement("span");
24061
+ description.className = "mk-scroll-preview-dock__description";
24062
+ copy.append(title, description);
24063
+ panel.append(image, copy);
24064
+ const nav = document.createElement("nav");
24065
+ nav.className = "mk-scroll-preview-dock__nav";
24066
+ const pill = document.createElement("span");
24067
+ pill.className = "mk-scroll-preview-dock__pill";
24068
+ pill.setAttribute("aria-hidden", "true");
24069
+ const empty = document.createElement("p");
24070
+ empty.className = "mk-scroll-preview-dock__empty";
24071
+ empty.textContent = "No hay secciones para explorar.";
24072
+ root.replaceChildren(panel, nav, empty);
24073
+ scope.attr(root, "class", `${root.className} mk-scroll-preview-dock`.trim());
24074
+ scope.attr(root, "data-mk-ready", "");
24075
+ const items = () => opts.items ?? [];
24076
+ const enabled = (item) => !opts.disabled && !item.disabled;
24077
+ const section = (item) => {
24078
+ if (item.section instanceof HTMLElement) return item.section;
24079
+ if (!item.section) return document.getElementById(item.id);
24080
+ try {
24081
+ return (scroller ?? document).querySelector(item.section);
24082
+ } catch {
24083
+ return null;
24084
+ }
24085
+ };
24086
+ const links = () => [...nav.querySelectorAll("a")];
24087
+ const thumb = (node, item) => {
24088
+ node.replaceChildren();
24089
+ if (item.thumbnail) {
24090
+ const img = document.createElement("img");
24091
+ img.src = item.thumbnail;
24092
+ img.alt = "";
24093
+ img.draggable = false;
24094
+ node.append(img);
24095
+ } else {
24096
+ const letter = document.createElement("span");
24097
+ letter.textContent = item.label.slice(0, 2);
24098
+ node.append(letter);
24099
+ }
24100
+ };
24101
+ const preview = (id, animate = true) => {
24102
+ const item = items().find((item2) => item2.id === id);
24103
+ if (!item || previewed === id) return;
24104
+ previewed = id;
24105
+ thumb(image, item);
24106
+ title.textContent = item.label;
24107
+ description.textContent = item.description ?? "Explorar secci\xF3n";
24108
+ for (const link of links()) link.dataset.mkPreview = String(link.dataset.mkSection === id);
24109
+ if (animate) {
24110
+ gsap.killTweensOf(panel);
24111
+ track(blurIn(panel, { from: "soft", duration: 0.28 }));
24112
+ }
24113
+ };
24114
+ const place3 = (animate = true) => {
24115
+ const active = links().find((link) => link.dataset.mkSection === current3);
24116
+ pill.hidden = !active;
24117
+ if (!active) return;
24118
+ track(gsap.to(pill, { x: active.offsetLeft, y: active.offsetTop, width: active.offsetWidth, height: active.offsetHeight, duration: reduced() || !animate ? 0 : 0.45, ease: EASE.swatch, overwrite: "auto" }));
24119
+ };
24120
+ const activate = (id, notify = true) => {
24121
+ if (scope.disposed || current3 === id) return;
24122
+ current3 = id;
24123
+ for (const link of links()) {
24124
+ if (link.dataset.mkSection === id) link.setAttribute("aria-current", "location");
24125
+ else link.removeAttribute("aria-current");
24126
+ }
24127
+ place3();
24128
+ if (!root.contains(document.activeElement) && !root.matches(":hover")) preview(id);
24129
+ else if (!previewed) preview(id, false);
24130
+ if (notify) {
24131
+ opts.onChange?.(id);
24132
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { value: id } }));
24133
+ }
24134
+ };
24135
+ const update = () => {
24136
+ frame = 0;
24137
+ if (scope.disposed) return;
24138
+ const top = scroller ? scroller.getBoundingClientRect().top + scroller.clientTop : 0;
24139
+ const height = scroller ? scroller.clientHeight : window.innerHeight;
24140
+ const line = top + Math.min(120, height * 0.3) + (opts.offset ?? 0);
24141
+ const targets = items().filter(enabled).map((item) => ({ item, node: section(item) })).filter((entry) => !!entry.node);
24142
+ let target = targets[0];
24143
+ for (const entry of targets) if (entry.node.getBoundingClientRect().top <= line) target = entry;
24144
+ const atEnd = scroller ? scroller.scrollHeight > scroller.clientHeight && scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight - 2 : document.documentElement.scrollHeight > window.innerHeight && window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - 2;
24145
+ if (atEnd) target = targets.at(-1);
24146
+ if (target) activate(target.item.id);
24147
+ place3(false);
24148
+ };
24149
+ const queue = () => {
24150
+ if (!frame) frame = requestAnimationFrame(update);
24151
+ };
24152
+ const bindScroller = () => {
24153
+ unbindScroller();
24154
+ scroller = typeof opts.scroller === "string" ? (() => {
24155
+ try {
24156
+ return root.closest(opts.scroller) ?? document.querySelector(opts.scroller);
24157
+ } catch {
24158
+ return null;
24159
+ }
24160
+ })() : opts.scroller ?? null;
24161
+ const target = scroller ?? window;
24162
+ target.addEventListener("scroll", queue, { passive: true });
24163
+ target.addEventListener("wheel", cancelScroll, { passive: true });
24164
+ target.addEventListener("touchstart", cancelScroll, { passive: true });
24165
+ unbindScroller = () => {
24166
+ target.removeEventListener("scroll", queue);
24167
+ target.removeEventListener("wheel", cancelScroll);
24168
+ target.removeEventListener("touchstart", cancelScroll);
24169
+ };
24170
+ };
24171
+ function cancelScroll() {
24172
+ scrolling?.kill();
24173
+ scrolling = null;
24174
+ }
24175
+ const select = (id) => {
24176
+ if (scope.disposed) return;
24177
+ const item = items().find((entry) => entry.id === id);
24178
+ if (!item || !enabled(item)) return;
24179
+ const target = section(item);
24180
+ if (!target) return;
24181
+ cancelScroll();
24182
+ const top = Math.max(0, (scroller ? scroller.scrollTop + target.getBoundingClientRect().top - scroller.getBoundingClientRect().top - scroller.clientTop : window.scrollY + target.getBoundingClientRect().top) - (opts.offset ?? 0));
24183
+ activate(id);
24184
+ preview(id);
24185
+ if (scroller) {
24186
+ if (reduced()) scroller.scrollTop = top;
24187
+ else scrolling = gsap.to(scroller, { scrollTop: top, duration: 0.65, ease: EASE.signature, overwrite: "auto", onUpdate: queue });
24188
+ } else if (reduced()) window.scrollTo({ top, behavior: "instant" });
24189
+ else {
24190
+ const position2 = { top: window.scrollY };
24191
+ scrolling = gsap.to(position2, { top, duration: 0.65, ease: EASE.signature, onUpdate: () => {
24192
+ window.scrollTo(0, position2.top);
24193
+ queue();
24194
+ } });
24195
+ }
24196
+ };
24197
+ const render = () => {
24198
+ gsap.killTweensOf(pill);
24199
+ nav.replaceChildren(pill);
24200
+ nav.setAttribute("aria-label", opts.label ?? "Explorar secciones");
24201
+ const unique = /* @__PURE__ */ new Set();
24202
+ for (const item of items()) {
24203
+ if (!item.id || unique.has(item.id)) continue;
24204
+ unique.add(item.id);
24205
+ const link = document.createElement("a");
24206
+ link.href = `#${encodeURIComponent(section(item)?.id || item.id)}`;
24207
+ link.dataset.mkSection = item.id;
24208
+ link.className = "mk-scroll-preview-dock__item";
24209
+ const cover = document.createElement("span");
24210
+ cover.className = "mk-scroll-preview-dock__thumb";
24211
+ cover.setAttribute("aria-hidden", "true");
24212
+ thumb(cover, item);
24213
+ const label = document.createElement("span");
24214
+ label.textContent = item.label;
24215
+ link.append(cover, label);
24216
+ if (!enabled(item)) {
24217
+ link.setAttribute("aria-disabled", "true");
24218
+ link.tabIndex = -1;
24219
+ }
24220
+ nav.append(link);
24221
+ }
24222
+ empty.hidden = unique.size > 0;
24223
+ panel.hidden = unique.size === 0;
24224
+ nav.hidden = unique.size === 0;
24225
+ scope.attr(root, "data-mk-disabled", opts.disabled ? "" : null);
24226
+ previewed = "";
24227
+ const next = items().find((item) => item.id === current3 && enabled(item)) ?? items().find(enabled);
24228
+ current3 = "";
24229
+ if (next) {
24230
+ activate(next.id, false);
24231
+ preview(next.id, false);
24232
+ } else pill.hidden = true;
24233
+ };
24234
+ scope.on(nav, "click", (event) => {
24235
+ const link = event.target.closest("a[data-mk-section]");
24236
+ if (!link) return;
24237
+ if (link.getAttribute("aria-disabled") === "true") {
24238
+ event.preventDefault();
24239
+ return;
24240
+ }
24241
+ if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey || event.button !== 0) return;
24242
+ const item = items().find((item2) => item2.id === link.dataset.mkSection);
24243
+ if (!item || !section(item)) return;
24244
+ event.preventDefault();
24245
+ track(press(link));
24246
+ select(item.id);
24247
+ });
24248
+ scope.on(nav, "pointerover", (event) => {
24249
+ const link = event.target.closest("a[data-mk-section]");
24250
+ if (link && link.getAttribute("aria-disabled") !== "true") preview(link.dataset.mkSection);
24251
+ });
24252
+ scope.on(nav, "focusin", (event) => {
24253
+ const link = event.target.closest("a[data-mk-section]");
24254
+ if (link) preview(link.dataset.mkSection);
24255
+ });
24256
+ scope.on(root, "pointerleave", () => {
24257
+ if (!root.contains(document.activeElement)) preview(current3);
24258
+ });
24259
+ scope.on(root, "focusout", (event) => {
24260
+ if (!root.contains(event.relatedTarget)) preview(current3);
24261
+ });
24262
+ scope.on(nav, "keydown", (event) => {
24263
+ if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) {
24264
+ if (["PageUp", "PageDown", "ArrowUp", "ArrowDown", " "].includes(event.key)) cancelScroll();
24265
+ return;
24266
+ }
24267
+ const available = links().filter((link) => link.getAttribute("aria-disabled") !== "true");
24268
+ const index = available.indexOf(document.activeElement);
24269
+ if (index < 0 || !available.length) return;
24270
+ event.preventDefault();
24271
+ available[event.key === "Home" ? 0 : event.key === "End" ? available.length - 1 : (index + (event.key === "ArrowRight" ? 1 : -1) + available.length) % available.length]?.focus();
24272
+ });
24273
+ scope.on(window, "resize", queue, { passive: true });
24274
+ if (typeof ResizeObserver === "function") {
24275
+ const resize = scope.observe(new ResizeObserver(queue));
24276
+ resize.observe(nav);
24277
+ }
24278
+ bindScroller();
24279
+ render();
24280
+ update();
24281
+ return {
24282
+ select,
24283
+ update,
24284
+ get value() {
24285
+ return current3;
24286
+ },
24287
+ setOptions(next) {
24288
+ if (scope.disposed) return;
24289
+ const focusedId = root.contains(document.activeElement) ? document.activeElement?.closest("a[data-mk-section]")?.dataset.mkSection : void 0;
24290
+ opts = { ...opts, ...next };
24291
+ if ("scroller" in next) {
24292
+ cancelScroll();
24293
+ bindScroller();
24294
+ }
24295
+ render();
24296
+ if (focusedId) {
24297
+ const target = links().find((link) => link.dataset.mkSection === focusedId && link.getAttribute("aria-disabled") !== "true") ?? links().find((link) => link.getAttribute("aria-disabled") !== "true");
24298
+ if (target) target.focus();
24299
+ else {
24300
+ scope.attr(root, "tabindex", root.getAttribute("tabindex"));
24301
+ root.tabIndex = -1;
24302
+ root.focus();
24303
+ }
24304
+ }
24305
+ update();
24306
+ },
24307
+ destroy() {
24308
+ if (scope.disposed) return;
24309
+ cancelAnimationFrame(frame);
24310
+ cancelScroll();
24311
+ unbindScroller();
24312
+ animations.forEach((animation) => animation.kill());
24313
+ gsap.killTweensOf([...root.querySelectorAll("*")]);
24314
+ scope.dispose();
24315
+ root.replaceChildren(...original);
24316
+ }
24317
+ };
24318
+ }
24319
+
24320
+ // src/components/sticky-header/engine.ts
24321
+ function createStickyHeader(root, options = {}) {
24322
+ const surface = root?.querySelector("[data-mk-sticky-surface]");
24323
+ if (!root || !surface) {
24324
+ if (root) warnOnce("sticky-header: needs an authored [data-mk-sticky-surface]");
24325
+ return inert({ update() {
24326
+ }, setOptions() {
24327
+ }, compact: false, progress: 0 });
24328
+ }
24329
+ registerMotion();
24330
+ const scope = createScope();
24331
+ let opts = { ...options };
24332
+ let scroller = null;
24333
+ let unbind = () => {
24334
+ };
24335
+ let frame = 0;
24336
+ let progress = -1;
24337
+ let compact2 = false;
24338
+ const title = surface.querySelector("[data-mk-sticky-title]");
24339
+ const subtitle = surface.querySelector("[data-mk-sticky-subtitle]");
24340
+ const animations = /* @__PURE__ */ new Set();
24341
+ const track = (animation) => {
24342
+ if (animation) animations.add(animation);
24343
+ };
24344
+ for (const node of [root, surface, title, subtitle]) if (node) scope.attr(node, "style", node.getAttribute("style"));
24345
+ scope.attr(root, "class", `${root.className} mk-sticky-header`.trim());
24346
+ scope.attr(root, "data-mk-ready", "");
24347
+ const dimensions = () => {
24348
+ const large = Number.isFinite(opts.expandedHeight) ? Math.max(48, opts.expandedHeight) : 104;
24349
+ const small = Number.isFinite(opts.compactHeight) ? Math.max(40, Math.min(large, opts.compactHeight)) : Math.min(64, large);
24350
+ root.style.setProperty("--mk-sticky-expanded-height", `${large}px`);
24351
+ root.style.setProperty("--mk-sticky-top", `${Math.max(0, opts.top ?? 0)}px`);
24352
+ return { large, small };
24353
+ };
24354
+ const update = () => {
24355
+ frame = 0;
24356
+ if (scope.disposed) return;
24357
+ const { large, small } = dimensions();
24358
+ const position2 = scroller ? scroller.scrollTop : window.scrollY;
24359
+ const next = opts.disabled ? 0 : Math.max(0, Math.min(1, (position2 - Math.max(0, opts.threshold ?? 8)) / Math.max(1, opts.range ?? 96)));
24360
+ if (next === progress) return;
24361
+ const initial = progress < 0;
24362
+ progress = next;
24363
+ const isCompact = next >= 0.5;
24364
+ scope.attr(root, "data-mk-compact", String(isCompact));
24365
+ scope.attr(root, "data-mk-disabled", opts.disabled ? "" : null);
24366
+ const duration = reduced() || initial ? 0 : 0.22;
24367
+ track(gsap.to(surface, { height: large + (small - large) * next, borderRadius: 24 - 8 * next, paddingLeft: 24 - 8 * next, paddingRight: 24 - 8 * next, duration, ease: EASE.swatch, overwrite: "auto" }));
24368
+ if (title) track(gsap.to(title, { scale: 1 - 0.16 * next, y: -2 * next, transformOrigin: "left center", duration, ease: EASE.swatch, overwrite: "auto" }));
24369
+ if (subtitle) track(gsap.to(subtitle, { opacity: 1 - next, y: -8 * next, height: `${(1 - next) * 1.5}em`, filter: `blur(${next * 4}px)`, duration, ease: EASE.signature, overwrite: "auto" }));
24370
+ if (isCompact !== compact2) {
24371
+ compact2 = isCompact;
24372
+ opts.onChange?.(compact2);
24373
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { compact: compact2, progress } }));
24374
+ }
24375
+ };
24376
+ const queue = () => {
24377
+ if (!frame) frame = requestAnimationFrame(update);
24378
+ };
24379
+ const bind = () => {
24380
+ unbind();
24381
+ scroller = typeof opts.scroller === "string" ? (() => {
24382
+ try {
24383
+ return root.closest(opts.scroller) ?? document.querySelector(opts.scroller);
24384
+ } catch {
24385
+ return null;
24386
+ }
24387
+ })() : opts.scroller ?? null;
24388
+ const target = scroller ?? window;
24389
+ target.addEventListener("scroll", queue, { passive: true });
24390
+ unbind = () => target.removeEventListener("scroll", queue);
24391
+ };
24392
+ scope.on(window, "resize", queue, { passive: true });
24393
+ scope.on(surface, "click", (event) => {
24394
+ const control = event.target.closest("button, a");
24395
+ if (control && !control.matches(':disabled, [aria-disabled="true"]')) {
24396
+ scope.attr(control, "style", control.getAttribute("style"));
24397
+ track(press(control));
24398
+ }
24399
+ });
24400
+ if (typeof ResizeObserver === "function") {
24401
+ const observer = scope.observe(new ResizeObserver(queue));
24402
+ observer.observe(root);
24403
+ }
24404
+ bind();
24405
+ update();
24406
+ return {
24407
+ update,
24408
+ get compact() {
24409
+ return compact2;
24410
+ },
24411
+ get progress() {
24412
+ return Math.max(0, progress);
24413
+ },
24414
+ setOptions(next) {
24415
+ if (scope.disposed) return;
24416
+ opts = { ...opts, ...next };
24417
+ if ("scroller" in next) bind();
24418
+ progress = -1;
24419
+ update();
24420
+ },
24421
+ destroy() {
24422
+ if (scope.disposed) return;
24423
+ cancelAnimationFrame(frame);
24424
+ unbind();
24425
+ animations.forEach((animation) => animation.kill());
24426
+ gsap.killTweensOf([surface, title, subtitle].filter((node) => !!node));
24427
+ scope.dispose();
24428
+ }
24429
+ };
24430
+ }
24431
+
24432
+ // src/components/handwriting-text/glyphs.ts
24433
+ var GLYPHS = {
24434
+ A: { width: 35, strokes: ["M2 43L26 5L27 42", "M10 30L31 28"] },
24435
+ B: { width: 34, strokes: ["M4 43L14 7", "M10 8C40 -2 35 25 11 25C40 14 37 45 4 43"] },
24436
+ C: { width: 34, strokes: ["M33 12C18 -8 -3 20 5 36Q12 52 31 35"] },
24437
+ D: { width: 35, strokes: ["M5 43L15 7", "M10 7C46 -3 40 48 4 43"] },
24438
+ E: { width: 30, strokes: ["M31 7L13 9L4 42L29 40", "M10 25L27 23"] },
24439
+ F: { width: 29, strokes: ["M4 43L14 8L32 7", "M10 25L27 24"] },
24440
+ G: { width: 36, strokes: ["M33 12C15 -8 -4 27 7 39Q21 51 31 26L19 28"] },
24441
+ H: { width: 36, strokes: ["M4 43L14 7", "M28 43L37 7", "M8 27L32 24"] },
24442
+ I: { width: 20, strokes: ["M17 8L8 42", "M9 9L25 7", "M1 43L17 41"] },
24443
+ J: { width: 28, strokes: ["M19 8L32 7L24 33Q17 54 3 38"] },
24444
+ K: { width: 34, strokes: ["M4 43L14 7", "M35 7L10 29L29 43"] },
24445
+ L: { width: 28, strokes: ["M14 7L4 42Q15 39 29 41"] },
24446
+ M: { width: 47, strokes: ["M3 43L15 7L22 35L44 7L35 43"] },
24447
+ N: { width: 37, strokes: ["M4 43L14 7L28 42L38 7"] },
24448
+ O: { width: 36, strokes: ["M25 7C5 1 -5 43 15 43C35 46 46 3 25 7Z"] },
24449
+ P: { width: 32, strokes: ["M4 43L14 8C40 -2 39 30 8 27"] },
24450
+ Q: { width: 37, strokes: ["M25 7C5 1 -5 43 15 43C35 46 46 3 25 7Z", "M19 33L33 48"] },
24451
+ R: { width: 34, strokes: ["M4 43L14 8C40 -2 39 30 8 27L29 44"] },
24452
+ S: { width: 31, strokes: ["M31 12C19 -5 -4 16 16 25C39 35 12 55 2 36"] },
24453
+ T: { width: 31, strokes: ["M3 10L34 7", "M20 9L11 43"] },
24454
+ U: { width: 36, strokes: ["M13 7L5 31C-1 52 27 48 31 29L37 7"] },
24455
+ V: { width: 35, strokes: ["M7 7L10 43L37 7"] },
24456
+ W: { width: 48, strokes: ["M7 7L9 43L27 15L28 43L50 7"] },
24457
+ X: { width: 34, strokes: ["M10 7L28 43", "M36 7L2 43"] },
24458
+ Y: { width: 34, strokes: ["M8 7L19 27L37 7", "M19 27L14 43"] },
24459
+ Z: { width: 32, strokes: ["M7 9L34 7L2 43L29 41"] },
24460
+ a: { width: 27, strokes: ["M23 23C9 12 2 40 13 42C21 44 26 21 23 22L20 39Q20 47 29 37"] },
24461
+ b: { width: 27, strokes: ["M4 42Q21 -6 13 3Q5 7 7 36C19 7 34 30 19 40Q11 46 7 38L29 36"] },
24462
+ c: { width: 25, strokes: ["M23 24C17 13 3 26 6 37Q10 49 27 35"] },
24463
+ d: { width: 28, strokes: ["M22 24C8 12 0 39 11 42Q20 46 29 4Q31 -1 27 3L21 38Q21 46 31 35"] },
24464
+ e: { width: 25, strokes: ["M5 33Q25 29 21 21Q17 13 8 27C-1 43 15 49 27 35"] },
24465
+ f: { width: 23, strokes: ["M2 57Q1 63 7 52L22 7Q24 -3 16 5Q7 17 11 27L24 24", "M3 27L20 26"] },
24466
+ g: { width: 28, strokes: ["M24 24C10 12 1 39 12 42Q20 45 24 23L18 54Q12 68 6 57Q3 48 31 36"] },
24467
+ h: { width: 28, strokes: ["M4 42Q24 -6 14 4Q8 10 5 41C17 9 26 18 21 34Q17 49 31 35"] },
24468
+ i: { width: 15, strokes: ["M9 24L5 36Q2 47 18 35", "M12 13L12.2 13.2"] },
24469
+ j: { width: 18, strokes: ["M13 24L6 53Q1 68 -4 56Q-6 48 21 35", "M16 13L16.2 13.2"] },
24470
+ k: { width: 27, strokes: ["M4 42Q24 -7 14 4Q8 10 5 41", "M25 22Q8 38 10 32Q17 27 19 37Q21 45 30 35"] },
24471
+ l: { width: 18, strokes: ["M3 32Q28 -4 15 3Q7 8 6 31Q3 49 21 35"] },
24472
+ m: { width: 40, strokes: ["M3 41L9 23L5 39Q18 11 20 25L17 39Q31 11 32 25L29 36Q28 46 43 35"] },
24473
+ n: { width: 28, strokes: ["M3 41L9 23L5 39Q21 10 23 25L20 36Q19 46 31 35"] },
24474
+ o: { width: 27, strokes: ["M22 22C7 14 0 39 12 42Q22 46 26 28Q26 18 19 24Q15 33 30 32"] },
24475
+ p: { width: 28, strokes: ["M-1 58L11 22L7 35Q19 12 25 25Q29 40 14 42L8 39L31 35"] },
24476
+ q: { width: 28, strokes: ["M23 24C10 12 1 39 12 42Q22 45 24 23L17 58Q15 62 19 53L31 36"] },
24477
+ r: { width: 23, strokes: ["M2 41L9 22Q8 31 16 24Q20 18 21 23Q21 27 17 28L26 35"] },
24478
+ s: { width: 24, strokes: ["M22 21Q18 15 10 24Q6 28 17 33Q25 39 14 43Q3 46 6 38L27 35"] },
24479
+ t: { width: 21, strokes: ["M16 10L7 35Q3 48 24 35", "M2 25L23 23"] },
24480
+ u: { width: 29, strokes: ["M9 23L4 35Q1 52 24 24L20 38Q21 45 32 35"] },
24481
+ v: { width: 26, strokes: ["M6 23Q-1 58 22 27Q25 20 21 23Q19 31 29 31"] },
24482
+ w: { width: 39, strokes: ["M7 23Q-1 56 19 27Q10 56 34 27Q37 20 33 23Q31 31 42 31"] },
24483
+ x: { width: 25, strokes: ["M7 24Q14 28 17 39Q20 45 28 35", "M24 23L3 42"] },
24484
+ y: { width: 28, strokes: ["M8 23L4 35Q2 50 24 24L16 54Q11 67 5 58Q0 50 31 36"] },
24485
+ z: { width: 25, strokes: ["M6 25Q16 19 24 24L5 41Q14 36 20 43Q25 51 10 59Q1 63 5 54L28 36"] },
24486
+ "0": { width: 29, strokes: ["M23 8C4 0 -2 42 13 43C28 44 34 7 23 8Z"] },
24487
+ "1": { width: 20, strokes: ["M5 17L17 8L9 42", "M2 43L18 43"] },
24488
+ "2": { width: 28, strokes: ["M4 17C10 -2 35 7 23 22L3 42Q14 38 28 42"] },
24489
+ "3": { width: 27, strokes: ["M6 11Q32 0 23 20L13 25Q34 17 24 36Q17 48 3 39"] },
24490
+ "4": { width: 29, strokes: ["M20 7L2 31L30 29", "M25 9L17 43"] },
24491
+ "5": { width: 28, strokes: ["M29 8L10 9L5 25Q27 14 25 32Q20 49 3 39"] },
24492
+ "6": { width: 28, strokes: ["M25 8C7 -1 -6 43 13 43C30 43 29 16 13 25L5 33"] },
24493
+ "7": { width: 27, strokes: ["M4 10L29 9L9 43", "M9 26L24 25"] },
24494
+ "8": { width: 28, strokes: ["M18 24C-6 12 23 -2 27 12Q28 21 10 28C-5 37 13 52 24 38Q33 27 18 24Z"] },
24495
+ "9": { width: 28, strokes: ["M24 20Q5 38 4 21C4 3 31 1 25 21L14 44"] },
24496
+ ".": { width: 12, strokes: ["M6 41L6.4 41.4"] },
24497
+ ",": { width: 12, strokes: ["M8 40L4 49"] },
24498
+ "!": { width: 13, strokes: ["M12 5L6 31", "M5 41L5.4 41.4"] },
24499
+ "?": { width: 25, strokes: ["M3 14Q10 0 23 10Q29 18 16 24L11 31", "M9 42L9.4 42.4"] },
24500
+ "-": { width: 23, strokes: ["M4 28L22 27"] },
24501
+ "'": { width: 11, strokes: ["M9 7L6 15"] }
24502
+ };
24503
+
24504
+ // src/components/handwriting-text/engine.ts
24505
+ var SVG12 = "http://www.w3.org/2000/svg";
24506
+ function createHandwritingText(root, options = {}) {
24507
+ if (!root) return inert({ setText() {
24508
+ }, replay() {
24509
+ }, text: "" });
24510
+ registerMotion();
24511
+ const scope = createScope();
24512
+ let text = options.text ?? root.textContent ?? "";
24513
+ const authored = [...root.childNodes];
24514
+ const svg2 = document.createElementNS(SVG12, "svg");
24515
+ svg2.setAttribute("aria-hidden", "true");
24516
+ svg2.dataset.mkHandwritingDrawing = "";
24517
+ root.replaceChildren(svg2);
24518
+ scope.add(() => {
24519
+ svg2.remove();
24520
+ root.append(...authored);
24521
+ });
24522
+ scope.attr(root, "data-mk-handwriting", "");
24523
+ scope.attr(root, "data-mk-ready", "");
24524
+ scope.attr(root, "role", "img");
24525
+ let strokes = [];
24526
+ let timeline = null;
24527
+ const duration = Number.isFinite(options.duration) ? Math.max(0.1, Math.min(30, options.duration)) : 2.4;
24528
+ const complete = () => {
24529
+ if (scope.disposed) return;
24530
+ options.onComplete?.();
24531
+ root.dispatchEvent(new CustomEvent("mk:complete", { bubbles: true }));
24532
+ };
24533
+ const replay = () => {
24534
+ if (scope.disposed) return;
24535
+ timeline?.kill();
24536
+ timeline = null;
24537
+ if (reduced() || !strokes.length) {
24538
+ gsap.set(strokes, { strokeDashoffset: 0 });
24539
+ return;
24540
+ }
24541
+ gsap.set(strokes, { strokeDashoffset: 1 });
24542
+ timeline = gsap.timeline({ onComplete: complete });
24543
+ const step = duration / strokes.length;
24544
+ for (const stroke of strokes) timeline.to(stroke, { strokeDashoffset: 0, duration: step, ease: EASE.wipe });
24545
+ };
24546
+ const draw = () => {
24547
+ timeline?.kill();
24548
+ timeline = null;
24549
+ strokes = [];
24550
+ svg2.replaceChildren();
24551
+ scope.attr(root, "aria-label", text);
24552
+ scope.attr(root, "data-mk-empty", text ? null : "");
24553
+ let x = 5;
24554
+ let y = 6;
24555
+ let width = 10;
24556
+ for (const char of text) {
24557
+ if (char === "\n") {
24558
+ width = Math.max(width, x + 5);
24559
+ x = 5;
24560
+ y += 64;
24561
+ continue;
24562
+ }
24563
+ if (/\s/u.test(char)) {
24564
+ x += 14;
24565
+ continue;
24566
+ }
24567
+ const normalized = char.normalize("NFD");
24568
+ const glyph = GLYPHS[normalized[0]];
24569
+ if (glyph) {
24570
+ const paths = [...glyph.strokes];
24571
+ if (normalized.includes("\u0301")) paths.push("M16 14L23 7");
24572
+ if (normalized.includes("\u0303")) paths.push("M11 14Q16 8 20 13Q24 17 28 10");
24573
+ if (normalized.includes("\u0308")) paths.push("M12 12L12.3 12.3M23 12L23.3 12.3");
24574
+ for (const d of paths) {
24575
+ const path = document.createElementNS(SVG12, "path");
24576
+ path.setAttribute("d", d);
24577
+ path.setAttribute("transform", `translate(${x} ${y})`);
24578
+ path.setAttribute("pathLength", "1");
24579
+ path.setAttribute("stroke-dasharray", "1");
24580
+ path.setAttribute("stroke-dashoffset", "0");
24581
+ svg2.append(path);
24582
+ strokes.push(path);
24583
+ }
24584
+ x += glyph.width;
24585
+ } else {
24586
+ const fallback = document.createElementNS(SVG12, "text");
24587
+ fallback.textContent = char;
24588
+ fallback.setAttribute("x", String(x));
24589
+ fallback.setAttribute("y", String(y + 42));
24590
+ fallback.setAttribute("data-mk-handwriting-fallback", "");
24591
+ svg2.append(fallback);
24592
+ x += 34;
24593
+ }
24594
+ }
24595
+ svg2.setAttribute("viewBox", `0 0 ${Math.max(width, x + 8)} ${y + 64}`);
24596
+ svg2.setAttribute("preserveAspectRatio", "xMinYMid meet");
24597
+ };
24598
+ draw();
24599
+ if (options.autoplay !== false) replay();
24600
+ scope.add(() => {
24601
+ timeline?.kill();
24602
+ gsap.killTweensOf(strokes);
24603
+ });
24604
+ return {
24605
+ replay,
24606
+ setText(next, animate = true) {
24607
+ if (scope.disposed || next === text) return;
24608
+ text = String(next);
24609
+ draw();
24610
+ if (animate) replay();
24611
+ },
24612
+ get text() {
24613
+ return text;
24614
+ },
24615
+ destroy: () => scope.dispose()
24616
+ };
24617
+ }
24618
+
24619
+ // src/components/particle-button/engine.ts
24620
+ function createParticleButton(root, options = {}) {
24621
+ if (!root) return inert({ burst() {
24622
+ } });
24623
+ registerMotion();
24624
+ const scope = createScope();
24625
+ let button2 = root.matches("button") ? root : root.querySelector("button");
24626
+ if (!button2) {
24627
+ button2 = document.createElement("button");
24628
+ root.append(button2);
24629
+ const made = button2;
24630
+ scope.add(() => made.remove());
24631
+ }
24632
+ const control = button2;
24633
+ if (!control.textContent?.trim() && !control.querySelector("[aria-label], svg, img")) {
24634
+ const name = document.createElement("span");
24635
+ name.textContent = options.label ?? "Celebrar";
24636
+ control.append(name);
24637
+ scope.add(() => name.remove());
24638
+ }
24639
+ const originalStyle = control.getAttribute("style");
24640
+ const originalTransform = control.style.transform;
24641
+ scope.add(() => {
24642
+ if (originalStyle === null) control.removeAttribute("style");
24643
+ else control.setAttribute("style", originalStyle);
24644
+ });
24645
+ scope.attr(control, "type", control.getAttribute("type") ?? "button");
24646
+ scope.attr(control, "data-mk-particle-button", "");
24647
+ scope.attr(root, "data-mk-ready", "");
24648
+ const count = Number.isFinite(options.count) ? Math.min(16, Math.max(3, Math.round(options.count))) : 9;
24649
+ const distance = Number.isFinite(options.distance) ? Math.min(100, Math.max(12, options.distance)) : 52;
24650
+ let particles = null;
24651
+ let pressing = null;
24652
+ const fire = () => {
24653
+ if (scope.disposed || control.disabled || control.getAttribute("aria-disabled") === "true") return;
24654
+ particles?.kill();
24655
+ particles = reduced() ? null : burst(control, { count, distance, ring: false, size: 5, colors: ["var(--mk-text)", "var(--mk-accent)"] });
24656
+ };
24657
+ scope.on(control, "click", (event) => {
24658
+ if (control.disabled || control.getAttribute("aria-disabled") === "true") {
24659
+ event.preventDefault();
24660
+ return;
24661
+ }
24662
+ pressing?.kill();
24663
+ pressing = press(control);
24664
+ pressing?.eventCallback("onComplete", () => {
24665
+ gsap.set(control, { clearProps: "transform,scale" });
24666
+ control.style.transform = originalTransform;
24667
+ if (!control.getAttribute("style")) control.removeAttribute("style");
24668
+ });
24669
+ fire();
24670
+ options.onAction?.();
24671
+ root.dispatchEvent(new CustomEvent("mk:action", { bubbles: true }));
24672
+ });
24673
+ scope.add(() => {
24674
+ particles?.kill();
24675
+ pressing?.kill();
24676
+ });
24677
+ return { burst: fire, destroy: () => scope.dispose() };
24678
+ }
24679
+
24680
+ // src/components/magnetize-button/engine.ts
24681
+ function createMagnetizeButton(root, options = {}) {
24682
+ if (!root) return inert({ attract() {
24683
+ }, release() {
24684
+ }, attracted: false });
24685
+ registerMotion();
24686
+ const scope = createScope();
24687
+ let button2 = root.matches("button") ? root : root.querySelector("button");
24688
+ if (!button2) {
24689
+ button2 = document.createElement("button");
24690
+ root.append(button2);
24691
+ const made = button2;
24692
+ scope.add(() => made.remove());
24693
+ }
24694
+ const control = button2;
24695
+ if (!control.textContent?.trim() && !control.querySelector("[aria-label], svg, img")) {
24696
+ const label = document.createElement("span");
24697
+ label.textContent = options.label ?? "Reunir ideas";
24698
+ control.append(label);
24699
+ scope.add(() => label.remove());
24700
+ }
24701
+ const originalStyle = control.getAttribute("style");
24702
+ const originalTransform = control.style.transform;
24703
+ scope.add(() => {
24704
+ if (originalStyle === null) control.removeAttribute("style");
24705
+ else control.setAttribute("style", originalStyle);
24706
+ });
24707
+ scope.attr(control, "type", control.getAttribute("type") ?? "button");
24708
+ scope.attr(control, "data-mk-magnetize-button", "");
24709
+ scope.attr(root, "data-mk-ready", "");
24710
+ const layer = document.createElement("span");
24711
+ layer.dataset.mkMagnetParticles = "";
24712
+ layer.setAttribute("aria-hidden", "true");
24713
+ control.append(layer);
24714
+ scope.add(() => layer.remove());
24715
+ const count = Number.isFinite(options.count) ? Math.min(24, Math.max(4, Math.round(options.count))) : 14;
24716
+ const reach = Number.isFinite(options.reach) ? Math.min(90, Math.max(16, options.reach)) : 42;
24717
+ const dots = [];
24718
+ for (let i = 0; i < count; i++) {
24719
+ const dot = document.createElement("i");
24720
+ layer.append(dot);
24721
+ dots.push(dot);
24722
+ }
24723
+ let hovered = false;
24724
+ let focused = false;
24725
+ let attracted = false;
24726
+ let tween = null;
24727
+ let pressing = null;
24728
+ const disabled = () => control.disabled || control.getAttribute("aria-disabled") === "true";
24729
+ const positions = (near) => {
24730
+ const w = control.offsetWidth || 160;
24731
+ const h = control.offsetHeight || 48;
24732
+ return dots.map((_, i) => {
24733
+ const angle2 = i / count * Math.PI * 2 - Math.PI / 2;
24734
+ const c = Math.cos(angle2);
24735
+ const s = Math.sin(angle2);
24736
+ const boundary = Math.min((w / 2 + 4) / Math.max(1e-3, Math.abs(c)), (h / 2 + 4) / Math.max(1e-3, Math.abs(s)));
24737
+ const radius = boundary + (near ? 0 : reach * (0.72 + i % 3 * 0.14));
24738
+ return { x: c * radius, y: s * radius, opacity: near ? 0.88 : 0.25, scale: near ? 1 : 0.6 };
24739
+ });
24740
+ };
24741
+ const paint = (near, animate) => {
24742
+ tween?.kill();
24743
+ tween = null;
24744
+ layer.hidden = reduced() || disabled();
24745
+ if (layer.hidden) {
24746
+ attracted = false;
24747
+ scope.attr(control, "data-mk-attracted", null);
24748
+ return;
24749
+ }
24750
+ attracted = near;
24751
+ scope.attr(control, "data-mk-attracted", near ? "" : null);
24752
+ const targets = positions(near);
24753
+ if (!animate) {
24754
+ dots.forEach((dot, i) => gsap.set(dot, targets[i]));
24755
+ return;
24756
+ }
24757
+ tween = gsap.timeline();
24758
+ dots.forEach((dot, i) => tween.to(dot, { ...targets[i], duration: near ? 0.62 : 0.48, ease: near ? EASE.swatch : EASE.signature }, i * 8e-3));
24759
+ };
24760
+ const sync = () => paint(hovered || focused, true);
24761
+ scope.on(control, "pointerenter", () => {
24762
+ hovered = true;
24763
+ sync();
24764
+ });
24765
+ scope.on(control, "pointerleave", () => {
24766
+ hovered = false;
24767
+ sync();
24768
+ });
24769
+ scope.on(control, "focus", () => {
24770
+ focused = true;
24771
+ sync();
24772
+ });
24773
+ scope.on(control, "blur", () => {
24774
+ focused = false;
24775
+ sync();
24776
+ });
24777
+ scope.on(control, "click", (event) => {
24778
+ if (disabled()) {
24779
+ event.preventDefault();
24780
+ return;
24781
+ }
24782
+ pressing?.kill();
24783
+ pressing = press(control);
24784
+ pressing?.eventCallback("onComplete", () => {
24785
+ gsap.set(control, { clearProps: "transform,scale" });
24786
+ control.style.transform = originalTransform;
24787
+ if (!control.getAttribute("style")) control.removeAttribute("style");
24788
+ });
24789
+ options.onAction?.();
24790
+ root.dispatchEvent(new CustomEvent("mk:action", { bubbles: true }));
24791
+ });
24792
+ if (typeof ResizeObserver !== "undefined") scope.observe(new ResizeObserver(() => paint(attracted, false))).observe(control);
24793
+ if (typeof MutationObserver !== "undefined") scope.observe(new MutationObserver(() => paint(hovered || focused, false))).observe(control, { attributes: true, attributeFilter: ["disabled", "aria-disabled"] });
24794
+ if (typeof matchMedia === "function") {
24795
+ const media = matchMedia("(prefers-reduced-motion: reduce)");
24796
+ scope.on(media, "change", () => paint(hovered || focused, false));
24797
+ }
24798
+ paint(false, false);
24799
+ scope.add(() => {
24800
+ tween?.kill();
24801
+ pressing?.kill();
24802
+ gsap.killTweensOf(dots);
24803
+ });
24804
+ return { attract: () => {
24805
+ if (!scope.disposed) paint(true, true);
24806
+ }, release: () => {
24807
+ if (!scope.disposed) paint(false, true);
24808
+ }, get attracted() {
24809
+ return attracted;
24810
+ }, destroy: () => scope.dispose() };
24811
+ }
24812
+
24813
+ // src/components/badge-button/engine.ts
24814
+ var normalize2 = (value) => Number.isFinite(value) ? Math.max(0, Math.min(Number.MAX_SAFE_INTEGER, Math.round(value))) : 0;
24815
+ var sequence29 = 0;
24816
+ function createBadgeButton(root, options = {}) {
24817
+ if (!root) return inert({ setCount() {
24818
+ }, count: 0 });
24819
+ registerMotion();
24820
+ const scope = createScope();
24821
+ let button2 = root.matches("button") ? root : root.querySelector("button");
24822
+ if (!button2) {
24823
+ button2 = document.createElement("button");
24824
+ root.append(button2);
24825
+ const made = button2;
24826
+ scope.add(() => made.remove());
24827
+ }
24828
+ const control = button2;
24829
+ if (!control.textContent?.trim() && !control.querySelector("[aria-label], svg, img")) {
24830
+ const label = document.createElement("span");
24831
+ label.textContent = options.label ?? "Guardar";
24832
+ control.append(label);
24833
+ scope.add(() => label.remove());
24834
+ }
24835
+ const originalStyle = control.getAttribute("style");
24836
+ const originalTransform = control.style.transform;
24837
+ scope.add(() => {
24838
+ if (originalStyle === null) control.removeAttribute("style");
24839
+ else control.setAttribute("style", originalStyle);
24840
+ });
24841
+ const badge = document.createElement("span");
24842
+ badge.dataset.mkBadgeCount = "";
24843
+ badge.setAttribute("aria-hidden", "true");
24844
+ control.append(badge);
24845
+ scope.add(() => badge.remove());
24846
+ const spoken = document.createElement("span");
24847
+ spoken.className = "mk-sr-only";
24848
+ control.append(spoken);
24849
+ scope.add(() => spoken.remove());
24850
+ const authoredLabel = control.getAttribute("aria-label");
24851
+ const labelledBy = control.getAttribute("aria-labelledby");
24852
+ if (labelledBy?.trim()) {
24853
+ spoken.id = `mk-badge-quantity-${++sequence29}`;
24854
+ scope.attr(control, "aria-labelledby", `${labelledBy} ${spoken.id}`);
24855
+ }
24856
+ scope.attr(control, "type", control.getAttribute("type") ?? "button");
24857
+ scope.attr(control, "data-mk-badge-button", "");
24858
+ scope.attr(root, "data-mk-ready", "");
24859
+ let count = normalize2(options.count ?? 0);
24860
+ const max = Math.max(1, normalize2(options.max ?? 99));
24861
+ const step = Number.isFinite(options.step) ? Math.round(options.step) : 1;
24862
+ let rolling2 = null;
24863
+ let bump = null;
24864
+ let pressing = null;
24865
+ const format = () => count > max ? `${max}+` : String(count);
24866
+ const announce = () => {
24867
+ spoken.textContent = ` (${count})`;
24868
+ if (!labelledBy?.trim() && authoredLabel?.trim()) scope.attr(control, "aria-label", `${authoredLabel} (${count})`);
24869
+ };
24870
+ const paint = () => {
24871
+ badge.hidden = options.hideZero !== false && count === 0;
24872
+ badge.textContent = format();
24873
+ announce();
24874
+ };
24875
+ const setCount = (next, notify = false) => {
24876
+ if (scope.disposed || !Number.isFinite(next)) return;
24877
+ const previous = count;
24878
+ count = normalize2(next);
24879
+ if (count === previous) return;
24880
+ const wasHidden = badge.hidden;
24881
+ badge.hidden = options.hideZero !== false && count === 0;
24882
+ announce();
24883
+ rolling2?.kill();
24884
+ bump?.kill();
24885
+ if (reduced() || badge.hidden) paint();
24886
+ else {
24887
+ rolling2 = rollDigits(badge, format(), count >= previous ? 1 : -1, 0.34);
24888
+ bump = gsap.fromTo(badge, { scale: wasHidden ? 0.35 : 0.8, y: wasHidden ? 7 : 0 }, { scale: 1, y: 0, duration: 0.5, ease: wasHidden ? EASE.pop : EASE.swatch });
24889
+ }
24890
+ if (notify) {
24891
+ options.onChange?.(count);
24892
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { count } }));
24893
+ }
24894
+ };
24895
+ scope.on(control, "click", (event) => {
24896
+ if (control.disabled || control.getAttribute("aria-disabled") === "true") {
24897
+ event.preventDefault();
24898
+ return;
24899
+ }
24900
+ pressing?.kill();
24901
+ pressing = press(control);
24902
+ pressing?.eventCallback("onComplete", () => {
24903
+ gsap.set(control, { clearProps: "transform,scale" });
24904
+ control.style.transform = originalTransform;
24905
+ if (!control.getAttribute("style")) control.removeAttribute("style");
24906
+ });
24907
+ setCount(count + step, true);
24908
+ });
24909
+ paint();
24910
+ scope.add(() => {
24911
+ rolling2?.kill();
24912
+ bump?.kill();
24913
+ pressing?.kill();
24914
+ gsap.killTweensOf(badge);
24915
+ });
24916
+ return { setCount, get count() {
24917
+ return count;
24918
+ }, destroy: () => scope.dispose() };
24919
+ }
24920
+
24921
+ // src/components/morphing-page-dots/engine.ts
24922
+ function createMorphingPageDots(root, options = {}) {
24923
+ if (!root) return inert({ setValue() {
24924
+ }, value: 0 });
24925
+ registerMotion();
24926
+ const scope = createScope();
24927
+ const count = Number.isFinite(options.count) ? Math.min(20, Math.max(1, Math.round(options.count))) : 5;
24928
+ const normalize3 = (index) => Math.min(count - 1, Math.max(0, Math.round(index)));
24929
+ let value = normalize3(Number.isFinite(options.value) ? options.value : 0);
24930
+ const authored = [...root.childNodes];
24931
+ const rail = document.createElement("span");
24932
+ rail.dataset.mkPageRail = "";
24933
+ const blob = document.createElement("i");
24934
+ blob.dataset.mkPageBlob = "";
24935
+ blob.setAttribute("aria-hidden", "true");
24936
+ rail.append(blob);
24937
+ const buttons = [];
24938
+ for (let i = 0; i < count; i++) {
24939
+ const button2 = document.createElement("button");
24940
+ button2.type = "button";
24941
+ button2.dataset.mkPageDot = "";
24942
+ button2.setAttribute("aria-label", options.labels?.[i] ?? `P\xE1gina ${i + 1} de ${count}`);
24943
+ if (options.pageIds?.[i]) button2.setAttribute("aria-controls", options.pageIds[i]);
24944
+ button2.disabled = Boolean(options.disabled);
24945
+ const dot = document.createElement("i");
24946
+ dot.setAttribute("aria-hidden", "true");
24947
+ button2.append(dot);
24948
+ rail.append(button2);
24949
+ buttons.push(button2);
24950
+ }
24951
+ root.replaceChildren(rail);
24952
+ scope.add(() => {
24953
+ rail.remove();
24954
+ root.append(...authored);
24955
+ });
24956
+ scope.attr(root, "role", "group");
24957
+ scope.attr(root, "aria-label", options.label ?? "P\xE1ginas");
24958
+ scope.attr(root, "data-mk-morphing-page-dots", "");
24959
+ scope.attr(root, "data-mk-ready", "");
24960
+ let moving = null;
24961
+ let pressing = null;
24962
+ const at = (index) => {
24963
+ const button2 = buttons[index];
24964
+ const size = button2.offsetWidth || 44;
24965
+ return (button2.offsetLeft || index * size) + size / 2 - 12;
24966
+ };
24967
+ const place3 = () => {
24968
+ moving?.kill();
24969
+ moving = null;
24970
+ gsap.set(blob, { left: at(value), width: 24, scaleY: 1 });
24971
+ };
24972
+ const paint = () => buttons.forEach((button2, i) => {
24973
+ button2.setAttribute("aria-current", i === value ? "page" : "false");
24974
+ button2.tabIndex = i === value ? 0 : -1;
24975
+ });
24976
+ const setValue = (index, notify = false) => {
24977
+ if (scope.disposed || !Number.isFinite(index)) return;
24978
+ const next = normalize3(index);
24979
+ if (value === next) return;
24980
+ const start = at(value);
24981
+ const end = at(next);
24982
+ value = next;
24983
+ paint();
24984
+ moving?.kill();
24985
+ if (reduced()) place3();
24986
+ else {
24987
+ const current3 = Number(gsap.getProperty(blob, "left")) || start;
24988
+ moving = gsap.timeline().to(blob, { left: Math.min(current3, end), width: Math.abs(end - current3) + 24, scaleY: 0.68, duration: 0.18, ease: EASE.wipe }).to(blob, { left: end, width: 24, scaleY: 1, duration: 0.48, ease: EASE.swatch }, 0.13);
24989
+ }
24990
+ if (notify) {
24991
+ options.onChange?.(value);
24992
+ root.dispatchEvent(new CustomEvent("mk:change", { bubbles: true, detail: { value } }));
24993
+ }
24994
+ };
24995
+ buttons.forEach((button2, i) => {
24996
+ scope.on(button2, "click", () => {
24997
+ if (button2.disabled) return;
24998
+ pressing?.kill();
24999
+ pressing = press(button2);
25000
+ setValue(i, true);
25001
+ });
25002
+ scope.on(button2, "keydown", (event) => {
25003
+ if (button2.disabled) return;
25004
+ const key2 = event.key;
25005
+ if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(key2)) return;
25006
+ event.preventDefault();
25007
+ const rtl = getComputedStyle(root).direction === "rtl";
25008
+ let next = key2 === "Home" ? 0 : key2 === "End" ? count - 1 : (value + (key2 === "ArrowRight" !== rtl ? 1 : -1) + count) % count;
25009
+ setValue(next, true);
25010
+ buttons[next].focus();
25011
+ });
25012
+ });
25013
+ if (typeof ResizeObserver !== "undefined") scope.observe(new ResizeObserver(place3)).observe(rail);
25014
+ paint();
25015
+ place3();
25016
+ scope.add(() => {
25017
+ moving?.kill();
25018
+ pressing?.kill();
25019
+ });
25020
+ return { setValue, get value() {
25021
+ return value;
25022
+ }, destroy: () => scope.dispose() };
25023
+ }
25024
+
25025
+ // src/components/not-found/engine.ts
25026
+ var ILLUSTRATION = '<svg viewBox="0 0 320 140" fill="none" aria-hidden="true"><path data-mk-lost-track d="M20 115H100Q118 115 118 95V72Q118 53 138 53H185Q205 53 205 73V95Q205 115 224 115H300"/><g data-mk-lost-four><path d="M72 23L35 79H84M77 23V107"/><path d="M263 23L226 79H275M268 23V107"/></g><g data-mk-lost-portal><rect x="124" y="18" width="72" height="96" rx="32"/><ellipse cx="160" cy="66" rx="17" ry="29"/><path d="M145 66h30M160 51v30"/></g><path data-mk-lost-star d="M211 13v12m-6-6h12M105 118v8m-4-4h8"/></svg>';
25027
+ function createNotFound(root, options = {}) {
25028
+ if (!root) return inert({ replay() {
25029
+ } });
25030
+ registerMotion();
25031
+ const scope = createScope();
25032
+ const authored = [...root.childNodes];
25033
+ const content = document.createElement("div");
25034
+ content.dataset.mkNotFoundContent = "";
25035
+ const art = document.createElement("div");
25036
+ art.dataset.mkNotFoundArt = "";
25037
+ art.innerHTML = ILLUSTRATION;
25038
+ const eyebrow = document.createElement("p");
25039
+ eyebrow.dataset.mkNotFoundCode = "";
25040
+ eyebrow.textContent = `404 \xB7 ${options.brand ?? "Motion Kit"}`;
25041
+ const heading = document.createElement("h2");
25042
+ heading.textContent = options.title ?? "Este camino se perdi\xF3.";
25043
+ const description = document.createElement("p");
25044
+ description.dataset.mkNotFoundDescription = "";
25045
+ description.textContent = options.description ?? "La p\xE1gina que buscas no est\xE1 aqu\xED. Volvamos a un lugar conocido.";
25046
+ const actions = document.createElement("div");
25047
+ actions.dataset.mkNotFoundActions = "";
25048
+ const home = document.createElement("a");
25049
+ home.href = options.homeHref ?? "/";
25050
+ home.textContent = options.homeLabel ?? "Volver al inicio";
25051
+ actions.append(home);
25052
+ const back = document.createElement("button");
25053
+ back.type = "button";
25054
+ back.textContent = options.backLabel ?? "Ir atr\xE1s";
25055
+ back.disabled = !options.onBack && history.length <= 1;
25056
+ if (options.showBack !== false) actions.append(back);
25057
+ content.append(art, eyebrow, heading, description, actions);
25058
+ root.replaceChildren(content);
25059
+ scope.add(() => {
25060
+ content.remove();
25061
+ root.append(...authored);
25062
+ });
25063
+ scope.attr(root, "data-mk-not-found", "");
25064
+ scope.attr(root, "data-mk-ready", "");
25065
+ let entering = null;
25066
+ let drawing = null;
25067
+ let pressing = null;
25068
+ const portal = art.querySelector("[data-mk-lost-portal]");
25069
+ const replay = () => {
25070
+ if (scope.disposed) return;
25071
+ entering?.kill();
25072
+ drawing?.kill();
25073
+ if (reduced()) {
25074
+ gsap.set([art, eyebrow, heading, description, actions], { clearProps: "all" });
25075
+ return;
25076
+ }
25077
+ entering = blurIn([art, eyebrow, heading, description, actions], { from: "soft", duration: 0.5, stagger: 0.055 });
25078
+ drawing = gsap.fromTo(portal, { rotation: -12, scale: 0.82, transformOrigin: "50% 50%" }, { rotation: 0, scale: 1, duration: 0.8, ease: EASE.swatch });
25079
+ };
25080
+ scope.on(back, "click", () => {
25081
+ if (!back.disabled) {
25082
+ pressing?.kill();
25083
+ pressing = press(back);
25084
+ if (options.onBack) options.onBack();
25085
+ else history.back();
25086
+ }
25087
+ });
25088
+ scope.on(home, "click", () => {
25089
+ pressing?.kill();
25090
+ pressing = press(home);
25091
+ });
25092
+ replay();
25093
+ scope.add(() => {
25094
+ entering?.kill();
25095
+ drawing?.kill();
25096
+ pressing?.kill();
25097
+ });
25098
+ return { replay, destroy: () => scope.dispose() };
25099
+ }
25100
+
21223
25101
  export {
21224
25102
  PATHS,
21225
25103
  springPath,
@@ -21440,6 +25318,26 @@ export {
21440
25318
  sanitizeHtml,
21441
25319
  createRichTextEditor,
21442
25320
  createAddToCart,
21443
- createScrollIsland
25321
+ createScrollIsland,
25322
+ createSignaturePad,
25323
+ createWaveformPlayer,
25324
+ createVoiceMessageBubble,
25325
+ createDrilldownMenu,
25326
+ createWheelPicker,
25327
+ createStepper,
25328
+ createRadioGroup,
25329
+ createEqualizerSlider,
25330
+ createTemperatureSlider,
25331
+ createRatingScale,
25332
+ createNotificationStack,
25333
+ createBentoGrid,
25334
+ createScrollPreviewDock,
25335
+ createStickyHeader,
25336
+ createHandwritingText,
25337
+ createParticleButton,
25338
+ createMagnetizeButton,
25339
+ createBadgeButton,
25340
+ createMorphingPageDots,
25341
+ createNotFound
21444
25342
  };
21445
- //# sourceMappingURL=chunk-SDQ776LG.js.map
25343
+ //# sourceMappingURL=chunk-Q7IW4FV3.js.map