main
js 186 lines 5.21 KB
Raw
1 import * as initializer from "./initializer.js";
2 import * as _modals from "./modals.js";
3 import "./surfaces.js";
4 import * as _components from "./components.js";
5 import * as extensions from "./extensions.js";
6 import { registerAlpineMagic } from "./confirmClick.js";
7
8 // process extensions
9 await extensions.callJsExtensions("initFw_start")
10
11 // initialize required elements
12 await initializer.initialize();
13
14 // import alpine library
15 // @ts-ignore
16 await import("../vendor/alpine/alpine.min.js");
17
18 const Alpine = globalThis.Alpine;
19
20 // register $confirmClick magic helper for inline button confirmations
21 registerAlpineMagic();
22
23 // add x-destroy directive to alpine
24 Alpine.directive(
25 "destroy",
26 (_el, { expression }, { evaluateLater, cleanup }) => {
27 const onDestroy = evaluateLater(expression);
28 cleanup(() => onDestroy());
29 }
30 );
31
32 // add x-create directive to alpine
33 Alpine.directive(
34 "create",
35 (_el, { expression }, { evaluateLater }) => {
36 const onCreate = evaluateLater(expression);
37 onCreate();
38 }
39 );
40
41 const resolveSelector = (expression, evaluateLater, cb) => {
42 if (typeof expression !== "string" || !expression.trim()) return;
43
44 if (/^[\s]*["']/.test(expression)) {
45 const getSelector = evaluateLater(expression);
46 getSelector((evaluated) => {
47 if (typeof evaluated !== "string" || !evaluated.trim()) return;
48 cb(evaluated.trim());
49 });
50 return;
51 }
52
53 cb(expression.trim());
54 };
55
56 const moveOnNextTick = (el, expression, evaluateLater, fn) => {
57 Alpine.nextTick(() => {
58 resolveSelector(expression, evaluateLater, (selector) => fn(el, selector));
59 });
60 };
61
62 Alpine.directive(
63 "move-to-start",
64 (el, { expression }, { evaluateLater }) => {
65 moveOnNextTick(el, expression, evaluateLater, (_el, selector) => {
66 const parent = document.querySelector(selector);
67 if (!parent) return;
68 parent.insertBefore(_el, parent.firstChild);
69 });
70 }
71 );
72
73 Alpine.directive(
74 "move-to-end",
75 (el, { expression }, { evaluateLater }) => {
76 moveOnNextTick(el, expression, evaluateLater, (_el, selector) => {
77 const parent = document.querySelector(selector);
78 if (!parent) return;
79 parent.appendChild(_el);
80 });
81 }
82 );
83
84 Alpine.directive(
85 "move-to",
86 (el, { expression, modifiers, value }, { evaluateLater }) => {
87 const orderModifier = Array.isArray(modifiers)
88 ? modifiers.find((m) => /^\d+$/.test(m))
89 : null;
90
91 const orderRaw = orderModifier ?? value;
92 const order = Number(orderRaw);
93 if (!Number.isFinite(order)) return;
94
95 moveOnNextTick(el, expression, evaluateLater, (_el, selector) => {
96 const parent = document.querySelector(selector);
97 if (!parent) return;
98
99 const index = Math.max(0, Math.floor(order));
100 const beforeNode = parent.children.item(index) ?? null;
101 parent.insertBefore(_el, beforeNode);
102 });
103 }
104 );
105
106 Alpine.directive(
107 "move-before",
108 (el, { expression }, { evaluateLater }) => {
109 moveOnNextTick(el, expression, evaluateLater, (_el, selector) => {
110 const ref = document.querySelector(selector);
111 if (!ref || !ref.parentElement) return;
112 ref.parentElement.insertBefore(_el, ref);
113 });
114 }
115 );
116
117 Alpine.directive(
118 "move-after",
119 (el, { expression }, { evaluateLater }) => {
120 moveOnNextTick(el, expression, evaluateLater, (_el, selector) => {
121 const ref = document.querySelector(selector);
122 if (!ref || !ref.parentElement) return;
123 ref.parentElement.insertBefore(_el, ref.nextSibling);
124 });
125 }
126 );
127
128 // run every second if the component is active
129 Alpine.directive(
130 "every-second",
131 (_el, { expression }, { evaluateLater, cleanup }) => {
132 const onTick = evaluateLater(expression);
133 const intervalId = setInterval(() => onTick(), 1000);
134 cleanup(() => clearInterval(intervalId));
135 }
136 );
137
138 // run every minute if the component is active
139 Alpine.directive(
140 "every-minute",
141 (_el, { expression }, { evaluateLater, cleanup }) => {
142 const onTick = evaluateLater(expression);
143 const intervalId = setInterval(() => onTick(), 60_000);
144 cleanup(() => clearInterval(intervalId));
145 }
146 );
147
148 // run every hour if the component is active
149 Alpine.directive(
150 "every-hour",
151 (_el, { expression }, { evaluateLater, cleanup }) => {
152 const onTick = evaluateLater(expression);
153 const intervalId = setInterval(() => onTick(), 3_600_000);
154 cleanup(() => clearInterval(intervalId));
155 }
156 );
157
158
159 // clone existing global store into standalone instance
160 globalThis.Alpine.magic('instantiate', () => (src) => {
161 const out = {};
162 const desc = Object.getOwnPropertyDescriptors(src);
163
164 for (const k in desc) {
165 const d = desc[k];
166
167 if (d.get || d.set || typeof d.value === "function") {
168 Object.defineProperty(out, k, d);
169 } else {
170 const v = d.value;
171 Object.defineProperty(out, k, {
172 ...d,
173 value: Array.isArray(v)
174 ? v.map(i => (i && typeof i === "object" ? { ...i } : i))
175 : v && typeof v === "object"
176 ? { ...v }
177 : v
178 });
179 }
180 }
181
182 return out;
183 });
184
185 // process extensions
186 await extensions.callJsExtensions("initFw_end")