wowojs-cdn 1.2.3 → 1.3.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
@@ -2,14 +2,14 @@
2
2
 
3
3
  Gunakan **Wowojs** langsung di browser tanpa install NPM. Cocok buat prototyping cepat atau buat lu yang pengen sat-set langsung ngoding di file HTML dan buat pemula
4
4
 
5
- ---
5
+ **Versi Wowojs saat ini: 1.5.0**
6
6
 
7
7
  ## Cara Pakai
8
8
 
9
9
  Cukup tempelkan script ini di dalam tag `<head>` atau sebelum penutup `</body>`:
10
10
 
11
11
  ```html
12
- <script src="https://cdn.jsdelivr.net/npm/wowojs-cdn@1.2.3/dist/wowo.min.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/wowojs-cdn@1.3.0/dist/wowo.min.js"></script>
13
13
  <!-- ATAU -->
14
14
  <script src="https://unpkg.com/wowojs-cdn/dist/wowo.min.js"></script>
15
15
  1
@@ -21,7 +21,7 @@ Cukup tempelkan script ini di dalam tag `<head>` atau sebelum penutup `</body>`:
21
21
  <!DOCTYPE html>
22
22
  <html lang="id">
23
23
  <head>
24
- <script src="https://cdn.jsdelivr.net/npm/wowojs-cdn@1.2.3/dist/wowo.min.js"></script>
24
+ <script src="https://cdn.jsdelivr.net/npm/wowojs-cdn@1.3.0/dist/wowo.min.js"></script>
25
25
  </head>
26
26
  <body>
27
27
  <wowo-halo></wowo-halo>
@@ -29,9 +29,15 @@ Cukup tempelkan script ini di dalam tag `<head>` atau sebelum penutup `</body>`:
29
29
  <script>
30
30
  $BuatWilayah({
31
31
  namaWilayah: "halo",
32
- isiWilayah: () => "<h1>Halo dari Wowojs CDN! ?</h1>",
32
+ isiWilayah: () => "<h1>Halo dari Wowojs CDN!</h1>",
33
33
  });
34
34
  </script>
35
35
  </body>
36
36
  </html>
37
37
  ```
