@t007/input 0.0.23 → 0.0.25

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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  (() => {
3
- // ../../node_modules/sia-reactor/dist/chunk-RVYL3OLW.js
3
+ // ../../../sia-reactor/dist/chunk-RI45W4O6.js
4
4
  function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
5
5
  return assignEl(el, props, dataset, styles), el;
6
6
  }
@@ -17,7 +17,21 @@
17
17
  }
18
18
  }
19
19
 
20
- // ../utils/dist/index.js
20
+ // ../../../sia-reactor/dist/chunk-EZ4VRGYI.js
21
+ var CTX = {
22
+ /** Flag indicating whether the application is running in development mode. */
23
+ isDevEnv: "undefined" !== typeof process ? process.env.NODE_ENV !== "production" : true,
24
+ /** Flag indicating whether a cascade is currently ongoing so reactors can allow all writes. */
25
+ isCascading: false,
26
+ /** Active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
27
+ autotracker: null
28
+ };
29
+ var RTR_BATCH = "undefined" !== typeof window ? ("undefined" !== typeof queueMicrotask ? queueMicrotask : setTimeout).bind(window) : "undefined" !== typeof process && process.nextTick ? process.nextTick : setTimeout;
30
+ var RTR_LOG = console.log.bind(console, "[S.I.A Reactor]");
31
+ var NIL = Object.freeze({});
32
+
33
+ // ../utils/dist/chunk-N5KX6IW4.js
34
+ var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
21
35
  var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
22
36
  function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
23
37
  w.t007 ??= {}, w.t007._resourceCache ??= {};
@@ -64,10 +78,29 @@
64
78
  return src1.replace(/\\/g, "/").split("?")[0].trim() === src2.replace(/\\/g, "/").split("?")[0].trim();
65
79
  }
66
80
  }
67
- function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "tmg-video-controls-scroll-assist", vertical = true, horizontal = true } = {}) {
68
- t007._scrollers ??= /* @__PURE__ */ new WeakMap();
69
- t007._scroller_r_observer ??= new ResizeObserver((entries) => entries.forEach(({ target }) => t007._scrollers.get(target)?.update()));
70
- t007._scroller_m_observer ??= new MutationObserver((entries) => {
81
+ function formatSize(bytes, decimals = 3, base = 1e3) {
82
+ if (bytes < base) return `${bytes} byte${bytes == 1 ? "" : "s"}`;
83
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(base)), units.length - 1);
84
+ return `${(bytes / Math.pow(base, exponent)).toFixed(decimals).replace(/\.0+$/, "")} ${units[exponent]}`;
85
+ }
86
+ if ("undefined" !== typeof window) {
87
+ (window.t007 ??= {}).VIRTUAL_RESOURCE = VIRTUAL_RESOURCE;
88
+ window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
89
+ window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
90
+ window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
91
+ window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/index.min.css`;
92
+ window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/dist/index.min.css`;
93
+ window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/index.min.css`;
94
+ }
95
+
96
+ // ../utils/dist/hooks/vanilla.js
97
+ function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "t007-scroll-assist", vertical = true, horizontal = true } = NIL) {
98
+ const parent = el?.parentElement, existing = (t007._scrollers ??= /* @__PURE__ */ new WeakMap()).get(el);
99
+ if (!parent || existing) return existing ? existing : void 0;
100
+ t007._scrollers_r_observer ??= new ResizeObserver((entries) => {
101
+ for (const { target } of entries) t007._scrollers.get(target)?.update();
102
+ });
103
+ t007._scrollers_m_observer ??= new MutationObserver((entries) => {
71
104
  const els = /* @__PURE__ */ new Set();
72
105
  for (const entry of entries) {
73
106
  let node = entry.target instanceof Element ? entry.target : null;
@@ -76,12 +109,10 @@
76
109
  }
77
110
  for (const el2 of els) t007._scrollers.get(el2)?.update();
78
111
  });
79
- const parent = el?.parentElement;
80
- if (!parent || t007._scrollers.has(el)) return;
81
112
  const assist = {};
82
113
  let scrollId = null, last = performance.now(), assistWidth = 20, assistHeight = 20;
83
114
  const update = () => {
84
- const hasInteractive = !!parent.querySelector('button, a[href], input, select, textarea, [contenteditable="true"], [tabindex]:not([tabindex="-1"])');
115
+ const hasInteractive = !!parent.querySelector(INTERACTIVE_SELECTOR);
85
116
  if (horizontal) {
86
117
  const w = assist.left?.offsetWidth || assistWidth, check = hasInteractive ? el.clientWidth < w * 2 : false;
87
118
  assist.left.style.display = check ? "none" : el.scrollLeft > 0 ? "block" : "none";
@@ -113,93 +144,92 @@
113
144
  const addAssist = (dir) => {
114
145
  const div = createEl("div", { className: assistClassName }, { scrollDirection: dir }, { display: "none" });
115
146
  if (!div) return;
116
- ["pointerenter", "dragenter"].forEach((evt) => div.addEventListener(evt, () => scroll(dir)));
117
- ["pointerleave", "pointerup", "pointercancel", "dragleave", "dragend"].forEach((evt) => div.addEventListener(evt, stop));
147
+ for (const evt of ["pointerenter", "dragenter"]) div.addEventListener(evt, () => scroll(dir));
148
+ for (const evt of ["pointerleave", "pointerup", "pointercancel", "dragleave", "dragend"]) div.addEventListener(evt, stop);
118
149
  dir === "left" || dir === "up" ? parent.insertBefore(div, el) : parent.append(div);
119
150
  assist[dir] = div;
120
151
  };
121
- if (horizontal) ["left", "right"].forEach(addAssist);
122
- if (vertical) ["up", "down"].forEach(addAssist);
123
- el.addEventListener("scroll", update);
124
- t007._scroller_r_observer.observe(el);
125
- t007._scroller_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
126
- t007._scrollers.set(el, {
152
+ if (horizontal) for (const dir of ["left", "right"]) addAssist(dir);
153
+ if (vertical) for (const dir of ["up", "down"]) addAssist(dir);
154
+ const handle = {
127
155
  update,
128
156
  destroy() {
129
- stop();
130
- el.removeEventListener("scroll", update);
131
- t007._scroller_r_observer.unobserve(el);
132
- t007._scrollers.delete(el);
133
- Object.values(assist).forEach((a) => a.remove());
157
+ stop(), el.removeEventListener("scroll", update);
158
+ t007._scrollers_r_observer.unobserve(el), t007._scrollers.delete(el);
159
+ for (const a of Object.values(assist)) a.remove();
134
160
  }
135
- });
136
- return update(), t007._scrollers.get(el);
161
+ };
162
+ update(), el.addEventListener("scroll", update);
163
+ t007._scrollers_r_observer.observe(el), t007._scrollers_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
164
+ return t007._scrollers.set(el, handle), handle;
137
165
  }
138
- if ("undefined" !== typeof window) {
139
- window.t007 ??= {};
140
- t007.VIRTUAL_RESOURCE = VIRTUAL_RESOURCE;
141
- window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
142
- window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
143
- window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
144
- window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/index.min.css`;
145
- window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/dist/index.min.css`;
146
- window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/index.min.css`;
166
+
167
+ // src/ts/utils/consts.ts
168
+ var violationKeys = ["valueMissing", "typeMismatch", "patternMismatch", "stepMismatch", "tooShort", "tooLong", "rangeUnderflow", "rangeOverflow", "badInput", "customError"];
169
+ var dateTypes = ["date", "time", "datetime-local", "month"];
170
+ var nativeIconTypes = [...dateTypes];
171
+
172
+ // src/ts/utils/fn.ts
173
+ function getStrengthLevel(value, minLength = 0) {
174
+ value = value.trim();
175
+ let level = 0;
176
+ if (value.length < minLength) level = 1;
177
+ else {
178
+ if (/[a-z]/.test(value)) level++;
179
+ if (/[A-Z]/.test(value)) level++;
180
+ if (/[0-9]/.test(value)) level++;
181
+ if (/[\W_]/.test(value)) level++;
182
+ }
183
+ return Math.min(level, 4);
184
+ }
185
+ function getFilesHelper(files, opts) {
186
+ if (!files || !files.length) return { violation: null, message: "" };
187
+ const totalFiles = files.length;
188
+ let totalSize = 0, currFiles = 0;
189
+ const setMaxError = (size, max, n = 0) => ({ violation: "rangeOverflow", message: n ? `File ${files.length > 1 ? n : ""} size of ${formatSize(size)} exceeds the per file maximum of ${formatSize(max)}` : `Total files size of ${formatSize(size)} exceeds the total maximum of ${formatSize(max)}` });
190
+ const setMinError = (size, min, n = 0) => ({ violation: "rangeUnderflow", message: n ? `File ${files.length > 1 ? n : ""} size of ${formatSize(size)} is less than the per file minimum of ${formatSize(min)}` : `Total files size of ${formatSize(size)} is less than the total minimum of ${formatSize(min)}` });
191
+ for (const file of files) {
192
+ currFiles++;
193
+ totalSize += file.size;
194
+ if (opts.accept) {
195
+ const acceptedTypes = opts.accept.split(",").map((type) => type.trim().replace(/^[*\.]+|[*\.]+$/g, "")).filter(Boolean) || [];
196
+ if (!acceptedTypes.some((type) => file.type.includes(type))) return { violation: "typeMismatch", message: `File${currFiles > 1 ? currFiles : ""} type of '${file.type}' is not accepted.` };
197
+ }
198
+ if (opts.maxSize && file.size > opts.maxSize) return setMaxError(file.size, opts.maxSize, currFiles);
199
+ if (opts.minSize && file.size < opts.minSize) return setMinError(file.size, opts.minSize, currFiles);
200
+ if (opts.multiple) {
201
+ if (opts.maxTotalSize && totalSize > opts.maxTotalSize) return setMaxError(totalSize, opts.maxTotalSize);
202
+ if (opts.minTotalSize && totalSize < opts.minTotalSize) return setMinError(totalSize, opts.minTotalSize);
203
+ 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"}` };
204
+ 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"}` };
205
+ }
206
+ }
207
+ return { violation: null, message: "" };
147
208
  }
148
209
 
149
- // src/index.js
210
+ // src/js/index.js
150
211
  var formManager = {
151
212
  forms: document.getElementsByClassName("t007-input-form"),
152
- violationKeys: ["valueMissing", "typeMismatch", "patternMismatch", "stepMismatch", "tooShort", "tooLong", "rangeUnderflow", "rangeOverflow", "badInput", "customError"],
213
+ violationKeys,
153
214
  init() {
154
- t007.FM.observeDOMForFields();
155
- Array.from(t007.FM.forms).forEach(t007.FM.handleFormValidation);
215
+ t007.FM.observeDOMForFields(), Array.prototype.forEach.call(t007.FM.forms, t007.FM.handleFormValidation);
156
216
  },
157
217
  observeDOMForFields() {
158
218
  new MutationObserver((mutations) => {
159
- for (const mutation of mutations) {
219
+ for (const mutation of mutations)
160
220
  for (const node of mutation.addedNodes) {
161
- if (!node.tagName || !(node?.classList?.contains("t007-input-field") || node?.querySelector?.(".t007-input-field"))) continue;
221
+ if (!node.tagName || !(node.classList.contains("t007-input-field") || node.querySelector(".t007-input-field"))) continue;
162
222
  for (const field2 of [...node.querySelector(".t007-input-field") ? node.querySelectorAll(".t007-input-field") : [node]]) t007.FM.setUpField(field2);
163
223
  }
164
- }
165
224
  }).observe(document.body, { childList: true, subtree: true });
166
225
  },
167
- getFilesHelper(files, opts) {
168
- if (!files || !files.length) return { violation: null, message: "" };
169
- const totalFiles = files.length;
170
- let totalSize = 0;
171
- let currFiles = 0;
172
- 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)}` });
173
- 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)}` });
174
- for (const file of files) {
175
- currFiles++;
176
- totalSize += file.size;
177
- if (opts.accept) {
178
- const acceptedTypes = opts.accept.split(",").map((type) => type.trim().replace(/^[*\.]+|[*\.]+$/g, "")).filter(Boolean) || [];
179
- if (!acceptedTypes.some((type) => file.type.includes(type))) return { violation: "typeMismatch", message: `File${currFiles > 1 ? currFiles : ""} type of '${file.type}' is not accepted.` };
180
- }
181
- if (opts.maxSize && file.size > opts.maxSize) return setMaxError(file.size, opts.maxSize, currFiles);
182
- if (opts.minSize && file.size < opts.minSize) return setMinError(file.size, opts.minSize, currFiles);
183
- if (opts.multiple) {
184
- if (opts.maxTotalSize && totalSize > opts.maxTotalSize) return setMaxError(totalSize, opts.maxTotalSize);
185
- if (opts.minTotalSize && totalSize < opts.minTotalSize) return setMinError(totalSize, opts.minTotalSize);
186
- 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"}` };
187
- 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"}` };
188
- }
189
- }
190
- return { violation: null, message: "" };
191
- },
192
- formatSize(size, decimals = 3, base = 1e3) {
193
- if (size < base) return `${size} byte${size == 1 ? "" : "s"}`;
194
- 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);
195
- return `${(size / Math.pow(base, exponent)).toFixed(decimals).replace(/\.0+$/, "")} ${units[exponent]}`;
196
- },
226
+ getFilesHelper: (files, opts) => getFilesHelper(files, opts),
227
+ formatSize: (size, decimals = 3, base = 1e3) => formatSize(size, decimals, base),
197
228
  togglePasswordType: (input) => input.type = input.type === "password" ? "text" : "password",
