saloe 0.0.89 → 0.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,211 +1,295 @@
1
- const listener = ({
2
- SRC_ELEMEMENTS_QUERY = [],
3
- listenAfterMs = 2500
1
+ const LISTENER_SCRIPT = `({
2
+ SRC_ELEMEMENTS_QUERY = [],
3
+ listenAfterMs = 2_500,
4
4
  } = {}) => {
5
- const EVENTS_PREVENT_DEFAULT_MANDATORY = [
6
- "submit"
7
- ];
8
- const EVENTS = [
9
- "mouseover",
10
- "click",
11
- "submit",
12
- "input",
13
- "blur",
14
- "change",
15
- "focus",
16
- "invalid"
17
- ];
18
- const addListener = ({ srcElement, eventName, listeners, afterExecuteListeners }) => {
19
- srcElement == null ? void 0 : srcElement.addEventListener(eventName, (e) => {
20
- executeListeners({ e, srcElement, listeners, afterExecuteListeners });
21
- });
22
- };
23
- const executeListeners = async ({ e, srcElement, listeners, afterExecuteListeners }) => {
24
- await Promise.all(
25
- (listeners ?? []).map((listener2) => {
26
- if (listener2) return listener2({ e, srcElement });
27
- })
28
- );
29
- if (afterExecuteListeners) await afterExecuteListeners();
30
- };
31
- const getListenerFromScript = ({ script, eventName }) => {
32
- var _a;
33
- if (!script) return null;
34
- if (script[eventName]) return script[eventName];
35
- const prev = (_a = Object.keys(script)) == null ? void 0 : _a.find((key) => script[key][eventName]);
36
- if (!prev) return null;
37
- return script[prev][eventName];
38
- };
39
- const fetchListeners = async ({ srcElement, eventName, e }) => {
40
- var _a;
41
- if (!(srcElement == null ? void 0 : srcElement.getAttribute)) return;
42
- const scriptNames = srcElement == null ? void 0 : srcElement.getAttribute(`on-${eventName}`);
43
- if (!scriptNames) return;
44
- if (e && scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(eventName)) e.preventDefault();
45
- const scripts = await Promise.all(
46
- (_a = scriptNames == null ? void 0 : scriptNames.split(",")) == null ? void 0 : _a.map((scriptName) => {
47
- const scriptToImport = `/${scriptName == null ? void 0 : scriptName.trim()}.js`;
48
- return importScriptDynamically({ path: scriptToImport });
49
- })
50
- );
51
- const listeners = scripts == null ? void 0 : scripts.map((script) => getListenerFromScript({ script, eventName }));
52
- return listeners;
53
- };
54
- const addScripts = () => {
55
- const scriptsToLoad = [...document.querySelectorAll("script[data-script-to-load]")];
56
- return Promise.all(
57
- scriptsToLoad == null ? void 0 : scriptsToLoad.map((scriptToLoad) => {
58
- var _a;
59
- const id = scriptToLoad == null ? void 0 : scriptToLoad.getAttribute("data-script-to-load");
60
- scriptToLoad.removeAttribute("data-script-to-load");
61
- const attrs = (_a = scriptToLoad == null ? void 0 : scriptToLoad.getAttributeNames()) == null ? void 0 : _a.reduce((acc, attrName) => {
62
- const attrValue = scriptToLoad.getAttribute(attrName);
63
- if (attrValue !== "text/script-to-load") acc[attrName] = attrValue;
64
- return acc;
65
- }, {});
66
- const content = scriptToLoad == null ? void 0 : scriptToLoad.textContent;
67
- scriptToLoad == null ? void 0 : scriptToLoad.remove();
68
- return loadScript({ id, attrs, content }).catch((err) => {
69
- console.error(err);
70
- });
71
- })
72
- );
73
- };
74
- const loadScript = ({ id, attrs, content }) => {
75
- var _a;
76
- const script = document == null ? void 0 : document.createElement("script");
77
- (_a = Object.keys(attrs)) == null ? void 0 : _a.forEach((attrKey) => script == null ? void 0 : script.setAttribute(attrKey, attrs[attrKey]));
78
- script.id = id;
79
- script.type = "module";
80
- if (content) script == null ? void 0 : script.insertAdjacentHTML("beforeend", content);
81
- return new Promise((resolve, reject) => {
82
- var _a2, _b;
83
- if (!attrs.src) {
84
- resolve();
85
- (_a2 = document == null ? void 0 : document.body) == null ? void 0 : _a2.insertAdjacentElement("beforeend", script);
86
- return;
87
- }
88
- script.onload = script.onreadystatechange = function() {
89
- if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
90
- resolve();
91
- script.onload = script.onreadystatechange = null;
5
+ const EVENTS_PREVENT_DEFAULT_MANDATORY = [
6
+ 'submit'
7
+ ]
8
+
9
+ const EVENTS = [
10
+ 'mouseover',
11
+ 'click',
12
+ 'submit',
13
+ 'input',
14
+ 'blur',
15
+ 'change',
16
+ 'focus',
17
+ 'invalid',
18
+ ]
19
+
20
+ const addListener = ({ srcElement, eventName, listeners, afterExecuteListeners }) => {
21
+ srcElement?.addEventListener(eventName, (e) => {
22
+ executeListeners({ e, srcElement, listeners, afterExecuteListeners })
23
+ })
24
+ }
25
+
26
+ const executeListeners = async ({ e, srcElement, listeners, afterExecuteListeners }) => {
27
+ await Promise.all(
28
+ (listeners ?? []).map((listener) => {
29
+ if (listener) return listener({ e, srcElement })
30
+ })
31
+ )
32
+
33
+ if (afterExecuteListeners) await afterExecuteListeners()
34
+ }
35
+
36
+ const getListenerFromScript = ({ script, eventName }) => {
37
+ if (!script) return null
38
+ if (script[eventName]) return script[eventName]
39
+ const prev = Object.keys(script)?.find((key) => script[key][eventName])
40
+ if (!prev) return null
41
+ return script[prev][eventName]
42
+ }
43
+
44
+ const fetchListeners = async ({ srcElement, eventName, e }) => {
45
+ if (!srcElement?.getAttribute) return
46
+
47
+ const scriptNames = srcElement?.getAttribute(\`on-\${eventName}\`)
48
+ if (!scriptNames) return
49
+
50
+ if (e && scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(eventName)) e.preventDefault()
51
+
52
+ const scripts = await Promise.all(
53
+ scriptNames?.split(',')?.map((scriptName) => {
54
+ const scriptToImport = \`/\${scriptName?.trim()}.js\`
55
+ return importScriptDynamically({ path: scriptToImport })
56
+ })
57
+ )
58
+
59
+ const listeners = scripts?.map((script) => getListenerFromScript({ script, eventName }))
60
+
61
+ return listeners
62
+ }
63
+
64
+ const addScripts = () => {
65
+ const scriptsToLoad = [...document.querySelectorAll('script[data-script-to-load]')]
66
+ return Promise.all(
67
+ scriptsToLoad?.map((scriptToLoad) => {
68
+ const id = scriptToLoad?.getAttribute('data-script-to-load')
69
+ scriptToLoad.removeAttribute('data-script-to-load')
70
+
71
+ const attrs = scriptToLoad?.getAttributeNames()?.reduce((acc, attrName) => {
72
+ const attrValue = scriptToLoad.getAttribute(attrName)
73
+ if (attrValue !== 'text/script-to-load') acc[attrName] = attrValue
74
+ return acc
75
+ }, {})
76
+
77
+ const content = scriptToLoad?.textContent
78
+
79
+ scriptToLoad?.remove()
80
+
81
+ return loadScript({ id, attrs, content }).catch((err) => {
82
+ console.error(err)
83
+ })
84
+ })
85
+ )
86
+ }
87
+
88
+ const loadScript = ({ id, attrs, content }) => {
89
+ const script = document?.createElement('script')
90
+
91
+ Object.keys(attrs)?.forEach((attrKey) => script?.setAttribute(attrKey, attrs[attrKey]))
92
+ script.id = id
93
+ script.type = 'module'
94
+
95
+ if (content) script?.insertAdjacentHTML('beforeend', content)
96
+
97
+ return new Promise((resolve, reject) => {
98
+ if (!attrs.src) {
99
+ resolve()
100
+ document?.body?.insertAdjacentElement('beforeend', script)
101
+ return
102
+ }
103
+
104
+ script.onload = script.onreadystatechange = function () {
105
+ if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
106
+ resolve()
107
+ script.onload = script.onreadystatechange = null
108
+ }
109
+ }
110
+
111
+ script.onerror = () => {
112
+ console.error('script failed to load')
113
+ reject(new Error(\`Failed to load script with src \${script.src}\`))
114
+ }
115
+
116
+ document?.body?.insertAdjacentElement('beforeend', script)
117
+ })
118
+ }
119
+
120
+ // FIX: return import() to prevent __vitePreload to take action
121
+ const importScriptDynamically = ({ path }) => {
122
+ return import(path)?.catch((err) => { })
123
+ }
124
+
125
+ // load
126
+ const fireLoadListener = () => {
127
+ const eventName = 'load'
128
+ const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
129
+
130
+ srcElements?.forEach(async (srcElement) => {
131
+ const listeners = await fetchListeners({ srcElement, eventName, e: null })
132
+ executeListeners({ e: null, srcElement, listeners })
133
+
134
+ srcElement?.removeAttribute(\`on-\${eventName}\`)
135
+ })
136
+ }
137
+
138
+ // invalid
139
+ const fireInvalidListener = () => {
140
+ const eventName = 'invalid'
141
+ const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
142
+
143
+ srcElements?.forEach(async (srcElement) => {
144
+ const listeners = await fetchListeners({ srcElement, eventName, e: null })
145
+ addListener({ srcElement, eventName, listeners })
146
+ })
147
+ }
148
+
149
+ // blur
150
+ const fireBlurListener = () => {
151
+ const eventName = 'blur'
152
+ const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
153
+
154
+ srcElements?.forEach(async (srcElement) => {
155
+ const listeners = await fetchListeners({ srcElement, eventName, e: null })
156
+ addListener({ srcElement, eventName, listeners })
157
+ })
158
+ }
159
+
160
+ // focus
161
+ const fireFocusListener = () => {
162
+ const eventName = 'focus'
163
+ const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
164
+
165
+ srcElements?.forEach(async (srcElement) => {
166
+ const listeners = await fetchListeners({ srcElement, eventName, e: null })
167
+ addListener({ srcElement, eventName, listeners })
168
+ })
169
+ }
170
+
171
+ // observers
172
+ const fireObserverListeners = () => {
173
+ const srcElements = [...document.querySelectorAll('[on-observe]')]
174
+
175
+ const uniqueScriptNames = [...srcElements?.reduce((acc, srcElement) => {
176
+ const attribute = srcElement?.getAttribute('on-observe')
177
+ if (attribute === 'undefined') return acc
178
+
179
+ const scriptNames = attribute?.split(',')
180
+ scriptNames?.forEach((scriptName) => acc?.set(scriptName, 1))
181
+
182
+ return acc
183
+ }, new Map())?.keys()]
184
+
185
+ uniqueScriptNames?.forEach(async (scriptName) => {
186
+ const observedSrcElements = document.querySelectorAll(\`[on-observe*="\${scriptName}"]\`)
187
+
188
+ const script = await importScriptDynamically({ path: \`/\${scriptName?.trim()}.js\` })
189
+ const listener = getListenerFromScript({ script, eventName: 'observe' })
190
+ if (!listener) return
191
+
192
+ const observer = new IntersectionObserver((entries) => {
193
+ entries.forEach((entry) => listener({ entry, observer }))
194
+ }, {
195
+ threshold: .5,
196
+ })
197
+
198
+ observedSrcElements?.forEach((observerSrcElement) => {
199
+ observer.observe(observerSrcElement)
200
+
201
+ const observerAttr = observerSrcElement?.getAttribute('on-observe')
202
+ const updatedObserverAttr = observerAttr?.replaceAll(scriptName + ', ', '')?.replaceAll(', ' + scriptName, '')?.replaceAll(scriptName, '')
203
+
204
+ if (!updatedObserverAttr) observerSrcElement.removeAttribute('on-observe')
205
+ else observerSrcElement.setAttribute('on-observe', updatedObserverAttr)
206
+ })
207
+ })
208
+ }
209
+
210
+ const getSrcElement = ({ srcElement, eventName }) => {
211
+ if (!srcElement?.hasAttribute) return srcElement
212
+ const attribute = \`on-\${eventName}\`
213
+ const hasScriptName = srcElement?.hasAttribute(attribute)
214
+ if (hasScriptName) return srcElement
215
+
216
+ const query = \`:is(\${['a', 'button', ...SRC_ELEMEMENTS_QUERY].join(',')})[\${attribute}]\`
217
+ const closestButton = srcElement?.closest(query)
218
+ if (closestButton) return closestButton
219
+
220
+ return srcElement
221
+ }
222
+
223
+ const cloneSrcElement = ({ srcElement }) => {
224
+ const newSrcElement = document.createElement(srcElement?.tagName)
225
+
226
+ Array.from(srcElement?.attributes).forEach((attr) => {
227
+ if (attr.name.startsWith('on-')) return
228
+ newSrcElement.setAttribute(attr.name, attr.value)
229
+ })
230
+
231
+ return newSrcElement
232
+ }
233
+
234
+ const isAnchorBeingClicked = ({ srcElement, eventName }) => {
235
+ return srcElement?.tagName === 'A' && eventName === 'click'
236
+ }
237
+
238
+ const clickDefaultAnchor = ({ srcElement }) => {
239
+ const newAnchor = cloneSrcElement({ srcElement })
240
+ newAnchor.click()
241
+ }
242
+
243
+ const fireListeners = () => {
244
+ EVENTS.forEach((eventName) => {
245
+ document.body[\`on\${eventName}\`] = async (e) => {
246
+ const srcElement = getSrcElement({ srcElement: e?.srcElement, eventName })
247
+ const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName })
248
+
249
+ if (isAnchorClicked) e.preventDefault()
250
+
251
+ const listeners = await fetchListeners({ srcElement, eventName, e })
252
+ const afterExecuteListeners = isAnchorClicked
253
+ ? () => { clickDefaultAnchor({ srcElement }) }
254
+ : null
255
+
256
+ executeListeners({ e, srcElement, listeners, afterExecuteListeners })
257
+ addListener({ srcElement, eventName, listeners, afterExecuteListeners })
258
+
259
+ if (srcElement?.removeAttribute) srcElement.removeAttribute(\`on-\${eventName}\`)
260
+ }
261
+ })
262
+
263
+ const saloeListenEvent = new CustomEvent('saloeListen', {
264
+ detail: { message: 'This is a custom eventName!' }
265
+ })
266
+
267
+ document.body.addEventListener('saloeListen', async (e) => {
268
+ await addScripts()
269
+ fireLoadListener()
270
+ fireObserverListeners()
271
+ })
272
+
273
+ document.body.saloeListen = function () {
274
+ document.body.dispatchEvent(saloeListenEvent)
92
275
  }
93
- };
94
- script.onerror = () => {
95
- console.error("script failed to load");
96
- reject(new Error(`Failed to load script with src ${script.src}`));
97
- };
98
- (_b = document == null ? void 0 : document.body) == null ? void 0 : _b.insertAdjacentElement("beforeend", script);
99
- });
100
- };
101
- const importScriptDynamically = ({ path }) => {
102
- var _a;
103
- return (_a = import(path)) == null ? void 0 : _a.catch((err) => {
104
- });
105
- };
106
- const fireLoadListener = () => {
107
- const eventName = "load";
108
- const srcElements = document == null ? void 0 : document.querySelectorAll(`[on-${eventName}]`);
109
- srcElements == null ? void 0 : srcElements.forEach(async (srcElement) => {
110
- const listeners = await fetchListeners({ srcElement, eventName, e: null });
111
- executeListeners({ e: null, srcElement, listeners });
112
- srcElement == null ? void 0 : srcElement.removeAttribute(`on-${eventName}`);
113
- });
114
- };
115
- const fireObserverListeners = () => {
116
- var _a;
117
- const srcElements = [...document.querySelectorAll("[on-observe]")];
118
- const uniqueScriptNames = [...(_a = srcElements == null ? void 0 : srcElements.reduce((acc, srcElement) => {
119
- const attribute = srcElement == null ? void 0 : srcElement.getAttribute("on-observe");
120
- if (attribute === "undefined") return acc;
121
- const scriptNames = attribute == null ? void 0 : attribute.split(",");
122
- scriptNames == null ? void 0 : scriptNames.forEach((scriptName) => acc == null ? void 0 : acc.set(scriptName, 1));
123
- return acc;
124
- }, /* @__PURE__ */ new Map())) == null ? void 0 : _a.keys()];
125
- uniqueScriptNames == null ? void 0 : uniqueScriptNames.forEach(async (scriptName) => {
126
- const observedSrcElements = document.querySelectorAll(`[on-observe*="${scriptName}"]`);
127
- const script = await importScriptDynamically({ path: `/${scriptName == null ? void 0 : scriptName.trim()}.js` });
128
- const listener2 = getListenerFromScript({ script, eventName: "observe" });
129
- if (!listener2) return;
130
- const observer = new IntersectionObserver((entries) => {
131
- entries.forEach((entry) => listener2({ entry, observer }));
132
- }, {
133
- threshold: 0.5
134
- });
135
- observedSrcElements == null ? void 0 : observedSrcElements.forEach((observerSrcElement) => {
136
- var _a2, _b;
137
- observer.observe(observerSrcElement);
138
- const observerAttr = observerSrcElement == null ? void 0 : observerSrcElement.getAttribute("on-observe");
139
- const updatedObserverAttr = (_b = (_a2 = observerAttr == null ? void 0 : observerAttr.replaceAll(scriptName + ", ", "")) == null ? void 0 : _a2.replaceAll(", " + scriptName, "")) == null ? void 0 : _b.replaceAll(scriptName, "");
140
- if (!updatedObserverAttr) observerSrcElement.removeAttribute("on-observe");
141
- else observerSrcElement.setAttribute("on-observe", updatedObserverAttr);
142
- });
143
- });
144
- };
145
- const getSrcElement = ({ srcElement, eventName }) => {
146
- if (!(srcElement == null ? void 0 : srcElement.hasAttribute)) return srcElement;
147
- const attribute = `on-${eventName}`;
148
- const hasScriptName = srcElement == null ? void 0 : srcElement.hasAttribute(attribute);
149
- if (hasScriptName) return srcElement;
150
- const query = `:is(${["a", "button", ...SRC_ELEMEMENTS_QUERY].join(",")})[${attribute}]`;
151
- const closestButton = srcElement == null ? void 0 : srcElement.closest(query);
152
- if (closestButton) return closestButton;
153
- return srcElement;
154
- };
155
- const cloneSrcElement = ({ srcElement }) => {
156
- const newSrcElement = document.createElement(srcElement == null ? void 0 : srcElement.tagName);
157
- Array.from(srcElement == null ? void 0 : srcElement.attributes).forEach((attr) => {
158
- if (attr.name.startsWith("on-")) return;
159
- newSrcElement.setAttribute(attr.name, attr.value);
160
- });
161
- return newSrcElement;
162
- };
163
- const isAnchorBeingClicked = ({ srcElement, eventName }) => {
164
- return (srcElement == null ? void 0 : srcElement.tagName) === "A" && eventName === "click";
165
- };
166
- const clickDefaultAnchor = ({ srcElement }) => {
167
- const newAnchor = cloneSrcElement({ srcElement });
168
- newAnchor.click();
169
- };
170
- const fireListeners = () => {
171
- EVENTS.forEach((eventName) => {
172
- document.body[`on${eventName}`] = async (e) => {
173
- const srcElement = getSrcElement({ srcElement: e == null ? void 0 : e.srcElement, eventName });
174
- const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName });
175
- if (isAnchorClicked) e.preventDefault();
176
- const listeners = await fetchListeners({ srcElement, eventName, e });
177
- const afterExecuteListeners = isAnchorClicked ? () => {
178
- clickDefaultAnchor({ srcElement });
179
- } : null;
180
- executeListeners({ e, srcElement, listeners, afterExecuteListeners });
181
- addListener({ srcElement, eventName, listeners, afterExecuteListeners });
182
- if (srcElement == null ? void 0 : srcElement.removeAttribute) srcElement.removeAttribute(`on-${eventName}`);
183
- };
184
- });
185
- const saloeListenEvent = new CustomEvent("saloeListen", {
186
- detail: { message: "This is a custom eventName!" }
187
- });
188
- document.body.addEventListener("saloeListen", async (e) => {
189
- await addScripts();
190
- fireLoadListener();
191
- fireObserverListeners();
192
- });
193
- document.body.saloeListen = function() {
194
- document.body.dispatchEvent(saloeListenEvent);
195
- };
196
- };
197
- fireListeners();
198
- window.onload = () => {
199
- setTimeout(() => {
200
- document.body.saloeListen();
201
- }, listenAfterMs);
202
- };
203
- };
276
+
277
+ }
278
+
279
+ fireListeners()
280
+
281
+ window.onload = () => {
282
+ setTimeout(() => {
283
+ document.body.saloeListen()
284
+ }, listenAfterMs)
285
+ }
286
+ }`;
287
+ const listener = new Function("return (" + LISTENER_SCRIPT + ")")();
204
288
  const getScriptListener = ({
205
289
  SRC_ELEMEMENTS_QUERY = [],
206
290
  listenAfterMs = 2500
207
291
  } = {}) => {
208
- return `<script defer>(${listener.toString()})({ SRC_ELEMEMENTS_QUERY: ${JSON.stringify(SRC_ELEMEMENTS_QUERY)}, listenAfterMs: ${listenAfterMs} })<\/script>`;
292
+ return `<script defer>(${LISTENER_SCRIPT})({ SRC_ELEMEMENTS_QUERY: ${JSON.stringify(SRC_ELEMEMENTS_QUERY)}, listenAfterMs: ${listenAfterMs} })<\/script>`;
209
293
  };
210
294
  export {
211
295
  getScriptListener,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saloe",
3
- "version": "0.0.89",
3
+ "version": "0.0.91",
4
4
  "description": "Tools for making web development easy and efficient",
5
5
  "type": "module",
6
6
  "scripts": {