directix 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/dist/index.cjs +1790 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +829 -0
- package/dist/index.iife.js +1962 -198
- package/dist/index.iife.js.map +1 -1
- package/dist/index.iife.min.js +2 -2
- package/dist/index.mjs +1791 -27
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.d.ts +1 -1
- package/dist/nuxt/index.mjs +1 -1
- package/dist/nuxt/runtime/plugin.mjs +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* directix v1.
|
|
2
|
+
* directix v1.10.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,13 +58,13 @@ var __async = (__this, __arguments, generator) => {
|
|
|
58
58
|
});
|
|
59
59
|
};
|
|
60
60
|
/*!
|
|
61
|
-
* directix v1.
|
|
61
|
+
* directix v1.10.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
|
var _a;
|
|
67
|
-
import { ref, unref, onUnmounted, watch, readonly, shallowRef, computed, onMounted } from "vue";
|
|
67
|
+
import { ref, unref, onUnmounted, watch, readonly, shallowRef, computed, onMounted, reactive, watchEffect, isRef, toRaw, markRaw } from "vue";
|
|
68
68
|
function createVue2Directive(hooks) {
|
|
69
69
|
const directive = {
|
|
70
70
|
bind(el, binding, vnode) {
|
|
@@ -7171,23 +7171,23 @@ function handleEnd(e, state2, el) {
|
|
|
7171
7171
|
state2.initialAngle = 0;
|
|
7172
7172
|
state2.currentAngle = 0;
|
|
7173
7173
|
}
|
|
7174
|
-
const DEFAULT_ALLOWED_TAGS$
|
|
7175
|
-
const DEFAULT_ALLOWED_ATTRIBUTES$
|
|
7176
|
-
const DANGEROUS_TAGS$
|
|
7177
|
-
const DANGEROUS_ATTRIBUTES$
|
|
7174
|
+
const DEFAULT_ALLOWED_TAGS$2 = ["b", "i", "u", "strong", "em", "br", "p", "span", "div"];
|
|
7175
|
+
const DEFAULT_ALLOWED_ATTRIBUTES$2 = ["title", "alt", "href", "src"];
|
|
7176
|
+
const DANGEROUS_TAGS$2 = ["script", "iframe", "object", "embed", "form", "input", "style", "link", "meta", "base"];
|
|
7177
|
+
const DANGEROUS_ATTRIBUTES$2 = ["onclick", "onerror", "onload", "onmouseover", "onfocus", "onblur", "onchange", "onsubmit"];
|
|
7178
7178
|
function normalizeOptions$e(binding) {
|
|
7179
7179
|
if (binding === false) {
|
|
7180
7180
|
return { disabled: true };
|
|
7181
7181
|
}
|
|
7182
7182
|
if (binding === true) {
|
|
7183
7183
|
return {
|
|
7184
|
-
allowedTags: DEFAULT_ALLOWED_TAGS$
|
|
7185
|
-
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES$
|
|
7184
|
+
allowedTags: DEFAULT_ALLOWED_TAGS$2,
|
|
7185
|
+
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES$2
|
|
7186
7186
|
};
|
|
7187
7187
|
}
|
|
7188
7188
|
return __spreadValues({
|
|
7189
|
-
allowedTags: DEFAULT_ALLOWED_TAGS$
|
|
7190
|
-
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES$
|
|
7189
|
+
allowedTags: DEFAULT_ALLOWED_TAGS$2,
|
|
7190
|
+
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES$2,
|
|
7191
7191
|
allowDataUrls: false,
|
|
7192
7192
|
allowStyles: false,
|
|
7193
7193
|
allowClass: false,
|
|
@@ -7196,14 +7196,14 @@ function normalizeOptions$e(binding) {
|
|
|
7196
7196
|
sanitizeOnUpdate: true
|
|
7197
7197
|
}, binding);
|
|
7198
7198
|
}
|
|
7199
|
-
function sanitizeHtml(html, options) {
|
|
7199
|
+
function sanitizeHtml$1(html, options) {
|
|
7200
7200
|
var _a2;
|
|
7201
7201
|
if (options.handler) {
|
|
7202
7202
|
return options.handler(html);
|
|
7203
7203
|
}
|
|
7204
7204
|
const temp = document.createElement("div");
|
|
7205
7205
|
temp.innerHTML = html;
|
|
7206
|
-
for (const tag of DANGEROUS_TAGS$
|
|
7206
|
+
for (const tag of DANGEROUS_TAGS$2) {
|
|
7207
7207
|
const elements = temp.getElementsByTagName(tag);
|
|
7208
7208
|
while (elements.length > 0) {
|
|
7209
7209
|
(_a2 = elements[0].parentNode) == null ? void 0 : _a2.removeChild(elements[0]);
|
|
@@ -7217,7 +7217,7 @@ function sanitizeHtml(html, options) {
|
|
|
7217
7217
|
(_a3 = el.parentNode) == null ? void 0 : _a3.replaceChild(text, el);
|
|
7218
7218
|
return;
|
|
7219
7219
|
}
|
|
7220
|
-
for (const attr of DANGEROUS_ATTRIBUTES$
|
|
7220
|
+
for (const attr of DANGEROUS_ATTRIBUTES$2) {
|
|
7221
7221
|
el.removeAttribute(attr);
|
|
7222
7222
|
}
|
|
7223
7223
|
const href = el.getAttribute("href");
|
|
@@ -7255,8 +7255,8 @@ const vSanitize = defineDirective({
|
|
|
7255
7255
|
name: "sanitize",
|
|
7256
7256
|
ssr: true,
|
|
7257
7257
|
defaults: {
|
|
7258
|
-
allowedTags: DEFAULT_ALLOWED_TAGS$
|
|
7259
|
-
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES$
|
|
7258
|
+
allowedTags: DEFAULT_ALLOWED_TAGS$2,
|
|
7259
|
+
allowedAttributes: DEFAULT_ALLOWED_ATTRIBUTES$2,
|
|
7260
7260
|
allowDataUrls: false,
|
|
7261
7261
|
allowStyles: false,
|
|
7262
7262
|
allowClass: false,
|
|
@@ -7271,7 +7271,7 @@ const vSanitize = defineDirective({
|
|
|
7271
7271
|
if (options.disabled) return;
|
|
7272
7272
|
const content = el.innerHTML;
|
|
7273
7273
|
if (content) {
|
|
7274
|
-
el.innerHTML = sanitizeHtml(content, options);
|
|
7274
|
+
el.innerHTML = sanitizeHtml$1(content, options);
|
|
7275
7275
|
}
|
|
7276
7276
|
},
|
|
7277
7277
|
updated(el, binding) {
|
|
@@ -7283,14 +7283,14 @@ const vSanitize = defineDirective({
|
|
|
7283
7283
|
if (prevDisabled && !state2.options.disabled) {
|
|
7284
7284
|
const content2 = el.innerHTML;
|
|
7285
7285
|
if (content2) {
|
|
7286
|
-
el.innerHTML = sanitizeHtml(content2, state2.options);
|
|
7286
|
+
el.innerHTML = sanitizeHtml$1(content2, state2.options);
|
|
7287
7287
|
}
|
|
7288
7288
|
}
|
|
7289
7289
|
return;
|
|
7290
7290
|
}
|
|
7291
7291
|
const content = el.innerHTML;
|
|
7292
7292
|
if (content) {
|
|
7293
|
-
el.innerHTML = sanitizeHtml(content, state2.options);
|
|
7293
|
+
el.innerHTML = sanitizeHtml$1(content, state2.options);
|
|
7294
7294
|
}
|
|
7295
7295
|
},
|
|
7296
7296
|
unmounted(el) {
|
|
@@ -13698,14 +13698,14 @@ function useRotateGesture(options = {}) {
|
|
|
13698
13698
|
bind
|
|
13699
13699
|
};
|
|
13700
13700
|
}
|
|
13701
|
-
const DEFAULT_ALLOWED_TAGS = ["b", "i", "u", "strong", "em", "br", "p", "span", "div"];
|
|
13702
|
-
const DEFAULT_ALLOWED_ATTRIBUTES = ["title", "alt", "href", "src"];
|
|
13703
|
-
const DANGEROUS_TAGS = ["script", "iframe", "object", "embed", "form", "input", "style", "link", "meta", "base"];
|
|
13704
|
-
const DANGEROUS_ATTRIBUTES = ["onclick", "onerror", "onload", "onmouseover", "onfocus", "onblur", "onchange", "onsubmit"];
|
|
13701
|
+
const DEFAULT_ALLOWED_TAGS$1 = ["b", "i", "u", "strong", "em", "br", "p", "span", "div"];
|
|
13702
|
+
const DEFAULT_ALLOWED_ATTRIBUTES$1 = ["title", "alt", "href", "src"];
|
|
13703
|
+
const DANGEROUS_TAGS$1 = ["script", "iframe", "object", "embed", "form", "input", "style", "link", "meta", "base"];
|
|
13704
|
+
const DANGEROUS_ATTRIBUTES$1 = ["onclick", "onerror", "onload", "onmouseover", "onfocus", "onblur", "onchange", "onsubmit"];
|
|
13705
13705
|
function useSanitize(options = {}) {
|
|
13706
13706
|
const {
|
|
13707
|
-
allowedTags = DEFAULT_ALLOWED_TAGS,
|
|
13708
|
-
allowedAttributes = DEFAULT_ALLOWED_ATTRIBUTES,
|
|
13707
|
+
allowedTags = DEFAULT_ALLOWED_TAGS$1,
|
|
13708
|
+
allowedAttributes = DEFAULT_ALLOWED_ATTRIBUTES$1,
|
|
13709
13709
|
allowDataUrls = false,
|
|
13710
13710
|
allowStyles = false,
|
|
13711
13711
|
allowClass = false,
|
|
@@ -13720,7 +13720,7 @@ function useSanitize(options = {}) {
|
|
|
13720
13720
|
if (!isBrowser()) return html;
|
|
13721
13721
|
const temp = document.createElement("div");
|
|
13722
13722
|
temp.innerHTML = html;
|
|
13723
|
-
for (const tag of DANGEROUS_TAGS) {
|
|
13723
|
+
for (const tag of DANGEROUS_TAGS$1) {
|
|
13724
13724
|
const elements = temp.getElementsByTagName(tag);
|
|
13725
13725
|
while (elements.length > 0) {
|
|
13726
13726
|
(_a2 = elements[0].parentNode) == null ? void 0 : _a2.removeChild(elements[0]);
|
|
@@ -13734,7 +13734,7 @@ function useSanitize(options = {}) {
|
|
|
13734
13734
|
(_a3 = el.parentNode) == null ? void 0 : _a3.replaceChild(text, el);
|
|
13735
13735
|
return;
|
|
13736
13736
|
}
|
|
13737
|
-
for (const attr of DANGEROUS_ATTRIBUTES) {
|
|
13737
|
+
for (const attr of DANGEROUS_ATTRIBUTES$1) {
|
|
13738
13738
|
el.removeAttribute(attr);
|
|
13739
13739
|
}
|
|
13740
13740
|
const href = el.getAttribute("href");
|
|
@@ -15770,6 +15770,1734 @@ function createStyleDirective(options) {
|
|
|
15770
15770
|
}
|
|
15771
15771
|
});
|
|
15772
15772
|
}
|
|
15773
|
+
function applyAriaAttributes(el, config) {
|
|
15774
|
+
clearAriaAttributes(el);
|
|
15775
|
+
if (config.role) {
|
|
15776
|
+
el.setAttribute("role", config.role);
|
|
15777
|
+
}
|
|
15778
|
+
if (config.ariaExpanded !== void 0) {
|
|
15779
|
+
el.setAttribute("aria-expanded", String(config.ariaExpanded));
|
|
15780
|
+
}
|
|
15781
|
+
if (config.ariaSelected !== void 0) {
|
|
15782
|
+
el.setAttribute("aria-selected", String(config.ariaSelected));
|
|
15783
|
+
}
|
|
15784
|
+
if (config.ariaChecked !== void 0) {
|
|
15785
|
+
el.setAttribute("aria-checked", String(config.ariaChecked));
|
|
15786
|
+
}
|
|
15787
|
+
if (config.ariaDisabled !== void 0) {
|
|
15788
|
+
el.setAttribute("aria-disabled", String(config.ariaDisabled));
|
|
15789
|
+
if (config.ariaDisabled) {
|
|
15790
|
+
el.setAttribute("tabindex", "-1");
|
|
15791
|
+
}
|
|
15792
|
+
}
|
|
15793
|
+
if (config.ariaHidden !== void 0) {
|
|
15794
|
+
el.setAttribute("aria-hidden", String(config.ariaHidden));
|
|
15795
|
+
}
|
|
15796
|
+
if (config.ariaBusy !== void 0) {
|
|
15797
|
+
el.setAttribute("aria-busy", String(config.ariaBusy));
|
|
15798
|
+
}
|
|
15799
|
+
if (config.ariaPressed !== void 0) {
|
|
15800
|
+
el.setAttribute("aria-pressed", String(config.ariaPressed));
|
|
15801
|
+
}
|
|
15802
|
+
if (config.ariaCurrent !== void 0) {
|
|
15803
|
+
el.setAttribute("aria-current", typeof config.ariaCurrent === "boolean" ? String(config.ariaCurrent) : config.ariaCurrent);
|
|
15804
|
+
}
|
|
15805
|
+
if (config.ariaLabel) {
|
|
15806
|
+
el.setAttribute("aria-label", config.ariaLabel);
|
|
15807
|
+
}
|
|
15808
|
+
if (config.ariaLabelledBy) {
|
|
15809
|
+
el.setAttribute("aria-labelledby", config.ariaLabelledBy);
|
|
15810
|
+
}
|
|
15811
|
+
if (config.ariaDescribedBy) {
|
|
15812
|
+
el.setAttribute("aria-describedby", config.ariaDescribedBy);
|
|
15813
|
+
}
|
|
15814
|
+
if (config.ariaControls) {
|
|
15815
|
+
el.setAttribute("aria-controls", config.ariaControls);
|
|
15816
|
+
}
|
|
15817
|
+
if (config.ariaOwns) {
|
|
15818
|
+
el.setAttribute("aria-owns", config.ariaOwns);
|
|
15819
|
+
}
|
|
15820
|
+
if (config.ariaHasPopup !== void 0) {
|
|
15821
|
+
const value = typeof config.ariaHasPopup === "boolean" ? "true" : config.ariaHasPopup;
|
|
15822
|
+
el.setAttribute("aria-haspopup", value);
|
|
15823
|
+
}
|
|
15824
|
+
if (config.ariaAutoComplete) {
|
|
15825
|
+
el.setAttribute("aria-autocomplete", config.ariaAutoComplete);
|
|
15826
|
+
}
|
|
15827
|
+
if (config.ariaLive) {
|
|
15828
|
+
el.setAttribute("aria-live", config.ariaLive);
|
|
15829
|
+
}
|
|
15830
|
+
if (config.ariaAtomic !== void 0) {
|
|
15831
|
+
el.setAttribute("aria-atomic", String(config.ariaAtomic));
|
|
15832
|
+
}
|
|
15833
|
+
if (config.ariaRelevant) {
|
|
15834
|
+
el.setAttribute("aria-relevant", config.ariaRelevant);
|
|
15835
|
+
}
|
|
15836
|
+
if (config.ariaValueNow !== void 0) {
|
|
15837
|
+
el.setAttribute("aria-valuenow", String(config.ariaValueNow));
|
|
15838
|
+
}
|
|
15839
|
+
if (config.ariaValueMin !== void 0) {
|
|
15840
|
+
el.setAttribute("aria-valuemin", String(config.ariaValueMin));
|
|
15841
|
+
}
|
|
15842
|
+
if (config.ariaValueMax !== void 0) {
|
|
15843
|
+
el.setAttribute("aria-valuemax", String(config.ariaValueMax));
|
|
15844
|
+
}
|
|
15845
|
+
if (config.ariaValueText) {
|
|
15846
|
+
el.setAttribute("aria-valuetext", config.ariaValueText);
|
|
15847
|
+
}
|
|
15848
|
+
if (config.ariaPlaceholder) {
|
|
15849
|
+
el.setAttribute("aria-placeholder", config.ariaPlaceholder);
|
|
15850
|
+
}
|
|
15851
|
+
if (config.ariaRequired !== void 0) {
|
|
15852
|
+
el.setAttribute("aria-required", String(config.ariaRequired));
|
|
15853
|
+
}
|
|
15854
|
+
if (config.ariaReadonly !== void 0) {
|
|
15855
|
+
el.setAttribute("aria-readonly", String(config.ariaReadonly));
|
|
15856
|
+
}
|
|
15857
|
+
if (config.ariaModal !== void 0) {
|
|
15858
|
+
el.setAttribute("aria-modal", String(config.ariaModal));
|
|
15859
|
+
}
|
|
15860
|
+
if (config.tabIndex !== void 0) {
|
|
15861
|
+
el.setAttribute("tabindex", String(config.tabIndex));
|
|
15862
|
+
}
|
|
15863
|
+
}
|
|
15864
|
+
function clearAriaAttributes(el) {
|
|
15865
|
+
const ariaAttrs = Array.from(el.attributes).filter((attr) => attr.name.startsWith("aria-") || attr.name === "role");
|
|
15866
|
+
ariaAttrs.forEach((attr) => el.removeAttribute(attr.name));
|
|
15867
|
+
}
|
|
15868
|
+
function generateAriaId(prefix = "directix-aria") {
|
|
15869
|
+
return `${prefix}-${Math.random().toString(36).substring(2, 10)}`;
|
|
15870
|
+
}
|
|
15871
|
+
let announcerElement = null, announcerId = null;
|
|
15872
|
+
function ensureAnnouncer() {
|
|
15873
|
+
if (announcerElement && document.getElementById(announcerId || "")) {
|
|
15874
|
+
return announcerElement;
|
|
15875
|
+
}
|
|
15876
|
+
announcerId = "directix-sr-announcer";
|
|
15877
|
+
announcerElement = document.createElement("div");
|
|
15878
|
+
announcerElement.id = announcerId;
|
|
15879
|
+
announcerElement.setAttribute("aria-live", "polite");
|
|
15880
|
+
announcerElement.setAttribute("aria-atomic", "true");
|
|
15881
|
+
announcerElement.setAttribute(
|
|
15882
|
+
"style",
|
|
15883
|
+
"position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;"
|
|
15884
|
+
);
|
|
15885
|
+
document.body.appendChild(announcerElement);
|
|
15886
|
+
return announcerElement;
|
|
15887
|
+
}
|
|
15888
|
+
function announce(message, options = {}) {
|
|
15889
|
+
if (!isBrowser()) return;
|
|
15890
|
+
const { priority = "polite", timeout = 1e3, clear = true } = options;
|
|
15891
|
+
const announcer = ensureAnnouncer();
|
|
15892
|
+
announcer.setAttribute("aria-live", priority);
|
|
15893
|
+
announcer.textContent = "";
|
|
15894
|
+
requestAnimationFrame(() => {
|
|
15895
|
+
announcer.textContent = message;
|
|
15896
|
+
if (clear) {
|
|
15897
|
+
setTimeout(() => {
|
|
15898
|
+
if (announcer.textContent === message) {
|
|
15899
|
+
announcer.textContent = "";
|
|
15900
|
+
}
|
|
15901
|
+
}, timeout);
|
|
15902
|
+
}
|
|
15903
|
+
});
|
|
15904
|
+
}
|
|
15905
|
+
function clearAnnouncer() {
|
|
15906
|
+
if (announcerElement) {
|
|
15907
|
+
announcerElement.textContent = "";
|
|
15908
|
+
}
|
|
15909
|
+
}
|
|
15910
|
+
const DEFAULT_NEXT_KEYS = ["ArrowDown", "ArrowRight"];
|
|
15911
|
+
const DEFAULT_PREV_KEYS = ["ArrowUp", "ArrowLeft"];
|
|
15912
|
+
const DEFAULT_SELECT_KEYS = ["Enter", " "];
|
|
15913
|
+
const DEFAULT_CLOSE_KEYS = ["Escape"];
|
|
15914
|
+
const DEFAULT_HOME_KEYS = ["Home"];
|
|
15915
|
+
const DEFAULT_END_KEYS = ["End"];
|
|
15916
|
+
function useKeyboardNavigation(options = {}) {
|
|
15917
|
+
const {
|
|
15918
|
+
nextKeys = DEFAULT_NEXT_KEYS,
|
|
15919
|
+
prevKeys = DEFAULT_PREV_KEYS,
|
|
15920
|
+
selectKeys = DEFAULT_SELECT_KEYS,
|
|
15921
|
+
closeKeys = DEFAULT_CLOSE_KEYS,
|
|
15922
|
+
homeKeys = DEFAULT_HOME_KEYS,
|
|
15923
|
+
endKeys = DEFAULT_END_KEYS,
|
|
15924
|
+
focusTrap = false,
|
|
15925
|
+
returnFocus = true,
|
|
15926
|
+
mode: _mode = "linear",
|
|
15927
|
+
loop = true,
|
|
15928
|
+
rovingTabindex = false
|
|
15929
|
+
} = options;
|
|
15930
|
+
const focusedIndex = ref(0);
|
|
15931
|
+
let items = [], triggerElement = null, cleanup2 = null;
|
|
15932
|
+
function getFocusables() {
|
|
15933
|
+
return items.filter((item) => !item.hasAttribute("disabled") && item.getAttribute("aria-disabled") !== "true");
|
|
15934
|
+
}
|
|
15935
|
+
function focusIndex(index) {
|
|
15936
|
+
const focusables = getFocusables();
|
|
15937
|
+
if (focusables.length === 0) return;
|
|
15938
|
+
let newIndex = index;
|
|
15939
|
+
if (newIndex < 0) {
|
|
15940
|
+
newIndex = loop ? focusables.length - 1 : 0;
|
|
15941
|
+
} else if (newIndex >= focusables.length) {
|
|
15942
|
+
newIndex = loop ? 0 : focusables.length - 1;
|
|
15943
|
+
}
|
|
15944
|
+
const target = focusables[newIndex];
|
|
15945
|
+
if (target) {
|
|
15946
|
+
target.focus();
|
|
15947
|
+
if (rovingTabindex) {
|
|
15948
|
+
focusables.forEach((item, i) => {
|
|
15949
|
+
item.setAttribute("tabindex", i === newIndex ? "0" : "-1");
|
|
15950
|
+
});
|
|
15951
|
+
}
|
|
15952
|
+
focusedIndex.value = newIndex;
|
|
15953
|
+
}
|
|
15954
|
+
}
|
|
15955
|
+
function focusNext() {
|
|
15956
|
+
focusIndex(focusedIndex.value + 1);
|
|
15957
|
+
}
|
|
15958
|
+
function focusPrev() {
|
|
15959
|
+
focusIndex(focusedIndex.value - 1);
|
|
15960
|
+
}
|
|
15961
|
+
function focusFirst() {
|
|
15962
|
+
focusIndex(0);
|
|
15963
|
+
}
|
|
15964
|
+
function focusLast() {
|
|
15965
|
+
focusIndex(getFocusables().length - 1);
|
|
15966
|
+
}
|
|
15967
|
+
function handleKeyDown(e) {
|
|
15968
|
+
var _a2;
|
|
15969
|
+
const isModified = e.altKey || e.ctrlKey || e.metaKey;
|
|
15970
|
+
if (isModified) return;
|
|
15971
|
+
if (focusTrap && e.key === "Tab") {
|
|
15972
|
+
const focusables = getFocusables();
|
|
15973
|
+
if (focusables.length === 0) return;
|
|
15974
|
+
e.preventDefault();
|
|
15975
|
+
if (e.shiftKey) {
|
|
15976
|
+
focusPrev();
|
|
15977
|
+
} else {
|
|
15978
|
+
focusNext();
|
|
15979
|
+
}
|
|
15980
|
+
return;
|
|
15981
|
+
}
|
|
15982
|
+
if (nextKeys.includes(e.key)) {
|
|
15983
|
+
e.preventDefault();
|
|
15984
|
+
focusNext();
|
|
15985
|
+
} else if (prevKeys.includes(e.key)) {
|
|
15986
|
+
e.preventDefault();
|
|
15987
|
+
focusPrev();
|
|
15988
|
+
} else if (homeKeys.includes(e.key)) {
|
|
15989
|
+
e.preventDefault();
|
|
15990
|
+
focusFirst();
|
|
15991
|
+
} else if (endKeys.includes(e.key)) {
|
|
15992
|
+
e.preventDefault();
|
|
15993
|
+
focusLast();
|
|
15994
|
+
} else if (selectKeys.includes(e.key)) {
|
|
15995
|
+
e.preventDefault();
|
|
15996
|
+
(_a2 = items[focusedIndex.value]) == null ? void 0 : _a2.click();
|
|
15997
|
+
} else if (closeKeys.includes(e.key)) {
|
|
15998
|
+
e.preventDefault();
|
|
15999
|
+
if (returnFocus && triggerElement) {
|
|
16000
|
+
triggerElement.focus();
|
|
16001
|
+
}
|
|
16002
|
+
}
|
|
16003
|
+
}
|
|
16004
|
+
function bind(el, itemElements) {
|
|
16005
|
+
cleanup2 == null ? void 0 : cleanup2();
|
|
16006
|
+
items = itemElements;
|
|
16007
|
+
triggerElement = document.activeElement;
|
|
16008
|
+
el.addEventListener("keydown", handleKeyDown);
|
|
16009
|
+
if (rovingTabindex && items.length > 0) {
|
|
16010
|
+
items.forEach((item, i) => {
|
|
16011
|
+
item.setAttribute("tabindex", i === 0 ? "0" : "-1");
|
|
16012
|
+
});
|
|
16013
|
+
}
|
|
16014
|
+
if (items.length > 0) {
|
|
16015
|
+
focusIndex(0);
|
|
16016
|
+
}
|
|
16017
|
+
cleanup2 = () => {
|
|
16018
|
+
el.removeEventListener("keydown", handleKeyDown);
|
|
16019
|
+
items = [];
|
|
16020
|
+
};
|
|
16021
|
+
return cleanup2;
|
|
16022
|
+
}
|
|
16023
|
+
onUnmounted(() => {
|
|
16024
|
+
cleanup2 == null ? void 0 : cleanup2();
|
|
16025
|
+
});
|
|
16026
|
+
return {
|
|
16027
|
+
focusedIndex: readonly(focusedIndex),
|
|
16028
|
+
bind,
|
|
16029
|
+
focusIndex,
|
|
16030
|
+
focusNext,
|
|
16031
|
+
focusPrev,
|
|
16032
|
+
focusFirst,
|
|
16033
|
+
focusLast
|
|
16034
|
+
};
|
|
16035
|
+
}
|
|
16036
|
+
function useFocusTrap(container, options = {}) {
|
|
16037
|
+
const {
|
|
16038
|
+
initialFocus,
|
|
16039
|
+
allowOutsideClick = false,
|
|
16040
|
+
escapeDeactivates = true,
|
|
16041
|
+
onActivate,
|
|
16042
|
+
onDeactivate
|
|
16043
|
+
} = options;
|
|
16044
|
+
const isActive = ref(false);
|
|
16045
|
+
let lastFocusedElement = null;
|
|
16046
|
+
function getFocusableElements() {
|
|
16047
|
+
const el = container.value;
|
|
16048
|
+
if (!el) return [];
|
|
16049
|
+
const selector = [
|
|
16050
|
+
"a[href]",
|
|
16051
|
+
"button:not([disabled])",
|
|
16052
|
+
"textarea:not([disabled])",
|
|
16053
|
+
"input:not([disabled])",
|
|
16054
|
+
"select:not([disabled])",
|
|
16055
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
16056
|
+
].join(", ");
|
|
16057
|
+
return Array.from(el.querySelectorAll(selector)).filter((item) => !item.hasAttribute("aria-hidden"));
|
|
16058
|
+
}
|
|
16059
|
+
function handleKeyDown(e) {
|
|
16060
|
+
if (!isActive.value) return;
|
|
16061
|
+
if (escapeDeactivates && e.key === "Escape") {
|
|
16062
|
+
e.preventDefault();
|
|
16063
|
+
deactivate();
|
|
16064
|
+
return;
|
|
16065
|
+
}
|
|
16066
|
+
if (e.key !== "Tab") return;
|
|
16067
|
+
const el = container.value;
|
|
16068
|
+
if (!el) return;
|
|
16069
|
+
const focusables = getFocusableElements();
|
|
16070
|
+
if (focusables.length === 0) return;
|
|
16071
|
+
const firstFocusable = focusables[0];
|
|
16072
|
+
const lastFocusable = focusables[focusables.length - 1];
|
|
16073
|
+
const currentElement = document.activeElement;
|
|
16074
|
+
if (e.shiftKey) {
|
|
16075
|
+
if (currentElement === firstFocusable || !el.contains(currentElement)) {
|
|
16076
|
+
e.preventDefault();
|
|
16077
|
+
lastFocusable.focus();
|
|
16078
|
+
}
|
|
16079
|
+
} else {
|
|
16080
|
+
if (currentElement === lastFocusable || !el.contains(currentElement)) {
|
|
16081
|
+
e.preventDefault();
|
|
16082
|
+
firstFocusable.focus();
|
|
16083
|
+
}
|
|
16084
|
+
}
|
|
16085
|
+
}
|
|
16086
|
+
function handleOutsideClick(event) {
|
|
16087
|
+
if (!isActive.value) return;
|
|
16088
|
+
if (!container.value) return;
|
|
16089
|
+
if (typeof allowOutsideClick === "boolean" && !allowOutsideClick) {
|
|
16090
|
+
event.preventDefault();
|
|
16091
|
+
return;
|
|
16092
|
+
}
|
|
16093
|
+
if (typeof allowOutsideClick === "function" && !allowOutsideClick(event)) {
|
|
16094
|
+
event.preventDefault();
|
|
16095
|
+
}
|
|
16096
|
+
}
|
|
16097
|
+
function activate() {
|
|
16098
|
+
var _a2;
|
|
16099
|
+
if (isActive.value) return;
|
|
16100
|
+
lastFocusedElement = document.activeElement;
|
|
16101
|
+
if (initialFocus) {
|
|
16102
|
+
let initialEl = null;
|
|
16103
|
+
if (typeof initialFocus === "function") {
|
|
16104
|
+
initialEl = initialFocus();
|
|
16105
|
+
} else if (typeof initialFocus === "string") {
|
|
16106
|
+
initialEl = ((_a2 = container.value) == null ? void 0 : _a2.querySelector(initialFocus)) || null;
|
|
16107
|
+
} else {
|
|
16108
|
+
initialEl = initialFocus;
|
|
16109
|
+
}
|
|
16110
|
+
initialEl == null ? void 0 : initialEl.focus();
|
|
16111
|
+
} else {
|
|
16112
|
+
const focusables = getFocusableElements();
|
|
16113
|
+
if (focusables.length > 0) {
|
|
16114
|
+
focusables[0].focus();
|
|
16115
|
+
}
|
|
16116
|
+
}
|
|
16117
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
16118
|
+
document.addEventListener("mousedown", handleOutsideClick);
|
|
16119
|
+
document.addEventListener("touchstart", handleOutsideClick);
|
|
16120
|
+
isActive.value = true;
|
|
16121
|
+
onActivate == null ? void 0 : onActivate();
|
|
16122
|
+
}
|
|
16123
|
+
function deactivate() {
|
|
16124
|
+
if (!isActive.value) return;
|
|
16125
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
16126
|
+
document.removeEventListener("mousedown", handleOutsideClick);
|
|
16127
|
+
document.removeEventListener("touchstart", handleOutsideClick);
|
|
16128
|
+
if (lastFocusedElement && lastFocusedElement.focus) {
|
|
16129
|
+
lastFocusedElement.focus();
|
|
16130
|
+
}
|
|
16131
|
+
isActive.value = false;
|
|
16132
|
+
onDeactivate == null ? void 0 : onDeactivate();
|
|
16133
|
+
}
|
|
16134
|
+
onUnmounted(() => {
|
|
16135
|
+
deactivate();
|
|
16136
|
+
});
|
|
16137
|
+
return {
|
|
16138
|
+
activate,
|
|
16139
|
+
deactivate,
|
|
16140
|
+
isActive: readonly(isActive)
|
|
16141
|
+
};
|
|
16142
|
+
}
|
|
16143
|
+
function getAutoAriaConfig(options) {
|
|
16144
|
+
const { type, label, expanded, disabled, relatedId } = options;
|
|
16145
|
+
const configs = {
|
|
16146
|
+
tooltip: {
|
|
16147
|
+
role: "tooltip",
|
|
16148
|
+
ariaHidden: expanded === void 0 ? true : !expanded
|
|
16149
|
+
},
|
|
16150
|
+
menu: {
|
|
16151
|
+
role: "menu",
|
|
16152
|
+
ariaLabel: label,
|
|
16153
|
+
ariaExpanded: expanded,
|
|
16154
|
+
ariaDisabled: disabled
|
|
16155
|
+
},
|
|
16156
|
+
dialog: {
|
|
16157
|
+
role: "dialog",
|
|
16158
|
+
ariaLabel: label,
|
|
16159
|
+
ariaModal: true
|
|
16160
|
+
},
|
|
16161
|
+
popover: {
|
|
16162
|
+
role: "region",
|
|
16163
|
+
ariaLabel: label,
|
|
16164
|
+
ariaExpanded: expanded
|
|
16165
|
+
},
|
|
16166
|
+
dropdown: {
|
|
16167
|
+
role: "listbox",
|
|
16168
|
+
ariaLabel: label,
|
|
16169
|
+
ariaExpanded: expanded
|
|
16170
|
+
},
|
|
16171
|
+
modal: {
|
|
16172
|
+
role: "dialog",
|
|
16173
|
+
ariaModal: true,
|
|
16174
|
+
ariaLabel: label
|
|
16175
|
+
},
|
|
16176
|
+
alert: {
|
|
16177
|
+
role: "alert",
|
|
16178
|
+
ariaLive: "assertive",
|
|
16179
|
+
ariaAtomic: true
|
|
16180
|
+
},
|
|
16181
|
+
region: {
|
|
16182
|
+
role: "region",
|
|
16183
|
+
ariaLabel: label
|
|
16184
|
+
}
|
|
16185
|
+
};
|
|
16186
|
+
const config = __spreadValues({}, configs[type] || {});
|
|
16187
|
+
if (relatedId) {
|
|
16188
|
+
if (type === "tooltip") {
|
|
16189
|
+
config.ariaDescribedBy = relatedId;
|
|
16190
|
+
} else {
|
|
16191
|
+
config.ariaControls = relatedId;
|
|
16192
|
+
}
|
|
16193
|
+
}
|
|
16194
|
+
return config;
|
|
16195
|
+
}
|
|
16196
|
+
const DEFAULT_THRESHOLDS = {
|
|
16197
|
+
tap: 10,
|
|
16198
|
+
longPress: 500,
|
|
16199
|
+
swipe: 30,
|
|
16200
|
+
pinch: 0.1,
|
|
16201
|
+
rotate: 5,
|
|
16202
|
+
doubleTap: 300,
|
|
16203
|
+
swipeVelocity: 0.3
|
|
16204
|
+
};
|
|
16205
|
+
function triggerHaptic(type = "light") {
|
|
16206
|
+
if (!isBrowser()) return;
|
|
16207
|
+
const nav = navigator;
|
|
16208
|
+
if (nav.vibrate) {
|
|
16209
|
+
const patterns = {
|
|
16210
|
+
light: 10,
|
|
16211
|
+
medium: 20,
|
|
16212
|
+
heavy: 30,
|
|
16213
|
+
selection: [10, 50, 10]
|
|
16214
|
+
};
|
|
16215
|
+
nav.vibrate(patterns[type]);
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
function applyVisualFeedback(element, options = {}) {
|
|
16219
|
+
const {
|
|
16220
|
+
visualClass = "directix-touch-active",
|
|
16221
|
+
visualDuration = 150
|
|
16222
|
+
} = options;
|
|
16223
|
+
element.classList.add(visualClass);
|
|
16224
|
+
const timer = setTimeout(() => {
|
|
16225
|
+
element.classList.remove(visualClass);
|
|
16226
|
+
}, visualDuration);
|
|
16227
|
+
return () => {
|
|
16228
|
+
clearTimeout(timer);
|
|
16229
|
+
element.classList.remove(visualClass);
|
|
16230
|
+
};
|
|
16231
|
+
}
|
|
16232
|
+
function calculateVelocity(startX, startY, endX, endY, duration) {
|
|
16233
|
+
if (duration === 0) return 0;
|
|
16234
|
+
const distance = Math.sqrt(__pow(endX - startX, 2) + __pow(endY - startY, 2));
|
|
16235
|
+
return distance / duration;
|
|
16236
|
+
}
|
|
16237
|
+
function isEdgePoint(x, y, edgeSize = 20) {
|
|
16238
|
+
if (!isBrowser()) return { isEdge: false };
|
|
16239
|
+
const width = window.innerWidth;
|
|
16240
|
+
const height = window.innerHeight;
|
|
16241
|
+
if (x <= edgeSize) return { isEdge: true, edge: "left" };
|
|
16242
|
+
if (x >= width - edgeSize) return { isEdge: true, edge: "right" };
|
|
16243
|
+
if (y <= edgeSize) return { isEdge: true, edge: "top" };
|
|
16244
|
+
if (y >= height - edgeSize) return { isEdge: true, edge: "bottom" };
|
|
16245
|
+
return { isEdge: false };
|
|
16246
|
+
}
|
|
16247
|
+
function useEnhancedTouch(options = {}) {
|
|
16248
|
+
const {
|
|
16249
|
+
thresholds: userThresholds = {},
|
|
16250
|
+
feedback = {},
|
|
16251
|
+
debounce: debounce2 = 0,
|
|
16252
|
+
throttle: throttle2 = 16,
|
|
16253
|
+
passive = true,
|
|
16254
|
+
disabled = false,
|
|
16255
|
+
onTap,
|
|
16256
|
+
onDoubleTap,
|
|
16257
|
+
onLongPress,
|
|
16258
|
+
onSwipe,
|
|
16259
|
+
onSwipeLeft,
|
|
16260
|
+
onSwipeRight,
|
|
16261
|
+
onSwipeUp,
|
|
16262
|
+
onSwipeDown,
|
|
16263
|
+
onPan,
|
|
16264
|
+
onPinch,
|
|
16265
|
+
onPinchIn,
|
|
16266
|
+
onPinchOut,
|
|
16267
|
+
onRotate,
|
|
16268
|
+
onTwoFingerTap,
|
|
16269
|
+
onEdgeSwipe
|
|
16270
|
+
} = options;
|
|
16271
|
+
const thresholds = __spreadValues(__spreadValues({}, DEFAULT_THRESHOLDS), userThresholds);
|
|
16272
|
+
const activeGesture = ref(null);
|
|
16273
|
+
const isTouching = ref(false);
|
|
16274
|
+
let currentElement = null, startX = 0, startY = 0, startTime = 0, lastTapTime = 0, lastPanTime = 0, longPressTimer = null, initialPinchDistance = 0, initialAngle = 0, removeVisualFeedback = null, lastGestureTime = 0;
|
|
16275
|
+
function getTouchCenter(touches) {
|
|
16276
|
+
let x = 0, y = 0;
|
|
16277
|
+
for (let i = 0; i < touches.length; i++) {
|
|
16278
|
+
x += touches[i].clientX;
|
|
16279
|
+
y += touches[i].clientY;
|
|
16280
|
+
}
|
|
16281
|
+
return { x: x / touches.length, y: y / touches.length };
|
|
16282
|
+
}
|
|
16283
|
+
function getDistance2(t1, t2) {
|
|
16284
|
+
return Math.sqrt(__pow(t1.clientX - t2.clientX, 2) + __pow(t1.clientY - t2.clientY, 2));
|
|
16285
|
+
}
|
|
16286
|
+
function getAngle2(t1, t2) {
|
|
16287
|
+
return Math.atan2(t2.clientY - t1.clientY, t2.clientX - t1.clientX) * (180 / Math.PI);
|
|
16288
|
+
}
|
|
16289
|
+
function shouldProcessGesture() {
|
|
16290
|
+
if (typeof disabled === "boolean" ? disabled : disabled.value) return false;
|
|
16291
|
+
if (debounce2 > 0 && Date.now() - lastGestureTime < debounce2) return false;
|
|
16292
|
+
return true;
|
|
16293
|
+
}
|
|
16294
|
+
function handleTouchStart(e) {
|
|
16295
|
+
if (!shouldProcessGesture()) return;
|
|
16296
|
+
isTouching.value = true;
|
|
16297
|
+
startTime = Date.now();
|
|
16298
|
+
activeGesture.value = null;
|
|
16299
|
+
if (feedback.haptic) {
|
|
16300
|
+
triggerHaptic("light");
|
|
16301
|
+
}
|
|
16302
|
+
if (e.touches.length === 1) {
|
|
16303
|
+
startX = e.touches[0].clientX;
|
|
16304
|
+
startY = e.touches[0].clientY;
|
|
16305
|
+
if (onLongPress) {
|
|
16306
|
+
longPressTimer = setTimeout(() => {
|
|
16307
|
+
if (!activeGesture.value) {
|
|
16308
|
+
activeGesture.value = "longPress";
|
|
16309
|
+
lastGestureTime = Date.now();
|
|
16310
|
+
onLongPress({
|
|
16311
|
+
type: "longPress",
|
|
16312
|
+
center: { x: startX, y: startY },
|
|
16313
|
+
event: e,
|
|
16314
|
+
duration: Date.now() - startTime
|
|
16315
|
+
});
|
|
16316
|
+
if (feedback.haptic) triggerHaptic("medium");
|
|
16317
|
+
}
|
|
16318
|
+
}, thresholds.longPress);
|
|
16319
|
+
}
|
|
16320
|
+
} else if (e.touches.length === 2) {
|
|
16321
|
+
if (longPressTimer) {
|
|
16322
|
+
clearTimeout(longPressTimer);
|
|
16323
|
+
longPressTimer = null;
|
|
16324
|
+
}
|
|
16325
|
+
initialPinchDistance = getDistance2(e.touches[0], e.touches[1]);
|
|
16326
|
+
initialAngle = getAngle2(e.touches[0], e.touches[1]);
|
|
16327
|
+
}
|
|
16328
|
+
}
|
|
16329
|
+
function handleTouchMove(e) {
|
|
16330
|
+
if (!shouldProcessGesture()) return;
|
|
16331
|
+
if (longPressTimer) {
|
|
16332
|
+
clearTimeout(longPressTimer);
|
|
16333
|
+
longPressTimer = null;
|
|
16334
|
+
}
|
|
16335
|
+
if (e.touches.length === 1) {
|
|
16336
|
+
const currentX = e.touches[0].clientX;
|
|
16337
|
+
const currentY = e.touches[0].clientY;
|
|
16338
|
+
if (onPan) {
|
|
16339
|
+
const now = Date.now();
|
|
16340
|
+
if (now - lastPanTime >= throttle2) {
|
|
16341
|
+
lastPanTime = now;
|
|
16342
|
+
const deltaX = currentX - startX;
|
|
16343
|
+
const deltaY = currentY - startY;
|
|
16344
|
+
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
16345
|
+
if (distance > thresholds.tap) {
|
|
16346
|
+
activeGesture.value = "pan";
|
|
16347
|
+
onPan({
|
|
16348
|
+
type: "pan",
|
|
16349
|
+
distance,
|
|
16350
|
+
angle: Math.atan2(deltaY, deltaX) * (180 / Math.PI),
|
|
16351
|
+
center: { x: currentX, y: currentY },
|
|
16352
|
+
event: e
|
|
16353
|
+
});
|
|
16354
|
+
}
|
|
16355
|
+
}
|
|
16356
|
+
}
|
|
16357
|
+
} else if (e.touches.length === 2) {
|
|
16358
|
+
const currentDistance = getDistance2(e.touches[0], e.touches[1]);
|
|
16359
|
+
const currentAngle = getAngle2(e.touches[0], e.touches[1]);
|
|
16360
|
+
if (onPinch && initialPinchDistance > 0) {
|
|
16361
|
+
const scale = currentDistance / initialPinchDistance;
|
|
16362
|
+
const deltaScale = Math.abs(scale - 1);
|
|
16363
|
+
if (deltaScale > thresholds.pinch) {
|
|
16364
|
+
activeGesture.value = "pinch";
|
|
16365
|
+
onPinch({
|
|
16366
|
+
type: "pinch",
|
|
16367
|
+
scale,
|
|
16368
|
+
center: getTouchCenter(e.touches),
|
|
16369
|
+
event: e
|
|
16370
|
+
});
|
|
16371
|
+
if (scale < 1 && onPinchIn) {
|
|
16372
|
+
onPinchIn({
|
|
16373
|
+
type: "pinchIn",
|
|
16374
|
+
scale,
|
|
16375
|
+
center: getTouchCenter(e.touches),
|
|
16376
|
+
event: e
|
|
16377
|
+
});
|
|
16378
|
+
} else if (scale > 1 && onPinchOut) {
|
|
16379
|
+
onPinchOut({
|
|
16380
|
+
type: "pinchOut",
|
|
16381
|
+
scale,
|
|
16382
|
+
center: getTouchCenter(e.touches),
|
|
16383
|
+
event: e
|
|
16384
|
+
});
|
|
16385
|
+
}
|
|
16386
|
+
}
|
|
16387
|
+
}
|
|
16388
|
+
if (onRotate) {
|
|
16389
|
+
const rotation = currentAngle - initialAngle;
|
|
16390
|
+
if (Math.abs(rotation) > thresholds.rotate) {
|
|
16391
|
+
activeGesture.value = "rotate";
|
|
16392
|
+
onRotate({
|
|
16393
|
+
type: "rotate",
|
|
16394
|
+
rotation,
|
|
16395
|
+
center: getTouchCenter(e.touches),
|
|
16396
|
+
event: e
|
|
16397
|
+
});
|
|
16398
|
+
}
|
|
16399
|
+
}
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
16402
|
+
function handleTouchEnd(e) {
|
|
16403
|
+
var _a2, _b, _c, _d;
|
|
16404
|
+
if (!shouldProcessGesture()) return;
|
|
16405
|
+
isTouching.value = false;
|
|
16406
|
+
if (longPressTimer) {
|
|
16407
|
+
clearTimeout(longPressTimer);
|
|
16408
|
+
longPressTimer = null;
|
|
16409
|
+
}
|
|
16410
|
+
const duration = Date.now() - startTime;
|
|
16411
|
+
const endX = (_b = (_a2 = e.changedTouches[0]) == null ? void 0 : _a2.clientX) != null ? _b : startX;
|
|
16412
|
+
const endY = (_d = (_c = e.changedTouches[0]) == null ? void 0 : _c.clientY) != null ? _d : startY;
|
|
16413
|
+
const deltaX = endX - startX;
|
|
16414
|
+
const deltaY = endY - startY;
|
|
16415
|
+
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
16416
|
+
const velocity = calculateVelocity(startX, startY, endX, endY, duration);
|
|
16417
|
+
if (e.touches.length === 0 && e.changedTouches.length === 2 && onTwoFingerTap) {
|
|
16418
|
+
const twoFingerDistance = getDistance2(e.changedTouches[0], e.changedTouches[1]);
|
|
16419
|
+
if (twoFingerDistance < 50) {
|
|
16420
|
+
activeGesture.value = "twoFingerTap";
|
|
16421
|
+
onTwoFingerTap({
|
|
16422
|
+
type: "twoFingerTap",
|
|
16423
|
+
center: getTouchCenter(e.changedTouches),
|
|
16424
|
+
event: e
|
|
16425
|
+
});
|
|
16426
|
+
}
|
|
16427
|
+
}
|
|
16428
|
+
if (e.changedTouches.length === 1) {
|
|
16429
|
+
if (distance >= thresholds.swipe) {
|
|
16430
|
+
let direction;
|
|
16431
|
+
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
|
16432
|
+
direction = deltaX > 0 ? "right" : "left";
|
|
16433
|
+
} else {
|
|
16434
|
+
direction = deltaY > 0 ? "down" : "up";
|
|
16435
|
+
}
|
|
16436
|
+
const edge = isEdgePoint(startX, startY);
|
|
16437
|
+
if (edge.isEdge && onEdgeSwipe) {
|
|
16438
|
+
activeGesture.value = "edgeSwipe";
|
|
16439
|
+
onEdgeSwipe({
|
|
16440
|
+
type: "edgeSwipe",
|
|
16441
|
+
direction,
|
|
16442
|
+
distance,
|
|
16443
|
+
velocity,
|
|
16444
|
+
center: { x: endX, y: endY },
|
|
16445
|
+
event: e
|
|
16446
|
+
});
|
|
16447
|
+
}
|
|
16448
|
+
if (!activeGesture.value) {
|
|
16449
|
+
activeGesture.value = "swipe";
|
|
16450
|
+
const swipeEvent = {
|
|
16451
|
+
type: "swipe",
|
|
16452
|
+
direction,
|
|
16453
|
+
distance,
|
|
16454
|
+
velocity,
|
|
16455
|
+
angle: Math.atan2(deltaY, deltaX) * (180 / Math.PI),
|
|
16456
|
+
center: { x: endX, y: endY },
|
|
16457
|
+
event: e,
|
|
16458
|
+
duration
|
|
16459
|
+
};
|
|
16460
|
+
onSwipe == null ? void 0 : onSwipe(swipeEvent);
|
|
16461
|
+
if (direction === "left") onSwipeLeft == null ? void 0 : onSwipeLeft(swipeEvent);
|
|
16462
|
+
if (direction === "right") onSwipeRight == null ? void 0 : onSwipeRight(swipeEvent);
|
|
16463
|
+
if (direction === "up") onSwipeUp == null ? void 0 : onSwipeUp(swipeEvent);
|
|
16464
|
+
if (direction === "down") onSwipeDown == null ? void 0 : onSwipeDown(swipeEvent);
|
|
16465
|
+
if (feedback.haptic) triggerHaptic("light");
|
|
16466
|
+
}
|
|
16467
|
+
} else if (distance < thresholds.tap && duration < 300) {
|
|
16468
|
+
const now = Date.now();
|
|
16469
|
+
const timeSinceLastTap = now - lastTapTime;
|
|
16470
|
+
if (timeSinceLastTap < thresholds.doubleTap && onDoubleTap) {
|
|
16471
|
+
activeGesture.value = "doubleTap";
|
|
16472
|
+
onDoubleTap({
|
|
16473
|
+
type: "doubleTap",
|
|
16474
|
+
center: { x: endX, y: endY },
|
|
16475
|
+
event: e,
|
|
16476
|
+
duration
|
|
16477
|
+
});
|
|
16478
|
+
if (feedback.haptic) triggerHaptic("medium");
|
|
16479
|
+
lastTapTime = 0;
|
|
16480
|
+
} else if (onTap) {
|
|
16481
|
+
if (onDoubleTap) {
|
|
16482
|
+
setTimeout(() => {
|
|
16483
|
+
if (activeGesture.value !== "doubleTap") {
|
|
16484
|
+
activeGesture.value = "tap";
|
|
16485
|
+
onTap({
|
|
16486
|
+
type: "tap",
|
|
16487
|
+
center: { x: endX, y: endY },
|
|
16488
|
+
event: e,
|
|
16489
|
+
duration
|
|
16490
|
+
});
|
|
16491
|
+
if (feedback.haptic) triggerHaptic("light");
|
|
16492
|
+
}
|
|
16493
|
+
}, thresholds.doubleTap);
|
|
16494
|
+
} else {
|
|
16495
|
+
activeGesture.value = "tap";
|
|
16496
|
+
onTap({
|
|
16497
|
+
type: "tap",
|
|
16498
|
+
center: { x: endX, y: endY },
|
|
16499
|
+
event: e,
|
|
16500
|
+
duration
|
|
16501
|
+
});
|
|
16502
|
+
if (feedback.haptic) triggerHaptic("light");
|
|
16503
|
+
}
|
|
16504
|
+
lastTapTime = now;
|
|
16505
|
+
}
|
|
16506
|
+
}
|
|
16507
|
+
}
|
|
16508
|
+
if (removeVisualFeedback) {
|
|
16509
|
+
removeVisualFeedback();
|
|
16510
|
+
removeVisualFeedback = null;
|
|
16511
|
+
}
|
|
16512
|
+
lastGestureTime = Date.now();
|
|
16513
|
+
setTimeout(() => {
|
|
16514
|
+
activeGesture.value = null;
|
|
16515
|
+
}, 100);
|
|
16516
|
+
}
|
|
16517
|
+
function bind(element) {
|
|
16518
|
+
if (!isBrowser()) return () => {
|
|
16519
|
+
};
|
|
16520
|
+
unbind();
|
|
16521
|
+
currentElement = element;
|
|
16522
|
+
const touchOptions = passive ? { passive: true } : void 0;
|
|
16523
|
+
element.addEventListener("touchstart", handleTouchStart, touchOptions);
|
|
16524
|
+
element.addEventListener("touchmove", handleTouchMove, { passive: false });
|
|
16525
|
+
element.addEventListener("touchend", handleTouchEnd);
|
|
16526
|
+
element.addEventListener("touchcancel", handleTouchEnd);
|
|
16527
|
+
if (feedback.visual) {
|
|
16528
|
+
element.addEventListener("touchstart", () => {
|
|
16529
|
+
removeVisualFeedback = applyVisualFeedback(element, feedback);
|
|
16530
|
+
});
|
|
16531
|
+
}
|
|
16532
|
+
return unbind;
|
|
16533
|
+
}
|
|
16534
|
+
function unbind() {
|
|
16535
|
+
if (currentElement) {
|
|
16536
|
+
currentElement.removeEventListener("touchstart", handleTouchStart);
|
|
16537
|
+
currentElement.removeEventListener("touchmove", handleTouchMove);
|
|
16538
|
+
currentElement.removeEventListener("touchend", handleTouchEnd);
|
|
16539
|
+
currentElement.removeEventListener("touchcancel", handleTouchEnd);
|
|
16540
|
+
}
|
|
16541
|
+
if (longPressTimer) {
|
|
16542
|
+
clearTimeout(longPressTimer);
|
|
16543
|
+
longPressTimer = null;
|
|
16544
|
+
}
|
|
16545
|
+
if (removeVisualFeedback) {
|
|
16546
|
+
removeVisualFeedback();
|
|
16547
|
+
removeVisualFeedback = null;
|
|
16548
|
+
}
|
|
16549
|
+
currentElement = null;
|
|
16550
|
+
activeGesture.value = null;
|
|
16551
|
+
isTouching.value = false;
|
|
16552
|
+
}
|
|
16553
|
+
onUnmounted(unbind);
|
|
16554
|
+
return {
|
|
16555
|
+
activeGesture: readonly(activeGesture),
|
|
16556
|
+
bind,
|
|
16557
|
+
isTouching: readonly(isTouching)
|
|
16558
|
+
};
|
|
16559
|
+
}
|
|
16560
|
+
function addPassiveListener(element, event, handler, options) {
|
|
16561
|
+
element.addEventListener(event, handler, __spreadValues({ passive: true }, options));
|
|
16562
|
+
return () => element.removeEventListener(event, handler);
|
|
16563
|
+
}
|
|
16564
|
+
function addNonPassiveListener(element, event, handler, options) {
|
|
16565
|
+
element.addEventListener(event, handler, __spreadValues({ passive: false }, options));
|
|
16566
|
+
return () => element.removeEventListener(event, handler);
|
|
16567
|
+
}
|
|
16568
|
+
function isTouchDevice() {
|
|
16569
|
+
if (!isBrowser()) return false;
|
|
16570
|
+
return "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
16571
|
+
}
|
|
16572
|
+
function isMobileDevice() {
|
|
16573
|
+
if (!isBrowser()) return false;
|
|
16574
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
16575
|
+
}
|
|
16576
|
+
function getDevicePixelRatio() {
|
|
16577
|
+
if (!isBrowser()) return 1;
|
|
16578
|
+
return window.devicePixelRatio || 1;
|
|
16579
|
+
}
|
|
16580
|
+
function usePWA(config = {}) {
|
|
16581
|
+
const {
|
|
16582
|
+
serviceWorker: swConfig = {}
|
|
16583
|
+
} = config;
|
|
16584
|
+
const isOnline = ref(isBrowser() ? navigator.onLine : true);
|
|
16585
|
+
const isRegistered = ref(false);
|
|
16586
|
+
const needsUpdate = ref(false);
|
|
16587
|
+
let registration = null;
|
|
16588
|
+
function handleOnline() {
|
|
16589
|
+
isOnline.value = true;
|
|
16590
|
+
}
|
|
16591
|
+
function handleOffline() {
|
|
16592
|
+
isOnline.value = false;
|
|
16593
|
+
}
|
|
16594
|
+
function register() {
|
|
16595
|
+
return __async(this, null, function* () {
|
|
16596
|
+
if (!isBrowser() || !("serviceWorker" in navigator)) return;
|
|
16597
|
+
if (!swConfig.enabled) return;
|
|
16598
|
+
try {
|
|
16599
|
+
registration = yield navigator.serviceWorker.register(
|
|
16600
|
+
swConfig.path || "/sw.js",
|
|
16601
|
+
{ scope: swConfig.scope || "/" }
|
|
16602
|
+
);
|
|
16603
|
+
isRegistered.value = true;
|
|
16604
|
+
registration.addEventListener("updatefound", () => {
|
|
16605
|
+
const newWorker = registration == null ? void 0 : registration.installing;
|
|
16606
|
+
if (newWorker) {
|
|
16607
|
+
newWorker.addEventListener("statechange", () => {
|
|
16608
|
+
if (newWorker.state === "installed" && navigator.serviceWorker.controller) {
|
|
16609
|
+
needsUpdate.value = true;
|
|
16610
|
+
}
|
|
16611
|
+
});
|
|
16612
|
+
}
|
|
16613
|
+
});
|
|
16614
|
+
} catch (error2) {
|
|
16615
|
+
console.warn("[Directix] Service Worker registration failed:", error2);
|
|
16616
|
+
}
|
|
16617
|
+
});
|
|
16618
|
+
}
|
|
16619
|
+
function update() {
|
|
16620
|
+
return __async(this, null, function* () {
|
|
16621
|
+
if (!registration) return;
|
|
16622
|
+
try {
|
|
16623
|
+
yield registration.update();
|
|
16624
|
+
if (registration.waiting) {
|
|
16625
|
+
registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
|
16626
|
+
}
|
|
16627
|
+
} catch (error2) {
|
|
16628
|
+
console.warn("[Directix] Service Worker update failed:", error2);
|
|
16629
|
+
}
|
|
16630
|
+
});
|
|
16631
|
+
}
|
|
16632
|
+
function unregister() {
|
|
16633
|
+
return __async(this, null, function* () {
|
|
16634
|
+
if (!registration) return;
|
|
16635
|
+
try {
|
|
16636
|
+
yield registration.unregister();
|
|
16637
|
+
isRegistered.value = false;
|
|
16638
|
+
registration = null;
|
|
16639
|
+
} catch (error2) {
|
|
16640
|
+
console.warn("[Directix] Service Worker unregistration failed:", error2);
|
|
16641
|
+
}
|
|
16642
|
+
});
|
|
16643
|
+
}
|
|
16644
|
+
function init() {
|
|
16645
|
+
if (!isBrowser()) return () => {
|
|
16646
|
+
};
|
|
16647
|
+
window.addEventListener("online", handleOnline);
|
|
16648
|
+
window.addEventListener("offline", handleOffline);
|
|
16649
|
+
register();
|
|
16650
|
+
return () => {
|
|
16651
|
+
window.removeEventListener("online", handleOnline);
|
|
16652
|
+
window.removeEventListener("offline", handleOffline);
|
|
16653
|
+
};
|
|
16654
|
+
}
|
|
16655
|
+
onUnmounted(() => {
|
|
16656
|
+
unregister();
|
|
16657
|
+
});
|
|
16658
|
+
return {
|
|
16659
|
+
isOnline: readonly(isOnline),
|
|
16660
|
+
isRegistered: readonly(isRegistered),
|
|
16661
|
+
needsUpdate: readonly(needsUpdate),
|
|
16662
|
+
register,
|
|
16663
|
+
update,
|
|
16664
|
+
unregister,
|
|
16665
|
+
init
|
|
16666
|
+
};
|
|
16667
|
+
}
|
|
16668
|
+
class ObjectPool {
|
|
16669
|
+
constructor(factory, reset, maxSize = 100) {
|
|
16670
|
+
__publicField(this, "pool", []);
|
|
16671
|
+
__publicField(this, "factory");
|
|
16672
|
+
__publicField(this, "reset");
|
|
16673
|
+
__publicField(this, "maxSize");
|
|
16674
|
+
this.factory = factory;
|
|
16675
|
+
this.reset = reset;
|
|
16676
|
+
this.maxSize = maxSize;
|
|
16677
|
+
}
|
|
16678
|
+
acquire() {
|
|
16679
|
+
if (this.pool.length > 0) {
|
|
16680
|
+
return this.pool.pop();
|
|
16681
|
+
}
|
|
16682
|
+
return this.factory();
|
|
16683
|
+
}
|
|
16684
|
+
release(item) {
|
|
16685
|
+
if (this.pool.length < this.maxSize) {
|
|
16686
|
+
this.reset(item);
|
|
16687
|
+
this.pool.push(item);
|
|
16688
|
+
}
|
|
16689
|
+
}
|
|
16690
|
+
get size() {
|
|
16691
|
+
return this.pool.length;
|
|
16692
|
+
}
|
|
16693
|
+
clear() {
|
|
16694
|
+
this.pool.length = 0;
|
|
16695
|
+
}
|
|
16696
|
+
}
|
|
16697
|
+
const DEFAULT_ALLOWED_TAGS = [
|
|
16698
|
+
"b",
|
|
16699
|
+
"i",
|
|
16700
|
+
"u",
|
|
16701
|
+
"strong",
|
|
16702
|
+
"em",
|
|
16703
|
+
"br",
|
|
16704
|
+
"p",
|
|
16705
|
+
"span",
|
|
16706
|
+
"div",
|
|
16707
|
+
"h1",
|
|
16708
|
+
"h2",
|
|
16709
|
+
"h3",
|
|
16710
|
+
"h4",
|
|
16711
|
+
"h5",
|
|
16712
|
+
"h6",
|
|
16713
|
+
"ul",
|
|
16714
|
+
"ol",
|
|
16715
|
+
"li",
|
|
16716
|
+
"blockquote",
|
|
16717
|
+
"pre",
|
|
16718
|
+
"code",
|
|
16719
|
+
"a",
|
|
16720
|
+
"img",
|
|
16721
|
+
"table",
|
|
16722
|
+
"thead",
|
|
16723
|
+
"tbody",
|
|
16724
|
+
"tr",
|
|
16725
|
+
"td",
|
|
16726
|
+
"th"
|
|
16727
|
+
];
|
|
16728
|
+
const DEFAULT_ALLOWED_ATTRIBUTES = {
|
|
16729
|
+
"*": ["title", "alt", "class", "id"],
|
|
16730
|
+
a: ["href", "target", "rel", "title"],
|
|
16731
|
+
img: ["src", "alt", "title", "width", "height"]
|
|
16732
|
+
};
|
|
16733
|
+
const DEFAULT_ALLOWED_PROTOCOLS = ["http", "https", "mailto", "tel"];
|
|
16734
|
+
const DANGEROUS_TAGS = [
|
|
16735
|
+
"script",
|
|
16736
|
+
"iframe",
|
|
16737
|
+
"object",
|
|
16738
|
+
"embed",
|
|
16739
|
+
"applet",
|
|
16740
|
+
"form",
|
|
16741
|
+
"input",
|
|
16742
|
+
"button",
|
|
16743
|
+
"select",
|
|
16744
|
+
"textarea",
|
|
16745
|
+
"style",
|
|
16746
|
+
"link",
|
|
16747
|
+
"meta",
|
|
16748
|
+
"base",
|
|
16749
|
+
"frame",
|
|
16750
|
+
"frameset",
|
|
16751
|
+
"svg",
|
|
16752
|
+
"math",
|
|
16753
|
+
"template"
|
|
16754
|
+
];
|
|
16755
|
+
const DANGEROUS_ATTRIBUTES = [
|
|
16756
|
+
"onclick",
|
|
16757
|
+
"onerror",
|
|
16758
|
+
"onload",
|
|
16759
|
+
"onmouseover",
|
|
16760
|
+
"onmouseout",
|
|
16761
|
+
"onmousedown",
|
|
16762
|
+
"onmouseup",
|
|
16763
|
+
"onmousemove",
|
|
16764
|
+
"onfocus",
|
|
16765
|
+
"onblur",
|
|
16766
|
+
"onchange",
|
|
16767
|
+
"onsubmit",
|
|
16768
|
+
"onreset",
|
|
16769
|
+
"onkeydown",
|
|
16770
|
+
"onkeyup",
|
|
16771
|
+
"onkeypress",
|
|
16772
|
+
"oninput",
|
|
16773
|
+
"onscroll",
|
|
16774
|
+
"onresize",
|
|
16775
|
+
"onunload",
|
|
16776
|
+
"onbeforeunload",
|
|
16777
|
+
"onabort",
|
|
16778
|
+
"oncanplay",
|
|
16779
|
+
"oncanplaythrough",
|
|
16780
|
+
"ondurationchange",
|
|
16781
|
+
"onemptied",
|
|
16782
|
+
"onended",
|
|
16783
|
+
"onloadeddata",
|
|
16784
|
+
"onloadedmetadata",
|
|
16785
|
+
"onloadstart",
|
|
16786
|
+
"onpause",
|
|
16787
|
+
"onplay",
|
|
16788
|
+
"onplaying",
|
|
16789
|
+
"onprogress",
|
|
16790
|
+
"onratechange",
|
|
16791
|
+
"onseeked",
|
|
16792
|
+
"onseeking",
|
|
16793
|
+
"onstalled",
|
|
16794
|
+
"onsuspend",
|
|
16795
|
+
"ontimeupdate",
|
|
16796
|
+
"onvolumechange",
|
|
16797
|
+
"onwaiting",
|
|
16798
|
+
"onafterprint",
|
|
16799
|
+
"onbeforeprint",
|
|
16800
|
+
"oncontextmenu",
|
|
16801
|
+
"oncopy",
|
|
16802
|
+
"oncut",
|
|
16803
|
+
"onpaste",
|
|
16804
|
+
"ondblclick",
|
|
16805
|
+
"ondrag",
|
|
16806
|
+
"ondragend",
|
|
16807
|
+
"ondragenter",
|
|
16808
|
+
"ondragleave",
|
|
16809
|
+
"ondragover",
|
|
16810
|
+
"ondragstart",
|
|
16811
|
+
"ondrop",
|
|
16812
|
+
// Form-related
|
|
16813
|
+
"formaction",
|
|
16814
|
+
"action",
|
|
16815
|
+
"method",
|
|
16816
|
+
"enctype"
|
|
16817
|
+
];
|
|
16818
|
+
const DANGEROUS_URL_PATTERNS = [
|
|
16819
|
+
/^javascript:/i,
|
|
16820
|
+
/^data:/i,
|
|
16821
|
+
/^vbscript:/i,
|
|
16822
|
+
/^file:/i
|
|
16823
|
+
];
|
|
16824
|
+
function isUrlSafe(url, allowedProtocols = DEFAULT_ALLOWED_PROTOCOLS) {
|
|
16825
|
+
if (!url) return true;
|
|
16826
|
+
const trimmed = url.trim();
|
|
16827
|
+
for (const pattern of DANGEROUS_URL_PATTERNS) {
|
|
16828
|
+
if (pattern.test(trimmed)) {
|
|
16829
|
+
return false;
|
|
16830
|
+
}
|
|
16831
|
+
}
|
|
16832
|
+
const protocolMatch = trimmed.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
|
|
16833
|
+
if (protocolMatch) {
|
|
16834
|
+
return allowedProtocols.includes(protocolMatch[1].toLowerCase());
|
|
16835
|
+
}
|
|
16836
|
+
return true;
|
|
16837
|
+
}
|
|
16838
|
+
function sanitizeUrl(url, allowedProtocols = DEFAULT_ALLOWED_PROTOCOLS) {
|
|
16839
|
+
if (!url) return "";
|
|
16840
|
+
const trimmed = url.trim();
|
|
16841
|
+
if (!isUrlSafe(trimmed, allowedProtocols)) {
|
|
16842
|
+
return "";
|
|
16843
|
+
}
|
|
16844
|
+
return trimmed;
|
|
16845
|
+
}
|
|
16846
|
+
function escapeHtml(str) {
|
|
16847
|
+
const escapeMap = {
|
|
16848
|
+
"&": "&",
|
|
16849
|
+
"<": "<",
|
|
16850
|
+
">": ">",
|
|
16851
|
+
'"': """,
|
|
16852
|
+
"'": "'",
|
|
16853
|
+
"/": "/",
|
|
16854
|
+
"`": "`",
|
|
16855
|
+
"=": "="
|
|
16856
|
+
};
|
|
16857
|
+
return str.replace(/[&<>"'`=/]/g, (char) => escapeMap[char] || char);
|
|
16858
|
+
}
|
|
16859
|
+
function unescapeHtml(str) {
|
|
16860
|
+
const unescapeMap = {
|
|
16861
|
+
"&": "&",
|
|
16862
|
+
"<": "<",
|
|
16863
|
+
">": ">",
|
|
16864
|
+
""": '"',
|
|
16865
|
+
"'": "'",
|
|
16866
|
+
"/": "/",
|
|
16867
|
+
"`": "`",
|
|
16868
|
+
"=": "=",
|
|
16869
|
+
"'": "'"
|
|
16870
|
+
};
|
|
16871
|
+
return str.replace(/&[^;]+;/g, (entity) => unescapeMap[entity] || entity).replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10)));
|
|
16872
|
+
}
|
|
16873
|
+
function stripHtml(html) {
|
|
16874
|
+
return html.replace(/<[^>]*>/g, "");
|
|
16875
|
+
}
|
|
16876
|
+
function sanitizeHtml(html, config = {}) {
|
|
16877
|
+
var _a2;
|
|
16878
|
+
if (!html) return "";
|
|
16879
|
+
if (!isBrowser()) return html;
|
|
16880
|
+
const {
|
|
16881
|
+
allowedTags = DEFAULT_ALLOWED_TAGS,
|
|
16882
|
+
allowedAttributes = DEFAULT_ALLOWED_ATTRIBUTES,
|
|
16883
|
+
allowedProtocols = DEFAULT_ALLOWED_PROTOCOLS,
|
|
16884
|
+
allowDataUrls = false,
|
|
16885
|
+
allowInlineStyles = false,
|
|
16886
|
+
allowClass = true,
|
|
16887
|
+
allowId = false,
|
|
16888
|
+
detectDangerousPatterns = true,
|
|
16889
|
+
customFilters = []
|
|
16890
|
+
} = config;
|
|
16891
|
+
let result = html;
|
|
16892
|
+
for (const filter of customFilters) {
|
|
16893
|
+
result = filter(result);
|
|
16894
|
+
}
|
|
16895
|
+
if (detectDangerousPatterns) {
|
|
16896
|
+
const dangerousPatterns = [
|
|
16897
|
+
/<script[\s\S]*?>[\s\S]*?<\/script>/gi,
|
|
16898
|
+
/javascript:/gi,
|
|
16899
|
+
/on\w+\s*=/gi,
|
|
16900
|
+
/data:\s*text\/html/gi,
|
|
16901
|
+
/vbscript:/gi,
|
|
16902
|
+
/expression\s*\(/gi,
|
|
16903
|
+
/url\s*\(\s*["']?javascript:/gi
|
|
16904
|
+
];
|
|
16905
|
+
for (const pattern of dangerousPatterns) {
|
|
16906
|
+
if (pattern.test(result)) {
|
|
16907
|
+
result = result.replace(pattern, "");
|
|
16908
|
+
}
|
|
16909
|
+
}
|
|
16910
|
+
}
|
|
16911
|
+
const temp = document.createElement("div");
|
|
16912
|
+
temp.innerHTML = result;
|
|
16913
|
+
for (const tag of DANGEROUS_TAGS) {
|
|
16914
|
+
const elements = temp.getElementsByTagName(tag);
|
|
16915
|
+
while (elements.length > 0) {
|
|
16916
|
+
(_a2 = elements[0].parentNode) == null ? void 0 : _a2.removeChild(elements[0]);
|
|
16917
|
+
}
|
|
16918
|
+
}
|
|
16919
|
+
function processElement(el) {
|
|
16920
|
+
var _a3;
|
|
16921
|
+
const tagName = el.tagName.toLowerCase();
|
|
16922
|
+
if (!allowedTags.includes(tagName)) {
|
|
16923
|
+
const text = document.createTextNode(el.textContent || "");
|
|
16924
|
+
(_a3 = el.parentNode) == null ? void 0 : _a3.replaceChild(text, el);
|
|
16925
|
+
return;
|
|
16926
|
+
}
|
|
16927
|
+
for (const attr of DANGEROUS_ATTRIBUTES) {
|
|
16928
|
+
el.removeAttribute(attr);
|
|
16929
|
+
}
|
|
16930
|
+
const attrs = Array.from(el.attributes);
|
|
16931
|
+
for (const attr of attrs) {
|
|
16932
|
+
const attrName = attr.name.toLowerCase();
|
|
16933
|
+
if (attrName.startsWith("on")) {
|
|
16934
|
+
el.removeAttribute(attr.name);
|
|
16935
|
+
continue;
|
|
16936
|
+
}
|
|
16937
|
+
let isAllowed2 = false;
|
|
16938
|
+
if (Array.isArray(allowedAttributes)) {
|
|
16939
|
+
isAllowed2 = allowedAttributes.includes(attrName);
|
|
16940
|
+
} else {
|
|
16941
|
+
const globalAttrs = allowedAttributes["*"] || [];
|
|
16942
|
+
const tagAttrs = allowedAttributes[tagName] || [];
|
|
16943
|
+
isAllowed2 = globalAttrs.includes(attrName) || tagAttrs.includes(attrName);
|
|
16944
|
+
}
|
|
16945
|
+
if (attrName === "class" && !allowClass) {
|
|
16946
|
+
el.removeAttribute(attr.name);
|
|
16947
|
+
continue;
|
|
16948
|
+
}
|
|
16949
|
+
if (attrName === "id" && !allowId) {
|
|
16950
|
+
el.removeAttribute(attr.name);
|
|
16951
|
+
continue;
|
|
16952
|
+
}
|
|
16953
|
+
if (attrName === "style" && !allowInlineStyles) {
|
|
16954
|
+
el.removeAttribute(attr.name);
|
|
16955
|
+
continue;
|
|
16956
|
+
}
|
|
16957
|
+
if (attrName === "href" || attrName === "src") {
|
|
16958
|
+
const url = attr.value;
|
|
16959
|
+
if (!isUrlSafe(url, allowDataUrls ? [...allowedProtocols, "data"] : allowedProtocols)) {
|
|
16960
|
+
el.removeAttribute(attr.name);
|
|
16961
|
+
continue;
|
|
16962
|
+
}
|
|
16963
|
+
}
|
|
16964
|
+
if (!isAllowed2 && attrName !== "class" && attrName !== "id" && attrName !== "style") {
|
|
16965
|
+
el.removeAttribute(attr.name);
|
|
16966
|
+
}
|
|
16967
|
+
}
|
|
16968
|
+
for (const child of Array.from(el.children)) {
|
|
16969
|
+
processElement(child);
|
|
16970
|
+
}
|
|
16971
|
+
}
|
|
16972
|
+
for (const child of Array.from(temp.children)) {
|
|
16973
|
+
processElement(child);
|
|
16974
|
+
}
|
|
16975
|
+
return temp.innerHTML;
|
|
16976
|
+
}
|
|
16977
|
+
function getCSPNonce() {
|
|
16978
|
+
if (!isBrowser()) return null;
|
|
16979
|
+
const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
|
|
16980
|
+
if (meta) {
|
|
16981
|
+
const content = meta.content;
|
|
16982
|
+
const match = content.match(/nonce-([a-zA-Z0-9+/=]+)/);
|
|
16983
|
+
if (match) {
|
|
16984
|
+
return match[1];
|
|
16985
|
+
}
|
|
16986
|
+
}
|
|
16987
|
+
const scripts = document.querySelectorAll("script[nonce]");
|
|
16988
|
+
if (scripts.length > 0) {
|
|
16989
|
+
return scripts[0].nonce || null;
|
|
16990
|
+
}
|
|
16991
|
+
return null;
|
|
16992
|
+
}
|
|
16993
|
+
function injectStylesCSP(css, options = {}) {
|
|
16994
|
+
if (!isBrowser()) return null;
|
|
16995
|
+
const { nonce } = options;
|
|
16996
|
+
if (nonce || getCSPNonce()) {
|
|
16997
|
+
const style2 = document.createElement("style");
|
|
16998
|
+
style2.setAttribute("nonce", nonce || getCSPNonce() || "");
|
|
16999
|
+
style2.textContent = css;
|
|
17000
|
+
document.head.appendChild(style2);
|
|
17001
|
+
return style2;
|
|
17002
|
+
}
|
|
17003
|
+
const style = document.createElement("style");
|
|
17004
|
+
style.textContent = css;
|
|
17005
|
+
document.head.appendChild(style);
|
|
17006
|
+
return style;
|
|
17007
|
+
}
|
|
17008
|
+
function injectScriptCSP(src, options = {}) {
|
|
17009
|
+
if (!isBrowser()) return null;
|
|
17010
|
+
const { nonce } = options;
|
|
17011
|
+
const script = document.createElement("script");
|
|
17012
|
+
script.src = src;
|
|
17013
|
+
if (nonce || getCSPNonce()) {
|
|
17014
|
+
script.setAttribute("nonce", nonce || getCSPNonce() || "");
|
|
17015
|
+
}
|
|
17016
|
+
document.head.appendChild(script);
|
|
17017
|
+
return script;
|
|
17018
|
+
}
|
|
17019
|
+
const SecurityAudit = {
|
|
17020
|
+
/**
|
|
17021
|
+
* Scan for potential security issues in HTML
|
|
17022
|
+
*/
|
|
17023
|
+
scanHtml(html) {
|
|
17024
|
+
const issues = [];
|
|
17025
|
+
if (/<script[\s\S]*?>[\s\S]*?<\/script>/gi.test(html)) {
|
|
17026
|
+
issues.push({
|
|
17027
|
+
type: "script-injection",
|
|
17028
|
+
severity: "critical",
|
|
17029
|
+
description: "HTML contains script tags which could lead to XSS attacks",
|
|
17030
|
+
remediation: "Remove script tags or use a sanitization library"
|
|
17031
|
+
});
|
|
17032
|
+
}
|
|
17033
|
+
const eventHandlerMatch = html.match(/on\w+\s*=/gi);
|
|
17034
|
+
if (eventHandlerMatch) {
|
|
17035
|
+
issues.push({
|
|
17036
|
+
type: "event-handler",
|
|
17037
|
+
severity: "high",
|
|
17038
|
+
description: `Found ${eventHandlerMatch.length} event handler(s) which could be exploited`,
|
|
17039
|
+
remediation: "Remove inline event handlers and use addEventListener instead"
|
|
17040
|
+
});
|
|
17041
|
+
}
|
|
17042
|
+
if (/javascript:/gi.test(html)) {
|
|
17043
|
+
issues.push({
|
|
17044
|
+
type: "javascript-url",
|
|
17045
|
+
severity: "high",
|
|
17046
|
+
description: "HTML contains javascript: URLs which could lead to XSS attacks",
|
|
17047
|
+
remediation: "Remove javascript: URLs or validate/sanitize them"
|
|
17048
|
+
});
|
|
17049
|
+
}
|
|
17050
|
+
if (/data:\s*text\/html/gi.test(html)) {
|
|
17051
|
+
issues.push({
|
|
17052
|
+
type: "data-url",
|
|
17053
|
+
severity: "high",
|
|
17054
|
+
description: "HTML contains data:text/html URLs which could execute scripts",
|
|
17055
|
+
remediation: "Remove or sanitize data: URLs"
|
|
17056
|
+
});
|
|
17057
|
+
}
|
|
17058
|
+
if (/<iframe[\s\S]*?srcdoc=/gi.test(html)) {
|
|
17059
|
+
issues.push({
|
|
17060
|
+
type: "iframe-srcdoc",
|
|
17061
|
+
severity: "high",
|
|
17062
|
+
description: "HTML contains iframe with srcdoc attribute",
|
|
17063
|
+
remediation: "Avoid using srcdoc or sanitize its content"
|
|
17064
|
+
});
|
|
17065
|
+
}
|
|
17066
|
+
if (/<form[\s\S]*?action\s*=/gi.test(html)) {
|
|
17067
|
+
issues.push({
|
|
17068
|
+
type: "form-action",
|
|
17069
|
+
severity: "medium",
|
|
17070
|
+
description: "HTML contains form with action attribute",
|
|
17071
|
+
remediation: "Validate form actions or use CSRF protection"
|
|
17072
|
+
});
|
|
17073
|
+
}
|
|
17074
|
+
return issues;
|
|
17075
|
+
},
|
|
17076
|
+
/**
|
|
17077
|
+
* Check CSP configuration
|
|
17078
|
+
*/
|
|
17079
|
+
checkCSP() {
|
|
17080
|
+
var _a2, _b;
|
|
17081
|
+
const result = {
|
|
17082
|
+
policies: {},
|
|
17083
|
+
warnings: [],
|
|
17084
|
+
recommendations: []
|
|
17085
|
+
};
|
|
17086
|
+
if (!isBrowser()) {
|
|
17087
|
+
result.warnings.push("CSP check requires browser environment");
|
|
17088
|
+
return result;
|
|
17089
|
+
}
|
|
17090
|
+
const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
|
|
17091
|
+
if (meta) {
|
|
17092
|
+
const content = meta.content;
|
|
17093
|
+
const directives = content.split(";").map((d) => d.trim());
|
|
17094
|
+
for (const directive of directives) {
|
|
17095
|
+
const [name, ...values] = directive.split(/\s+/);
|
|
17096
|
+
if (name) {
|
|
17097
|
+
result.policies[name.toLowerCase()] = values;
|
|
17098
|
+
}
|
|
17099
|
+
}
|
|
17100
|
+
if ((_a2 = result.policies["script-src"]) == null ? void 0 : _a2.includes("'unsafe-inline'")) {
|
|
17101
|
+
result.warnings.push("CSP allows unsafe-inline scripts - this reduces XSS protection");
|
|
17102
|
+
}
|
|
17103
|
+
if ((_b = result.policies["script-src"]) == null ? void 0 : _b.includes("'unsafe-eval'")) {
|
|
17104
|
+
result.warnings.push("CSP allows unsafe-eval - this reduces XSS protection");
|
|
17105
|
+
}
|
|
17106
|
+
const recommendedDirectives = ["default-src", "script-src", "style-src", "img-src", "connect-src"];
|
|
17107
|
+
for (const directive of recommendedDirectives) {
|
|
17108
|
+
if (!result.policies[directive]) {
|
|
17109
|
+
result.recommendations.push(`Consider adding ${directive} directive to CSP`);
|
|
17110
|
+
}
|
|
17111
|
+
}
|
|
17112
|
+
} else {
|
|
17113
|
+
result.warnings.push("No CSP meta tag found - consider adding Content Security Policy");
|
|
17114
|
+
result.recommendations.push("Add a Content-Security-Policy meta tag or header");
|
|
17115
|
+
}
|
|
17116
|
+
return result;
|
|
17117
|
+
},
|
|
17118
|
+
/**
|
|
17119
|
+
* Check for known dependency vulnerabilities (Node.js environment only)
|
|
17120
|
+
* Note: This is a client-side check that uses npm audit API when available.
|
|
17121
|
+
* For production use, run `npm audit` or `pnpm audit` in CI/CD.
|
|
17122
|
+
*/
|
|
17123
|
+
checkDependencies() {
|
|
17124
|
+
return __async(this, null, function* () {
|
|
17125
|
+
var _a2, _b, _c, _d, _e;
|
|
17126
|
+
const vulnerabilities = [];
|
|
17127
|
+
if (typeof process === "undefined" || !((_a2 = process.versions) == null ? void 0 : _a2.node)) {
|
|
17128
|
+
console.warn("[Directix] checkDependencies() is only available in Node.js environment");
|
|
17129
|
+
return vulnerabilities;
|
|
17130
|
+
}
|
|
17131
|
+
try {
|
|
17132
|
+
const { execSync } = yield import("node:child_process");
|
|
17133
|
+
try {
|
|
17134
|
+
const result = execSync("npm audit --json", {
|
|
17135
|
+
encoding: "utf-8",
|
|
17136
|
+
timeout: 3e4
|
|
17137
|
+
});
|
|
17138
|
+
const audit = JSON.parse(result);
|
|
17139
|
+
if (audit.vulnerabilities) {
|
|
17140
|
+
for (const [name, info2] of Object.entries(audit.vulnerabilities)) {
|
|
17141
|
+
if (info2.via && Array.isArray(info2.via)) {
|
|
17142
|
+
for (const via of info2.via) {
|
|
17143
|
+
if (typeof via === "object" && via.title) {
|
|
17144
|
+
vulnerabilities.push({
|
|
17145
|
+
name,
|
|
17146
|
+
id: (_c = (_b = via.url) == null ? void 0 : _b.match(/(CVE-\d+-\d+|GHSA-[a-zA-Z0-9-]+)/)) == null ? void 0 : _c[0],
|
|
17147
|
+
version: info2.version || "unknown",
|
|
17148
|
+
severity: via.severity || info2.severity || "medium",
|
|
17149
|
+
title: via.title,
|
|
17150
|
+
url: via.url,
|
|
17151
|
+
patchedVersions: info2.fixAvailable ? "Available" : void 0
|
|
17152
|
+
});
|
|
17153
|
+
}
|
|
17154
|
+
}
|
|
17155
|
+
}
|
|
17156
|
+
}
|
|
17157
|
+
}
|
|
17158
|
+
} catch (execError) {
|
|
17159
|
+
if (execError.stdout) {
|
|
17160
|
+
try {
|
|
17161
|
+
const audit = JSON.parse(execError.stdout);
|
|
17162
|
+
if (audit.vulnerabilities) {
|
|
17163
|
+
for (const [name, info2] of Object.entries(audit.vulnerabilities)) {
|
|
17164
|
+
if (info2.via && Array.isArray(info2.via)) {
|
|
17165
|
+
for (const via of info2.via) {
|
|
17166
|
+
if (typeof via === "object" && via.title) {
|
|
17167
|
+
vulnerabilities.push({
|
|
17168
|
+
name,
|
|
17169
|
+
id: (_e = (_d = via.url) == null ? void 0 : _d.match(/(CVE-\d+-\d+|GHSA-[a-zA-Z0-9-]+)/)) == null ? void 0 : _e[0],
|
|
17170
|
+
version: info2.version || "unknown",
|
|
17171
|
+
severity: via.severity || info2.severity || "medium",
|
|
17172
|
+
title: via.title,
|
|
17173
|
+
url: via.url,
|
|
17174
|
+
patchedVersions: info2.fixAvailable ? "Available" : void 0
|
|
17175
|
+
});
|
|
17176
|
+
}
|
|
17177
|
+
}
|
|
17178
|
+
}
|
|
17179
|
+
}
|
|
17180
|
+
}
|
|
17181
|
+
} catch (e) {
|
|
17182
|
+
}
|
|
17183
|
+
}
|
|
17184
|
+
}
|
|
17185
|
+
} catch (error2) {
|
|
17186
|
+
console.warn("[Directix] Failed to check dependencies:", error2);
|
|
17187
|
+
}
|
|
17188
|
+
return vulnerabilities;
|
|
17189
|
+
});
|
|
17190
|
+
},
|
|
17191
|
+
/**
|
|
17192
|
+
* Generate security report
|
|
17193
|
+
*/
|
|
17194
|
+
generateReport(html) {
|
|
17195
|
+
const report = {
|
|
17196
|
+
vulnerabilities: [],
|
|
17197
|
+
warnings: [],
|
|
17198
|
+
recommendations: [],
|
|
17199
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
17200
|
+
};
|
|
17201
|
+
if (html) {
|
|
17202
|
+
report.vulnerabilities = this.scanHtml(html);
|
|
17203
|
+
}
|
|
17204
|
+
const cspResult = this.checkCSP();
|
|
17205
|
+
for (const warning of cspResult.warnings) {
|
|
17206
|
+
report.warnings.push({
|
|
17207
|
+
type: "csp-warning",
|
|
17208
|
+
severity: "medium",
|
|
17209
|
+
description: warning
|
|
17210
|
+
});
|
|
17211
|
+
}
|
|
17212
|
+
report.recommendations.push(...cspResult.recommendations);
|
|
17213
|
+
return report;
|
|
17214
|
+
},
|
|
17215
|
+
/**
|
|
17216
|
+
* Format security report
|
|
17217
|
+
*/
|
|
17218
|
+
formatReport(report, format = "text") {
|
|
17219
|
+
if (format === "json") {
|
|
17220
|
+
return JSON.stringify(report, null, 2);
|
|
17221
|
+
}
|
|
17222
|
+
if (format === "html") {
|
|
17223
|
+
let html = '<div class="security-report">';
|
|
17224
|
+
html += `<h2>Security Report</h2>`;
|
|
17225
|
+
html += `<p>Generated: ${report.timestamp.toISOString()}</p>`;
|
|
17226
|
+
if (report.vulnerabilities.length > 0) {
|
|
17227
|
+
html += "<h3>Vulnerabilities</h3><ul>";
|
|
17228
|
+
for (const vuln of report.vulnerabilities) {
|
|
17229
|
+
html += `<li class="severity-${vuln.severity}"><strong>${vuln.type}</strong>: ${vuln.description}</li>`;
|
|
17230
|
+
}
|
|
17231
|
+
html += "</ul>";
|
|
17232
|
+
}
|
|
17233
|
+
if (report.warnings.length > 0) {
|
|
17234
|
+
html += "<h3>Warnings</h3><ul>";
|
|
17235
|
+
for (const warning of report.warnings) {
|
|
17236
|
+
html += `<li class="severity-${warning.severity}"><strong>${warning.type}</strong>: ${warning.description}</li>`;
|
|
17237
|
+
}
|
|
17238
|
+
html += "</ul>";
|
|
17239
|
+
}
|
|
17240
|
+
if (report.recommendations.length > 0) {
|
|
17241
|
+
html += "<h3>Recommendations</h3><ul>";
|
|
17242
|
+
for (const rec of report.recommendations) {
|
|
17243
|
+
html += `<li>${rec}</li>`;
|
|
17244
|
+
}
|
|
17245
|
+
html += "</ul>";
|
|
17246
|
+
}
|
|
17247
|
+
html += "</div>";
|
|
17248
|
+
return html;
|
|
17249
|
+
}
|
|
17250
|
+
let text = "Security Report\n";
|
|
17251
|
+
text += `Generated: ${report.timestamp.toISOString()}
|
|
17252
|
+
|
|
17253
|
+
`;
|
|
17254
|
+
if (report.vulnerabilities.length > 0) {
|
|
17255
|
+
text += "Vulnerabilities:\n";
|
|
17256
|
+
for (const vuln of report.vulnerabilities) {
|
|
17257
|
+
text += ` [${vuln.severity.toUpperCase()}] ${vuln.type}: ${vuln.description}
|
|
17258
|
+
`;
|
|
17259
|
+
}
|
|
17260
|
+
text += "\n";
|
|
17261
|
+
}
|
|
17262
|
+
if (report.warnings.length > 0) {
|
|
17263
|
+
text += "Warnings:\n";
|
|
17264
|
+
for (const warning of report.warnings) {
|
|
17265
|
+
text += ` [${warning.severity.toUpperCase()}] ${warning.type}: ${warning.description}
|
|
17266
|
+
`;
|
|
17267
|
+
}
|
|
17268
|
+
text += "\n";
|
|
17269
|
+
}
|
|
17270
|
+
if (report.recommendations.length > 0) {
|
|
17271
|
+
text += "Recommendations:\n";
|
|
17272
|
+
for (const rec of report.recommendations) {
|
|
17273
|
+
text += ` - ${rec}
|
|
17274
|
+
`;
|
|
17275
|
+
}
|
|
17276
|
+
}
|
|
17277
|
+
return text;
|
|
17278
|
+
}
|
|
17279
|
+
};
|
|
17280
|
+
class SafeContentHandler {
|
|
17281
|
+
constructor(config = {}) {
|
|
17282
|
+
__publicField(this, "config");
|
|
17283
|
+
this.config = config;
|
|
17284
|
+
}
|
|
17285
|
+
/**
|
|
17286
|
+
* Sanitize and set HTML content
|
|
17287
|
+
*/
|
|
17288
|
+
setHtml(element, content) {
|
|
17289
|
+
element.innerHTML = sanitizeHtml(content, this.config);
|
|
17290
|
+
}
|
|
17291
|
+
/**
|
|
17292
|
+
* Sanitize and set text content
|
|
17293
|
+
*/
|
|
17294
|
+
setText(element, content) {
|
|
17295
|
+
element.textContent = content;
|
|
17296
|
+
}
|
|
17297
|
+
/**
|
|
17298
|
+
* Set attribute with URL validation
|
|
17299
|
+
*/
|
|
17300
|
+
setAttribute(element, name, value) {
|
|
17301
|
+
if (name.toLowerCase().startsWith("on")) {
|
|
17302
|
+
return;
|
|
17303
|
+
}
|
|
17304
|
+
if (name.toLowerCase() === "href" || name.toLowerCase() === "src") {
|
|
17305
|
+
value = sanitizeUrl(value, this.config.allowedProtocols);
|
|
17306
|
+
}
|
|
17307
|
+
element.setAttribute(name, value);
|
|
17308
|
+
}
|
|
17309
|
+
/**
|
|
17310
|
+
* Get sanitized HTML
|
|
17311
|
+
*/
|
|
17312
|
+
getSanitizedHtml(content) {
|
|
17313
|
+
return sanitizeHtml(content, this.config);
|
|
17314
|
+
}
|
|
17315
|
+
}
|
|
17316
|
+
function createSafeContentHandler(config) {
|
|
17317
|
+
return new SafeContentHandler(config);
|
|
17318
|
+
}
|
|
17319
|
+
function useLazyOptimized(options = {}) {
|
|
17320
|
+
const {
|
|
17321
|
+
threshold = 0,
|
|
17322
|
+
rootMargin = "0px",
|
|
17323
|
+
once = true,
|
|
17324
|
+
onLoad
|
|
17325
|
+
} = options;
|
|
17326
|
+
const state2 = shallowRef({
|
|
17327
|
+
loading: false,
|
|
17328
|
+
loaded: false,
|
|
17329
|
+
error: null,
|
|
17330
|
+
isVisible: false
|
|
17331
|
+
});
|
|
17332
|
+
let observer = null;
|
|
17333
|
+
function disconnect() {
|
|
17334
|
+
if (observer) {
|
|
17335
|
+
observer.disconnect();
|
|
17336
|
+
observer = null;
|
|
17337
|
+
}
|
|
17338
|
+
}
|
|
17339
|
+
function observe2(el) {
|
|
17340
|
+
disconnect();
|
|
17341
|
+
observer = new IntersectionObserver(
|
|
17342
|
+
(entries) => {
|
|
17343
|
+
const entry = entries[0];
|
|
17344
|
+
if (entry == null ? void 0 : entry.isIntersecting) {
|
|
17345
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { isVisible: true });
|
|
17346
|
+
load2();
|
|
17347
|
+
if (once) {
|
|
17348
|
+
disconnect();
|
|
17349
|
+
}
|
|
17350
|
+
}
|
|
17351
|
+
},
|
|
17352
|
+
{ threshold, rootMargin }
|
|
17353
|
+
);
|
|
17354
|
+
observer.observe(el);
|
|
17355
|
+
}
|
|
17356
|
+
function load2() {
|
|
17357
|
+
if (state2.value.loading || state2.value.loaded) return;
|
|
17358
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { loading: true, error: null });
|
|
17359
|
+
try {
|
|
17360
|
+
onLoad == null ? void 0 : onLoad({});
|
|
17361
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { loading: false, loaded: true });
|
|
17362
|
+
} catch (e) {
|
|
17363
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { loading: false, error: e });
|
|
17364
|
+
}
|
|
17365
|
+
}
|
|
17366
|
+
return {
|
|
17367
|
+
state: readonly(state2),
|
|
17368
|
+
observe: observe2,
|
|
17369
|
+
disconnect,
|
|
17370
|
+
load: load2
|
|
17371
|
+
};
|
|
17372
|
+
}
|
|
17373
|
+
function useDirectiveInstance(options = {}) {
|
|
17374
|
+
const { initialState = {}, shallow = false } = options;
|
|
17375
|
+
let element = null;
|
|
17376
|
+
const state2 = shallow ? reactive(initialState) : reactive(initialState);
|
|
17377
|
+
function setElement(el) {
|
|
17378
|
+
element = markRaw(el);
|
|
17379
|
+
}
|
|
17380
|
+
function setState2(updater) {
|
|
17381
|
+
const newState = updater(toRaw(state2));
|
|
17382
|
+
Object.assign(state2, newState);
|
|
17383
|
+
}
|
|
17384
|
+
function reset() {
|
|
17385
|
+
Object.assign(state2, initialState);
|
|
17386
|
+
}
|
|
17387
|
+
return {
|
|
17388
|
+
get element() {
|
|
17389
|
+
return element;
|
|
17390
|
+
},
|
|
17391
|
+
set element(el) {
|
|
17392
|
+
if (el) setElement(el);
|
|
17393
|
+
},
|
|
17394
|
+
state: readonly(state2),
|
|
17395
|
+
setElement,
|
|
17396
|
+
setState: setState2,
|
|
17397
|
+
reset
|
|
17398
|
+
};
|
|
17399
|
+
}
|
|
17400
|
+
function computedWithCleanup(options) {
|
|
17401
|
+
const { get: get2, cleanup: cleanup2 } = options;
|
|
17402
|
+
let oldValue;
|
|
17403
|
+
return computed({
|
|
17404
|
+
get() {
|
|
17405
|
+
const newValue = get2();
|
|
17406
|
+
if (oldValue !== void 0 && oldValue !== newValue) {
|
|
17407
|
+
cleanup2 == null ? void 0 : cleanup2(oldValue);
|
|
17408
|
+
}
|
|
17409
|
+
oldValue = newValue;
|
|
17410
|
+
return newValue;
|
|
17411
|
+
},
|
|
17412
|
+
set() {
|
|
17413
|
+
}
|
|
17414
|
+
});
|
|
17415
|
+
}
|
|
17416
|
+
function watchEffectBinding(options) {
|
|
17417
|
+
const { binding, effect } = options;
|
|
17418
|
+
let cleanupFn = null, cleanup2 = (fn) => {
|
|
17419
|
+
cleanupFn = fn;
|
|
17420
|
+
};
|
|
17421
|
+
const stop = watchEffect((onCleanup) => {
|
|
17422
|
+
cleanup2 = onCleanup;
|
|
17423
|
+
if (cleanupFn) {
|
|
17424
|
+
cleanupFn();
|
|
17425
|
+
cleanupFn = null;
|
|
17426
|
+
}
|
|
17427
|
+
if (isRef(binding)) {
|
|
17428
|
+
effect(binding.value, void 0, cleanup2);
|
|
17429
|
+
} else {
|
|
17430
|
+
effect(binding, void 0, cleanup2);
|
|
17431
|
+
}
|
|
17432
|
+
});
|
|
17433
|
+
return () => {
|
|
17434
|
+
if (cleanupFn) {
|
|
17435
|
+
cleanupFn();
|
|
17436
|
+
}
|
|
17437
|
+
stop();
|
|
17438
|
+
};
|
|
17439
|
+
}
|
|
17440
|
+
function useSuspenseDirective(options) {
|
|
17441
|
+
const { loader, onSuccess, onError } = options;
|
|
17442
|
+
const state2 = shallowRef({
|
|
17443
|
+
loading: false,
|
|
17444
|
+
error: null,
|
|
17445
|
+
data: null
|
|
17446
|
+
});
|
|
17447
|
+
function load2() {
|
|
17448
|
+
return __async(this, null, function* () {
|
|
17449
|
+
if (state2.value.loading) return;
|
|
17450
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { loading: true, error: null });
|
|
17451
|
+
try {
|
|
17452
|
+
const data = yield loader();
|
|
17453
|
+
state2.value = { loading: false, error: null, data };
|
|
17454
|
+
onSuccess == null ? void 0 : onSuccess(data);
|
|
17455
|
+
} catch (error2) {
|
|
17456
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { loading: false, error: error2 });
|
|
17457
|
+
onError == null ? void 0 : onError(error2);
|
|
17458
|
+
}
|
|
17459
|
+
});
|
|
17460
|
+
}
|
|
17461
|
+
function retry() {
|
|
17462
|
+
return __async(this, null, function* () {
|
|
17463
|
+
state2.value = __spreadProps(__spreadValues({}, state2.value), { error: null });
|
|
17464
|
+
yield load2();
|
|
17465
|
+
});
|
|
17466
|
+
}
|
|
17467
|
+
return {
|
|
17468
|
+
state: readonly(state2),
|
|
17469
|
+
load: load2,
|
|
17470
|
+
retry
|
|
17471
|
+
};
|
|
17472
|
+
}
|
|
17473
|
+
function ensureTeleportTarget(target) {
|
|
17474
|
+
if (typeof document === "undefined") return null;
|
|
17475
|
+
let el = document.querySelector(target);
|
|
17476
|
+
if (!el) {
|
|
17477
|
+
el = document.createElement("div");
|
|
17478
|
+
el.id = target.replace("#", "");
|
|
17479
|
+
document.body.appendChild(el);
|
|
17480
|
+
}
|
|
17481
|
+
return el;
|
|
17482
|
+
}
|
|
17483
|
+
function teleportContent(content, options) {
|
|
17484
|
+
const { to, disabled = false } = options;
|
|
17485
|
+
if (disabled || typeof document === "undefined") {
|
|
17486
|
+
return () => {
|
|
17487
|
+
};
|
|
17488
|
+
}
|
|
17489
|
+
const targetEl = typeof to === "string" ? ensureTeleportTarget(to) : to;
|
|
17490
|
+
if (!targetEl) return () => {
|
|
17491
|
+
};
|
|
17492
|
+
const parent = content.parentNode;
|
|
17493
|
+
const nextSibling = content.nextSibling;
|
|
17494
|
+
targetEl.appendChild(content);
|
|
17495
|
+
return () => {
|
|
17496
|
+
if (parent && content.parentNode === targetEl) {
|
|
17497
|
+
parent.insertBefore(content, nextSibling);
|
|
17498
|
+
}
|
|
17499
|
+
};
|
|
17500
|
+
}
|
|
15773
17501
|
const zhCN = {
|
|
15774
17502
|
directives: {
|
|
15775
17503
|
debounce: {
|
|
@@ -17852,10 +19580,17 @@ const Directix = {
|
|
|
17852
19580
|
};
|
|
17853
19581
|
export {
|
|
17854
19582
|
Directix,
|
|
19583
|
+
ObjectPool,
|
|
17855
19584
|
PluginManager,
|
|
17856
19585
|
PluginRegistry,
|
|
19586
|
+
SafeContentHandler,
|
|
19587
|
+
SecurityAudit,
|
|
17857
19588
|
addCleanup$1 as addCleanupVue2,
|
|
17858
19589
|
addCleanup as addCleanupVue3,
|
|
19590
|
+
addNonPassiveListener,
|
|
19591
|
+
addPassiveListener,
|
|
19592
|
+
announce,
|
|
19593
|
+
applyAriaAttributes,
|
|
17859
19594
|
assert,
|
|
17860
19595
|
assertPositive,
|
|
17861
19596
|
assertRange,
|
|
@@ -17864,8 +19599,11 @@ export {
|
|
|
17864
19599
|
calculateTime,
|
|
17865
19600
|
capitalizeText,
|
|
17866
19601
|
capitalizeWord,
|
|
19602
|
+
clearAnnouncer,
|
|
19603
|
+
clearAriaAttributes,
|
|
17867
19604
|
clearDevtoolsState,
|
|
17868
19605
|
clearPerformanceMetrics,
|
|
19606
|
+
computedWithCleanup,
|
|
17869
19607
|
configurePerformance,
|
|
17870
19608
|
configurePermission,
|
|
17871
19609
|
createCapitalizer,
|
|
@@ -17877,6 +19615,7 @@ export {
|
|
|
17877
19615
|
createMoneyFormatter,
|
|
17878
19616
|
createNumberFormatter,
|
|
17879
19617
|
createPermissionChecker,
|
|
19618
|
+
createSafeContentHandler,
|
|
17880
19619
|
createStyleDirective,
|
|
17881
19620
|
createTrimmer,
|
|
17882
19621
|
createUppercaser,
|
|
@@ -17899,7 +19638,9 @@ export {
|
|
|
17899
19638
|
enableDevtools,
|
|
17900
19639
|
enablePerformance,
|
|
17901
19640
|
endMeasure,
|
|
19641
|
+
ensureTeleportTarget,
|
|
17902
19642
|
error,
|
|
19643
|
+
escapeHtml,
|
|
17903
19644
|
exportPerformanceData,
|
|
17904
19645
|
formatCurrencyLocale,
|
|
17905
19646
|
formatDateLocale,
|
|
@@ -17907,9 +19648,13 @@ export {
|
|
|
17907
19648
|
formatNumber,
|
|
17908
19649
|
formatNumberLocale,
|
|
17909
19650
|
formatTime,
|
|
19651
|
+
generateAriaId,
|
|
17910
19652
|
generateId,
|
|
17911
19653
|
get,
|
|
19654
|
+
getAutoAriaConfig,
|
|
19655
|
+
getCSPNonce,
|
|
17912
19656
|
getDateFormat,
|
|
19657
|
+
getDevicePixelRatio,
|
|
17913
19658
|
getDevtoolsState,
|
|
17914
19659
|
getDirectiveMetrics,
|
|
17915
19660
|
getLocale,
|
|
@@ -17926,18 +19671,23 @@ export {
|
|
|
17926
19671
|
getTimezoneInfo,
|
|
17927
19672
|
getVueVersion,
|
|
17928
19673
|
info,
|
|
19674
|
+
injectScriptCSP,
|
|
19675
|
+
injectStylesCSP,
|
|
17929
19676
|
isArray,
|
|
17930
19677
|
isBoolean,
|
|
17931
19678
|
isBrowser,
|
|
17932
19679
|
isDevtoolsAvailable,
|
|
17933
19680
|
isEmpty,
|
|
17934
19681
|
isFunction,
|
|
19682
|
+
isMobileDevice,
|
|
17935
19683
|
isNumber,
|
|
17936
19684
|
isObject,
|
|
17937
19685
|
isPerformanceEnabled,
|
|
17938
19686
|
isPromise,
|
|
17939
19687
|
isSSR,
|
|
17940
19688
|
isString,
|
|
19689
|
+
isTouchDevice,
|
|
19690
|
+
isUrlSafe,
|
|
17941
19691
|
isVue2,
|
|
17942
19692
|
isVue27,
|
|
17943
19693
|
isVue3,
|
|
@@ -17954,6 +19704,8 @@ export {
|
|
|
17954
19704
|
resetPluginManager,
|
|
17955
19705
|
resetPluginRegistry,
|
|
17956
19706
|
resetVueVersion,
|
|
19707
|
+
sanitizeHtml,
|
|
19708
|
+
sanitizeUrl,
|
|
17957
19709
|
set,
|
|
17958
19710
|
setLocale,
|
|
17959
19711
|
setVueVersion,
|
|
@@ -17961,17 +19713,21 @@ export {
|
|
|
17961
19713
|
setWarningI18n,
|
|
17962
19714
|
setWarningLevel,
|
|
17963
19715
|
startMeasure,
|
|
19716
|
+
stripHtml,
|
|
17964
19717
|
supportsClipboard,
|
|
17965
19718
|
supportsIntersectionObserver,
|
|
17966
19719
|
supportsMutationObserver,
|
|
17967
19720
|
supportsPassive,
|
|
17968
19721
|
supportsResizeObserver,
|
|
17969
19722
|
t,
|
|
19723
|
+
teleportContent,
|
|
17970
19724
|
throttleFn,
|
|
17971
19725
|
trackDirective,
|
|
17972
19726
|
trackPlugin,
|
|
19727
|
+
triggerHaptic,
|
|
17973
19728
|
trimText,
|
|
17974
19729
|
truncateText,
|
|
19730
|
+
unescapeHtml,
|
|
17975
19731
|
untrackDirective,
|
|
17976
19732
|
untrackPlugin,
|
|
17977
19733
|
uppercaseText,
|
|
@@ -17985,12 +19741,15 @@ export {
|
|
|
17985
19741
|
useCountdown,
|
|
17986
19742
|
useCounter,
|
|
17987
19743
|
useDebounce,
|
|
19744
|
+
useDirectiveInstance,
|
|
17988
19745
|
useDraggable,
|
|
17989
19746
|
useEllipsis,
|
|
17990
19747
|
useEmoji,
|
|
19748
|
+
useEnhancedTouch,
|
|
17991
19749
|
useExport,
|
|
17992
19750
|
useFade,
|
|
17993
19751
|
useFocus,
|
|
19752
|
+
useFocusTrap,
|
|
17994
19753
|
useFullscreen,
|
|
17995
19754
|
useHighlight,
|
|
17996
19755
|
useHotkey,
|
|
@@ -17998,7 +19757,9 @@ export {
|
|
|
17998
19757
|
useImagePreview,
|
|
17999
19758
|
useInfiniteScroll,
|
|
18000
19759
|
useIntersect,
|
|
19760
|
+
useKeyboardNavigation,
|
|
18001
19761
|
useLazy,
|
|
19762
|
+
useLazyOptimized,
|
|
18002
19763
|
useLoading,
|
|
18003
19764
|
useLongPress,
|
|
18004
19765
|
useLottie,
|
|
@@ -18007,6 +19768,7 @@ export {
|
|
|
18007
19768
|
useMoney,
|
|
18008
19769
|
useMutation,
|
|
18009
19770
|
useNumber,
|
|
19771
|
+
usePWA,
|
|
18010
19772
|
usePan,
|
|
18011
19773
|
useParallax,
|
|
18012
19774
|
usePermission,
|
|
@@ -18021,6 +19783,7 @@ export {
|
|
|
18021
19783
|
useScroll,
|
|
18022
19784
|
useSkeleton,
|
|
18023
19785
|
useSticky,
|
|
19786
|
+
useSuspenseDirective,
|
|
18024
19787
|
useSwipe,
|
|
18025
19788
|
useThrottle,
|
|
18026
19789
|
useTooltip,
|
|
@@ -18095,6 +19858,7 @@ export {
|
|
|
18095
19858
|
warnMissingParam,
|
|
18096
19859
|
warnNotSupported,
|
|
18097
19860
|
warnSSRNotSupported,
|
|
19861
|
+
watchEffectBinding,
|
|
18098
19862
|
withPerformanceMonitoring,
|
|
18099
19863
|
wouldTextTruncate,
|
|
18100
19864
|
zhCN
|