198
229
  toggleFilled: (input) => input?.toggleAttribute("data-filled", input.type === "checkbox" || input.type === "radio" ? input.checked : input.value !== "" || input.files?.length > 0),
199
230
  setFallbackHelper(field2) {
200
231
  const helperTextWrapper = field2?.querySelector(".t007-input-helper-text-wrapper");
201
- if (!helperTextWrapper || helperTextWrapper.querySelector(".t007-input-helper-text[data-violation='auto']")) return;
202
- helperTextWrapper.append(createEl("p", { className: "t007-input-helper-text" }, { violation: "auto" }));
232
+ !helperTextWrapper?.querySelector(".t007-input-helper-text[data-violation='auto']") && helperTextWrapper?.append(createEl("p", { className: "t007-input-helper-text" }, { violation: "auto" }));
203
233
  },
204
234
  setFieldListeners(field2) {
205
235
  if (!field2) return;
@@ -207,36 +237,22 @@
207
237
  if (input.type === "file")
208
238
  input.addEventListener("input", async () => {
209
239
  const file = input.files?.[0], img = new Image();
210
- img.onload = () => {
211
- input.style.setProperty("--t007-input-image-src", `url(${src})`);
212
- input.classList.add("t007-input-image-selected");
213
- setTimeout(() => URL.revokeObjectURL(src), 1e3);
214
- };
215
- img.onerror = () => {
216
- input.style.removeProperty("--t007-input-image-src");
217
- input.classList.remove("t007-input-image-selected");
218
- URL.revokeObjectURL(src);
219
- };
240
+ img.onload = () => (input.style.setProperty("--t007-input-image-src", `url(${src})`), input.classList.add("t007-input-image-selected"), setTimeout(() => URL.revokeObjectURL(src), 1e3));
241
+ img.onerror = () => (input.style.removeProperty("--t007-input-image-src"), input.classList.remove("t007-input-image-selected"), URL.revokeObjectURL(src));
220
242
  let src;
221
243
  if (file?.type?.startsWith("image")) src = URL.createObjectURL(file);
222
- else if (file?.type?.startsWith("video")) {
244
+ else if (file?.type?.startsWith("video"))
223
245
  src = await new Promise((resolve) => {
224
246
  let video = createEl("video"), canvas = createEl("canvas"), context = canvas.getContext("2d");
225
247
  video.ontimeupdate = () => {
226
248
  context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
227
- canvas.toBlob((blob) => resolve(URL.createObjectURL(blob)));
228
- URL.revokeObjectURL(video.src);
249
+ canvas.toBlob((blob) => resolve(URL.createObjectURL(blob))), URL.revokeObjectURL(video.src);
229
250
  video = video.src = video.onloadedmetadata = video.ontimeupdate = null;
230
251
  };
231
252
  video.onloadeddata = () => video.currentTime = 3;
232
253
  video.src = URL.createObjectURL(file);
233
254
  });
234
- }
235
- if (!src) {
236
- input.style.removeProperty("--t007-input-image-src");
237
- input.classList.remove("t007-input-image-selected");
238
- return;
239
- }
255
+ if (!src) return input.style.removeProperty("--t007-input-image-src"), input.classList.remove("t007-input-image-selected");
240
256
  img.src = src;
241
257
  });
242
258
  if (floatingLabel) floatingLabel.ontransitionend = () => floatingLabel.classList.remove("t007-input-shake");
@@ -245,9 +261,7 @@
245
261
  },
