@fivelab/web-utils 1.0.3 → 1.0.5
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/behaviors/confirm.d.ts +0 -2
- package/dist/behaviors/confirm.js +2 -3
- package/dist/behaviors/confirm.js.map +1 -1
- package/dist/behaviors/copy.d.ts +0 -2
- package/dist/behaviors/copy.js +2 -3
- package/dist/behaviors/copy.js.map +1 -1
- package/dist/behaviors/index.d.ts +1 -0
- package/dist/behaviors/index.js +4 -3
- package/dist/behaviors/index.js.map +1 -1
- package/dist/behaviors/processing.d.ts +0 -2
- package/dist/behaviors/processing.js +4 -5
- package/dist/behaviors/processing.js.map +1 -1
- package/dist/behaviors/textarea-auto-resize.d.ts +2 -0
- package/dist/behaviors/textarea-auto-resize.js +10 -0
- package/dist/behaviors/textarea-auto-resize.js.map +1 -0
- package/dist/browser/file.d.ts +1 -0
- package/dist/browser/file.js +11 -0
- package/dist/browser/file.js.map +1 -0
- package/dist/browser/index.d.ts +3 -1
- package/dist/browser/index.js +3 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/visibility.d.ts +6 -0
- package/dist/browser/visibility.js +28 -0
- package/dist/browser/visibility.js.map +1 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.js +47 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/constants.d.ts +7 -0
- package/dist/core/constants.js +10 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/observable.d.ts +5 -0
- package/dist/core/observable.js +17 -0
- package/dist/core/observable.js.map +1 -0
- package/dist/core/path.d.ts +1 -0
- package/dist/core/path.js +11 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/time.d.ts +7 -0
- package/dist/core/time.js +22 -0
- package/dist/core/time.js.map +1 -0
- package/dist/dom/changes.d.ts +1 -1
- package/dist/dom/changes.js.map +1 -1
- package/dist/dom/events.js.map +1 -1
- package/dist/dom/form.d.ts +15 -0
- package/dist/dom/form.js +138 -0
- package/dist/dom/form.js.map +1 -0
- package/dist/dom/html.d.ts +4 -0
- package/dist/dom/html.js +39 -0
- package/dist/dom/html.js.map +1 -0
- package/dist/dom/index.d.ts +4 -0
- package/dist/dom/index.js +4 -0
- package/dist/dom/index.js.map +1 -1
- package/dist/dom/text.d.ts +6 -0
- package/dist/dom/text.js +40 -0
- package/dist/dom/text.js.map +1 -0
- package/dist/dom/textarea.d.ts +1 -0
- package/dist/dom/textarea.js +17 -0
- package/dist/dom/textarea.js.map +1 -0
- package/package.json +49 -10
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { navigateTo } from '../browser/navigation.js';
|
|
2
|
+
import { kAttrHref, kAttrConfirm } from '../core/constants.js';
|
|
2
3
|
|
|
3
|
-
const kAttrHref = 'data-href';
|
|
4
|
-
const kAttrConfirm = 'data-confirm';
|
|
5
4
|
const confirmBehavior = (element, event) => {
|
|
6
5
|
event.preventDefault();
|
|
7
6
|
const href = element.getAttribute(kAttrHref);
|
|
@@ -14,5 +13,5 @@ const confirmBehavior = (element, event) => {
|
|
|
14
13
|
}
|
|
15
14
|
};
|
|
16
15
|
|
|
17
|
-
export { confirmBehavior
|
|
16
|
+
export { confirmBehavior };
|
|
18
17
|
//# sourceMappingURL=confirm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm.js","sources":["../../src/behaviors/confirm.ts"],"sourcesContent":["import { navigateTo } from '../browser/navigation';\nimport { DomEventCallback } from '../dom';\
|
|
1
|
+
{"version":3,"file":"confirm.js","sources":["../../src/behaviors/confirm.ts"],"sourcesContent":["import { navigateTo } from '../browser/navigation';\nimport { DomEventCallback } from '../dom';\nimport { kAttrConfirm, kAttrHref } from '../core/constants';\n\nexport const confirmBehavior: DomEventCallback<HTMLElement> = (element: HTMLElement, event: Event): void => {\n event.preventDefault();\n\n const href = element.getAttribute(kAttrHref);\n const message = element.getAttribute(kAttrConfirm) || 'Are you sure want?';\n\n if (!href) {\n throw new Error(`Can't process data confirm. Missed \"${kAttrHref}\" attribute.`);\n }\n\n if (confirm(message)) {\n navigateTo(href);\n }\n};\n"],"names":[],"mappings":";;;MAIa,eAAe,GAAkC,CAAC,OAAoB,EAAE,KAAY,KAAU;IACvG,KAAK,CAAC,cAAc,EAAE;IAEtB,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,oBAAoB;IAE1E,IAAI,CAAC,IAAI,EAAE;AACP,QAAA,MAAM,IAAI,KAAK,CAAC,uCAAuC,SAAS,CAAA,YAAA,CAAc,CAAC;IACnF;AAEA,IAAA,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAClB,UAAU,CAAC,IAAI,CAAC;IACpB;AACJ;;;;"}
|
package/dist/behaviors/copy.d.ts
CHANGED
|
@@ -2,6 +2,4 @@ import { DomEventCallback } from '../dom';
|
|
|
2
2
|
export type CopyBehaviorOptions = {
|
|
3
3
|
success?: (text: string, element: HTMLElement) => void;
|
|
4
4
|
};
|
|
5
|
-
export declare const kAttrCopy = "data-copy";
|
|
6
|
-
export declare const kAttrMessage = "data-copy-message";
|
|
7
5
|
export declare const createCopyBehavior: (options?: CopyBehaviorOptions) => DomEventCallback<HTMLElement>;
|
package/dist/behaviors/copy.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { kAttrCopy, kAttrMessage } from '../core/constants.js';
|
|
1
2
|
import { readStringAttribute } from '../dom/attributes.js';
|
|
2
3
|
import { copyToClipboard } from '../browser/clipboard.js';
|
|
3
4
|
|
|
4
|
-
const kAttrCopy = 'data-copy';
|
|
5
|
-
const kAttrMessage = 'data-copy-message';
|
|
6
5
|
const copyBehavior = async (element, event) => {
|
|
7
6
|
if (element.nodeName.toLowerCase() === 'a' && element.getAttribute('href') === '#') {
|
|
8
7
|
event.preventDefault();
|
|
@@ -18,5 +17,5 @@ const createCopyBehavior = (options) => {
|
|
|
18
17
|
};
|
|
19
18
|
};
|
|
20
19
|
|
|
21
|
-
export { createCopyBehavior
|
|
20
|
+
export { createCopyBehavior };
|
|
22
21
|
//# sourceMappingURL=copy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy.js","sources":["../../src/behaviors/copy.ts"],"sourcesContent":["import { copyToClipboard } from '../browser';\nimport { DomEventCallback, readStringAttribute } from '../dom';\n\nexport type CopyBehaviorOptions = {\n success?: (text: string, element: HTMLElement) => void;\n};\n\
|
|
1
|
+
{"version":3,"file":"copy.js","sources":["../../src/behaviors/copy.ts"],"sourcesContent":["import { copyToClipboard } from '../browser';\nimport { DomEventCallback, readStringAttribute } from '../dom';\nimport { kAttrCopy, kAttrMessage } from '../core/constants';\n\nexport type CopyBehaviorOptions = {\n success?: (text: string, element: HTMLElement) => void;\n};\n\nconst copyBehavior: DomEventCallback<HTMLElement> = async (element: HTMLElement, event: Event) => {\n if (element.nodeName.toLowerCase() === 'a' && element.getAttribute('href') === '#') {\n event.preventDefault();\n }\n\n const data = readStringAttribute(element, kAttrCopy);\n\n await copyToClipboard(data);\n};\n\nexport const createCopyBehavior = (options?: CopyBehaviorOptions): DomEventCallback<HTMLElement> => {\n return async (el: HTMLElement, ev: Event) => {\n await copyBehavior(el, ev);\n\n const message = readStringAttribute(el, kAttrMessage, 'Success copy to clipboard.');\n options?.success?.(message, el);\n };\n};\n"],"names":[],"mappings":";;;;AAQA,MAAM,YAAY,GAAkC,OAAO,OAAoB,EAAE,KAAY,KAAI;AAC7F,IAAA,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE;QAChF,KAAK,CAAC,cAAc,EAAE;IAC1B;IAEA,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC;AAEpD,IAAA,MAAM,eAAe,CAAC,IAAI,CAAC;AAC/B,CAAC;AAEM,MAAM,kBAAkB,GAAG,CAAC,OAA6B,KAAmC;AAC/F,IAAA,OAAO,OAAO,EAAe,EAAE,EAAS,KAAI;AACxC,QAAA,MAAM,YAAY,CAAC,EAAE,EAAE,EAAE,CAAC;QAE1B,MAAM,OAAO,GAAG,mBAAmB,CAAC,EAAE,EAAE,YAAY,EAAE,4BAA4B,CAAC;QACnF,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE,CAAC;AACnC,IAAA,CAAC;AACL;;;;"}
|
package/dist/behaviors/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { confirmBehavior
|
|
2
|
-
export { createCopyBehavior
|
|
3
|
-
export {
|
|
1
|
+
export { confirmBehavior } from './confirm.js';
|
|
2
|
+
export { createCopyBehavior } from './copy.js';
|
|
3
|
+
export { processingBehavior } from './processing.js';
|
|
4
|
+
export { createTextareaAutoResizeBehavior } from './textarea-auto-resize.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
import { kAttrProcessing, kAttrProcessingMode } from '../core/constants.js';
|
|
1
2
|
import { readBoolAttribute, readStringAttribute } from '../dom/attributes.js';
|
|
2
3
|
import { createSpinner } from '../ui/spinner.js';
|
|
3
4
|
import { disableElement, enableElement } from '../dom/state.js';
|
|
4
5
|
import { addClass, removeClass } from '../dom/classes.js';
|
|
5
6
|
|
|
6
|
-
const kProcessingAttribute = 'data-processing';
|
|
7
|
-
const kProcessingModeAttribute = 'data-processing-mode';
|
|
8
7
|
const processingBehavior = (element) => {
|
|
9
|
-
const processing = readBoolAttribute(element,
|
|
10
|
-
const mode = readStringAttribute(element,
|
|
8
|
+
const processing = readBoolAttribute(element, kAttrProcessing);
|
|
9
|
+
const mode = readStringAttribute(element, kAttrProcessingMode, 'prepend');
|
|
11
10
|
if (processing) {
|
|
12
11
|
if (element.querySelector('[role="status"]')) {
|
|
13
12
|
// Spinner already exist. Nothing action.
|
|
@@ -39,5 +38,5 @@ const processingBehavior = (element) => {
|
|
|
39
38
|
}
|
|
40
39
|
};
|
|
41
40
|
|
|
42
|
-
export {
|
|
41
|
+
export { processingBehavior };
|
|
43
42
|
//# sourceMappingURL=processing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processing.js","sources":["../../src/behaviors/processing.ts"],"sourcesContent":["import { addClass, disableElement, DomChangeCallback, enableElement, readBoolAttribute, readStringAttribute, removeClass } from '../dom';\nimport { createSpinner } from '../ui';\
|
|
1
|
+
{"version":3,"file":"processing.js","sources":["../../src/behaviors/processing.ts"],"sourcesContent":["import { addClass, disableElement, DomChangeCallback, enableElement, readBoolAttribute, readStringAttribute, removeClass } from '../dom';\nimport { createSpinner } from '../ui';\nimport { kAttrProcessing, kAttrProcessingMode } from '../core/constants';\n\ntype ProcessingMode = 'prepend' | 'replace';\n\nexport const processingBehavior: DomChangeCallback<HTMLElement> = (element): void => {\n const processing = readBoolAttribute(element, kAttrProcessing);\n const mode: ProcessingMode = <ProcessingMode>readStringAttribute(element, kAttrProcessingMode, 'prepend');\n\n if (processing) {\n if (element.querySelector('[role=\"status\"]')) {\n // Spinner already exist. Nothing action.\n return;\n }\n\n const spinner = createSpinner('small');\n\n if (mode === 'prepend') {\n element.prepend(spinner);\n } else {\n element.setAttribute('data-html', element.innerHTML);\n element.innerHTML = spinner.outerHTML;\n }\n\n disableElement(element);\n\n if (element.tagName.toLowerCase() === 'a') {\n addClass(element, 'disabled');\n }\n } else {\n enableElement(element);\n\n (<HTMLSpanElement | null>element.querySelector('[role=\"status\"]'))?.remove();\n\n if (element.tagName.toLowerCase() === 'a') {\n removeClass(element, 'disabled');\n }\n\n if (mode === 'replace') {\n element.innerHTML = readStringAttribute(element, 'data-html');\n element.removeAttribute('data-html');\n }\n }\n};\n"],"names":[],"mappings":";;;;;;AAMO,MAAM,kBAAkB,GAAmC,CAAC,OAAO,KAAU;IAChF,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,EAAE,eAAe,CAAC;IAC9D,MAAM,IAAI,GAAmC,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,EAAE,SAAS,CAAC;IAEzG,IAAI,UAAU,EAAE;AACZ,QAAA,IAAI,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAC,EAAE;;YAE1C;QACJ;AAEA,QAAA,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC;AAEtC,QAAA,IAAI,IAAI,KAAK,SAAS,EAAE;AACpB,YAAA,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAC5B;aAAO;YACH,OAAO,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC;AACpD,YAAA,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS;QACzC;QAEA,cAAc,CAAC,OAAO,CAAC;QAEvB,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE;AACvC,YAAA,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;QACjC;IACJ;SAAO;QACH,aAAa,CAAC,OAAO,CAAC;QAEG,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAE,EAAE,MAAM,EAAE;QAE5E,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE;AACvC,YAAA,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC;QACpC;AAEA,QAAA,IAAI,IAAI,KAAK,SAAS,EAAE;YACpB,OAAO,CAAC,SAAS,GAAG,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC;AAC7D,YAAA,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC;QACxC;IACJ;AACJ;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { applyTextareaAutoResize } from '../dom/textarea.js';
|
|
2
|
+
|
|
3
|
+
const createTextareaAutoResizeBehavior = (maxRows = 4) => {
|
|
4
|
+
return (element) => {
|
|
5
|
+
applyTextareaAutoResize(element, maxRows);
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export { createTextareaAutoResizeBehavior };
|
|
10
|
+
//# sourceMappingURL=textarea-auto-resize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textarea-auto-resize.js","sources":["../../src/behaviors/textarea-auto-resize.ts"],"sourcesContent":["import { applyTextareaAutoResize, DomChangeCallback } from '../dom';\n\nexport const createTextareaAutoResizeBehavior = (maxRows: number = 4): DomChangeCallback<HTMLTextAreaElement> => {\n return (element) => {\n applyTextareaAutoResize(element, maxRows);\n };\n};\n"],"names":[],"mappings":";;MAEa,gCAAgC,GAAG,CAAC,OAAA,GAAkB,CAAC,KAA4C;IAC5G,OAAO,CAAC,OAAO,KAAI;AACf,QAAA,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC;AAC7C,IAAA,CAAC;AACL;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function readFileAsArrayBuffer(file: File): Promise<ArrayBuffer>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function readFileAsArrayBuffer(file) {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
const reader = new FileReader();
|
|
4
|
+
reader.onload = () => resolve(reader.result);
|
|
5
|
+
reader.onerror = () => reject(reader.error);
|
|
6
|
+
reader.readAsArrayBuffer(file);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { readFileAsArrayBuffer };
|
|
11
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sources":["../../src/browser/file.ts"],"sourcesContent":["export function readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => resolve(reader.result as ArrayBuffer);\n reader.onerror = () => reject(reader.error);\n\n reader.readAsArrayBuffer(file);\n });\n}\n"],"names":[],"mappings":"AAAM,SAAU,qBAAqB,CAAC,IAAU,EAAA;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;AACnC,QAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAE/B,QAAA,MAAM,CAAC,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAqB,CAAC;AAC3D,QAAA,MAAM,CAAC,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAE3C,QAAA,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAClC,IAAA,CAAC,CAAC;AACN;;;;"}
|
package/dist/browser/index.d.ts
CHANGED
package/dist/browser/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { getNetworkConnection } from './network.js';
|
|
2
1
|
export { copyToClipboard } from './clipboard.js';
|
|
2
|
+
export { readFileAsArrayBuffer } from './file.js';
|
|
3
|
+
export { getNetworkConnection } from './network.js';
|
|
3
4
|
export { notifyByResponse, notifyError, notifyFetchError, notifyInfo, notifySuccess, notifyWarning } from './notifications.js';
|
|
4
5
|
export { request } from './request.js';
|
|
6
|
+
export { observeElementVisibility } from './visibility.js';
|
|
5
7
|
export { registerNotificationAdapter } from './notifications/adapter.js';
|
|
6
8
|
export { createToastAdapter } from './notifications/toastr.js';
|
|
7
9
|
export { createNotyfAdapter } from './notifications/notyf.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type ElementVisibilityCallback<T extends Element = Element> = (element: T, visible: boolean) => void;
|
|
2
|
+
type ObserveVisibilityOptions = {
|
|
3
|
+
readonly once?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export declare function observeElementVisibility<T extends Element = Element>(element: T, callback: ElementVisibilityCallback<T>, options?: ObserveVisibilityOptions): () => void;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const observers = new Map();
|
|
2
|
+
const intersectionObserver = new IntersectionObserver((entries) => {
|
|
3
|
+
for (const entry of entries) {
|
|
4
|
+
const observer = observers.get(entry.target);
|
|
5
|
+
if (!observer) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
observer.callback(entry.target, entry.isIntersecting);
|
|
9
|
+
if (observer.once && entry.isIntersecting) {
|
|
10
|
+
intersectionObserver.unobserve(entry.target);
|
|
11
|
+
observers.delete(entry.target);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
function observeElementVisibility(element, callback, options) {
|
|
16
|
+
observers.set(element, {
|
|
17
|
+
callback: callback,
|
|
18
|
+
once: options?.once ?? false,
|
|
19
|
+
});
|
|
20
|
+
intersectionObserver.observe(element);
|
|
21
|
+
return () => {
|
|
22
|
+
intersectionObserver.unobserve(element);
|
|
23
|
+
observers.delete(element);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { observeElementVisibility };
|
|
28
|
+
//# sourceMappingURL=visibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visibility.js","sources":["../../src/browser/visibility.ts"],"sourcesContent":["export type ElementVisibilityCallback<T extends Element = Element> = (element: T, visible: boolean) => void;\n\ntype ObserverEntry = {\n callback: ElementVisibilityCallback;\n once: boolean;\n};\n\ntype ObserveVisibilityOptions = {\n readonly once?: boolean;\n}\n\nconst observers = new Map<Element, ObserverEntry>();\n\nconst intersectionObserver = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n const observer = observers.get(entry.target);\n\n if (!observer) {\n continue;\n }\n\n observer.callback(entry.target, entry.isIntersecting);\n\n if (observer.once && entry.isIntersecting) {\n intersectionObserver.unobserve(entry.target);\n observers.delete(entry.target);\n }\n }\n});\n\nexport function observeElementVisibility<T extends Element = Element>(element: T, callback: ElementVisibilityCallback<T>, options?: ObserveVisibilityOptions): () => void {\n observers.set(element, {\n callback: callback as ElementVisibilityCallback,\n once: options?.once ?? false,\n });\n\n intersectionObserver.observe(element);\n\n return () => {\n intersectionObserver.unobserve(element);\n observers.delete(element);\n };\n}\n"],"names":[],"mappings":"AAWA,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B;AAEnD,MAAM,oBAAoB,GAAG,IAAI,oBAAoB,CAAC,CAAC,OAAO,KAAI;AAC9D,IAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;QACzB,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;QAE5C,IAAI,CAAC,QAAQ,EAAE;YACX;QACJ;QAEA,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC;QAErD,IAAI,QAAQ,CAAC,IAAI,IAAI,KAAK,CAAC,cAAc,EAAE;AACvC,YAAA,oBAAoB,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;AAC5C,YAAA,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QAClC;IACJ;AACJ,CAAC,CAAC;SAEc,wBAAwB,CAA8B,OAAU,EAAE,QAAsC,EAAE,OAAkC,EAAA;AACxJ,IAAA,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE;AACnB,QAAA,QAAQ,EAAE,QAAqC;AAC/C,QAAA,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,KAAK;AAC/B,KAAA,CAAC;AAEF,IAAA,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC;AAErC,IAAA,OAAO,MAAK;AACR,QAAA,oBAAoB,CAAC,SAAS,CAAC,OAAO,CAAC;AACvC,QAAA,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7B,IAAA,CAAC;AACL;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function setConfig(key: string, value: unknown): void;
|
|
2
|
+
export declare function getConfig<T = unknown>(key: string, timeout?: number): Promise<T>;
|
|
3
|
+
export declare function hasConfig(key: string): boolean;
|
|
4
|
+
export declare const __test__: {
|
|
5
|
+
reset: () => void;
|
|
6
|
+
} | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
let store = new Map();
|
|
2
|
+
let waiters = new Map();
|
|
3
|
+
function setConfig(key, value) {
|
|
4
|
+
store.set(key, value);
|
|
5
|
+
const waiterEntry = waiters.get(key);
|
|
6
|
+
if (waiterEntry) {
|
|
7
|
+
waiterEntry[1](value);
|
|
8
|
+
waiters.delete(key);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
async function getConfig(key, timeout = 1000) {
|
|
12
|
+
if (store.has(key)) {
|
|
13
|
+
return store.get(key);
|
|
14
|
+
}
|
|
15
|
+
const existence = waiters.get(key);
|
|
16
|
+
if (existence) {
|
|
17
|
+
return existence[0];
|
|
18
|
+
}
|
|
19
|
+
let timer;
|
|
20
|
+
let wrappedResolve;
|
|
21
|
+
const promise = new Promise((resolve, reject) => {
|
|
22
|
+
timer = setTimeout(() => {
|
|
23
|
+
waiters.delete(key);
|
|
24
|
+
reject(new Error(`Failed to read config "${key}" during timeout (${timeout}ms).`));
|
|
25
|
+
}, timeout);
|
|
26
|
+
wrappedResolve = (value) => {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
resolve(value);
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
waiters.set(key, [promise, wrappedResolve]);
|
|
32
|
+
return promise;
|
|
33
|
+
}
|
|
34
|
+
function hasConfig(key) {
|
|
35
|
+
return store.has(key);
|
|
36
|
+
}
|
|
37
|
+
const __test__ = import.meta.env?.MODE === 'test'
|
|
38
|
+
? {
|
|
39
|
+
reset: () => {
|
|
40
|
+
store = new Map();
|
|
41
|
+
waiters = new Map();
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
: undefined;
|
|
45
|
+
|
|
46
|
+
export { __test__, getConfig, hasConfig, setConfig };
|
|
47
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sources":["../../src/core/config.ts"],"sourcesContent":["let store: Map<string, unknown> = new Map();\nlet waiters: Map<string, [Promise<unknown>, (value: unknown) => void]> = new Map();\n\nexport function setConfig(key: string, value: unknown): void {\n store.set(key, value);\n\n const waiterEntry = waiters.get(key);\n\n if (waiterEntry) {\n waiterEntry[1](value);\n waiters.delete(key);\n }\n}\n\nexport async function getConfig<T = unknown>(key: string, timeout = 1000): Promise<T> {\n if (store.has(key)) {\n return store.get(key) as T;\n }\n\n const existence = waiters.get(key);\n\n if (existence) {\n return existence[0] as T;\n }\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n let wrappedResolve!: (value: unknown) => void;\n\n const promise = new Promise<T>((resolve, reject) => {\n timer = setTimeout(() => {\n waiters.delete(key);\n reject(new Error(`Failed to read config \"${key}\" during timeout (${timeout}ms).`));\n }, timeout);\n\n wrappedResolve = (value: unknown) => {\n clearTimeout(timer);\n resolve(value as T);\n };\n });\n\n waiters.set(key, [promise as Promise<unknown>, wrappedResolve]);\n\n return promise;\n}\n\nexport function hasConfig(key: string): boolean {\n return store.has(key);\n}\n\nexport const __test__ = import.meta.env?.MODE === 'test'\n ? {\n reset: () => {\n store = new Map();\n waiters = new Map();\n },\n }\n : undefined;\n"],"names":[],"mappings":"AAAA,IAAI,KAAK,GAAyB,IAAI,GAAG,EAAE;AAC3C,IAAI,OAAO,GAA8D,IAAI,GAAG,EAAE;AAE5E,SAAU,SAAS,CAAC,GAAW,EAAE,KAAc,EAAA;AACjD,IAAA,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;IAErB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IAEpC,IAAI,WAAW,EAAE;AACb,QAAA,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB,QAAA,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;IACvB;AACJ;AAEO,eAAe,SAAS,CAAc,GAAW,EAAE,OAAO,GAAG,IAAI,EAAA;AACpE,IAAA,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;AAChB,QAAA,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAM;IAC9B;IAEA,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IAElC,IAAI,SAAS,EAAE;AACX,QAAA,OAAO,SAAS,CAAC,CAAC,CAAM;IAC5B;AAEA,IAAA,IAAI,KAAgD;AAEpD,IAAA,IAAI,cAAyC;IAE7C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,KAAI;AAC/C,QAAA,KAAK,GAAG,UAAU,CAAC,MAAK;AACpB,YAAA,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;YACnB,MAAM,CAAC,IAAI,KAAK,CAAC,CAAA,uBAAA,EAA0B,GAAG,CAAA,kBAAA,EAAqB,OAAO,CAAA,IAAA,CAAM,CAAC,CAAC;QACtF,CAAC,EAAE,OAAO,CAAC;AAEX,QAAA,cAAc,GAAG,CAAC,KAAc,KAAI;YAChC,YAAY,CAAC,KAAK,CAAC;YACnB,OAAO,CAAC,KAAU,CAAC;AACvB,QAAA,CAAC;AACL,IAAA,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAA2B,EAAE,cAAc,CAAC,CAAC;AAE/D,IAAA,OAAO,OAAO;AAClB;AAEM,SAAU,SAAS,CAAC,GAAW,EAAA;AACjC,IAAA,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AACzB;AAEO,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK;AAC9C,MAAE;QACE,KAAK,EAAE,MAAK;AACR,YAAA,KAAK,GAAG,IAAI,GAAG,EAAE;AACjB,YAAA,OAAO,GAAG,IAAI,GAAG,EAAE;QACvB,CAAC;AACJ;MACC;;;;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const kAttrProcessing = "data-processing";
|
|
2
|
+
export declare const kAttrProcessingMode = "data-processing-mode";
|
|
3
|
+
export declare const kAttrHref = "data-href";
|
|
4
|
+
export declare const kAttrConfirm = "data-confirm";
|
|
5
|
+
export declare const kAttrCopy = "data-copy";
|
|
6
|
+
export declare const kAttrMessage = "data-message";
|
|
7
|
+
export declare const kAttrMaxRows = "data-max-rows";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const kAttrProcessing = 'data-processing';
|
|
2
|
+
const kAttrProcessingMode = 'data-processing-mode';
|
|
3
|
+
const kAttrHref = 'data-href';
|
|
4
|
+
const kAttrConfirm = 'data-confirm';
|
|
5
|
+
const kAttrCopy = 'data-copy';
|
|
6
|
+
const kAttrMessage = 'data-message';
|
|
7
|
+
const kAttrMaxRows = 'data-max-rows';
|
|
8
|
+
|
|
9
|
+
export { kAttrConfirm, kAttrCopy, kAttrHref, kAttrMaxRows, kAttrMessage, kAttrProcessing, kAttrProcessingMode };
|
|
10
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../src/core/constants.ts"],"sourcesContent":["export const kAttrProcessing = 'data-processing';\nexport const kAttrProcessingMode = 'data-processing-mode';\nexport const kAttrHref = 'data-href';\nexport const kAttrConfirm = 'data-confirm';\nexport const kAttrCopy = 'data-copy';\nexport const kAttrMessage = 'data-message';\nexport const kAttrMaxRows = 'data-max-rows';"],"names":[],"mappings":"AAAO,MAAM,eAAe,GAAG;AACxB,MAAM,mBAAmB,GAAG;AAC5B,MAAM,SAAS,GAAG;AAClB,MAAM,YAAY,GAAG;AACrB,MAAM,SAAS,GAAG;AAClB,MAAM,YAAY,GAAG;AACrB,MAAM,YAAY,GAAG;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class Observable {
|
|
2
|
+
listeners = new Set();
|
|
3
|
+
subscribe(callback) {
|
|
4
|
+
this.listeners.add(callback);
|
|
5
|
+
return () => {
|
|
6
|
+
this.listeners.delete(callback);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
emit(data) {
|
|
10
|
+
for (const callback of this.listeners) {
|
|
11
|
+
callback(data);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { Observable };
|
|
17
|
+
//# sourceMappingURL=observable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observable.js","sources":["../../src/core/observable.ts"],"sourcesContent":["export class Observable<T> {\n private listeners = new Set<(data: T) => void>();\n\n subscribe(callback: (data: T) => void): () => void {\n this.listeners.add(callback);\n\n return () => {\n this.listeners.delete(callback);\n };\n }\n\n emit(data: T): void {\n for (const callback of this.listeners) {\n callback(data);\n }\n }\n}\n"],"names":[],"mappings":"MAAa,UAAU,CAAA;AACX,IAAA,SAAS,GAAG,IAAI,GAAG,EAAqB;AAEhD,IAAA,SAAS,CAAC,QAA2B,EAAA;AACjC,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;AAE5B,QAAA,OAAO,MAAK;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AACnC,QAAA,CAAC;IACL;AAEA,IAAA,IAAI,CAAC,IAAO,EAAA;AACR,QAAA,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;YACnC,QAAQ,CAAC,IAAI,CAAC;QAClB;IACJ;AACH;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getExtension(value: string | File): string | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function getExtension(value) {
|
|
2
|
+
const name = typeof value === 'string' ? value : value.name;
|
|
3
|
+
const index = name.lastIndexOf('.');
|
|
4
|
+
if (index === -1 || index === name.length - 1) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return name.slice(index + 1).toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { getExtension };
|
|
11
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sources":["../../src/core/path.ts"],"sourcesContent":["export function getExtension(value: string | File): string | null {\n const name = typeof value === 'string' ? value : value.name;\n\n const index = name.lastIndexOf('.');\n\n if (index === -1 || index === name.length - 1) {\n return null;\n }\n\n return name.slice(index + 1).toLowerCase();\n}\n"],"names":[],"mappings":"AAAM,SAAU,YAAY,CAAC,KAAoB,EAAA;AAC7C,IAAA,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC,IAAI;IAE3D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;AAEnC,IAAA,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AAC3C,QAAA,OAAO,IAAI;IACf;IAEA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;AAC9C;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function diffTime(from, to) {
|
|
2
|
+
let diffSeconds = Math.floor((to.getTime() - from.getTime()) / 1000);
|
|
3
|
+
const sign = diffSeconds < 0 ? -1 : 1;
|
|
4
|
+
diffSeconds = Math.abs(diffSeconds);
|
|
5
|
+
const days = Math.floor(diffSeconds / 86400);
|
|
6
|
+
diffSeconds -= days * 86400;
|
|
7
|
+
const hours = Math.floor(diffSeconds / 3600);
|
|
8
|
+
diffSeconds -= hours * 3600;
|
|
9
|
+
const minutes = Math.floor(diffSeconds / 60);
|
|
10
|
+
diffSeconds -= minutes * 60;
|
|
11
|
+
const seconds = diffSeconds;
|
|
12
|
+
const applySign = (value, sign) => value === 0 ? 0 : value * sign;
|
|
13
|
+
return {
|
|
14
|
+
days: applySign(days, sign),
|
|
15
|
+
hours: applySign(hours, sign),
|
|
16
|
+
minutes: applySign(minutes, sign),
|
|
17
|
+
seconds: applySign(seconds, sign),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { diffTime };
|
|
22
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sources":["../../src/core/time.ts"],"sourcesContent":["export type TimeDiff = {\n readonly days: number;\n readonly hours: number;\n readonly minutes: number;\n readonly seconds: number;\n};\n\nexport function diffTime(from: Date, to: Date): TimeDiff {\n let diffSeconds = Math.floor((to.getTime() - from.getTime()) / 1000);\n\n const sign = diffSeconds < 0 ? -1 : 1;\n diffSeconds = Math.abs(diffSeconds);\n\n const days = Math.floor(diffSeconds / 86400);\n diffSeconds -= days * 86400;\n\n const hours = Math.floor(diffSeconds / 3600);\n diffSeconds -= hours * 3600;\n\n const minutes = Math.floor(diffSeconds / 60);\n diffSeconds -= minutes * 60;\n\n const seconds = diffSeconds;\n\n const applySign = (value: number, sign: number) => value === 0 ? 0 : value * sign;\n\n return {\n days: applySign(days, sign),\n hours: applySign(hours, sign),\n minutes: applySign(minutes, sign),\n seconds: applySign(seconds, sign),\n };\n}\n"],"names":[],"mappings":"AAOM,SAAU,QAAQ,CAAC,IAAU,EAAE,EAAQ,EAAA;IACzC,IAAI,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC;AAEpE,IAAA,MAAM,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC;AACrC,IAAA,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;IAEnC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC;AAC5C,IAAA,WAAW,IAAI,IAAI,GAAG,KAAK;IAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;AAC5C,IAAA,WAAW,IAAI,KAAK,GAAG,IAAI;IAE3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC;AAC5C,IAAA,WAAW,IAAI,OAAO,GAAG,EAAE;IAE3B,MAAM,OAAO,GAAG,WAAW;IAE3B,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,IAAY,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI;IAEjF,OAAO;AACH,QAAA,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;AAC3B,QAAA,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC;AAC7B,QAAA,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC;AACjC,QAAA,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC;KACpC;AACL;;;;"}
|
package/dist/dom/changes.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ type SelectorsDomChangeOptions = BaseDomChangeOptions & {
|
|
|
12
12
|
};
|
|
13
13
|
export type DomChangeCallback<T extends Element = Element> = (target: T, item?: MutationRecord) => void;
|
|
14
14
|
export type DomChangeCallbacks<T extends Element = Element> = Record<string, DomChangeCallback<T>>;
|
|
15
|
-
export declare function onDomChanges(options: SelectorDomChangeOptions, callback: DomChangeCallback): void;
|
|
15
|
+
export declare function onDomChanges<T extends Element = Element>(options: SelectorDomChangeOptions, callback: DomChangeCallback<T>): void;
|
|
16
16
|
export declare function onDomChanges(options: SelectorsDomChangeOptions): void;
|
|
17
17
|
export {};
|
package/dist/dom/changes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changes.js","sources":["../../src/dom/changes.ts"],"sourcesContent":["import { onDomReady } from './ready';\n\ntype BaseDomChangeOptions = MutationObserverInit & {\n readonly onDomReady?: boolean; // execute handler after dom ready?\n readonly target?: string; // where we must see changes?\n}\n\ntype SelectorDomChangeOptions = BaseDomChangeOptions & {\n readonly selector?: string; // what element we find?\n selectors?: never;\n}\n\ntype SelectorsDomChangeOptions = BaseDomChangeOptions & {\n readonly selectors?: DomChangeCallbacks; // each selector must contain callback function\n selector?: never;\n}\n\ntype DomChangeOptions = SelectorsDomChangeOptions | SelectorDomChangeOptions;\n\nexport type DomChangeCallback<T extends Element = Element> = (target: T, item?: MutationRecord) => void;\nexport type DomChangeCallbacks<T extends Element = Element> = Record<string, DomChangeCallback<T>>;\n\nexport function onDomChanges(options: SelectorDomChangeOptions, callback: DomChangeCallback): void;\nexport function onDomChanges(options: SelectorsDomChangeOptions): void;\n\nexport function onDomChanges(options: DomChangeOptions, callback?: DomChangeCallback): void {\n if (options.selector && options.selectors) {\n throw new Error('Only one option must be provided: either selector or selectors, not both.');\n }\n\n if (options.selectors && callback) {\n throw new Error('Only one option must be provided: either selectors or callback, not both.');\n }\n\n function changesOnElementWithSelector(element: HTMLElement, handler: DomChangeCallback, item?: MutationRecord, selector?: string): void {\n if (selector) {\n if (element.matches(selector)) {\n handler.call(null, element, item);\n } else {\n element.querySelectorAll(selector).forEach((innerElement) => {\n handler.call(null, innerElement, item);\n });\n }\n } else {\n handler.call(null, element, item);\n }\n }\n\n function changesOnElementWithSelectors(element: HTMLElement, selectors: DomChangeCallbacks, item?: MutationRecord): void {\n Object.entries(selectors).forEach(([selector, handler]) => {\n changesOnElementWithSelector.call(null, element, handler, item, selector);\n });\n }\n\n let selectors: DomChangeCallbacks | undefined = undefined;\n\n if (options.selectors) {\n selectors = options.selectors;\n } else if (options.selector) {\n if (!callback) {\n throw new Error('Missed callback.');\n }\n\n selectors = {};\n selectors[options.selector] = callback;\n }\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((item) => {\n item.addedNodes.forEach((node) => {\n if (!(node instanceof HTMLElement)) {\n return;\n }\n\n if (selectors) {\n changesOnElementWithSelectors(node, selectors, item);\n } else {\n if (!callback) {\n throw new Error('Missed callback.');\n }\n\n changesOnElementWithSelector(node, callback, item);\n }\n });\n\n if (item.attributeName) {\n callback?.call(null, <Element>item.target, item);\n }\n });\n });\n\n onDomReady(() => {\n const target = <HTMLElement>(options.target ? document.querySelector(options.target) : document.body);\n\n if (!target) {\n console.debug(`The target with selector \"${options.target}\" for listen page changes was not found.`);\n\n return;\n }\n\n observer.observe(target, options);\n\n if (options.onDomReady) {\n if (!selectors) {\n throw new Error('Selector or selectors is required for enable \"on dom ready\".');\n }\n\n changesOnElementWithSelectors(target, selectors);\n }\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"changes.js","sources":["../../src/dom/changes.ts"],"sourcesContent":["import { onDomReady } from './ready';\n\ntype BaseDomChangeOptions = MutationObserverInit & {\n readonly onDomReady?: boolean; // execute handler after dom ready?\n readonly target?: string; // where we must see changes?\n}\n\ntype SelectorDomChangeOptions = BaseDomChangeOptions & {\n readonly selector?: string; // what element we find?\n selectors?: never;\n}\n\ntype SelectorsDomChangeOptions = BaseDomChangeOptions & {\n readonly selectors?: DomChangeCallbacks; // each selector must contain callback function\n selector?: never;\n}\n\ntype DomChangeOptions = SelectorsDomChangeOptions | SelectorDomChangeOptions;\n\nexport type DomChangeCallback<T extends Element = Element> = (target: T, item?: MutationRecord) => void;\nexport type DomChangeCallbacks<T extends Element = Element> = Record<string, DomChangeCallback<T>>;\n\nexport function onDomChanges<T extends Element = Element>(options: SelectorDomChangeOptions, callback: DomChangeCallback<T>): void;\nexport function onDomChanges(options: SelectorsDomChangeOptions): void;\n\nexport function onDomChanges(options: DomChangeOptions, callback?: DomChangeCallback): void {\n if (options.selector && options.selectors) {\n throw new Error('Only one option must be provided: either selector or selectors, not both.');\n }\n\n if (options.selectors && callback) {\n throw new Error('Only one option must be provided: either selectors or callback, not both.');\n }\n\n function changesOnElementWithSelector(element: HTMLElement, handler: DomChangeCallback, item?: MutationRecord, selector?: string): void {\n if (selector) {\n if (element.matches(selector)) {\n handler.call(null, element, item);\n } else {\n element.querySelectorAll(selector).forEach((innerElement) => {\n handler.call(null, innerElement, item);\n });\n }\n } else {\n handler.call(null, element, item);\n }\n }\n\n function changesOnElementWithSelectors(element: HTMLElement, selectors: DomChangeCallbacks, item?: MutationRecord): void {\n Object.entries(selectors).forEach(([selector, handler]) => {\n changesOnElementWithSelector.call(null, element, handler, item, selector);\n });\n }\n\n let selectors: DomChangeCallbacks | undefined = undefined;\n\n if (options.selectors) {\n selectors = options.selectors;\n } else if (options.selector) {\n if (!callback) {\n throw new Error('Missed callback.');\n }\n\n selectors = {};\n selectors[options.selector] = callback;\n }\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((item) => {\n item.addedNodes.forEach((node) => {\n if (!(node instanceof HTMLElement)) {\n return;\n }\n\n if (selectors) {\n changesOnElementWithSelectors(node, selectors, item);\n } else {\n if (!callback) {\n throw new Error('Missed callback.');\n }\n\n changesOnElementWithSelector(node, callback, item);\n }\n });\n\n if (item.attributeName) {\n callback?.call(null, <Element>item.target, item);\n }\n });\n });\n\n onDomReady(() => {\n const target = <HTMLElement>(options.target ? document.querySelector(options.target) : document.body);\n\n if (!target) {\n console.debug(`The target with selector \"${options.target}\" for listen page changes was not found.`);\n\n return;\n }\n\n observer.observe(target, options);\n\n if (options.onDomReady) {\n if (!selectors) {\n throw new Error('Selector or selectors is required for enable \"on dom ready\".');\n }\n\n changesOnElementWithSelectors(target, selectors);\n }\n });\n}\n"],"names":[],"mappings":"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"}
|
package/dist/dom/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sources":["../../src/dom/events.ts"],"sourcesContent":["import { onDomReady } from './ready';\n\nexport type DomEventCallback<E extends Element = Element> = (element: E, event: Event) => void | Promise<void>;\nexport type DomEventCallbacks<E extends Element = Element> = Record<string, DomEventCallback<E>>;\n\ntype EventName = 'click' | 'change';\ntype Selector = string;\n\ntype BaseListenOptions = {\n readonly target?: string | HTMLElement;\n}\n\ntype SelectorListenOptions = BaseListenOptions & {\n readonly selector: Selector;\n selectors?: never;\n}\n\ntype SelectorsListenOptions<E extends Element = Element> = BaseListenOptions & {\n readonly selectors: DomEventCallbacks<E>;\n selector?: never;\n}\n\nexport function onDomEvents<E extends Element = Element>(eventName: EventName, options: SelectorListenOptions | string, handler: DomEventCallback<E>): void;\nexport function onDomEvents<E extends Element = Element>(eventName: EventName, options: SelectorsListenOptions<E>): void;\n\nexport function onDomEvents
|
|
1
|
+
{"version":3,"file":"events.js","sources":["../../src/dom/events.ts"],"sourcesContent":["import { onDomReady } from './ready';\n\nexport type DomEventCallback<E extends Element = Element> = (element: E, event: Event) => void | Promise<void>;\nexport type DomEventCallbacks<E extends Element = Element> = Record<string, DomEventCallback<E>>;\n\ntype EventName = 'click' | 'change';\ntype Selector = string;\n\ntype BaseListenOptions = {\n readonly target?: string | HTMLElement;\n}\n\ntype SelectorListenOptions = BaseListenOptions & {\n readonly selector: Selector;\n selectors?: never;\n}\n\ntype SelectorsListenOptions<E extends Element = Element> = BaseListenOptions & {\n readonly selectors: DomEventCallbacks<E>;\n selector?: never;\n}\n\nexport function onDomEvents<E extends Element = Element>(eventName: EventName, options: SelectorListenOptions | string, handler: DomEventCallback<E>): void;\nexport function onDomEvents<E extends Element = Element>(eventName: EventName, options: SelectorsListenOptions<E>): void;\n\nexport function onDomEvents(eventName: EventName, options: SelectorListenOptions | SelectorsListenOptions | string, handler?: DomEventCallback): void {\n if (typeof options === 'string') {\n options = <SelectorListenOptions>{\n selector: options,\n };\n }\n\n if (options.selectors && handler) {\n throw new Error('Only one option must be provided: either selectors or callback, not both.');\n }\n\n let selectors: DomEventCallbacks;\n\n if (options.selectors) {\n selectors = options.selectors as DomEventCallbacks;\n } else {\n if (!handler) {\n throw new Error('Missed handler');\n }\n\n selectors = {};\n selectors[options.selector] = handler as DomEventCallback;\n }\n\n const findHandler = (selectors: DomEventCallbacks, element: HTMLElement): [HTMLElement, DomEventCallback] | null => {\n for (const [selector, handler] of Object.entries(selectors)) {\n if (element.matches(selector)) {\n return [element, handler];\n }\n\n const parent = <HTMLElement>element.closest(selector);\n\n if (parent) {\n return [parent, handler];\n }\n }\n\n return null;\n };\n\n onDomReady(() => {\n let target: Element | null = document.body;\n\n if (options.target) {\n target = options.target instanceof Element ? options.target : document.querySelector(options.target);\n\n if (!target) {\n throw new Error(`Missed target element by selector \"${options.target}\".`);\n }\n }\n\n target.addEventListener(eventName, (event): void => {\n const target = <HTMLElement>event.target;\n const entry = findHandler(selectors, target);\n\n if (entry) {\n entry[1].call(null, entry[0], event);\n }\n });\n });\n}\n"],"names":[],"mappings":";;SAyBgB,WAAW,CAAC,SAAoB,EAAE,OAAgE,EAAE,OAA0B,EAAA;AAC1I,IAAA,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;AAC7B,QAAA,OAAO,GAA0B;AAC7B,YAAA,QAAQ,EAAE,OAAO;SACpB;IACL;AAEA,IAAA,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,EAAE;AAC9B,QAAA,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC;IAChG;AAEA,IAAA,IAAI,SAA4B;AAEhC,IAAA,IAAI,OAAO,CAAC,SAAS,EAAE;AACnB,QAAA,SAAS,GAAG,OAAO,CAAC,SAA8B;IACtD;SAAO;QACH,IAAI,CAAC,OAAO,EAAE;AACV,YAAA,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC;QACrC;QAEA,SAAS,GAAG,EAAE;AACd,QAAA,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,OAA2B;IAC7D;AAEA,IAAA,MAAM,WAAW,GAAG,CAAC,SAA4B,EAAE,OAAoB,KAA4C;AAC/G,QAAA,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;AACzD,YAAA,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;AAC3B,gBAAA,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;YAC7B;YAEA,MAAM,MAAM,GAAgB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;YAErD,IAAI,MAAM,EAAE;AACR,gBAAA,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;YAC5B;QACJ;AAEA,QAAA,OAAO,IAAI;AACf,IAAA,CAAC;IAED,UAAU,CAAC,MAAK;AACZ,QAAA,IAAI,MAAM,GAAmB,QAAQ,CAAC,IAAI;AAE1C,QAAA,IAAI,OAAO,CAAC,MAAM,EAAE;YAChB,MAAM,GAAG,OAAO,CAAC,MAAM,YAAY,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC;YAEpG,IAAI,CAAC,MAAM,EAAE;gBACT,MAAM,IAAI,KAAK,CAAC,CAAA,mCAAA,EAAsC,OAAO,CAAC,MAAM,CAAA,EAAA,CAAI,CAAC;YAC7E;QACJ;QAEA,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,KAAU;AAC/C,YAAA,MAAM,MAAM,GAAgB,KAAK,CAAC,MAAM;YACxC,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC;YAE5C,IAAI,KAAK,EAAE;AACP,gBAAA,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;YACxC;AACJ,QAAA,CAAC,CAAC;AACN,IAAA,CAAC,CAAC;AACN;;;;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type FormElementValue = string | boolean | number | File | File[] | null;
|
|
2
|
+
type OutputCtor = typeof FormData | typeof URLSearchParams;
|
|
3
|
+
type FormDataResult<T> = T extends typeof FormData ? FormData : T extends typeof URLSearchParams ? URLSearchParams : URLSearchParams;
|
|
4
|
+
export declare function startFormProcessing(form: HTMLFormElement): void;
|
|
5
|
+
export declare function endFormProcessing(form: HTMLFormElement): void;
|
|
6
|
+
export declare function readInputValue(element: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement): string;
|
|
7
|
+
export declare function readCheckboxValue(input: HTMLInputElement): boolean;
|
|
8
|
+
export declare function readRadioValue(form: HTMLFormElement, name: string): string | null;
|
|
9
|
+
export declare function readNumberInput(element: HTMLInputElement): number | null;
|
|
10
|
+
export declare function readBooleanInput(element: HTMLInputElement): boolean;
|
|
11
|
+
export declare function readFileInput(input: HTMLInputElement): File | File[] | null;
|
|
12
|
+
export declare function readElementValue(element: Element): FormElementValue;
|
|
13
|
+
export declare function readFormData(form: HTMLFormElement): URLSearchParams;
|
|
14
|
+
export declare function readFormData<T extends OutputCtor>(form: HTMLFormElement, output: T): FormDataResult<T>;
|
|
15
|
+
export {};
|
package/dist/dom/form.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { readBoolAttribute } from './attributes.js';
|
|
2
|
+
import { isDisabled } from './state.js';
|
|
3
|
+
import { kAttrProcessing } from '../core/constants.js';
|
|
4
|
+
|
|
5
|
+
const kAttrFormProcessing = 'data-form-processing';
|
|
6
|
+
function getFormControls(form) {
|
|
7
|
+
return Array.from(form.querySelectorAll('input, select, textarea, button'));
|
|
8
|
+
}
|
|
9
|
+
function startFormProcessing(form) {
|
|
10
|
+
getFormControls(form).forEach((el) => {
|
|
11
|
+
if (el.disabled) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
el.disabled = true;
|
|
15
|
+
el.setAttribute(kAttrFormProcessing, 'true');
|
|
16
|
+
});
|
|
17
|
+
form.querySelector('button[type="submit"]')?.setAttribute(kAttrProcessing, '1');
|
|
18
|
+
}
|
|
19
|
+
function endFormProcessing(form) {
|
|
20
|
+
getFormControls(form).forEach((el) => {
|
|
21
|
+
if (readBoolAttribute(el, kAttrFormProcessing)) {
|
|
22
|
+
el.disabled = false;
|
|
23
|
+
el.removeAttribute(kAttrFormProcessing);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
form.querySelector('button[type="submit"]')?.removeAttribute(kAttrProcessing);
|
|
27
|
+
}
|
|
28
|
+
function readInputValue(element) {
|
|
29
|
+
return element.value;
|
|
30
|
+
}
|
|
31
|
+
function readCheckboxValue(input) {
|
|
32
|
+
if (input.type !== 'checkbox') {
|
|
33
|
+
throw new TypeError('Expected checkbox input');
|
|
34
|
+
}
|
|
35
|
+
return input.checked;
|
|
36
|
+
}
|
|
37
|
+
function readRadioValue(form, name) {
|
|
38
|
+
const checked = form.querySelector(`input[type="radio"][name="${name}"]:checked`);
|
|
39
|
+
return checked?.value ?? null;
|
|
40
|
+
}
|
|
41
|
+
function readNumberInput(element) {
|
|
42
|
+
const value = element.value.trim();
|
|
43
|
+
if (value === '') {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const num = Number(value);
|
|
47
|
+
return Number.isNaN(num) ? null : num;
|
|
48
|
+
}
|
|
49
|
+
function readBooleanInput(element) {
|
|
50
|
+
return element.checked;
|
|
51
|
+
}
|
|
52
|
+
function readFileInput(input) {
|
|
53
|
+
if (input.type !== 'file') {
|
|
54
|
+
throw new TypeError('Expected file input');
|
|
55
|
+
}
|
|
56
|
+
const files = input.files;
|
|
57
|
+
if (!files || files.length === 0) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
if (input.multiple) {
|
|
61
|
+
return Array.from(files);
|
|
62
|
+
}
|
|
63
|
+
return files[0] ?? null;
|
|
64
|
+
}
|
|
65
|
+
function readElementValue(element) {
|
|
66
|
+
if (element instanceof HTMLInputElement) {
|
|
67
|
+
switch (element.type) {
|
|
68
|
+
case 'checkbox':
|
|
69
|
+
return readCheckboxValue(element);
|
|
70
|
+
case 'number':
|
|
71
|
+
return readNumberInput(element);
|
|
72
|
+
case 'radio':
|
|
73
|
+
if (!element.form || !element.name) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return readRadioValue(element.form, element.name);
|
|
77
|
+
case 'file':
|
|
78
|
+
return readFileInput(element);
|
|
79
|
+
default:
|
|
80
|
+
return readInputValue(element);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (element instanceof HTMLTextAreaElement) {
|
|
84
|
+
return readInputValue(element);
|
|
85
|
+
}
|
|
86
|
+
if (element instanceof HTMLSelectElement) {
|
|
87
|
+
return readInputValue(element);
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function readFormData(form, output = URLSearchParams) {
|
|
92
|
+
const result = output === FormData
|
|
93
|
+
? new FormData()
|
|
94
|
+
: new URLSearchParams();
|
|
95
|
+
const elements = Array.from(form.elements);
|
|
96
|
+
const append = (target, key, value) => {
|
|
97
|
+
const v = typeof value === 'boolean'
|
|
98
|
+
? value ? '1' : '0'
|
|
99
|
+
: typeof value === 'number'
|
|
100
|
+
? String(value)
|
|
101
|
+
: value;
|
|
102
|
+
if (target instanceof FormData) {
|
|
103
|
+
target.append(key, v);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
target.append(key, String(v));
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
for (const el of elements) {
|
|
110
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) {
|
|
111
|
+
if (!('name' in el)) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (isDisabled(el)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (!el.name) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const value = readElementValue(el);
|
|
121
|
+
if (value === null) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
// File[]
|
|
125
|
+
if (Array.isArray(value)) {
|
|
126
|
+
for (const v of value) {
|
|
127
|
+
append(result, el.name, v);
|
|
128
|
+
}
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
append(result, el.name, value);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { endFormProcessing, readBooleanInput, readCheckboxValue, readElementValue, readFileInput, readFormData, readInputValue, readNumberInput, readRadioValue, startFormProcessing };
|
|
138
|
+
//# sourceMappingURL=form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sources":["../../src/dom/form.ts"],"sourcesContent":["import { readBoolAttribute } from './attributes';\nimport { isDisabled } from './state';\nimport { kAttrProcessing } from '../core/constants';\n\ntype FormElementValue = | string | boolean | number | File | File[] | null;\ntype OutputCtor = typeof FormData | typeof URLSearchParams;\n\ntype FormDataResult<T> =\n T extends typeof FormData ? FormData :\n T extends typeof URLSearchParams ? URLSearchParams :\n URLSearchParams;\n\nconst kAttrFormProcessing = 'data-form-processing';\n\nfunction getFormControls(form: HTMLFormElement): HTMLElement[] {\n return Array.from(form.querySelectorAll<HTMLElement>('input, select, textarea, button'));\n}\n\nexport function startFormProcessing(form: HTMLFormElement): void {\n getFormControls(form).forEach((el) => {\n if ((el as HTMLInputElement).disabled) {\n return;\n }\n\n (el as HTMLInputElement).disabled = true;\n\n el.setAttribute(kAttrFormProcessing, 'true');\n });\n\n form.querySelector('button[type=\"submit\"]')?.setAttribute(kAttrProcessing, '1');\n}\n\nexport function endFormProcessing(form: HTMLFormElement): void {\n getFormControls(form).forEach((el) => {\n if (readBoolAttribute(el, kAttrFormProcessing)) {\n (el as HTMLInputElement).disabled = false;\n\n el.removeAttribute(kAttrFormProcessing);\n }\n });\n\n form.querySelector('button[type=\"submit\"]')?.removeAttribute(kAttrProcessing);\n}\n\nexport function readInputValue(element: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement): string {\n return element.value;\n}\n\nexport function readCheckboxValue(input: HTMLInputElement): boolean {\n if (input.type !== 'checkbox') {\n throw new TypeError('Expected checkbox input');\n }\n\n return input.checked;\n}\n\nexport function readRadioValue(form: HTMLFormElement, name: string): string | null {\n const checked = form.querySelector<HTMLInputElement>(`input[type=\"radio\"][name=\"${name}\"]:checked`);\n\n return checked?.value ?? null;\n}\n\nexport function readNumberInput(element: HTMLInputElement): number | null {\n const value = element.value.trim();\n\n if (value === '') {\n return null;\n }\n\n const num = Number(value);\n\n return Number.isNaN(num) ? null : num;\n}\n\nexport function readBooleanInput(element: HTMLInputElement): boolean {\n return element.checked;\n}\n\nexport function readFileInput(input: HTMLInputElement): File | File[] | null {\n if (input.type !== 'file') {\n throw new TypeError('Expected file input');\n }\n\n const files = input.files;\n\n if (!files || files.length === 0) {\n return null;\n }\n\n if (input.multiple) {\n return Array.from(files);\n }\n\n return files[0] ?? null;\n}\n\nexport function readElementValue(element: Element): FormElementValue {\n if (element instanceof HTMLInputElement) {\n switch (element.type) {\n case 'checkbox':\n return readCheckboxValue(element);\n\n case 'number':\n return readNumberInput(element);\n\n case 'radio':\n if (!element.form || !element.name) {\n return null;\n }\n\n return readRadioValue(element.form, element.name);\n\n case 'file':\n return readFileInput(element);\n\n default:\n return readInputValue(element);\n }\n }\n\n if (element instanceof HTMLTextAreaElement) {\n return readInputValue(element);\n }\n\n if (element instanceof HTMLSelectElement) {\n return readInputValue(element);\n }\n\n return null;\n}\n\nexport function readFormData(form: HTMLFormElement): URLSearchParams;\nexport function readFormData<T extends OutputCtor>(form: HTMLFormElement, output: T): FormDataResult<T>;\n\nexport function readFormData(form: HTMLFormElement, output: OutputCtor = URLSearchParams): FormData | URLSearchParams {\n const result =\n output === FormData\n ? new FormData()\n : new URLSearchParams();\n\n const elements = Array.from(form.elements);\n\n const append = (target: FormData | URLSearchParams, key: string, value: string | number | boolean | File): void => {\n const v =\n typeof value === 'boolean'\n ? value ? '1' : '0'\n : typeof value === 'number'\n ? String(value)\n : value;\n\n if (target instanceof FormData) {\n target.append(key, v);\n } else {\n target.append(key, String(v));\n }\n };\n\n for (const el of elements) {\n if (el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) {\n if (!('name' in el)) {\n continue;\n }\n\n if (isDisabled(el)) {\n continue;\n }\n\n if (!el.name) {\n continue;\n }\n\n const value = readElementValue(el);\n\n if (value === null) {\n continue;\n }\n\n // File[]\n if (Array.isArray(value)) {\n for (const v of value) {\n append(result, el.name, v);\n }\n\n continue;\n }\n\n append(result, el.name, value);\n }\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function replaceHtmlString<T extends HTMLElement = HTMLElement>(element: T, replacements: Record<string, string>): T;
|
|
2
|
+
export declare function createElementFromHtml(html: string): HTMLElement;
|
|
3
|
+
export declare function replaceElement(element: Element, replacement: string): Element;
|
|
4
|
+
export declare function replaceElement<T extends Element = Element>(element: T, replacement: T): T;
|
package/dist/dom/html.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function replaceHtmlString(element, replacements) {
|
|
2
|
+
let html = element.outerHTML;
|
|
3
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
4
|
+
html = html.replaceAll(key, value);
|
|
5
|
+
}
|
|
6
|
+
const template = document.createElement('template');
|
|
7
|
+
template.innerHTML = html.trim();
|
|
8
|
+
const newElement = template.content.firstElementChild;
|
|
9
|
+
if (!(newElement instanceof HTMLElement)) {
|
|
10
|
+
throw new Error('replaceHtmlString: result is not HTMLElement');
|
|
11
|
+
}
|
|
12
|
+
if (newElement.tagName !== element.tagName) {
|
|
13
|
+
throw new Error(`replaceHtmlString: element tag changed from <${element.tagName.toLowerCase()}> to <${newElement.tagName.toLowerCase()}>`);
|
|
14
|
+
}
|
|
15
|
+
return newElement;
|
|
16
|
+
}
|
|
17
|
+
function createElementFromHtml(html) {
|
|
18
|
+
const template = document.createElement('template');
|
|
19
|
+
template.innerHTML = html.trim();
|
|
20
|
+
const element = template.content.firstElementChild;
|
|
21
|
+
if (!(element instanceof HTMLElement)) {
|
|
22
|
+
throw new Error('createElementFromHtml: HTML did not produce a HTMLElement');
|
|
23
|
+
}
|
|
24
|
+
return element;
|
|
25
|
+
}
|
|
26
|
+
function replaceElement(element, replacement) {
|
|
27
|
+
let newElement;
|
|
28
|
+
if (typeof replacement === 'string') {
|
|
29
|
+
newElement = createElementFromHtml(replacement);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
newElement = replacement;
|
|
33
|
+
}
|
|
34
|
+
element.replaceWith(newElement);
|
|
35
|
+
return newElement;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { createElementFromHtml, replaceElement, replaceHtmlString };
|
|
39
|
+
//# sourceMappingURL=html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sources":["../../src/dom/html.ts"],"sourcesContent":["export function replaceHtmlString<T extends HTMLElement = HTMLElement>(element: T, replacements: Record<string, string>): T {\n let html = element.outerHTML;\n\n for (const [key, value] of Object.entries(replacements)) {\n html = html.replaceAll(key, value);\n }\n\n const template = document.createElement('template');\n template.innerHTML = html.trim();\n\n const newElement = template.content.firstElementChild;\n\n if (!(newElement instanceof HTMLElement)) {\n throw new Error('replaceHtmlString: result is not HTMLElement');\n }\n\n if (newElement.tagName !== element.tagName) {\n throw new Error(`replaceHtmlString: element tag changed from <${element.tagName.toLowerCase()}> to <${newElement.tagName.toLowerCase()}>`);\n }\n\n return newElement as T;\n}\n\nexport function createElementFromHtml(html: string): HTMLElement {\n const template = document.createElement('template');\n template.innerHTML = html.trim();\n\n const element = template.content.firstElementChild;\n\n if (!(element instanceof HTMLElement)) {\n throw new Error('createElementFromHtml: HTML did not produce a HTMLElement');\n }\n\n return element;\n}\n\nexport function replaceElement(element: Element, replacement: string): Element;\nexport function replaceElement<T extends Element = Element>(element: T, replacement: T): T;\n\nexport function replaceElement(element: Element, replacement: Element | string): Element {\n let newElement: Element;\n\n if (typeof replacement === 'string') {\n newElement = createElementFromHtml(replacement);\n } else {\n newElement = replacement;\n }\n\n element.replaceWith(newElement);\n\n return newElement;\n}"],"names":[],"mappings":"AAAM,SAAU,iBAAiB,CAAsC,OAAU,EAAE,YAAoC,EAAA;AACnH,IAAA,IAAI,IAAI,GAAG,OAAO,CAAC,SAAS;AAE5B,IAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;QACrD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC;IACtC;IAEA,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC;AACnD,IAAA,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE;AAEhC,IAAA,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,iBAAiB;AAErD,IAAA,IAAI,EAAE,UAAU,YAAY,WAAW,CAAC,EAAE;AACtC,QAAA,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC;IACnE;IAEA,IAAI,UAAU,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE;AACxC,QAAA,MAAM,IAAI,KAAK,CAAC,gDAAgD,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA,MAAA,EAAS,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA,CAAA,CAAG,CAAC;IAC9I;AAEA,IAAA,OAAO,UAAe;AAC1B;AAEM,SAAU,qBAAqB,CAAC,IAAY,EAAA;IAC9C,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC;AACnD,IAAA,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE;AAEhC,IAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,iBAAiB;AAElD,IAAA,IAAI,EAAE,OAAO,YAAY,WAAW,CAAC,EAAE;AACnC,QAAA,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC;IAChF;AAEA,IAAA,OAAO,OAAO;AAClB;AAKM,SAAU,cAAc,CAAC,OAAgB,EAAE,WAA6B,EAAA;AAC1E,IAAA,IAAI,UAAmB;AAEvB,IAAA,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE;AACjC,QAAA,UAAU,GAAG,qBAAqB,CAAC,WAAW,CAAC;IACnD;SAAO;QACH,UAAU,GAAG,WAAW;IAC5B;AAEA,IAAA,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC;AAE/B,IAAA,OAAO,UAAU;AACrB;;;;"}
|
package/dist/dom/index.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ export * from './attributes';
|
|
|
2
2
|
export * from './changes';
|
|
3
3
|
export * from './classes';
|
|
4
4
|
export * from './events';
|
|
5
|
+
export * from './form';
|
|
6
|
+
export * from './html';
|
|
5
7
|
export * from './ready';
|
|
6
8
|
export * from './state';
|
|
9
|
+
export * from './text';
|
|
10
|
+
export * from './textarea';
|
|
7
11
|
export * from './visibility';
|
package/dist/dom/index.js
CHANGED
|
@@ -2,7 +2,11 @@ export { readBoolAttribute, readStringAttribute } from './attributes.js';
|
|
|
2
2
|
export { onDomChanges } from './changes.js';
|
|
3
3
|
export { addClass, removeClass } from './classes.js';
|
|
4
4
|
export { onDomEvents } from './events.js';
|
|
5
|
+
export { endFormProcessing, readBooleanInput, readCheckboxValue, readElementValue, readFileInput, readFormData, readInputValue, readNumberInput, readRadioValue, startFormProcessing } from './form.js';
|
|
6
|
+
export { createElementFromHtml, replaceElement, replaceHtmlString } from './html.js';
|
|
5
7
|
export { onDomReady } from './ready.js';
|
|
6
8
|
export { disableElement, enableElement, isDisabled } from './state.js';
|
|
9
|
+
export { animateEllipsis } from './text.js';
|
|
10
|
+
export { applyTextareaAutoResize } from './textarea.js';
|
|
7
11
|
export { hideElement, showElement } from './visibility.js';
|
|
8
12
|
//# sourceMappingURL=index.js.map
|
package/dist/dom/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
package/dist/dom/text.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function animateEllipsis(element, options) {
|
|
2
|
+
const maxDots = options?.maxDots ?? 3;
|
|
3
|
+
const interval = options?.interval ?? 250;
|
|
4
|
+
let dots = 0;
|
|
5
|
+
let timer = null;
|
|
6
|
+
const dotsContainer = document.createElement('span');
|
|
7
|
+
dotsContainer.setAttribute('aria-hidden', 'true');
|
|
8
|
+
const dotsElements = [];
|
|
9
|
+
for (let i = 0; i < maxDots; i++) {
|
|
10
|
+
const dot = document.createElement('span');
|
|
11
|
+
dot.textContent = '.';
|
|
12
|
+
dot.style.visibility = 'hidden';
|
|
13
|
+
dotsContainer.appendChild(dot);
|
|
14
|
+
dotsElements.push(dot);
|
|
15
|
+
}
|
|
16
|
+
element.appendChild(dotsContainer);
|
|
17
|
+
const tick = () => {
|
|
18
|
+
if (!element.isConnected) {
|
|
19
|
+
stop();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
dots = (dots + 1) % (maxDots + 1);
|
|
23
|
+
dotsElements.forEach((dot, index) => {
|
|
24
|
+
dot.style.visibility = index < dots ? 'visible' : 'hidden';
|
|
25
|
+
});
|
|
26
|
+
timer = window.setTimeout(tick, interval);
|
|
27
|
+
};
|
|
28
|
+
const stop = () => {
|
|
29
|
+
if (timer !== null) {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
timer = null;
|
|
32
|
+
}
|
|
33
|
+
dotsContainer.remove();
|
|
34
|
+
};
|
|
35
|
+
tick();
|
|
36
|
+
return stop;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { animateEllipsis };
|
|
40
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sources":["../../src/dom/text.ts"],"sourcesContent":["type AnimateEllipsisOptions = {\n maxDots?: number;\n interval?: number;\n}\n\nexport function animateEllipsis(element: HTMLElement, options?: AnimateEllipsisOptions): () => void {\n const maxDots = options?.maxDots ?? 3;\n const interval = options?.interval ?? 250;\n\n let dots = 0;\n let timer: number | null = null;\n\n const dotsContainer = document.createElement('span');\n dotsContainer.setAttribute('aria-hidden', 'true');\n\n const dotsElements: HTMLSpanElement[] = [];\n\n for (let i = 0; i < maxDots; i++) {\n const dot = document.createElement('span');\n dot.textContent = '.';\n dot.style.visibility = 'hidden';\n dotsContainer.appendChild(dot);\n dotsElements.push(dot);\n }\n\n element.appendChild(dotsContainer);\n\n const tick = () => {\n if (!element.isConnected) {\n stop();\n\n return;\n }\n\n dots = (dots + 1) % (maxDots + 1);\n\n dotsElements.forEach((dot, index) => {\n dot.style.visibility = index < dots ? 'visible' : 'hidden';\n });\n\n timer = window.setTimeout(tick, interval);\n };\n\n const stop = () => {\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n dotsContainer.remove();\n };\n\n tick();\n\n return stop;\n}\n"],"names":[],"mappings":"AAKM,SAAU,eAAe,CAAC,OAAoB,EAAE,OAAgC,EAAA;AAClF,IAAA,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,CAAC;AACrC,IAAA,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,GAAG;IAEzC,IAAI,IAAI,GAAG,CAAC;IACZ,IAAI,KAAK,GAAkB,IAAI;IAE/B,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC;AACpD,IAAA,aAAa,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC;IAEjD,MAAM,YAAY,GAAsB,EAAE;AAE1C,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC;AAC1C,QAAA,GAAG,CAAC,WAAW,GAAG,GAAG;AACrB,QAAA,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ;AAC/B,QAAA,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC;AAC9B,QAAA,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;IAC1B;AAEA,IAAA,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC;IAElC,MAAM,IAAI,GAAG,MAAK;AACd,QAAA,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;AACtB,YAAA,IAAI,EAAE;YAEN;QACJ;AAEA,QAAA,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC;QAEjC,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,KAAI;AAChC,YAAA,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ;AAC9D,QAAA,CAAC,CAAC;QAEF,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC;AAC7C,IAAA,CAAC;IAED,MAAM,IAAI,GAAG,MAAK;AACd,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;YAChB,YAAY,CAAC,KAAK,CAAC;YACnB,KAAK,GAAG,IAAI;QAChB;QAEA,aAAa,CAAC,MAAM,EAAE;AAC1B,IAAA,CAAC;AAED,IAAA,IAAI,EAAE;AAEN,IAAA,OAAO,IAAI;AACf;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function applyTextareaAutoResize(textarea: HTMLTextAreaElement, maxRows?: number): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { kAttrMaxRows } from '../core/constants.js';
|
|
2
|
+
|
|
3
|
+
function applyTextareaAutoResize(textarea, maxRows = 4) {
|
|
4
|
+
const computed = window.getComputedStyle(textarea);
|
|
5
|
+
const attr = textarea.getAttribute(kAttrMaxRows);
|
|
6
|
+
const limit = attr ? Number.parseInt(attr, 10) : maxRows;
|
|
7
|
+
const fontSize = Number.parseFloat(computed.fontSize) || 16;
|
|
8
|
+
const lineHeight = computed.lineHeight === 'normal' ? fontSize * 1.2 : Number.parseFloat(computed.lineHeight);
|
|
9
|
+
const paddingY = (Number.parseFloat(computed.paddingTop) || 0) +
|
|
10
|
+
(Number.parseFloat(computed.paddingBottom) || 0);
|
|
11
|
+
const lines = Math.max(1, textarea.value.split('\n').length);
|
|
12
|
+
const visibleLines = Math.min(lines, Number.isFinite(limit) ? limit : maxRows);
|
|
13
|
+
textarea.style.height = `${lineHeight * visibleLines + paddingY}px`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { applyTextareaAutoResize };
|
|
17
|
+
//# sourceMappingURL=textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textarea.js","sources":["../../src/dom/textarea.ts"],"sourcesContent":["import { kAttrMaxRows } from '../core/constants';\n\nexport function applyTextareaAutoResize(textarea: HTMLTextAreaElement, maxRows: number = 4): void {\n const computed = window.getComputedStyle(textarea);\n\n const attr = textarea.getAttribute(kAttrMaxRows);\n const limit = attr ? Number.parseInt(attr, 10) : maxRows;\n\n const fontSize = Number.parseFloat(computed.fontSize) || 16;\n const lineHeight = computed.lineHeight === 'normal' ? fontSize * 1.2 : Number.parseFloat(computed.lineHeight);\n\n const paddingY =\n (Number.parseFloat(computed.paddingTop) || 0) +\n (Number.parseFloat(computed.paddingBottom) || 0);\n\n const lines = Math.max(1, textarea.value.split('\\n').length);\n const visibleLines = Math.min(lines, Number.isFinite(limit) ? limit : maxRows);\n\n textarea.style.height = `${lineHeight * visibleLines + paddingY}px`;\n}\n"],"names":[],"mappings":";;SAEgB,uBAAuB,CAAC,QAA6B,EAAE,UAAkB,CAAC,EAAA;IACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC;IAElD,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC,YAAY,CAAC;AAChD,IAAA,MAAM,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,OAAO;AAExD,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;IAC3D,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,KAAK,QAAQ,GAAG,QAAQ,GAAG,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;AAE7G,IAAA,MAAM,QAAQ,GACV,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;SAC3C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAEpD,IAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC;AAE9E,IAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAA,EAAG,UAAU,GAAG,YAAY,GAAG,QAAQ,CAAA,EAAA,CAAI;AACvE;;;;"}
|
package/package.json
CHANGED
|
@@ -1,27 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fivelab/web-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The helpers for easy manipulate with dom.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"exports": {
|
|
9
|
-
"./
|
|
10
|
-
"types": "./dist/
|
|
11
|
-
"import": "./dist/
|
|
9
|
+
"./browser": {
|
|
10
|
+
"types": "./dist/browser/index.d.ts",
|
|
11
|
+
"import": "./dist/browser/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./browser/*": {
|
|
14
|
+
"types": "./dist/browser/*.d.ts",
|
|
15
|
+
"import": "./dist/browser/*.js"
|
|
16
|
+
},
|
|
17
|
+
"./behaviors": {
|
|
18
|
+
"types": "./dist/behaviors/index.d.ts",
|
|
19
|
+
"import": "./dist/behaviors/index.js"
|
|
12
20
|
},
|
|
13
21
|
"./behaviors/*": {
|
|
14
22
|
"types": "./dist/behaviors/*.d.ts",
|
|
15
23
|
"import": "./dist/behaviors/*.js"
|
|
16
24
|
},
|
|
17
|
-
"./
|
|
18
|
-
"types": "./dist/
|
|
19
|
-
"import": "./dist/
|
|
25
|
+
"./core": {
|
|
26
|
+
"types": "./dist/core/index.d.ts",
|
|
27
|
+
"import": "./dist/core/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./core/*": {
|
|
30
|
+
"types": "./dist/core/*.d.ts",
|
|
31
|
+
"import": "./dist/core/*.js"
|
|
32
|
+
},
|
|
33
|
+
"./dom": {
|
|
34
|
+
"types": "./dist/dom/index.d.ts",
|
|
35
|
+
"import": "./dist/dom/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./dom/*": {
|
|
38
|
+
"types": "./dist/dom/*.d.ts",
|
|
39
|
+
"import": "./dist/dom/*.js"
|
|
40
|
+
},
|
|
41
|
+
"./observability": {
|
|
42
|
+
"types": "./dist/observability/index.d.ts",
|
|
43
|
+
"import": "./dist/observability/index.js"
|
|
20
44
|
},
|
|
21
45
|
"./observability/*": {
|
|
22
46
|
"types": "./dist/observability/*.d.ts",
|
|
23
47
|
"import": "./dist/observability/*.js"
|
|
24
48
|
},
|
|
49
|
+
"./ui": {
|
|
50
|
+
"types": "./dist/ui/index.d.ts",
|
|
51
|
+
"import": "./dist/ui/index.js"
|
|
52
|
+
},
|
|
25
53
|
"./ui/*": {
|
|
26
54
|
"types": "./dist/ui/*.d.ts",
|
|
27
55
|
"import": "./dist/ui/*.js"
|
|
@@ -47,9 +75,20 @@
|
|
|
47
75
|
"vitest": "~4.0"
|
|
48
76
|
},
|
|
49
77
|
"peerDependencies": {
|
|
50
|
-
"@sentry/browser": "^10.
|
|
51
|
-
"toastr": "^2.
|
|
52
|
-
"notyf": "^3.
|
|
78
|
+
"@sentry/browser": "^10.0",
|
|
79
|
+
"toastr": "^2.0",
|
|
80
|
+
"notyf": "^3.0"
|
|
81
|
+
},
|
|
82
|
+
"peerDependenciesMeta": {
|
|
83
|
+
"@sentry/browser": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"toastr": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"notyf": {
|
|
90
|
+
"optional": true
|
|
91
|
+
}
|
|
53
92
|
},
|
|
54
93
|
"scripts": {
|
|
55
94
|
"clean": "rm -rf dist/*",
|