create-snapp-app 1.0.1 → 2.0.0

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/README.md CHANGED
@@ -6,5 +6,6 @@ Create new **Snapp** apps easily:
6
6
  npm create snapp-app myApp
7
7
 
8
8
  cd myApp
9
- npm run snapp
9
+ npm install
10
+ npm run dev
10
11
  ```
package/bin/create.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  import fs from "fs";
3
3
  import path from "path";
4
4
  import { fileURLToPath } from "url";
@@ -38,14 +38,27 @@ Example:
38
38
  fs.mkdirSync(targetPath, { recursive: true });
39
39
  fs.cpSync(templatePath, targetPath, { recursive: true });
40
40
 
41
+ // Replace {{APP_NAME}} in template files
42
+ const packageJsonPath = path.join(targetPath, "package.json");
43
+ if (fs.existsSync(packageJsonPath)) {
44
+ let content = fs.readFileSync(packageJsonPath, "utf-8");
45
+ fs.writeFileSync(packageJsonPath, content.replace(/{{APP_NAME}}/g, appName));
46
+ }
47
+
48
+ const indexHtmlPath = path.join(targetPath, "index.html");
49
+ if (fs.existsSync(indexHtmlPath)) {
50
+ let content = fs.readFileSync(indexHtmlPath, "utf-8");
51
+ fs.writeFileSync(indexHtmlPath, content.replace(/{{APP_NAME}}/g, appName));
52
+ }
53
+
41
54
  console.log(`
42
- Successfully created Snapp app!
55
+ Successfully created Snapp app: ${appName}!
43
56
 
44
57
  Next:
45
58
  cd ${appName}
46
59
 
47
60
  npm install