246
262
  setUpField(field2) {
247
263
  if (field2.dataset.setUp) return;
248
- t007.FM.toggleFilled(field2.querySelector(".t007-input"));
249
- t007.FM.setFallbackHelper(field2);
250
- t007.FM.setFieldListeners(field2);
264
+ t007.FM.toggleFilled(field2.querySelector(".t007-input")), t007.FM.setFallbackHelper(field2), t007.FM.setFieldListeners(field2);
251
265
  field2.dataset.setUp = "true";
252
266
  },
253
267
  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 }) {
@@ -281,19 +295,18 @@
281
295
  if (maxTotalSize) inputEl.setAttribute("maxtotalsize", maxTotalSize);
282
296
  Object.keys(otherProps).forEach((key) => inputEl[key] = otherProps[key]);
283
297
  labelEl.append(!isWrapper ? inputEl : children);
284
- const nativeTypes = ["date", "time", "month", "datetime-local"];
285
- if (nativeTypes.includes(type) && nativeIcon) labelEl.append(createEl("i", { className: "t007-input-icon t007-input-native-icon", innerHTML: nativeIcon }));
298
+ if (nativeIconTypes.includes(type) && nativeIcon) labelEl.append(createEl("i", { className: "t007-input-icon t007-input-native-icon", innerHTML: nativeIcon }));
286
299
  else if (endIcon) labelEl.append(createEl("i", { className: "t007-input-icon", innerHTML: endIcon }));
287
- if (type === "password" && eyeToggler) {
288
- 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>` }));
289
- 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>` }));
290
- }
300
+ if (type === "password" && eyeToggler)
301
+ labelEl.append(
302
+ 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>` }),
303
+ 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>` })
304
+ );
291
305
  if (helperText !== false) {
292
306
  const helperLine = createEl("div", { className: "t007-input-helper-line" }), helperWrapper = createEl("div", { className: "t007-input-helper-text-wrapper", tabIndex: "-1" });
293
307
  if (helperText.info) helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText.info }, { violation: "none" }));