38
+
39
+ ## Links
40
+
41
+ - [Wowojs](https://www.npmjs.com/package/wowojs "Library Wowojs")
42
+ - [Github](https://www.github.com/deviedcodev/wowo.js "Repositori Github")
43
+ - [Create-wowo](https://www.npmjs.com/package/create-wowo "Framework Wowojs")
package/dist/wowo.min.js CHANGED
@@ -1 +1 @@
1
- !function(){"use strict";function t(t,e){n({modul:"State: $antek2",detail:{nama:t,value:e}});const a=sessionStorage.getItem(t);let o=null;try{if(null!==a&&(o=JSON.parse(a)),"function"==typeof e){const a=e(o);return sessionStorage.setItem(t,JSON.stringify(a)),a}return 1===arguments.length?o:(sessionStorage.setItem(t,JSON.stringify(e)),e)}catch(r){if(console.error(`Gagal memproses JSON untuk "${t}", mereset data...`,r),arguments.length>1){const a="function"==typeof e?e(null):e;return sessionStorage.setItem(t,JSON.stringify(a)),a}return null}}function e(t){const e=document.querySelector(t);e&&"function"==typeof e.render?e.render():document.addEventListener("DOMContentLoaded",()=>{e&&e.render()},{once:!0})}let a=[];function n({modul:t,detail:e,aktif:n=!1}){a.push({waktu:(new Date).toLocaleTimeString(),modul:t,detail:e}),n&&console.dir(a)}window.$BuatWilayah=function({namaWilayah:t,isiWilayah:e,style:a="",methods:o={},deskripsi:r}){n({modul:"Component: $BuatWilayah",detail:{namaWilayah:t,isiWilayah:e,style:a||"tidak ada",methods:o||"tidak ada",deskripsi:r||"tidak ada"}});const i=`wowo-${t.toLowerCase()}`;customElements.get(i)||customElements.define(i,class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}getProps(){const t={};for(let e of this.attributes)t[e.name]=e.value;return t}render(){const t=this.getProps(),n="function"==typeof e?e(t):e;let r=a?`<style>${a}</style>`:"";this.shadowRoot.innerHTML=n+r;this.shadowRoot.querySelectorAll("*").forEach(e=>{[...e.attributes].forEach(a=>{if(a.name.startsWith("@")){const n=a.name.slice(1),r=a.value.replace("()","");o[r]&&(e.addEventListener(n,e=>{o[r](e,t),this.render()}),e.removeAttribute(a.name))}})})}})},window.$antek2=t,window.$PecatAntek2=function(t){n({modul:"State: $PecatAntek2",detail:{nama:t}}),"string"==typeof t&&t.trim()||console.warn(`Nama tidak valid: ${t}`),null===sessionStorage.getItem(t)&&console.info(`Key "${t}" tidak ditemukan, tidak ada yang dihapus.`);try{sessionStorage.removeItem(t)}catch(e){console.error(`Gagal menghapus ${t}:`,e)}},window.$BangunEkonomi=function(t){n({modul:"Render: $BangunEkonomi",detail:t}),Array.isArray(t)?t.forEach(t=>{e(t)}):e(t)},window.$UrusKeuangan=function(t,e){n({modul:"Reducer: $UrusKeuangan",detail:[{reducer:t,action:e}]});try{return t(e)}catch(a){console.error(`terjadi error ${t} \n ${a}`)}},window.$CuriData=async function({data:e,state:a,request:o,reload:r=!1}){try{const i=await fetch(e,o);if(!i.ok)throw new Error(`Status: ${i.status}`);const s=await i.json();if(!s||"object"!=typeof s&&!Array.isArray(s))throw new Error(`Data ${e} bukan JSON kocak`);t(a,s),n({modul:"API: $CuriData",detail:{data:e,state:a}}),r&&location.reload()}catch(i){console.error(`Gagal curi data ${e}\n ${i}`)}},window.$Sejarah=n}();
1
+ var Wowo=function(e){"use strict";function t({namaWilayah:e,isiWilayah:t,style:a="",methods:o={},deskripsi:r,noShadow:i=!1}){n({modul:"Component: $BuatWilayah",detail:{namaWilayah:e,isiWilayah:t,style:a||"tidak ada",methods:o||"tidak ada",deskripsi:r||"tidak ada",noShadow:i||!1}});const s=`wowo-${e.toLowerCase()}`;customElements.get(s)||customElements.define(s,class extends HTMLElement{constructor(){super(),i||this.attachShadow({mode:"open"})}connectedCallback(){this.render()}getProps(){const e={};for(let t of this.attributes)e[t.name]=t.value;return e}render(){const e=this.getProps(),n="function"==typeof t?t(e):t;let r=a?`<style>${a}</style>`:"";const s=i?this:this.shadowRoot;if(s){s.innerHTML=n+r;s.querySelectorAll("*").forEach(t=>{[...t.attributes].forEach(a=>{if(a.name.startsWith("@")){const n=a.name.slice(1),r=a.value.replace("()","");o[r]&&(t.addEventListener(n,t=>{o[r](t,e),this.render()}),t.removeAttribute(a.name))}})})}}})}function a(e,t){if(n({modul:"State: $antek2",detail:{nama:e,value:t}}),1===arguments.length){if(void 0!==cacheAntek[e])return cacheAntek[e];const t=sessionStorage.getItem(e);try{const a=null!==t?JSON.parse(t):null;return cacheAntek[e]=a,a}catch(r){return console.error(`Data "${e}" korup, isinya:`,t),null}}let o;if("function"==typeof t){o=t(a(e))}else o=t;try{const t=JSON.stringify(o);return sessionStorage.setItem(e,t),cacheAntek[e]=o,o}catch(r){return console.error(`Gagal menyimpan "${e}":`,r),o}}function n({modul:e,detail:t,aktif:a=!1}){history.push({waktu:(new Date).toLocaleTimeString(),modul:e,detail:t}),a&&console.dir(history)}function o(e){window.history.pushState({},"",e),window.dispatchEvent(new PopStateEvent("popstate"))}return window.$BuatWilayah=t,window.$antek2=a,window.$PecatAntek2=function(e){n({modul:"State: $PecatAntek2",detail:{nama:e}}),delete cacheAntek[e],sessionStorage.removeItem(e)},window.$BangunEkonomi=function(e){n({modul:"Render: $BangunEkonomi",detail:e}),(Array.isArray(e)?e:[e]).forEach(e=>{!function(e){const t=()=>{const t=document.querySelectorAll(e);t.length>0?t.forEach(e=>{"function"==typeof e.render&&e.render()}):console.warn(`[WowoJS] Gagal bangun ekonomi: ${e} tidak ditemukan di DOM.`)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t,{once:!0}):t()}(e)})},window.$UrusKeuangan=function(e,t){n({modul:"Reducer: $UrusKeuangan",detail:[{reducer:e,action:t}]});try{return e(t)}catch(a){console.error(`terjadi error ${e} \n ${a}`)}},window.$CuriData=async function({data:e,state:t,request:o={},reload:r=!1}){try{const i={cache:"no-store",...o},s=await fetch(e,i);if(!s.ok)throw new Error(`Status: ${s.status} - Lu mau curi apa? Gak ada datanya!`);const c=await s.json();if(null===c||"object"!=typeof c)throw new Error(`Data dari ${e} bukan JSON yang bener, kocak`);return a(t,c),n({modul:"API: $CuriData",detail:{data:e,state:t}}),r&&requestAnimationFrame(()=>{const e=document.querySelector("wowo-router");e&&"function"==typeof e.render&&e.render()}),c}catch(i){return console.error("[WowoJS Error] Gagal curi data:",i.message),null}},window.$Sejarah=n,window.$Ke=o,window.$Router=function(e){const n=()=>{const t=window.location.pathname||"/",n=(o=t).length>1&&o.endsWith("/")?o.slice(0,-1):o;var o;let r={},i=null;for(const a of e){let e=a.route.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*").replace(/:(\w+)/g,"([^/]+)");const t=new RegExp("^"+e+"$"),o=n.match(t);if(o){i=a;(a.route.match(/:(\w+)/g)||[]).map(e=>e.slice(1)).forEach((e,t)=>{r[e]=o[t+1]});break}}if(i||(i=e.find(e=>"*"===e.route)),i){a("params",r||{}),a("halaman_aktif",Array.isArray(i.wilayah)?i.wilayah[0]:i.wilayah),queueMicrotask(()=>{const e=document.querySelector("wowo-router");e&&"function"==typeof e.render&&e.render()})}};n(),t({namaWilayah:"router",noShadow:!0,isiWilayah:()=>a("halaman_aktif")||""});const r=e=>{const t=e.target.closest("a");if(t&&t.href.startsWith(window.location.origin)){const a=t.getAttribute("href");!a||a.startsWith("#")||t.target||(e.preventDefault(),o(a))}};window.removeEventListener("click",r),window.addEventListener("click",r),window.onpopstate=()=>n()},e.$Ke=o,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),e}({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wowojs-cdn",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "Akses wowojs lewat CDN",
5
5
  "main": "wowo.js",
6
6
  "unpkg": "dist/wowo.min.js",
@@ -13,7 +13,8 @@
13
13
  "author": "",
14
14
  "license": "ISC",
15
15
  "dependencies": {
16
- "vite": "^7.3.1"
16
+ "vite": "^7.3.1",
17
+ "wowojs": "^1.5.0"
17
18
  },
18
19
  "devDependencies": {
19
20
  "terser": "^5.46.0"
package/wowo.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Wowojs v1.2.1
2
+ * Wowojs v1.5.0
3
3
  * @license MIT
4
4
  * @author Devied Rahmadsyah
5
5
  */
@@ -10,6 +10,7 @@ function $BuatWilayah({
10
10
  style = "",
11
11
  methods = {},
12
12
  deskripsi,
13
+ noShadow = false,
13
14
  }) {
14
15
  $Sejarah({
15
16
  modul: "Component: $BuatWilayah",
@@ -19,6 +20,7 @@ function $BuatWilayah({
19
20
  style: style || "tidak ada",
20
21
  methods: methods || "tidak ada",
21
22
  deskripsi: deskripsi || "tidak ada",
23
+ noShadow: noShadow || false,
22
24
  },
23
25
  });
24
26
 
@@ -30,7 +32,9 @@ function $BuatWilayah({
30
32
  class extends HTMLElement {
31
33
  constructor() {
32
34
  super();
33
- this.attachShadow({ mode: "open" });
35
+ if (!noShadow) {
36
+ this.attachShadow({ mode: "open" });
37
+ }
34
38
  }
35
39
 
36
40
  connectedCallback() {
@@ -50,27 +54,32 @@ function $BuatWilayah({
50
54
  const konten =
51
55
  typeof isiWilayah === "function" ? isiWilayah(props) : isiWilayah;
52
56
  let css = style ? `<style>${style}</style>` : "";
53
- this.shadowRoot.innerHTML = konten + css;
54
57
 
55
- const allElements = this.shadowRoot.querySelectorAll("*");
58
+ const target = noShadow ? this : this.shadowRoot;
59
+
60
+ if (target) {
61
+ target.innerHTML = konten + css;
56
62
 
57
- allElements.forEach((el) => {
58
- [...el.attributes].forEach((attr) => {
59
- if (attr.name.startsWith("@")) {
60
- const eventType = attr.name.slice(1);
61
- const functionName = attr.value.replace("()", "");
63
+ const allElements = target.querySelectorAll("*");
62
64
 
63
- if (methods[functionName]) {
64
- el.addEventListener(eventType, (e) => {
65
- methods[functionName](e, props);
66
- this.render();
67
- });
65
+ allElements.forEach((el) => {
66
+ [...el.attributes].forEach((attr) => {
67
+ if (attr.name.startsWith("@")) {
68
+ const eventType = attr.name.slice(1);
69
+ const functionName = attr.value.replace("()", "");
68
70
 
69
- el.removeAttribute(attr.name);
71
+ if (methods[functionName]) {
72
+ el.addEventListener(eventType, (e) => {
73
+ methods[functionName](e, props);
74
+ this.render();
75
+ });
76
+
77
+ el.removeAttribute(attr.name);
78
+ }
70
79
  }
71
- }
80
+ });
72
81
  });
73
- });
82
+ }
74
83
  }
75
84
  },
76
85
  );
@@ -79,78 +88,50 @@ function $BuatWilayah({
79
88
  function $antek2(name, value) {
80
89
  $Sejarah({
81
90
  modul: "State: $antek2",
82
- detail: {
83
- nama: name,
84
- value: value,
85
- },
91
+ detail: { nama: name, value: value },
86
92
  });
87
- const dataLama = sessionStorage.getItem(name);
88
- let parsedLama = null;
89
93
 
90
- try {
91
- if (dataLama !== null) {
92
- parsedLama = JSON.parse(dataLama);
93
- }
94
+ if (arguments.length === 1) {
95
+ if (cacheAntek[name] !== undefined) return cacheAntek[name];
94
96
 
95
- if (typeof value === "function") {
96
- const newValue = value(parsedLama);
97
- sessionStorage.setItem(name, JSON.stringify(newValue));
98
- return newValue;
99
- } else if (arguments.length === 1) {
100
- return parsedLama;
101
- } else {
102
- sessionStorage.setItem(name, JSON.stringify(value));
103
- return value;
97
+ const raw = sessionStorage.getItem(name);
98
+ try {
99
+ const parsed = raw !== null ? JSON.parse(raw) : null;
100
+ cacheAntek[name] = parsed;
101
+ return parsed;
102
+ } catch (e) {
103
+ console.error(`Data "${name}" korup, isinya:`, raw);
104
+ return null;
104
105
  }
105
- } catch (e) {
106
- console.error(`Gagal memproses JSON untuk "${name}", mereset data...`, e);
107
- if (arguments.length > 1) {
108
- const defaultValue = typeof value === "function" ? value(null) : value;
109
- sessionStorage.setItem(name, JSON.stringify(defaultValue));
110
- return defaultValue;
111
- }
112
- return null;
113
- }
114
- }
115
-
116
- function $PecatAntek2(name) {
117
- $Sejarah({
118
- modul: "State: $PecatAntek2",
119
- detail: {
120
- nama: name,
121
- },
122
- });
123
- if (typeof name !== "string" || !name.trim()) {
124
- console.warn(`Nama tidak valid: ${name}`);
125
106
  }
126
107
 
127
- if (sessionStorage.getItem(name) === null) {
128
- console.info(`Key "${name}" tidak ditemukan, tidak ada yang dihapus.`);
108
+ let newValue;
109
+ if (typeof value === "function") {
110
+ const dataLama = $antek2(name);
111
+ newValue = value(dataLama);
112
+ } else {
113
+ newValue = value;
129
114
  }
130
115
 
131
116
  try {
132
- sessionStorage.removeItem(name);
117
+ const stringified = JSON.stringify(newValue);
118
+ sessionStorage.setItem(name, stringified);
119
+ cacheAntek[name] = newValue;
120
+ return newValue;
133
121
  } catch (e) {
134
- console.error(`Gagal menghapus ${name}:`, e);
122
+ console.error(`Gagal menyimpan "${name}":`, e);
123
+ return newValue;
135
124
  }
136
125
  }
137
126
 
138
- function $UrusKeuangan(reducer, action) {
127
+ function $PecatAntek2(name) {
139
128
  $Sejarah({
140
- modul: "Reducer: $UrusKeuangan",
141
- detail: [
142
- {
143
- reducer: reducer,
144
- action: action,
145
- },
146
- ],
129
+ modul: "State: $PecatAntek2",
130
+ detail: { nama: name },
147
131
  });
148
- try {
149
- return reducer(action);
150
- } catch (error) {
151
- console.error(`terjadi error ${reducer}
152
- ${error}`);
153
- }
132
+
133
+ delete cacheAntek[name];
134
+ sessionStorage.removeItem(name);
154
135
  }
155
136
 
156
137
  function $BangunEkonomi(components) {
@@ -158,66 +139,195 @@ function $BangunEkonomi(components) {
158
139
  modul: "Render: $BangunEkonomi",
159
140
  detail: components,
160
141
  });
161
- if (Array.isArray(components)) {
162
- components.forEach((comp) => {
163
- const selector = typeof comp === "string" ? comp : comp;
164
- eksekusi(selector);
165
- });
166
- } else {
167
- eksekusi(components);
168
- }
142
+
143
+ const targets = Array.isArray(components) ? components : [components];
144
+
145
+ targets.forEach((selector) => {
146
+ eksekusi(selector);
147
+ });
169
148
  }
170
- function eksekusi(components) {
171
- const element = document.querySelector(components);
172
- if (element && typeof element.render === "function") {
173
- element.render();
149
+
150
+ function eksekusi(selector) {
151
+ const jalankan = () => {
152
+ // Pakai querySelectorAll biar semua komponen sejenis dapet update
153
+ const elements = document.querySelectorAll(selector);
154
+
155
+ if (elements.length > 0) {
156
+ elements.forEach((el) => {
157
+ if (typeof el.render === "function") {
158
+ el.render();
159
+ }
160
+ });
161
+ } else {
162
+ console.warn(
163
+ `[WowoJS] Gagal bangun ekonomi: ${selector} tidak ditemukan di DOM.`,
164
+ );
165
+ }
166
+ };
167
+
168
+ if (document.readyState === "loading") {
169
+ document.addEventListener("DOMContentLoaded", jalankan, { once: true });
174
170
  } else {
175
- document.addEventListener(
176
- "DOMContentLoaded",
177
- () => {
178
- if (element) element.render();
179
- },
180
- { once: true },
181
- );
171
+ jalankan();
182
172
  }
183
173
  }
184
174
 
185
- async function $CuriData({ data, state, request, reload = false }) {
175
+ async function $CuriData({ data, state, request = {}, reload = false }) {
186
176
  try {
187
- const response = await fetch(data, request);
177
+ const options = {
178
+ cache: "no-store",
179
+ ...request,
180
+ };
181
+
182
+ const response = await fetch(data, options);
183
+
188
184
  if (!response.ok) {
189
- throw new Error(`Status: ${response.status}`);
185
+ throw new Error(
186
+ `Status: ${response.status} - Lu mau curi apa? Gak ada datanya!`,
187
+ );
190
188
  }
189
+
191
190
  const json = await response.json();
192
- if (!json || (typeof json !== "object" && !Array.isArray(json))) {
193
- throw new Error(`Data ${data} bukan JSON kocak`);
191
+
192
+ if (json === null || typeof json !== "object") {
193
+ throw new Error(`Data dari ${data} bukan JSON yang bener, kocak`);
194
194
  }
195
+
195
196
  $antek2(state, json);
197
+
196
198
  $Sejarah({
197
199
  modul: "API: $CuriData",
198
- detail: {
199
- data: data,
200
- state: state,
201
- },
200
+ detail: { data, state },
202
201
  });
203
- if (reload) location.reload();
202
+
203
+ if (reload) {
204
+ requestAnimationFrame(() => {
205
+ const router = document.querySelector("wowo-router");
206
+ if (router && typeof router.render === "function") {
207
+ router.render();
208
+ }
209
+ });
210
+ }
211
+
212
+ return json;
204
213
  } catch (e) {
205
- console.error(`Gagal curi data ${data}
206
- ${e}`);
214
+ console.error(`[WowoJS Error] Gagal curi data:`, e.message);
215
+ return null;
216
+ }
217
+ }
218
+
219
+ function $UrusKeuangan(reducer, action) {
220
+ $Sejarah({
221
+ modul: "Reducer: $UrusKeuangan",
222
+ detail: [
223
+ {
224
+ reducer: reducer,
225
+ action: action,
226
+ },
227
+ ],
228
+ });
229
+ try {
230
+ return reducer(action);
231
+ } catch (error) {
232
+ console.error(`terjadi error ${reducer}
233
+ ${error}`);
207
234
  }
208
235
  }
209
- let _catatan = [];
236
+
210
237
  function $Sejarah({ modul, detail, aktif = false }) {
211
- _catatan.push({
238
+ history.push({
212
239
  waktu: new Date().toLocaleTimeString(),
213
240
  modul,
214
241
  detail,
215
242
  });
216
243
  if (aktif) {
217
- console.dir(_catatan);
244
+ console.dir(history);
218
245
  }
219
246
  }
220
247
 
248
+ function $Router(routes) {
249
+ const normalizePath = (p) => {
250
+ if (!p) return "/";
251
+ if (p.length > 1 && p.endsWith("/")) return p.slice(0, -1);
252
+ return p;
253
+ };
254
+
255
+ const jalankanUpdate = () => {
256
+ const rawPath = window.location.pathname || "/";
257
+ const path = normalizePath(rawPath);
258
+ let params = {};
259
+ let matchedRoute = null;
260
+
261
+ for (const r of routes) {
262
+ let pathRegexStr = r.route
263
+ .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
264
+ .replace(/\*/g, ".*")
265
+ .replace(/:(\w+)/g, "([^/]+)");
266
+
267
+ const routeRegex = new RegExp("^" + pathRegexStr + "$");
268
+ const match = path.match(routeRegex);
269
+
270
+ if (match) {
271
+ matchedRoute = r;
272
+ const paramNames = (r.route.match(/:(\w+)/g) || []).map((n) =>
273
+ n.slice(1),
274
+ );
275
+ paramNames.forEach((name, index) => {
276
+ params[name] = match[index + 1];
277
+ });
278
+ break;
279
+ }
280
+ }
281
+
282
+ if (!matchedRoute) matchedRoute = routes.find((r) => r.route === "*");
283
+
284
+ if (matchedRoute) {
285
+ $antek2("params", params || {});
286
+
287
+ let component = Array.isArray(matchedRoute.wilayah)
288
+ ? matchedRoute.wilayah[0]
289
+ : matchedRoute.wilayah;
290
+
291
+ $antek2("halaman_aktif", component);
292
+
293
+ queueMicrotask(() => {
294
+ const routerElem = document.querySelector("wowo-router");
295
+ if (routerElem && typeof routerElem.render === "function") {
296
+ routerElem.render();
297
+ }
298
+ });
299
+ }
300
+ };
301
+
302
+ jalankanUpdate();
303
+
304
+ $BuatWilayah({
305
+ namaWilayah: "router",
306
+ noShadow: true,
307
+ isiWilayah: () => $antek2("halaman_aktif") || "",
308
+ });
309
+
310
+ const handleLinkClick = (e) => {
311
+ const link = e.target.closest("a");
312
+ if (link && link.href.startsWith(window.location.origin)) {
313
+ const targetPath = link.getAttribute("href");
314
+ if (targetPath && !targetPath.startsWith("#") && !link.target) {
315
+ e.preventDefault();
316
+ $Ke(targetPath);
317
+ }
318
+ }
319
+ };
320
+
321
+ window.removeEventListener("click", handleLinkClick);
322
+ window.addEventListener("click", handleLinkClick);
323
+ window.onpopstate = () => jalankanUpdate();
324
+ }
325
+
326
+ export function $Ke(path) {
327
+ window.history.pushState({}, "", path);
328
+ window.dispatchEvent(new PopStateEvent("popstate"));
329
+ }
330
+
221
331
  window.$BuatWilayah = $BuatWilayah;
222
332
  window.$antek2 = $antek2;
223
333
  window.$PecatAntek2 = $PecatAntek2;
@@ -225,3 +335,5 @@ window.$BangunEkonomi = $BangunEkonomi;
225
335
  window.$UrusKeuangan = $UrusKeuangan;
226
336
  window.$CuriData = $CuriData;
227
337
  window.$Sejarah = $Sejarah;
338
+ window.$Ke = $Ke;
339
+ window.$Router = $Router;