@t007/input 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.global.js +46 -41
- package/dist/index.js +35 -153
- package/dist/standalone.js +441 -0
- package/package.json +7 -9
- package/src/ts/types/index.d.ts +7 -7
package/dist/index.global.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
4
3
|
// ../utils/dist/index.js
|
|
5
4
|
function isSameURL(src1, src2) {
|
|
6
5
|
if (typeof src1 !== "string" || typeof src2 !== "string" || !src1 || !src2) return false;
|
|
@@ -11,14 +10,20 @@
|
|
|
11
10
|
return src1.replace(/\\/g, "/").split("?")[0].trim() === src2.replace(/\\/g, "/").split("?")[0].trim();
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
|
-
function createEl(tag, props
|
|
15
|
-
return assignEl(
|
|
13
|
+
function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
|
|
14
|
+
return assignEl(el, props, dataset, styles), el;
|
|
16
15
|
}
|
|
17
|
-
function assignEl(el, props
|
|
16
|
+
function assignEl(el, props, dataset, styles) {
|
|
18
17
|
if (!el) return;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
if (props) {
|
|
19
|
+
for (const k of Object.keys(props)) if (props[k] !== void 0) el[k] = props[k];
|
|
20
|
+
}
|
|
21
|
+
if (dataset) {
|
|
22
|
+
for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) el.dataset[k] = String(dataset[k]);
|
|
23
|
+
}
|
|
24
|
+
if (styles) {
|
|
25
|
+
for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
|
|
26
|
+
}
|
|
22
27
|
}
|
|
23
28
|
function loadResource(src, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
|
|
24
29
|
w.t007._resourceCache ??= {};
|
|
@@ -121,13 +126,13 @@
|
|
|
121
126
|
window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
|
|
122
127
|
window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
|
|
123
128
|
window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
|
|
124
|
-
window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/
|
|
125
|
-
window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/
|
|
126
|
-
window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/
|
|
129
|
+
window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/style.css`;
|
|
130
|
+
window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/style.css`;
|
|
131
|
+
window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/style.css`;
|
|
127
132
|
}
|
|
128
133
|
|
|
129
134
|
// src/index.js
|
|
130
|
-
var
|
|
135
|
+
var formManager = {
|
|
131
136
|
forms: document.getElementsByClassName("t007-input-form"),
|
|
132
137
|
violationKeys: ["valueMissing", "typeMismatch", "patternMismatch", "stepMismatch", "tooShort", "tooLong", "rangeUnderflow", "rangeOverflow", "badInput", "customError"],
|
|
133
138
|
init() {
|
|
@@ -139,7 +144,7 @@
|
|
|
139
144
|
for (const mutation of mutations) {
|
|
140
145
|
for (const node of mutation.addedNodes) {
|
|
141
146
|
if (!node.tagName || !(node?.classList?.contains("t007-input-field") || node?.querySelector?.(".t007-input-field"))) continue;
|
|
142
|
-
for (const
|
|
147
|
+
for (const field2 of [...node.querySelector(".t007-input-field") ? node.querySelectorAll(".t007-input-field") : [node]]) t007.FM.setUpField(field2);
|
|
143
148
|
}
|
|
144
149
|
}
|
|
145
150
|
}).observe(document.body, { childList: true, subtree: true });
|
|
@@ -176,14 +181,14 @@
|
|
|
176
181
|
},
|
|
177
182
|
togglePasswordType: (input) => input.type = input.type === "password" ? "text" : "password",
|
|
178
183
|
toggleFilled: (input) => input?.toggleAttribute("data-filled", input.type === "checkbox" || input.type === "radio" ? input.checked : input.value !== "" || input.files?.length > 0),
|
|
179
|
-
setFallbackHelper(
|
|
180
|
-
const helperTextWrapper =
|
|
184
|
+
setFallbackHelper(field2) {
|
|
185
|
+
const helperTextWrapper = field2?.querySelector(".t007-input-helper-text-wrapper");
|
|
181
186
|
if (!helperTextWrapper || helperTextWrapper.querySelector(".t007-input-helper-text[data-violation='auto']")) return;
|
|
182
187
|
helperTextWrapper.append(createEl("p", { className: "t007-input-helper-text" }, { violation: "auto" }));
|
|
183
188
|
},
|
|
184
|
-
setFieldListeners(
|
|
185
|
-
if (!
|
|
186
|
-
const input =
|
|
189
|
+
setFieldListeners(field2) {
|
|
190
|
+
if (!field2) return;
|
|
191
|
+
const input = field2.querySelector(".t007-input"), floatingLabel = field2.querySelector(".t007-input-floating-label"), eyeOpen = field2.querySelector(".t007-input-password-visible-icon"), eyeClosed = field2.querySelector(".t007-input-password-hidden-icon");
|
|
187
192
|
if (input.type === "file")
|
|
188
193
|
input.addEventListener("input", async () => {
|
|
189
194
|
const file = input.files?.[0], img = new Image();
|
|
@@ -221,18 +226,18 @@
|
|
|
221
226
|
});
|
|
222
227
|
if (floatingLabel) floatingLabel.ontransitionend = () => floatingLabel.classList.remove("t007-input-shake");
|
|
223
228
|
if (eyeOpen && eyeClosed) eyeOpen.onclick = eyeClosed.onclick = () => t007.FM.togglePasswordType(input);
|
|
224
|
-
initScrollAssist(
|
|
229
|
+
initScrollAssist(field2.querySelector(".t007-input-helper-text-wrapper"), { vertical: false });
|
|
225
230
|
},
|
|
226
|
-
setUpField(
|
|
227
|
-
if (
|
|
228
|
-
t007.FM.toggleFilled(
|
|
229
|
-
t007.FM.setFallbackHelper(
|
|
230
|
-
t007.FM.setFieldListeners(
|
|
231
|
-
|
|
231
|
+
setUpField(field2) {
|
|
232
|
+
if (field2.dataset.setUp) return;
|
|
233
|
+
t007.FM.toggleFilled(field2.querySelector(".t007-input"));
|
|
234
|
+
t007.FM.setFallbackHelper(field2);
|
|
235
|
+
t007.FM.setFieldListeners(field2);
|
|
236
|
+
field2.dataset.setUp = "true";
|
|
232
237
|
},
|
|
233
238
|
field({ isWrapper = false, label = "", type = "text", placeholder = "", custom = "", minSize, maxSize, minTotalSize, maxTotalSize, options = [], indeterminate = false, eyeToggler = true, passwordMeter = true, helperText = {}, className = "", fieldClassName = "", children, startIcon = "", endIcon = "", nativeIcon = "", passwordVisibleIcon = "", passwordHiddenIcon = "", ...otherProps }) {
|
|
234
|
-
const isSelect = type === "select", isTextArea = type === "textarea", isCheckboxOrRadio = type === "checkbox" || type === "radio",
|
|
235
|
-
|
|
239
|
+
const isSelect = type === "select", isTextArea = type === "textarea", isCheckboxOrRadio = type === "checkbox" || type === "radio", field2 = createEl("div", { className: `t007-input-field${isWrapper ? " t007-input-is-wrapper" : ""}${indeterminate ? " t007-input-indeterminate" : ""}${!!nativeIcon ? " t007-input-icon-override" : ""}${helperText === false ? " t007-input-no-helper" : ""}${fieldClassName ? ` ${fieldClassName}` : ""}` }), labelEl = createEl("label", { className: isCheckboxOrRadio ? `t007-input-${type}-wrapper` : "t007-input-wrapper" });
|
|
240
|
+
field2.append(labelEl);
|
|
236
241
|
if (isCheckboxOrRadio) {
|
|
237
242
|
labelEl.innerHTML = `
|
|
238
243
|
<span class="t007-input-${type}-box">
|
|
@@ -251,7 +256,7 @@
|
|
|
251
256
|
`;
|
|
252
257
|
labelEl.append(outline);
|
|
253
258
|
}
|
|
254
|
-
const inputEl =
|
|
259
|
+
const inputEl = field2.inputEl = createEl(isTextArea ? "textarea" : isSelect ? "select" : "input", { className: `t007-input${className ? ` ${className}` : ""}`, placeholder });
|
|
255
260
|
if (isSelect && Array.isArray(options)) inputEl.innerHTML = options.map((opt) => typeof opt === "string" ? `<option value="${opt}">${opt}</option>` : `<option value="${opt.value}">${opt.option}</option>`).join("");
|
|
256
261
|
if (!isSelect && !isTextArea) inputEl.type = type;
|
|
257
262
|
if (custom) inputEl.setAttribute("custom", custom);
|
|
@@ -273,7 +278,7 @@
|
|
|
273
278
|
if (helperText.info) helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText.info }, { violation: "none" }));
|
|
274
279
|
t007.FM?.violationKeys?.forEach((key) => helperText[key] && helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText[key] }, { violation: key })));
|
|
275
280
|
helperLine.append(helperWrapper);
|
|
276
|
-
|
|
281
|
+
field2.append(helperLine);
|
|
277
282
|
}
|
|
278
283
|
if (passwordMeter && type === "password") {
|
|
279
284
|
const meter = createEl("div", { className: "t007-input-password-meter" }, { strengthLevel: "1" });
|
|
@@ -285,9 +290,9 @@
|
|
|
285
290
|
<div class="t007-input-p-very-strong"></div>
|
|
286
291
|
</div>
|
|
287
292
|
`;
|
|
288
|
-
|
|
293
|
+
field2.append(meter);
|
|
289
294
|
}
|
|
290
|
-
return
|
|
295
|
+
return field2;
|
|
291
296
|
},
|
|
292
297
|
handleFormValidation(form) {
|
|
293
298
|
if (!form?.classList.contains("t007-input-form") || form.dataset?.isValidating) return;
|
|
@@ -321,7 +326,7 @@
|
|
|
321
326
|
form.classList.toggle("t007-input-submit-loading", bool);
|
|
322
327
|
}
|
|
323
328
|
function toggleError(input, bool, flag = false) {
|
|
324
|
-
const
|
|
329
|
+
const field2 = input.closest(".t007-input-field"), floatingLabel = field2.querySelector(".t007-input-floating-label");
|
|
325
330
|
if (bool && flag) {
|
|
326
331
|
input.setAttribute("data-error", "");
|
|
327
332
|
floatingLabel?.classList.add("t007-input-shake");
|
|
@@ -329,7 +334,7 @@
|
|
|
329
334
|
toggleHelper(input, input.hasAttribute("data-error"));
|
|
330
335
|
}
|
|
331
336
|
function toggleHelper(input, bool) {
|
|
332
|
-
const
|
|
337
|
+
const field2 = input.closest(".t007-input-field"), violation = t007.FM.violationKeys.find((violation2) => input.Validity?.[violation2] || input.validity[violation2]) ?? "", helper = field2.querySelector(`.t007-input-helper-text[data-violation="${violation}"]`), fallbackHelper = field2.querySelector(`.t007-input-helper-text[data-violation="auto"]`);
|
|
333
338
|
input.closest(".t007-input-field").querySelectorAll(`.t007-input-helper-text:not([data-violation="${violation}"])`).forEach((helper2) => helper2?.classList.remove("t007-input-show"));
|
|
334
339
|
if (helper) helper.classList.toggle("t007-input-show", bool);
|
|
335
340
|
else if (fallbackHelper) {
|
|
@@ -413,22 +418,22 @@
|
|
|
413
418
|
}
|
|
414
419
|
function toggleFormGlobalError(bool) {
|
|
415
420
|
form.toggleAttribute("data-global-error", bool);
|
|
416
|
-
form.querySelectorAll(".t007-input-field").forEach((
|
|
417
|
-
|
|
418
|
-
if (bool)
|
|
421
|
+
form.querySelectorAll(".t007-input-field").forEach((field2) => {
|
|
422
|
+
field2.querySelector(".t007-input")?.toggleAttribute("data-error", bool);
|
|
423
|
+
if (bool) field2.querySelector(".t007-input-floating-label")?.classList.add("t007-input-shake");
|
|
419
424
|
});
|
|
420
425
|
}
|
|
421
426
|
}
|
|
422
427
|
};
|
|
428
|
+
var { field, handleFormValidation } = formManager;
|
|
423
429
|
if (typeof window !== "undefined") {
|
|
424
|
-
t007.FM =
|
|
425
|
-
t007.field =
|
|
426
|
-
t007.handleFormValidation =
|
|
430
|
+
t007.FM = formManager;
|
|
431
|
+
t007.field = field;
|
|
432
|
+
t007.handleFormValidation = handleFormValidation;
|
|
427
433
|
window.field ??= t007.field;
|
|
428
434
|
window.handleFormValidation ??= t007.handleFormValidation;
|
|
429
435
|
console.log("%cT007 Input helpers attached to window!", "color: darkturquoise");
|
|
430
436
|
loadResource(T007_INPUT_CSS_SRC);
|
|
431
437
|
t007.FM.init();
|
|
432
438
|
}
|
|
433
|
-
|
|
434
439
|
})();
|
package/dist/index.js
CHANGED
|
@@ -1,130 +1,6 @@
|
|
|
1
|
-
// ../utils/dist/index.js
|
|
2
|
-
function isSameURL(src1, src2) {
|
|
3
|
-
if (typeof src1 !== "string" || typeof src2 !== "string" || !src1 || !src2) return false;
|
|
4
|
-
try {
|
|
5
|
-
const u1 = new URL(src1, window.location.href), u2 = new URL(src2, window.location.href);
|
|
6
|
-
return decodeURIComponent(u1.origin + u1.pathname) === decodeURIComponent(u2.origin + u2.pathname);
|
|
7
|
-
} catch {
|
|
8
|
-
return src1.replace(/\\/g, "/").split("?")[0].trim() === src2.replace(/\\/g, "/").split("?")[0].trim();
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
function createEl(tag, props = {}, dataset = {}, styles = {}) {
|
|
12
|
-
return assignEl(tag ? document?.createElement(tag) : void 0, props, dataset, styles) ?? null;
|
|
13
|
-
}
|
|
14
|
-
function assignEl(el, props = {}, dataset = {}, styles = {}) {
|
|
15
|
-
if (!el) return;
|
|
16
|
-
for (const k of Object.keys(props)) if (props[k] !== void 0) el[k] = props[k];
|
|
17
|
-
for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) el.dataset[k] = String(dataset[k]);
|
|
18
|
-
for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
|
|
19
|
-
}
|
|
20
|
-
function loadResource(src, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
|
|
21
|
-
w.t007._resourceCache ??= {};
|
|
22
|
-
if (w.t007._resourceCache[src]) return w.t007._resourceCache[src];
|
|
23
|
-
const existing = type === "script" ? Array.prototype.find.call(w.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(w.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
|
|
24
|
-
if (existing) return w.t007._resourceCache[src] = Promise.resolve(existing);
|
|
25
|
-
w.t007._resourceCache[src] = new Promise((resolve, reject) => {
|
|
26
|
-
(function tryLoad(remaining, el) {
|
|
27
|
-
const onerror = () => {
|
|
28
|
-
el?.remove?.();
|
|
29
|
-
if (remaining > 1) {
|
|
30
|
-
setTimeout(tryLoad, 1e3, remaining - 1);
|
|
31
|
-
console.warn(`Retrying ${type} load (${attempts - remaining + 1}): ${src}...`);
|
|
32
|
-
} else {
|
|
33
|
-
delete w.t007._resourceCache[src];
|
|
34
|
-
reject(new Error(`${type} load failed after ${attempts} attempts: ${src}`));
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
const url = retryKey && remaining < attempts ? `${src}${src.includes("?") ? "&" : "?"}_${retryKey}=${Date.now()}` : src;
|
|
38
|
-
if (type === "script") w.document.body.append(el = createEl("script", { src: url, type: module ? "module" : "text/javascript", crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
39
|
-
else if (type === "style") w.document.head.append(el = createEl("link", { rel: "stylesheet", href: url, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
40
|
-
else reject(new Error(`Unsupported resource type: ${type}`));
|
|
41
|
-
})(attempts);
|
|
42
|
-
});
|
|
43
|
-
return w.t007._resourceCache[src];
|
|
44
|
-
}
|
|
45
|
-
function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "tmg-video-controls-scroll-assist", vertical = true, horizontal = true } = {}) {
|
|
46
|
-
t007._scrollers ??= /* @__PURE__ */ new WeakMap();
|
|
47
|
-
t007._scroller_r_observer ??= new ResizeObserver((entries) => entries.forEach(({ target }) => t007._scrollers.get(target)?.update()));
|
|
48
|
-
t007._scroller_m_observer ??= new MutationObserver((entries) => {
|
|
49
|
-
const els = /* @__PURE__ */ new Set();
|
|
50
|
-
for (const entry of entries) {
|
|
51
|
-
let node = entry.target instanceof Element ? entry.target : null;
|
|
52
|
-
while (node && !t007._scrollers.has(node)) node = node.parentElement;
|
|
53
|
-
if (node) els.add(node);
|
|
54
|
-
}
|
|
55
|
-
for (const el2 of els) t007._scrollers.get(el2)?.update();
|
|
56
|
-
});
|
|
57
|
-
const parent = el?.parentElement;
|
|
58
|
-
if (!parent || t007._scrollers.has(el)) return;
|
|
59
|
-
const assist = {};
|
|
60
|
-
let scrollId = null, last = performance.now(), assistWidth = 20, assistHeight = 20;
|
|
61
|
-
const update = () => {
|
|
62
|
-
const hasInteractive = !!parent.querySelector('button, a[href], input, select, textarea, [contenteditable="true"], [tabindex]:not([tabindex="-1"])');
|
|
63
|
-
if (horizontal) {
|
|
64
|
-
const w = assist.left?.offsetWidth || assistWidth, check = hasInteractive ? el.clientWidth < w * 2 : false;
|
|
65
|
-
assist.left.style.display = check ? "none" : el.scrollLeft > 0 ? "block" : "none";
|
|
66
|
-
assist.right.style.display = check ? "none" : el.scrollLeft + el.clientWidth < el.scrollWidth - 1 ? "block" : "none";
|
|
67
|
-
assistWidth = w;
|
|
68
|
-
}
|
|
69
|
-
if (vertical) {
|
|
70
|
-
const h = assist.up?.offsetHeight || assistHeight, check = hasInteractive ? el.clientHeight < h * 2 : false;
|
|
71
|
-
assist.up.style.display = check ? "none" : el.scrollTop > 0 ? "block" : "none";
|
|
72
|
-
assist.down.style.display = check ? "none" : el.scrollTop + el.clientHeight < el.scrollHeight - 1 ? "block" : "none";
|
|
73
|
-
assistHeight = h;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
const scroll = (dir) => {
|
|
77
|
-
const frame = () => {
|
|
78
|
-
const now = performance.now(), dt = now - last;
|
|
79
|
-
last = now;
|
|
80
|
-
const d = pxPerSecond * dt / 1e3;
|
|
81
|
-
if (dir === "left") el.scrollLeft = Math.max(0, el.scrollLeft - d);
|
|
82
|
-
if (dir === "right") el.scrollLeft = Math.min(el.scrollWidth - el.clientWidth, el.scrollLeft + d);
|
|
83
|
-
if (dir === "up") el.scrollTop = Math.max(0, el.scrollTop - d);
|
|
84
|
-
if (dir === "down") el.scrollTop = Math.min(el.scrollHeight - el.clientHeight, el.scrollTop + d);
|
|
85
|
-
scrollId = requestAnimationFrame(frame);
|
|
86
|
-
};
|
|
87
|
-
last = performance.now();
|
|
88
|
-
frame();
|
|
89
|
-
};
|
|
90
|
-
const stop = () => (cancelAnimationFrame(scrollId ?? 0), scrollId = null);
|
|
91
|
-
const addAssist = (dir) => {
|
|
92
|
-
const div = createEl("div", { className: assistClassName }, { scrollDirection: dir }, { display: "none" });
|
|
93
|
-
if (!div) return;
|
|
94
|
-
["pointerenter", "dragenter"].forEach((evt) => div.addEventListener(evt, () => scroll(dir)));
|
|
95
|
-
["pointerleave", "pointerup", "pointercancel", "dragleave", "dragend"].forEach((evt) => div.addEventListener(evt, stop));
|
|
96
|
-
dir === "left" || dir === "up" ? parent.insertBefore(div, el) : parent.append(div);
|
|
97
|
-
assist[dir] = div;
|
|
98
|
-
};
|
|
99
|
-
if (horizontal) ["left", "right"].forEach(addAssist);
|
|
100
|
-
if (vertical) ["up", "down"].forEach(addAssist);
|
|
101
|
-
el.addEventListener("scroll", update);
|
|
102
|
-
t007._scroller_r_observer.observe(el);
|
|
103
|
-
t007._scroller_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
|
|
104
|
-
t007._scrollers.set(el, {
|
|
105
|
-
update,
|
|
106
|
-
destroy() {
|
|
107
|
-
stop();
|
|
108
|
-
el.removeEventListener("scroll", update);
|
|
109
|
-
t007._scroller_r_observer.unobserve(el);
|
|
110
|
-
t007._scrollers.delete(el);
|
|
111
|
-
Object.values(assist).forEach((a) => a.remove());
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
return update(), t007._scrollers.get(el);
|
|
115
|
-
}
|
|
116
|
-
if (typeof window !== "undefined") {
|
|
117
|
-
window.t007 ??= {};
|
|
118
|
-
window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
|
|
119
|
-
window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
|
|
120
|
-
window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
|
|
121
|
-
window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/style.css`;
|
|
122
|
-
window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/dist/style.css`;
|
|
123
|
-
window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/style.css`;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
1
|
// src/index.js
|
|
127
|
-
|
|
2
|
+
import { createEl, loadResource, initScrollAssist } from "@t007/utils";
|
|
3
|
+
var formManager = {
|
|
128
4
|
forms: document.getElementsByClassName("t007-input-form"),
|
|
129
5
|
violationKeys: ["valueMissing", "typeMismatch", "patternMismatch", "stepMismatch", "tooShort", "tooLong", "rangeUnderflow", "rangeOverflow", "badInput", "customError"],
|
|
130
6
|
init() {
|
|
@@ -136,7 +12,7 @@ var T007_Form_Manager = {
|
|
|
136
12
|
for (const mutation of mutations) {
|
|
137
13
|
for (const node of mutation.addedNodes) {
|
|
138
14
|
if (!node.tagName || !(node?.classList?.contains("t007-input-field") || node?.querySelector?.(".t007-input-field"))) continue;
|
|
139
|
-
for (const
|
|
15
|
+
for (const field2 of [...node.querySelector(".t007-input-field") ? node.querySelectorAll(".t007-input-field") : [node]]) t007.FM.setUpField(field2);
|
|
140
16
|
}
|
|
141
17
|
}
|
|
142
18
|
}).observe(document.body, { childList: true, subtree: true });
|
|
@@ -173,14 +49,14 @@ var T007_Form_Manager = {
|
|
|
173
49
|
},
|
|
174
50
|
togglePasswordType: (input) => input.type = input.type === "password" ? "text" : "password",
|
|
175
51
|
toggleFilled: (input) => input?.toggleAttribute("data-filled", input.type === "checkbox" || input.type === "radio" ? input.checked : input.value !== "" || input.files?.length > 0),
|
|
176
|
-
setFallbackHelper(
|
|
177
|
-
const helperTextWrapper =
|
|
52
|
+
setFallbackHelper(field2) {
|
|
53
|
+
const helperTextWrapper = field2?.querySelector(".t007-input-helper-text-wrapper");
|
|
178
54
|
if (!helperTextWrapper || helperTextWrapper.querySelector(".t007-input-helper-text[data-violation='auto']")) return;
|
|
179
55
|
helperTextWrapper.append(createEl("p", { className: "t007-input-helper-text" }, { violation: "auto" }));
|
|
180
56
|
},
|
|
181
|
-
setFieldListeners(
|
|
182
|
-
if (!
|
|
183
|
-
const input =
|
|
57
|
+
setFieldListeners(field2) {
|
|
58
|
+
if (!field2) return;
|
|
59
|
+
const input = field2.querySelector(".t007-input"), floatingLabel = field2.querySelector(".t007-input-floating-label"), eyeOpen = field2.querySelector(".t007-input-password-visible-icon"), eyeClosed = field2.querySelector(".t007-input-password-hidden-icon");
|
|
184
60
|
if (input.type === "file")
|
|
185
61
|
input.addEventListener("input", async () => {
|
|
186
62
|
const file = input.files?.[0], img = new Image();
|
|
@@ -218,18 +94,18 @@ var T007_Form_Manager = {
|
|
|
218
94
|
});
|
|
219
95
|
if (floatingLabel) floatingLabel.ontransitionend = () => floatingLabel.classList.remove("t007-input-shake");
|
|
220
96
|
if (eyeOpen && eyeClosed) eyeOpen.onclick = eyeClosed.onclick = () => t007.FM.togglePasswordType(input);
|
|
221
|
-
initScrollAssist(
|
|
97
|
+
initScrollAssist(field2.querySelector(".t007-input-helper-text-wrapper"), { vertical: false });
|
|
222
98
|
},
|
|
223
|
-
setUpField(
|
|
224
|
-
if (
|
|
225
|
-
t007.FM.toggleFilled(
|
|
226
|
-
t007.FM.setFallbackHelper(
|
|
227
|
-
t007.FM.setFieldListeners(
|
|
228
|
-
|
|
99
|
+
setUpField(field2) {
|
|
100
|
+
if (field2.dataset.setUp) return;
|
|
101
|
+
t007.FM.toggleFilled(field2.querySelector(".t007-input"));
|
|
102
|
+
t007.FM.setFallbackHelper(field2);
|
|
103
|
+
t007.FM.setFieldListeners(field2);
|
|
104
|
+
field2.dataset.setUp = "true";
|
|
229
105
|
},
|
|
230
106
|
field({ isWrapper = false, label = "", type = "text", placeholder = "", custom = "", minSize, maxSize, minTotalSize, maxTotalSize, options = [], indeterminate = false, eyeToggler = true, passwordMeter = true, helperText = {}, className = "", fieldClassName = "", children, startIcon = "", endIcon = "", nativeIcon = "", passwordVisibleIcon = "", passwordHiddenIcon = "", ...otherProps }) {
|
|
231
|
-
const isSelect = type === "select", isTextArea = type === "textarea", isCheckboxOrRadio = type === "checkbox" || type === "radio",
|
|
232
|
-
|
|
107
|
+
const isSelect = type === "select", isTextArea = type === "textarea", isCheckboxOrRadio = type === "checkbox" || type === "radio", field2 = createEl("div", { className: `t007-input-field${isWrapper ? " t007-input-is-wrapper" : ""}${indeterminate ? " t007-input-indeterminate" : ""}${!!nativeIcon ? " t007-input-icon-override" : ""}${helperText === false ? " t007-input-no-helper" : ""}${fieldClassName ? ` ${fieldClassName}` : ""}` }), labelEl = createEl("label", { className: isCheckboxOrRadio ? `t007-input-${type}-wrapper` : "t007-input-wrapper" });
|
|
108
|
+
field2.append(labelEl);
|
|
233
109
|
if (isCheckboxOrRadio) {
|
|
234
110
|
labelEl.innerHTML = `
|
|
235
111
|
<span class="t007-input-${type}-box">
|
|
@@ -248,7 +124,7 @@ var T007_Form_Manager = {
|
|
|
248
124
|
`;
|
|
249
125
|
labelEl.append(outline);
|
|
250
126
|
}
|
|
251
|
-
const inputEl =
|
|
127
|
+
const inputEl = field2.inputEl = createEl(isTextArea ? "textarea" : isSelect ? "select" : "input", { className: `t007-input${className ? ` ${className}` : ""}`, placeholder });
|
|
252
128
|
if (isSelect && Array.isArray(options)) inputEl.innerHTML = options.map((opt) => typeof opt === "string" ? `<option value="${opt}">${opt}</option>` : `<option value="${opt.value}">${opt.option}</option>`).join("");
|
|
253
129
|
if (!isSelect && !isTextArea) inputEl.type = type;
|
|
254
130
|
if (custom) inputEl.setAttribute("custom", custom);
|
|
@@ -270,7 +146,7 @@ var T007_Form_Manager = {
|
|
|
270
146
|
if (helperText.info) helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText.info }, { violation: "none" }));
|
|
271
147
|
t007.FM?.violationKeys?.forEach((key) => helperText[key] && helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText[key] }, { violation: key })));
|
|
272
148
|
helperLine.append(helperWrapper);
|
|
273
|
-
|
|
149
|
+
field2.append(helperLine);
|
|
274
150
|
}
|
|
275
151
|
if (passwordMeter && type === "password") {
|
|
276
152
|
const meter = createEl("div", { className: "t007-input-password-meter" }, { strengthLevel: "1" });
|
|
@@ -282,9 +158,9 @@ var T007_Form_Manager = {
|
|
|
282
158
|
<div class="t007-input-p-very-strong"></div>
|
|
283
159
|
</div>
|
|
284
160
|
`;
|
|
285
|
-
|
|
161
|
+
field2.append(meter);
|
|
286
162
|
}
|
|
287
|
-
return
|
|
163
|
+
return field2;
|
|
288
164
|
},
|
|
289
165
|
handleFormValidation(form) {
|
|
290
166
|
if (!form?.classList.contains("t007-input-form") || form.dataset?.isValidating) return;
|
|
@@ -318,7 +194,7 @@ var T007_Form_Manager = {
|
|
|
318
194
|
form.classList.toggle("t007-input-submit-loading", bool);
|
|
319
195
|
}
|
|
320
196
|
function toggleError(input, bool, flag = false) {
|
|
321
|
-
const
|
|
197
|
+
const field2 = input.closest(".t007-input-field"), floatingLabel = field2.querySelector(".t007-input-floating-label");
|
|
322
198
|
if (bool && flag) {
|
|
323
199
|
input.setAttribute("data-error", "");
|
|
324
200
|
floatingLabel?.classList.add("t007-input-shake");
|
|
@@ -326,7 +202,7 @@ var T007_Form_Manager = {
|
|
|
326
202
|
toggleHelper(input, input.hasAttribute("data-error"));
|
|
327
203
|
}
|
|
328
204
|
function toggleHelper(input, bool) {
|
|
329
|
-
const
|
|
205
|
+
const field2 = input.closest(".t007-input-field"), violation = t007.FM.violationKeys.find((violation2) => input.Validity?.[violation2] || input.validity[violation2]) ?? "", helper = field2.querySelector(`.t007-input-helper-text[data-violation="${violation}"]`), fallbackHelper = field2.querySelector(`.t007-input-helper-text[data-violation="auto"]`);
|
|
330
206
|
input.closest(".t007-input-field").querySelectorAll(`.t007-input-helper-text:not([data-violation="${violation}"])`).forEach((helper2) => helper2?.classList.remove("t007-input-show"));
|
|
331
207
|
if (helper) helper.classList.toggle("t007-input-show", bool);
|
|
332
208
|
else if (fallbackHelper) {
|
|
@@ -410,20 +286,26 @@ var T007_Form_Manager = {
|
|
|
410
286
|
}
|
|
411
287
|
function toggleFormGlobalError(bool) {
|
|
412
288
|
form.toggleAttribute("data-global-error", bool);
|
|
413
|
-
form.querySelectorAll(".t007-input-field").forEach((
|
|
414
|
-
|
|
415
|
-
if (bool)
|
|
289
|
+
form.querySelectorAll(".t007-input-field").forEach((field2) => {
|
|
290
|
+
field2.querySelector(".t007-input")?.toggleAttribute("data-error", bool);
|
|
291
|
+
if (bool) field2.querySelector(".t007-input-floating-label")?.classList.add("t007-input-shake");
|
|
416
292
|
});
|
|
417
293
|
}
|
|
418
294
|
}
|
|
419
295
|
};
|
|
296
|
+
var { field, handleFormValidation } = formManager;
|
|
420
297
|
if (typeof window !== "undefined") {
|
|
421
|
-
t007.FM =
|
|
422
|
-
t007.field =
|
|
423
|
-
t007.handleFormValidation =
|
|
298
|
+
t007.FM = formManager;
|
|
299
|
+
t007.field = field;
|
|
300
|
+
t007.handleFormValidation = handleFormValidation;
|
|
424
301
|
window.field ??= t007.field;
|
|
425
302
|
window.handleFormValidation ??= t007.handleFormValidation;
|
|
426
303
|
console.log("%cT007 Input helpers attached to window!", "color: darkturquoise");
|
|
427
304
|
loadResource(T007_INPUT_CSS_SRC);
|
|
428
305
|
t007.FM.init();
|
|
429
306
|
}
|
|
307
|
+
export {
|
|
308
|
+
field,
|
|
309
|
+
formManager,
|
|
310
|
+
handleFormValidation
|
|
311
|
+
};
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
// ../utils/dist/index.js
|
|
2
|
+
function isSameURL(src1, src2) {
|
|
3
|
+
if (typeof src1 !== "string" || typeof src2 !== "string" || !src1 || !src2) return false;
|
|
4
|
+
try {
|
|
5
|
+
const u1 = new URL(src1, window.location.href), u2 = new URL(src2, window.location.href);
|
|
6
|
+
return decodeURIComponent(u1.origin + u1.pathname) === decodeURIComponent(u2.origin + u2.pathname);
|
|
7
|
+
} catch {
|
|
8
|
+
return src1.replace(/\\/g, "/").split("?")[0].trim() === src2.replace(/\\/g, "/").split("?")[0].trim();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
|
|
12
|
+
return assignEl(el, props, dataset, styles), el;
|
|
13
|
+
}
|
|
14
|
+
function assignEl(el, props, dataset, styles) {
|
|
15
|
+
if (!el) return;
|
|
16
|
+
if (props) {
|
|
17
|
+
for (const k of Object.keys(props)) if (props[k] !== void 0) el[k] = props[k];
|
|
18
|
+
}
|
|
19
|
+
if (dataset) {
|
|
20
|
+
for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) el.dataset[k] = String(dataset[k]);
|
|
21
|
+
}
|
|
22
|
+
if (styles) {
|
|
23
|
+
for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function loadResource(src, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
|
|
27
|
+
w.t007._resourceCache ??= {};
|
|
28
|
+
if (w.t007._resourceCache[src]) return w.t007._resourceCache[src];
|
|
29
|
+
const existing = type === "script" ? Array.prototype.find.call(w.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(w.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
|
|
30
|
+
if (existing) return w.t007._resourceCache[src] = Promise.resolve(existing);
|
|
31
|
+
w.t007._resourceCache[src] = new Promise((resolve, reject) => {
|
|
32
|
+
(function tryLoad(remaining, el) {
|
|
33
|
+
const onerror = () => {
|
|
34
|
+
el?.remove?.();
|
|
35
|
+
if (remaining > 1) {
|
|
36
|
+
setTimeout(tryLoad, 1e3, remaining - 1);
|
|
37
|
+
console.warn(`Retrying ${type} load (${attempts - remaining + 1}): ${src}...`);
|
|
38
|
+
} else {
|
|
39
|
+
delete w.t007._resourceCache[src];
|
|
40
|
+
reject(new Error(`${type} load failed after ${attempts} attempts: ${src}`));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const url = retryKey && remaining < attempts ? `${src}${src.includes("?") ? "&" : "?"}_${retryKey}=${Date.now()}` : src;
|
|
44
|
+
if (type === "script") w.document.body.append(el = createEl("script", { src: url, type: module ? "module" : "text/javascript", crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
45
|
+
else if (type === "style") w.document.head.append(el = createEl("link", { rel: "stylesheet", href: url, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
46
|
+
else reject(new Error(`Unsupported resource type: ${type}`));
|
|
47
|
+
})(attempts);
|
|
48
|
+
});
|
|
49
|
+
return w.t007._resourceCache[src];
|
|
50
|
+
}
|
|
51
|
+
function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "tmg-video-controls-scroll-assist", vertical = true, horizontal = true } = {}) {
|
|
52
|
+
t007._scrollers ??= /* @__PURE__ */ new WeakMap();
|
|
53
|
+
t007._scroller_r_observer ??= new ResizeObserver((entries) => entries.forEach(({ target }) => t007._scrollers.get(target)?.update()));
|
|
54
|
+
t007._scroller_m_observer ??= new MutationObserver((entries) => {
|
|
55
|
+
const els = /* @__PURE__ */ new Set();
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
let node = entry.target instanceof Element ? entry.target : null;
|
|
58
|
+
while (node && !t007._scrollers.has(node)) node = node.parentElement;
|
|
59
|
+
if (node) els.add(node);
|
|
60
|
+
}
|
|
61
|
+
for (const el2 of els) t007._scrollers.get(el2)?.update();
|
|
62
|
+
});
|
|
63
|
+
const parent = el?.parentElement;
|
|
64
|
+
if (!parent || t007._scrollers.has(el)) return;
|
|
65
|
+
const assist = {};
|
|
66
|
+
let scrollId = null, last = performance.now(), assistWidth = 20, assistHeight = 20;
|
|
67
|
+
const update = () => {
|
|
68
|
+
const hasInteractive = !!parent.querySelector('button, a[href], input, select, textarea, [contenteditable="true"], [tabindex]:not([tabindex="-1"])');
|
|
69
|
+
if (horizontal) {
|
|
70
|
+
const w = assist.left?.offsetWidth || assistWidth, check = hasInteractive ? el.clientWidth < w * 2 : false;
|
|
71
|
+
assist.left.style.display = check ? "none" : el.scrollLeft > 0 ? "block" : "none";
|
|
72
|
+
assist.right.style.display = check ? "none" : el.scrollLeft + el.clientWidth < el.scrollWidth - 1 ? "block" : "none";
|
|
73
|
+
assistWidth = w;
|
|
74
|
+
}
|
|
75
|
+
if (vertical) {
|
|
76
|
+
const h = assist.up?.offsetHeight || assistHeight, check = hasInteractive ? el.clientHeight < h * 2 : false;
|
|
77
|
+
assist.up.style.display = check ? "none" : el.scrollTop > 0 ? "block" : "none";
|
|
78
|
+
assist.down.style.display = check ? "none" : el.scrollTop + el.clientHeight < el.scrollHeight - 1 ? "block" : "none";
|
|
79
|
+
assistHeight = h;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const scroll = (dir) => {
|
|
83
|
+
const frame = () => {
|
|
84
|
+
const now = performance.now(), dt = now - last;
|
|
85
|
+
last = now;
|
|
86
|
+
const d = pxPerSecond * dt / 1e3;
|
|
87
|
+
if (dir === "left") el.scrollLeft = Math.max(0, el.scrollLeft - d);
|
|
88
|
+
if (dir === "right") el.scrollLeft = Math.min(el.scrollWidth - el.clientWidth, el.scrollLeft + d);
|
|
89
|
+
if (dir === "up") el.scrollTop = Math.max(0, el.scrollTop - d);
|
|
90
|
+
if (dir === "down") el.scrollTop = Math.min(el.scrollHeight - el.clientHeight, el.scrollTop + d);
|
|
91
|
+
scrollId = requestAnimationFrame(frame);
|
|
92
|
+
};
|
|
93
|
+
last = performance.now();
|
|
94
|
+
frame();
|
|
95
|
+
};
|
|
96
|
+
const stop = () => (cancelAnimationFrame(scrollId ?? 0), scrollId = null);
|
|
97
|
+
const addAssist = (dir) => {
|
|
98
|
+
const div = createEl("div", { className: assistClassName }, { scrollDirection: dir }, { display: "none" });
|
|
99
|
+
if (!div) return;
|
|
100
|
+
["pointerenter", "dragenter"].forEach((evt) => div.addEventListener(evt, () => scroll(dir)));
|
|
101
|
+
["pointerleave", "pointerup", "pointercancel", "dragleave", "dragend"].forEach((evt) => div.addEventListener(evt, stop));
|
|
102
|
+
dir === "left" || dir === "up" ? parent.insertBefore(div, el) : parent.append(div);
|
|
103
|
+
assist[dir] = div;
|
|
104
|
+
};
|
|
105
|
+
if (horizontal) ["left", "right"].forEach(addAssist);
|
|
106
|
+
if (vertical) ["up", "down"].forEach(addAssist);
|
|
107
|
+
el.addEventListener("scroll", update);
|
|
108
|
+
t007._scroller_r_observer.observe(el);
|
|
109
|
+
t007._scroller_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
|
|
110
|
+
t007._scrollers.set(el, {
|
|
111
|
+
update,
|
|
112
|
+
destroy() {
|
|
113
|
+
stop();
|
|
114
|
+
el.removeEventListener("scroll", update);
|
|
115
|
+
t007._scroller_r_observer.unobserve(el);
|
|
116
|
+
t007._scrollers.delete(el);
|
|
117
|
+
Object.values(assist).forEach((a) => a.remove());
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return update(), t007._scrollers.get(el);
|
|
121
|
+
}
|
|
122
|
+
if (typeof window !== "undefined") {
|
|
123
|
+
window.t007 ??= {};
|
|
124
|
+
window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
|
|
125
|
+
window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
|
|
126
|
+
window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
|
|
127
|
+
window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/style.css`;
|
|
128
|
+
window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/style.css`;
|
|
129
|
+
window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/style.css`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/index.js
|
|
133
|
+
var formManager = {
|
|
134
|
+
forms: document.getElementsByClassName("t007-input-form"),
|
|
135
|
+
violationKeys: ["valueMissing", "typeMismatch", "patternMismatch", "stepMismatch", "tooShort", "tooLong", "rangeUnderflow", "rangeOverflow", "badInput", "customError"],
|
|
136
|
+
init() {
|
|
137
|
+
t007.FM.observeDOMForFields();
|
|
138
|
+
Array.from(t007.FM.forms).forEach(t007.FM.handleFormValidation);
|
|
139
|
+
},
|
|
140
|
+
observeDOMForFields() {
|
|
141
|
+
new MutationObserver((mutations) => {
|
|
142
|
+
for (const mutation of mutations) {
|
|
143
|
+
for (const node of mutation.addedNodes) {
|
|
144
|
+
if (!node.tagName || !(node?.classList?.contains("t007-input-field") || node?.querySelector?.(".t007-input-field"))) continue;
|
|
145
|
+
for (const field2 of [...node.querySelector(".t007-input-field") ? node.querySelectorAll(".t007-input-field") : [node]]) t007.FM.setUpField(field2);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}).observe(document.body, { childList: true, subtree: true });
|
|
149
|
+
},
|
|
150
|
+
getFilesHelper(files, opts) {
|
|
151
|
+
if (!files || !files.length) return { violation: null, message: "" };
|
|
152
|
+
const totalFiles = files.length;
|
|
153
|
+
let totalSize = 0;
|
|
154
|
+
let currFiles = 0;
|
|
155
|
+
const setMaxError = (size, max, n = 0) => ({ violation: "rangeOverflow", message: n ? `File ${files.length > 1 ? n : ""} size of ${t007.FM.formatSize(size)} exceeds the per file maximum of ${t007.FM.formatSize(max)}` : `Total files size of ${t007.FM.formatSize(size)} exceeds the total maximum of ${t007.FM.formatSize(max)}` });
|
|
156
|
+
const setMinError = (size, min, n = 0) => ({ violation: "rangeUnderflow", message: n ? `File ${files.length > 1 ? n : ""} size of ${t007.FM.formatSize(size)} is less than the per file minimum of ${t007.FM.formatSize(min)}` : `Total files size of ${t007.FM.formatSize(size)} is less than the total minimum of ${t007.FM.formatSize(min)}` });
|
|
157
|
+
for (const file of files) {
|
|
158
|
+
currFiles++;
|
|
159
|
+
totalSize += file.size;
|
|
160
|
+
if (opts.accept) {
|
|
161
|
+
const acceptedTypes = opts.accept.split(",").map((type) => type.trim().replace(/^[*\.]+|[*\.]+$/g, "")).filter(Boolean) || [];
|
|
162
|
+
if (!acceptedTypes.some((type) => file.type.includes(type))) return { violation: "typeMismatch", message: `File${currFiles > 1 ? currFiles : ""} type of '${file.type}' is not accepted.` };
|
|
163
|
+
}
|
|
164
|
+
if (opts.maxSize && file.size > opts.maxSize) return setMaxError(file.size, opts.maxSize, currFiles);
|
|
165
|
+
if (opts.minSize && file.size < opts.minSize) return setMinError(file.size, opts.minSize, currFiles);
|
|
166
|
+
if (opts.multiple) {
|
|
167
|
+
if (opts.maxTotalSize && totalSize > opts.maxTotalSize) return setMaxError(totalSize, opts.maxTotalSize);
|
|
168
|
+
if (opts.minTotalSize && totalSize < opts.minTotalSize) return setMinError(totalSize, opts.minTotalSize);
|
|
169
|
+
if (opts.maxLength && totalFiles > opts.maxLength) return { violation: "tooLong", message: `Selected ${totalFiles} files exceeds the maximum of ${opts.maxLength} allowed file${opts.maxLength == 1 ? "" : "s"}` };
|
|
170
|
+
if (opts.minLength && totalFiles < opts.minLength) return { violation: "tooShort", message: `Selected ${totalFiles} files is less than the minimum of ${opts.minLength} allowed file${opts.minLength == 1 ? "" : "s"}` };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return { violation: null, message: "" };
|
|
174
|
+
},
|
|
175
|
+
formatSize(size, decimals = 3, base = 1e3) {
|
|
176
|
+
if (size < base) return `${size} byte${size == 1 ? "" : "s"}`;
|
|
177
|
+
const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], exponent = Math.min(Math.floor(Math.log(size) / Math.log(base)), units.length - 1);
|
|
178
|
+
return `${(size / Math.pow(base, exponent)).toFixed(decimals).replace(/\.0+$/, "")} ${units[exponent]}`;
|
|
179
|
+
},
|
|
180
|
+
togglePasswordType: (input) => input.type = input.type === "password" ? "text" : "password",
|
|
181
|
+
toggleFilled: (input) => input?.toggleAttribute("data-filled", input.type === "checkbox" || input.type === "radio" ? input.checked : input.value !== "" || input.files?.length > 0),
|
|
182
|
+
setFallbackHelper(field2) {
|
|
183
|
+
const helperTextWrapper = field2?.querySelector(".t007-input-helper-text-wrapper");
|
|
184
|
+
if (!helperTextWrapper || helperTextWrapper.querySelector(".t007-input-helper-text[data-violation='auto']")) return;
|
|
185
|
+
helperTextWrapper.append(createEl("p", { className: "t007-input-helper-text" }, { violation: "auto" }));
|
|
186
|
+
},
|
|
187
|
+
setFieldListeners(field2) {
|
|
188
|
+
if (!field2) return;
|
|
189
|
+
const input = field2.querySelector(".t007-input"), floatingLabel = field2.querySelector(".t007-input-floating-label"), eyeOpen = field2.querySelector(".t007-input-password-visible-icon"), eyeClosed = field2.querySelector(".t007-input-password-hidden-icon");
|
|
190
|
+
if (input.type === "file")
|
|
191
|
+
input.addEventListener("input", async () => {
|
|
192
|
+
const file = input.files?.[0], img = new Image();
|
|
193
|
+
img.onload = () => {
|
|
194
|
+
input.style.setProperty("--t007-input-image-src", `url(${src})`);
|
|
195
|
+
input.classList.add("t007-input-image-selected");
|
|
196
|
+
setTimeout(() => URL.revokeObjectURL(src), 1e3);
|
|
197
|
+
};
|
|
198
|
+
img.onerror = () => {
|
|
199
|
+
input.style.removeProperty("--t007-input-image-src");
|
|
200
|
+
input.classList.remove("t007-input-image-selected");
|
|
201
|
+
URL.revokeObjectURL(src);
|
|
202
|
+
};
|
|
203
|
+
let src;
|
|
204
|
+
if (file?.type?.startsWith("image")) src = URL.createObjectURL(file);
|
|
205
|
+
else if (file?.type?.startsWith("video")) {
|
|
206
|
+
src = await new Promise((resolve) => {
|
|
207
|
+
let video = createEl("video"), canvas = createEl("canvas"), context = canvas.getContext("2d");
|
|
208
|
+
video.ontimeupdate = () => {
|
|
209
|
+
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
|
210
|
+
canvas.toBlob((blob) => resolve(URL.createObjectURL(blob)));
|
|
211
|
+
URL.revokeObjectURL(video.src);
|
|
212
|
+
video = video.src = video.onloadedmetadata = video.ontimeupdate = null;
|
|
213
|
+
};
|
|
214
|
+
video.onloadeddata = () => video.currentTime = 3;
|
|
215
|
+
video.src = URL.createObjectURL(file);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (!src) {
|
|
219
|
+
input.style.removeProperty("--t007-input-image-src");
|
|
220
|
+
input.classList.remove("t007-input-image-selected");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
img.src = src;
|
|
224
|
+
});
|
|
225
|
+
if (floatingLabel) floatingLabel.ontransitionend = () => floatingLabel.classList.remove("t007-input-shake");
|
|
226
|
+
if (eyeOpen && eyeClosed) eyeOpen.onclick = eyeClosed.onclick = () => t007.FM.togglePasswordType(input);
|
|
227
|
+
initScrollAssist(field2.querySelector(".t007-input-helper-text-wrapper"), { vertical: false });
|
|
228
|
+
},
|
|
229
|
+
setUpField(field2) {
|
|
230
|
+
if (field2.dataset.setUp) return;
|
|
231
|
+
t007.FM.toggleFilled(field2.querySelector(".t007-input"));
|
|
232
|
+
t007.FM.setFallbackHelper(field2);
|
|
233
|
+
t007.FM.setFieldListeners(field2);
|
|
234
|
+
field2.dataset.setUp = "true";
|
|
235
|
+
},
|
|
236
|
+
field({ isWrapper = false, label = "", type = "text", placeholder = "", custom = "", minSize, maxSize, minTotalSize, maxTotalSize, options = [], indeterminate = false, eyeToggler = true, passwordMeter = true, helperText = {}, className = "", fieldClassName = "", children, startIcon = "", endIcon = "", nativeIcon = "", passwordVisibleIcon = "", passwordHiddenIcon = "", ...otherProps }) {
|
|
237
|
+
const isSelect = type === "select", isTextArea = type === "textarea", isCheckboxOrRadio = type === "checkbox" || type === "radio", field2 = createEl("div", { className: `t007-input-field${isWrapper ? " t007-input-is-wrapper" : ""}${indeterminate ? " t007-input-indeterminate" : ""}${!!nativeIcon ? " t007-input-icon-override" : ""}${helperText === false ? " t007-input-no-helper" : ""}${fieldClassName ? ` ${fieldClassName}` : ""}` }), labelEl = createEl("label", { className: isCheckboxOrRadio ? `t007-input-${type}-wrapper` : "t007-input-wrapper" });
|
|
238
|
+
field2.append(labelEl);
|
|
239
|
+
if (isCheckboxOrRadio) {
|
|
240
|
+
labelEl.innerHTML = `
|
|
241
|
+
<span class="t007-input-${type}-box">
|
|
242
|
+
<span class="t007-input-${type}-tag"></span>
|
|
243
|
+
</span>
|
|
244
|
+
<span class="t007-input-${type}-label">${label}</span>
|
|
245
|
+
`;
|
|
246
|
+
} else {
|
|
247
|
+
const outline = createEl("span", { className: "t007-input-outline" });
|
|
248
|
+
outline.innerHTML = `
|
|
249
|
+
<span class="t007-input-outline-leading"></span>
|
|
250
|
+
<span class="t007-input-outline-notch">
|
|
251
|
+
<span class="t007-input-floating-label">${label}</span>
|
|
252
|
+
</span>
|
|
253
|
+
<span class="t007-input-outline-trailing"></span>
|
|
254
|
+
`;
|
|
255
|
+
labelEl.append(outline);
|
|
256
|
+
}
|
|
257
|
+
const inputEl = field2.inputEl = createEl(isTextArea ? "textarea" : isSelect ? "select" : "input", { className: `t007-input${className ? ` ${className}` : ""}`, placeholder });
|
|
258
|
+
if (isSelect && Array.isArray(options)) inputEl.innerHTML = options.map((opt) => typeof opt === "string" ? `<option value="${opt}">${opt}</option>` : `<option value="${opt.value}">${opt.option}</option>`).join("");
|
|
259
|
+
if (!isSelect && !isTextArea) inputEl.type = type;
|
|
260
|
+
if (custom) inputEl.setAttribute("custom", custom);
|
|
261
|
+
if (minSize) inputEl.setAttribute("minsize", minSize);
|
|
262
|
+
if (maxSize) inputEl.setAttribute("maxsize", maxSize);
|
|
263
|
+
if (minTotalSize) inputEl.setAttribute("mintotalsize", minTotalSize);
|
|
264
|
+
if (maxTotalSize) inputEl.setAttribute("maxtotalsize", maxTotalSize);
|
|
265
|
+
Object.keys(otherProps).forEach((key) => inputEl[key] = otherProps[key]);
|
|
266
|
+
labelEl.append(!isWrapper ? inputEl : children);
|
|
267
|
+
const nativeTypes = ["date", "time", "month", "datetime-local"];
|
|
268
|
+
if (nativeTypes.includes(type) && nativeIcon) labelEl.append(createEl("i", { className: "t007-input-icon t007-input-native-icon", innerHTML: nativeIcon }));
|
|
269
|
+
else if (endIcon) labelEl.append(createEl("i", { className: "t007-input-icon", innerHTML: endIcon }));
|
|
270
|
+
if (type === "password" && eyeToggler) {
|
|
271
|
+
labelEl.append(createEl("i", { role: "button", ariaLabel: "Show password", className: "t007-input-icon t007-input-password-visible-icon", innerHTML: passwordVisibleIcon || `<svg width="24" height="24"><path fill="rgba(0,0,0,.54)" d="M12 16q1.875 0 3.188-1.312Q16.5 13.375 16.5 11.5q0-1.875-1.312-3.188Q13.875 7 12 7q-1.875 0-3.188 1.312Q7.5 9.625 7.5 11.5q0 1.875 1.312 3.188Q10.125 16 12 16Zm0-1.8q-1.125 0-1.912-.788Q9.3 12.625 9.3 11.5t.788-1.913Q10.875 8.8 12 8.8t1.913.787q.787.788.787 1.913t-.787 1.912q-.788.788-1.913.788Zm0 4.8q-3.65 0-6.65-2.038-3-2.037-4.35-5.462 1.35-3.425 4.35-5.463Q8.35 4 12 4q3.65 0 6.65 2.037 3 2.038 4.35 5.463-1.35 3.425-4.35 5.462Q15.65 19 12 19Z"/></svg>` }));
|
|
272
|
+
labelEl.append(createEl("i", { role: "button", ariaLabel: "Hide password", className: "t007-input-icon t007-input-password-hidden-icon", innerHTML: passwordHiddenIcon || `<svg width="24" height="24"><path fill="rgba(0,0,0,.54)" d="m19.8 22.6-4.2-4.15q-.875.275-1.762.413Q12.95 19 12 19q-3.775 0-6.725-2.087Q2.325 14.825 1 11.5q.525-1.325 1.325-2.463Q3.125 7.9 4.15 7L1.4 4.2l1.4-1.4 18.4 18.4ZM12 16q.275 0 .512-.025.238-.025.513-.1l-5.4-5.4q-.075.275-.1.513-.025.237-.025.512 0 1.875 1.312 3.188Q10.125 16 12 16Zm7.3.45-3.175-3.15q.175-.425.275-.862.1-.438.1-.938 0-1.875-1.312-3.188Q13.875 7 12 7q-.5 0-.938.1-.437.1-.862.3L7.65 4.85q1.025-.425 2.1-.638Q10.825 4 12 4q3.775 0 6.725 2.087Q21.675 8.175 23 11.5q-.575 1.475-1.512 2.738Q20.55 15.5 19.3 16.45Zm-4.625-4.6-3-3q.7-.125 1.288.112.587.238 1.012.688.425.45.613 1.038.187.587.087 1.162Z"/></svg>` }));
|
|
273
|
+
}
|
|
274
|
+
if (helperText !== false) {
|
|
275
|
+
const helperLine = createEl("div", { className: "t007-input-helper-line" }), helperWrapper = createEl("div", { className: "t007-input-helper-text-wrapper", tabIndex: "-1" });
|
|
276
|
+
if (helperText.info) helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText.info }, { violation: "none" }));
|
|
277
|
+
t007.FM?.violationKeys?.forEach((key) => helperText[key] && helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText[key] }, { violation: key })));
|
|
278
|
+
helperLine.append(helperWrapper);
|
|
279
|
+
field2.append(helperLine);
|
|
280
|
+
}
|
|
281
|
+
if (passwordMeter && type === "password") {
|
|
282
|
+
const meter = createEl("div", { className: "t007-input-password-meter" }, { strengthLevel: "1" });
|
|
283
|
+
meter.innerHTML = `
|
|
284
|
+
<div class="t007-input-password-strength-meter">
|
|
285
|
+
<div class="t007-input-p-weak"></div>
|
|
286
|
+
<div class="t007-input-p-fair"></div>
|
|
287
|
+
<div class="t007-input-p-strong"></div>
|
|
288
|
+
<div class="t007-input-p-very-strong"></div>
|
|
289
|
+
</div>
|
|
290
|
+
`;
|
|
291
|
+
field2.append(meter);
|
|
292
|
+
}
|
|
293
|
+
return field2;
|
|
294
|
+
},
|
|
295
|
+
handleFormValidation(form) {
|
|
296
|
+
if (!form?.classList.contains("t007-input-form") || form.dataset?.isValidating) return;
|
|
297
|
+
form.dataset.isValidating = "true";
|
|
298
|
+
form.validateOnClient = validateFormOnClient;
|
|
299
|
+
form.toggleGlobalError = toggleFormGlobalError;
|
|
300
|
+
const fields = form.getElementsByClassName("t007-input-field"), inputs = form.getElementsByClassName("t007-input");
|
|
301
|
+
Array.from(fields).forEach(t007.FM.setUpField);
|
|
302
|
+
form.addEventListener("input", ({ target }) => {
|
|
303
|
+
t007.FM.toggleFilled(target);
|
|
304
|
+
validateInput(target);
|
|
305
|
+
});
|
|
306
|
+
form.addEventListener("focusout", ({ target }) => validateInput(target, true));
|
|
307
|
+
form.addEventListener("submit", async (e) => {
|
|
308
|
+
toggleSubmitLoader(true);
|
|
309
|
+
try {
|
|
310
|
+
e.preventDefault();
|
|
311
|
+
if (!validateFormOnClient()) return;
|
|
312
|
+
if (form.validateOnServer && !await form.validateOnServer()) {
|
|
313
|
+
toggleFormGlobalError(true);
|
|
314
|
+
form.addEventListener("input", () => toggleFormGlobalError(false), { once: true, useCapture: true });
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
form.onSubmit ? form.onSubmit() : form.submit();
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.error(error);
|
|
320
|
+
}
|
|
321
|
+
toggleSubmitLoader(false);
|
|
322
|
+
});
|
|
323
|
+
function toggleSubmitLoader(bool) {
|
|
324
|
+
form.classList.toggle("t007-input-submit-loading", bool);
|
|
325
|
+
}
|
|
326
|
+
function toggleError(input, bool, flag = false) {
|
|
327
|
+
const field2 = input.closest(".t007-input-field"), floatingLabel = field2.querySelector(".t007-input-floating-label");
|
|
328
|
+
if (bool && flag) {
|
|
329
|
+
input.setAttribute("data-error", "");
|
|
330
|
+
floatingLabel?.classList.add("t007-input-shake");
|
|
331
|
+
} else if (!bool) input.removeAttribute("data-error");
|
|
332
|
+
toggleHelper(input, input.hasAttribute("data-error"));
|
|
333
|
+
}
|
|
334
|
+
function toggleHelper(input, bool) {
|
|
335
|
+
const field2 = input.closest(".t007-input-field"), violation = t007.FM.violationKeys.find((violation2) => input.Validity?.[violation2] || input.validity[violation2]) ?? "", helper = field2.querySelector(`.t007-input-helper-text[data-violation="${violation}"]`), fallbackHelper = field2.querySelector(`.t007-input-helper-text[data-violation="auto"]`);
|
|
336
|
+
input.closest(".t007-input-field").querySelectorAll(`.t007-input-helper-text:not([data-violation="${violation}"])`).forEach((helper2) => helper2?.classList.remove("t007-input-show"));
|
|
337
|
+
if (helper) helper.classList.toggle("t007-input-show", bool);
|
|
338
|
+
else if (fallbackHelper) {
|
|
339
|
+
fallbackHelper.textContent = input.validationMessage;
|
|
340
|
+
fallbackHelper.classList.toggle("t007-input-show", bool);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function forceRevalidate(input) {
|
|
344
|
+
input.checkValidity();
|
|
345
|
+
input.dispatchEvent(new Event("input"));
|
|
346
|
+
}
|
|
347
|
+
function updatePasswordMeter(input) {
|
|
348
|
+
const passwordMeter = input.closest(".t007-input-field").querySelector(".t007-input-password-meter");
|
|
349
|
+
if (!passwordMeter) return;
|
|
350
|
+
const value = input.value?.trim();
|
|
351
|
+
let strengthLevel = 0;
|
|
352
|
+
if (value.length < Number(input.minLength ?? 0)) strengthLevel = 1;
|
|
353
|
+
else {
|
|
354
|
+
if (/[a-z]/.test(value)) strengthLevel++;
|
|
355
|
+
if (/[A-Z]/.test(value)) strengthLevel++;
|
|
356
|
+
if (/[0-9]/.test(value)) strengthLevel++;
|
|
357
|
+
if (/[\W_]/.test(value)) strengthLevel++;
|
|
358
|
+
}
|
|
359
|
+
passwordMeter.dataset.strengthLevel = strengthLevel;
|
|
360
|
+
}
|
|
361
|
+
function validateInput(input, flag = false) {
|
|
362
|
+
if (form.dataset.globalError || !input?.classList.contains("t007-input")) return;
|
|
363
|
+
updatePasswordMeter(input);
|
|
364
|
+
let value, errorBool;
|
|
365
|
+
switch (input.custom ?? input.getAttribute("custom")) {
|
|
366
|
+
case "password":
|
|
367
|
+
value = input.value?.trim();
|
|
368
|
+
if (value === "") break;
|
|
369
|
+
const confirmPasswordInput = Array.from(inputs).find((input2) => (input2.custom ?? input2.getAttribute("custom")) === "confirm-password");
|
|
370
|
+
if (!confirmPasswordInput) break;
|
|
371
|
+
const confirmPasswordValue = confirmPasswordInput.value?.trim();
|
|
372
|
+
confirmPasswordInput.setCustomValidity(value !== confirmPasswordValue ? "Both passwords do not match" : "");
|
|
373
|
+
toggleError(confirmPasswordInput, value !== confirmPasswordValue, flag);
|
|
374
|
+
break;
|
|
375
|
+
case "confirm_password":
|
|
376
|
+
value = input.value?.trim();
|
|
377
|
+
if (value === "") break;
|
|
378
|
+
const passwordInput = Array.from(inputs).find((input2) => (input2.custom ?? input2.getAttribute("custom")) === "password");
|
|
379
|
+
if (!passwordInput) break;
|
|
380
|
+
const passwordValue = passwordInput.value?.trim();
|
|
381
|
+
errorBool = value !== passwordValue;
|
|
382
|
+
input.setCustomValidity(errorBool ? "Both passwords do not match" : "");
|
|
383
|
+
break;
|
|
384
|
+
case "onward_date":
|
|
385
|
+
if (input.min) break;
|
|
386
|
+
input.min = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
387
|
+
forceRevalidate(input);
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
if (input.type === "file") {
|
|
391
|
+
input.Validity = {};
|
|
392
|
+
const { violation, message } = t007.FM.getFilesHelper(input.files ?? [], {
|
|
393
|
+
accept: input.accept,
|
|
394
|
+
multiple: input.multiple,
|
|
395
|
+
maxSize: input.maxSize ?? Number(input.getAttribute("maxsize")),
|
|
396
|
+
minSize: input.minSize ?? Number(input.getAttribute("minsize")),
|
|
397
|
+
maxTotalSize: input.maxTotalSize ?? Number(input.getAttribute("maxtotalsize")),
|
|
398
|
+
minTotalSize: input.minTotalSize ?? Number(input.getAttribute("mintotalsize")),
|
|
399
|
+
maxLength: input.maxLength ?? Number(input.getAttribute("maxlength")),
|
|
400
|
+
minLength: input.minLength ?? Number(input.getAttribute("minLength"))
|
|
401
|
+
});
|
|
402
|
+
errorBool = !!message;
|
|
403
|
+
input.setCustomValidity(message);
|
|
404
|
+
if (violation) input.Validity[violation] = true;
|
|
405
|
+
}
|
|
406
|
+
errorBool = errorBool ?? !input.validity?.valid;
|
|
407
|
+
toggleError(input, errorBool, flag);
|
|
408
|
+
if (errorBool) return;
|
|
409
|
+
if (input.type === "radio")
|
|
410
|
+
Array.from(inputs)?.filter((i) => i.name == input.name)?.forEach((radio) => toggleError(radio, errorBool, flag));
|
|
411
|
+
}
|
|
412
|
+
function validateFormOnClient() {
|
|
413
|
+
Array.from(inputs).forEach((input) => validateInput(input, true));
|
|
414
|
+
form.querySelector("input:invalid")?.focus();
|
|
415
|
+
return Array.from(inputs).every((input) => input.checkValidity());
|
|
416
|
+
}
|
|
417
|
+
function toggleFormGlobalError(bool) {
|
|
418
|
+
form.toggleAttribute("data-global-error", bool);
|
|
419
|
+
form.querySelectorAll(".t007-input-field").forEach((field2) => {
|
|
420
|
+
field2.querySelector(".t007-input")?.toggleAttribute("data-error", bool);
|
|
421
|
+
if (bool) field2.querySelector(".t007-input-floating-label")?.classList.add("t007-input-shake");
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var { field, handleFormValidation } = formManager;
|
|
427
|
+
if (typeof window !== "undefined") {
|
|
428
|
+
t007.FM = formManager;
|
|
429
|
+
t007.field = field;
|
|
430
|
+
t007.handleFormValidation = handleFormValidation;
|
|
431
|
+
window.field ??= t007.field;
|
|
432
|
+
window.handleFormValidation ??= t007.handleFormValidation;
|
|
433
|
+
console.log("%cT007 Input helpers attached to window!", "color: darkturquoise");
|
|
434
|
+
loadResource(T007_INPUT_CSS_SRC);
|
|
435
|
+
t007.FM.init();
|
|
436
|
+
}
|
|
437
|
+
export {
|
|
438
|
+
field,
|
|
439
|
+
formManager,
|
|
440
|
+
handleFormValidation
|
|
441
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t007/input",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "A lightweight, pure JS input system.",
|
|
5
5
|
"author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"type": "module",
|
|
17
17
|
"main": "./dist/index.js",
|
|
18
18
|
"module": "./dist/index.js",
|
|
19
|
-
"
|
|
19
|
+
"unpkg": "./dist/index.global.js",
|
|
20
|
+
"jsdelivr": "./dist/index.global.js",
|
|
20
21
|
"types": "./src/ts/types/index.d.ts",
|
|
21
22
|
"style": "./src/css/index.css",
|
|
22
23
|
"sideEffects": [
|
|
@@ -26,17 +27,14 @@
|
|
|
26
27
|
".": {
|
|
27
28
|
"types": "./src/ts/types/index.d.ts",
|
|
28
29
|
"import": "./dist/index.js",
|
|
29
|
-
"default": "./dist/index.
|
|
30
|
+
"default": "./dist/index.js"
|
|
30
31
|
},
|
|
32
|
+
"./standalone": "./dist/standalone.js",
|
|
33
|
+
"./global": "./dist/index.global.js",
|
|
31
34
|
"./style.css": "./src/css/index.css"
|
|
32
35
|
},
|
|
33
36
|
"scripts": {
|
|
34
|
-
"build": "tsup
|
|
35
|
-
},
|
|
36
|
-
"tsup": {
|
|
37
|
-
"noExternal": [
|
|
38
|
-
"@t007/utils"
|
|
39
|
-
]
|
|
37
|
+
"build": "tsup --config ../../tsup.config.ts"
|
|
40
38
|
},
|
|
41
39
|
"files": [
|
|
42
40
|
"dist",
|
package/src/ts/types/index.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface FieldOptions extends Partial<
|
|
|
27
27
|
passwordHiddenIcon?: string;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export interface
|
|
30
|
+
export interface FormManager {
|
|
31
31
|
forms: HTMLCollectionOf<HTMLFormElement>;
|
|
32
32
|
violationKeys: string[];
|
|
33
33
|
init(): void;
|
|
@@ -47,15 +47,15 @@ export interface T007FormManager {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// BUNDLE EXPORTS & GLOBAL DECLARATIONS
|
|
50
|
-
export const
|
|
51
|
-
export const field =
|
|
52
|
-
export const handleFormValidation =
|
|
50
|
+
export const formManager: FormManager;
|
|
51
|
+
export const field = FormManager["field"];
|
|
52
|
+
export const handleFormValidation = FormManager["handleFormValidation"];
|
|
53
53
|
|
|
54
54
|
declare global {
|
|
55
55
|
interface T007Namespace {
|
|
56
|
-
FM:
|
|
57
|
-
field?:
|
|
58
|
-
handleFormValidation?:
|
|
56
|
+
FM: FormManager;
|
|
57
|
+
field?: FormManager["field"];
|
|
58
|
+
handleFormValidation?: FormManager["handleFormValidation"];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
interface Window {
|