294
- t007.FM?.violationKeys?.forEach((key) => helperText[key] && helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText[key] }, { violation: key })));
295
- helperLine.append(helperWrapper);
296
- field2.append(helperLine);
308
+ t007.FM.violationKeys?.forEach((key) => helperText[key] && helperWrapper.append(createEl("p", { className: "t007-input-helper-text", textContent: helperText[key] }, { violation: key })));
309
+ helperLine.append(helperWrapper), field2.append(helperLine);
297
310
  }
298
311
  if (passwordMeter && type === "password") {
299
312
  const meter = createEl("div", { className: "t007-input-password-meter" }, { strengthLevel: "1" });
@@ -315,36 +328,26 @@
315
328
  form.validateOnClient = validateFormOnClient;
316
329
  form.toggleGlobalError = toggleFormGlobalError;
317
330
  const fields = form.getElementsByClassName("t007-input-field"), inputs = form.getElementsByClassName("t007-input");
318
- Array.from(fields).forEach(t007.FM.setUpField);
319
- form.addEventListener("input", ({ target }) => {
320
- t007.FM.toggleFilled(target);
321
- validateInput(target);
322
- });
331
+ Array.prototype.forEach.call(fields, t007.FM.setUpField);
332
+ form.addEventListener("input", ({ target }) => (t007.FM.toggleFilled(target), validateInput(target)));
323
333
  form.addEventListener("focusout", ({ target }) => validateInput(target, true));
324
334
  form.addEventListener("submit", async (e) => {
325
- toggleSubmitLoader(true);
335
+ form.classList.toggle("t007-input-submit-loading", true);
326
336
  try {
327
337
  e.preventDefault();
328
338
  if (!validateFormOnClient()) return;
329
- if (form.validateOnServer && !await form.validateOnServer()) {
330
- toggleFormGlobalError(true);
331
- form.addEventListener("input", () => toggleFormGlobalError(false), { once: true, useCapture: true });
332
- return;
333
- }
334
- form.onSubmit ? form.onSubmit() : form.submit();
339
+ if (form.validateOnServer && !await form.validateOnServer()) return toggleFormGlobalError(true), form.addEventListener("input", () => toggleFormGlobalError(false), { once: true, useCapture: true });
340
+ form.onSubmit ? form.onSubmit(e) : form.submit();
335
341
  } catch (error) {
336
342
  console.error(error);
337
343
  }
338
- toggleSubmitLoader(false);
344
+ form.classList.toggle("t007-input-submit-loading", false);
339
345
  });
340
- function toggleSubmitLoader(bool) {
341
- form.classList.toggle("t007-input-submit-loading", bool);
342
- }
343
346
  function toggleError(input, bool, flag = false) {
344
347
  const field2 = input.closest(".t007-input-field"), floatingLabel = field2.querySelector(".t007-input-floating-label");
345
348
  if (bool && flag) {
346
349
  input.setAttribute("data-error", "");
347
- floatingLabel?.classList.add("t007-input-shake");
350
+ floatingLabel?.classList.add("t007-input-shake"), setTimeout(() => floatingLabel?.classList.remove("t007-input-shake"), 520);
348
351
  } else if (!bool) input.removeAttribute("data-error");
349
352
  toggleHelper(input, input.hasAttribute("data-error"));
350
353
  }
@@ -352,28 +355,11 @@
352
355
  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"]`);
353
356
  input.closest(".t007-input-field").querySelectorAll(`.t007-input-helper-text:not([data-violation="${violation}"])`).forEach((helper2) => helper2?.classList.remove("t007-input-show"));
354
357
  if (helper) helper.classList.toggle("t007-input-show", bool);
355
- else if (fallbackHelper) {
356
- fallbackHelper.textContent = input.validationMessage;
357
- fallbackHelper.classList.toggle("t007-input-show", bool);
358
- }
359
- }
360
- function forceRevalidate(input) {
361
- input.checkValidity();
362
- input.dispatchEvent(new Event("input"));
358
+ else if (fallbackHelper) fallbackHelper.textContent = input.validationMessage, fallbackHelper.classList.toggle("t007-input-show", bool);
363
359
  }