48
- npm run snapp
61
+ npm run dev
49
62
  `);
50
63
  } catch (error) {
51
64
  console.error("❌ Some error came up:", error.message);
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
- {
2
- "name": "create-snapp-app",
3
- "version": "1.0.1",
4
- "description": "Create Snapp apps with zero configuration",
5
- "type": "module",
6
- "bin": {
7
- "create-snapp-app": "./bin/create.js"
8
- },
9
- "files": [
10
- "bin",
11
- "template"
12
- ],
13
- "keywords": [
14
- "snapp",
15
- "create-snapp-app",
16
- "cli",
17
- "boilerplate"
18
- ],
19
- "author": "kigemmanuel",
20
- "license": "MIT",
21
- "engines": {
22
- "node": ">=14.0.0"
23
- }
24
- }
1
+ {
2
+ "name": "create-snapp-app",
3
+ "version": "2.0.0",
4
+ "description": "Create Snapp apps with zero configuration",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-snapp-app": "./bin/create.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "template"
12
+ ],
13
+ "keywords": [
14
+ "snapp",
15
+ "create-snapp-app",
16
+ "cli",
17
+ "boilerplate"
18
+ ],
19
+ "author": "kigemmanuel",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=14.0.0"
23
+ }
24
+ }
@@ -1,12 +1,13 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>snapp-app</title>
5
- <link rel="stylesheet" href="style/style.css">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- </head>
8
- <body>
9
- <div id="snapp-body"></div>
10
- <script type="module" src="src/index.js"></script>
11
- </body>
12
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>{{APP_NAME}}</title>
6
+ <link rel="stylesheet" href="style/style.css">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="public/index.js"></script>
12
+ </body>
13
+ </html>
@@ -1,12 +1,16 @@
1
1
  {
2
- "name": "snapp-app",
2
+ "name": "{{APP_NAME}}",
3
3
  "version": "1.0.0",
4
- "description": "My snapp app",
4
+ "description": "My Snapp app",
5
+ "type": "module",
5
6
  "scripts": {
6
- "snapp": "npx snapp build -E public -W",
7
- "snapp:minify": "npx snapp build -E public -M"
7
+ "dev": "npx snapp build -W",
8
+ "build": "npx snapp build -M"
9
+ },
10
+ "dependencies": {
11
+ "@snappjs/core": "^3.0.0"
8
12
  },
9
13
  "devDependencies": {
10
- "snapp-kit": "^3.0.0"
14
+ "snapp-kit": "^3.1.0"
11
15
  }
12
16
  }
@@ -0,0 +1 @@
1
+
@@ -1,39 +1,39 @@
1
-
2
- .button {
3
- background-color: #4a90e2;
4
- color: #fff;
5
- border: none;
6
- border-radius: 8px;
7
- padding: 10px 18px;
8
- font-size: 16px;
9
- cursor: pointer;
10
- transition: background 0.2s, transform 0.2s;
11
- }
12
-
13
- .button:hover {
14
- background-color: #357abd;
15
- transform: translateY(-2px);
16
- }
17
-
18
- .center-div {
19
- position: absolute;
20
- display: grid;
21
- place-items: center;
22
- top: 50%;
23
- left: 50%;
24
- width: 100%;
25
- transform: translate(-50%, -50%);
26
- }
27
-
28
- .a-href {
29
- color: #4a90e2;
30
- text-decoration: none;
31
- font-weight: bold;
32
- }
33
-
34
- .link-div {
35
- margin: 10px 0;
36
- display: flex;
37
- flex-direction: column;
38
- text-align: center;
39
- }
1
+
2
+ .button {
3
+ background-color: #4a90e2;
4
+ color: #fff;
5
+ border: none;
6
+ border-radius: 8px;
7
+ padding: 10px 18px;
8
+ font-size: 16px;
9
+ cursor: pointer;
10
+ transition: background 0.2s, transform 0.2s;
11
+ }
12
+
13
+ .button:hover {
14
+ background-color: #357abd;
15
+ transform: translateY(-2px);
16
+ }
17
+
18
+ .center-div {
19
+ position: absolute;
20
+ display: grid;
21
+ place-items: center;
22
+ top: 50%;
23
+ left: 50%;
24
+ width: 100%;
25
+ transform: translate(-50%, -50%);
26
+ }
27
+
28
+ .a-href {
29
+ color: #4a90e2;
30
+ text-decoration: none;
31
+ font-weight: bold;
32
+ }
33
+
34
+ .link-div {
35
+ margin: 10px 0;
36
+ display: flex;
37
+ flex-direction: column;
38
+ text-align: center;
39
+ }
@@ -1,11 +1,12 @@
1
-
2
- const Links = () => {
3
-
4
- return <div className="link-div">
5
- <a className="a-href" target="_blank" href="https://github.com/kigemmanuel/Snapp">Learn Snapp</a>
6
- <span className="a-href" style={{color: '#0C2340'}}>Please star and follow</span>
7
- </div>
8
-
9
- }
10
-
11
- export default Links
1
+ import snapp from "@snappjs/core"
2
+
3
+ const Links = () => {
4
+
5
+ return <div className="link-div">
6
+ <a className="a-href" target="_blank" href="https://github.com/SnappJS/snapp">Learn Snapp</a>
7
+ <span className="a-href" style={{color: '#0C2340'}}>Please star and follow</span>
8
+ </div>
9
+
10
+ }
11
+
12
+ export default Links
@@ -1,27 +1,28 @@
1
-
2
- import snapp from "../src/snapp.js"
3
- import Links from "./components/Links"
4
-
5
- const App = () => {
6
-
7
- const count = snapp.dynamic(0)
8
-
9
- return <div className="center-div">
10
-
11
- <img style={{width: "auto", height: "200px"}} src="assets/snapp.png" alt="snapp" />
12
- <h2>Welcome to snapp {() => count.value}</h2>
13
-
14
- <button
15
- className="button"
16
- onClick={() => count.update(count.value + 1)}
17
- >
18
- Click To Count
19
- </button>
20
-
21
- <Links />
22
- </div>
23
-
24
- }
25
-
26
- const SnappBody = document.querySelector("#snapp-body");
27
- snapp.render(SnappBody, App())
1
+ import snapp from "@snappjs/core"
2
+ import Links from "./components/Links"
3
+
4
+ const App = () => {
5
+
6
+ const count = snapp.dynamic(0)
7
+
8
+ return <div className="center-div">
9
+
10
+ <img style={{width: "auto", height: "200px"}} src="assets/snapp.png" alt="snapp" />
11
+ <h2>Welcome to Snapp {() => count.value}</h2>
12
+
13
+ <button
14
+ className="button"
15
+ onClick={() => count.update(count.value + 1)}
16
+ >
17
+ Click To Count
18
+ </button>
19
+
20
+ <Links />
21
+ </div>
22
+
23
+ }
24
+
25
+ const app = snapp.select("#app");
26
+ snapp.render(app, App(), null, () => {
27
+ console.log("Snapp rendered successfully")
28
+ })
@@ -1,22 +0,0 @@
1
- import snapp from "./snapp.js";
2
-
3
- // public/views/components/Links.jsx
4
- var Links = () => {
5
- return /* @__PURE__ */ snapp.create("div", { className: "link-div" }, /* @__PURE__ */ snapp.create("a", { className: "a-href", target: "_blank", href: "https://github.com/kigemmanuel/Snapp" }, "Learn Snapp"), /* @__PURE__ */ snapp.create("span", { className: "a-href", style: { color: "#0C2340" } }, "Please star and follow"));
6
- };
7
- var Links_default = Links;
8
-
9
- // public/views/index.jsx
10
- var App = () => {
11
- const count = snapp.dynamic(0);
12
- return /* @__PURE__ */ snapp.create("div", { className: "center-div" }, /* @__PURE__ */ snapp.create("img", { style: { width: "auto", height: "200px" }, src: "assets/snapp.png", alt: "snapp" }), /* @__PURE__ */ snapp.create("h2", null, "Welcome to snapp ", () => count.value), /* @__PURE__ */ snapp.create(
13
- "button",
14
- {
15
- className: "button",
16
- onClick: () => count.update(count.value + 1)
17
- },
18
- "Click To Count"
19
- ), /* @__PURE__ */ snapp.create(Links_default, null));
20
- };
21
- var SnappBody = document.querySelector("#snapp-body");
22
- snapp.render(SnappBody, App());
@@ -1,573 +0,0 @@
1
-
2
- /*
3
- * Snapp Framework v2.1.1
4
- * A lightweight JSX-like framework for vanilla JavaScript
5
- *
6
- * @version 2.1.1
7
- * @license MIT
8
- * @repository https://github.com/kigemmanuel/Snapp
9
- *
10
- * Features:
11
- * - JSX-like syntax compilation
12
- * - Component-based architecture
13
- * - Zero dependencies
14
- * - Lightweight and fast
15
- ;*l
16
- - Dynamic state
17
- *
18
- * Built with ❤️ for modern web development
19
- *
20
- * Copyright (c) 2025 kigemmanuel
21
- * Released under the MIT License
22
- */
23
-
24
- const snapp = (() => {
25
-
26
- var dataId = 0;
27
- var dynamicId = 1;
28
-
29
- var DOMReady = false;
30
- var track_dynamic = null;
31
-
32
- const dynamicData = {};
33
- const dynamicDependencies = new Map();
34
-
35
- const eventListener = {};
36
- const elementEvent = {};
37
-
38
- const eventMap = {
39
- 'onmouseenter': 'onmouseover',
40
- 'onmouseleave': 'onmouseout',
41
- 'ondoubleclick': 'ondblclick'
42
- };
43
-
44
- const SVG_ELEMENTS = new Set([
45
- 'svg', 'circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect',
46
- 'text', 'textPath', 'tspan', 'defs', 'g', 'marker', 'mask', 'pattern',
47
- 'switch', 'symbol', 'linearGradient', 'radialGradient', 'stop', 'filter',
48
- 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite',
49
- 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight',
50
- 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR',
51
- 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology',
52
- 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile',
53
- 'feTurbulence', 'image', 'use', 'foreignObject', 'animate', 'animateMotion',
54
- 'animateTransform', 'mpath', 'set', 'clipPath', 'desc', 'metadata', 'view'
55
- ]);
56
-
57
- const create = (element, props, ...children) => {
58
- const flatChildren = flattenChildren(children);
59
- if (element != "<>" && typeof element === "string")
60
- return createElement(element, props, flatChildren);
61
-
62
-
63
- if (typeof element === 'function')
64
- return createComponent(element, props, flatChildren);
65
-
66
- if (element === "<>")
67
- return createFragment(flatChildren);
68
- }
69
-
70
- const render = (body, App, type, callBack) => {
71
-
72
- if (!document.contains(body)) {
73
- console.error("ERROR: Rending to a non existing/removed element", body)
74
- if (typeof callBack === "function") return callBack(false)
75
- }
76
-
77
- if (typeof App === 'string' || typeof App === 'number' || App instanceof Element || App instanceof DocumentFragment) {
78
- DOMReady = false;
79
-
80
- switch (true) {
81
- case (type === "before"):
82
- body.before(App);
83
- break;
84
-
85
- case (type === "prepend"):
86
- body.prepend(App);
87
- break;
88
-
89
- case (type === "replace"):
90
- body.replaceWith(App);
91
- break;
92
-
93
- case (type === "append"):
94
- body.append(App);
95
- break;
96
-
97
- case (type === "after"):
98
- body.after(App);
99
- break;
100
-
101
- default:
102
- body.replaceChildren(App);
103
- break;
104
- }
105
-
106
- DOMReady = true;
107
- document.dispatchEvent(new Event("DOM"))
108
- if (typeof callBack === "function") return callBack(true);
109
-
110
- } else {
111
- console.error("Failed to render! ", typeof App, App)
112
- if (typeof callBack === "function") return callBack(false)
113
- }
114
- }
115
-
116
- const remove = (items) => {
117
-
118
- items = (Array.isArray(items)) ? items : [items];
119
-
120
- items.forEach(item => {
121
-
122
- if (item instanceof Element) {
123
- item.remove()
124
- }
125
-
126
- })
127
- }
128
-
129
- const on = (event, callBack) => {
130
-
131
- if (typeof event === "string" && event.toUpperCase() === "DOM") {
132
- if (DOMReady === true) {
133
- callBack()
134
- } else {
135
- document.addEventListener(event.toUpperCase(), callBack, { once: true })
136
- }
137
- }
138
-
139
- }
140
-
141
- const select = (name) => {
142
- if (typeof name === 'string') {
143
- const element = document.querySelector(name);
144
- if (!element) {
145
- console.error(`Element with "${name}" not found`)
146
- return null
147
- }
148
- return element
149
- }
150
-
151
- if (Array.isArray(name)) {
152
- return name.map(ele => {
153
- const element = document.querySelector(ele)
154
- if (!element) {
155
- console.error(`Element with "${ele}" not found`);
156
- return null
157
- }
158
- return element
159
- })
160
- }
161
- console.error("Invalid selector!")
162
- return null;
163
- }
164
-
165
- const selectAll = (name) => {
166
- if (typeof name === 'string') {
167
- const element = document.querySelectorAll(name)
168
-
169
- if (element.length === 0) {
170
- console.error(`Element with "${name}" not found`)
171
- return null
172
- }
173
- return element
174
- }
175
-
176
- if (Array.isArray(name)) {
177
- return name.map(ele => {
178
- const element = document.querySelectorAll(ele)
179
-
180
- if (element.length === 0) {
181
- console.error(`Element with "${ele}" not found`)
182
- return null
183
- }
184
- return element;
185
- })
186
- }
187
- console.error("Invalid selector!")
188
- return null;
189
- }
190
-
191
- const createElement = (element, props, children) => {
192
- const ele = SVG_ELEMENTS.has(element)
193
- ? document.createElementNS("http://www.w3.org/2000/svg", element)
194
- : document.createElement(element);
195
-
196
- dataId++
197
-
198
- if (props) {
199
- for (let [key, value] of Object.entries(props)) {
200
-
201
- if (value == null || value === false) continue
202
-
203
- if (key === "className") key = "class";
204
- if (key === "htmlFor") key = "for";
205
-
206
- if (value === true || value === "") {
207
- ele.setAttribute(key, "")
208
- continue
209
- }
210
-
211
- if (key === 'style') {
212
- if (typeof value === 'object') {
213
- for (const [property, style] of Object.entries(value)) {
214
- track_dynamic = new Set()
215
- const mainStyle = (typeof style === "function") ? style() : style;
216
- const newDynamicId = [...track_dynamic]
217
- track_dynamic = null;
218
-
219
- if (newDynamicId.length > 0) {
220
- const subscribeData = {
221
- type: "style",
222
- prop: property,
223
- temp: style,
224
- subscribe: newDynamicId
225
- }
226
-
227
- ele.setAttribute("snapp-dynamic", dataId);
228
- subscribeDynamic(newDynamicId, subscribeData, ele)
229
- }
230
-
231
- if (property.includes('-')) {
232
- ele.style.setProperty(property, mainStyle);
233
- } else {
234
- ele.style[property] = mainStyle;
235
- }
236
- }
237
- }
238
- else {
239
- console.warn(`Invalid style for ${element} `, value)
240
- continue
241
- }
242
- continue;
243
- }
244
-
245
- if (key.startsWith("on") && key !== "on" && typeof value === "function") {
246
- let lowerCaseKey = key.toLowerCase();
247
- lowerCaseKey = eventMap[lowerCaseKey] || lowerCaseKey;
248
-
249
- if (lowerCaseKey in ele) {
250
- const eventType = lowerCaseKey.slice(2);
251
- ele.setAttribute("snapp-data", dataId);
252
- addEventListener(eventType, value, dataId);
253
- ele.setAttribute("snapp-e-" + eventType, "true");
254
- } else {
255
- console.warn(`Event "${lowerCaseKey}", Do not exist for `, ele)
256
- }
257
- continue;
258
- }
259
-
260
- if (typeof value === "function" && !key.startsWith("on")) {
261
- track_dynamic = new Set()
262
- ele.setAttribute(key, value())
263
- const newDynamicId = [...track_dynamic]
264
- track_dynamic = null;
265
-
266
- if (newDynamicId.length > 0) {
267
- const subscribeData = {
268
- type: "attr",
269
- attr: key,
270
- temp: value,
271
- subscribe: newDynamicId
272
- }
273
-
274
- ele.setAttribute("snapp-dynamic", dataId);
275
- subscribeDynamic(newDynamicId, subscribeData, ele)
276
- }
277
-
278
- continue;
279
- }
280
-
281
- // Default
282
- ele.setAttribute(key, value);
283
- }
284
- }
285
-
286
- children.forEach(node => {
287
- if (typeof node === 'string' || typeof node === 'number' || node instanceof Element || node instanceof DocumentFragment) {
288
- ele.append(node);
289
- return;
290
- }
291
-
292
- if (typeof node === 'function') {
293
- track_dynamic = new Set()
294
- const textNode = document.createTextNode(node())
295
- const newDynamicId = [...track_dynamic]
296
- track_dynamic = null;
297
-
298
- if (newDynamicId.length > 0) {
299
- const subscribeData = {
300
- type: "node",
301
- node: textNode,
302
- temp: node,
303
- subscribe: newDynamicId
304
- }
305
-
306
- ele.setAttribute("snapp-dynamic", dataId);
307
- subscribeDynamic(newDynamicId, subscribeData, ele)
308
- }
309
-
310
- ele.append(textNode)
311
- }
312
- });
313
-
314
- return ele;
315
- }
316
-
317
- const createFragment = (children) => {
318
- const frag = document.createDocumentFragment();
319
- children.forEach(node => {
320
- if (typeof node === 'string' || typeof node === 'number' || node instanceof Element || node instanceof DocumentFragment) {
321
- frag.append(node);
322
- }
323
- });
324
-
325
- return frag;
326
- }
327
-
328
- const createComponent = (element, props = {}, children) => {
329
- const totalProps = { ...props, children };
330
- const comp = element(totalProps);
331
-
332
- return comp;
333
- }
334
-
335
- const flattenChildren = (children) => {
336
- const final = []
337
-
338
- for (const child of children) {
339
- if (Array.isArray(child)) {
340
- final.push(...flattenChildren(child))
341
- } else if (child !== null && child !== undefined && child !== '' && child !== false) {
342
- final.push(child)
343
- }
344
- }
345
-
346
- return final
347
- }
348
-
349
-
350
- const applystyle = (element, styles) => {
351
- element = (Array.isArray(element)) ? element : [element];
352
-
353
- element.forEach(ele => {
354
-
355
- if (!(ele instanceof Element)) {
356
- console.error(`Error! can not apply style to "${element}", selelct a valid element`)
357
- return;
358
- }
359
-
360
- if (typeof styles === "object") {
361
- for (const [property, style] of Object.entries(styles)) {
362
- if (property.includes('-')) {
363
- ele.style.setProperty(property, style);
364
- } else {
365
- ele.style[property] = style;
366
- }
367
- }
368
- }
369
- })
370
- }
371
-
372
- const removestyle = (element, styles) => {
373
- element = (Array.isArray(element)) ? element : [element];
374
-
375
- element.forEach(ele => {
376
- if (!(ele instanceof Element)) {
377
- console.error(`Error! can not remove style from "${element}", selelct a valid element`)
378
- return;
379
- }
380
-
381
- if (styles === true) return ele.removeAttribute("style")
382
- if (typeof styles === "object") {
383
- for (const [property, style] of Object.entries(styles)) {
384
- if (property.includes('-')) {
385
- ele.style.removeProperty(property);
386
- } else {
387
- ele.style[property] = "";
388
- }
389
- }
390
- }
391
- })
392
- }
393
-
394
-
395
- const addEventListener = (eventType, event, elementId) => {
396
-
397
- const eventTemplate = (element) => {
398
- const target = element.target;
399
-
400
- if (!target || target.nodeType !== 1) {
401
- console.log('Target is not an element, skipping...');
402
- return;
403
- }
404
-
405
- const elWithAttr = target.closest(`[snapp-e-${eventType}]`);
406
- if (!elWithAttr) return;
407
- const elementDataId = elWithAttr.getAttribute("snapp-data");
408
- elementEvent[eventType]?.[elementDataId](element)
409
- }
410
-
411
- if (!(eventType in eventListener)) {
412
- elementEvent[eventType] = {}
413
-
414
- eventListener[eventType] = eventTemplate;
415
- document.addEventListener(eventType, eventListener[eventType])
416
- }
417
-
418
- elementEvent[eventType][elementId] = event;
419
- }
420
-
421
-
422
- const dynamic = (initialtValue = "") => {
423
- const id = `dynamic-${dynamicId++}`;
424
- dynamicData[id] = {
425
- value: initialtValue,
426
- subscribe: new Map()
427
- };
428
-
429
- const update = (newValue) => {
430
- if (dynamicData[id].value !== newValue) {
431
- dynamicData[id].value = newValue;
432
- for (const [element, items] of dynamicData[id].subscribe) {
433
- updateDynamicValue(element, items)
434
- }
435
- }
436
- }
437
-
438
- return {
439
- get value() {
440
- if (track_dynamic) {
441
- track_dynamic.add(id)
442
- }
443
- return dynamicData[id].value
444
- },
445
- update,
446
- }
447
- }
448
-
449
- const updateDynamicValue = (element, items) => {
450
- items.forEach(item => {
451
- const dynamic = dynamicDependencies.get(element)?.[item];
452
- if (dynamic) {
453
- const previousDynamicId = new Set(dynamic.subscribe);
454
- track_dynamic = new Set();
455
- const newTemp = dynamic.temp();
456
- const newTrack_dynamic = [...track_dynamic]
457
- track_dynamic = null;
458
-
459
- if (dynamic.type === "node") {
460
- dynamic.node.nodeValue = newTemp;
461
- } else if (dynamic.type === "attr") {
462
- element.setAttribute(dynamic.attr, newTemp)
463
- } else if (dynamic.type === "style") {
464
- if (newTemp.includes('-')) {
465
- element.style.setProperty(dynamic.prop, newTemp);
466
- } else {
467
- element.style[dynamic.prop] = newTemp;
468
- }
469
- }
470
-
471
- newTrack_dynamic.forEach(dynamicId => {
472
- if (previousDynamicId.has(dynamicId)) return
473
-
474
- if (!dynamicData[dynamicId]["subscribe"].has(element)) {
475
- dynamicData[dynamicId]["subscribe"].set(element, [])
476
- }
477
- dynamicData[dynamicId]["subscribe"].get(element).push(item)
478
- dynamicDependencies.get(element)[item].subscribe.push(dynamicId)
479
- })
480
- }
481
-
482
- })
483
- }
484
-
485
- const subscribeDynamic = (dynamicId, subscribeData, element) => {
486
- if (!dynamicDependencies.has(element)) {
487
- dynamicDependencies.set(element, [])
488
- }
489
- dynamicDependencies.get(element).push(subscribeData)
490
- const subscribeIndex = dynamicDependencies.get(element).length - 1;
491
-
492
- dynamicId.forEach(id => {
493
- if (!dynamicData[id]) return
494
-
495
- if (!dynamicData[id]["subscribe"].has(element)) {
496
- dynamicData[id]["subscribe"].set(element, [])
497
- }
498
-
499
- dynamicData[id]["subscribe"].get(element).push(subscribeIndex)
500
- })
501
- }
502
-
503
- const observer = new MutationObserver((mutations) => {
504
- mutations.forEach(element => {
505
- element.removedNodes.forEach(node => {
506
- if (node instanceof Element) {
507
- const elementDataId = node.getAttribute("snapp-data");
508
- if (elementDataId) {
509
- for (const attrName of node.getAttributeNames()) {
510
- if (attrName.startsWith('snapp-e-')) {
511
- const eventType = attrName.replace("snapp-e-", "");
512
-
513
- if (elementEvent[eventType]?.[elementDataId]) {
514
- delete elementEvent[eventType]?.[elementDataId]
515
- }
516
-
517
- if (Object.keys(elementEvent[eventType]).length === 0) {
518
- document.removeEventListener(eventType, eventListener[eventType])
519
- delete eventListener[eventType]
520
- delete elementEvent[eventType]
521
- }
522
- }
523
- }
524
- };
525
-
526
- if (node.getAttribute("snapp-dynamic")) {
527
- dynamicDependencies.delete(node);
528
- callCleardynamicElement()
529
- }
530
-
531
- }
532
- })
533
- });
534
- })
535
- observer.observe(document, {
536
- childList: true,
537
- subtree: true
538
- })
539
-
540
- let timeOut = null;
541
- let callCount = 0;
542
- const callCleardynamicElement = (delay = 15000, threshold = 30) => {
543
- callCount++
544
- clearTimeout(timeOut);
545
-
546
- if (callCount >= threshold) {
547
- cleardynamicElement()
548
- callCount = 0;
549
- } else {
550
- timeOut = setTimeout(() => {
551
- cleardynamicElement()
552
- callCount = 0;
553
- }, delay)
554
- }
555
- }
556
-
557
- const cleardynamicElement = () => {
558
- for (const [dynamicId, items] of Object.entries(dynamicData)) {
559
- for (const [element, data] of items.subscribe) {
560
- if (!element.isConnected) {
561
- dynamicData[dynamicId].subscribe.delete(element)
562
- }
563
- }
564
- }
565
- }
566
-
567
- return {
568
- create, render, on, select, selectAll, applystyle, removestyle, remove, dynamic
569
- }
570
-
571
- })()
572
-
573
- export default snapp;
File without changes