create-prisma-php-app 1.13.3 → 1.13.4

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.
@@ -595,7 +595,7 @@ class FormHandler
595
595
  }
596
596
  }
597
597
 
598
- let formHandler = null;
598
+ let formHandler = FormHandler ? new FormHandler() : null;
599
599
  // Initialize FormHandler on initial page load
600
600
  document.addEventListener('DOMContentLoaded', function() {
601
601
  formHandler = new FormHandler();
@@ -29,163 +29,6 @@ function debounce(func, wait = 300, immediate = false) {
29
29
  };
30
30
  }
31
31
 
32
- /**
33
- * Represents a HTTP request.
34
- */
35
- class RequestApi {
36
- static instance = null;
37
-
38
- /**
39
- * The constructor is now private. To ensure it's not accessible from outside,
40
- * you can throw an error if someone tries to instantiate it directly
41
- * (though JavaScript does not have true private constructors).
42
- */
43
- constructor(baseURL = window.location.origin) {
44
- this.baseURL = baseURL;
45
- }
46
-
47
- /**
48
- * Static method to get instance of RequestApi.
49
- *
50
- * @param {string} [baseURL=window.location.origin] - The base URL for the request.
51
- * @returns {RequestApi} The singleton instance of the RequestApi.
52
- */
53
- static getInstance(baseURL = window.location.origin) {
54
- if (!RequestApi.instance) {
55
- RequestApi.instance = new RequestApi(baseURL);
56
- }
57
- return RequestApi.instance;
58
- }
59
-
60
- /**
61
- * Sends a HTTP request.
62
- *
63
- * @async
64
- * @param {string} method - The HTTP method.
65
- * @param {string} url - The URL to send the request to.
66
- * @param {*} [data=null] - The data to send with the request.
67
- * @param {Object} [headers={}] - The headers to include in the request.
68
- * @returns {Promise<unknown>} - A promise that resolves to the response data.
69
- */
70
- async request(method, url, data = null, headers = {}) {
71
- let fullUrl = `${this.baseURL}${url}`;
72
- const options = {
73
- method,
74
- headers: {
75
- "Content-Type": "application/json",
76
- "X-Requested-With": "XMLHttpRequest",
77
- ...headers,
78
- },
79
- };
80
-
81
- if (data) {
82
- if (method === "GET") {
83
- const params = new URLSearchParams(data).toString();
84
- fullUrl += `?${params}`;
85
- } else if (method !== "HEAD" && method !== "OPTIONS") {
86
- options.body = JSON.stringify(data);
87
- }
88
- }
89
-
90
- try {
91
- const response = await fetch(fullUrl, options);
92
- if (method === "HEAD") {
93
- return response.headers;
94
- }
95
- const contentType = response.headers.get("content-type");
96
- if (contentType && contentType.includes("application/json")) {
97
- return await response.json();
98
- } else {
99
- return await response.text();
100
- }
101
- } catch (error) {
102
- throw error;
103
- }
104
- }
105
-
106
- /**
107
- * Sends a GET request.
108
- *
109
- * @param {string} url - The URL to send the request to.
110
- * @param {*} [params] - The parameters to include in the request.
111
- * @param {Object} [headers={}] - The headers to include in the request.
112
- * @returns {Promise<unknown>} - A promise that resolves to the response data.
113
- */
114
- get(url, params, headers) {
115
- return this.request("GET", url, params, headers);
116
- }
117
-
118
- /**
119
- * Sends a POST request.
120
- *
121
- * @param {string} url - The URL to send the request to.
122
- * @param {*} data - The data to send with the request.
123
- * @param {Object} [headers={}] - The headers to include in the request.
124
- * @returns {Promise<unknown>} - A promise that resolves to the response data.
125
- */
126
- post(url, data, headers) {
127
- return this.request("POST", url, data, headers);
128
- }
129
-
130
- /**
131
- * Sends a PUT request.
132
- *
133
- * @param {string} url - The URL to send the request to.
134
- * @param {*} data - The data to send with the request.
135
- * @param {Object} [headers={}] - The headers to include in the request.
136
- * @returns {Promise<unknown>} - A promise that resolves to the response data.
137
- */
138
- put(url, data, headers) {
139
- return this.request("PUT", url, data, headers);
140
- }
141
-
142
- /**
143
- * Sends a DELETE request.
144
- *
145
- * @param {string} url - The URL to send the request to.
146
- * @param {*} data - The data to send with the request.
147
- * @param {Object} [headers={}] - The headers to include in the request.
148
- * @returns {Promise<unknown>} - A promise that resolves to the response data.
149
- */
150
- delete(url, data, headers) {
151
- return this.request("DELETE", url, data, headers);
152
- }
153
-
154
- /**
155
- * Sends a PATCH request.
156
- *
157
- * @param {string} url - The URL to send the request to.
158
- * @param {*} data - The data to send with the request.
159
- * @param {Object} [headers={}] - The headers to include in the request.
160
- * @returns {Promise<unknown>} - A promise that resolves to the response data.
161
- */
162
- patch(url, data, headers) {
163
- return this.request("PATCH", url, data, headers);
164
- }
165
-
166
- /**
167
- * Sends a HEAD request.
168
- *
169
- * @param {string} url - The URL to send the request to.
170
- * @param {Object} [headers={}] - The headers to include in the request.
171
- * @returns {Promise<unknown>} - A promise that resolves to the response headers.
172
- */
173
- head(url, headers) {
174
- return this.request("HEAD", url, null, headers);
175
- }
176
-
177
- /**
178
- * Sends an OPTIONS request.
179
- *
180
- * @param {string} url - The URL to send the request to.
181
- * @param {Object} [headers={}] - The headers to include in the request.
182
- * @returns {Promise<unknown>} - A promise that resolves to the options available.
183
- */
184
- options(url, headers) {
185
- return this.request("OPTIONS", url, null, headers);
186
- }
187
- }
188
-
189
32
  /**
190
33
  * Copies text to the clipboard.
191
34
  *
@@ -230,310 +73,493 @@ function copyCode(btnElement) {
230
73
  copyToClipboard(textToCopy, btnElement);
231
74
  }
232
75
 
233
- /**
234
- * Manages the application state.
235
- */
236
- class StateManager {
237
- static instance = null;
238
-
76
+ if (
77
+ typeof RequestApi === "undefined" &&
78
+ typeof StateManager === "undefined" &&
79
+ typeof HXConnector === "undefined"
80
+ ) {
239
81
  /**
240
- * Creates a new StateManager instance.
241
- *
242
- * @param {{}} [initialState={}] - The initial state.
82
+ * Represents a HTTP request.
243
83
  */
244
- constructor(initialState = {}) {
245
- this.state = initialState;
246
- this.listeners = [];
247
- }
84
+ class RequestApi {
85
+ static instance = null;
86
+
87
+ /**
88
+ * The constructor is now private. To ensure it's not accessible from outside,
89
+ * you can throw an error if someone tries to instantiate it directly
90
+ * (though JavaScript does not have true private constructors).
91
+ */
92
+ constructor(baseURL = window.location.origin) {
93
+ this.baseURL = baseURL;
94
+ }
248
95
 
249
- /**
250
- * Gets the singleton instance of StateManager.
251
- *
252
- * @static
253
- * @param {{}} [initialState={}] - The initial state.
254
- * @returns {StateManager} - The StateManager instance.
255
- */
256
- static getInstance(initialState = {}) {
257
- if (!StateManager.instance) {
258
- StateManager.instance = new StateManager(initialState);
259
- StateManager.instance.loadState(); // Load state immediately after instance creation
96
+ /**
97
+ * Static method to get instance of RequestApi.
98
+ *
99
+ * @param {string} [baseURL=window.location.origin] - The base URL for the request.
100
+ * @returns {RequestApi} The singleton instance of the RequestApi.
101
+ */
102
+ static getInstance(baseURL = window.location.origin) {
103
+ if (!RequestApi.instance) {
104
+ RequestApi.instance = new RequestApi(baseURL);
105
+ }
106
+ return RequestApi.instance;
260
107
  }
261
- return StateManager.instance;
262
- }
263
108
 
264
- /**
265
- * Sets the state.
266
- *
267
- * @param {*} update - The state update.
268
- * @param {boolean} [saveToStorage=false] - Whether to save the state to localStorage.
269
- */
270
- setState(update, saveToStorage = false) {
271
- this.state = { ...this.state, ...update };
272
- this.listeners.forEach((listener) => listener(this.state));
273
- if (saveToStorage) {
274
- this.saveState();
109
+ /**
110
+ * Sends a HTTP request.
111
+ *
112
+ * @async
113
+ * @param {string} method - The HTTP method.
114
+ * @param {string} url - The URL to send the request to.
115
+ * @param {*} [data=null] - The data to send with the request.
116
+ * @param {Object} [headers={}] - The headers to include in the request.
117
+ * @returns {Promise<unknown>} - A promise that resolves to the response data.
118
+ */
119
+ async request(method, url, data = null, headers = {}) {
120
+ let fullUrl = `${this.baseURL}${url}`;
121
+ const options = {
122
+ method,
123
+ headers: {
124
+ "Content-Type": "application/json",
125
+ "X-Requested-With": "XMLHttpRequest",
126
+ ...headers,
127
+ },
128
+ };
129
+
130
+ if (data) {
131
+ if (method === "GET") {
132
+ const params = new URLSearchParams(data).toString();
133
+ fullUrl += `?${params}`;
134
+ } else if (method !== "HEAD" && method !== "OPTIONS") {
135
+ options.body = JSON.stringify(data);
136
+ }
137
+ }
138
+
139
+ try {
140
+ const response = await fetch(fullUrl, options);
141
+ if (method === "HEAD") {
142
+ return response.headers;
143
+ }
144
+ const contentType = response.headers.get("content-type");
145
+ if (contentType && contentType.includes("application/json")) {
146
+ return await response.json();
147
+ } else {
148
+ return await response.text();
149
+ }
150
+ } catch (error) {
151
+ throw error;
152
+ }
275
153
  }
276
- }
277
154
 
278
- /**
279
- * Subscribes to state changes.
280
- *
281
- * @param {*} listener - The listener function.
282
- * @returns {Function} - A function to unsubscribe the listener.
283
- */
284
- subscribe(listener) {
285
- this.listeners.push(listener);
286
- listener(this.state); // Immediately invoke the listener with the current state
287
- return () =>
288
- (this.listeners = this.listeners.filter((l) => l !== listener));
289
- }
155
+ /**
156
+ * Sends a GET request.
157
+ *
158
+ * @param {string} url - The URL to send the request to.
159
+ * @param {*} [params] - The parameters to include in the request.
160
+ * @param {Object} [headers={}] - The headers to include in the request.
161
+ * @returns {Promise<unknown>} - A promise that resolves to the response data.
162
+ */
163
+ get(url, params, headers) {
164
+ return this.request("GET", url, params, headers);
165
+ }
290
166
 
291
- /**
292
- * Saves the state to localStorage.
293
- */
294
- saveState() {
295
- localStorage.setItem("appState", JSON.stringify(this.state));
296
- }
167
+ /**
168
+ * Sends a POST request.
169
+ *
170
+ * @param {string} url - The URL to send the request to.
171
+ * @param {*} data - The data to send with the request.
172
+ * @param {Object} [headers={}] - The headers to include in the request.
173
+ * @returns {Promise<unknown>} - A promise that resolves to the response data.
174
+ */
175
+ post(url, data, headers) {
176
+ return this.request("POST", url, data, headers);
177
+ }
297
178
 
298
- /**
299
- * Loads the state from localStorage.
300
- */
301
- loadState() {
302
- const state = localStorage.getItem("appState");
303
- if (state) {
304
- this.state = JSON.parse(state);
305
- this.listeners.forEach((listener) => listener(this.state));
179
+ /**
180
+ * Sends a PUT request.
181
+ *
182
+ * @param {string} url - The URL to send the request to.
183
+ * @param {*} data - The data to send with the request.
184
+ * @param {Object} [headers={}] - The headers to include in the request.
185
+ * @returns {Promise<unknown>} - A promise that resolves to the response data.
186
+ */
187
+ put(url, data, headers) {
188
+ return this.request("PUT", url, data, headers);
189
+ }
190
+
191
+ /**
192
+ * Sends a DELETE request.
193
+ *
194
+ * @param {string} url - The URL to send the request to.
195
+ * @param {*} data - The data to send with the request.
196
+ * @param {Object} [headers={}] - The headers to include in the request.
197
+ * @returns {Promise<unknown>} - A promise that resolves to the response data.
198
+ */
199
+ delete(url, data, headers) {
200
+ return this.request("DELETE", url, data, headers);
201
+ }
202
+
203
+ /**
204
+ * Sends a PATCH request.
205
+ *
206
+ * @param {string} url - The URL to send the request to.
207
+ * @param {*} data - The data to send with the request.
208
+ * @param {Object} [headers={}] - The headers to include in the request.
209
+ * @returns {Promise<unknown>} - A promise that resolves to the response data.
210
+ */
211
+ patch(url, data, headers) {
212
+ return this.request("PATCH", url, data, headers);
213
+ }
214
+
215
+ /**
216
+ * Sends a HEAD request.
217
+ *
218
+ * @param {string} url - The URL to send the request to.
219
+ * @param {Object} [headers={}] - The headers to include in the request.
220
+ * @returns {Promise<unknown>} - A promise that resolves to the response headers.
221
+ */
222
+ head(url, headers) {
223
+ return this.request("HEAD", url, null, headers);
224
+ }
225
+
226
+ /**
227
+ * Sends an OPTIONS request.
228
+ *
229
+ * @param {string} url - The URL to send the request to.
230
+ * @param {Object} [headers={}] - The headers to include in the request.
231
+ * @returns {Promise<unknown>} - A promise that resolves to the options available.
232
+ */
233
+ options(url, headers) {
234
+ return this.request("OPTIONS", url, null, headers);
306
235
  }
307
236
  }
308
237
 
309
238
  /**
310
- * Resets the state to its initial value.
311
- *
312
- * @param {boolean} [clearFromStorage=false] - Whether to clear the state from localStorage.
239
+ * Manages the application state.
313
240
  */
314
- resetState(clearFromStorage = false) {
315
- this.state = {}; // Reset the state to an empty object or a default state if you prefer
316
- this.listeners.forEach((listener) => listener(this.state));
317
- if (clearFromStorage) {
318
- localStorage.removeItem("appState"); // Clear the state from localStorage
241
+ class StateManager {
242
+ static instance = null;
243
+
244
+ /**
245
+ * Creates a new StateManager instance.
246
+ *
247
+ * @param {{}} [initialState={}] - The initial state.
248
+ */
249
+ constructor(initialState = {}) {
250
+ this.state = initialState;
251
+ this.listeners = [];
319
252
  }
320
- }
321
- }
322
253
 
323
- class HXConnector {
324
- // Static property to hold the single instance
325
- static instance = null;
254
+ /**
255
+ * Gets the singleton instance of StateManager.
256
+ *
257
+ * @static
258
+ * @param {{}} [initialState={}] - The initial state.
259
+ * @returns {StateManager} - The StateManager instance.
260
+ */
261
+ static getInstance(initialState = {}) {
262
+ if (!StateManager.instance) {
263
+ StateManager.instance = new StateManager(initialState);
264
+ StateManager.instance.loadState(); // Load state immediately after instance creation
265
+ }
266
+ return StateManager.instance;
267
+ }
326
268
 
327
- // Private constructor to prevent direct instantiation
328
- constructor() {
329
- if (HXConnector.instance) {
330
- return HXConnector.instance;
269
+ /**
270
+ * Sets the state.
271
+ *
272
+ * @param {*} update - The state update.
273
+ * @param {boolean} [saveToStorage=false] - Whether to save the state to localStorage.
274
+ */
275
+ setState(update, saveToStorage = false) {
276
+ this.state = { ...this.state, ...update };
277
+ this.listeners.forEach((listener) => listener(this.state));
278
+ if (saveToStorage) {
279
+ this.saveState();
280
+ }
331
281
  }
332
282
 
333
- this.init();
334
- HXConnector.instance = this;
335
- }
283
+ /**
284
+ * Subscribes to state changes.
285
+ *
286
+ * @param {*} listener - The listener function.
287
+ * @returns {Function} - A function to unsubscribe the listener.
288
+ */
289
+ subscribe(listener) {
290
+ this.listeners.push(listener);
291
+ listener(this.state); // Immediately invoke the listener with the current state
292
+ return () =>
293
+ (this.listeners = this.listeners.filter((l) => l !== listener));
294
+ }
336
295
 
337
- // Static method to get the single instance
338
- static getInstance() {
339
- if (!HXConnector.instance) {
340
- HXConnector.instance = new HXConnector();
296
+ /**
297
+ * Saves the state to localStorage.
298
+ */
299
+ saveState() {
300
+ localStorage.setItem("appState", JSON.stringify(this.state));
301
+ }
302
+
303
+ /**
304
+ * Loads the state from localStorage.
305
+ */
306
+ loadState() {
307
+ const state = localStorage.getItem("appState");
308
+ if (state) {
309
+ this.state = JSON.parse(state);
310
+ this.listeners.forEach((listener) => listener(this.state));
311
+ }
341
312
  }
342
- return HXConnector.instance;
343
- }
344
313
 
345
- // Initializes the HXConnector by connecting attributes of elements with
346
- // `hx-trigger` and `hx-vals` attributes, and sets up an event listener to handle
347
- // new elements added after HTMX swaps.
348
- init() {
349
- this.connectAttributes(document.querySelectorAll("[hx-trigger][hx-vals]"));
350
- this.handleFormEvents(document.querySelectorAll("[hx-form]"));
351
-
352
- document.body.addEventListener("htmx:afterSwap", (event) => {
353
- this.connectAttributes(
354
- event.detail.target.querySelectorAll("[hx-trigger][hx-vals]")
355
- );
356
- this.handleFormEvents(event.detail.target.querySelectorAll("[hx-form]"));
357
- });
314
+ /**
315
+ * Resets the state to its initial value.
316
+ *
317
+ * @param {boolean} [clearFromStorage=false] - Whether to clear the state from localStorage.
318
+ */
319
+ resetState(clearFromStorage = false) {
320
+ this.state = {}; // Reset the state to an empty object or a default state if you prefer
321
+ this.listeners.forEach((listener) => listener(this.state));
322
+ if (clearFromStorage) {
323
+ localStorage.removeItem("appState"); // Clear the state from localStorage
324
+ }
325
+ }
358
326
  }
359
327
 
360
- // Connects attributes of the provided elements based on the values specified
361
- // in their `hx-vals` attributes and attaches event listeners based on `hx-trigger`.
362
- connectAttributes(elements) {
363
- elements.forEach((element) => {
364
- const event = element.getAttribute("hx-trigger");
365
- element.addEventListener(event, (el) => {
366
- const targetElement = el.target.closest("[hx-trigger]");
367
- if (targetElement) {
368
- const values = JSON.parse(targetElement.getAttribute("hx-vals"));
369
-
370
- // Process targets
371
- if (values.targets) {
372
- values.targets.forEach((target) => {
373
- const targetElem = document.getElementById(target.id);
374
- if (targetElem) {
375
- this.updateElementValues(targetElem, target.value);
376
- }
377
- });
378
- }
328
+ /**
329
+ * Connects elements with `hx-trigger` and `hx-vals` attributes to update
330
+ * their values and attributes based on the specified triggers.
331
+ * Also handles form events based on the `hx-form` attribute.
332
+ * This class is a singleton.
333
+ **/
334
+ class HXConnector {
335
+ // Static property to hold the single instance
336
+ static instance = null;
337
+
338
+ // Private constructor to prevent direct instantiation
339
+ constructor() {
340
+ if (HXConnector.instance) {
341
+ return HXConnector.instance;
342
+ }
379
343
 
380
- // Process attributes
381
- if (values.attributes) {
382
- values.attributes.forEach((attributeSet) => {
383
- const element = document.getElementById(attributeSet.id);
384
- if (element) {
385
- Object.keys(attributeSet.attributes).forEach((attr) => {
386
- const value = attributeSet.attributes[attr];
387
- switch (attr) {
388
- case "class":
389
- this.updateClassAttribute(element, value);
390
- break;
391
- case "add":
392
- element.setAttribute(value, "");
393
- break;
394
- case "remove":
395
- element.removeAttribute(value);
396
- break;
397
- default:
398
- element.setAttribute(attr, value);
399
- }
400
- });
401
- }
402
- });
403
- }
344
+ this.init();
345
+ HXConnector.instance = this;
346
+ }
404
347
 
405
- // Register swaps to be processed after the htmx request completes
406
- if (values.swaps) {
407
- document.addEventListener(
408
- "htmx:afterRequest",
409
- () => {
410
- values.swaps.forEach((swap) => {
411
- const element = document.getElementById(swap.id);
412
- if (element) {
413
- Object.keys(swap.attributes).forEach((attr) => {
414
- const value = swap.attributes[attr];
415
- switch (attr) {
416
- case "class":
417
- this.updateClassAttribute(element, value);
418
- break;
419
- case "add":
420
- element.setAttribute(value, "");
421
- break;
422
- case "remove":
423
- element.removeAttribute(value);
424
- break;
425
- default:
426
- element.setAttribute(attr, value);
427
- }
428
- });
429
- }
430
- });
431
- },
432
- {
433
- once: true,
434
- }
435
- );
436
- }
437
- }
348
+ // Static method to get the single instance
349
+ static getInstance() {
350
+ if (!HXConnector.instance) {
351
+ HXConnector.instance = new HXConnector();
352
+ }
353
+ return HXConnector.instance;
354
+ }
355
+
356
+ // Initializes the HXConnector by connecting attributes of elements with
357
+ // `hx-trigger` and `hx-vals` attributes, and sets up an event listener to handle
358
+ // new elements added after HTMX swaps.
359
+ init() {
360
+ this.connectAttributes(document.querySelectorAll("[hx-trigger][hx-vals]"));
361
+ this.handleFormEvents(document.querySelectorAll("[hx-form]"));
362
+
363
+ document.body.addEventListener("htmx:afterSwap", (event) => {
364
+ this.connectAttributes(
365
+ event.detail.target.querySelectorAll("[hx-trigger][hx-vals]")
366
+ );
367
+ this.handleFormEvents(event.detail.target.querySelectorAll("[hx-form]"));
438
368
  });
439
- });
440
- }
369
+ }
441
370
 
442
- // Handles form events for the provided forms based on their `hx-form` attribute.
443
- handleFormEvents(forms) {
444
- forms.forEach((form) => {
445
- const eventAttr = form.getAttribute("hx-form");
446
- if (eventAttr) {
447
- const [eventType, functionName] = eventAttr.split(":");
448
-
449
- form.addEventListener(`htmx:${eventType}`, (event) => {
450
- switch (functionName) {
451
- case "reset":
452
- if (event.detail.successful) {
453
- form.reset();
454
- }
455
- break;
456
-
457
- case "clear":
458
- if (event.detail.successful) {
459
- this.clearForm(form);
460
- }
461
- break;
462
-
463
- case "disable":
464
- this.toggleForm(form, true);
465
- break;
466
-
467
- case "enable":
468
- this.toggleForm(form, false);
469
- break;
470
-
471
- // Add more cases as needed
472
-
473
- default:
474
- console.warn(`Unhandled function name: ${functionName}`);
475
- break;
371
+ // Connects attributes of the provided elements based on the values specified
372
+ // in their `hx-vals` attributes and attaches event listeners based on `hx-trigger`.
373
+ connectAttributes(elements) {
374
+ elements.forEach((element) => {
375
+ const event = element.getAttribute("hx-trigger");
376
+ element.addEventListener(event, (el) => {
377
+ const targetElement = el.target.closest("[hx-trigger]");
378
+ if (targetElement) {
379
+ const values = JSON.parse(targetElement.getAttribute("hx-vals"));
380
+
381
+ // Process targets
382
+ if (values.targets) {
383
+ values.targets.forEach((target) => {
384
+ const targetElem = document.getElementById(target.id);
385
+ if (targetElem) {
386
+ this.updateElementValues(targetElem, target.value);
387
+ }
388
+ });
389
+ }
390
+
391
+ // Process attributes
392
+ if (values.attributes) {
393
+ values.attributes.forEach((attributeSet) => {
394
+ const element = document.getElementById(attributeSet.id);
395
+ if (element) {
396
+ Object.keys(attributeSet.attributes).forEach((attr) => {
397
+ const value = attributeSet.attributes[attr];
398
+ switch (attr) {
399
+ case "class":
400
+ this.updateClassAttribute(element, value);
401
+ break;
402
+ case "add":
403
+ element.setAttribute(value, "");
404
+ break;
405
+ case "remove":
406
+ element.removeAttribute(value);
407
+ break;
408
+ default:
409
+ element.setAttribute(attr, value);
410
+ }
411
+ });
412
+ }
413
+ });
414
+ }
415
+
416
+ // Register swaps to be processed after the htmx request completes
417
+ if (values.swaps) {
418
+ document.addEventListener(
419
+ "htmx:afterRequest",
420
+ () => {
421
+ values.swaps.forEach((swap) => {
422
+ const element = document.getElementById(swap.id);
423
+ if (element) {
424
+ Object.keys(swap.attributes).forEach((attr) => {
425
+ const value = swap.attributes[attr];
426
+ switch (attr) {
427
+ case "class":
428
+ this.updateClassAttribute(element, value);
429
+ break;
430
+ case "add":
431
+ element.setAttribute(value, "");
432
+ break;
433
+ case "remove":
434
+ element.removeAttribute(value);
435
+ break;
436
+ default:
437
+ element.setAttribute(attr, value);
438
+ }
439
+ });
440
+ }
441
+ });
442
+ },
443
+ {
444
+ once: true,
445
+ }
446
+ );
447
+ }
476
448
  }
477
449
  });
478
- }
479
- });
480
- }
450
+ });
451
+ }
481
452
 
482
- // Clears the input values of the specified form.
483
- clearForm(form) {
484
- const inputs = form.querySelectorAll("input, textarea, select");
485
- inputs.forEach((input) => {
486
- if (input.type === "checkbox" || input.type === "radio") {
487
- input.checked = false;
488
- } else {
489
- input.value = "";
490
- }
491
- });
492
- }
453
+ // Handles form events for the provided forms based on their `hx-form` attribute.
454
+ handleFormEvents(forms) {
455
+ forms.forEach((form) => {
456
+ const eventAttr = form.getAttribute("hx-form");
457
+ if (eventAttr) {
458
+ const [eventType, functionName] = eventAttr.split(":");
459
+
460
+ form.addEventListener(`htmx:${eventType}`, (event) => {
461
+ switch (functionName) {
462
+ case "reset":
463
+ if (event.detail.successful) {
464
+ form.reset();
465
+ }
466
+ break;
467
+
468
+ case "clear":
469
+ if (event.detail.successful) {
470
+ this.clearForm(form);
471
+ }
472
+ break;
473
+
474
+ case "disable":
475
+ this.toggleForm(form, true);
476
+ break;
477
+
478
+ case "enable":
479
+ this.toggleForm(form, false);
480
+ break;
481
+
482
+ // Add more cases as needed
483
+
484
+ default:
485
+ console.warn(`Unhandled function name: ${functionName}`);
486
+ break;
487
+ }
488
+ });
489
+ }
490
+ });
491
+ }
493
492
 
494
- // Toggles the disabled state of the specified form's inputs.
495
- toggleForm(form, state) {
496
- const inputs = form.querySelectorAll("input, textarea, select, button");
497
- inputs.forEach((input) => {
498
- input.disabled = state;
499
- });
500
- }
493
+ // Clears the input values of the specified form.
494
+ clearForm(form) {
495
+ const inputs = form.querySelectorAll("input, textarea, select");
496
+ inputs.forEach((input) => {
497
+ if (input.type === "checkbox" || input.type === "radio") {
498
+ input.checked = false;
499
+ } else {
500
+ input.value = "";
501
+ }
502
+ });
503
+ }
504
+
505
+ // Toggles the disabled state of the specified form's inputs.
506
+ toggleForm(form, state) {
507
+ const inputs = form.querySelectorAll("input, textarea, select, button");
508
+ inputs.forEach((input) => {
509
+ input.disabled = state;
510
+ });
511
+ }
501
512
 
502
- // Updates the values of the specified element based on its tag name and type.
503
- updateElementValues(element, value) {
504
- const tagName = element.tagName;
505
- const inputType = element.type;
513
+ // Updates the values of the specified element based on its tag name and type.
514
+ updateElementValues(element, value) {
515
+ const tagName = element.tagName;
516
+ const inputType = element.type;
506
517
 
507
- if (tagName === "INPUT" || tagName === "TEXTAREA") {
508
- if (inputType === "checkbox") {
509
- element.checked = value;
518
+ if (tagName === "INPUT" || tagName === "TEXTAREA") {
519
+ if (inputType === "checkbox") {
520
+ element.checked = value;
521
+ } else {
522
+ element.value = value;
523
+ }
510
524
  } else {
511
- element.value = value;
525
+ element.textContent = value;
512
526
  }
513
- } else {
514
- element.textContent = value;
527
+ }
528
+
529
+ // Updates the class attribute of the specified element. Class names starting
530
+ // with a hyphen (`-`) are removed, others are added.
531
+ updateClassAttribute(element, className) {
532
+ const classNames = className.split(" ");
533
+ classNames.forEach((name) => {
534
+ if (name.startsWith("-")) {
535
+ element.classList.remove(name.substring(1));
536
+ } else {
537
+ element.classList.add(name);
538
+ }
539
+ });
515
540
  }
516
541
  }
517
542
 
518
- // Updates the class attribute of the specified element. Class names starting
519
- // with a hyphen (`-`) are removed, others are added.
520
- updateClassAttribute(element, className) {
521
- const classNames = className.split(" ");
522
- classNames.forEach((name) => {
523
- if (name.startsWith("-")) {
524
- element.classList.remove(name.substring(1));
525
- } else {
526
- element.classList.add(name);
527
- }
528
- });
543
+ let store = null;
544
+ let api = null;
545
+ let hxConnector = null;
546
+
547
+ // Function to initialize instances
548
+ function initializeInstances() {
549
+ store = StateManager.getInstance();
550
+ api = RequestApi.getInstance();
551
+ hxConnector = HXConnector.getInstance();
529
552
  }
530
- }
531
553
 
532
- let store = null;
533
- let api = null;
534
- let hxConnector = null;
535
- document.addEventListener("DOMContentLoaded", function () {
536
- store = StateManager.getInstance();
537
- api = RequestApi.getInstance();
538
- hxConnector = HXConnector.getInstance();
539
- });
554
+ // Initialize instances on initial page load
555
+ document.addEventListener("DOMContentLoaded", function () {
556
+ initializeInstances();
557
+
558
+ // Ensure document.body exists before attaching the event listener
559
+ if (document.body) {
560
+ document.body.addEventListener("htmx:afterOnLoad", function () {
561
+ initializeInstances();
562
+ });
563
+ }
564
+ });
565
+ }
@@ -8,8 +8,8 @@
8
8
  <title><?php echo htmlspecialchars($metadata['title']); ?></title>
9
9
  <link rel="shortcut icon" href="<?php echo $baseUrl; ?>favicon.ico" type="image/x-icon">
10
10
  <script>
11
- const baseUrl = '<?php echo $baseUrl; ?>';
12
- const pathname = '<?php echo $pathname; ?>';
11
+ var baseUrl = '<?php echo $baseUrl; ?>';
12
+ var pathname = '<?php echo $pathname; ?>';
13
13
  </script>
14
14
  </head>
15
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "1.13.3",
3
+ "version": "1.13.4",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",