364
360
  function updatePasswordMeter(input) {
365
361
  const passwordMeter = input.closest(".t007-input-field").querySelector(".t007-input-password-meter");
366
- if (!passwordMeter) return;
367
- const value = input.value?.trim();
368
- let strengthLevel = 0;
369
- if (value.length < Number(input.minLength ?? 0)) strengthLevel = 1;
370
- else {
371
- if (/[a-z]/.test(value)) strengthLevel++;
372
- if (/[A-Z]/.test(value)) strengthLevel++;
373
- if (/[0-9]/.test(value)) strengthLevel++;
374
- if (/[\W_]/.test(value)) strengthLevel++;
375
- }
376
- passwordMeter.dataset.strengthLevel = strengthLevel;
362
+ if (passwordMeter) passwordMeter.dataset.strengthLevel = `${getStrengthLevel(input.value, Number(input.minLength ?? 0))}`;
377
363
  }
378
364
  function validateInput(input, flag = false) {
379
365
  if (form.dataset.globalError || !input?.classList.contains("t007-input")) return;
@@ -383,7 +369,7 @@
383
369
  case "password":
384
370
  value = input.value?.trim();
385
371
  if (value === "") break;
386
- const confirmPasswordInput = Array.from(inputs).find((input2) => (input2.custom ?? input2.getAttribute("custom")) === "confirm-password");
372
+ const confirmPasswordInput = Array.prototype.find.call(inputs, (input2) => (input2.custom ?? input2.getAttribute("custom")) === "confirm-password");
387
373
  if (!confirmPasswordInput) break;
388
374
  const confirmPasswordValue = confirmPasswordInput.value?.trim();
389
375
  confirmPasswordInput.setCustomValidity(value !== confirmPasswordValue ? "Both passwords do not match" : "");
@@ -392,7 +378,7 @@
392
378
  case "confirm_password":
393
379
  value = input.value?.trim();
394
380
  if (value === "") break;
395
- const passwordInput = Array.from(inputs).find((input2) => (input2.custom ?? input2.getAttribute("custom")) === "password");
381
+ const passwordInput = Array.prototype.find.call(inputs, (input2) => (input2.custom ?? input2.getAttribute("custom")) === "password");
396
382
  if (!passwordInput) break;
397
383
  const passwordValue = passwordInput.value?.trim();
398
384
  errorBool = value !== passwordValue;
@@ -401,21 +387,17 @@
401
387
  case "onward_date":
402
388
  if (input.min) break;
403
389
  input.min = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
404
- forceRevalidate(input);
390
+ input.checkValidity(), input.dispatchEvent(new Event("input"));
391
+ break;
392
+ case "past_date":
393
+ if (input.max) break;
394
+ input.max = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
395
+ input.checkValidity(), input.dispatchEvent(new Event("input"));
405
396
  break;
406
397
  }
