@windwalker-io/unicorn-next 0.1.18 → 0.1.21
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/chunks/_arrayPush.js +325 -108
- package/dist/chunks/_arrayPush.js.map +1 -1
- package/dist/chunks/_baseRest.js +155 -60
- package/dist/chunks/_baseRest.js.map +1 -1
- package/dist/chunks/_baseUnary.js +463 -0
- package/dist/chunks/_baseUnary.js.map +1 -0
- package/dist/chunks/_getPrototype.js +292 -100
- package/dist/chunks/_getPrototype.js.map +1 -1
- package/dist/chunks/alert-adapter.js +29 -0
- package/dist/chunks/alert-adapter.js.map +1 -0
- package/dist/chunks/alert.js +21 -0
- package/dist/chunks/alert.js.map +1 -0
- package/dist/chunks/arr.js +24 -0
- package/dist/chunks/arr.js.map +1 -0
- package/dist/chunks/button-radio.js +127 -145
- package/dist/chunks/button-radio.js.map +1 -1
- package/dist/chunks/checkboxes-multi-select.js +44 -43
- package/dist/chunks/checkboxes-multi-select.js.map +1 -1
- package/dist/chunks/chunk.js +24 -0
- package/dist/chunks/cloneDeep.js +679 -212
- package/dist/chunks/cloneDeep.js.map +1 -1
- package/dist/chunks/cropper.min.js +6 -5
- package/dist/chunks/cropper.min.js.map +1 -1
- package/dist/chunks/crypto.js +26 -0
- package/dist/chunks/crypto.js.map +1 -0
- package/dist/chunks/data.js +49 -0
- package/dist/chunks/data.js.map +1 -0
- package/dist/chunks/dom.js +128 -0
- package/dist/chunks/dom.js.map +1 -0
- package/dist/chunks/events.js +270 -0
- package/dist/chunks/events.js.map +1 -0
- package/dist/chunks/field-cascade-select.js +207 -250
- package/dist/chunks/field-cascade-select.js.map +1 -1
- package/dist/chunks/field-file-drag.js +175 -209
- package/dist/chunks/field-file-drag.js.map +1 -1
- package/dist/chunks/field-flatpickr.js +94 -898
- package/dist/chunks/field-flatpickr.js.map +1 -1
- package/dist/chunks/field-modal-select.js +728 -467
- package/dist/chunks/field-modal-select.js.map +1 -1
- package/dist/chunks/field-modal-tree.js +771 -766
- package/dist/chunks/field-modal-tree.js.map +1 -1
- package/dist/chunks/field-multi-uploader.js +249 -256
- package/dist/chunks/field-multi-uploader.js.map +1 -1
- package/dist/chunks/field-repeatable.js +111 -127
- package/dist/chunks/field-repeatable.js.map +1 -1
- package/dist/chunks/field-single-image-drag.js +286 -338
- package/dist/chunks/field-single-image-drag.js.map +1 -1
- package/dist/chunks/form.js +146 -159
- package/dist/chunks/form.js.map +1 -1
- package/dist/chunks/grid.js +349 -418
- package/dist/chunks/grid.js.map +1 -1
- package/dist/chunks/helper.js +39 -0
- package/dist/chunks/helper.js.map +1 -0
- package/dist/chunks/http-client.js +221 -211
- package/dist/chunks/http-client.js.map +1 -1
- package/dist/chunks/iframe-modal.js +95 -115
- package/dist/chunks/iframe-modal.js.map +1 -1
- package/dist/chunks/keep-tab.js +92 -101
- package/dist/chunks/keep-tab.js.map +1 -1
- package/dist/chunks/lang.js +250 -0
- package/dist/chunks/lang.js.map +1 -0
- package/dist/chunks/legacy.js +197 -201
- package/dist/chunks/legacy.js.map +1 -1
- package/dist/chunks/list-dependent.js +195 -228
- package/dist/chunks/list-dependent.js.map +1 -1
- package/dist/chunks/loader.js +106 -0
- package/dist/chunks/loader.js.map +1 -0
- package/dist/chunks/monthSelect.js +251 -0
- package/dist/chunks/monthSelect.js.map +1 -0
- package/dist/chunks/router.js +111 -0
- package/dist/chunks/router.js.map +1 -0
- package/dist/chunks/s3-multipart-uploader.js +183 -210
- package/dist/chunks/s3-multipart-uploader.js.map +1 -1
- package/dist/chunks/s3-uploader.js +106 -128
- package/dist/chunks/s3-uploader.js.map +1 -1
- package/dist/chunks/show-on.js +358 -205
- package/dist/chunks/show-on.js.map +1 -1
- package/dist/chunks/timing.js +10 -0
- package/dist/chunks/timing.js.map +1 -0
- package/dist/chunks/tinymce.js +153 -203
- package/dist/chunks/tinymce.js.map +1 -1
- package/dist/chunks/ui-bootstrap5.js +58 -72
- package/dist/chunks/ui-bootstrap5.js.map +1 -1
- package/dist/chunks/ui.js +320 -0
- package/dist/chunks/ui.js.map +1 -0
- package/dist/chunks/unicorn.js.map +1 -1
- package/dist/chunks/useQueue.js +111 -0
- package/dist/chunks/useQueue.js.map +1 -0
- package/dist/chunks/useStack.js +76 -0
- package/dist/chunks/useStack.js.map +1 -0
- package/dist/chunks/validation.js +761 -853
- package/dist/chunks/validation.js.map +1 -1
- package/dist/editor.css +1 -1
- package/dist/index.d.ts +27 -15
- package/dist/multi-level-menu.css +1 -1
- package/dist/switcher.css +1 -1
- package/dist/unicorn.js +805 -130
- package/dist/unicorn.js.map +1 -1
- package/package.json +3 -3
- package/src/composable/useBsModalAlert.ts +92 -12
- package/src/composable/useHttp.ts +13 -1
- package/src/module/s3-uploader.ts +1 -1
- package/src/service/ui.ts +31 -15
- package/vite.config.ts +5 -1
- package/dist/chunks/_commonjsHelpers.js +0 -7
- package/dist/chunks/index.js +0 -314
- package/dist/chunks/isArguments.js +0 -146
- package/dist/chunks/unicorn.js +0 -2580
|
@@ -1,78 +1,64 @@
|
|
|
1
|
+
import { d as selectOne, o as html, u as selectAll } from "./dom.js";
|
|
2
|
+
import { i as uid } from "./crypto.js";
|
|
1
3
|
import * as bootstrap from "bootstrap";
|
|
2
4
|
import { Tooltip } from "bootstrap";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
const msgHtml = html(`<div id="${id}" class="alert alert-${type} alert-dismissible fade show" role="alert">
|
|
5
|
+
//#region src/module/ui-bootstrap5.ts
|
|
6
|
+
var UIBootstrap5 = class {
|
|
7
|
+
static instance = null;
|
|
8
|
+
bootstrap = bootstrap;
|
|
9
|
+
static get() {
|
|
10
|
+
return this.instance ??= new this();
|
|
11
|
+
}
|
|
12
|
+
renderMessage(messages, type = "info") {
|
|
13
|
+
if (!Array.isArray(messages)) messages = [messages];
|
|
14
|
+
let text = "";
|
|
15
|
+
const id = "uni-msg-" + uid();
|
|
16
|
+
messages.forEach((msg) => {
|
|
17
|
+
text += `<div class="">${msg}</div>`;
|
|
18
|
+
});
|
|
19
|
+
const msgHtml = html(`<div id="${id}" class="alert alert-${type} alert-dismissible fade show" role="alert">
|
|
20
20
|
${text}
|
|
21
21
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
22
22
|
</div>`);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (selector instanceof NodeList) {
|
|
61
|
-
return Array.from(selector);
|
|
62
|
-
} else if (typeof selector === "string") {
|
|
63
|
-
return selectAll(selector);
|
|
64
|
-
} else {
|
|
65
|
-
return [selector];
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
getMajorVersion(module) {
|
|
69
|
-
return Number(module.VERSION.split(".").shift());
|
|
70
|
-
}
|
|
71
|
-
pushBootstrapToGlobal() {
|
|
72
|
-
window.bootstrap = bootstrap;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
export {
|
|
76
|
-
UIBootstrap5
|
|
23
|
+
const container = selectOne(".c-messages-container");
|
|
24
|
+
if (container) container.appendChild(msgHtml);
|
|
25
|
+
return () => {
|
|
26
|
+
const ele = document.getElementById(id);
|
|
27
|
+
if (ele) ele.remove();
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
clearMessages() {
|
|
31
|
+
const container = selectOne(".c-messages-container");
|
|
32
|
+
if (container) container.innerHTML = "";
|
|
33
|
+
}
|
|
34
|
+
async keepTab(selector, options = {}) {
|
|
35
|
+
const module = await import("./keep-tab.js");
|
|
36
|
+
await module.ready;
|
|
37
|
+
if (selector) return new module.KeepTab(selector, options);
|
|
38
|
+
return module;
|
|
39
|
+
}
|
|
40
|
+
async buttonRadio(selector, options = {}) {
|
|
41
|
+
const m = await import("./button-radio.js");
|
|
42
|
+
await m.ready;
|
|
43
|
+
if (selector) return m.ButtonRadio.handle(selector, options);
|
|
44
|
+
return m;
|
|
45
|
+
}
|
|
46
|
+
tooltip(selector = "[data-bs-toggle=\"tooltip\"]", config = {}) {
|
|
47
|
+
return this.selectAsArray(selector).map((ele) => Tooltip.getOrCreateInstance(ele, config));
|
|
48
|
+
}
|
|
49
|
+
selectAsArray(selector) {
|
|
50
|
+
if (selector instanceof NodeList) return Array.from(selector);
|
|
51
|
+
else if (typeof selector === "string") return selectAll(selector);
|
|
52
|
+
else return [selector];
|
|
53
|
+
}
|
|
54
|
+
getMajorVersion(module) {
|
|
55
|
+
return Number(module.VERSION.split(".").shift());
|
|
56
|
+
}
|
|
57
|
+
pushBootstrapToGlobal() {
|
|
58
|
+
window.bootstrap = bootstrap;
|
|
59
|
+
}
|
|
77
60
|
};
|
|
78
|
-
//#
|
|
61
|
+
//#endregion
|
|
62
|
+
export { UIBootstrap5 };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=ui-bootstrap5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-bootstrap5.js","sources":["../../src/module/ui-bootstrap5.ts"],"sourcesContent":["import * as bootstrap from 'bootstrap';\nimport { Tooltip } from 'bootstrap';\nimport type { ButtonRadio, ButtonRadioModule, ButtonRadioOptions } from '../bootstrap/button-radio';\nimport type { KeepTab, KeepTabModule, KeepTabOptions } from '../bootstrap/keep-tab';\nimport { html, selectAll, selectOne, uid } from '../service';\nimport type { UIThemeInterface } from '../types';\n\nexport class UIBootstrap5 implements UIThemeInterface {\n static instance: UIBootstrap5 | null = null;\n\n bootstrap = bootstrap;\n\n static get() {\n return this.instance ??= new this();\n }\n\n renderMessage(messages: string | string[], type: string = 'info'): () => void {\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n\n let text = '';\n const id = 'uni-msg-' + uid();\n\n messages.forEach((msg) => {\n text += `<div class=\"\">${msg}</div>`;\n });\n\n const msgHtml = html(`<div id=\"${id}\" class=\"alert alert-${type} alert-dismissible fade show\" role=\"alert\">\n ${text}\n <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>\n</div>`);\n\n const container = selectOne('.c-messages-container');\n\n if (container) {\n container.appendChild(msgHtml);\n }\n\n return () => {\n const ele = document.getElementById(id);\n\n if (ele) {\n ele.remove();\n }\n }\n }\n\n clearMessages() {\n const container = selectOne('.c-messages-container');\n\n if (container) {\n container.innerHTML = '';\n }\n }\n\n async keepTab(): Promise<KeepTabModule>;\n async keepTab(selector?: string | HTMLElement, options?: KeepTabOptions): Promise<KeepTab>;\n async keepTab(selector?: string | HTMLElement, options: KeepTabOptions = {}): Promise<any> {\n const module = await import('../bootstrap/keep-tab');\n\n await module.ready;\n\n if (selector) {\n return new module.KeepTab(selector, options);\n }\n\n return module;\n }\n\n async buttonRadio(): Promise<ButtonRadioModule>;\n async buttonRadio(selector?: string | HTMLElement, options?: ButtonRadioOptions): Promise<ButtonRadio>;\n async buttonRadio(selector?: string | HTMLElement, options: ButtonRadioOptions = {}): Promise<any> {\n const m = await import('../bootstrap/button-radio');\n\n await m.ready;\n\n if (selector) {\n return m.ButtonRadio.handle(selector, options);\n }\n\n return m;\n }\n\n tooltip(\n selector: NodeListOf<Element> | Element | string = '[data-bs-toggle=\"tooltip\"]',\n config: Partial<Tooltip.Options> = {}\n ): Tooltip[] {\n return this.selectAsArray(selector)\n .map((ele) => Tooltip.getOrCreateInstance(ele, config));\n }\n\n protected selectAsArray(selector: NodeListOf<Element> | Element | string) {\n if (selector instanceof NodeList) {\n return Array.from(selector);\n } else if (typeof selector === 'string') {\n return selectAll(selector);\n } else {\n return [selector];\n }\n }\n\n getMajorVersion(module: any) {\n return Number(module.VERSION.split('.').shift());\n }\n\n pushBootstrapToGlobal() {\n window.bootstrap = bootstrap;\n }\n}\n\ndeclare global {\n export interface Window {\n bootstrap: typeof bootstrap;\n }\n}\n"],"
|
|
1
|
+
{"version":3,"file":"ui-bootstrap5.js","names":[],"sources":["../../src/module/ui-bootstrap5.ts"],"sourcesContent":["import * as bootstrap from 'bootstrap';\nimport { Tooltip } from 'bootstrap';\nimport type { ButtonRadio, ButtonRadioModule, ButtonRadioOptions } from '../bootstrap/button-radio';\nimport type { KeepTab, KeepTabModule, KeepTabOptions } from '../bootstrap/keep-tab';\nimport { html, selectAll, selectOne, uid } from '../service';\nimport type { UIThemeInterface } from '../types';\n\nexport class UIBootstrap5 implements UIThemeInterface {\n static instance: UIBootstrap5 | null = null;\n\n bootstrap = bootstrap;\n\n static get() {\n return this.instance ??= new this();\n }\n\n renderMessage(messages: string | string[], type: string = 'info'): () => void {\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n\n let text = '';\n const id = 'uni-msg-' + uid();\n\n messages.forEach((msg) => {\n text += `<div class=\"\">${msg}</div>`;\n });\n\n const msgHtml = html(`<div id=\"${id}\" class=\"alert alert-${type} alert-dismissible fade show\" role=\"alert\">\n ${text}\n <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>\n</div>`);\n\n const container = selectOne('.c-messages-container');\n\n if (container) {\n container.appendChild(msgHtml);\n }\n\n return () => {\n const ele = document.getElementById(id);\n\n if (ele) {\n ele.remove();\n }\n }\n }\n\n clearMessages() {\n const container = selectOne('.c-messages-container');\n\n if (container) {\n container.innerHTML = '';\n }\n }\n\n async keepTab(): Promise<KeepTabModule>;\n async keepTab(selector?: string | HTMLElement, options?: KeepTabOptions): Promise<KeepTab>;\n async keepTab(selector?: string | HTMLElement, options: KeepTabOptions = {}): Promise<any> {\n const module = await import('../bootstrap/keep-tab');\n\n await module.ready;\n\n if (selector) {\n return new module.KeepTab(selector, options);\n }\n\n return module;\n }\n\n async buttonRadio(): Promise<ButtonRadioModule>;\n async buttonRadio(selector?: string | HTMLElement, options?: ButtonRadioOptions): Promise<ButtonRadio>;\n async buttonRadio(selector?: string | HTMLElement, options: ButtonRadioOptions = {}): Promise<any> {\n const m = await import('../bootstrap/button-radio');\n\n await m.ready;\n\n if (selector) {\n return m.ButtonRadio.handle(selector, options);\n }\n\n return m;\n }\n\n tooltip(\n selector: NodeListOf<Element> | Element | string = '[data-bs-toggle=\"tooltip\"]',\n config: Partial<Tooltip.Options> = {}\n ): Tooltip[] {\n return this.selectAsArray(selector)\n .map((ele) => Tooltip.getOrCreateInstance(ele, config));\n }\n\n protected selectAsArray(selector: NodeListOf<Element> | Element | string) {\n if (selector instanceof NodeList) {\n return Array.from(selector);\n } else if (typeof selector === 'string') {\n return selectAll(selector);\n } else {\n return [selector];\n }\n }\n\n getMajorVersion(module: any) {\n return Number(module.VERSION.split('.').shift());\n }\n\n pushBootstrapToGlobal() {\n window.bootstrap = bootstrap;\n }\n}\n\ndeclare global {\n export interface Window {\n bootstrap: typeof bootstrap;\n }\n}\n"],"mappings":";;;;;AAOA,IAAa,eAAb,MAAsD;CACpD,OAAO,WAAgC;CAEvC,YAAY;CAEZ,OAAO,MAAM;AACX,SAAO,KAAK,aAAa,IAAI,MAAM;;CAGrC,cAAc,UAA6B,OAAe,QAAoB;AAC5E,MAAI,CAAC,MAAM,QAAQ,SAAS,CAC1B,YAAW,CAAC,SAAS;EAGvB,IAAI,OAAO;EACX,MAAM,KAAK,aAAa,KAAK;AAE7B,WAAS,SAAS,QAAQ;AACxB,WAAQ,iBAAiB,IAAI;IAC7B;EAEF,MAAM,UAAU,KAAK,YAAY,GAAG,uBAAuB,KAAK;IAChE,KAAK;;QAED;EAEJ,MAAM,YAAY,UAAU,wBAAwB;AAEpD,MAAI,UACF,WAAU,YAAY,QAAQ;AAGhC,eAAa;GACX,MAAM,MAAM,SAAS,eAAe,GAAG;AAEvC,OAAI,IACF,KAAI,QAAQ;;;CAKlB,gBAAgB;EACd,MAAM,YAAY,UAAU,wBAAwB;AAEpD,MAAI,UACF,WAAU,YAAY;;CAM1B,MAAM,QAAQ,UAAiC,UAA0B,EAAE,EAAgB;EACzF,MAAM,SAAS,MAAM,OAAO;AAE5B,QAAM,OAAO;AAEb,MAAI,SACF,QAAO,IAAI,OAAO,QAAQ,UAAU,QAAQ;AAG9C,SAAO;;CAKT,MAAM,YAAY,UAAiC,UAA8B,EAAE,EAAgB;EACjG,MAAM,IAAI,MAAM,OAAO;AAEvB,QAAM,EAAE;AAER,MAAI,SACF,QAAO,EAAE,YAAY,OAAO,UAAU,QAAQ;AAGhD,SAAO;;CAGT,QACE,WAAmD,gCACnD,SAAmC,EAAE,EAC1B;AACX,SAAO,KAAK,cAAc,SAAS,CAChC,KAAK,QAAQ,QAAQ,oBAAoB,KAAK,OAAO,CAAC;;CAG3D,cAAwB,UAAkD;AACxE,MAAI,oBAAoB,SACtB,QAAO,MAAM,KAAK,SAAS;WAClB,OAAO,aAAa,SAC7B,QAAO,UAAU,SAAS;MAE1B,QAAO,CAAC,SAAS;;CAIrB,gBAAgB,QAAa;AAC3B,SAAO,OAAO,OAAO,QAAQ,MAAM,IAAI,CAAC,OAAO,CAAC;;CAGlD,wBAAwB;AACtB,SAAO,YAAY"}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { n as removeData, t as data } from "./data.js";
|
|
2
|
+
import { c as module, d as selectOne, o as html, u as selectAll } from "./dom.js";
|
|
3
|
+
import { t as AlertAdapter } from "./alert-adapter.js";
|
|
4
|
+
import { n as useStack } from "./useStack.js";
|
|
5
|
+
import { a as nextTick } from "./helper.js";
|
|
6
|
+
import { i as useImport, n as useCssImport } from "./loader.js";
|
|
7
|
+
//#region src/service/animate.ts
|
|
8
|
+
function animateTo(element, styles, options = {}) {
|
|
9
|
+
element = selectOne(element);
|
|
10
|
+
const currentStyles = window.getComputedStyle(element);
|
|
11
|
+
const transitions = {};
|
|
12
|
+
for (const name in styles) {
|
|
13
|
+
const value = styles[name];
|
|
14
|
+
transitions[name] = Array.isArray(value) ? value : [currentStyles.getPropertyValue(name), value];
|
|
15
|
+
}
|
|
16
|
+
if (typeof options === "number") options = { duration: options };
|
|
17
|
+
options = Object.assign({
|
|
18
|
+
duration: 400,
|
|
19
|
+
easing: "linear",
|
|
20
|
+
fill: "both"
|
|
21
|
+
}, options);
|
|
22
|
+
const animation = element.animate(transitions, options);
|
|
23
|
+
animation.addEventListener("finish", () => {
|
|
24
|
+
for (const name in styles) {
|
|
25
|
+
const value = styles[name];
|
|
26
|
+
element.style.setProperty(name, Array.isArray(value) ? value[value.length - 1] : value);
|
|
27
|
+
}
|
|
28
|
+
animation.cancel();
|
|
29
|
+
});
|
|
30
|
+
return animation;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region ../../../../node_modules/@lyrasoft/ts-toolkit/src/generic/promise.ts
|
|
34
|
+
function promiseWithResolvers() {
|
|
35
|
+
let resolve;
|
|
36
|
+
let reject;
|
|
37
|
+
return {
|
|
38
|
+
promise: new Promise((rs, rj) => {
|
|
39
|
+
resolve = rs;
|
|
40
|
+
reject = rj;
|
|
41
|
+
}),
|
|
42
|
+
resolve,
|
|
43
|
+
reject
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/service/ui.ts
|
|
48
|
+
var ui;
|
|
49
|
+
AlertAdapter.alert = (title, text = "", type = "info") => {
|
|
50
|
+
if (text) title += " | " + text;
|
|
51
|
+
window.alert(title);
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
};
|
|
54
|
+
AlertAdapter.confirm = (message, text = "", type = "info") => {
|
|
55
|
+
message = message || "Are you sure?";
|
|
56
|
+
if (text) message += " | " + text;
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
resolve(window.confirm(message));
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
AlertAdapter.notify = async (title, text, type = "log") => {
|
|
62
|
+
if (text) title += " | " + text;
|
|
63
|
+
return ui.theme?.renderMessage(title, type) ?? (() => null);
|
|
64
|
+
};
|
|
65
|
+
AlertAdapter.clearNotifies = async () => {
|
|
66
|
+
ui.theme?.clearMessages();
|
|
67
|
+
};
|
|
68
|
+
AlertAdapter.confirmText = () => "OK";
|
|
69
|
+
AlertAdapter.cancelText = () => "Cancel";
|
|
70
|
+
AlertAdapter.deleteText = () => "Delete";
|
|
71
|
+
function useAlertAdapter(config) {
|
|
72
|
+
if (config) Object.assign(AlertAdapter, config);
|
|
73
|
+
return AlertAdapter;
|
|
74
|
+
}
|
|
75
|
+
function useUI(instance) {
|
|
76
|
+
if (instance) ui = instance;
|
|
77
|
+
return ui ??= new UnicornUI();
|
|
78
|
+
}
|
|
79
|
+
function useUITheme(theme) {
|
|
80
|
+
const ui = useUI();
|
|
81
|
+
if (ui.theme && !theme) return ui.theme;
|
|
82
|
+
if (typeof theme === "function") theme = new theme();
|
|
83
|
+
ui.installTheme(theme);
|
|
84
|
+
return ui.theme;
|
|
85
|
+
}
|
|
86
|
+
var UnicornUI = class {
|
|
87
|
+
theme;
|
|
88
|
+
static get defaultOptions() {
|
|
89
|
+
return { messageSelector: ".message-wrap" };
|
|
90
|
+
}
|
|
91
|
+
installTheme(theme) {
|
|
92
|
+
this.theme = theme;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var prepares = [];
|
|
96
|
+
var { promise: alpineLoaded, resolve: alpineResolve } = /* @__PURE__ */ promiseWithResolvers();
|
|
97
|
+
async function loadAlpine(callback) {
|
|
98
|
+
if (callback && !window.Alpine) prepares.push(callback);
|
|
99
|
+
const { default: Alpine } = await useImport("@alpinejs");
|
|
100
|
+
if (!window.Alpine) {
|
|
101
|
+
await Promise.all(prepares.map((callback) => Promise.resolve(callback(Alpine))));
|
|
102
|
+
Alpine.start();
|
|
103
|
+
window.Alpine = Alpine;
|
|
104
|
+
alpineResolve(Alpine);
|
|
105
|
+
} else if (callback) await callback(Alpine);
|
|
106
|
+
return Alpine;
|
|
107
|
+
}
|
|
108
|
+
async function initAlpineComponent(directive) {
|
|
109
|
+
const Alpine = await alpineLoaded;
|
|
110
|
+
await nextTick();
|
|
111
|
+
selectAll(`[${directive}]`, (el) => {
|
|
112
|
+
const code = el.getAttribute(directive) || "";
|
|
113
|
+
el.removeAttribute(directive);
|
|
114
|
+
Alpine.mutateDom(() => {
|
|
115
|
+
el.setAttribute("x-data", code);
|
|
116
|
+
});
|
|
117
|
+
Alpine.initTree(el);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Before Alpine init
|
|
122
|
+
*/
|
|
123
|
+
async function prepareAlpine(callback) {
|
|
124
|
+
if (window.Alpine) await callback(window.Alpine);
|
|
125
|
+
else prepares.push(callback);
|
|
126
|
+
}
|
|
127
|
+
async function prepareAlpineDefer(callback) {
|
|
128
|
+
await alpineLoaded;
|
|
129
|
+
await callback(window.Alpine);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Render Messages.
|
|
133
|
+
*/
|
|
134
|
+
function renderMessage(messages, type = "info") {
|
|
135
|
+
return ui.theme?.renderMessage(messages, type);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clear messages.
|
|
139
|
+
*/
|
|
140
|
+
function clearMessages() {
|
|
141
|
+
ui.theme?.clearMessages();
|
|
142
|
+
}
|
|
143
|
+
async function mark(selector, keyword = "", options = {}) {
|
|
144
|
+
const modules = await useImport("@vendor/mark.js/dist/mark.min.js");
|
|
145
|
+
if (selector != null) new Mark(selector).mark(keyword, options);
|
|
146
|
+
return modules;
|
|
147
|
+
}
|
|
148
|
+
async function slideUp(target, duration = 300) {
|
|
149
|
+
const ele = selectOne(target);
|
|
150
|
+
if (!ele) return Promise.resolve();
|
|
151
|
+
ele.style.overflow = "hidden";
|
|
152
|
+
const animation = animateTo(ele, {
|
|
153
|
+
height: 0,
|
|
154
|
+
paddingTop: 0,
|
|
155
|
+
paddingBottom: 0
|
|
156
|
+
}, {
|
|
157
|
+
duration,
|
|
158
|
+
easing: "ease-out"
|
|
159
|
+
});
|
|
160
|
+
data(ele, "animation.sliding.up", true);
|
|
161
|
+
const r = await animation.finished;
|
|
162
|
+
if (!data(ele, "animation.sliding.down")) ele.style.display = "none";
|
|
163
|
+
removeData(ele, "animation.sliding.up");
|
|
164
|
+
return r;
|
|
165
|
+
}
|
|
166
|
+
function slideDown(target, duration = 300, display = "block") {
|
|
167
|
+
const ele = selectOne(target);
|
|
168
|
+
if (!ele) return Promise.resolve();
|
|
169
|
+
data(ele, "animation.sliding.down", true);
|
|
170
|
+
ele.style.display = display;
|
|
171
|
+
ele.style.overflow = "hidden";
|
|
172
|
+
let maxHeight = 0;
|
|
173
|
+
for (const child of Array.from(ele.children)) maxHeight = Math.max(child.offsetHeight, maxHeight);
|
|
174
|
+
const animation = animateTo(ele, { height: [0, maxHeight + "px"] }, {
|
|
175
|
+
duration,
|
|
176
|
+
easing: "ease-out"
|
|
177
|
+
});
|
|
178
|
+
animation.addEventListener("finish", () => {
|
|
179
|
+
ele.style.height = "";
|
|
180
|
+
if (!data(ele, "animation.sliding.up")) ele.style.overflow = "visible";
|
|
181
|
+
removeData(ele, "animation.sliding.down");
|
|
182
|
+
});
|
|
183
|
+
return animation.finished;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* slideToggle
|
|
187
|
+
*/
|
|
188
|
+
function slideToggle(target, duration = 500, display = "block") {
|
|
189
|
+
const ele = selectOne(target);
|
|
190
|
+
if (!ele) return Promise.resolve();
|
|
191
|
+
if (window.getComputedStyle(ele).display === "none") return slideDown(ele, duration, display);
|
|
192
|
+
else return slideUp(ele, duration);
|
|
193
|
+
}
|
|
194
|
+
async function fadeOut(selector, duration = 500) {
|
|
195
|
+
const el = selectOne(selector);
|
|
196
|
+
if (!el) return;
|
|
197
|
+
const p = await animateTo(el, { opacity: 0 }, {
|
|
198
|
+
duration,
|
|
199
|
+
easing: "ease-out"
|
|
200
|
+
}).finished;
|
|
201
|
+
el.style.display = "none";
|
|
202
|
+
return p;
|
|
203
|
+
}
|
|
204
|
+
async function fadeIn(selector, duration = 500, display = "block") {
|
|
205
|
+
const el = selectOne(selector);
|
|
206
|
+
if (!el) return;
|
|
207
|
+
el.style.display = "";
|
|
208
|
+
if (window.getComputedStyle(el).display !== display) el.style.display = display;
|
|
209
|
+
return animateTo(el, { opacity: 1 }, {
|
|
210
|
+
duration,
|
|
211
|
+
easing: "ease-out"
|
|
212
|
+
}).finished;
|
|
213
|
+
}
|
|
214
|
+
async function highlight(selector, color = "#ffff99", duration = 600) {
|
|
215
|
+
const ele = selectOne(selector);
|
|
216
|
+
if (!ele) return;
|
|
217
|
+
duration /= 2;
|
|
218
|
+
const bg = window.getComputedStyle(ele).backgroundColor;
|
|
219
|
+
await animateTo(ele, { backgroundColor: color }, { duration }).finished;
|
|
220
|
+
return animateTo(ele, { backgroundColor: bg }, { duration });
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Color Picker.
|
|
224
|
+
*/
|
|
225
|
+
async function useColorPicker(selector, options = {}) {
|
|
226
|
+
if (options?.theme === "dark") useCssImport("@spectrum/spectrum-dark.min.css");
|
|
227
|
+
else if (!options?.theme) useCssImport("@spectrum/spectrum.min.css");
|
|
228
|
+
const m = await useImport("@spectrum");
|
|
229
|
+
if (typeof options.locale === "string") {
|
|
230
|
+
let ls = options.locale.split("-").map((l) => l.toLowerCase());
|
|
231
|
+
if (ls[0] === ls[1]) ls = [ls];
|
|
232
|
+
ls = ls.join("-");
|
|
233
|
+
try {
|
|
234
|
+
await useImport(`@spectrum/i18n/${ls}.js`);
|
|
235
|
+
} catch (e) {
|
|
236
|
+
console.warn(`Unable to load Spectrum locale "${ls}" (${options.locale})`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (selector) return module(selector, "spectrum", (ele) => Spectrum.getInstance(ele, options));
|
|
240
|
+
return m;
|
|
241
|
+
}
|
|
242
|
+
function useDisableOnSubmit(formSelector = "#admin-form", buttonSelector = "", options = {}) {
|
|
243
|
+
buttonSelector = buttonSelector || [
|
|
244
|
+
"#admin-toolbar button",
|
|
245
|
+
"#admin-toolbar a",
|
|
246
|
+
formSelector + " .disable-on-submit",
|
|
247
|
+
formSelector + " .js-dos",
|
|
248
|
+
formSelector + " [data-dos]"
|
|
249
|
+
].join(",");
|
|
250
|
+
const iconSelector = options.iconSelector || [
|
|
251
|
+
"[class*=\"fa-\"]",
|
|
252
|
+
"[data-spin]",
|
|
253
|
+
"[data-spinner]"
|
|
254
|
+
].join(",");
|
|
255
|
+
const event = options.event || "submit";
|
|
256
|
+
const spinnerClass = options.spinnerClass || "spinner-border spinner-border-sm";
|
|
257
|
+
const loadingClass = options.loadingCass || "is-uni-loading";
|
|
258
|
+
selectAll(buttonSelector, (button) => {
|
|
259
|
+
button.addEventListener("click", (e) => {
|
|
260
|
+
button.dataset.clicked = "1";
|
|
261
|
+
setTimeout(() => {
|
|
262
|
+
delete button.dataset.clicked;
|
|
263
|
+
}, 1500);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
const form = selectOne(formSelector);
|
|
267
|
+
form?.addEventListener(event, (e) => {
|
|
268
|
+
setTimeout(() => {
|
|
269
|
+
if (!form.checkValidity()) return;
|
|
270
|
+
selectAll(buttonSelector, (button) => {
|
|
271
|
+
button.style.pointerEvents = "none";
|
|
272
|
+
button.setAttribute("disabled", "disabled");
|
|
273
|
+
button.classList.add("disabled");
|
|
274
|
+
if (button.dataset.clicked) makeButtonLoading(button);
|
|
275
|
+
});
|
|
276
|
+
if (e instanceof SubmitEvent && e.submitter) makeButtonLoading(e.submitter);
|
|
277
|
+
}, 0);
|
|
278
|
+
});
|
|
279
|
+
function makeButtonLoading(button) {
|
|
280
|
+
let icon = button.querySelector(iconSelector);
|
|
281
|
+
button.classList.add(loadingClass);
|
|
282
|
+
if (icon) {
|
|
283
|
+
const i = html("<i></i>");
|
|
284
|
+
icon.parentNode?.replaceChild(i, icon);
|
|
285
|
+
i.setAttribute("class", spinnerClass);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function useDisableIfStackNotEmpty(buttonSelector = "[data-task=save]", stackName = "uploading") {
|
|
290
|
+
useStack(stackName).observe((stack, length) => {
|
|
291
|
+
for (const button of selectAll(buttonSelector)) if (length > 0) {
|
|
292
|
+
button.setAttribute("disabled", "disabled");
|
|
293
|
+
button.classList.add("disabled");
|
|
294
|
+
} else {
|
|
295
|
+
button.removeAttribute("disabled");
|
|
296
|
+
button.classList.remove("disabled");
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Keep alive.
|
|
302
|
+
*/
|
|
303
|
+
function useKeepAlive(url, time = 6e4) {
|
|
304
|
+
const aliveHandle = window.setInterval(() => fetch(url), time);
|
|
305
|
+
return () => {
|
|
306
|
+
clearInterval(aliveHandle);
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Vue component field.
|
|
311
|
+
*/
|
|
312
|
+
async function useVueComponentField(selector, value, options = {}) {
|
|
313
|
+
const m = await useImport("@unicorn/field/vue-component-field.js");
|
|
314
|
+
if (selector) m.VueComponentField.init(selector, value, options);
|
|
315
|
+
return m;
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
export { promiseWithResolvers as C, useVueComponentField as S, useDisableIfStackNotEmpty as _, highlight as a, useUI as b, mark as c, renderMessage as d, slideDown as f, useColorPicker as g, useAlertAdapter as h, fadeOut as i, prepareAlpine as l, slideUp as m, clearMessages as n, initAlpineComponent as o, slideToggle as p, fadeIn as r, loadAlpine as s, UnicornUI as t, prepareAlpineDefer as u, useDisableOnSubmit as v, animateTo as w, useUITheme as x, useKeepAlive as y };
|
|
319
|
+
|
|
320
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","names":[],"sources":["../../src/service/animate.ts","../../../../../../node_modules/@lyrasoft/ts-toolkit/src/generic/promise.ts","../../src/service/ui.ts"],"sourcesContent":["import { selectOne } from './dom';\n\nexport function animateTo(\n element: HTMLElement,\n styles: Partial<Record<keyof CSSStyleDeclaration, any>>,\n options: number | KeyframeAnimationOptions = {}\n): Animation {\n element = selectOne(element);\n\n const currentStyles = window.getComputedStyle(element);\n const transitions: Record<string, any[]> = {};\n\n for (const name in styles) {\n const value = styles[name];\n\n transitions[name] = Array.isArray(value)\n ? value\n : [\n currentStyles.getPropertyValue(name),\n value\n ];\n }\n\n if (typeof options === 'number') {\n options = { duration: options };\n }\n\n options = Object.assign(\n {\n duration: 400,\n easing: 'linear',\n fill: 'both'\n },\n options\n );\n\n const animation = element.animate(\n transitions,\n options\n );\n\n animation.addEventListener('finish', () => {\n for (const name in styles) {\n const value = styles[name];\n\n element.style.setProperty(\n name,\n Array.isArray(value)\n ? value[value.length - 1]\n : value\n );\n }\n\n animation.cancel();\n });\n\n return animation;\n}\n","declare type WithResolversReturn<T> = {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\n\nexport function promiseWithResolvers<T = void>(): WithResolversReturn<T> {\n let resolve: (value: T | PromiseLike<T>) => void;\n let reject: (reason?: any) => void;\n\n const promise = new Promise<T>((rs, rj) => {\n resolve = rs;\n reject = rj;\n });\n\n // @ts-ignore\n return { promise, resolve, reject };\n}\n","import {\n AlertAdapter,\n deleteConfirm,\n simpleAlert,\n simpleConfirm,\n simpleNotify,\n clearNotifies,\n promiseWithResolvers\n} from '@lyrasoft/ts-toolkit/generic';\nimport type { Alpine as AlpineGlobal } from 'alpinejs';\nimport type { default as SpectrumGlobal } from 'spectrum-vanilla';\nimport type { SpectrumOptions } from 'spectrum-vanilla/dist/types/types';\nimport type { default as TomSelectGlobal } from 'tom-select';\nimport { useStack } from '../composable';\nimport { data, removeData } from '../data';\nimport type { Constructor, MaybePromise, Nullable, UIThemeInterface } from '../types';\nimport { animateTo } from './animate';\nimport { html, module, selectAll, selectOne } from './dom';\nimport { nextTick } from './helper';\nimport { useCssImport, useImport } from './loader';\n\nlet ui: UnicornUI;\n\nAlertAdapter.alert = (title: string, text = '', type = 'info'): Promise<void> => {\n if (text) {\n title += ' | ' + text;\n }\n\n window.alert(title);\n\n return Promise.resolve();\n};\n\nAlertAdapter.confirm = (message: string, text = '', type = 'info'): Promise<boolean> => {\n message = message || 'Are you sure?';\n\n if (text) {\n message += ' | ' + text;\n }\n\n return new Promise((resolve) => {\n resolve(window.confirm(message));\n });\n};\n\nAlertAdapter.notify = async (title: string, text?: string, type: string = 'log'): Promise<() => any> => {\n if (text) {\n title += ' | ' + text;\n }\n\n return ui.theme?.renderMessage(title, type) ?? (() => null);\n};\n\nAlertAdapter.clearNotifies = async (): Promise<void> => {\n ui.theme?.clearMessages();\n};\n\nAlertAdapter.confirmText = () => 'OK';\nAlertAdapter.cancelText = () => 'Cancel';\nAlertAdapter.deleteText = () => 'Delete';\n\nexport { simpleAlert, simpleConfirm, deleteConfirm, simpleNotify, clearNotifies };\n\nexport interface AlertAdapterConfig {\n alert?: typeof AlertAdapter['alert'];\n confirm?: typeof AlertAdapter['confirm'];\n deleteConfirm?: typeof AlertAdapter['deleteConfirm'];\n confirmText?: typeof AlertAdapter['confirmText'];\n cancelText?: typeof AlertAdapter['cancelText'];\n deleteText?: typeof AlertAdapter['deleteText'];\n notify?: typeof AlertAdapter['notify'];\n clearNotifies?: typeof AlertAdapter['clearNotifies'];\n}\n\nexport function useAlertAdapter(config?: AlertAdapterConfig): typeof AlertAdapter {\n if (config) {\n Object.assign(AlertAdapter, config);\n }\n\n return AlertAdapter;\n}\n\nexport function useUI(instance?: UnicornUI): UnicornUI {\n if (instance) {\n ui = instance;\n }\n\n return ui ??= new UnicornUI();\n}\n\nexport function useUITheme<T extends UIThemeInterface>(theme?: T | Constructor<T>): UIThemeInterface {\n const ui = useUI();\n\n if (ui.theme && !theme) {\n return ui.theme;\n }\n\n if (typeof theme === 'function') {\n theme = new theme();\n }\n\n ui.installTheme(theme);\n\n return ui.theme!;\n}\n\nexport class UnicornUI {\n theme?: UIThemeInterface;\n\n static get defaultOptions() {\n return {\n messageSelector: '.message-wrap',\n };\n }\n\n installTheme(theme: any) {\n this.theme = theme;\n }\n\n // confirm(message: string): Promise<boolean> {\n // message = message || 'Are you sure?';\n //\n // return new Promise((resolve) => {\n // resolve(window.confirm(message));\n // });\n // }\n //\n // alert(title: string, text = '', type = 'info'): Promise<boolean> {\n // if (text) {\n // title += ' | ' + text;\n // }\n //\n // window.alert(title);\n //\n // return Promise.resolve(true);\n // }\n}\n\nconst prepares: AlpinePrepareCallback[] = [];\ntype AlpinePrepareCallback = (Alpine: AlpineGlobal) => MaybePromise<any>;\nconst { promise: alpineLoaded, resolve: alpineResolve } = promiseWithResolvers<AlpineGlobal>();\n\nexport async function loadAlpine(callback?: Nullable<AlpinePrepareCallback>): Promise<AlpineGlobal> {\n if (callback && !window.Alpine) {\n prepares.push(callback);\n }\n\n const { default: Alpine }: { default: AlpineGlobal } = await useImport('@alpinejs');\n\n if (!window.Alpine) {\n await Promise.all(prepares.map((callback) => Promise.resolve(callback(Alpine))));\n\n Alpine.start();\n\n window.Alpine = Alpine;\n\n alpineResolve(Alpine);\n } else if (callback) {\n await callback(Alpine);\n }\n\n return Alpine;\n}\n\nexport async function initAlpineComponent(directive: string) {\n const Alpine = await alpineLoaded;\n\n await nextTick();\n\n selectAll<HTMLElement>(`[${directive}]`, (el) => {\n const code = el.getAttribute(directive) || '';\n el.removeAttribute(directive);\n\n // @see https://github.com/alpinejs/alpine/issues/359#issuecomment-973688464\n Alpine.mutateDom(() => {\n el.setAttribute('x-data', code);\n });\n\n Alpine.initTree(el);\n });\n}\n\n/**\n * Before Alpine init\n */\nexport async function prepareAlpine(callback: AlpinePrepareCallback) {\n if (window.Alpine) {\n await callback(window.Alpine);\n } else {\n prepares.push(callback);\n }\n}\n\nexport async function prepareAlpineDefer(callback: AlpinePrepareCallback) {\n const Alpine = await alpineLoaded;\n\n await callback(window.Alpine);\n}\n\n/**\n * Render Messages.\n */\nexport function renderMessage(messages: string | string[], type: string = 'info') {\n return ui.theme?.renderMessage(messages, type);\n}\n\n/**\n * Clear messages.\n */\nexport function clearMessages() {\n ui.theme?.clearMessages();\n}\n\nexport async function mark(selector?: string | HTMLElement, keyword: string = '', options: Record<string, any> = {}) {\n const modules = await useImport('@vendor/mark.js/dist/mark.min.js');\n\n if (selector != null) {\n const instance = new Mark(selector);\n instance.mark(keyword, options);\n }\n\n return modules;\n}\n\nexport async function slideUp(target: string | HTMLElement, duration: number = 300): Promise<Animation | void> {\n const ele = selectOne(target);\n\n if (!ele) {\n return Promise.resolve();\n }\n\n ele.style.overflow = 'hidden';\n\n const animation = animateTo(\n ele,\n { height: 0, paddingTop: 0, paddingBottom: 0 },\n { duration, easing: 'ease-out' }\n );\n\n data(ele, 'animation.sliding.up', true);\n\n const r = await animation.finished;\n\n if (!data(ele, 'animation.sliding.down')) {\n ele.style.display = 'none';\n }\n\n removeData(ele, 'animation.sliding.up');\n\n return r;\n}\n\nexport function slideDown(\n target: string | HTMLElement,\n duration: number = 300,\n display: string = 'block'): Promise<Animation | void> {\n const ele = selectOne(target);\n\n if (!ele) {\n return Promise.resolve();\n }\n\n data(ele, 'animation.sliding.down', true);\n\n ele.style.display = display;\n ele.style.overflow = 'hidden';\n\n// Get height\n let maxHeight = 0;\n for (const child of Array.from(ele.children) as HTMLElement[]) {\n maxHeight = Math.max(child.offsetHeight, maxHeight);\n }\n\n const animation = animateTo(\n ele,\n {\n height: [\n 0,\n maxHeight + 'px'\n ]\n },\n { duration, easing: 'ease-out' }\n );\n\n animation.addEventListener('finish', () => {\n ele.style.height = '';\n\n if (!data(ele, 'animation.sliding.up')) {\n ele.style.overflow = 'visible';\n }\n\n removeData(ele, 'animation.sliding.down');\n });\n\n return animation.finished;\n}\n\n/**\n * slideToggle\n */\nexport function slideToggle(\n target: string | HTMLElement,\n duration: number = 500,\n display: string = 'block'): Promise<Animation | void> {\n const ele = selectOne(target);\n\n if (!ele) {\n return Promise.resolve();\n }\n\n if (window.getComputedStyle(ele).display === 'none') {\n return slideDown(ele, duration, display);\n } else {\n return slideUp(ele, duration);\n }\n}\n\nexport async function fadeOut(selector: string | HTMLElement, duration: number = 500): Promise<Animation | void> {\n const el = selectOne(selector);\n\n if (!el) {\n return;\n }\n\n const animation = animateTo(el, { opacity: 0 }, { duration, easing: 'ease-out' });\n\n const p = await animation.finished;\n el.style.display = 'none';\n\n return p;\n};\n\nexport async function fadeIn(\n selector: string | HTMLElement,\n duration: number = 500,\n display: string = 'block'\n): Promise<Animation | void> {\n const el = selectOne(selector);\n\n if (!el) {\n return;\n }\n\n el.style.display = '';\n\n if (window.getComputedStyle(el).display !== display) {\n el.style.display = display;\n }\n\n const animation = animateTo(el, { opacity: 1 }, { duration, easing: 'ease-out' });\n\n return animation.finished;\n};\n\nexport async function highlight(\n selector: string | HTMLElement,\n color: string = '#ffff99',\n duration: number = 600\n): Promise<Animation | void> {\n const ele = selectOne(selector);\n\n if (!ele) {\n return;\n }\n\n duration /= 2;\n const bg = window.getComputedStyle(ele).backgroundColor;\n\n const animation = animateTo(ele, { backgroundColor: color }, { duration });\n\n await animation.finished;\n\n return animateTo(ele, { backgroundColor: bg }, { duration });\n}\n\n/**\n * Color Picker.\n */\nexport async function useColorPicker(\n selector?: Nullable<string | HTMLElement | NodeListOf<HTMLElement>>,\n options: Partial<SpectrumOptions> = {}\n): Promise<any> {\n if (options?.theme === 'dark') {\n useCssImport('@spectrum/spectrum-dark.min.css');\n } else if (!options?.theme) {\n useCssImport('@spectrum/spectrum.min.css');\n }\n\n const m = await useImport('@spectrum');\n\n // Locale\n if (typeof options.locale === 'string') {\n let ls: any = options.locale.split('-').map((l) => l.toLowerCase());\n\n if (ls[0] === ls[1]) {\n ls = [ls];\n }\n\n ls = ls.join('-');\n try {\n await useImport(`@spectrum/i18n/${ls}.js`);\n } catch (e) {\n console.warn(`Unable to load Spectrum locale \"${ls}\" (${options.locale})`);\n }\n }\n\n if (selector) {\n return module<any, HTMLElement>(selector, 'spectrum', (ele) => Spectrum.getInstance(ele, options));\n }\n\n return m;\n}\n\nexport interface DisableOnSubmitOptions {\n event?: string;\n spinnerClass?: string;\n loadingCass?: string;\n iconSelector?: string;\n}\n\nexport function useDisableOnSubmit(\n formSelector: string | HTMLFormElement = '#admin-form',\n buttonSelector: string = '',\n options: DisableOnSubmitOptions = {}\n) {\n // Todo: Use object to handle it\n buttonSelector = buttonSelector || [\n '#admin-toolbar button',\n '#admin-toolbar a',\n formSelector + ' .disable-on-submit',\n formSelector + ' .js-dos',\n formSelector + ' [data-dos]',\n ].join(',');\n\n const iconSelector = options.iconSelector || [\n '[class*=\"fa-\"]',\n '[data-spin]',\n '[data-spinner]',\n ].join(',');\n\n const event = options.event || 'submit';\n const spinnerClass = options.spinnerClass || 'spinner-border spinner-border-sm';\n const loadingClass = options.loadingCass || 'is-uni-loading';\n\n selectAll<HTMLElement>(buttonSelector, (button) => {\n button.addEventListener('click', (e) => {\n button.dataset.clicked = '1';\n\n setTimeout(() => {\n delete button.dataset.clicked;\n }, 1500);\n });\n });\n\n const form = selectOne<HTMLFormElement>(formSelector);\n\n form?.addEventListener(event, (e: Event) => {\n setTimeout(() => {\n if (!form.checkValidity()) {\n return;\n }\n\n selectAll<HTMLElement>(buttonSelector, (button) => {\n button.style.pointerEvents = 'none';\n button.setAttribute('disabled', 'disabled');\n button.classList.add('disabled');\n\n if (button.dataset.clicked) {\n makeButtonLoading(button);\n }\n });\n\n if (e instanceof SubmitEvent && e.submitter) {\n makeButtonLoading(e.submitter);\n }\n }, 0);\n });\n\n function makeButtonLoading(button: HTMLElement) {\n let icon = button.querySelector(iconSelector);\n button.classList.add(loadingClass);\n\n if (icon) {\n const i = html('<i></i>');\n icon.parentNode?.replaceChild(i, icon);\n\n i.setAttribute('class', spinnerClass);\n // icon.styles.width = '1em';\n // icon.styles.height = '1em';\n // icon.styles.borderWith = '.15em';\n }\n }\n}\n\nexport function useDisableIfStackNotEmpty(buttonSelector: string = '[data-task=save]',\n stackName: string = 'uploading') {\n const stack = useStack(stackName);\n\n stack.observe((stack, length) => {\n for (const button of selectAll<HTMLElement>(buttonSelector)) {\n if (length > 0) {\n button.setAttribute('disabled', 'disabled');\n button.classList.add('disabled');\n } else {\n button.removeAttribute('disabled');\n button.classList.remove('disabled');\n }\n }\n });\n}\n\n/**\n * Keep alive.\n */\nexport function useKeepAlive(url: string, time: number = 60000): () => void {\n const aliveHandle = window.setInterval(() => fetch(url), time);\n\n return () => {\n clearInterval(aliveHandle);\n };\n}\n\n/**\n * Vue component field.\n */\nexport async function useVueComponentField(\n selector?: Nullable<string | HTMLElement>,\n value?: any,\n options: Record<string, any> = {}\n): Promise<any> {\n const m = await useImport('@unicorn/field/vue-component-field.js');\n\n if (selector) {\n m.VueComponentField.init(selector, value, options);\n }\n\n return m;\n}\n\ndeclare global {\n var Alpine: AlpineGlobal;\n var TomSelect: typeof TomSelectGlobal;\n var Spectrum: typeof SpectrumGlobal;\n var Mark: any;\n}\n"],"x_google_ignoreList":[1],"mappings":"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"}
|