@vanduo-oss/framework 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -10
- package/css/components/navbar.css +5 -0
- package/dist/build-info.json +3 -3
- package/dist/vanduo.cjs.js +68 -44
- package/dist/vanduo.cjs.js.map +2 -2
- package/dist/vanduo.cjs.min.js +4 -4
- package/dist/vanduo.cjs.min.js.map +3 -3
- package/dist/vanduo.css +5 -1
- package/dist/vanduo.css.map +1 -1
- package/dist/vanduo.esm.js +68 -44
- package/dist/vanduo.esm.js.map +2 -2
- package/dist/vanduo.esm.min.js +4 -4
- package/dist/vanduo.esm.min.js.map +3 -3
- package/dist/vanduo.js +68 -44
- package/dist/vanduo.js.map +2 -2
- package/dist/vanduo.min.css +2 -2
- package/dist/vanduo.min.css.map +1 -1
- package/dist/vanduo.min.js +4 -4
- package/dist/vanduo.min.js.map +3 -3
- package/js/components/code-snippet.js +5 -4
- package/js/components/dropdown.js +9 -9
- package/js/components/image-box.js +7 -1
- package/js/components/modals.js +18 -10
- package/js/components/navbar.js +3 -3
- package/js/components/select.js +15 -13
- package/js/components/suggest.js +14 -1
- package/js/components/theme-customizer.js +0 -1
- package/js/components/validate.js +14 -3
- package/js/utils/helpers.js +7 -3
- package/package.json +2 -2
package/dist/vanduo.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Vanduo v1.3.
|
|
1
|
+
/*! Vanduo v1.3.1 | Built: 2026-03-20T21:48:40.922Z | git:7e73bb8 | development */
|
|
2
2
|
|
|
3
3
|
// js/utils/lifecycle.js
|
|
4
4
|
(function() {
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
// js/vanduo.js
|
|
108
108
|
(function() {
|
|
109
109
|
"use strict";
|
|
110
|
-
const VANDUO_VERSION = true ? "1.3.
|
|
110
|
+
const VANDUO_VERSION = true ? "1.3.1" : "0.0.0-dev";
|
|
111
111
|
const Vanduo2 = {
|
|
112
112
|
version: VANDUO_VERSION,
|
|
113
113
|
components: {},
|
|
@@ -418,16 +418,17 @@
|
|
|
418
418
|
}
|
|
419
419
|
const codeElement = activePane.querySelector("code") || activePane;
|
|
420
420
|
const code = codeElement.textContent;
|
|
421
|
+
let copySuccess;
|
|
421
422
|
try {
|
|
422
423
|
await navigator.clipboard.writeText(code);
|
|
423
|
-
|
|
424
|
+
copySuccess = true;
|
|
424
425
|
} catch (_err) {
|
|
425
|
-
|
|
426
|
-
this.showCopyFeedback(copyBtn, success);
|
|
426
|
+
copySuccess = this.fallbackCopy(code);
|
|
427
427
|
}
|
|
428
|
+
this.showCopyFeedback(copyBtn, copySuccess);
|
|
428
429
|
const event = new CustomEvent("codesnippet:copy", {
|
|
429
430
|
bubbles: true,
|
|
430
|
-
detail: { snippet, code, success:
|
|
431
|
+
detail: { snippet, code, success: copySuccess }
|
|
431
432
|
});
|
|
432
433
|
snippet.dispatchEvent(event);
|
|
433
434
|
},
|
|
@@ -864,9 +865,6 @@
|
|
|
864
865
|
const Dropdown = {
|
|
865
866
|
// Store initialized dropdowns and their cleanup functions
|
|
866
867
|
instances: /* @__PURE__ */ new Map(),
|
|
867
|
-
// Typeahead state
|
|
868
|
-
_typeaheadBuffer: "",
|
|
869
|
-
_typeaheadTimer: null,
|
|
870
868
|
/**
|
|
871
869
|
* Initialize dropdown components
|
|
872
870
|
*/
|
|
@@ -930,7 +928,7 @@
|
|
|
930
928
|
item.addEventListener("keydown", itemKeydownHandler);
|
|
931
929
|
cleanupFunctions.push(() => item.removeEventListener("keydown", itemKeydownHandler));
|
|
932
930
|
});
|
|
933
|
-
this.instances.set(dropdown, { toggle, menu, cleanup: cleanupFunctions });
|
|
931
|
+
this.instances.set(dropdown, { toggle, menu, cleanup: cleanupFunctions, typeaheadBuffer: "", typeaheadTimer: null });
|
|
934
932
|
},
|
|
935
933
|
/**
|
|
936
934
|
* Toggle dropdown
|
|
@@ -1059,16 +1057,18 @@
|
|
|
1059
1057
|
break;
|
|
1060
1058
|
default:
|
|
1061
1059
|
if (isOpen && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
1062
|
-
|
|
1063
|
-
|
|
1060
|
+
const instance = this.instances.get(dropdown);
|
|
1061
|
+
if (!instance) break;
|
|
1062
|
+
clearTimeout(instance.typeaheadTimer);
|
|
1063
|
+
instance.typeaheadBuffer += e.key.toLowerCase();
|
|
1064
1064
|
const match = items.find(
|
|
1065
|
-
(item) => item.textContent.trim().toLowerCase().startsWith(
|
|
1065
|
+
(item) => item.textContent.trim().toLowerCase().startsWith(instance.typeaheadBuffer)
|
|
1066
1066
|
);
|
|
1067
1067
|
if (match) {
|
|
1068
1068
|
match.focus();
|
|
1069
1069
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1070
|
+
instance.typeaheadTimer = setTimeout(() => {
|
|
1071
|
+
instance.typeaheadBuffer = "";
|
|
1072
1072
|
}, 500);
|
|
1073
1073
|
}
|
|
1074
1074
|
break;
|
|
@@ -1776,9 +1776,10 @@
|
|
|
1776
1776
|
}));
|
|
1777
1777
|
if (!this.img.complete) {
|
|
1778
1778
|
this.img.style.opacity = "0";
|
|
1779
|
-
this.
|
|
1779
|
+
this._imgLoadHandler = () => {
|
|
1780
1780
|
this.img.style.opacity = "";
|
|
1781
1781
|
};
|
|
1782
|
+
this.img.addEventListener("load", this._imgLoadHandler, { once: true });
|
|
1782
1783
|
}
|
|
1783
1784
|
},
|
|
1784
1785
|
/**
|
|
@@ -1797,6 +1798,10 @@
|
|
|
1797
1798
|
}
|
|
1798
1799
|
setTimeout(() => {
|
|
1799
1800
|
if (!this.isOpen) {
|
|
1801
|
+
if (this._imgLoadHandler) {
|
|
1802
|
+
this.img.removeEventListener("load", this._imgLoadHandler);
|
|
1803
|
+
this._imgLoadHandler = null;
|
|
1804
|
+
}
|
|
1800
1805
|
this.img.src = "";
|
|
1801
1806
|
this.img.alt = "";
|
|
1802
1807
|
}
|
|
@@ -1856,6 +1861,8 @@
|
|
|
1856
1861
|
zIndexCounter: 1050,
|
|
1857
1862
|
// Store trigger cleanup functions
|
|
1858
1863
|
_triggerCleanups: [],
|
|
1864
|
+
// Shared ESC key handler (installed once)
|
|
1865
|
+
_sharedEscHandler: null,
|
|
1859
1866
|
/**
|
|
1860
1867
|
* Initialize modals
|
|
1861
1868
|
*/
|
|
@@ -1920,16 +1927,17 @@
|
|
|
1920
1927
|
};
|
|
1921
1928
|
backdrop.addEventListener("click", backdropClickHandler);
|
|
1922
1929
|
cleanupFunctions.push(() => backdrop.removeEventListener("click", backdropClickHandler));
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1930
|
+
if (!this._sharedEscHandler) {
|
|
1931
|
+
this._sharedEscHandler = (e) => {
|
|
1932
|
+
if (e.key === "Escape" && this.openModals.length > 0) {
|
|
1933
|
+
const topModal = this.openModals[this.openModals.length - 1];
|
|
1934
|
+
if (topModal.dataset.keyboard !== "false") {
|
|
1935
|
+
this.close(topModal);
|
|
1936
|
+
}
|
|
1928
1937
|
}
|
|
1929
|
-
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
cleanupFunctions.push(() => document.removeEventListener("keydown", escKeyHandler));
|
|
1938
|
+
};
|
|
1939
|
+
document.addEventListener("keydown", this._sharedEscHandler);
|
|
1940
|
+
}
|
|
1933
1941
|
this.modals.set(modal, { backdrop, dialog, trapHandler: null, cleanup: cleanupFunctions });
|
|
1934
1942
|
},
|
|
1935
1943
|
/**
|
|
@@ -2109,6 +2117,10 @@
|
|
|
2109
2117
|
});
|
|
2110
2118
|
this._triggerCleanups.forEach((fn) => fn());
|
|
2111
2119
|
this._triggerCleanups = [];
|
|
2120
|
+
if (this._sharedEscHandler) {
|
|
2121
|
+
document.removeEventListener("keydown", this._sharedEscHandler);
|
|
2122
|
+
this._sharedEscHandler = null;
|
|
2123
|
+
}
|
|
2112
2124
|
}
|
|
2113
2125
|
};
|
|
2114
2126
|
if (typeof window.Vanduo !== "undefined") {
|
|
@@ -2274,7 +2286,7 @@
|
|
|
2274
2286
|
if (overlay) {
|
|
2275
2287
|
overlay.classList.add("is-active");
|
|
2276
2288
|
}
|
|
2277
|
-
document.body.
|
|
2289
|
+
document.body.classList.add("body-navbar-open");
|
|
2278
2290
|
toggle.setAttribute("aria-expanded", "true");
|
|
2279
2291
|
menu.setAttribute("aria-hidden", "false");
|
|
2280
2292
|
},
|
|
@@ -2291,7 +2303,7 @@
|
|
|
2291
2303
|
if (overlay) {
|
|
2292
2304
|
overlay.classList.remove("is-active");
|
|
2293
2305
|
}
|
|
2294
|
-
document.body.
|
|
2306
|
+
document.body.classList.remove("body-navbar-open");
|
|
2295
2307
|
const dropdownMenus = menu.querySelectorAll(".vd-navbar-dropdown-menu.is-open");
|
|
2296
2308
|
dropdownMenus.forEach((dropdownMenu) => {
|
|
2297
2309
|
dropdownMenu.classList.remove("is-open");
|
|
@@ -2850,9 +2862,6 @@
|
|
|
2850
2862
|
const Select = {
|
|
2851
2863
|
// Store initialized selects and their cleanup functions
|
|
2852
2864
|
instances: /* @__PURE__ */ new Map(),
|
|
2853
|
-
// Typeahead state
|
|
2854
|
-
_typeaheadBuffer: "",
|
|
2855
|
-
_typeaheadTimer: null,
|
|
2856
2865
|
/**
|
|
2857
2866
|
* Initialize select components
|
|
2858
2867
|
*/
|
|
@@ -2933,7 +2942,7 @@
|
|
|
2933
2942
|
};
|
|
2934
2943
|
select.addEventListener("change", changeHandler);
|
|
2935
2944
|
cleanupFunctions.push(() => select.removeEventListener("change", changeHandler));
|
|
2936
|
-
this.instances.set(select, { wrapper, button, dropdown, cleanup: cleanupFunctions });
|
|
2945
|
+
this.instances.set(select, { wrapper, button, dropdown, cleanup: cleanupFunctions, typeaheadBuffer: "", typeaheadTimer: null });
|
|
2937
2946
|
},
|
|
2938
2947
|
/**
|
|
2939
2948
|
* Build options in dropdown
|
|
@@ -3027,7 +3036,7 @@
|
|
|
3027
3036
|
* @param {HTMLElement} dropdown - Dropdown container
|
|
3028
3037
|
*/
|
|
3029
3038
|
updateSelectedOptions: function(select, dropdown) {
|
|
3030
|
-
const options = dropdown.querySelectorAll(".
|
|
3039
|
+
const options = dropdown.querySelectorAll(".custom-select-option");
|
|
3031
3040
|
const selectedValues = Array.from(select.selectedOptions).map((opt) => opt.value);
|
|
3032
3041
|
options.forEach((optionEl) => {
|
|
3033
3042
|
const value = optionEl.dataset.value;
|
|
@@ -3061,7 +3070,7 @@
|
|
|
3061
3070
|
openDropdown: function(button, dropdown) {
|
|
3062
3071
|
dropdown.classList.add("is-open");
|
|
3063
3072
|
button.setAttribute("aria-expanded", "true");
|
|
3064
|
-
const firstOption = dropdown.querySelector(".
|
|
3073
|
+
const firstOption = dropdown.querySelector(".custom-select-option:not(.is-disabled)");
|
|
3065
3074
|
if (firstOption) {
|
|
3066
3075
|
firstOption.focus();
|
|
3067
3076
|
}
|
|
@@ -3084,7 +3093,7 @@
|
|
|
3084
3093
|
*/
|
|
3085
3094
|
handleKeydown: function(e, select, button, dropdown) {
|
|
3086
3095
|
const isOpen = dropdown.classList.contains("is-open");
|
|
3087
|
-
const options = Array.from(dropdown.querySelectorAll(".
|
|
3096
|
+
const options = Array.from(dropdown.querySelectorAll(".custom-select-option:not(.is-disabled)"));
|
|
3088
3097
|
const currentIndex = options.findIndex((opt) => opt === document.activeElement);
|
|
3089
3098
|
switch (e.key) {
|
|
3090
3099
|
case "Enter":
|
|
@@ -3135,16 +3144,18 @@
|
|
|
3135
3144
|
break;
|
|
3136
3145
|
default:
|
|
3137
3146
|
if (isOpen && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
3138
|
-
|
|
3139
|
-
|
|
3147
|
+
const instance = this.instances.get(select);
|
|
3148
|
+
if (!instance) break;
|
|
3149
|
+
clearTimeout(instance.typeaheadTimer);
|
|
3150
|
+
instance.typeaheadBuffer += e.key.toLowerCase();
|
|
3140
3151
|
const match = options.find(
|
|
3141
|
-
(opt) => opt.textContent.trim().toLowerCase().startsWith(
|
|
3152
|
+
(opt) => opt.textContent.trim().toLowerCase().startsWith(instance.typeaheadBuffer)
|
|
3142
3153
|
);
|
|
3143
3154
|
if (match) {
|
|
3144
3155
|
match.focus();
|
|
3145
3156
|
}
|
|
3146
|
-
|
|
3147
|
-
|
|
3157
|
+
instance.typeaheadTimer = setTimeout(() => {
|
|
3158
|
+
instance.typeaheadBuffer = "";
|
|
3148
3159
|
}, 500);
|
|
3149
3160
|
}
|
|
3150
3161
|
break;
|
|
@@ -3176,7 +3187,9 @@
|
|
|
3176
3187
|
if (element.id) {
|
|
3177
3188
|
return element.id;
|
|
3178
3189
|
}
|
|
3179
|
-
|
|
3190
|
+
const id = "select-" + Math.random().toString(36).substr(2, 9);
|
|
3191
|
+
element.id = id;
|
|
3192
|
+
return id;
|
|
3180
3193
|
},
|
|
3181
3194
|
/**
|
|
3182
3195
|
* Destroy a select instance and clean up event listeners
|
|
@@ -4230,7 +4243,6 @@
|
|
|
4230
4243
|
this.applyNeutral(this.DEFAULTS.NEUTRAL);
|
|
4231
4244
|
this.applyRadius(this.DEFAULTS.RADIUS);
|
|
4232
4245
|
this.applyFont(this.DEFAULTS.FONT);
|
|
4233
|
-
this.applyTheme(this.DEFAULTS.THEME);
|
|
4234
4246
|
this.updateUI();
|
|
4235
4247
|
this.dispatchEvent("reset", { state: { ...this.state } });
|
|
4236
4248
|
},
|
|
@@ -7015,6 +7027,11 @@
|
|
|
7015
7027
|
// js/components/suggest.js
|
|
7016
7028
|
(function() {
|
|
7017
7029
|
"use strict";
|
|
7030
|
+
function _escapeHtml(text) {
|
|
7031
|
+
const div = document.createElement("div");
|
|
7032
|
+
div.textContent = text;
|
|
7033
|
+
return div.innerHTML;
|
|
7034
|
+
}
|
|
7018
7035
|
const Suggest = {
|
|
7019
7036
|
instances: /* @__PURE__ */ new Map(),
|
|
7020
7037
|
init: function() {
|
|
@@ -7074,8 +7091,9 @@
|
|
|
7074
7091
|
li.id = listId + "-item-" + i;
|
|
7075
7092
|
const text = typeof item === "object" ? item.label || item.text || String(item) : String(item);
|
|
7076
7093
|
if (query) {
|
|
7094
|
+
const escaped = _escapeHtml(text);
|
|
7077
7095
|
const re = new RegExp("(" + query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + ")", "gi");
|
|
7078
|
-
li.innerHTML =
|
|
7096
|
+
li.innerHTML = escaped.replace(re, '<span class="vd-suggest-match">$1</span>');
|
|
7079
7097
|
} else {
|
|
7080
7098
|
li.textContent = text;
|
|
7081
7099
|
}
|
|
@@ -7228,14 +7246,20 @@
|
|
|
7228
7246
|
maxVal: (value, param) => parseFloat(value) <= parseFloat(param),
|
|
7229
7247
|
pattern: (value, param) => {
|
|
7230
7248
|
try {
|
|
7249
|
+
if (param.length > 100) return false;
|
|
7231
7250
|
return new RegExp(param).test(value);
|
|
7232
7251
|
} catch (_e) {
|
|
7233
7252
|
return false;
|
|
7234
7253
|
}
|
|
7235
7254
|
},
|
|
7236
7255
|
match: (value, param) => {
|
|
7237
|
-
|
|
7238
|
-
|
|
7256
|
+
try {
|
|
7257
|
+
const escaped = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(param) : param;
|
|
7258
|
+
const other = document.querySelector('[name="' + escaped + '"]');
|
|
7259
|
+
return other ? value === other.value : false;
|
|
7260
|
+
} catch (_e) {
|
|
7261
|
+
return false;
|
|
7262
|
+
}
|
|
7239
7263
|
}
|
|
7240
7264
|
},
|
|
7241
7265
|
messages: {
|