407
398
  if (input.type === "file") {
408
399
  input.Validity = {};
409
- const { violation, message } = t007.FM.getFilesHelper(input.files ?? [], {
410
- accept: input.accept,
411
- multiple: input.multiple,
412
- maxSize: input.maxSize ?? Number(input.getAttribute("maxsize")),
413
- minSize: input.minSize ?? Number(input.getAttribute("minsize")),
414
- maxTotalSize: input.maxTotalSize ?? Number(input.getAttribute("maxtotalsize")),
415
- minTotalSize: input.minTotalSize ?? Number(input.getAttribute("mintotalsize")),
416
- maxLength: input.maxLength ?? Number(input.getAttribute("maxlength")),
417
- minLength: input.minLength ?? Number(input.getAttribute("minLength"))
418
- });
400
+ const { violation, message } = t007.FM.getFilesHelper(input.files ?? [], { accept: input.accept, multiple: input.multiple, maxSize: input.maxSize ?? Number(input.getAttribute("maxsize")), minSize: input.minSize ?? Number(input.getAttribute("minsize")), maxTotalSize: input.maxTotalSize ?? Number(input.getAttribute("maxtotalsize")), minTotalSize: input.minTotalSize ?? Number(input.getAttribute("mintotalsize")), maxLength: input.maxLength ?? Number(input.getAttribute("maxlength")), minLength: input.minLength ?? Number(input.getAttribute("minLength")) });
419
401
  errorBool = !!message;
420
402
  input.setCustomValidity(message);
421
403
  if (violation) input.Validity[violation] = true;
@@ -424,18 +406,22 @@
424
406
  toggleError(input, errorBool, flag);
425
407
  if (errorBool) return;
426
408
  if (input.type === "radio")
427
- Array.from(inputs)?.filter((i) => i.name == input.name)?.forEach((radio) => toggleError(radio, errorBool, flag));
409
+ Array.prototype.forEach.call(
410
+ Array.prototype.filter.call(inputs, (i) => i.name == input.name),
411
+ (radio) => toggleError(radio, errorBool, flag)
412
+ );
428
413
  }
429
414
  function validateFormOnClient() {
430
- Array.from(inputs).forEach((input) => validateInput(input, true));
415
+ Array.prototype.forEach.call(inputs, (input) => validateInput(input, true));
431
416
  form.querySelector("input:invalid")?.focus();
432
- return Array.from(inputs).every((input) => input.checkValidity());
417
+ return Array.prototype.every.call(inputs, (input) => input.checkValidity());
433
418
  }
434
419
  function toggleFormGlobalError(bool) {
435
420
  form.toggleAttribute("data-global-error", bool);
436
421
  form.querySelectorAll(".t007-input-field").forEach((field2) => {
437
422
  field2.querySelector(".t007-input")?.toggleAttribute("data-error", bool);
438
- if (bool) field2.querySelector(".t007-input-floating-label")?.classList.add("t007-input-shake");
423
+ const floatingLabel = field2.querySelector(".t007-input-floating-label");
424
+ floatingLabel?.classList.toggle("t007-input-shake", bool), bool && setTimeout(() => floatingLabel?.classList.remove("t007-input-shake"), 520);
439
425
  });
440
426
  }
441
427
  }