directix 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * directix v1.3.0
2
+ * directix v1.4.0
3
3
  * A comprehensive, easy-to-use, and high-performance Vue custom directives library supporting both Vue 2 and Vue 3
4
4
  * (c) 2021-present saqqdy <https://github.com/saqqdy>
5
5
  * Released under the MIT License.
@@ -58,12 +58,13 @@ var __async = (__this, __arguments, generator) => {
58
58
  });
59
59
  };
60
60
  /*!
61
- * directix v1.3.0
61
+ * directix v1.4.0
62
62
  * A comprehensive, easy-to-use, and high-performance Vue custom directives library supporting both Vue 2 and Vue 3
63
63
  * (c) 2021-present saqqdy <https://github.com/saqqdy>
64
64
  * Released under the MIT License.
65
65
  */
66
66
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
67
+ const vue = require("vue");
67
68
  function createVue2Directive(hooks) {
68
69
  const directive = {
69
70
  bind(el, binding, vnode) {
@@ -218,8 +219,8 @@ function getVueVersion() {
218
219
  }
219
220
  }
220
221
  try {
221
- const vue = require("vue");
222
- const version = parseVersion(vue == null ? void 0 : vue.version);
222
+ const vue2 = require("vue");
223
+ const version = parseVersion(vue2 == null ? void 0 : vue2.version);
223
224
  if (version !== null) {
224
225
  _vueVersion = version;
225
226
  return _vueVersion;
@@ -228,19 +229,19 @@ function getVueVersion() {
228
229
  }
229
230
  if (typeof window !== "undefined") {
230
231
  const win = window;
231
- const vue = win.Vue;
232
- if (vue == null ? void 0 : vue.version) {
233
- const version = parseVersion(vue.version);
232
+ const vue2 = win.Vue;
233
+ if (vue2 == null ? void 0 : vue2.version) {
234
+ const version = parseVersion(vue2.version);
234
235
  if (version !== null) {
235
236
  _vueVersion = version;
236
237
  return _vueVersion;
237
238
  }
238
239
  }
239
- if (typeof (vue == null ? void 0 : vue.observable) === "function") {
240
+ if (typeof (vue2 == null ? void 0 : vue2.observable) === "function") {
240
241
  _vueVersion = 2;
241
242
  return _vueVersion;
242
243
  }
243
- if (typeof (vue == null ? void 0 : vue.createApp) === "function" && typeof (vue == null ? void 0 : vue.observable) !== "function") {
244
+ if (typeof (vue2 == null ? void 0 : vue2.createApp) === "function" && typeof (vue2 == null ? void 0 : vue2.observable) !== "function") {
244
245
  _vueVersion = 3;
245
246
  return _vueVersion;
246
247
  }
@@ -442,7 +443,7 @@ function transformTextContent(el, transformFn) {
442
443
  function isInputElement(el) {
443
444
  return el.tagName === "INPUT" || el.tagName === "TEXTAREA";
444
445
  }
445
- const DEFAULT_KEEP_LOWER = [
446
+ const DEFAULT_KEEP_LOWER$1 = [
446
447
  "a",
447
448
  "an",
448
449
  "the",
@@ -461,25 +462,25 @@ const DEFAULT_KEEP_LOWER = [
461
462
  "with",
462
463
  "as"
463
464
  ];
464
- function capitalizeText(text, options) {
465
+ function capitalizeText$1(text, options) {
465
466
  if (!text) return text;
466
- const { every = true, keepLower = DEFAULT_KEEP_LOWER } = options;
467
+ const { every = true, keepLower = DEFAULT_KEEP_LOWER$1 } = options;
467
468
  if (every) {
468
469
  const words = text.toLowerCase().split(/\s+/);
469
470
  return words.map((word, index) => {
470
471
  if (index === 0) {
471
- return capitalizeWord(word);
472
+ return capitalizeWord$1(word);
472
473
  }
473
474
  if (keepLower.includes(word.toLowerCase())) {
474
475
  return word.toLowerCase();
475
476
  }
476
- return capitalizeWord(word);
477
+ return capitalizeWord$1(word);
477
478
  }).join(" ");
478
479
  } else {
479
- return capitalizeWord(text);
480
+ return capitalizeWord$1(text);
480
481
  }
481
482
  }
482
- function capitalizeWord(word) {
483
+ function capitalizeWord$1(word) {
483
484
  if (!word) return word;
484
485
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
485
486
  }
@@ -493,7 +494,7 @@ function normalizeOptions$B(binding) {
493
494
  }
494
495
  return {
495
496
  every: (_a = binding.every) != null ? _a : true,
496
- keepLower: (_b = binding.keepLower) != null ? _b : DEFAULT_KEEP_LOWER,
497
+ keepLower: (_b = binding.keepLower) != null ? _b : DEFAULT_KEEP_LOWER$1,
497
498
  onInput: (_c = binding.onInput) != null ? _c : true
498
499
  };
499
500
  }
@@ -503,20 +504,20 @@ const vCapitalcase = defineDirective({
503
504
  mounted(el, binding) {
504
505
  const options = normalizeOptions$B(binding.value);
505
506
  if (isInputElement(el)) {
506
- const cleanup2 = setupTextTransformInput(el, options, (text) => capitalizeText(text, options));
507
+ const cleanup2 = setupTextTransformInput(el, options, (text) => capitalizeText$1(text, options));
507
508
  el.__capitalcaseCleanup = cleanup2;
508
509
  } else {
509
- transformTextContent(el, (text) => capitalizeText(text, options));
510
+ transformTextContent(el, (text) => capitalizeText$1(text, options));
510
511
  }
511
512
  },
512
513
  updated(el, binding) {
513
514
  const options = normalizeOptions$B(binding.value);
514
515
  if (isInputElement(el)) {
515
516
  if (options.onInput) {
516
- el.value = capitalizeText(el.value, options);
517
+ el.value = capitalizeText$1(el.value, options);
517
518
  }
518
519
  } else {
519
- transformTextContent(el, (text) => capitalizeText(text, options));
520
+ transformTextContent(el, (text) => capitalizeText$1(text, options));
520
521
  }
521
522
  },
522
523
  unmounted(el) {
@@ -525,133 +526,15 @@ const vCapitalcase = defineDirective({
525
526
  delete el.__capitalcaseCleanup;
526
527
  }
527
528
  });
528
- const vClickDelay = defineDirective({
529
- name: "click-delay",
530
- ssr: true,
531
- defaults: {
532
- delay: 300,
533
- disabled: false,
534
- pendingClass: "v-click-delay--pending",
535
- feedback: true
536
- },
537
- mounted(el, binding) {
538
- const options = normalizeOptions$A(binding.value, binding);
539
- if (options.disabled) return;
540
- const state = {
541
- options,
542
- handler: createClickHandler(el, options),
543
- isPending: false,
544
- timeoutId: null
545
- };
546
- el.__clickDelay = state;
547
- el.addEventListener("click", state.handler);
548
- el.addEventListener("touchend", state.handler);
549
- },
550
- updated(el, binding) {
551
- const state = el.__clickDelay;
552
- if (!state) {
553
- const options = normalizeOptions$A(binding.value, binding);
554
- if (!options.disabled) {
555
- const newState = {
556
- options,
557
- handler: createClickHandler(el, options),
558
- isPending: false,
559
- timeoutId: null
560
- };
561
- el.__clickDelay = newState;
562
- el.addEventListener("click", newState.handler);
563
- el.addEventListener("touchend", newState.handler);
564
- }
565
- return;
566
- }
567
- const newOptions = normalizeOptions$A(binding.value, binding);
568
- if (newOptions.disabled && !state.options.disabled) {
569
- el.removeEventListener("click", state.handler);
570
- el.removeEventListener("touchend", state.handler);
571
- if (state.timeoutId) {
572
- clearTimeout(state.timeoutId);
573
- }
574
- removePendingClass(el, state.options);
575
- delete el.__clickDelay;
576
- } else if (!newOptions.disabled && state.options.disabled) {
577
- state.handler = createClickHandler(el, newOptions);
578
- state.isPending = false;
579
- state.timeoutId = null;
580
- el.addEventListener("click", state.handler);
581
- el.addEventListener("touchend", state.handler);
582
- }
583
- state.options = newOptions;
584
- },
585
- unmounted(el) {
586
- const state = el.__clickDelay;
587
- if (!state) return;
588
- el.removeEventListener("click", state.handler);
589
- el.removeEventListener("touchend", state.handler);
590
- if (state.timeoutId) {
591
- clearTimeout(state.timeoutId);
592
- }
593
- removePendingClass(el, state.options);
594
- delete el.__clickDelay;
595
- }
596
- });
597
- function createClickHandler(el, options) {
598
- return (event) => {
599
- const state = el.__clickDelay;
600
- if (!state || state.isPending) {
601
- event.preventDefault();
602
- event.stopPropagation();
603
- return;
604
- }
605
- state.isPending = true;
606
- if (options.feedback && options.pendingClass) {
607
- el.classList.add(options.pendingClass);
608
- }
609
- options.handler(event);
610
- state.timeoutId = setTimeout(() => {
611
- state.isPending = false;
612
- state.timeoutId = null;
613
- removePendingClass(el, options);
614
- }, options.delay);
615
- };
616
- }
617
- function removePendingClass(el, options) {
618
- if (options.feedback && options.pendingClass) {
619
- el.classList.remove(options.pendingClass);
620
- }
529
+ const STATE_PREFIX = "__directix_";
530
+ function setState$1(el, key, state) {
531
+ el[STATE_PREFIX + key] = state;
621
532
  }
622
- function parseTime$1(arg) {
623
- if (!arg) return null;
624
- if (arg.endsWith("ms")) {
625
- return parseInt(arg, 10);
626
- }
627
- if (arg.endsWith("s")) {
628
- return parseFloat(arg) * 1e3;
629
- }
630
- const num = parseInt(arg, 10);
631
- return Number.isNaN(num) ? null : num;
533
+ function getState$1(el, key) {
534
+ return el[STATE_PREFIX + key];
632
535
  }
633
- function normalizeOptions$A(binding, directiveBinding) {
634
- var _a, _b, _c, _d;
635
- const delay = parseTime$1(directiveBinding.arg) || 300;
636
- if (typeof binding === "function") {
637
- return {
638
- handler: binding,
639
- delay,
640
- disabled: false,
641
- pendingClass: "v-click-delay--pending",
642
- feedback: true
643
- };
644
- }
645
- if (!binding) {
646
- throw new Error("[Directix] v-click-delay: handler is required");
647
- }
648
- return {
649
- handler: binding.handler,
650
- delay: (_a = binding.delay) != null ? _a : delay,
651
- disabled: (_b = binding.disabled) != null ? _b : false,
652
- pendingClass: (_c = binding.pendingClass) != null ? _c : "v-click-delay--pending",
653
- feedback: (_d = binding.feedback) != null ? _d : true
654
- };
536
+ function deleteState(el, key) {
537
+ delete el[STATE_PREFIX + key];
655
538
  }
656
539
  function isElement(value) {
657
540
  return value instanceof Element;
@@ -678,15 +561,15 @@ function getScrollParent(el) {
678
561
  }
679
562
  function on(target, event, handler, options = false) {
680
563
  if (!isBrowser()) return;
681
- const opts = normalizeOptions$z(options);
564
+ const opts = normalizeOptions$A(options);
682
565
  target.addEventListener(event, handler, opts);
683
566
  }
684
567
  function off(target, event, handler, options = false) {
685
568
  if (!isBrowser()) return;
686
- const opts = normalizeOptions$z(options);
569
+ const opts = normalizeOptions$A(options);
687
570
  target.removeEventListener(event, handler, opts);
688
571
  }
689
- function normalizeOptions$z(options) {
572
+ function normalizeOptions$A(options) {
690
573
  if (typeof options === "boolean") {
691
574
  return options;
692
575
  }
@@ -696,7 +579,7 @@ function normalizeOptions$z(options) {
696
579
  }
697
580
  return capture;
698
581
  }
699
- function getEventPosition(e) {
582
+ function getEventPosition$1(e) {
700
583
  let clientX = 0, clientY = 0;
701
584
  if ("touches" in e && e.touches.length > 0) {
702
585
  clientX = e.touches[0].clientX;
@@ -712,6 +595,58 @@ function getEventPosition(e) {
712
595
  clientY
713
596
  };
714
597
  }
598
+ function bindEvents$2(target, events, options = false) {
599
+ Object.entries(events).forEach(([event, handler]) => {
600
+ target.addEventListener(event, handler, typeof options === "boolean" ? options : normalizeOptionsObject(options));
601
+ });
602
+ return () => {
603
+ Object.entries(events).forEach(([event, handler]) => {
604
+ target.removeEventListener(event, handler, typeof options === "boolean" ? options : normalizeOptionsObject(options));
605
+ });
606
+ };
607
+ }
608
+ function normalizeOptionsObject(options) {
609
+ const { capture = false, passive = false, once = false } = options;
610
+ if (supportsPassive()) {
611
+ return { capture, passive, once };
612
+ }
613
+ return capture;
614
+ }
615
+ const EVENT_MODIFIERS = [
616
+ "click",
617
+ "input",
618
+ "change",
619
+ "submit",
620
+ "scroll",
621
+ "resize",
622
+ "mouseenter",
623
+ "mouseleave",
624
+ "mousemove",
625
+ "mousedown",
626
+ "mouseup",
627
+ "keydown",
628
+ "keyup",
629
+ "focus",
630
+ "blur",
631
+ "touchstart",
632
+ "touchmove",
633
+ "touchend"
634
+ ];
635
+ function getEventTypeFromModifiers(modifiers) {
636
+ for (const modifier of EVENT_MODIFIERS) {
637
+ if (modifiers[modifier]) {
638
+ return modifier;
639
+ }
640
+ }
641
+ return null;
642
+ }
643
+ function getDefaultEventType(el) {
644
+ const tagName = el.tagName.toLowerCase();
645
+ if (tagName === "input" || tagName === "textarea") {
646
+ return "input";
647
+ }
648
+ return "click";
649
+ }
715
650
  function isString(value) {
716
651
  return typeof value === "string";
717
652
  }
@@ -898,53 +833,171 @@ function parseTime(arg) {
898
833
  function generateId(prefix = "") {
899
834
  return `${prefix}${Date.now().toString(36)}${Math.random().toString(36).slice(2, 9)}`;
900
835
  }
901
- const vClickOutside = defineDirective({
902
- name: "click-outside",
903
- ssr: false,
836
+ const STATE_KEY$5 = "clickDelay";
837
+ function removePendingClass(el, options) {
838
+ if (options.feedback && options.pendingClass) {
839
+ el.classList.remove(options.pendingClass);
840
+ }
841
+ }
842
+ function createClickHandler(el, options) {
843
+ return (event) => {
844
+ const state = getState$1(el, STATE_KEY$5);
845
+ if (!state || state.isPending) {
846
+ event.preventDefault();
847
+ event.stopPropagation();
848
+ return;
849
+ }
850
+ state.isPending = true;
851
+ if (options.feedback && options.pendingClass) {
852
+ el.classList.add(options.pendingClass);
853
+ }
854
+ options.handler(event);
855
+ state.timeoutId = setTimeout(() => {
856
+ state.isPending = false;
857
+ state.timeoutId = null;
858
+ removePendingClass(el, options);
859
+ }, options.delay);
860
+ };
861
+ }
862
+ function normalizeOptions$z(binding, directiveBinding) {
863
+ var _a, _b, _c, _d;
864
+ const delay = parseTime(directiveBinding.arg) || 300;
865
+ if (typeof binding === "function") {
866
+ return {
867
+ handler: binding,
868
+ delay,
869
+ disabled: false,
870
+ pendingClass: "v-click-delay--pending",
871
+ feedback: true
872
+ };
873
+ }
874
+ if (!binding) {
875
+ throw new Error("[Directix] v-click-delay: handler is required");
876
+ }
877
+ return {
878
+ handler: binding.handler,
879
+ delay: (_a = binding.delay) != null ? _a : delay,
880
+ disabled: (_b = binding.disabled) != null ? _b : false,
881
+ pendingClass: (_c = binding.pendingClass) != null ? _c : "v-click-delay--pending",
882
+ feedback: (_d = binding.feedback) != null ? _d : true
883
+ };
884
+ }
885
+ const vClickDelay = defineDirective({
886
+ name: "click-delay",
887
+ ssr: true,
904
888
  defaults: {
905
- capture: true,
906
- events: ["click"],
889
+ delay: 300,
907
890
  disabled: false,
908
- stop: false,
909
- prevent: false
891
+ pendingClass: "v-click-delay--pending",
892
+ feedback: true
910
893
  },
911
894
  mounted(el, binding) {
912
- const options = normalizeOptions$y(binding.value);
895
+ const options = normalizeOptions$z(binding.value, binding);
913
896
  if (options.disabled) return;
914
897
  const state = {
915
898
  options,
916
- handlers: /* @__PURE__ */ new Map()
917
- };
918
- el.__clickOutside = state;
919
- const createHandler = (_eventType) => {
920
- return (event) => {
921
- if (!isValidClick(el, event, options)) {
922
- return;
923
- }
924
- if (options.stop) {
925
- event.stopPropagation();
926
- }
927
- if (options.prevent) {
928
- event.preventDefault();
929
- }
930
- options.handler(event);
931
- };
899
+ handler: createClickHandler(el, options),
900
+ isPending: false,
901
+ timeoutId: null
932
902
  };
933
- options.events.forEach((eventType) => {
934
- const handler = createHandler();
935
- state.handlers.set(eventType, handler);
936
- const listenerOptions = {
937
- capture: options.capture,
938
- passive: !options.prevent
939
- };
940
- on(document, eventType, handler, listenerOptions);
941
- });
903
+ setState$1(el, STATE_KEY$5, state);
904
+ el.addEventListener("click", state.handler);
905
+ el.addEventListener("touchend", state.handler);
942
906
  },
943
907
  updated(el, binding) {
944
- const state = el.__clickOutside;
945
- if (!state) return;
946
- const oldOptions = state.options;
947
- const newOptions = normalizeOptions$y(binding.value);
908
+ const state = getState$1(el, STATE_KEY$5);
909
+ if (!state) {
910
+ const options = normalizeOptions$z(binding.value, binding);
911
+ if (!options.disabled) {
912
+ const newState = {
913
+ options,
914
+ handler: createClickHandler(el, options),
915
+ isPending: false,
916
+ timeoutId: null
917
+ };
918
+ setState$1(el, STATE_KEY$5, newState);
919
+ el.addEventListener("click", newState.handler);
920
+ el.addEventListener("touchend", newState.handler);
921
+ }
922
+ return;
923
+ }
924
+ const newOptions = normalizeOptions$z(binding.value, binding);
925
+ if (newOptions.disabled && !state.options.disabled) {
926
+ el.removeEventListener("click", state.handler);
927
+ el.removeEventListener("touchend", state.handler);
928
+ if (state.timeoutId) {
929
+ clearTimeout(state.timeoutId);
930
+ }
931
+ removePendingClass(el, state.options);
932
+ deleteState(el, STATE_KEY$5);
933
+ } else if (!newOptions.disabled && state.options.disabled) {
934
+ state.handler = createClickHandler(el, newOptions);
935
+ state.isPending = false;
936
+ state.timeoutId = null;
937
+ el.addEventListener("click", state.handler);
938
+ el.addEventListener("touchend", state.handler);
939
+ }
940
+ state.options = newOptions;
941
+ },
942
+ unmounted(el) {
943
+ const state = getState$1(el, STATE_KEY$5);
944
+ if (!state) return;
945
+ el.removeEventListener("click", state.handler);
946
+ el.removeEventListener("touchend", state.handler);
947
+ if (state.timeoutId) {
948
+ clearTimeout(state.timeoutId);
949
+ }
950
+ removePendingClass(el, state.options);
951
+ deleteState(el, STATE_KEY$5);
952
+ }
953
+ });
954
+ const vClickOutside = defineDirective({
955
+ name: "click-outside",
956
+ ssr: false,
957
+ defaults: {
958
+ capture: true,
959
+ events: ["click"],
960
+ disabled: false,
961
+ stop: false,
962
+ prevent: false
963
+ },
964
+ mounted(el, binding) {
965
+ const options = normalizeOptions$y(binding.value);
966
+ if (options.disabled) return;
967
+ const state = {
968
+ options,
969
+ handlers: /* @__PURE__ */ new Map()
970
+ };
971
+ el.__clickOutside = state;
972
+ const createHandler = (_eventType) => {
973
+ return (event) => {
974
+ if (!isValidClick$1(el, event, options)) {
975
+ return;
976
+ }
977
+ if (options.stop) {
978
+ event.stopPropagation();
979
+ }
980
+ if (options.prevent) {
981
+ event.preventDefault();
982
+ }
983
+ options.handler(event);
984
+ };
985
+ };
986
+ options.events.forEach((eventType) => {
987
+ const handler = createHandler();
988
+ state.handlers.set(eventType, handler);
989
+ const listenerOptions = {
990
+ capture: options.capture,
991
+ passive: !options.prevent
992
+ };
993
+ on(document, eventType, handler, listenerOptions);
994
+ });
995
+ },
996
+ updated(el, binding) {
997
+ const state = el.__clickOutside;
998
+ if (!state) return;
999
+ const oldOptions = state.options;
1000
+ const newOptions = normalizeOptions$y(binding.value);
948
1001
  if (oldOptions.disabled !== newOptions.disabled) {
949
1002
  if (newOptions.disabled) {
950
1003
  state.handlers.forEach((handler, eventType) => {
@@ -954,7 +1007,7 @@ const vClickOutside = defineDirective({
954
1007
  } else {
955
1008
  const createHandler = (_eventType) => {
956
1009
  return (event) => {
957
- if (!isValidClick(el, event, newOptions)) return;
1010
+ if (!isValidClick$1(el, event, newOptions)) return;
958
1011
  if (newOptions.stop) event.stopPropagation();
959
1012
  if (newOptions.prevent) event.preventDefault();
960
1013
  newOptions.handler(event);
@@ -1004,7 +1057,7 @@ function normalizeOptions$y(binding) {
1004
1057
  prevent: (_e = binding.prevent) != null ? _e : false
1005
1058
  }, binding);
1006
1059
  }
1007
- function isValidClick(el, event, options) {
1060
+ function isValidClick$1(el, event, options) {
1008
1061
  var _a;
1009
1062
  const target = event.target;
1010
1063
  if (el.contains(target)) {
@@ -1020,7 +1073,7 @@ function isValidClick(el, event, options) {
1020
1073
  }
1021
1074
  return true;
1022
1075
  }
1023
- function copyToClipboard(text) {
1076
+ function copyToClipboard$1(text) {
1024
1077
  return __async(this, null, function* () {
1025
1078
  if (supportsClipboard()) {
1026
1079
  try {
@@ -1030,10 +1083,10 @@ function copyToClipboard(text) {
1030
1083
  console.warn("[Directix] Clipboard API failed, falling back to execCommand");
1031
1084
  }
1032
1085
  }
1033
- return copyWithExecCommand(text);
1086
+ return copyWithExecCommand$1(text);
1034
1087
  });
1035
1088
  }
1036
- function copyWithExecCommand(text) {
1089
+ function copyWithExecCommand$1(text) {
1037
1090
  const textarea = document.createElement("textarea");
1038
1091
  textarea.value = text;
1039
1092
  textarea.style.cssText = `
@@ -1075,7 +1128,7 @@ const vCopy = defineDirective({
1075
1128
  return;
1076
1129
  }
1077
1130
  try {
1078
- const success = yield copyToClipboard(text);
1131
+ const success = yield copyToClipboard$1(text);
1079
1132
  if (success) {
1080
1133
  (_b = (_a = state.options).onSuccess) == null ? void 0 : _b.call(_a, text);
1081
1134
  el.dispatchEvent(new CustomEvent("copy:success", { detail: { text } }));
@@ -1112,7 +1165,7 @@ function normalizeOptions$x(binding) {
1112
1165
  }
1113
1166
  return binding;
1114
1167
  }
1115
- function parseTargetTime(target) {
1168
+ function parseTargetTime$1(target) {
1116
1169
  if (target instanceof Date) {
1117
1170
  return target.getTime();
1118
1171
  }
@@ -1121,7 +1174,7 @@ function parseTargetTime(target) {
1121
1174
  }
1122
1175
  return new Date(target).getTime();
1123
1176
  }
1124
- function calculateTime(remaining) {
1177
+ function calculateTime$1(remaining) {
1125
1178
  const total = Math.max(0, remaining);
1126
1179
  return {
1127
1180
  days: Math.floor(total / (1e3 * 60 * 60 * 24)),
@@ -1132,7 +1185,7 @@ function calculateTime(remaining) {
1132
1185
  total
1133
1186
  };
1134
1187
  }
1135
- function formatTime(time, format) {
1188
+ function formatTime$1(time, format) {
1136
1189
  if (typeof format === "function") {
1137
1190
  return format(time);
1138
1191
  }
@@ -1167,7 +1220,7 @@ const vCountdown = defineDirective({
1167
1220
  ssr: true,
1168
1221
  mounted(el, binding) {
1169
1222
  const options = normalizeOptions$w(binding.value);
1170
- const targetTime = parseTargetTime(options.target);
1223
+ const targetTime = parseTargetTime$1(options.target);
1171
1224
  const state = {
1172
1225
  options,
1173
1226
  targetTime,
@@ -1185,7 +1238,7 @@ const vCountdown = defineDirective({
1185
1238
  updated(el, binding) {
1186
1239
  const state = el.__countdown;
1187
1240
  const newOptions = normalizeOptions$w(binding.value);
1188
- const newTargetTime = parseTargetTime(newOptions.target);
1241
+ const newTargetTime = parseTargetTime$1(newOptions.target);
1189
1242
  if (newTargetTime !== state.targetTime) {
1190
1243
  state.targetTime = newTargetTime;
1191
1244
  state.options = newOptions;
@@ -1224,7 +1277,7 @@ function startCountdown(el, state) {
1224
1277
  }
1225
1278
  updateDisplay(el, state);
1226
1279
  if (state.options.onTick) {
1227
- const time = calculateTime(state.remaining);
1280
+ const time = calculateTime$1(state.remaining);
1228
1281
  state.options.onTick(time);
1229
1282
  }
1230
1283
  };
@@ -1238,45 +1291,10 @@ function stopCountdown(state) {
1238
1291
  }
1239
1292
  }
1240
1293
  function updateDisplay(el, state) {
1241
- const time = calculateTime(state.remaining);
1242
- const display = formatTime(time, state.options.format || "hh:mm:ss");
1294
+ const time = calculateTime$1(state.remaining);
1295
+ const display = formatTime$1(time, state.options.format || "hh:mm:ss");
1243
1296
  el.textContent = display;
1244
1297
  }
1245
- const EVENT_MODIFIERS = [
1246
- "click",
1247
- "input",
1248
- "change",
1249
- "submit",
1250
- "scroll",
1251
- "resize",
1252
- "mouseenter",
1253
- "mouseleave",
1254
- "mousemove",
1255
- "mousedown",
1256
- "mouseup",
1257
- "keydown",
1258
- "keyup",
1259
- "focus",
1260
- "blur",
1261
- "touchstart",
1262
- "touchmove",
1263
- "touchend"
1264
- ];
1265
- function getEventTypeFromModifiers(modifiers) {
1266
- for (const modifier of EVENT_MODIFIERS) {
1267
- if (modifiers[modifier]) {
1268
- return modifier;
1269
- }
1270
- }
1271
- return null;
1272
- }
1273
- function getDefaultEventType(el) {
1274
- const tagName = el.tagName.toLowerCase();
1275
- if (tagName === "input" || tagName === "textarea") {
1276
- return "input";
1277
- }
1278
- return "click";
1279
- }
1280
1298
  function normalizeOptions$v(binding, directiveBinding) {
1281
1299
  const wait = parseTime(directiveBinding.arg) || 300;
1282
1300
  if (typeof binding === "function") {
@@ -1336,7 +1354,7 @@ const vDebounce = defineDirective({
1336
1354
  delete el.__debounce;
1337
1355
  }
1338
1356
  });
1339
- function getBoundary(_el, boundary) {
1357
+ function getBoundary$1(_el, boundary) {
1340
1358
  var _a, _b;
1341
1359
  if (!boundary) return null;
1342
1360
  if (typeof boundary === "function") {
@@ -1349,7 +1367,7 @@ function getBoundary(_el, boundary) {
1349
1367
  }
1350
1368
  return boundary.getBoundingClientRect();
1351
1369
  }
1352
- function getClientCoords(e) {
1370
+ function getClientCoords$1(e) {
1353
1371
  if (e.type.startsWith("touch")) {
1354
1372
  const touch = e.touches[0];
1355
1373
  return { clientX: touch.clientX, clientY: touch.clientY };
@@ -1357,7 +1375,7 @@ function getClientCoords(e) {
1357
1375
  const mouseEvent = e;
1358
1376
  return { clientX: mouseEvent.clientX, clientY: mouseEvent.clientY };
1359
1377
  }
1360
- function parseTranslate(transform) {
1378
+ function parseTranslate$1(transform) {
1361
1379
  const match = transform.match(/translate\(([-\d.]+)px,\s*([-\d.]+)px\)/);
1362
1380
  if (match) {
1363
1381
  return { x: parseFloat(match[1]), y: parseFloat(match[2]) };
@@ -1420,15 +1438,15 @@ const vDraggable = defineDirective({
1420
1438
  if (e.type === "touchstart") {
1421
1439
  e.preventDefault();
1422
1440
  }
1423
- const { clientX, clientY } = getClientCoords(e);
1441
+ const { clientX, clientY } = getClientCoords$1(e);
1424
1442
  state.isDragging = true;
1425
1443
  state.startX = clientX;
1426
1444
  state.startY = clientY;
1427
- const { x, y } = parseTranslate(el.style.transform);
1445
+ const { x, y } = parseTranslate$1(el.style.transform);
1428
1446
  state.offsetX = x;
1429
1447
  state.offsetY = y;
1430
1448
  if (state.options.constrain || state.options.boundary) {
1431
- const boundary = state.options.boundary ? getBoundary(el, state.options.boundary) : (_a = el.parentElement) == null ? void 0 : _a.getBoundingClientRect();
1449
+ const boundary = state.options.boundary ? getBoundary$1(el, state.options.boundary) : (_a = el.parentElement) == null ? void 0 : _a.getBoundingClientRect();
1432
1450
  if (boundary) {
1433
1451
  const elRect = el.getBoundingClientRect();
1434
1452
  state.initialLeft = elRect.left - boundary.left;
@@ -1443,7 +1461,7 @@ const vDraggable = defineDirective({
1443
1461
  state.moveHandler = (moveEvent) => {
1444
1462
  var _a2, _b2;
1445
1463
  if (!state.isDragging) return;
1446
- const { clientX: moveX, clientY: moveY } = getClientCoords(moveEvent);
1464
+ const { clientX: moveX, clientY: moveY } = getClientCoords$1(moveEvent);
1447
1465
  let deltaX = moveX - state.startX, deltaY = moveY - state.startY;
1448
1466
  if (state.options.axis === "x") {
1449
1467
  deltaY = 0;
@@ -1481,7 +1499,7 @@ const vDraggable = defineDirective({
1481
1499
  document.removeEventListener("mouseup", state.endHandler);
1482
1500
  document.removeEventListener("touchend", state.endHandler);
1483
1501
  }
1484
- const { x: finalX, y: finalY } = parseTranslate(el.style.transform);
1502
+ const { x: finalX, y: finalY } = parseTranslate$1(el.style.transform);
1485
1503
  (_b2 = (_a2 = state.options).onEnd) == null ? void 0 : _b2.call(_a2, { x: finalX, y: finalY }, new MouseEvent("mouseup"));
1486
1504
  };
1487
1505
  document.addEventListener("mousemove", state.moveHandler);
@@ -1657,7 +1675,7 @@ function normalizeOptions$t(binding) {
1657
1675
  titleBehavior: (_d = binding == null ? void 0 : binding.titleBehavior) != null ? _d : "auto"
1658
1676
  };
1659
1677
  }
1660
- const FOCUSABLE_TAGS = /* @__PURE__ */ new Set(["input", "textarea", "select", "button"]);
1678
+ const FOCUSABLE_TAGS$1 = /* @__PURE__ */ new Set(["input", "textarea", "select", "button"]);
1661
1679
  function isEqual(a, b) {
1662
1680
  if (a === b) return true;
1663
1681
  if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
@@ -1679,7 +1697,7 @@ const vFocus = defineDirective({
1679
1697
  mounted(el, binding) {
1680
1698
  if (!isBrowser()) return;
1681
1699
  const options = normalizeOptions$s(binding.value);
1682
- if (!options.focus || !isFocusable(el)) {
1700
+ if (!options.focus || !isFocusable$1(el)) {
1683
1701
  if (options.focus) {
1684
1702
  console.warn("[Directix] v-focus: Element is not focusable");
1685
1703
  }
@@ -1747,10 +1765,10 @@ function normalizeOptions$s(binding) {
1747
1765
  refocus: false
1748
1766
  }, binding);
1749
1767
  }
1750
- function isFocusable(el) {
1768
+ function isFocusable$1(el) {
1751
1769
  if (!isBrowser()) return false;
1752
1770
  const tagName = el.tagName.toLowerCase();
1753
- if (FOCUSABLE_TAGS.has(tagName)) {
1771
+ if (FOCUSABLE_TAGS$1.has(tagName)) {
1754
1772
  return !el.disabled;
1755
1773
  }
1756
1774
  if (el.isContentEditable) return true;
@@ -1761,7 +1779,7 @@ function isFocusable(el) {
1761
1779
  }
1762
1780
  return false;
1763
1781
  }
1764
- const KEY_ALIASES = {
1782
+ const KEY_ALIASES$1 = {
1765
1783
  esc: "escape",
1766
1784
  space: " ",
1767
1785
  up: "arrowup",
@@ -1793,7 +1811,7 @@ const KEY_ALIASES = {
1793
1811
  const MODIFIER_KEYS = /* @__PURE__ */ new Set(["ctrl", "alt", "shift", "meta"]);
1794
1812
  function normalizeKey(key) {
1795
1813
  const lowerKey = key.toLowerCase();
1796
- return KEY_ALIASES[lowerKey] || lowerKey;
1814
+ return KEY_ALIASES$1[lowerKey] || lowerKey;
1797
1815
  }
1798
1816
  function parseHotkeyString(hotkey) {
1799
1817
  const parts = hotkey.toLowerCase().split(/[+.]/);
@@ -1808,7 +1826,7 @@ function parseHotkeyString(hotkey) {
1808
1826
  }
1809
1827
  return { key, modifiers };
1810
1828
  }
1811
- function matchesHotkey(event, entry) {
1829
+ function matchesHotkey$1(event, entry) {
1812
1830
  if (normalizeKey(event.key) !== entry.key) return false;
1813
1831
  const eventModifiers = /* @__PURE__ */ new Set();
1814
1832
  if (event.ctrlKey) eventModifiers.add("ctrl");
@@ -1895,7 +1913,7 @@ function createKeydownHandler(state) {
1895
1913
  return (event) => {
1896
1914
  for (const entry of state.entries) {
1897
1915
  if (entry.disabled) continue;
1898
- if (!matchesHotkey(event, entry)) continue;
1916
+ if (!matchesHotkey$1(event, entry)) continue;
1899
1917
  if (entry.prevent) event.preventDefault();
1900
1918
  if (entry.stop) event.stopPropagation();
1901
1919
  entry.handler(event);
@@ -1935,6 +1953,61 @@ const vHotkey = defineDirective({
1935
1953
  delete el.__hotkey;
1936
1954
  }
1937
1955
  });
1956
+ function useTimer() {
1957
+ const timeouts = /* @__PURE__ */ new Set();
1958
+ const intervals = /* @__PURE__ */ new Set();
1959
+ return {
1960
+ /**
1961
+ * Set a timeout (tracked for cleanup)
1962
+ */
1963
+ setTimeout(fn, delay) {
1964
+ const id = setTimeout(() => {
1965
+ timeouts.delete(id);
1966
+ fn();
1967
+ }, delay);
1968
+ timeouts.add(id);
1969
+ return id;
1970
+ },
1971
+ /**
1972
+ * Clear a specific timeout
1973
+ */
1974
+ clearTimeout(id) {
1975
+ clearTimeout(id);
1976
+ timeouts.delete(id);
1977
+ },
1978
+ /**
1979
+ * Set an interval (tracked for cleanup)
1980
+ */
1981
+ setInterval(fn, delay) {
1982
+ const id = setInterval(fn, delay);
1983
+ intervals.add(id);
1984
+ return id;
1985
+ },
1986
+ /**
1987
+ * Clear a specific interval
1988
+ */
1989
+ clearInterval(id) {
1990
+ clearInterval(id);
1991
+ intervals.delete(id);
1992
+ },
1993
+ /**
1994
+ * Clear all tracked timers
1995
+ */
1996
+ clearAll() {
1997
+ timeouts.forEach((id) => clearTimeout(id));
1998
+ intervals.forEach((id) => clearInterval(id));
1999
+ timeouts.clear();
2000
+ intervals.clear();
2001
+ },
2002
+ /**
2003
+ * Check if there are any active timers
2004
+ */
2005
+ hasActive() {
2006
+ return timeouts.size > 0 || intervals.size > 0;
2007
+ }
2008
+ };
2009
+ }
2010
+ const STATE_KEY$4 = "hover";
1938
2011
  function normalizeOptions$r(binding) {
1939
2012
  if (typeof binding === "function") {
1940
2013
  return { handler: binding, class: "v-hover" };
@@ -1946,6 +2019,26 @@ function normalizeOptions$r(binding) {
1946
2019
  leaveDelay: 0
1947
2020
  }, binding);
1948
2021
  }
2022
+ function applyHoverState(el, state, e) {
2023
+ var _a, _b;
2024
+ const { options } = state;
2025
+ if (options.class) {
2026
+ el.classList.add(options.class);
2027
+ }
2028
+ el.dispatchEvent(new CustomEvent("hover:enter", { detail: { event: e } }));
2029
+ (_a = options.onEnter) == null ? void 0 : _a.call(options, e);
2030
+ (_b = options.handler) == null ? void 0 : _b.call(options, true, e);
2031
+ }
2032
+ function applyLeaveState(el, state, e) {
2033
+ var _a, _b;
2034
+ const { options } = state;
2035
+ if (options.class) {
2036
+ el.classList.remove(options.class);
2037
+ }
2038
+ el.dispatchEvent(new CustomEvent("hover:leave", { detail: { event: e } }));
2039
+ (_a = options.onLeave) == null ? void 0 : _a.call(options, e);
2040
+ (_b = options.handler) == null ? void 0 : _b.call(options, false, e);
2041
+ }
1949
2042
  const vHover = defineDirective({
1950
2043
  name: "hover",
1951
2044
  ssr: false,
@@ -1958,56 +2051,54 @@ const vHover = defineDirective({
1958
2051
  mounted(el, binding) {
1959
2052
  const options = normalizeOptions$r(binding.value);
1960
2053
  if (options.disabled || !isBrowser()) return;
2054
+ const timer = useTimer();
2055
+ let isHovering = false;
1961
2056
  const state = {
1962
2057
  options,
1963
2058
  isHovering: false,
1964
- enterTimerId: null,
1965
- leaveTimerId: null,
1966
- enterHandler: () => {
1967
- },
1968
- leaveHandler: () => {
1969
- }
2059
+ timer,
2060
+ cleanup: null
1970
2061
  };
1971
- state.enterHandler = (e) => {
2062
+ const enterHandler = (e) => {
1972
2063
  const event = e;
1973
- if (state.leaveTimerId) {
1974
- clearTimeout(state.leaveTimerId);
1975
- state.leaveTimerId = null;
1976
- }
1977
- if (state.isHovering) return;
2064
+ timer.clearAll();
2065
+ if (isHovering) return;
1978
2066
  if (options.enterDelay && options.enterDelay > 0) {
1979
- state.enterTimerId = setTimeout(() => {
2067
+ timer.setTimeout(() => {
2068
+ isHovering = true;
1980
2069
  state.isHovering = true;
1981
2070
  applyHoverState(el, state, event);
1982
2071
  }, options.enterDelay);
1983
2072
  } else {
2073
+ isHovering = true;
1984
2074
  state.isHovering = true;
1985
2075
  applyHoverState(el, state, event);
1986
2076
  }
1987
2077
  };
1988
- state.leaveHandler = (e) => {
2078
+ const leaveHandler = (e) => {
1989
2079
  const event = e;
1990
- if (state.enterTimerId) {
1991
- clearTimeout(state.enterTimerId);
1992
- state.enterTimerId = null;
1993
- }
1994
- if (!state.isHovering) return;
2080
+ timer.clearAll();
2081
+ if (!isHovering) return;
1995
2082
  if (options.leaveDelay && options.leaveDelay > 0) {
1996
- state.leaveTimerId = setTimeout(() => {
2083
+ timer.setTimeout(() => {
2084
+ isHovering = false;
1997
2085
  state.isHovering = false;
1998
2086
  applyLeaveState(el, state, event);
1999
2087
  }, options.leaveDelay);
2000
2088
  } else {
2089
+ isHovering = false;
2001
2090
  state.isHovering = false;
2002
2091
  applyLeaveState(el, state, event);
2003
2092
  }
2004
2093
  };
2005
- el.__hover = state;
2006
- on(el, "mouseenter", state.enterHandler);
2007
- on(el, "mouseleave", state.leaveHandler);
2094
+ state.cleanup = bindEvents$2(el, {
2095
+ mouseenter: enterHandler,
2096
+ mouseleave: leaveHandler
2097
+ });
2098
+ setState$1(el, STATE_KEY$4, state);
2008
2099
  },
2009
2100
  updated(el, binding) {
2010
- const state = el.__hover;
2101
+ const state = getState$1(el, STATE_KEY$4);
2011
2102
  if (!state) return;
2012
2103
  const newOptions = normalizeOptions$r(binding.value);
2013
2104
  if (newOptions.disabled && !state.options.disabled) {
@@ -2016,40 +2107,15 @@ const vHover = defineDirective({
2016
2107
  state.options = newOptions;
2017
2108
  },
2018
2109
  unmounted(el) {
2019
- const state = el.__hover;
2110
+ var _a;
2111
+ const state = getState$1(el, STATE_KEY$4);
2020
2112
  if (!state) return;
2021
- if (state.enterTimerId) {
2022
- clearTimeout(state.enterTimerId);
2023
- }
2024
- if (state.leaveTimerId) {
2025
- clearTimeout(state.leaveTimerId);
2026
- }
2027
- off(el, "mouseenter", state.enterHandler);
2028
- off(el, "mouseleave", state.leaveHandler);
2113
+ state.timer.clearAll();
2114
+ (_a = state.cleanup) == null ? void 0 : _a.call(state);
2029
2115
  el.classList.remove(state.options.class || "v-hover");
2030
- delete el.__hover;
2116
+ deleteState(el, STATE_KEY$4);
2031
2117
  }
2032
2118
  });
2033
- function applyHoverState(el, state, e) {
2034
- var _a, _b;
2035
- const { options } = state;
2036
- if (options.class) {
2037
- el.classList.add(options.class);
2038
- }
2039
- el.dispatchEvent(new CustomEvent("hover:enter", { detail: { event: e } }));
2040
- (_a = options.onEnter) == null ? void 0 : _a.call(options, e);
2041
- (_b = options.handler) == null ? void 0 : _b.call(options, true, e);
2042
- }
2043
- function applyLeaveState(el, state, e) {
2044
- var _a, _b;
2045
- const { options } = state;
2046
- if (options.class) {
2047
- el.classList.remove(options.class);
2048
- }
2049
- el.dispatchEvent(new CustomEvent("hover:leave", { detail: { event: e } }));
2050
- (_a = options.onLeave) == null ? void 0 : _a.call(options, e);
2051
- (_b = options.handler) == null ? void 0 : _b.call(options, false, e);
2052
- }
2053
2119
  const DEFAULTS = {
2054
2120
  minScale: 0.5,
2055
2121
  maxScale: 5,
@@ -2060,7 +2126,7 @@ const DEFAULTS = {
2060
2126
  zoomIndicatorDuration: 1500
2061
2127
  };
2062
2128
  let globalZIndex = 9999;
2063
- function getDistance$2(x1, y1, x2, y2) {
2129
+ function getDistance$3(x1, y1, x2, y2) {
2064
2130
  return Math.sqrt(__pow(x2 - x1, 2) + __pow(y2 - y1, 2));
2065
2131
  }
2066
2132
  function clamp(value, min, max) {
@@ -2243,7 +2309,7 @@ function createGestureHandlers(state, transformManager, closePreview) {
2243
2309
  gesture.swipeStartY = e.touches[0].clientY;
2244
2310
  } else if (e.touches.length === 2 && options.enablePinchZoom !== false) {
2245
2311
  gesture.isDragging = false;
2246
- gesture.startDistance = getDistance$2(
2312
+ gesture.startDistance = getDistance$3(
2247
2313
  e.touches[0].clientX,
2248
2314
  e.touches[0].clientY,
2249
2315
  e.touches[1].clientX,
@@ -2264,7 +2330,7 @@ function createGestureHandlers(state, transformManager, closePreview) {
2264
2330
  transform.translateY = constrained.y;
2265
2331
  updateTransform(false);
2266
2332
  } else if (e.touches.length === 2 && options.enablePinchZoom !== false) {
2267
- const currentDistance = getDistance$2(
2333
+ const currentDistance = getDistance$3(
2268
2334
  e.touches[0].clientX,
2269
2335
  e.touches[0].clientY,
2270
2336
  e.touches[1].clientX,
@@ -3033,7 +3099,7 @@ function normalizeOptions$l(binding) {
3033
3099
  tickInterval: 100
3034
3100
  }, binding);
3035
3101
  }
3036
- function getDistance$1(p1, p2) {
3102
+ function getDistance$2(p1, p2) {
3037
3103
  return Math.sqrt(__pow(p2.x - p1.x, 2) + __pow(p2.y - p1.y, 2));
3038
3104
  }
3039
3105
  const vLongPress = defineDirective({
@@ -3080,7 +3146,7 @@ const vLongPress = defineDirective({
3080
3146
  clearInterval(state.tickTimerId);
3081
3147
  state.tickTimerId = null;
3082
3148
  }
3083
- const pos = getEventPosition(event);
3149
+ const pos = getEventPosition$1(event);
3084
3150
  state.startPos = { x: pos.x, y: pos.y };
3085
3151
  state.startTime = Date.now();
3086
3152
  (_a = options.onStart) == null ? void 0 : _a.call(options, event);
@@ -3120,8 +3186,8 @@ const vLongPress = defineDirective({
3120
3186
  var _a;
3121
3187
  if (!state.timerId) return;
3122
3188
  const event = e;
3123
- const pos = getEventPosition(event);
3124
- const distance = getDistance$1(state.startPos, { x: pos.x, y: pos.y });
3189
+ const pos = getEventPosition$1(event);
3190
+ const distance = getDistance$2(state.startPos, { x: pos.x, y: pos.y });
3125
3191
  if (distance > (options.distance || 10)) {
3126
3192
  if (state.timerId) {
3127
3193
  clearTimeout(state.timerId);
@@ -3356,7 +3422,7 @@ const vMask = defineDirective({
3356
3422
  delete el[STATE_KEY$2];
3357
3423
  }
3358
3424
  });
3359
- function formatNumber(value, options) {
3425
+ function formatNumber$1(value, options) {
3360
3426
  const { precision = 0, separator = ",", decimal = ".", prefix = "", suffix = "" } = options;
3361
3427
  const fixed = value.toFixed(precision);
3362
3428
  const [intPart, decPart] = fixed.split(".");
@@ -3459,7 +3525,7 @@ function setupNumberInput(el, options, formatFn) {
3459
3525
  el.removeEventListener("blur", onBlur);
3460
3526
  };
3461
3527
  }
3462
- function formatMoney(value, options) {
3528
+ function formatMoney$1(value, options) {
3463
3529
  const { precision = 2, separator = ",", decimal = ".", symbol = "$", symbolPosition = "before" } = options;
3464
3530
  const fixed = value.toFixed(precision);
3465
3531
  const [intPart, decPart] = fixed.split(".");
@@ -3480,14 +3546,14 @@ const vMoney = defineDirective({
3480
3546
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA") {
3481
3547
  const { symbol = "$", symbolPosition = "before" } = options;
3482
3548
  const prefix = symbolPosition === "before" ? symbol : "";
3483
- const cleanup2 = setupNumberInput(el, __spreadProps(__spreadValues({}, options), { prefix }), formatMoney);
3549
+ const cleanup2 = setupNumberInput(el, __spreadProps(__spreadValues({}, options), { prefix }), formatMoney$1);
3484
3550
  el.__money = { options, cleanup: cleanup2 };
3485
3551
  requestAnimationFrame(() => {
3486
3552
  const inputEl = el;
3487
3553
  if (inputEl.value) {
3488
3554
  const num = parseToNumber(inputEl.value, options.decimal || ".");
3489
3555
  if (num !== null) {
3490
- const formatted = formatMoney(clampValue(num, options), options);
3556
+ const formatted = formatMoney$1(clampValue(num, options), options);
3491
3557
  if (formatted !== inputEl.value) {
3492
3558
  inputEl.value = formatted;
3493
3559
  inputEl.dispatchEvent(new Event("input", { bubbles: true }));
@@ -3506,7 +3572,7 @@ const vMoney = defineDirective({
3506
3572
  }
3507
3573
  }
3508
3574
  if (value !== null) {
3509
- el.textContent = formatMoney(clampValue(value, options), options);
3575
+ el.textContent = formatMoney$1(clampValue(value, options), options);
3510
3576
  }
3511
3577
  }
3512
3578
  },
@@ -3523,7 +3589,7 @@ const vMoney = defineDirective({
3523
3589
  value = binding.value.value;
3524
3590
  }
3525
3591
  if (value !== null) {
3526
- el.textContent = formatMoney(clampValue(value, options), options);
3592
+ el.textContent = formatMoney$1(clampValue(value, options), options);
3527
3593
  }
3528
3594
  }
3529
3595
  },
@@ -3641,14 +3707,14 @@ const vNumber = defineDirective({
3641
3707
  var _a, _b;
3642
3708
  const options = typeof binding.value === "number" ? { precision: binding.value } : (_a = binding.value) != null ? _a : {};
3643
3709
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA") {
3644
- const cleanup2 = setupNumberInput(el, options, formatNumber);
3710
+ const cleanup2 = setupNumberInput(el, options, formatNumber$1);
3645
3711
  el.__number = { options, cleanup: cleanup2 };
3646
3712
  requestAnimationFrame(() => {
3647
3713
  const inputEl = el;
3648
3714
  if (inputEl.value) {
3649
3715
  const num = parseToNumber(inputEl.value, options.decimal || ".");
3650
3716
  if (num !== null) {
3651
- const formatted = formatNumber(clampValue(num, options), options);
3717
+ const formatted = formatNumber$1(clampValue(num, options), options);
3652
3718
  if (formatted !== inputEl.value) {
3653
3719
  inputEl.value = formatted;
3654
3720
  inputEl.dispatchEvent(new Event("input", { bubbles: true }));
@@ -3669,7 +3735,7 @@ const vNumber = defineDirective({
3669
3735
  }
3670
3736
  }
3671
3737
  if (value !== null) {
3672
- el.textContent = formatNumber(clampValue(value, options), options);
3738
+ el.textContent = formatNumber$1(clampValue(value, options), options);
3673
3739
  }
3674
3740
  }
3675
3741
  },
@@ -3687,7 +3753,7 @@ const vNumber = defineDirective({
3687
3753
  value = binding.value.value;
3688
3754
  }
3689
3755
  if (value !== null) {
3690
- el.textContent = formatNumber(clampValue(value, options), options);
3756
+ el.textContent = formatNumber$1(clampValue(value, options), options);
3691
3757
  }
3692
3758
  }
3693
3759
  },
@@ -3698,14 +3764,6 @@ const vNumber = defineDirective({
3698
3764
  }
3699
3765
  });
3700
3766
  const STATE_KEY$1 = "__permission";
3701
- const WILDCARD = "*";
3702
- let globalConfig = null;
3703
- function configurePermission(config) {
3704
- globalConfig = config;
3705
- }
3706
- function getPermissionConfig() {
3707
- return globalConfig;
3708
- }
3709
3767
  function normalizeOptions$h(binding) {
3710
3768
  if (!binding) {
3711
3769
  throw new Error("[Directix] v-permission: permission value is required");
@@ -3718,39 +3776,14 @@ function normalizeOptions$h(binding) {
3718
3776
  }
3719
3777
  return binding;
3720
3778
  }
3721
- function hasPermission(required, permissions) {
3722
- return permissions.includes(WILDCARD) || permissions.includes(required);
3723
- }
3724
3779
  function verifyPermission(options) {
3725
- var _a;
3726
3780
  if (options.check) {
3727
3781
  return options.check(options.value, options.mode || "some");
3728
3782
  }
3729
- if (!globalConfig) {
3783
+ {
3730
3784
  console.warn("[Directix] v-permission: No permission config provided");
3731
3785
  return true;
3732
3786
  }
3733
- const permissions = globalConfig.getPermissions();
3734
- const roles = ((_a = globalConfig.getRoles) == null ? void 0 : _a.call(globalConfig)) || [];
3735
- const roleMap = globalConfig.roleMap || {};
3736
- const required = Array.isArray(options.value) ? options.value : [options.value];
3737
- const mode = options.mode || "some";
3738
- function checkSingle(value) {
3739
- if (value in roleMap) {
3740
- return roles.includes(value);
3741
- }
3742
- if (hasPermission(value, permissions)) {
3743
- return true;
3744
- }
3745
- for (const role of roles) {
3746
- const rolePermissions = roleMap[role] || [];
3747
- if (hasPermission(value, rolePermissions)) {
3748
- return true;
3749
- }
3750
- }
3751
- return false;
3752
- }
3753
- return mode === "every" ? required.every(checkSingle) : required.some(checkSingle);
3754
3787
  }
3755
3788
  function handleDenied(el, action, state) {
3756
3789
  var _a, _b;
@@ -3899,16 +3932,16 @@ function printElement(triggerEl, options) {
3899
3932
  return;
3900
3933
  }
3901
3934
  if (options.newWindow) {
3902
- yield printInNewWindow(targetEl, options);
3935
+ yield printInNewWindow$1(targetEl, options);
3903
3936
  } else {
3904
- yield printInIframe(targetEl, options);
3937
+ yield printInIframe$1(targetEl, options);
3905
3938
  }
3906
3939
  if (options.onAfterPrint) {
3907
3940
  options.onAfterPrint();
3908
3941
  }
3909
3942
  });
3910
3943
  }
3911
- function printInIframe(el, options) {
3944
+ function printInIframe$1(el, options) {
3912
3945
  return __async(this, null, function* () {
3913
3946
  var _a, _b, _c;
3914
3947
  const iframe = document.createElement("iframe");
@@ -3920,11 +3953,11 @@ function printInIframe(el, options) {
3920
3953
  document.body.removeChild(iframe);
3921
3954
  return;
3922
3955
  }
3923
- const content = buildPrintContent(el, options);
3956
+ const content = buildPrintContent$1(el, options);
3924
3957
  iframeDoc.open();
3925
3958
  iframeDoc.write(content);
3926
3959
  iframeDoc.close();
3927
- yield waitForImages(iframeDoc);
3960
+ yield waitForImages$1(iframeDoc);
3928
3961
  try {
3929
3962
  (_b = iframe.contentWindow) == null ? void 0 : _b.focus();
3930
3963
  (_c = iframe.contentWindow) == null ? void 0 : _c.print();
@@ -3936,18 +3969,18 @@ function printInIframe(el, options) {
3936
3969
  }, 1e3);
3937
3970
  });
3938
3971
  }
3939
- function printInNewWindow(el, options) {
3972
+ function printInNewWindow$1(el, options) {
3940
3973
  return __async(this, null, function* () {
3941
3974
  const printWindow = window.open("", "_blank");
3942
3975
  if (!printWindow) {
3943
3976
  console.warn("[Directix] v-print: Could not open print window");
3944
3977
  return;
3945
3978
  }
3946
- const content = buildPrintContent(el, options);
3979
+ const content = buildPrintContent$1(el, options);
3947
3980
  printWindow.document.open();
3948
3981
  printWindow.document.write(content);
3949
3982
  printWindow.document.close();
3950
- yield waitForImages(printWindow.document);
3983
+ yield waitForImages$1(printWindow.document);
3951
3984
  printWindow.focus();
3952
3985
  printWindow.print();
3953
3986
  setTimeout(() => {
@@ -3955,7 +3988,7 @@ function printInNewWindow(el, options) {
3955
3988
  }, 1e3);
3956
3989
  });
3957
3990
  }
3958
- function buildPrintContent(el, options) {
3991
+ function buildPrintContent$1(el, options) {
3959
3992
  let styles = "";
3960
3993
  document.querySelectorAll('style, link[rel="stylesheet"]').forEach((styleEl) => {
3961
3994
  if (styleEl.tagName === "STYLE") {
@@ -3996,7 +4029,7 @@ function buildPrintContent(el, options) {
3996
4029
  </body>
3997
4030
  </html>`;
3998
4031
  }
3999
- function waitForImages(doc) {
4032
+ function waitForImages$1(doc) {
4000
4033
  const images = doc.querySelectorAll("img");
4001
4034
  const promises = [];
4002
4035
  images.forEach((img) => {
@@ -4089,16 +4122,16 @@ function triggerRefresh(internal) {
4089
4122
  try {
4090
4123
  yield internal.options.handler();
4091
4124
  setState(internal, "success");
4092
- yield sleep(internal.options.successDuration);
4125
+ yield sleep$1(internal.options.successDuration);
4093
4126
  } catch (e) {
4094
4127
  setState(internal, "error");
4095
- yield sleep(internal.options.errorDuration);
4128
+ yield sleep$1(internal.options.errorDuration);
4096
4129
  } finally {
4097
4130
  resetPosition(internal);
4098
4131
  }
4099
4132
  });
4100
4133
  }
4101
- function sleep(ms) {
4134
+ function sleep$1(ms) {
4102
4135
  return new Promise((resolve) => setTimeout(resolve, ms));
4103
4136
  }
4104
4137
  function createHandlers(internal) {
@@ -4824,8 +4857,8 @@ const vSticky = defineDirective({
4824
4857
  });
4825
4858
  const DEFAULT_THRESHOLD = 30;
4826
4859
  const DEFAULT_MAX_TIME = 500;
4827
- const DEFAULT_DIRECTIONS = ["left", "right", "up", "down"];
4828
- function getSwipeDirection(deltaX, deltaY, allowedDirections) {
4860
+ const DEFAULT_DIRECTIONS$1 = ["left", "right", "up", "down"];
4861
+ function getSwipeDirection$1(deltaX, deltaY, allowedDirections) {
4829
4862
  const absX = Math.abs(deltaX);
4830
4863
  const absY = Math.abs(deltaY);
4831
4864
  if (absX > absY) {
@@ -4843,7 +4876,7 @@ function normalizeOptions$9(binding) {
4843
4876
  handler: binding.handler,
4844
4877
  threshold: (_a = binding.threshold) != null ? _a : DEFAULT_THRESHOLD,
4845
4878
  maxTime: (_b = binding.maxTime) != null ? _b : DEFAULT_MAX_TIME,
4846
- directions: (_c = binding.directions) != null ? _c : [...DEFAULT_DIRECTIONS],
4879
+ directions: (_c = binding.directions) != null ? _c : [...DEFAULT_DIRECTIONS$1],
4847
4880
  preventScrollOnSwipe: (_d = binding.preventScrollOnSwipe) != null ? _d : true,
4848
4881
  disabled: (_e = binding.disabled) != null ? _e : false,
4849
4882
  mouse: (_f = binding.mouse) != null ? _f : true,
@@ -4859,7 +4892,7 @@ function triggerSwipe(state, deltaX, deltaY, deltaTime, event, el) {
4859
4892
  if (deltaTime > ((_a = options.maxTime) != null ? _a : DEFAULT_MAX_TIME)) return;
4860
4893
  const distance = Math.max(Math.abs(deltaX), Math.abs(deltaY));
4861
4894
  if (distance < ((_b = options.threshold) != null ? _b : DEFAULT_THRESHOLD)) return;
4862
- const direction = getSwipeDirection(deltaX, deltaY, (_c = options.directions) != null ? _c : DEFAULT_DIRECTIONS);
4895
+ const direction = getSwipeDirection$1(deltaX, deltaY, (_c = options.directions) != null ? _c : DEFAULT_DIRECTIONS$1);
4863
4896
  if (!direction) return;
4864
4897
  if (options.preventScrollOnSwipe && event.cancelable) {
4865
4898
  event.preventDefault();
@@ -5348,7 +5381,7 @@ const vTooltip = defineDirective({
5348
5381
  delete el.__tooltip;
5349
5382
  }
5350
5383
  });
5351
- const getDistance = (x1, y1, x2, y2) => Math.sqrt(__pow(x2 - x1, 2) + __pow(y2 - y1, 2));
5384
+ const getDistance$1 = (x1, y1, x2, y2) => Math.sqrt(__pow(x2 - x1, 2) + __pow(y2 - y1, 2));
5352
5385
  const getAngle = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
5353
5386
  const MOUSE_IGNORE_DURATION = 400;
5354
5387
  const vTouch = defineDirective({
@@ -5426,7 +5459,7 @@ const vTouch = defineDirective({
5426
5459
  } else if (e.touches.length === 2) {
5427
5460
  clearLongPressTimer();
5428
5461
  const [t1, t2] = e.touches;
5429
- state.startDistance = getDistance(t1.clientX, t1.clientY, t2.clientX, t2.clientY);
5462
+ state.startDistance = getDistance$1(t1.clientX, t1.clientY, t2.clientX, t2.clientY);
5430
5463
  state.startAngle = getAngle(t1.clientX, t1.clientY, t2.clientX, t2.clientY);
5431
5464
  state.lastScale = 1;
5432
5465
  state.lastAngle = 0;
@@ -5443,7 +5476,7 @@ const vTouch = defineDirective({
5443
5476
  }
5444
5477
  if (e.touches.length === 2) {
5445
5478
  const [t1, t2] = e.touches;
5446
- const currentDistance = getDistance(t1.clientX, t1.clientY, t2.clientX, t2.clientY);
5479
+ const currentDistance = getDistance$1(t1.clientX, t1.clientY, t2.clientX, t2.clientY);
5447
5480
  const currentAngle = getAngle(t1.clientX, t1.clientY, t2.clientX, t2.clientY);
5448
5481
  if (state.options.enablePinch && state.options.onPinch) {
5449
5482
  const scale = currentDistance / state.startDistance;
@@ -5562,9 +5595,9 @@ function normalizeOptions$6(binding) {
5562
5595
  onTouchEnd: binding == null ? void 0 : binding.onTouchEnd
5563
5596
  };
5564
5597
  }
5565
- function trimText(text, options) {
5598
+ function trimText$1(text, options) {
5566
5599
  const { position = "both", chars } = options;
5567
- const charPattern = chars ? `[\\s${escapeRegex(chars)}]` : "\\s";
5600
+ const charPattern = chars ? `[\\s${escapeRegex$2(chars)}]` : "\\s";
5568
5601
  switch (position) {
5569
5602
  case "start":
5570
5603
  return text.replace(new RegExp(`^${charPattern}+`, "g"), "");
@@ -5575,7 +5608,7 @@ function trimText(text, options) {
5575
5608
  return text.replace(new RegExp(`^${charPattern}+|${charPattern}+$`, "g"), "");
5576
5609
  }
5577
5610
  }
5578
- function escapeRegex(str) {
5611
+ function escapeRegex$2(str) {
5579
5612
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5580
5613
  }
5581
5614
  const vTrim = defineDirective({
@@ -5587,7 +5620,7 @@ const vTrim = defineDirective({
5587
5620
  setupInputElement(el, options);
5588
5621
  } else {
5589
5622
  const text = el.textContent || "";
5590
- el.textContent = trimText(text, options);
5623
+ el.textContent = trimText$1(text, options);
5591
5624
  }
5592
5625
  },
5593
5626
  updated(el, binding) {
@@ -5599,7 +5632,7 @@ const vTrim = defineDirective({
5599
5632
  }
5600
5633
  } else {
5601
5634
  const text = el.textContent || "";
5602
- el.textContent = trimText(text, options);
5635
+ el.textContent = trimText$1(text, options);
5603
5636
  }
5604
5637
  },
5605
5638
  unmounted(el) {
@@ -5618,7 +5651,7 @@ function setupInputElement(el, options) {
5618
5651
  el.__trim = state;
5619
5652
  const performTrim = () => {
5620
5653
  const originalValue = el.value;
5621
- const trimmed = trimText(originalValue, options);
5654
+ const trimmed = trimText$1(originalValue, options);
5622
5655
  if (originalValue !== trimmed) {
5623
5656
  el.value = trimmed;
5624
5657
  el.dispatchEvent(new Event("input", { bubbles: true }));
@@ -5667,7 +5700,7 @@ function normalizeOptions$5(binding) {
5667
5700
  chars: binding.chars
5668
5701
  };
5669
5702
  }
5670
- function truncateText(text, options) {
5703
+ function truncateText$1(text, options) {
5671
5704
  const { length = 100, position = "end", ellipsis = "..." } = options;
5672
5705
  if (text.length <= length) {
5673
5706
  return text;
@@ -5730,7 +5763,7 @@ function applyTruncation(el, text, options) {
5730
5763
  el.setAttribute("title", text);
5731
5764
  }
5732
5765
  } else {
5733
- const truncated = truncateText(text, options);
5766
+ const truncated = truncateText$1(text, options);
5734
5767
  el.textContent = truncated;
5735
5768
  if (showTitle && text && text !== truncated) {
5736
5769
  el.setAttribute("title", text);
@@ -6116,7 +6149,7 @@ function applyVisibility(el, state, isVisible) {
6116
6149
  state.options.handler(isVisible);
6117
6150
  }
6118
6151
  }
6119
- function createWatermarkCanvas(options) {
6152
+ function createWatermarkCanvas$1(options) {
6120
6153
  var _a;
6121
6154
  const canvas = document.createElement("canvas");
6122
6155
  const ctx = canvas.getContext("2d");
@@ -6232,7 +6265,7 @@ const vWatermark = defineDirective({
6232
6265
  });
6233
6266
  function applyWatermark(el, state) {
6234
6267
  const options = state.options;
6235
- state.canvas = createWatermarkCanvas(options);
6268
+ state.canvas = createWatermarkCanvas$1(options);
6236
6269
  state.watermarkEl = createWatermarkElement(state.canvas, options);
6237
6270
  el.appendChild(state.watermarkEl);
6238
6271
  if (options.protect) {
@@ -6255,7 +6288,7 @@ function setupProtection(el, state) {
6255
6288
  state.observer = new MutationObserver((mutations) => {
6256
6289
  if (!state.watermarkEl || !el.contains(state.watermarkEl)) {
6257
6290
  if (!state.options.disabled) {
6258
- state.canvas = createWatermarkCanvas(state.options);
6291
+ state.canvas = createWatermarkCanvas$1(state.options);
6259
6292
  state.watermarkEl = createWatermarkElement(state.canvas, state.options);
6260
6293
  el.appendChild(state.watermarkEl);
6261
6294
  }
@@ -6280,6 +6313,2988 @@ function setupProtection(el, state) {
6280
6313
  attributeFilter: ["style", "class", "hidden"]
6281
6314
  });
6282
6315
  }
6316
+ const DEFAULT_KEEP_LOWER = [
6317
+ "a",
6318
+ "an",
6319
+ "the",
6320
+ "and",
6321
+ "but",
6322
+ "or",
6323
+ "for",
6324
+ "nor",
6325
+ "on",
6326
+ "at",
6327
+ "to",
6328
+ "from",
6329
+ "by",
6330
+ "in",
6331
+ "of",
6332
+ "with",
6333
+ "as"
6334
+ ];
6335
+ function capitalizeWord(word) {
6336
+ if (!word) return word;
6337
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
6338
+ }
6339
+ function capitalizeText(text, options = {}) {
6340
+ if (!text) return text;
6341
+ const { every = true, keepLower = DEFAULT_KEEP_LOWER } = options;
6342
+ if (every) {
6343
+ const words = text.toLowerCase().split(/\s+/);
6344
+ return words.map((word, index) => {
6345
+ if (index === 0) {
6346
+ return capitalizeWord(word);
6347
+ }
6348
+ if (keepLower.includes(word.toLowerCase())) {
6349
+ return word.toLowerCase();
6350
+ }
6351
+ return capitalizeWord(word);
6352
+ }).join(" ");
6353
+ } else {
6354
+ return capitalizeWord(text);
6355
+ }
6356
+ }
6357
+ function useCapitalcase(options) {
6358
+ const {
6359
+ text,
6360
+ every = true,
6361
+ keepLower = DEFAULT_KEEP_LOWER
6362
+ } = options;
6363
+ const original = vue.ref(vue.unref(text));
6364
+ const capitalized = vue.ref("");
6365
+ function calculate() {
6366
+ const textValue = vue.unref(text);
6367
+ const everyValue = vue.unref(every);
6368
+ const keepLowerValue = vue.unref(keepLower);
6369
+ original.value = textValue;
6370
+ capitalized.value = capitalizeText(textValue, {
6371
+ every: everyValue,
6372
+ keepLower: keepLowerValue
6373
+ });
6374
+ }
6375
+ vue.watch(
6376
+ () => [vue.unref(text), vue.unref(every), vue.unref(keepLower)],
6377
+ () => calculate(),
6378
+ { immediate: true }
6379
+ );
6380
+ return {
6381
+ capitalized,
6382
+ original
6383
+ };
6384
+ }
6385
+ function createCapitalizer(options = {}) {
6386
+ return (text) => capitalizeText(text, options);
6387
+ }
6388
+ function useClickDelay(options) {
6389
+ const {
6390
+ handler,
6391
+ delay = 300,
6392
+ disabled = false
6393
+ } = options;
6394
+ const isPending = vue.ref(false);
6395
+ let timeoutId = null;
6396
+ const getDelay = () => vue.unref(delay);
6397
+ const getDisabled = () => vue.unref(disabled);
6398
+ function click(event) {
6399
+ if (getDisabled() || isPending.value) {
6400
+ event.preventDefault();
6401
+ event.stopPropagation();
6402
+ return;
6403
+ }
6404
+ isPending.value = true;
6405
+ handler(event);
6406
+ timeoutId = setTimeout(() => {
6407
+ isPending.value = false;
6408
+ timeoutId = null;
6409
+ }, getDelay());
6410
+ }
6411
+ function reset() {
6412
+ if (timeoutId) {
6413
+ clearTimeout(timeoutId);
6414
+ timeoutId = null;
6415
+ }
6416
+ isPending.value = false;
6417
+ }
6418
+ function cancel() {
6419
+ if (timeoutId) {
6420
+ clearTimeout(timeoutId);
6421
+ timeoutId = null;
6422
+ }
6423
+ }
6424
+ vue.onUnmounted(() => {
6425
+ cancel();
6426
+ });
6427
+ return {
6428
+ isPending,
6429
+ click,
6430
+ reset,
6431
+ cancel
6432
+ };
6433
+ }
6434
+ function createDelayedClick(handler, delay = 300) {
6435
+ let isPending = false;
6436
+ return (event) => {
6437
+ if (isPending) {
6438
+ event.preventDefault();
6439
+ event.stopPropagation();
6440
+ return;
6441
+ }
6442
+ isPending = true;
6443
+ handler(event);
6444
+ setTimeout(() => {
6445
+ isPending = false;
6446
+ }, delay);
6447
+ };
6448
+ }
6449
+ function isValidClick(el, event, exclude) {
6450
+ const target = event.target;
6451
+ if (el.contains(target)) {
6452
+ return false;
6453
+ }
6454
+ if (exclude == null ? void 0 : exclude.length) {
6455
+ for (const item of exclude) {
6456
+ const excludeEl = typeof item === "function" ? item() : vue.unref(item);
6457
+ const resolved = typeof excludeEl === "string" ? getElement(excludeEl) : excludeEl;
6458
+ if (resolved && (resolved === target || resolved.contains(target))) {
6459
+ return false;
6460
+ }
6461
+ }
6462
+ }
6463
+ return true;
6464
+ }
6465
+ function useClickOutside(options) {
6466
+ const {
6467
+ handler,
6468
+ exclude = [],
6469
+ capture = true,
6470
+ events = ["click"],
6471
+ stop = false,
6472
+ prevent = false
6473
+ } = options;
6474
+ let currentElement = null;
6475
+ const handlers = /* @__PURE__ */ new Map();
6476
+ function createEventHandler(_eventType) {
6477
+ return (event) => {
6478
+ if (!currentElement) return;
6479
+ if (!isValidClick(currentElement, event, exclude)) {
6480
+ return;
6481
+ }
6482
+ if (stop) {
6483
+ event.stopPropagation();
6484
+ }
6485
+ if (prevent) {
6486
+ event.preventDefault();
6487
+ }
6488
+ handler(event);
6489
+ };
6490
+ }
6491
+ function bind(element) {
6492
+ if (!isBrowser()) return () => {
6493
+ };
6494
+ unbind();
6495
+ currentElement = element;
6496
+ events.forEach((eventType) => {
6497
+ const eventHandler = createEventHandler();
6498
+ handlers.set(eventType, eventHandler);
6499
+ document.addEventListener(eventType, eventHandler, {
6500
+ capture,
6501
+ passive: !prevent
6502
+ });
6503
+ });
6504
+ return unbind;
6505
+ }
6506
+ function unbind() {
6507
+ handlers.forEach((eventHandler, eventType) => {
6508
+ document.removeEventListener(eventType, eventHandler, { capture });
6509
+ });
6510
+ handlers.clear();
6511
+ currentElement = null;
6512
+ }
6513
+ vue.onUnmounted(() => {
6514
+ unbind();
6515
+ });
6516
+ return {
6517
+ bind
6518
+ };
6519
+ }
6520
+ function copyToClipboard(text) {
6521
+ return __async(this, null, function* () {
6522
+ if (supportsClipboard()) {
6523
+ try {
6524
+ yield navigator.clipboard.writeText(text);
6525
+ return true;
6526
+ } catch (e) {
6527
+ console.warn("[Directix] Clipboard API failed, falling back to execCommand");
6528
+ }
6529
+ }
6530
+ return copyWithExecCommand(text);
6531
+ });
6532
+ }
6533
+ function copyWithExecCommand(text) {
6534
+ if (!isBrowser()) return false;
6535
+ const textarea = document.createElement("textarea");
6536
+ textarea.value = text;
6537
+ textarea.style.cssText = `
6538
+ position: fixed;
6539
+ top: -9999px;
6540
+ left: -9999px;
6541
+ opacity: 0;
6542
+ pointer-events: none;
6543
+ `;
6544
+ document.body.appendChild(textarea);
6545
+ try {
6546
+ textarea.select();
6547
+ textarea.setSelectionRange(0, textarea.value.length);
6548
+ return document.execCommand("copy");
6549
+ } catch (e) {
6550
+ return false;
6551
+ } finally {
6552
+ document.body.removeChild(textarea);
6553
+ }
6554
+ }
6555
+ function useCopy(options = {}) {
6556
+ const {
6557
+ source,
6558
+ onSuccess,
6559
+ onError,
6560
+ copiedTimeout = 1500
6561
+ } = options;
6562
+ const copied = vue.ref(false);
6563
+ const error = vue.ref(null);
6564
+ const isSupported = supportsClipboard() || isBrowser();
6565
+ let timeoutId = null;
6566
+ function copy(text) {
6567
+ return __async(this, null, function* () {
6568
+ const value = text != null ? text : vue.unref(source);
6569
+ if (!value) {
6570
+ console.warn("[Directix] useCopy: No text to copy");
6571
+ return false;
6572
+ }
6573
+ if (timeoutId) {
6574
+ clearTimeout(timeoutId);
6575
+ timeoutId = null;
6576
+ }
6577
+ error.value = null;
6578
+ try {
6579
+ const success = yield copyToClipboard(value);
6580
+ if (success) {
6581
+ copied.value = true;
6582
+ onSuccess == null ? void 0 : onSuccess(value);
6583
+ timeoutId = setTimeout(() => {
6584
+ copied.value = false;
6585
+ timeoutId = null;
6586
+ }, copiedTimeout);
6587
+ return true;
6588
+ } else {
6589
+ throw new Error("Copy failed");
6590
+ }
6591
+ } catch (err) {
6592
+ const copyError = err;
6593
+ error.value = copyError;
6594
+ copied.value = false;
6595
+ onError == null ? void 0 : onError(copyError);
6596
+ return false;
6597
+ }
6598
+ });
6599
+ }
6600
+ return {
6601
+ copy,
6602
+ copied: vue.readonly(copied),
6603
+ error: vue.readonly(error),
6604
+ isSupported
6605
+ };
6606
+ }
6607
+ function parseTargetTime(target) {
6608
+ if (target instanceof Date) {
6609
+ return target.getTime();
6610
+ }
6611
+ if (typeof target === "number") {
6612
+ return target;
6613
+ }
6614
+ return new Date(target).getTime();
6615
+ }
6616
+ function calculateTime(remaining) {
6617
+ const total = Math.max(0, remaining);
6618
+ return {
6619
+ days: Math.floor(total / (1e3 * 60 * 60 * 24)),
6620
+ hours: Math.floor(total % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60)),
6621
+ minutes: Math.floor(total % (1e3 * 60 * 60) / (1e3 * 60)),
6622
+ seconds: Math.floor(total % (1e3 * 60) / 1e3),
6623
+ milliseconds: total % 1e3,
6624
+ total
6625
+ };
6626
+ }
6627
+ function formatTime(time, format) {
6628
+ if (typeof format === "function") {
6629
+ return format(time);
6630
+ }
6631
+ const pad = (n, len = 2) => String(n).padStart(len, "0");
6632
+ const result = format.replace(/dd/gi, pad(time.days)).replace(/hh/gi, pad(time.hours)).replace(/mm/gi, pad(time.minutes)).replace(/ss/gi, pad(time.seconds)).replace(/S{3}/gi, pad(time.milliseconds, 3)).replace(/SS/gi, pad(Math.floor(time.milliseconds / 10))).replace(/S/gi, String(Math.floor(time.milliseconds / 100)));
6633
+ return result;
6634
+ }
6635
+ function useCountdown(options) {
6636
+ const {
6637
+ target,
6638
+ format = "hh:mm:ss",
6639
+ onComplete,
6640
+ onTick,
6641
+ interval = 1e3,
6642
+ autoStart = true
6643
+ } = options;
6644
+ const time = vue.ref(calculateTime(0));
6645
+ const formatted = vue.ref("");
6646
+ const running = vue.ref(false);
6647
+ const paused = vue.ref(false);
6648
+ const completed = vue.ref(false);
6649
+ let intervalId = null, targetTime = 0, remainingWhenPaused = 0;
6650
+ const getInterval = () => vue.unref(interval);
6651
+ const getFormat = () => vue.unref(format);
6652
+ function update() {
6653
+ const now = Date.now();
6654
+ const remaining = targetTime - now;
6655
+ if (remaining <= 0) {
6656
+ time.value = calculateTime(0);
6657
+ formatted.value = formatTime(time.value, getFormat());
6658
+ completed.value = true;
6659
+ running.value = false;
6660
+ stop();
6661
+ if (onComplete) {
6662
+ onComplete();
6663
+ }
6664
+ return;
6665
+ }
6666
+ time.value = calculateTime(remaining);
6667
+ formatted.value = formatTime(time.value, getFormat());
6668
+ if (onTick) {
6669
+ onTick(time.value);
6670
+ }
6671
+ }
6672
+ function start() {
6673
+ if (running.value) return;
6674
+ targetTime = parseTargetTime(vue.unref(target));
6675
+ running.value = true;
6676
+ paused.value = false;
6677
+ completed.value = false;
6678
+ update();
6679
+ intervalId = setInterval(update, getInterval());
6680
+ }
6681
+ function stop() {
6682
+ if (intervalId) {
6683
+ clearInterval(intervalId);
6684
+ intervalId = null;
6685
+ }
6686
+ running.value = false;
6687
+ }
6688
+ function pause() {
6689
+ if (!running.value) return;
6690
+ remainingWhenPaused = targetTime - Date.now();
6691
+ stop();
6692
+ paused.value = true;
6693
+ }
6694
+ function resume() {
6695
+ if (running.value || !paused.value) return;
6696
+ targetTime = Date.now() + remainingWhenPaused;
6697
+ running.value = true;
6698
+ paused.value = false;
6699
+ update();
6700
+ intervalId = setInterval(update, getInterval());
6701
+ }
6702
+ function reset() {
6703
+ stop();
6704
+ paused.value = false;
6705
+ completed.value = false;
6706
+ remainingWhenPaused = 0;
6707
+ time.value = calculateTime(0);
6708
+ formatted.value = formatTime(time.value, getFormat());
6709
+ }
6710
+ vue.watch(
6711
+ () => vue.unref(target),
6712
+ (newTarget) => {
6713
+ if (running.value) {
6714
+ targetTime = parseTargetTime(newTarget);
6715
+ }
6716
+ }
6717
+ );
6718
+ if (vue.unref(autoStart)) {
6719
+ start();
6720
+ }
6721
+ vue.onUnmounted(() => {
6722
+ stop();
6723
+ });
6724
+ return {
6725
+ time,
6726
+ formatted,
6727
+ running,
6728
+ paused,
6729
+ completed,
6730
+ start,
6731
+ pause,
6732
+ resume,
6733
+ reset
6734
+ };
6735
+ }
6736
+ function useDebounce(options) {
6737
+ const {
6738
+ handler,
6739
+ wait = 300,
6740
+ leading = false,
6741
+ trailing = true
6742
+ } = options;
6743
+ let timerId = null, lastArgs = null, lastThis = null;
6744
+ const invokeFunc = () => {
6745
+ if (lastArgs) {
6746
+ handler.apply(lastThis, lastArgs);
6747
+ lastArgs = null;
6748
+ lastThis = null;
6749
+ }
6750
+ };
6751
+ const getWait = () => vue.unref(wait);
6752
+ const getLeading = () => vue.unref(leading);
6753
+ const getTrailing = () => vue.unref(trailing);
6754
+ function run(...args) {
6755
+ lastArgs = args;
6756
+ lastThis = this;
6757
+ if (timerId) {
6758
+ clearTimeout(timerId);
6759
+ }
6760
+ if (getLeading() && !timerId) {
6761
+ invokeFunc();
6762
+ }
6763
+ timerId = setTimeout(() => {
6764
+ if (getTrailing()) {
6765
+ invokeFunc();
6766
+ }
6767
+ timerId = null;
6768
+ }, getWait());
6769
+ }
6770
+ function cancel() {
6771
+ if (timerId) {
6772
+ clearTimeout(timerId);
6773
+ timerId = null;
6774
+ }
6775
+ lastArgs = null;
6776
+ lastThis = null;
6777
+ }
6778
+ function flush() {
6779
+ if (timerId) {
6780
+ clearTimeout(timerId);
6781
+ invokeFunc();
6782
+ timerId = null;
6783
+ }
6784
+ }
6785
+ function pending() {
6786
+ return timerId !== null;
6787
+ }
6788
+ vue.onUnmounted(() => {
6789
+ cancel();
6790
+ });
6791
+ return {
6792
+ run,
6793
+ cancel,
6794
+ flush,
6795
+ pending
6796
+ };
6797
+ }
6798
+ function debounceFn(fn, wait = 300, options) {
6799
+ return debounce(fn, wait, options);
6800
+ }
6801
+ function getBoundary(boundary) {
6802
+ var _a, _b;
6803
+ if (!boundary) return null;
6804
+ if (typeof boundary === "function") {
6805
+ const boundaryEl = boundary();
6806
+ return (_a = boundaryEl == null ? void 0 : boundaryEl.getBoundingClientRect()) != null ? _a : null;
6807
+ }
6808
+ if (typeof boundary === "string") {
6809
+ const boundaryEl = document.querySelector(boundary);
6810
+ return (_b = boundaryEl == null ? void 0 : boundaryEl.getBoundingClientRect()) != null ? _b : null;
6811
+ }
6812
+ return boundary.getBoundingClientRect();
6813
+ }
6814
+ function getClientCoords(e) {
6815
+ if (e.type.startsWith("touch")) {
6816
+ const touch = e.touches[0] || e.changedTouches[0];
6817
+ return { clientX: touch.clientX, clientY: touch.clientY };
6818
+ }
6819
+ const mouseEvent = e;
6820
+ return { clientX: mouseEvent.clientX, clientY: mouseEvent.clientY };
6821
+ }
6822
+ function parseTranslate(transform) {
6823
+ const match = transform.match(/translate\(([-\d.]+)px,\s*([-\d.]+)px\)/);
6824
+ if (match) {
6825
+ return { x: parseFloat(match[1]), y: parseFloat(match[2]) };
6826
+ }
6827
+ return { x: 0, y: 0 };
6828
+ }
6829
+ function useDraggable(options = {}) {
6830
+ const {
6831
+ axis = "both",
6832
+ constrain = false,
6833
+ boundary,
6834
+ handle,
6835
+ grid,
6836
+ disabled = false,
6837
+ onStart,
6838
+ onDrag,
6839
+ onEnd
6840
+ } = options;
6841
+ const position = vue.ref({ x: 0, y: 0 });
6842
+ const isDragging = vue.ref(false);
6843
+ let currentElement = null, handleEl = null, startX = 0, startY = 0, offsetX = 0, offsetY = 0, initialLeft = 0, initialTop = 0, boundaryWidth = 0, boundaryHeight = 0, elWidth = 0, elHeight = 0;
6844
+ function startDrag(e) {
6845
+ var _a;
6846
+ if (vue.unref(disabled)) return;
6847
+ e.preventDefault();
6848
+ const { clientX, clientY } = getClientCoords(e);
6849
+ isDragging.value = true;
6850
+ startX = clientX;
6851
+ startY = clientY;
6852
+ const { x, y } = parseTranslate(currentElement.style.transform);
6853
+ offsetX = x;
6854
+ offsetY = y;
6855
+ if (vue.unref(constrain) || boundary) {
6856
+ const boundaryRect = boundary ? getBoundary(boundary) : (_a = currentElement.parentElement) == null ? void 0 : _a.getBoundingClientRect();
6857
+ if (boundaryRect) {
6858
+ const elRect = currentElement.getBoundingClientRect();
6859
+ initialLeft = elRect.left - boundaryRect.left;
6860
+ initialTop = elRect.top - boundaryRect.top;
6861
+ boundaryWidth = boundaryRect.width;
6862
+ boundaryHeight = boundaryRect.height;
6863
+ elWidth = elRect.width;
6864
+ elHeight = elRect.height;
6865
+ }
6866
+ }
6867
+ currentElement.classList.add("v-draggable--dragging");
6868
+ document.addEventListener("mousemove", handleDrag);
6869
+ document.addEventListener("mouseup", endDrag);
6870
+ document.addEventListener("touchmove", handleDrag, { passive: false });
6871
+ document.addEventListener("touchend", endDrag);
6872
+ onStart == null ? void 0 : onStart({ x: offsetX, y: offsetY }, e);
6873
+ }
6874
+ function handleDrag(e) {
6875
+ if (!isDragging.value || vue.unref(disabled)) return;
6876
+ e.preventDefault();
6877
+ const { clientX, clientY } = getClientCoords(e);
6878
+ let deltaX = clientX - startX, deltaY = clientY - startY, newX = offsetX + deltaX, newY = offsetY + deltaY;
6879
+ const currentAxis = vue.unref(axis);
6880
+ if (currentAxis === "x") {
6881
+ deltaY = 0;
6882
+ } else if (currentAxis === "y") {
6883
+ deltaX = 0;
6884
+ }
6885
+ const currentGrid = vue.unref(grid);
6886
+ if (currentGrid) {
6887
+ deltaX = Math.round(deltaX / currentGrid[0]) * currentGrid[0];
6888
+ deltaY = Math.round(deltaY / currentGrid[1]) * currentGrid[1];
6889
+ }
6890
+ if (vue.unref(constrain) || boundary) {
6891
+ const newLeft = initialLeft + deltaX;
6892
+ const newTop = initialTop + deltaY;
6893
+ const maxLeft = boundaryWidth - elWidth;
6894
+ const maxTop = boundaryHeight - elHeight;
6895
+ const constrainedLeft = Math.max(0, Math.min(newLeft, maxLeft));
6896
+ const constrainedTop = Math.max(0, Math.min(newTop, maxTop));
6897
+ newX = offsetX + (constrainedLeft - initialLeft);
6898
+ newY = offsetY + (constrainedTop - initialTop);
6899
+ }
6900
+ currentElement.style.transform = `translate(${newX}px, ${newY}px)`;
6901
+ position.value = { x: newX, y: newY };
6902
+ onDrag == null ? void 0 : onDrag({ x: newX, y: newY }, e);
6903
+ }
6904
+ function endDrag(e) {
6905
+ if (!isDragging.value) return;
6906
+ isDragging.value = false;
6907
+ currentElement == null ? void 0 : currentElement.classList.remove("v-draggable--dragging");
6908
+ document.removeEventListener("mousemove", handleDrag);
6909
+ document.removeEventListener("mouseup", endDrag);
6910
+ document.removeEventListener("touchmove", handleDrag);
6911
+ document.removeEventListener("touchend", endDrag);
6912
+ onEnd == null ? void 0 : onEnd(__spreadValues({}, position.value), e);
6913
+ }
6914
+ function reset() {
6915
+ if (currentElement) {
6916
+ currentElement.style.transform = "translate(0px, 0px)";
6917
+ position.value = { x: 0, y: 0 };
6918
+ }
6919
+ }
6920
+ function bind(element) {
6921
+ if (!isBrowser()) return () => {
6922
+ };
6923
+ unbind();
6924
+ currentElement = element;
6925
+ if (getComputedStyle(element).position === "static") {
6926
+ element.style.position = "absolute";
6927
+ }
6928
+ handleEl = handle ? element.querySelector(handle) : null;
6929
+ const target = handleEl || element;
6930
+ target.addEventListener("mousedown", startDrag);
6931
+ target.addEventListener("touchstart", startDrag, { passive: false });
6932
+ return unbind;
6933
+ }
6934
+ function unbind() {
6935
+ if (currentElement) {
6936
+ const target = handleEl || currentElement;
6937
+ target.removeEventListener("mousedown", startDrag);
6938
+ target.removeEventListener("touchstart", startDrag);
6939
+ }
6940
+ currentElement = null;
6941
+ handleEl = null;
6942
+ }
6943
+ vue.onUnmounted(() => {
6944
+ unbind();
6945
+ });
6946
+ return {
6947
+ position: vue.readonly(position),
6948
+ isDragging: vue.readonly(isDragging),
6949
+ reset,
6950
+ bind
6951
+ };
6952
+ }
6953
+ function measureTextWidth(text, fontSize = 14, fontFamily = "sans-serif") {
6954
+ if (typeof document === "undefined") return text.length * 8;
6955
+ const canvas = document.createElement("canvas");
6956
+ const ctx = canvas.getContext("2d");
6957
+ if (!ctx) return text.length * 8;
6958
+ ctx.font = `${fontSize}px ${fontFamily}`;
6959
+ return ctx.measureText(text).width;
6960
+ }
6961
+ function truncateToWidth(text, maxWidth, ellipsis = "...", fontSize = 14, fontFamily = "sans-serif") {
6962
+ if (maxWidth <= 0) return text;
6963
+ const textWidth = measureTextWidth(text, fontSize, fontFamily);
6964
+ if (textWidth <= maxWidth) return text;
6965
+ const ellipsisWidth = measureTextWidth(ellipsis, fontSize, fontFamily);
6966
+ const availableWidth = maxWidth - ellipsisWidth;
6967
+ if (availableWidth <= 0) return ellipsis;
6968
+ let low = 0, high = text.length;
6969
+ while (low < high) {
6970
+ const mid = Math.floor((low + high + 1) / 2);
6971
+ const truncatedText = text.slice(0, mid);
6972
+ const truncatedWidth = measureTextWidth(truncatedText, fontSize, fontFamily);
6973
+ if (truncatedWidth <= availableWidth) {
6974
+ low = mid;
6975
+ } else {
6976
+ high = mid - 1;
6977
+ }
6978
+ }
6979
+ return text.slice(0, low) + ellipsis;
6980
+ }
6981
+ function truncateToLines(text, lines, ellipsis = "...") {
6982
+ if (lines <= 0) return "";
6983
+ const avgCharsPerLine = 80;
6984
+ const maxChars = lines * avgCharsPerLine;
6985
+ if (text.length <= maxChars) return text;
6986
+ return text.slice(0, maxChars - ellipsis.length) + ellipsis;
6987
+ }
6988
+ function useEllipsis(options) {
6989
+ const {
6990
+ text,
6991
+ lines = 1,
6992
+ ellipsis = "...",
6993
+ maxWidth = 0
6994
+ } = options;
6995
+ const original = vue.ref(vue.unref(text));
6996
+ const truncated = vue.ref("");
6997
+ const isTruncated = vue.ref(false);
6998
+ function calculate() {
6999
+ const textValue = vue.unref(text);
7000
+ const linesValue = vue.unref(lines);
7001
+ const ellipsisValue = vue.unref(ellipsis);
7002
+ const maxWidthValue = vue.unref(maxWidth);
7003
+ original.value = textValue;
7004
+ if (!textValue) {
7005
+ truncated.value = "";
7006
+ isTruncated.value = false;
7007
+ return;
7008
+ }
7009
+ if (maxWidthValue > 0) {
7010
+ const result = truncateToWidth(textValue, maxWidthValue, ellipsisValue);
7011
+ truncated.value = result;
7012
+ isTruncated.value = result !== textValue;
7013
+ } else if (linesValue > 1) {
7014
+ const result = truncateToLines(textValue, linesValue, ellipsisValue);
7015
+ truncated.value = result;
7016
+ isTruncated.value = result !== textValue;
7017
+ } else {
7018
+ truncated.value = textValue;
7019
+ isTruncated.value = false;
7020
+ }
7021
+ }
7022
+ function calculateForWidth(width) {
7023
+ const textValue = vue.unref(text);
7024
+ const ellipsisValue = vue.unref(ellipsis);
7025
+ if (!textValue || width <= 0) return textValue || "";
7026
+ return truncateToWidth(textValue, width, ellipsisValue);
7027
+ }
7028
+ function wouldTruncate(width) {
7029
+ const textValue = vue.unref(text);
7030
+ if (!textValue || width <= 0) return false;
7031
+ const textWidth = measureTextWidth(textValue);
7032
+ return textWidth > width;
7033
+ }
7034
+ vue.watch(
7035
+ () => [vue.unref(text), vue.unref(lines), vue.unref(ellipsis), vue.unref(maxWidth)],
7036
+ () => calculate(),
7037
+ { immediate: true }
7038
+ );
7039
+ vue.onUnmounted(() => {
7040
+ });
7041
+ return {
7042
+ truncated,
7043
+ isTruncated,
7044
+ original,
7045
+ calculateForWidth,
7046
+ wouldTruncate
7047
+ };
7048
+ }
7049
+ function truncateText(text, maxLength, ellipsis = "...") {
7050
+ if (!text || text.length <= maxLength) return text;
7051
+ return text.slice(0, maxLength - ellipsis.length) + ellipsis;
7052
+ }
7053
+ function wouldTextTruncate(text, containerWidth, fontSize = 14) {
7054
+ return measureTextWidth(text, fontSize) > containerWidth;
7055
+ }
7056
+ const FOCUSABLE_TAGS = /* @__PURE__ */ new Set(["input", "textarea", "select", "button"]);
7057
+ function isFocusable(el) {
7058
+ if (!isBrowser()) return false;
7059
+ const tagName = el.tagName.toLowerCase();
7060
+ if (FOCUSABLE_TAGS.has(tagName)) {
7061
+ return !el.disabled;
7062
+ }
7063
+ if (el.isContentEditable) return true;
7064
+ const tabindex = el.getAttribute("tabindex");
7065
+ if (tabindex != null) return tabindex !== "-1";
7066
+ if (tagName === "a" || tagName === "area") {
7067
+ return el.hasAttribute("href");
7068
+ }
7069
+ return false;
7070
+ }
7071
+ function useFocus(options = {}) {
7072
+ const { onFocus, onBlur } = options;
7073
+ const isFocused = vue.ref(false);
7074
+ let currentElement = null, focusHandler = null, blurHandler = null;
7075
+ function focus() {
7076
+ if (currentElement && isFocusable(currentElement)) {
7077
+ currentElement.focus();
7078
+ }
7079
+ }
7080
+ function blur() {
7081
+ if (currentElement) {
7082
+ currentElement.blur();
7083
+ }
7084
+ }
7085
+ function bind(element) {
7086
+ if (!isBrowser()) return () => {
7087
+ };
7088
+ unbind();
7089
+ currentElement = element;
7090
+ focusHandler = (e) => {
7091
+ isFocused.value = true;
7092
+ onFocus == null ? void 0 : onFocus(e);
7093
+ };
7094
+ blurHandler = (e) => {
7095
+ isFocused.value = false;
7096
+ onBlur == null ? void 0 : onBlur(e);
7097
+ };
7098
+ element.addEventListener("focus", focusHandler);
7099
+ element.addEventListener("blur", blurHandler);
7100
+ isFocused.value = document.activeElement === element;
7101
+ return unbind;
7102
+ }
7103
+ function unbind() {
7104
+ if (currentElement) {
7105
+ if (focusHandler) {
7106
+ currentElement.removeEventListener("focus", focusHandler);
7107
+ }
7108
+ if (blurHandler) {
7109
+ currentElement.removeEventListener("blur", blurHandler);
7110
+ }
7111
+ }
7112
+ currentElement = null;
7113
+ focusHandler = null;
7114
+ blurHandler = null;
7115
+ isFocused.value = false;
7116
+ }
7117
+ vue.onUnmounted(() => {
7118
+ unbind();
7119
+ });
7120
+ return {
7121
+ isFocused: vue.readonly(isFocused),
7122
+ focus,
7123
+ blur,
7124
+ bind
7125
+ };
7126
+ }
7127
+ const KEY_ALIASES = {
7128
+ esc: "Escape",
7129
+ space: " ",
7130
+ up: "ArrowUp",
7131
+ down: "ArrowDown",
7132
+ left: "ArrowLeft",
7133
+ right: "ArrowRight",
7134
+ enter: "Enter",
7135
+ tab: "Tab",
7136
+ backspace: "Backspace",
7137
+ delete: "Delete",
7138
+ insert: "Insert",
7139
+ home: "Home",
7140
+ end: "End",
7141
+ pageup: "PageUp",
7142
+ pagedown: "PageDown",
7143
+ plus: "+",
7144
+ minus: "-"
7145
+ };
7146
+ const MODIFIERS = /* @__PURE__ */ new Set(["ctrl", "alt", "shift", "meta"]);
7147
+ function parseHotkey(hotkey) {
7148
+ const parts = hotkey.toLowerCase().split("+").map((p) => p.trim());
7149
+ const modifiers = /* @__PURE__ */ new Set();
7150
+ let key = "";
7151
+ for (const part of parts) {
7152
+ if (MODIFIERS.has(part)) {
7153
+ modifiers.add(part);
7154
+ } else {
7155
+ key = KEY_ALIASES[part] || part;
7156
+ }
7157
+ }
7158
+ return { key, modifiers };
7159
+ }
7160
+ function matchesHotkey(event, definition) {
7161
+ if (definition.modifiers.has("ctrl") !== (event.ctrlKey || event.metaKey)) return false;
7162
+ if (definition.modifiers.has("alt") !== event.altKey) return false;
7163
+ if (definition.modifiers.has("shift") !== event.shiftKey) return false;
7164
+ if (definition.modifiers.has("meta") !== event.metaKey) return false;
7165
+ const eventKey = event.key;
7166
+ const targetKey = definition.key;
7167
+ return eventKey.toLowerCase() === targetKey.toLowerCase();
7168
+ }
7169
+ function useHotkey(options = {}) {
7170
+ const {
7171
+ hotkey,
7172
+ hotkeys = [],
7173
+ target,
7174
+ enabled: initialEnabled = true
7175
+ } = options;
7176
+ const enabled = vue.ref(vue.unref(initialEnabled));
7177
+ const hotkeyMap = /* @__PURE__ */ new Map();
7178
+ let currentTarget = null, keydownHandler = null, keyupHandler = null;
7179
+ if (hotkey) {
7180
+ addHotkey(hotkey);
7181
+ }
7182
+ hotkeys.forEach(addHotkey);
7183
+ function addHotkey(def) {
7184
+ const parsed = parseHotkey(def.key);
7185
+ const key = parsed.key.toLowerCase();
7186
+ if (!hotkeyMap.has(key)) {
7187
+ hotkeyMap.set(key, []);
7188
+ }
7189
+ hotkeyMap.get(key).push(def);
7190
+ }
7191
+ function removeHotkey(key) {
7192
+ hotkeyMap.delete(key.toLowerCase());
7193
+ }
7194
+ function clearHotkeys() {
7195
+ hotkeyMap.clear();
7196
+ }
7197
+ function handleKeyEvent(event, isKeyup) {
7198
+ if (!enabled.value) return;
7199
+ const key = event.key.toLowerCase();
7200
+ const definitions = hotkeyMap.get(key);
7201
+ if (!definitions) return;
7202
+ for (const def of definitions) {
7203
+ if (vue.unref(def.disabled)) continue;
7204
+ if (!!def.keyup !== isKeyup) continue;
7205
+ const parsed = parseHotkey(def.key);
7206
+ if (matchesHotkey(event, parsed)) {
7207
+ if (def.prevent !== false) {
7208
+ event.preventDefault();
7209
+ }
7210
+ if (def.stop) {
7211
+ event.stopPropagation();
7212
+ }
7213
+ def.handler(event);
7214
+ break;
7215
+ }
7216
+ }
7217
+ }
7218
+ function bind() {
7219
+ if (!isBrowser()) return;
7220
+ unbind();
7221
+ currentTarget = target ? vue.unref(target) : document;
7222
+ keydownHandler = (e) => handleKeyEvent(e, false);
7223
+ keyupHandler = (e) => handleKeyEvent(e, true);
7224
+ currentTarget == null ? void 0 : currentTarget.addEventListener("keydown", keydownHandler);
7225
+ currentTarget == null ? void 0 : currentTarget.addEventListener("keyup", keyupHandler);
7226
+ }
7227
+ function unbind() {
7228
+ if (currentTarget) {
7229
+ if (keydownHandler) {
7230
+ currentTarget.removeEventListener("keydown", keydownHandler);
7231
+ }
7232
+ if (keyupHandler) {
7233
+ currentTarget.removeEventListener("keyup", keyupHandler);
7234
+ }
7235
+ }
7236
+ currentTarget = null;
7237
+ keydownHandler = null;
7238
+ keyupHandler = null;
7239
+ }
7240
+ function enable() {
7241
+ enabled.value = true;
7242
+ }
7243
+ function disable() {
7244
+ enabled.value = false;
7245
+ }
7246
+ function toggle() {
7247
+ enabled.value = !enabled.value;
7248
+ }
7249
+ vue.watch(enabled, (newEnabled) => {
7250
+ if (newEnabled) {
7251
+ bind();
7252
+ } else {
7253
+ unbind();
7254
+ }
7255
+ });
7256
+ if (target && typeof target === "object" && "value" in target) {
7257
+ vue.watch(target, () => {
7258
+ if (enabled.value) {
7259
+ bind();
7260
+ }
7261
+ });
7262
+ }
7263
+ if (enabled.value) {
7264
+ bind();
7265
+ }
7266
+ vue.onUnmounted(() => {
7267
+ unbind();
7268
+ });
7269
+ return {
7270
+ enabled,
7271
+ enable,
7272
+ disable,
7273
+ toggle,
7274
+ add: addHotkey,
7275
+ remove: removeHotkey,
7276
+ clear: clearHotkeys
7277
+ };
7278
+ }
7279
+ function useHover(options = {}) {
7280
+ const {
7281
+ onEnter,
7282
+ onLeave,
7283
+ class: hoverClass,
7284
+ enterDelay = 0,
7285
+ leaveDelay = 0
7286
+ } = options;
7287
+ const isHovering = vue.ref(false);
7288
+ let enterTimerId = null, leaveTimerId = null, currentElement = null;
7289
+ function clearTimers() {
7290
+ if (enterTimerId) {
7291
+ clearTimeout(enterTimerId);
7292
+ enterTimerId = null;
7293
+ }
7294
+ if (leaveTimerId) {
7295
+ clearTimeout(leaveTimerId);
7296
+ leaveTimerId = null;
7297
+ }
7298
+ }
7299
+ function handleMouseEnter(event) {
7300
+ if (leaveTimerId) {
7301
+ clearTimeout(leaveTimerId);
7302
+ leaveTimerId = null;
7303
+ }
7304
+ if (isHovering.value) return;
7305
+ const delay = vue.unref(enterDelay);
7306
+ if (delay && delay > 0) {
7307
+ enterTimerId = setTimeout(() => {
7308
+ isHovering.value = true;
7309
+ applyHoverState2();
7310
+ onEnter == null ? void 0 : onEnter(event);
7311
+ enterTimerId = null;
7312
+ }, delay);
7313
+ } else {
7314
+ isHovering.value = true;
7315
+ applyHoverState2();
7316
+ onEnter == null ? void 0 : onEnter(event);
7317
+ }
7318
+ }
7319
+ function handleMouseLeave(event) {
7320
+ if (enterTimerId) {
7321
+ clearTimeout(enterTimerId);
7322
+ enterTimerId = null;
7323
+ }
7324
+ if (!isHovering.value) return;
7325
+ const delay = vue.unref(leaveDelay);
7326
+ if (delay && delay > 0) {
7327
+ leaveTimerId = setTimeout(() => {
7328
+ isHovering.value = false;
7329
+ removeHoverState();
7330
+ onLeave == null ? void 0 : onLeave(event);
7331
+ leaveTimerId = null;
7332
+ }, delay);
7333
+ } else {
7334
+ isHovering.value = false;
7335
+ removeHoverState();
7336
+ onLeave == null ? void 0 : onLeave(event);
7337
+ }
7338
+ }
7339
+ function applyHoverState2() {
7340
+ if (currentElement && hoverClass) {
7341
+ currentElement.classList.add(hoverClass);
7342
+ }
7343
+ }
7344
+ function removeHoverState() {
7345
+ if (currentElement && hoverClass) {
7346
+ currentElement.classList.remove(hoverClass);
7347
+ }
7348
+ }
7349
+ function bind(element) {
7350
+ if (!isBrowser()) return () => {
7351
+ };
7352
+ currentElement = element;
7353
+ element.addEventListener("mouseenter", handleMouseEnter);
7354
+ element.addEventListener("mouseleave", handleMouseLeave);
7355
+ return () => {
7356
+ element.removeEventListener("mouseenter", handleMouseEnter);
7357
+ element.removeEventListener("mouseleave", handleMouseLeave);
7358
+ clearTimers();
7359
+ removeHoverState();
7360
+ currentElement = null;
7361
+ };
7362
+ }
7363
+ vue.onUnmounted(() => {
7364
+ clearTimers();
7365
+ removeHoverState();
7366
+ });
7367
+ return {
7368
+ isHovering,
7369
+ bind
7370
+ };
7371
+ }
7372
+ function useImagePreview(options = {}) {
7373
+ const {
7374
+ src: initialSrc,
7375
+ closeOnClickOutside = true,
7376
+ closeOnEsc = true,
7377
+ showCloseButton = true,
7378
+ onOpen,
7379
+ onClose
7380
+ } = options;
7381
+ const isOpen = vue.ref(false);
7382
+ const currentSrc = vue.ref("");
7383
+ let currentElement = null, overlay = null, clickHandler = null, keydownHandler = null;
7384
+ function createOverlay2() {
7385
+ const div = document.createElement("div");
7386
+ div.className = "v-image-preview";
7387
+ div.style.cssText = `
7388
+ position: fixed;
7389
+ top: 0;
7390
+ left: 0;
7391
+ right: 0;
7392
+ bottom: 0;
7393
+ z-index: 9999;
7394
+ background: rgba(0, 0, 0, 0.9);
7395
+ display: flex;
7396
+ align-items: center;
7397
+ justify-content: center;
7398
+ cursor: zoom-out;
7399
+ `;
7400
+ return div;
7401
+ }
7402
+ function open(src) {
7403
+ if (!isBrowser()) return;
7404
+ const imageSrc = src || (initialSrc && typeof initialSrc === "object" ? initialSrc.value : initialSrc);
7405
+ if (!imageSrc && !currentElement) return;
7406
+ const finalSrc = imageSrc || currentElement.src;
7407
+ currentSrc.value = finalSrc;
7408
+ overlay = createOverlay2();
7409
+ const img = document.createElement("img");
7410
+ img.src = finalSrc;
7411
+ img.style.cssText = `
7412
+ max-width: 90%;
7413
+ max-height: 90%;
7414
+ object-fit: contain;
7415
+ cursor: default;
7416
+ `;
7417
+ if (showCloseButton) {
7418
+ const closeBtn = document.createElement("button");
7419
+ closeBtn.className = "v-image-preview__close";
7420
+ closeBtn.innerHTML = "&times;";
7421
+ closeBtn.style.cssText = `
7422
+ position: absolute;
7423
+ top: 20px;
7424
+ right: 20px;
7425
+ width: 40px;
7426
+ height: 40px;
7427
+ border: none;
7428
+ background: rgba(255, 255, 255, 0.2);
7429
+ color: white;
7430
+ font-size: 24px;
7431
+ cursor: pointer;
7432
+ border-radius: 50%;
7433
+ display: flex;
7434
+ align-items: center;
7435
+ justify-content: center;
7436
+ `;
7437
+ closeBtn.addEventListener("click", (e) => {
7438
+ e.stopPropagation();
7439
+ close();
7440
+ });
7441
+ overlay.appendChild(closeBtn);
7442
+ }
7443
+ overlay.appendChild(img);
7444
+ document.body.appendChild(overlay);
7445
+ if (closeOnClickOutside) {
7446
+ clickHandler = close;
7447
+ overlay.addEventListener("click", clickHandler);
7448
+ }
7449
+ if (closeOnEsc) {
7450
+ keydownHandler = (e) => {
7451
+ if (e.key === "Escape") {
7452
+ close();
7453
+ }
7454
+ };
7455
+ document.addEventListener("keydown", keydownHandler);
7456
+ }
7457
+ isOpen.value = true;
7458
+ onOpen == null ? void 0 : onOpen();
7459
+ }
7460
+ function close() {
7461
+ if (overlay) {
7462
+ overlay.remove();
7463
+ overlay = null;
7464
+ }
7465
+ if (clickHandler) {
7466
+ document.removeEventListener("click", clickHandler);
7467
+ clickHandler = null;
7468
+ }
7469
+ if (keydownHandler) {
7470
+ document.removeEventListener("keydown", keydownHandler);
7471
+ keydownHandler = null;
7472
+ }
7473
+ isOpen.value = false;
7474
+ currentSrc.value = "";
7475
+ onClose == null ? void 0 : onClose();
7476
+ }
7477
+ function handleElementClick() {
7478
+ if (currentElement) {
7479
+ open(currentElement.src);
7480
+ }
7481
+ }
7482
+ function bind(element) {
7483
+ if (!isBrowser()) return () => {
7484
+ };
7485
+ unbind();
7486
+ currentElement = element;
7487
+ element.style.cursor = "zoom-in";
7488
+ element.addEventListener("click", handleElementClick);
7489
+ return unbind;
7490
+ }
7491
+ function unbind() {
7492
+ if (currentElement) {
7493
+ currentElement.style.cursor = "";
7494
+ currentElement.removeEventListener("click", handleElementClick);
7495
+ }
7496
+ currentElement = null;
7497
+ }
7498
+ vue.onUnmounted(() => {
7499
+ unbind();
7500
+ close();
7501
+ });
7502
+ return {
7503
+ isOpen: vue.readonly(isOpen),
7504
+ currentSrc: vue.readonly(currentSrc),
7505
+ open,
7506
+ close,
7507
+ bind
7508
+ };
7509
+ }
7510
+ function useIntersect(options = {}) {
7511
+ const {
7512
+ handler,
7513
+ onEnter,
7514
+ onLeave,
7515
+ onChange,
7516
+ root = null,
7517
+ rootMargin = "0px",
7518
+ threshold = 0,
7519
+ once = false
7520
+ } = options;
7521
+ const isIntersecting = vue.ref(false);
7522
+ const ratio = vue.ref(0);
7523
+ let observer = null, hasTriggeredOnce = false;
7524
+ function createObserver2() {
7525
+ if (!isBrowser() || !supportsIntersectionObserver()) {
7526
+ console.warn("[Directix] useIntersect: IntersectionObserver not supported");
7527
+ return null;
7528
+ }
7529
+ return new IntersectionObserver(
7530
+ (entries) => {
7531
+ for (const entry of entries) {
7532
+ if (once && hasTriggeredOnce) continue;
7533
+ const intersecting = entry.isIntersecting;
7534
+ isIntersecting.value = intersecting;
7535
+ ratio.value = entry.intersectionRatio;
7536
+ handler == null ? void 0 : handler(entry, observer);
7537
+ onChange == null ? void 0 : onChange(intersecting, entry);
7538
+ if (intersecting) {
7539
+ onEnter == null ? void 0 : onEnter(entry, observer);
7540
+ if (once) hasTriggeredOnce = true;
7541
+ } else {
7542
+ onLeave == null ? void 0 : onLeave(entry, observer);
7543
+ }
7544
+ }
7545
+ },
7546
+ {
7547
+ root: vue.unref(root),
7548
+ rootMargin,
7549
+ threshold
7550
+ }
7551
+ );
7552
+ }
7553
+ function bind(element) {
7554
+ if (!isBrowser()) return () => {
7555
+ };
7556
+ stop();
7557
+ observer = createObserver2();
7558
+ if (observer) {
7559
+ observer.observe(element);
7560
+ }
7561
+ return stop;
7562
+ }
7563
+ function stop() {
7564
+ if (observer) {
7565
+ observer.disconnect();
7566
+ observer = null;
7567
+ }
7568
+ isIntersecting.value = false;
7569
+ ratio.value = 0;
7570
+ }
7571
+ vue.onUnmounted(() => {
7572
+ stop();
7573
+ });
7574
+ return {
7575
+ isIntersecting: vue.readonly(isIntersecting),
7576
+ ratio: vue.readonly(ratio),
7577
+ bind,
7578
+ stop
7579
+ };
7580
+ }
7581
+ function getEventPosition(e) {
7582
+ if ("touches" in e && e.touches.length > 0) {
7583
+ return {
7584
+ x: e.touches[0].clientX,
7585
+ y: e.touches[0].clientY
7586
+ };
7587
+ }
7588
+ if ("clientX" in e) {
7589
+ return {
7590
+ x: e.clientX,
7591
+ y: e.clientY
7592
+ };
7593
+ }
7594
+ return { x: 0, y: 0 };
7595
+ }
7596
+ function getDistance(p1, p2) {
7597
+ return Math.sqrt(__pow(p2.x - p1.x, 2) + __pow(p2.y - p1.y, 2));
7598
+ }
7599
+ function useLongPress(options = {}) {
7600
+ const {
7601
+ duration = 500,
7602
+ distance = 10,
7603
+ onStart,
7604
+ onTrigger,
7605
+ onCancel,
7606
+ onTick,
7607
+ tickInterval = 100,
7608
+ prevent = true
7609
+ } = options;
7610
+ const isPressing = vue.ref(false);
7611
+ let timerId = null, tickTimerId = null, startPos = { x: 0, y: 0 }, startPosSet = false;
7612
+ function start(event) {
7613
+ if (!isBrowser()) return;
7614
+ if (prevent) {
7615
+ event.preventDefault();
7616
+ }
7617
+ clearTimers();
7618
+ startPos = getEventPosition(event);
7619
+ startPosSet = true;
7620
+ isPressing.value = true;
7621
+ onStart == null ? void 0 : onStart(event);
7622
+ if (onTick) {
7623
+ let remaining = vue.unref(duration);
7624
+ tickTimerId = setInterval(() => {
7625
+ remaining -= tickInterval;
7626
+ onTick == null ? void 0 : onTick(Math.max(0, remaining));
7627
+ }, tickInterval);
7628
+ }
7629
+ timerId = setTimeout(() => {
7630
+ clearTimers();
7631
+ isPressing.value = false;
7632
+ onTrigger == null ? void 0 : onTrigger(event);
7633
+ }, vue.unref(duration));
7634
+ }
7635
+ function stop(event) {
7636
+ if (!isPressing.value) return;
7637
+ clearTimers();
7638
+ startPosSet = false;
7639
+ isPressing.value = false;
7640
+ onCancel == null ? void 0 : onCancel(event);
7641
+ }
7642
+ function handleMove(event) {
7643
+ if (!isPressing.value || !startPosSet) return;
7644
+ const pos = getEventPosition(event);
7645
+ const dist = getDistance(startPos, pos);
7646
+ if (dist > vue.unref(distance)) {
7647
+ stop(event);
7648
+ }
7649
+ }
7650
+ function clearTimers() {
7651
+ if (timerId) {
7652
+ clearTimeout(timerId);
7653
+ timerId = null;
7654
+ }
7655
+ if (tickTimerId) {
7656
+ clearInterval(tickTimerId);
7657
+ tickTimerId = null;
7658
+ }
7659
+ }
7660
+ function bind(element) {
7661
+ element.addEventListener("mousedown", start);
7662
+ element.addEventListener("mouseup", stop);
7663
+ element.addEventListener("mouseleave", stop);
7664
+ element.addEventListener("mousemove", handleMove);
7665
+ element.addEventListener("touchstart", start, { passive: !prevent });
7666
+ element.addEventListener("touchend", stop);
7667
+ element.addEventListener("touchcancel", stop);
7668
+ element.addEventListener("touchmove", handleMove, { passive: true });
7669
+ return () => {
7670
+ element.removeEventListener("mousedown", start);
7671
+ element.removeEventListener("mouseup", stop);
7672
+ element.removeEventListener("mouseleave", stop);
7673
+ element.removeEventListener("mousemove", handleMove);
7674
+ element.removeEventListener("touchstart", start);
7675
+ element.removeEventListener("touchend", stop);
7676
+ element.removeEventListener("touchcancel", stop);
7677
+ element.removeEventListener("touchmove", handleMove);
7678
+ clearTimers();
7679
+ };
7680
+ }
7681
+ vue.onUnmounted(() => {
7682
+ clearTimers();
7683
+ });
7684
+ return {
7685
+ isPressing,
7686
+ start,
7687
+ stop,
7688
+ bind
7689
+ };
7690
+ }
7691
+ function lowercaseText(text, firstOnly = false) {
7692
+ if (!text) return text;
7693
+ if (firstOnly) {
7694
+ return text.charAt(0).toLowerCase() + text.slice(1);
7695
+ }
7696
+ return text.toLowerCase();
7697
+ }
7698
+ function useLowercase(options) {
7699
+ const {
7700
+ text,
7701
+ first = false
7702
+ } = options;
7703
+ const original = vue.ref(vue.unref(text));
7704
+ const transformed = vue.ref("");
7705
+ function calculate() {
7706
+ const textValue = vue.unref(text);
7707
+ const firstValue = vue.unref(first);
7708
+ original.value = textValue;
7709
+ transformed.value = lowercaseText(textValue, firstValue);
7710
+ }
7711
+ vue.watch(
7712
+ () => [vue.unref(text), vue.unref(first)],
7713
+ () => calculate(),
7714
+ { immediate: true }
7715
+ );
7716
+ return {
7717
+ transformed,
7718
+ original
7719
+ };
7720
+ }
7721
+ function createLowercaser(first = false) {
7722
+ return (text) => lowercaseText(text, first);
7723
+ }
7724
+ function formatMoney(value, options = {}) {
7725
+ const {
7726
+ precision = 2,
7727
+ separator = ",",
7728
+ decimal = ".",
7729
+ symbol = "$",
7730
+ symbolPosition = "before"
7731
+ } = options;
7732
+ const fixed = value.toFixed(precision);
7733
+ const [intPart, decPart] = fixed.split(".");
7734
+ const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
7735
+ let result = formattedInt;
7736
+ if (precision > 0 && decPart) {
7737
+ result += decimal + decPart;
7738
+ }
7739
+ return symbolPosition === "before" ? symbol + result : result + symbol;
7740
+ }
7741
+ function parseMoney(formatted, options = {}) {
7742
+ const { decimal = ".", symbol = "$" } = options;
7743
+ let cleaned = formatted.replace(new RegExp(`[${symbol}\\s]`, "g"), "");
7744
+ if (decimal !== ".") {
7745
+ cleaned = cleaned.replace(/,/g, "");
7746
+ cleaned = cleaned.replace(new RegExp(`\\${decimal}`, "g"), ".");
7747
+ } else {
7748
+ cleaned = cleaned.replace(/,/g, "");
7749
+ }
7750
+ return parseFloat(cleaned) || 0;
7751
+ }
7752
+ function useMoney(options) {
7753
+ const {
7754
+ value,
7755
+ symbol = "$",
7756
+ symbolPosition = "before",
7757
+ precision = 2,
7758
+ separator = ",",
7759
+ decimal = "."
7760
+ } = options;
7761
+ const valueRef = vue.ref(vue.unref(value));
7762
+ function getFormatOptions() {
7763
+ return {
7764
+ precision: vue.unref(precision),
7765
+ separator: vue.unref(separator),
7766
+ decimal: vue.unref(decimal),
7767
+ symbol: vue.unref(symbol),
7768
+ symbolPosition: vue.unref(symbolPosition)
7769
+ };
7770
+ }
7771
+ const formatted = vue.computed(() => {
7772
+ return formatMoney(valueRef.value, getFormatOptions());
7773
+ });
7774
+ function parse(formattedString) {
7775
+ return parseMoney(formattedString, {
7776
+ decimal: vue.unref(decimal),
7777
+ symbol: vue.unref(symbol)
7778
+ });
7779
+ }
7780
+ vue.watch(
7781
+ () => vue.unref(value),
7782
+ (newValue) => {
7783
+ valueRef.value = newValue;
7784
+ }
7785
+ );
7786
+ return {
7787
+ value: valueRef,
7788
+ formatted,
7789
+ parse
7790
+ };
7791
+ }
7792
+ function createMoneyFormatter(options = {}) {
7793
+ return (value) => formatMoney(value, options);
7794
+ }
7795
+ function formatNumber(value, options = {}) {
7796
+ const {
7797
+ precision = 0,
7798
+ separator = ",",
7799
+ decimal = ".",
7800
+ prefix = "",
7801
+ suffix = ""
7802
+ } = options;
7803
+ const fixed = value.toFixed(precision);
7804
+ const [intPart, decPart] = fixed.split(".");
7805
+ const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
7806
+ let result = formattedInt;
7807
+ if (precision > 0 && decPart) {
7808
+ result += decimal + decPart;
7809
+ }
7810
+ return prefix + result + suffix;
7811
+ }
7812
+ function parseNumber(formatted, options = {}) {
7813
+ const { decimal = ".", prefix = "", suffix = "" } = options;
7814
+ let cleaned = formatted.replace(new RegExp(`^${escapeRegex$1(prefix)}`), "").replace(new RegExp(`${escapeRegex$1(suffix)}$`), "").replace(/\s/g, "");
7815
+ if (decimal !== ".") {
7816
+ cleaned = cleaned.replace(/,/g, "");
7817
+ cleaned = cleaned.replace(new RegExp(`\\${decimal}`, "g"), ".");
7818
+ } else {
7819
+ cleaned = cleaned.replace(/,/g, "");
7820
+ }
7821
+ return parseFloat(cleaned) || 0;
7822
+ }
7823
+ function escapeRegex$1(str) {
7824
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7825
+ }
7826
+ function useNumber(options) {
7827
+ const {
7828
+ value,
7829
+ precision = 0,
7830
+ separator = ",",
7831
+ decimal = ".",
7832
+ prefix = "",
7833
+ suffix = ""
7834
+ } = options;
7835
+ const valueRef = vue.ref(vue.unref(value));
7836
+ function getFormatOptions() {
7837
+ return {
7838
+ precision: vue.unref(precision),
7839
+ separator: vue.unref(separator),
7840
+ decimal: vue.unref(decimal),
7841
+ prefix: vue.unref(prefix),
7842
+ suffix: vue.unref(suffix)
7843
+ };
7844
+ }
7845
+ const formatted = vue.computed(() => {
7846
+ return formatNumber(valueRef.value, getFormatOptions());
7847
+ });
7848
+ function parse(formattedString) {
7849
+ return parseNumber(formattedString, {
7850
+ decimal: vue.unref(decimal),
7851
+ prefix: vue.unref(prefix),
7852
+ suffix: vue.unref(suffix)
7853
+ });
7854
+ }
7855
+ vue.watch(
7856
+ () => vue.unref(value),
7857
+ (newValue) => {
7858
+ valueRef.value = newValue;
7859
+ }
7860
+ );
7861
+ return {
7862
+ value: valueRef,
7863
+ formatted,
7864
+ parse
7865
+ };
7866
+ }
7867
+ function createNumberFormatter(options = {}) {
7868
+ return (value) => formatNumber(value, options);
7869
+ }
7870
+ const WILDCARD = "*";
7871
+ function hasPermission(required, permissions) {
7872
+ return permissions.includes(WILDCARD) || permissions.includes(required);
7873
+ }
7874
+ function usePermission(options) {
7875
+ const {
7876
+ value,
7877
+ mode = "some",
7878
+ check,
7879
+ getPermissions,
7880
+ getRoles,
7881
+ roleMap = {}
7882
+ } = options;
7883
+ const granted = vue.ref(false);
7884
+ function verifyPermission2() {
7885
+ if (check) {
7886
+ return check(vue.unref(value), vue.unref(mode));
7887
+ }
7888
+ if (!getPermissions) {
7889
+ console.warn("[Directix] usePermission: getPermissions function is required");
7890
+ return true;
7891
+ }
7892
+ const permissions = getPermissions();
7893
+ const roles = (getRoles == null ? void 0 : getRoles()) || [];
7894
+ const required = Array.isArray(vue.unref(value)) ? vue.unref(value) : [vue.unref(value)];
7895
+ const currentMode = vue.unref(mode);
7896
+ function checkSingle(perm) {
7897
+ if (perm in roleMap) {
7898
+ return roles.includes(perm);
7899
+ }
7900
+ if (hasPermission(perm, permissions)) {
7901
+ return true;
7902
+ }
7903
+ for (const role of roles) {
7904
+ const rolePermissions = roleMap[role] || [];
7905
+ if (hasPermission(perm, rolePermissions)) {
7906
+ return true;
7907
+ }
7908
+ }
7909
+ return false;
7910
+ }
7911
+ return currentMode === "every" ? required.every(checkSingle) : required.some(checkSingle);
7912
+ }
7913
+ function recheck() {
7914
+ granted.value = verifyPermission2();
7915
+ }
7916
+ vue.watch(
7917
+ () => vue.unref(value),
7918
+ () => recheck(),
7919
+ { immediate: true }
7920
+ );
7921
+ if (typeof mode === "object" && "value" in mode) {
7922
+ vue.watch(mode, () => recheck());
7923
+ }
7924
+ return {
7925
+ granted: vue.readonly(granted),
7926
+ recheck
7927
+ };
7928
+ }
7929
+ function createPermissionChecker(config) {
7930
+ const { getPermissions, getRoles, roleMap = {} } = config;
7931
+ return (value, mode = "some") => {
7932
+ const permissions = getPermissions();
7933
+ const roles = (getRoles == null ? void 0 : getRoles()) || [];
7934
+ const required = Array.isArray(value) ? value : [value];
7935
+ function checkSingle(perm) {
7936
+ if (perm in roleMap) {
7937
+ return roles.includes(perm);
7938
+ }
7939
+ if (hasPermission(perm, permissions)) {
7940
+ return true;
7941
+ }
7942
+ for (const role of roles) {
7943
+ const rolePermissions = roleMap[role] || [];
7944
+ if (hasPermission(perm, rolePermissions)) {
7945
+ return true;
7946
+ }
7947
+ }
7948
+ return false;
7949
+ }
7950
+ return mode === "every" ? required.every(checkSingle) : required.some(checkSingle);
7951
+ };
7952
+ }
7953
+ function waitForImages(doc) {
7954
+ const images = doc.querySelectorAll("img");
7955
+ const promises = [];
7956
+ images.forEach((img) => {
7957
+ if (!img.complete) {
7958
+ promises.push(
7959
+ new Promise((resolve) => {
7960
+ img.onload = () => resolve();
7961
+ img.onerror = () => resolve();
7962
+ })
7963
+ );
7964
+ }
7965
+ });
7966
+ return Promise.all(promises);
7967
+ }
7968
+ function buildPrintContent(el, options) {
7969
+ let styles = "";
7970
+ if (typeof document !== "undefined") {
7971
+ document.querySelectorAll('style, link[rel="stylesheet"]').forEach((styleEl) => {
7972
+ if (styleEl.tagName === "STYLE") {
7973
+ styles += `<style>${styleEl.textContent}</style>`;
7974
+ } else if (styleEl.tagName === "LINK") {
7975
+ const href = styleEl.href;
7976
+ styles += `<link rel="stylesheet" href="${href}">`;
7977
+ }
7978
+ });
7979
+ }
7980
+ options.cssUrls.forEach((url) => {
7981
+ styles += `<link rel="stylesheet" href="${url}">`;
7982
+ });
7983
+ if (options.styles) {
7984
+ styles += `<style>${options.styles}</style>`;
7985
+ }
7986
+ styles += `
7987
+ <style>
7988
+ @media print {
7989
+ body { margin: 0; padding: 20px; }
7990
+ ${options.printClass ? `.${options.printClass} { page-break-inside: avoid; }` : ""}
7991
+ }
7992
+ </style>
7993
+ `;
7994
+ const title = options.title || (typeof document !== "undefined" ? document.title : "Print");
7995
+ const content = el.outerHTML;
7996
+ return `<!DOCTYPE html>
7997
+ <html>
7998
+ <head>
7999
+ <meta charset="utf-8">
8000
+ <title>${title}</title>
8001
+ ${styles}
8002
+ </head>
8003
+ <body>
8004
+ ${content}
8005
+ </body>
8006
+ </html>`;
8007
+ }
8008
+ function printInIframe(el, options) {
8009
+ return __async(this, null, function* () {
8010
+ var _a, _b, _c;
8011
+ const iframe = document.createElement("iframe");
8012
+ iframe.style.cssText = "position: absolute; top: -10000px; left: -10000px; width: 0; height: 0; border: none;";
8013
+ document.body.appendChild(iframe);
8014
+ const iframeDoc = iframe.contentDocument || ((_a = iframe.contentWindow) == null ? void 0 : _a.document);
8015
+ if (!iframeDoc) {
8016
+ console.warn("[Directix] usePrint: Could not access iframe document");
8017
+ document.body.removeChild(iframe);
8018
+ return;
8019
+ }
8020
+ const content = buildPrintContent(el, options);
8021
+ iframeDoc.open();
8022
+ iframeDoc.write(content);
8023
+ iframeDoc.close();
8024
+ yield waitForImages(iframeDoc);
8025
+ try {
8026
+ (_b = iframe.contentWindow) == null ? void 0 : _b.focus();
8027
+ (_c = iframe.contentWindow) == null ? void 0 : _c.print();
8028
+ } catch (err) {
8029
+ console.error("[Directix] usePrint: Print failed", err);
8030
+ }
8031
+ setTimeout(() => {
8032
+ document.body.removeChild(iframe);
8033
+ }, 1e3);
8034
+ });
8035
+ }
8036
+ function printInNewWindow(el, options) {
8037
+ return __async(this, null, function* () {
8038
+ const printWindow = window.open("", "_blank");
8039
+ if (!printWindow) {
8040
+ console.warn("[Directix] usePrint: Could not open print window");
8041
+ return;
8042
+ }
8043
+ const content = buildPrintContent(el, options);
8044
+ printWindow.document.open();
8045
+ printWindow.document.write(content);
8046
+ printWindow.document.close();
8047
+ yield waitForImages(printWindow.document);
8048
+ printWindow.focus();
8049
+ printWindow.print();
8050
+ setTimeout(() => {
8051
+ printWindow.close();
8052
+ }, 1e3);
8053
+ });
8054
+ }
8055
+ function usePrint(options = {}) {
8056
+ const {
8057
+ title,
8058
+ styles,
8059
+ cssUrls = [],
8060
+ onBeforePrint,
8061
+ onAfterPrint,
8062
+ newWindow = false,
8063
+ printClass
8064
+ } = options;
8065
+ const isPrinting = vue.ref(false);
8066
+ function print(target) {
8067
+ return __async(this, null, function* () {
8068
+ if (onBeforePrint) {
8069
+ const result = onBeforePrint();
8070
+ if (result === false) return;
8071
+ }
8072
+ isPrinting.value = true;
8073
+ try {
8074
+ let targetEl = null;
8075
+ if (typeof target === "string") {
8076
+ targetEl = document.querySelector(target);
8077
+ } else if (target instanceof HTMLElement) {
8078
+ targetEl = target;
8079
+ } else {
8080
+ targetEl = document.body;
8081
+ }
8082
+ if (!targetEl) {
8083
+ console.warn("[Directix] usePrint: Target element not found");
8084
+ return;
8085
+ }
8086
+ const printOptions = {
8087
+ title: vue.unref(title) || "",
8088
+ styles: Array.isArray(vue.unref(styles)) ? vue.unref(styles).join("\n") : vue.unref(styles) || "",
8089
+ cssUrls: vue.unref(cssUrls) || [],
8090
+ printClass: vue.unref(printClass)
8091
+ };
8092
+ if (vue.unref(newWindow)) {
8093
+ yield printInNewWindow(targetEl, printOptions);
8094
+ } else {
8095
+ yield printInIframe(targetEl, printOptions);
8096
+ }
8097
+ if (onAfterPrint) {
8098
+ onAfterPrint();
8099
+ }
8100
+ } finally {
8101
+ isPrinting.value = false;
8102
+ }
8103
+ });
8104
+ }
8105
+ function printPage() {
8106
+ return __async(this, null, function* () {
8107
+ yield print();
8108
+ });
8109
+ }
8110
+ vue.onUnmounted(() => {
8111
+ });
8112
+ return {
8113
+ isPrinting,
8114
+ print,
8115
+ printPage
8116
+ };
8117
+ }
8118
+ function quickPrint(_0) {
8119
+ return __async(this, arguments, function* (target, options = {}) {
8120
+ const { print } = usePrint(options);
8121
+ yield print(target);
8122
+ });
8123
+ }
8124
+ function sleep(ms) {
8125
+ return new Promise((resolve) => setTimeout(resolve, ms));
8126
+ }
8127
+ function usePullRefresh(options) {
8128
+ const {
8129
+ handler,
8130
+ distance = 60,
8131
+ maxDistance = 100,
8132
+ disabled = false,
8133
+ successDuration = 500,
8134
+ errorDuration = 1e3
8135
+ } = options;
8136
+ const state = vue.ref("idle");
8137
+ const distanceValue = vue.ref(0);
8138
+ const isPulling = vue.ref(false);
8139
+ const containerRef = vue.ref(null);
8140
+ let startY = 0, currentY = 0;
8141
+ const getDistance2 = () => vue.unref(distance);
8142
+ const getMaxDistance = () => vue.unref(maxDistance);
8143
+ const getDisabled = () => vue.unref(disabled);
8144
+ const getSuccessDuration = () => vue.unref(successDuration);
8145
+ const getErrorDuration = () => vue.unref(errorDuration);
8146
+ function reset() {
8147
+ state.value = "idle";
8148
+ distanceValue.value = 0;
8149
+ isPulling.value = false;
8150
+ }
8151
+ function refresh() {
8152
+ return __async(this, null, function* () {
8153
+ state.value = "loading";
8154
+ try {
8155
+ yield handler();
8156
+ state.value = "success";
8157
+ yield sleep(getSuccessDuration());
8158
+ } catch (e) {
8159
+ state.value = "error";
8160
+ yield sleep(getErrorDuration());
8161
+ } finally {
8162
+ reset();
8163
+ }
8164
+ });
8165
+ }
8166
+ function touchstart(e) {
8167
+ if (getDisabled() || state.value === "loading") return;
8168
+ const container = containerRef.value;
8169
+ if (container && container.scrollTop > 0) return;
8170
+ isPulling.value = true;
8171
+ startY = e.touches[0].clientY;
8172
+ currentY = startY;
8173
+ state.value = "idle";
8174
+ }
8175
+ function touchmove(e) {
8176
+ if (!isPulling.value || getDisabled() || state.value === "loading") return;
8177
+ currentY = e.touches[0].clientY;
8178
+ const diff = currentY - startY;
8179
+ if (diff <= 0) {
8180
+ distanceValue.value = 0;
8181
+ state.value = "idle";
8182
+ return;
8183
+ }
8184
+ e.preventDefault();
8185
+ const calculatedDistance = Math.min(diff * 0.5, getMaxDistance());
8186
+ distanceValue.value = calculatedDistance;
8187
+ const progress = calculatedDistance / getDistance2();
8188
+ state.value = progress >= 1 ? "ready" : "pulling";
8189
+ }
8190
+ function touchend() {
8191
+ if (!isPulling.value || getDisabled()) return;
8192
+ isPulling.value = false;
8193
+ if (state.value === "ready" && distanceValue.value >= getDistance2()) {
8194
+ refresh();
8195
+ } else {
8196
+ distanceValue.value = 0;
8197
+ reset();
8198
+ }
8199
+ }
8200
+ vue.onUnmounted(() => {
8201
+ reset();
8202
+ });
8203
+ return {
8204
+ state,
8205
+ distance: distanceValue,
8206
+ isPulling,
8207
+ events: {
8208
+ touchstart,
8209
+ touchmove,
8210
+ touchend
8211
+ },
8212
+ containerRef,
8213
+ refresh
8214
+ };
8215
+ }
8216
+ function useResize(options = {}) {
8217
+ const {
8218
+ debounce: debounce2 = 0,
8219
+ box = "content-box",
8220
+ onResize
8221
+ } = options;
8222
+ const width = vue.ref(0);
8223
+ const height = vue.ref(0);
8224
+ let observer = null, debounceTimer = null, fallbackIframe = null;
8225
+ function handleResize(entry) {
8226
+ const currentDebounce = vue.unref(debounce2);
8227
+ function doUpdate() {
8228
+ width.value = entry.contentRect.width;
8229
+ height.value = entry.contentRect.height;
8230
+ onResize == null ? void 0 : onResize({
8231
+ width: entry.contentRect.width,
8232
+ height: entry.contentRect.height,
8233
+ contentRect: entry.contentRect
8234
+ });
8235
+ }
8236
+ if (currentDebounce && currentDebounce > 0) {
8237
+ if (debounceTimer) {
8238
+ clearTimeout(debounceTimer);
8239
+ }
8240
+ debounceTimer = setTimeout(doUpdate, currentDebounce);
8241
+ } else {
8242
+ doUpdate();
8243
+ }
8244
+ }
8245
+ function createObserver2() {
8246
+ if (!isBrowser()) return;
8247
+ if (supportsResizeObserver()) {
8248
+ observer = new ResizeObserver((entries) => {
8249
+ for (const entry of entries) {
8250
+ handleResize(entry);
8251
+ }
8252
+ });
8253
+ }
8254
+ }
8255
+ function bind(element) {
8256
+ if (!isBrowser()) return () => {
8257
+ };
8258
+ stop();
8259
+ const rect = element.getBoundingClientRect();
8260
+ width.value = rect.width;
8261
+ height.value = rect.height;
8262
+ if (supportsResizeObserver()) {
8263
+ createObserver2();
8264
+ observer == null ? void 0 : observer.observe(element, { box });
8265
+ } else {
8266
+ fallbackIframe = document.createElement("iframe");
8267
+ fallbackIframe.style.cssText = `
8268
+ position: absolute;
8269
+ top: 0;
8270
+ left: 0;
8271
+ width: 100%;
8272
+ height: 100%;
8273
+ border: none;
8274
+ pointer-events: none;
8275
+ opacity: 0;
8276
+ `;
8277
+ const computedStyle = getComputedStyle(element);
8278
+ if (computedStyle.position === "static") {
8279
+ element.style.position = "relative";
8280
+ }
8281
+ element.appendChild(fallbackIframe);
8282
+ const iWindow = fallbackIframe.contentWindow;
8283
+ if (iWindow) {
8284
+ iWindow.addEventListener("resize", () => {
8285
+ const rect2 = element.getBoundingClientRect();
8286
+ handleResize({
8287
+ contentRect: rect2
8288
+ });
8289
+ });
8290
+ }
8291
+ }
8292
+ return stop;
8293
+ }
8294
+ function stop() {
8295
+ if (observer) {
8296
+ observer.disconnect();
8297
+ observer = null;
8298
+ }
8299
+ if (fallbackIframe) {
8300
+ fallbackIframe.remove();
8301
+ fallbackIframe = null;
8302
+ }
8303
+ if (debounceTimer) {
8304
+ clearTimeout(debounceTimer);
8305
+ debounceTimer = null;
8306
+ }
8307
+ }
8308
+ vue.onUnmounted(() => {
8309
+ stop();
8310
+ });
8311
+ return {
8312
+ width: vue.readonly(width),
8313
+ height: vue.readonly(height),
8314
+ bind,
8315
+ stop
8316
+ };
8317
+ }
8318
+ function getScrollInfoFromContainer(container, lastScrollLeft, lastScrollTop) {
8319
+ let scrollLeft = 0, scrollTop = 0, scrollLeftMax = 0, scrollTopMax = 0;
8320
+ if (container === window) {
8321
+ scrollLeft = window.scrollX || document.documentElement.scrollLeft;
8322
+ scrollTop = window.scrollY || document.documentElement.scrollTop;
8323
+ scrollLeftMax = document.documentElement.scrollWidth - window.innerWidth;
8324
+ scrollTopMax = document.documentElement.scrollHeight - window.innerHeight;
8325
+ } else {
8326
+ const el = container;
8327
+ scrollLeft = el.scrollLeft;
8328
+ scrollTop = el.scrollTop;
8329
+ scrollLeftMax = el.scrollWidth - el.clientWidth;
8330
+ scrollTopMax = el.scrollHeight - el.clientHeight;
8331
+ }
8332
+ const progressX = scrollLeftMax > 0 ? scrollLeft / scrollLeftMax : 0;
8333
+ const progressY = scrollTopMax > 0 ? scrollTop / scrollTopMax : 0;
8334
+ const directionX = scrollLeft !== lastScrollLeft ? scrollLeft > lastScrollLeft ? 1 : -1 : 0;
8335
+ const directionY = scrollTop !== lastScrollTop ? scrollTop > lastScrollTop ? 1 : -1 : 0;
8336
+ return {
8337
+ scrollLeft,
8338
+ scrollTop,
8339
+ scrollLeftMax,
8340
+ scrollTopMax,
8341
+ progressX,
8342
+ progressY,
8343
+ directionX,
8344
+ directionY
8345
+ };
8346
+ }
8347
+ function useScroll(options = {}) {
8348
+ const { throttle: throttle2 = 0, passive = true } = options;
8349
+ const scrollLeft = vue.ref(0);
8350
+ const scrollTop = vue.ref(0);
8351
+ const progressX = vue.ref(0);
8352
+ const progressY = vue.ref(0);
8353
+ const directionX = vue.ref(0);
8354
+ const directionY = vue.ref(0);
8355
+ const isScrolling = vue.ref(false);
8356
+ let container = null, lastScrollLeft = 0, lastScrollTop = 0, scrollHandler = null, throttleTimer = null, scrollTimeout = null;
8357
+ const info = vue.computed(() => ({
8358
+ scrollLeft: scrollLeft.value,
8359
+ scrollTop: scrollTop.value,
8360
+ scrollLeftMax: 0,
8361
+ scrollTopMax: 0,
8362
+ progressX: progressX.value,
8363
+ progressY: progressY.value,
8364
+ directionX: directionX.value,
8365
+ directionY: directionY.value
8366
+ }));
8367
+ function updateScrollInfo(_e) {
8368
+ if (!container) return;
8369
+ const currentThrottle = vue.unref(throttle2);
8370
+ function doUpdate() {
8371
+ const scrollInfo = getScrollInfoFromContainer(container, lastScrollLeft, lastScrollTop);
8372
+ scrollLeft.value = scrollInfo.scrollLeft;
8373
+ scrollTop.value = scrollInfo.scrollTop;
8374
+ progressX.value = scrollInfo.progressX;
8375
+ progressY.value = scrollInfo.progressY;
8376
+ directionX.value = scrollInfo.directionX;
8377
+ directionY.value = scrollInfo.directionY;
8378
+ lastScrollLeft = scrollInfo.scrollLeft;
8379
+ lastScrollTop = scrollInfo.scrollTop;
8380
+ isScrolling.value = true;
8381
+ if (scrollTimeout) {
8382
+ clearTimeout(scrollTimeout);
8383
+ }
8384
+ scrollTimeout = setTimeout(() => {
8385
+ isScrolling.value = false;
8386
+ }, 150);
8387
+ }
8388
+ if (currentThrottle && currentThrottle > 0) {
8389
+ if (!throttleTimer) {
8390
+ throttleTimer = setTimeout(() => {
8391
+ doUpdate();
8392
+ throttleTimer = null;
8393
+ }, currentThrottle);
8394
+ }
8395
+ } else {
8396
+ doUpdate();
8397
+ }
8398
+ }
8399
+ function bind(element) {
8400
+ if (!isBrowser()) return () => {
8401
+ };
8402
+ stop();
8403
+ if (element) {
8404
+ container = element;
8405
+ } else {
8406
+ container = window;
8407
+ }
8408
+ const initialInfo = getScrollInfoFromContainer(container, 0, 0);
8409
+ scrollLeft.value = initialInfo.scrollLeft;
8410
+ scrollTop.value = initialInfo.scrollTop;
8411
+ progressX.value = initialInfo.progressX;
8412
+ progressY.value = initialInfo.progressY;
8413
+ lastScrollLeft = initialInfo.scrollLeft;
8414
+ lastScrollTop = initialInfo.scrollTop;
8415
+ scrollHandler = updateScrollInfo;
8416
+ container.addEventListener("scroll", scrollHandler, { passive });
8417
+ return stop;
8418
+ }
8419
+ function stop() {
8420
+ if (container && scrollHandler) {
8421
+ container.removeEventListener("scroll", scrollHandler);
8422
+ }
8423
+ if (throttleTimer) {
8424
+ clearTimeout(throttleTimer);
8425
+ throttleTimer = null;
8426
+ }
8427
+ if (scrollTimeout) {
8428
+ clearTimeout(scrollTimeout);
8429
+ scrollTimeout = null;
8430
+ }
8431
+ container = null;
8432
+ scrollHandler = null;
8433
+ }
8434
+ function scrollTo(opts) {
8435
+ if (!container) return;
8436
+ const { top, left, behavior = "smooth" } = opts;
8437
+ if (container === window) {
8438
+ window.scrollTo({
8439
+ top,
8440
+ left,
8441
+ behavior
8442
+ });
8443
+ } else {
8444
+ const el = container;
8445
+ if (top !== void 0) el.scrollTop = top;
8446
+ if (left !== void 0) el.scrollLeft = left;
8447
+ }
8448
+ }
8449
+ vue.onUnmounted(() => {
8450
+ stop();
8451
+ });
8452
+ return {
8453
+ scrollLeft: vue.readonly(scrollLeft),
8454
+ scrollTop: vue.readonly(scrollTop),
8455
+ progressX: vue.readonly(progressX),
8456
+ progressY: vue.readonly(progressY),
8457
+ directionX: vue.readonly(directionX),
8458
+ directionY: vue.readonly(directionY),
8459
+ isScrolling: vue.readonly(isScrolling),
8460
+ info: vue.readonly(info),
8461
+ bind,
8462
+ stop,
8463
+ scrollTo
8464
+ };
8465
+ }
8466
+ const DEFAULT_DIRECTIONS = ["left", "right", "up", "down"];
8467
+ function getSwipeDirection(deltaX, deltaY, allowedDirections) {
8468
+ const absX = Math.abs(deltaX);
8469
+ const absY = Math.abs(deltaY);
8470
+ if (absX > absY) {
8471
+ const direction = deltaX > 0 ? "right" : "left";
8472
+ return allowedDirections.includes(direction) ? direction : null;
8473
+ } else {
8474
+ const direction = deltaY > 0 ? "down" : "up";
8475
+ return allowedDirections.includes(direction) ? direction : null;
8476
+ }
8477
+ }
8478
+ function useSwipe(options = {}) {
8479
+ const {
8480
+ handler,
8481
+ threshold = 30,
8482
+ maxTime = 500,
8483
+ directions = DEFAULT_DIRECTIONS,
8484
+ preventScrollOnSwipe = true,
8485
+ mouse = true,
8486
+ onLeft,
8487
+ onRight,
8488
+ onUp,
8489
+ onDown
8490
+ } = options;
8491
+ const direction = vue.ref(null);
8492
+ const lengthX = vue.ref(0);
8493
+ const lengthY = vue.ref(0);
8494
+ const isSwiping = vue.ref(false);
8495
+ let currentElement = null, startX = 0, startY = 0, startTime = 0;
8496
+ function triggerSwipe2(deltaX, deltaY, deltaTime, event) {
8497
+ var _a;
8498
+ const currentThreshold = vue.unref(threshold);
8499
+ const currentMaxTime = vue.unref(maxTime);
8500
+ if (deltaTime > currentMaxTime) return;
8501
+ const distance = Math.max(Math.abs(deltaX), Math.abs(deltaY));
8502
+ if (distance < currentThreshold) return;
8503
+ const swipeDirection = getSwipeDirection(deltaX, deltaY, directions);
8504
+ if (!swipeDirection) return;
8505
+ direction.value = swipeDirection;
8506
+ lengthX.value = deltaX;
8507
+ lengthY.value = deltaY;
8508
+ if (preventScrollOnSwipe && event.cancelable) {
8509
+ event.preventDefault();
8510
+ }
8511
+ handler == null ? void 0 : handler(swipeDirection, event);
8512
+ const callbacks = {
8513
+ left: onLeft,
8514
+ right: onRight,
8515
+ up: onUp,
8516
+ down: onDown
8517
+ };
8518
+ (_a = callbacks[swipeDirection]) == null ? void 0 : _a.call(callbacks);
8519
+ currentElement == null ? void 0 : currentElement.dispatchEvent(new CustomEvent("swipe", {
8520
+ detail: { direction: swipeDirection, deltaX, deltaY, deltaTime }
8521
+ }));
8522
+ }
8523
+ function handleStart(clientX, clientY) {
8524
+ startX = clientX;
8525
+ startY = clientY;
8526
+ startTime = Date.now();
8527
+ isSwiping.value = true;
8528
+ direction.value = null;
8529
+ lengthX.value = 0;
8530
+ lengthY.value = 0;
8531
+ }
8532
+ function handleEnd(clientX, clientY, event) {
8533
+ if (!isSwiping.value) return;
8534
+ isSwiping.value = false;
8535
+ const deltaX = clientX - startX;
8536
+ const deltaY = clientY - startY;
8537
+ const deltaTime = Date.now() - startTime;
8538
+ triggerSwipe2(deltaX, deltaY, deltaTime, event);
8539
+ }
8540
+ function touchStart(e) {
8541
+ handleStart(e.touches[0].clientX, e.touches[0].clientY);
8542
+ }
8543
+ function touchMove(e) {
8544
+ if (!isSwiping.value || !preventScrollOnSwipe) return;
8545
+ e.preventDefault();
8546
+ }
8547
+ function touchEnd(e) {
8548
+ const touch = e.changedTouches[0];
8549
+ handleEnd(touch.clientX, touch.clientY, e);
8550
+ }
8551
+ function mouseDown(e) {
8552
+ handleStart(e.clientX, e.clientY);
8553
+ }
8554
+ function mouseUp(e) {
8555
+ handleEnd(e.clientX, e.clientY, e);
8556
+ }
8557
+ function mouseLeave(e) {
8558
+ if (isSwiping.value) {
8559
+ handleEnd(e.clientX, e.clientY, e);
8560
+ }
8561
+ }
8562
+ function bind(element) {
8563
+ if (!isBrowser()) return () => {
8564
+ };
8565
+ unbind();
8566
+ currentElement = element;
8567
+ element.style.touchAction = "none";
8568
+ element.style.userSelect = "none";
8569
+ element.addEventListener("touchstart", touchStart, { passive: true });
8570
+ element.addEventListener("touchmove", touchMove, { passive: false });
8571
+ element.addEventListener("touchend", touchEnd);
8572
+ element.addEventListener("touchcancel", touchEnd);
8573
+ if (vue.unref(mouse)) {
8574
+ element.addEventListener("mousedown", mouseDown);
8575
+ element.addEventListener("mouseup", mouseUp);
8576
+ element.addEventListener("mouseleave", mouseLeave);
8577
+ }
8578
+ return unbind;
8579
+ }
8580
+ function unbind() {
8581
+ if (!currentElement) return;
8582
+ currentElement.removeEventListener("touchstart", touchStart);
8583
+ currentElement.removeEventListener("touchmove", touchMove);
8584
+ currentElement.removeEventListener("touchend", touchEnd);
8585
+ currentElement.removeEventListener("touchcancel", touchEnd);
8586
+ if (vue.unref(mouse)) {
8587
+ currentElement.removeEventListener("mousedown", mouseDown);
8588
+ currentElement.removeEventListener("mouseup", mouseUp);
8589
+ currentElement.removeEventListener("mouseleave", mouseLeave);
8590
+ }
8591
+ currentElement = null;
8592
+ }
8593
+ vue.onUnmounted(() => {
8594
+ unbind();
8595
+ });
8596
+ return {
8597
+ direction: vue.readonly(direction),
8598
+ lengthX: vue.readonly(lengthX),
8599
+ lengthY: vue.readonly(lengthY),
8600
+ isSwiping: vue.readonly(isSwiping),
8601
+ bind
8602
+ };
8603
+ }
8604
+ function useThrottle(options) {
8605
+ const {
8606
+ handler,
8607
+ wait = 300,
8608
+ leading = true,
8609
+ trailing = true
8610
+ } = options;
8611
+ let timerId = null, lastArgs = null, lastThis = null, lastCallTime = 0;
8612
+ const getWait = () => vue.unref(wait);
8613
+ const getLeading = () => vue.unref(leading);
8614
+ const getTrailing = () => vue.unref(trailing);
8615
+ const invokeFunc = () => {
8616
+ if (lastArgs) {
8617
+ handler.apply(lastThis, lastArgs);
8618
+ lastArgs = null;
8619
+ lastThis = null;
8620
+ }
8621
+ };
8622
+ function run(...args) {
8623
+ const now = Date.now();
8624
+ const currentWait = getWait();
8625
+ if (!lastCallTime && !getLeading()) {
8626
+ lastCallTime = now;
8627
+ }
8628
+ const remaining = currentWait - (now - lastCallTime);
8629
+ lastArgs = args;
8630
+ lastThis = this;
8631
+ if (remaining <= 0 || remaining > currentWait) {
8632
+ if (timerId) {
8633
+ clearTimeout(timerId);
8634
+ timerId = null;
8635
+ }
8636
+ lastCallTime = now;
8637
+ invokeFunc();
8638
+ } else if (!timerId && getTrailing()) {
8639
+ timerId = setTimeout(() => {
8640
+ lastCallTime = getLeading() ? Date.now() : 0;
8641
+ timerId = null;
8642
+ invokeFunc();
8643
+ }, remaining);
8644
+ }
8645
+ }
8646
+ function cancel() {
8647
+ if (timerId) {
8648
+ clearTimeout(timerId);
8649
+ timerId = null;
8650
+ }
8651
+ lastCallTime = 0;
8652
+ lastArgs = null;
8653
+ lastThis = null;
8654
+ }
8655
+ vue.onUnmounted(() => {
8656
+ cancel();
8657
+ });
8658
+ return {
8659
+ run,
8660
+ cancel
8661
+ };
8662
+ }
8663
+ function throttleFn(fn, wait = 300, options) {
8664
+ return throttle(fn, wait, options);
8665
+ }
8666
+ function useTouch(options = {}) {
8667
+ const {
8668
+ onSwipe,
8669
+ onSwipeLeft,
8670
+ onSwipeRight,
8671
+ onSwipeUp,
8672
+ onSwipeDown,
8673
+ onPinch,
8674
+ onRotate,
8675
+ onTap,
8676
+ onLongPress,
8677
+ swipeThreshold = 30,
8678
+ longPressDuration = 500,
8679
+ tapDuration = 250,
8680
+ disabled = false
8681
+ } = options;
8682
+ const gesture = vue.ref(null);
8683
+ let currentElement = null, startX = 0, startY = 0, startTime = 0, longPressTimer = null, initialPinchDistance = 0, initialAngle = 0;
8684
+ function getTouchCenter(touches) {
8685
+ let x = 0, y = 0;
8686
+ for (let i = 0; i < touches.length; i++) {
8687
+ x += touches[i].clientX;
8688
+ y += touches[i].clientY;
8689
+ }
8690
+ return { x: x / touches.length, y: y / touches.length };
8691
+ }
8692
+ function getDistance2(touch1, touch2) {
8693
+ const dx = touch1.clientX - touch2.clientX;
8694
+ const dy = touch1.clientY - touch2.clientY;
8695
+ return Math.sqrt(dx * dx + dy * dy);
8696
+ }
8697
+ function getAngle2(touch1, touch2) {
8698
+ return Math.atan2(touch2.clientY - touch1.clientY, touch2.clientX - touch1.clientX) * (180 / Math.PI);
8699
+ }
8700
+ function handleTouchStart(e) {
8701
+ if (vue.unref(disabled)) return;
8702
+ startTime = Date.now();
8703
+ gesture.value = null;
8704
+ if (e.touches.length === 1) {
8705
+ startX = e.touches[0].clientX;
8706
+ startY = e.touches[0].clientY;
8707
+ if (onLongPress) {
8708
+ longPressTimer = setTimeout(() => {
8709
+ gesture.value = "longPress";
8710
+ onLongPress({
8711
+ type: "longPress",
8712
+ center: { x: startX, y: startY },
8713
+ event: e
8714
+ });
8715
+ }, longPressDuration);
8716
+ }
8717
+ } else if (e.touches.length === 2) {
8718
+ initialPinchDistance = getDistance2(e.touches[0], e.touches[1]);
8719
+ initialAngle = getAngle2(e.touches[0], e.touches[1]);
8720
+ }
8721
+ }
8722
+ function handleTouchMove(e) {
8723
+ if (vue.unref(disabled)) return;
8724
+ if (longPressTimer) {
8725
+ clearTimeout(longPressTimer);
8726
+ longPressTimer = null;
8727
+ }
8728
+ if (e.touches.length === 2 && (onPinch || onRotate)) {
8729
+ const currentDistance = getDistance2(e.touches[0], e.touches[1]);
8730
+ const currentAngle = getAngle2(e.touches[0], e.touches[1]);
8731
+ if (onPinch && initialPinchDistance > 0) {
8732
+ const scale = currentDistance / initialPinchDistance;
8733
+ gesture.value = "pinch";
8734
+ onPinch({
8735
+ type: "pinch",
8736
+ scale,
8737
+ center: getTouchCenter(e.touches),
8738
+ event: e
8739
+ });
8740
+ }
8741
+ if (onRotate) {
8742
+ const rotation = currentAngle - initialAngle;
8743
+ gesture.value = "rotate";
8744
+ onRotate({
8745
+ type: "rotate",
8746
+ rotation,
8747
+ center: getTouchCenter(e.touches),
8748
+ event: e
8749
+ });
8750
+ }
8751
+ }
8752
+ }
8753
+ function handleTouchEnd(e) {
8754
+ if (vue.unref(disabled)) return;
8755
+ if (longPressTimer) {
8756
+ clearTimeout(longPressTimer);
8757
+ longPressTimer = null;
8758
+ }
8759
+ const duration = Date.now() - startTime;
8760
+ if (e.changedTouches.length === 1) {
8761
+ const endX = e.changedTouches[0].clientX;
8762
+ const endY = e.changedTouches[0].clientY;
8763
+ const deltaX = endX - startX;
8764
+ const deltaY = endY - startY;
8765
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
8766
+ if (distance >= swipeThreshold) {
8767
+ gesture.value = "swipe";
8768
+ let direction;
8769
+ if (Math.abs(deltaX) > Math.abs(deltaY)) {
8770
+ direction = deltaX > 0 ? "right" : "left";
8771
+ } else {
8772
+ direction = deltaY > 0 ? "down" : "up";
8773
+ }
8774
+ const event = {
8775
+ type: "swipe",
8776
+ direction,
8777
+ distance,
8778
+ angle: Math.atan2(deltaY, deltaX) * (180 / Math.PI),
8779
+ center: { x: endX, y: endY },
8780
+ event: e
8781
+ };
8782
+ onSwipe == null ? void 0 : onSwipe(event);
8783
+ switch (direction) {
8784
+ case "left":
8785
+ onSwipeLeft == null ? void 0 : onSwipeLeft(event);
8786
+ break;
8787
+ case "right":
8788
+ onSwipeRight == null ? void 0 : onSwipeRight(event);
8789
+ break;
8790
+ case "up":
8791
+ onSwipeUp == null ? void 0 : onSwipeUp(event);
8792
+ break;
8793
+ case "down":
8794
+ onSwipeDown == null ? void 0 : onSwipeDown(event);
8795
+ break;
8796
+ }
8797
+ } else if (distance < 10 && duration < tapDuration && onTap) {
8798
+ gesture.value = "tap";
8799
+ onTap({
8800
+ type: "tap",
8801
+ center: { x: endX, y: endY },
8802
+ event: e
8803
+ });
8804
+ }
8805
+ }
8806
+ gesture.value = null;
8807
+ }
8808
+ function bind(element) {
8809
+ if (!isBrowser()) return () => {
8810
+ };
8811
+ unbind();
8812
+ currentElement = element;
8813
+ element.addEventListener("touchstart", handleTouchStart, { passive: true });
8814
+ element.addEventListener("touchmove", handleTouchMove, { passive: true });
8815
+ element.addEventListener("touchend", handleTouchEnd);
8816
+ element.addEventListener("touchcancel", handleTouchEnd);
8817
+ return unbind;
8818
+ }
8819
+ function unbind() {
8820
+ if (currentElement) {
8821
+ currentElement.removeEventListener("touchstart", handleTouchStart);
8822
+ currentElement.removeEventListener("touchmove", handleTouchMove);
8823
+ currentElement.removeEventListener("touchend", handleTouchEnd);
8824
+ currentElement.removeEventListener("touchcancel", handleTouchEnd);
8825
+ }
8826
+ if (longPressTimer) {
8827
+ clearTimeout(longPressTimer);
8828
+ longPressTimer = null;
8829
+ }
8830
+ currentElement = null;
8831
+ gesture.value = null;
8832
+ }
8833
+ vue.onUnmounted(() => {
8834
+ unbind();
8835
+ });
8836
+ return {
8837
+ gesture: vue.readonly(gesture),
8838
+ bind
8839
+ };
8840
+ }
8841
+ function escapeRegex(str) {
8842
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8843
+ }
8844
+ function trimText(text, position = "both", chars) {
8845
+ const charPattern = chars ? `[\\s${escapeRegex(chars)}]` : "\\s";
8846
+ switch (position) {
8847
+ case "start":
8848
+ return text.replace(new RegExp(`^${charPattern}+`, "g"), "");
8849
+ case "end":
8850
+ return text.replace(new RegExp(`${charPattern}+$`, "g"), "");
8851
+ case "both":
8852
+ default:
8853
+ return text.replace(new RegExp(`^${charPattern}+|${charPattern}+$`, "g"), "");
8854
+ }
8855
+ }
8856
+ function useTrim(options) {
8857
+ const {
8858
+ text,
8859
+ position = "both",
8860
+ chars
8861
+ } = options;
8862
+ const original = vue.ref(vue.unref(text));
8863
+ const trimmed = vue.ref("");
8864
+ const wasTrimmed = vue.ref(false);
8865
+ function calculate() {
8866
+ const textValue = vue.unref(text);
8867
+ const positionValue = vue.unref(position);
8868
+ const charsValue = vue.unref(chars);
8869
+ original.value = textValue;
8870
+ trimmed.value = trimText(textValue, positionValue, charsValue);
8871
+ wasTrimmed.value = trimmed.value !== textValue;
8872
+ }
8873
+ vue.watch(
8874
+ () => [vue.unref(text), vue.unref(position), vue.unref(chars)],
8875
+ () => calculate(),
8876
+ { immediate: true }
8877
+ );
8878
+ return {
8879
+ trimmed,
8880
+ original,
8881
+ wasTrimmed
8882
+ };
8883
+ }
8884
+ function createTrimmer(position = "both", chars) {
8885
+ return (text) => trimText(text, position, chars);
8886
+ }
8887
+ function uppercaseText(text, firstOnly = false) {
8888
+ if (!text) return text;
8889
+ if (firstOnly) {
8890
+ return text.charAt(0).toUpperCase() + text.slice(1);
8891
+ }
8892
+ return text.toUpperCase();
8893
+ }
8894
+ function useUppercase(options) {
8895
+ const {
8896
+ text,
8897
+ first = false
8898
+ } = options;
8899
+ const original = vue.ref(vue.unref(text));
8900
+ const transformed = vue.ref("");
8901
+ function calculate() {
8902
+ const textValue = vue.unref(text);
8903
+ const firstValue = vue.unref(first);
8904
+ original.value = textValue;
8905
+ transformed.value = uppercaseText(textValue, firstValue);
8906
+ }
8907
+ vue.watch(
8908
+ () => [vue.unref(text), vue.unref(first)],
8909
+ () => calculate(),
8910
+ { immediate: true }
8911
+ );
8912
+ return {
8913
+ transformed,
8914
+ original
8915
+ };
8916
+ }
8917
+ function createUppercaser(first = false) {
8918
+ return (text) => uppercaseText(text, first);
8919
+ }
8920
+ function useVirtualList(options) {
8921
+ const {
8922
+ items,
8923
+ itemSize = 50,
8924
+ height = 400,
8925
+ overscan = 3,
8926
+ keyField: _keyField = "id"
8927
+ } = options;
8928
+ const containerRef = vue.ref(null);
8929
+ const scrollTop = vue.ref(0);
8930
+ const startIndex = vue.ref(0);
8931
+ const endIndex = vue.ref(0);
8932
+ const getItems = () => vue.unref(items);
8933
+ const getItemSizeValue = () => vue.unref(itemSize);
8934
+ const getHeight = () => vue.unref(height);
8935
+ const getOverscan = () => vue.unref(overscan);
8936
+ const totalHeight = vue.computed(() => {
8937
+ const itemsList = getItems();
8938
+ const size = getItemSizeValue();
8939
+ if (typeof size === "function") {
8940
+ let total = 0;
8941
+ for (let i = 0; i < itemsList.length; i++) {
8942
+ total += size(i);
8943
+ }
8944
+ return total;
8945
+ }
8946
+ return size * itemsList.length;
8947
+ });
8948
+ function calculateVisibleRange2() {
8949
+ const itemsList = getItems();
8950
+ const size = getItemSizeValue();
8951
+ const containerHeight = getHeight();
8952
+ const overscanValue = getOverscan();
8953
+ const currentScrollTop = scrollTop.value;
8954
+ let start = 0, end = 0, offsetY = 0;
8955
+ if (typeof size === "function") {
8956
+ let currentOffset = 0;
8957
+ for (let i = 0; i < itemsList.length; i++) {
8958
+ const itemHeight = size(i);
8959
+ if (currentOffset + itemHeight > currentScrollTop) {
8960
+ start = i;
8961
+ offsetY = currentOffset;
8962
+ break;
8963
+ }
8964
+ currentOffset += itemHeight;
8965
+ }
8966
+ end = start;
8967
+ currentOffset = offsetY;
8968
+ while (end < itemsList.length && currentOffset < currentScrollTop + containerHeight) {
8969
+ currentOffset += size(end);
8970
+ end++;
8971
+ }
8972
+ start = Math.max(0, start - overscanValue);
8973
+ end = Math.min(itemsList.length, end + overscanValue);
8974
+ currentOffset = 0;
8975
+ for (let i = 0; i < start; i++) {
8976
+ currentOffset += size(i);
8977
+ }
8978
+ offsetY = currentOffset;
8979
+ } else {
8980
+ start = Math.max(0, Math.floor(currentScrollTop / size) - overscanValue);
8981
+ end = Math.min(itemsList.length, Math.ceil((currentScrollTop + containerHeight) / size) + overscanValue);
8982
+ offsetY = start * size;
8983
+ }
8984
+ return { start, end, offsetY };
8985
+ }
8986
+ const visibleItems = vue.computed(() => {
8987
+ const itemsList = getItems();
8988
+ const size = getItemSizeValue();
8989
+ const { start, end, offsetY } = calculateVisibleRange2();
8990
+ startIndex.value = start;
8991
+ endIndex.value = end;
8992
+ const result = [];
8993
+ let currentOffset = offsetY;
8994
+ for (let i = start; i < end; i++) {
8995
+ const item = itemsList[i];
8996
+ if (item !== void 0) {
8997
+ const itemHeight = typeof size === "function" ? size(i) : size;
8998
+ result.push({
8999
+ item,
9000
+ index: i,
9001
+ style: {
9002
+ position: "absolute",
9003
+ top: `${currentOffset}px`,
9004
+ height: `${itemHeight}px`,
9005
+ width: "100%"
9006
+ }
9007
+ });
9008
+ currentOffset += itemHeight;
9009
+ }
9010
+ }
9011
+ return result;
9012
+ });
9013
+ const listStyle = vue.computed(() => ({
9014
+ height: `${getHeight()}px`,
9015
+ overflow: "auto",
9016
+ position: "relative"
9017
+ }));
9018
+ function handleScroll(event) {
9019
+ const target = event.target;
9020
+ scrollTop.value = target.scrollTop;
9021
+ }
9022
+ function scrollToIndex(index) {
9023
+ if (!containerRef.value) return;
9024
+ const size = getItemSizeValue();
9025
+ const itemsList = getItems();
9026
+ if (typeof size === "function") {
9027
+ let offset = 0;
9028
+ for (let i = 0; i < Math.min(index, itemsList.length); i++) {
9029
+ offset += size(i);
9030
+ }
9031
+ containerRef.value.scrollTop = offset;
9032
+ } else {
9033
+ containerRef.value.scrollTop = index * size;
9034
+ }
9035
+ }
9036
+ function scrollTo(position) {
9037
+ if (!containerRef.value) return;
9038
+ containerRef.value.scrollTop = position;
9039
+ }
9040
+ vue.onMounted(() => {
9041
+ if (containerRef.value) {
9042
+ containerRef.value.addEventListener("scroll", handleScroll, { passive: true });
9043
+ }
9044
+ });
9045
+ vue.onUnmounted(() => {
9046
+ if (containerRef.value) {
9047
+ containerRef.value.removeEventListener("scroll", handleScroll);
9048
+ }
9049
+ });
9050
+ return {
9051
+ visibleItems,
9052
+ totalHeight,
9053
+ scrollTop,
9054
+ startIndex,
9055
+ endIndex,
9056
+ scrollToIndex,
9057
+ scrollTo,
9058
+ containerRef,
9059
+ listStyle
9060
+ };
9061
+ }
9062
+ function useVisible(options = {}) {
9063
+ const {
9064
+ initial = true,
9065
+ useHidden = false,
9066
+ onChange
9067
+ } = options;
9068
+ const visible = vue.ref(vue.unref(initial));
9069
+ let currentElement = null, originalDisplay = "", originalVisibility = "";
9070
+ function show() {
9071
+ visible.value = true;
9072
+ }
9073
+ function hide() {
9074
+ visible.value = false;
9075
+ }
9076
+ function toggle() {
9077
+ visible.value = !visible.value;
9078
+ }
9079
+ function applyVisibility2(isVisible) {
9080
+ if (!currentElement) return;
9081
+ if (isVisible) {
9082
+ currentElement.classList.remove("v-hidden");
9083
+ currentElement.classList.add("v-visible");
9084
+ if (useHidden) {
9085
+ currentElement.style.visibility = originalVisibility || "visible";
9086
+ } else {
9087
+ currentElement.style.display = originalDisplay;
9088
+ }
9089
+ } else {
9090
+ currentElement.classList.remove("v-visible");
9091
+ currentElement.classList.add("v-hidden");
9092
+ if (useHidden) {
9093
+ currentElement.style.visibility = "hidden";
9094
+ } else {
9095
+ currentElement.style.display = "none";
9096
+ }
9097
+ }
9098
+ }
9099
+ function bind(element) {
9100
+ if (!isBrowser()) return () => {
9101
+ };
9102
+ unbind();
9103
+ currentElement = element;
9104
+ originalDisplay = element.style.display;
9105
+ originalVisibility = element.style.visibility;
9106
+ applyVisibility2(visible.value);
9107
+ return unbind;
9108
+ }
9109
+ function unbind() {
9110
+ if (currentElement) {
9111
+ currentElement.style.display = originalDisplay;
9112
+ currentElement.style.visibility = originalVisibility;
9113
+ currentElement.classList.remove("v-hidden", "v-visible");
9114
+ }
9115
+ currentElement = null;
9116
+ }
9117
+ vue.watch(visible, (newValue, oldValue) => {
9118
+ if (newValue !== oldValue) {
9119
+ applyVisibility2(newValue);
9120
+ onChange == null ? void 0 : onChange(newValue);
9121
+ }
9122
+ });
9123
+ if (typeof initial === "object" && "value" in initial) {
9124
+ vue.watch(initial, (newValue) => {
9125
+ visible.value = newValue;
9126
+ });
9127
+ }
9128
+ vue.onUnmounted(() => {
9129
+ unbind();
9130
+ });
9131
+ return {
9132
+ visible,
9133
+ show,
9134
+ hide,
9135
+ toggle,
9136
+ bind
9137
+ };
9138
+ }
9139
+ function createWatermarkCanvas(options) {
9140
+ const canvas = document.createElement("canvas");
9141
+ const ctx = canvas.getContext("2d");
9142
+ if (!ctx) {
9143
+ throw new Error("[Directix] useWatermark: Could not get canvas context");
9144
+ }
9145
+ const {
9146
+ content,
9147
+ width,
9148
+ height,
9149
+ fontSize,
9150
+ fontFamily,
9151
+ fontWeight,
9152
+ color,
9153
+ rotate
9154
+ } = options;
9155
+ canvas.width = width;
9156
+ canvas.height = height;
9157
+ ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
9158
+ ctx.fillStyle = color;
9159
+ ctx.textAlign = "center";
9160
+ ctx.textBaseline = "middle";
9161
+ ctx.translate(width / 2, height / 2);
9162
+ ctx.rotate(rotate * Math.PI / 180);
9163
+ const contentArray = Array.isArray(content) ? content : [content];
9164
+ const lineHeight = fontSize * 1.5;
9165
+ const startY = -((contentArray.length - 1) * lineHeight) / 2;
9166
+ contentArray.forEach((text, index) => {
9167
+ ctx.fillText(text, 0, startY + index * lineHeight);
9168
+ });
9169
+ return canvas;
9170
+ }
9171
+ function useWatermark(options) {
9172
+ const {
9173
+ content,
9174
+ width = 300,
9175
+ height = 200,
9176
+ rotate = -22,
9177
+ fontSize = 16,
9178
+ fontFamily = "sans-serif",
9179
+ fontWeight = "normal",
9180
+ color = "rgba(128, 128, 128, 0.15)",
9181
+ gap = [100, 100],
9182
+ zIndex = 9999,
9183
+ disabled = false,
9184
+ protect: _protect = true
9185
+ } = options;
9186
+ const canvas = vue.ref(null);
9187
+ const dataUrl = vue.ref("");
9188
+ const disabledRef = vue.ref(vue.unref(disabled));
9189
+ function generate() {
9190
+ const contentValue = vue.unref(content);
9191
+ const widthValue = vue.unref(width);
9192
+ const heightValue = vue.unref(height);
9193
+ const rotateValue = vue.unref(rotate);
9194
+ const fontSizeValue = vue.unref(fontSize);
9195
+ const fontFamilyValue = vue.unref(fontFamily);
9196
+ const fontWeightValue = vue.unref(fontWeight);
9197
+ const colorValue = vue.unref(color);
9198
+ canvas.value = createWatermarkCanvas({
9199
+ content: contentValue,
9200
+ width: widthValue,
9201
+ height: heightValue,
9202
+ fontSize: fontSizeValue,
9203
+ fontFamily: fontFamilyValue,
9204
+ fontWeight: fontWeightValue,
9205
+ color: colorValue,
9206
+ rotate: rotateValue
9207
+ });
9208
+ dataUrl.value = canvas.value.toDataURL();
9209
+ }
9210
+ const style = vue.ref({
9211
+ position: "absolute",
9212
+ top: "0",
9213
+ left: "0",
9214
+ width: "100%",
9215
+ height: "100%",
9216
+ pointerEvents: "none",
9217
+ zIndex: vue.unref(zIndex),
9218
+ backgroundImage: "",
9219
+ backgroundRepeat: "repeat",
9220
+ backgroundPosition: "0 0",
9221
+ backgroundSize: ""
9222
+ });
9223
+ function updateStyle() {
9224
+ const gapValue = vue.unref(gap);
9225
+ const zIndexValue = vue.unref(zIndex);
9226
+ const gapArray = Array.isArray(gapValue) ? gapValue : [gapValue, gapValue];
9227
+ const widthValue = vue.unref(width);
9228
+ const heightValue = vue.unref(height);
9229
+ style.value = __spreadProps(__spreadValues({}, style.value), {
9230
+ zIndex: zIndexValue,
9231
+ backgroundImage: `url("${dataUrl.value}")`,
9232
+ backgroundPosition: `${gapArray[0] / 2}px ${gapArray[1] / 2}px`,
9233
+ backgroundSize: `${widthValue + gapArray[0]}px ${heightValue + gapArray[1]}px`
9234
+ });
9235
+ }
9236
+ function update(newOptions) {
9237
+ Object.assign(options, newOptions);
9238
+ generate();
9239
+ updateStyle();
9240
+ }
9241
+ function enable() {
9242
+ disabledRef.value = false;
9243
+ }
9244
+ function disable() {
9245
+ disabledRef.value = true;
9246
+ }
9247
+ vue.watch(
9248
+ () => [
9249
+ vue.unref(content),
9250
+ vue.unref(width),
9251
+ vue.unref(height),
9252
+ vue.unref(rotate),
9253
+ vue.unref(fontSize),
9254
+ vue.unref(fontFamily),
9255
+ vue.unref(fontWeight),
9256
+ vue.unref(color),
9257
+ vue.unref(gap),
9258
+ vue.unref(zIndex)
9259
+ ],
9260
+ () => {
9261
+ generate();
9262
+ updateStyle();
9263
+ },
9264
+ { immediate: true }
9265
+ );
9266
+ vue.watch(disabledRef, (isDisabled) => {
9267
+ style.value.display = isDisabled ? "none" : "block";
9268
+ });
9269
+ if (vue.unref(disabled)) {
9270
+ style.value.display = "none";
9271
+ }
9272
+ vue.onUnmounted(() => {
9273
+ });
9274
+ return {
9275
+ canvas,
9276
+ dataUrl,
9277
+ style,
9278
+ disabled: disabledRef,
9279
+ update,
9280
+ enable,
9281
+ disable
9282
+ };
9283
+ }
9284
+ function createWatermarkUrl(content, options = {}) {
9285
+ var _a, _b, _c, _d, _e;
9286
+ const canvas = createWatermarkCanvas({
9287
+ content,
9288
+ width: (_a = options.width) != null ? _a : 300,
9289
+ height: (_b = options.height) != null ? _b : 200,
9290
+ fontSize: (_c = options.fontSize) != null ? _c : 16,
9291
+ fontFamily: "sans-serif",
9292
+ fontWeight: "normal",
9293
+ color: (_d = options.color) != null ? _d : "rgba(128, 128, 128, 0.15)",
9294
+ rotate: (_e = options.rotate) != null ? _e : -22
9295
+ });
9296
+ return canvas.toDataURL();
9297
+ }
6283
9298
  const allDirectives = {
6284
9299
  "click-outside": vClickOutside,
6285
9300
  "click-delay": vClickDelay,
@@ -6364,32 +9379,31 @@ const Directix = {
6364
9379
  exports.Directix = Directix;
6365
9380
  exports.addCleanupVue2 = addCleanup$1;
6366
9381
  exports.addCleanupVue3 = addCleanup;
6367
- exports.capitalcase = vCapitalcase;
6368
- exports.clickDelay = vClickDelay;
6369
- exports.clickOutside = vClickOutside;
6370
- exports.configurePermission = configurePermission;
6371
- exports.copy = vCopy;
6372
- exports.countdown = vCountdown;
9382
+ exports.calculateTime = calculateTime;
9383
+ exports.capitalizeText = capitalizeText;
9384
+ exports.capitalizeWord = capitalizeWord;
9385
+ exports.createCapitalizer = createCapitalizer;
9386
+ exports.createDelayedClick = createDelayedClick;
9387
+ exports.createLowercaser = createLowercaser;
9388
+ exports.createMoneyFormatter = createMoneyFormatter;
9389
+ exports.createNumberFormatter = createNumberFormatter;
9390
+ exports.createPermissionChecker = createPermissionChecker;
9391
+ exports.createTrimmer = createTrimmer;
9392
+ exports.createUppercaser = createUppercaser;
6373
9393
  exports.createVue2Directive = createVue2Directive;
6374
9394
  exports.createVue3Directive = createVue3Directive;
6375
- exports.debounce = vDebounce;
6376
- exports.debounceFn = debounce;
9395
+ exports.createWatermarkUrl = createWatermarkUrl;
9396
+ exports.debounceFn = debounceFn;
6377
9397
  exports.deepClone = deepClone;
6378
9398
  exports.deepMerge = deepMerge;
6379
9399
  exports.defineDirective = defineDirective;
6380
9400
  exports.defineDirectiveGroup = defineDirectiveGroup;
6381
- exports.draggable = vDraggable;
6382
- exports.ellipsis = vEllipsis;
6383
- exports.focus = vFocus;
9401
+ exports.formatMoney = formatMoney;
9402
+ exports.formatNumber = formatNumber;
9403
+ exports.formatTime = formatTime;
6384
9404
  exports.generateId = generateId;
6385
9405
  exports.get = get;
6386
- exports.getPermissionConfig = getPermissionConfig;
6387
9406
  exports.getVueVersion = getVueVersion;
6388
- exports.hotkey = vHotkey;
6389
- exports.hover = vHover;
6390
- exports.imagePreview = vImagePreview;
6391
- exports.infiniteScroll = vInfiniteScroll;
6392
- exports.intersect = vIntersect;
6393
9407
  exports.isArray = isArray;
6394
9408
  exports.isBoolean = isBoolean;
6395
9409
  exports.isBrowser = isBrowser;
@@ -6403,39 +9417,54 @@ exports.isString = isString;
6403
9417
  exports.isVue2 = isVue2;
6404
9418
  exports.isVue27 = isVue27;
6405
9419
  exports.isVue3 = isVue3;
6406
- exports.lazy = vLazy;
6407
- exports.loading = vLoading;
6408
- exports.longPress = vLongPress;
6409
- exports.lowercase = vLowercase;
6410
- exports.mask = vMask;
6411
- exports.money = vMoney;
6412
- exports.mutation = vMutation;
6413
- exports.number = vNumber;
9420
+ exports.lowercaseText = lowercaseText;
9421
+ exports.parseMoney = parseMoney;
9422
+ exports.parseNumber = parseNumber;
9423
+ exports.parseTargetTime = parseTargetTime;
6414
9424
  exports.parseTime = parseTime;
6415
- exports.permission = vPermission;
6416
- exports.print = vPrint;
6417
- exports.pullRefresh = vPullRefresh;
9425
+ exports.quickPrint = quickPrint;
6418
9426
  exports.resetVueVersion = resetVueVersion;
6419
- exports.resize = vResize;
6420
- exports.ripple = vRipple;
6421
- exports.sanitize = vSanitize;
6422
- exports.scroll = vScroll;
6423
9427
  exports.set = set;
6424
9428
  exports.setVueVersion = setVueVersion;
6425
- exports.sticky = vSticky;
6426
9429
  exports.supportsClipboard = supportsClipboard;
6427
9430
  exports.supportsIntersectionObserver = supportsIntersectionObserver;
6428
9431
  exports.supportsMutationObserver = supportsMutationObserver;
6429
9432
  exports.supportsPassive = supportsPassive;
6430
9433
  exports.supportsResizeObserver = supportsResizeObserver;
6431
- exports.swipe = vSwipe;
6432
- exports.throttle = vThrottle;
6433
- exports.throttleFn = throttle;
6434
- exports.tooltip = vTooltip;
6435
- exports.touch = vTouch;
6436
- exports.trim = vTrim;
6437
- exports.truncate = vTruncate;
6438
- exports.uppercase = vUppercase;
9434
+ exports.throttleFn = throttleFn;
9435
+ exports.trimText = trimText;
9436
+ exports.truncateText = truncateText;
9437
+ exports.uppercaseText = uppercaseText;
9438
+ exports.useCapitalcase = useCapitalcase;
9439
+ exports.useClickDelay = useClickDelay;
9440
+ exports.useClickOutside = useClickOutside;
9441
+ exports.useCopy = useCopy;
9442
+ exports.useCountdown = useCountdown;
9443
+ exports.useDebounce = useDebounce;
9444
+ exports.useDraggable = useDraggable;
9445
+ exports.useEllipsis = useEllipsis;
9446
+ exports.useFocus = useFocus;
9447
+ exports.useHotkey = useHotkey;
9448
+ exports.useHover = useHover;
9449
+ exports.useImagePreview = useImagePreview;
9450
+ exports.useIntersect = useIntersect;
9451
+ exports.useLongPress = useLongPress;
9452
+ exports.useLowercase = useLowercase;
9453
+ exports.useMoney = useMoney;
9454
+ exports.useNumber = useNumber;
9455
+ exports.usePermission = usePermission;
9456
+ exports.usePrint = usePrint;
9457
+ exports.usePullRefresh = usePullRefresh;
9458
+ exports.useResize = useResize;
9459
+ exports.useScroll = useScroll;
9460
+ exports.useSwipe = useSwipe;
9461
+ exports.useThrottle = useThrottle;
9462
+ exports.useTouch = useTouch;
9463
+ exports.useTrim = useTrim;
9464
+ exports.useUppercase = useUppercase;
9465
+ exports.useVirtualList = useVirtualList;
9466
+ exports.useVisible = useVisible;
9467
+ exports.useWatermark = useWatermark;
6439
9468
  exports.vCapitalcase = vCapitalcase;
6440
9469
  exports.vClickDelay = vClickDelay;
6441
9470
  exports.vClickOutside = vClickOutside;
@@ -6476,7 +9505,5 @@ exports.vUppercase = vUppercase;
6476
9505
  exports.vVirtualList = vVirtualList;
6477
9506
  exports.vVisible = vVisible;
6478
9507
  exports.vWatermark = vWatermark;
6479
- exports.virtualList = vVirtualList;
6480
- exports.visible = vVisible;
6481
- exports.watermark = vWatermark;
9508
+ exports.wouldTextTruncate = wouldTextTruncate;
6482
9509
  //# sourceMappingURL=index.cjs.map