litewire 1.0.0 → 1.0.1
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 +95 -53
- package/package.json +2 -2
- package/src/litewire.js +16 -2
package/README.MD
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Litewire Framework
|
|
2
2
|
|
|
3
|
+
```bash
|
|
4
|
+
npm i litewire
|
|
5
|
+
```
|
|
6
|
+
|
|
3
7
|
## Complete Architecture Manual & Reference Guide
|
|
4
8
|
|
|
5
9
|
A comprehensive technical breakdown of the HTML-driven AJAX engine, dynamic component loader, DOM swapping, state management, and lifecycle events.
|
|
@@ -57,8 +61,8 @@ To support deployment in deeply nested directories or custom app sub-paths, Lite
|
|
|
57
61
|
```javascript
|
|
58
62
|
// Custom manual instantiation with options
|
|
59
63
|
const customLitewire = new Litewire({
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
baseUrl: "[https://api.myproject.com](https://api.myproject.com)",
|
|
65
|
+
loadingClass: "is-loading", // Class applied to active triggers and indicators
|
|
62
66
|
});
|
|
63
67
|
```
|
|
64
68
|
|
|
@@ -68,18 +72,18 @@ const customLitewire = new Litewire({
|
|
|
68
72
|
|
|
69
73
|
All core functionalities are driven by attaching `lw-*` attributes directly to standard HTML tags.
|
|
70
74
|
|
|
71
|
-
| Attribute
|
|
72
|
-
|
|
73
|
-
| `lw-get`
|
|
74
|
-
| `lw-post`
|
|
75
|
-
| `lw-put`
|
|
76
|
-
| `lw-delete`
|
|
77
|
-
| `lw-trigger`
|
|
78
|
-
| `lw-target`
|
|
79
|
-
| `lw-swap`
|
|
80
|
-
| `lw-indicator` | CSS Selector
|
|
81
|
-
| `lw-push-url`
|
|
82
|
-
| `lw-component` | JS File Path
|
|
75
|
+
| Attribute | Accepted Values | Default | Functional Description |
|
|
76
|
+
| -------------- | --------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
77
|
+
| `lw-get` | Relative / Absolute Path | None | Executes an HTTP GET request to the specified endpoint. |
|
|
78
|
+
| `lw-post` | Relative / Absolute Path | None | Executes an HTTP POST request. Submits form payload if bound to or inside a `<form>`. |
|
|
79
|
+
| `lw-put` | Relative / Absolute Path | None | Executes an HTTP PUT request with FormData payload attachment. |
|
|
80
|
+
| `lw-delete` | Relative / Absolute Path | None | Executes an HTTP DELETE request. |
|
|
81
|
+
| `lw-trigger` | `click`, `submit`, `load`, custom | Contextual | Overrides trigger event. Defaults to `submit` for forms, `click` for interactive tags. `load` fires instantly. |
|
|
82
|
+
| `lw-target` | CSS Selector | Self Element | Specifies the container element where the returned HTML response will be rendered. |
|
|
83
|
+
| `lw-swap` | `innerHTML`, `outerHTML`, `prepend`, `append` | `innerHTML` | Controls how the received HTML response replaces or integrates into the target element. |
|
|
84
|
+
| `lw-indicator` | CSS Selector | `.litewire-indicator` | Specifies target loading elements. Automatically toggles the active `loadingClass` during request execution. |
|
|
85
|
+
| `lw-push-url` | `true`, `false`, Custom Path | `false` | Pushes a new state to the browser history, caching DOM contents for native back/forward navigation. |
|
|
86
|
+
| `lw-component` | JS File Path | None | Asynchronously imports a JavaScript module and mounts it directly onto the host DOM element. |
|
|
83
87
|
|
|
84
88
|
---
|
|
85
89
|
|
|
@@ -104,33 +108,33 @@ When an element with `lw-component="path/to/module.js"` is injected into the DOM
|
|
|
104
108
|
|
|
105
109
|
```html
|
|
106
110
|
<!-- Target element containing component directives and dataset parameters -->
|
|
107
|
-
<div
|
|
108
|
-
lw-component="assets/js/uploader.js"
|
|
109
|
-
data-max-files="5"
|
|
110
|
-
data-allowed-types="image/png,image/jpeg"
|
|
111
|
-
|
|
111
|
+
<div
|
|
112
|
+
lw-component="assets/js/uploader.js"
|
|
113
|
+
data-max-files="5"
|
|
114
|
+
data-allowed-types="image/png,image/jpeg"
|
|
115
|
+
></div>
|
|
112
116
|
```
|
|
113
117
|
|
|
114
118
|
#### JavaScript Module (`assets/js/uploader.js`)
|
|
115
119
|
|
|
116
120
|
```javascript
|
|
117
121
|
export default class ImageUploader {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
constructor(element, params) {
|
|
123
|
+
this.container = element;
|
|
124
|
+
this.maxFiles = params.maxFiles || 1;
|
|
125
|
+
this.allowedTypes = params.allowedTypes || "*";
|
|
126
|
+
|
|
127
|
+
this.render();
|
|
128
|
+
}
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
render() {
|
|
131
|
+
this.container.innerHTML = `
|
|
128
132
|
<div class="upload-box">
|
|
129
133
|
<p>Upload up to ${this.maxFiles} files (${this.allowedTypes})</p>
|
|
130
134
|
<input type="file" multiple accept="${this.allowedTypes}">
|
|
131
135
|
</div>
|
|
132
136
|
`;
|
|
133
|
-
|
|
137
|
+
}
|
|
134
138
|
}
|
|
135
139
|
```
|
|
136
140
|
|
|
@@ -171,22 +175,22 @@ Enabling history tracking via `lw-push-url="true"` allows AJAX-driven applicatio
|
|
|
171
175
|
|
|
172
176
|
Litewire dispatches standard, bubbling DOM events during the request lifecycles. Custom JavaScript code can hook into these lifecycle stages using standard `addEventListener` calls.
|
|
173
177
|
|
|
174
|
-
| Event Name
|
|
175
|
-
|
|
176
|
-
| `litewire:beforeRequest` | `null`
|
|
177
|
-
| `litewire:afterRequest`
|
|
178
|
-
| `litewire:error`
|
|
178
|
+
| Event Name | `event.detail` | Description / Usage |
|
|
179
|
+
| ------------------------ | ------------------ | --------------------------------------------------------------------------------------------------------------- |
|
|
180
|
+
| `litewire:beforeRequest` | `null` | Fires immediately before the HTTP request is initiated. Ideal for disabling inputs or custom client validation. |
|
|
181
|
+
| `litewire:afterRequest` | `null` | Fires after the request succeeds and the HTML content swap is complete. Ideal for triggering animations. |
|
|
182
|
+
| `litewire:error` | `{ error: Error }` | Fires if a network error occurs or the HTTP response returns an error status (non-2xx). |
|
|
179
183
|
|
|
180
184
|
### Lifecycle Hooks Example
|
|
181
185
|
|
|
182
186
|
```javascript
|
|
183
187
|
// Global logging and notification system integration
|
|
184
|
-
document.addEventListener(
|
|
185
|
-
|
|
188
|
+
document.addEventListener("litewire:beforeRequest", (e) => {
|
|
189
|
+
console.log("Initiating Litewire request from:", e.target);
|
|
186
190
|
});
|
|
187
191
|
|
|
188
|
-
document.addEventListener(
|
|
189
|
-
|
|
192
|
+
document.addEventListener("litewire:error", (e) => {
|
|
193
|
+
alert(`Request failed: ${e.detail.error.message}`);
|
|
190
194
|
});
|
|
191
195
|
```
|
|
192
196
|
|
|
@@ -201,7 +205,7 @@ Litewire natively secures outgoing write operations (`POST`, `PUT`, `DELETE`) ag
|
|
|
201
205
|
Before dispatching non-GET requests, Litewire scans the host page head for a CSRF meta tag:
|
|
202
206
|
|
|
203
207
|
```html
|
|
204
|
-
<meta name="csrf-token" content="abc123securehash456"
|
|
208
|
+
<meta name="csrf-token" content="abc123securehash456" />
|
|
205
209
|
```
|
|
206
210
|
|
|
207
211
|
If detected, Litewire automatically includes the retrieved token into the HTTP request headers:
|
|
@@ -218,14 +222,15 @@ X-CSRF-TOKEN: abc123securehash456
|
|
|
218
222
|
|
|
219
223
|
```html
|
|
220
224
|
<!-- Live search input updating target table and browser address bar -->
|
|
221
|
-
<input
|
|
222
|
-
type="text"
|
|
223
|
-
name="q"
|
|
224
|
-
placeholder="Search users..."
|
|
225
|
-
lw-get="/users/search"
|
|
226
|
-
lw-trigger="keyup"
|
|
227
|
-
lw-target="#user-table-body"
|
|
228
|
-
lw-push-url="true"
|
|
225
|
+
<input
|
|
226
|
+
type="text"
|
|
227
|
+
name="q"
|
|
228
|
+
placeholder="Search users..."
|
|
229
|
+
lw-get="/users/search"
|
|
230
|
+
lw-trigger="keyup"
|
|
231
|
+
lw-target="#user-table-body"
|
|
232
|
+
lw-push-url="true"
|
|
233
|
+
/>
|
|
229
234
|
|
|
230
235
|
<table>
|
|
231
236
|
<tbody id="user-table-body">
|
|
@@ -234,14 +239,47 @@ X-CSRF-TOKEN: abc123securehash456
|
|
|
234
239
|
</table>
|
|
235
240
|
```
|
|
236
241
|
|
|
242
|
+
```php
|
|
243
|
+
// Route
|
|
244
|
+
Route::get('/users/search', 'UsersController@search')->name('user.search');
|
|
245
|
+
|
|
246
|
+
//UserController
|
|
247
|
+
public function search(Request $request)
|
|
248
|
+
{
|
|
249
|
+
$query = $request->input('q', '');
|
|
250
|
+
$search = $this->model('UsersModel')->searchUser($query);
|
|
251
|
+
$data = [
|
|
252
|
+
'users' => $search
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
$html = $this->render('users/search', $data);
|
|
256
|
+
return $this->response($html);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
//Blade
|
|
260
|
+
@if (!empty($users))
|
|
261
|
+
@foreach ($users as $index => $user)
|
|
262
|
+
<tr>
|
|
263
|
+
<td>{{ $index + 1 }}</td>
|
|
264
|
+
<td>{{ $user['fullname'] }}</td>
|
|
265
|
+
</tr>
|
|
266
|
+
@endforeach
|
|
267
|
+
@endif
|
|
268
|
+
```
|
|
269
|
+
|
|
237
270
|
### Pattern B: Form Submission with Indicator & Append Swap
|
|
238
271
|
|
|
239
272
|
```html
|
|
240
|
-
<form
|
|
273
|
+
<form
|
|
274
|
+
lw-post="/comments/add"
|
|
275
|
+
lw-target="#comments-list"
|
|
276
|
+
lw-swap="append"
|
|
277
|
+
lw-indicator="#spinner"
|
|
278
|
+
>
|
|
241
279
|
<textarea name="comment" required placeholder="Write a comment..."></textarea>
|
|
242
|
-
|
|
280
|
+
|
|
243
281
|
<button type="submit">
|
|
244
|
-
Post Comment
|
|
282
|
+
Post Comment
|
|
245
283
|
<span id="spinner" class="litewire-indicator hidden">Posting...</span>
|
|
246
284
|
</button>
|
|
247
285
|
</form>
|
|
@@ -255,9 +293,13 @@ X-CSRF-TOKEN: abc123securehash456
|
|
|
255
293
|
|
|
256
294
|
```html
|
|
257
295
|
<!-- Automatically fetches and replaces content once page loads -->
|
|
258
|
-
<div
|
|
259
|
-
|
|
296
|
+
<div
|
|
297
|
+
lw-get="/analytics/widget"
|
|
298
|
+
lw-trigger="load"
|
|
299
|
+
lw-target="#analytics-container"
|
|
300
|
+
>
|
|
301
|
+
<p>Loading real-time analytics data...</p>
|
|
260
302
|
</div>
|
|
261
303
|
|
|
262
304
|
<div id="analytics-container"></div>
|
|
263
|
-
```
|
|
305
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litewire",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A lightweight HTML-driven AJAX engine and dynamic ES module component loader.",
|
|
5
5
|
"main": "src/litewire.js",
|
|
6
6
|
"module": "src/litewire.js",
|
|
@@ -30,4 +30,4 @@
|
|
|
30
30
|
"url": "https://github.com/languaojs/litewire/issues"
|
|
31
31
|
},
|
|
32
32
|
"homepage": "https://github.com/languaojs/litewire#readme"
|
|
33
|
-
}
|
|
33
|
+
}
|
package/src/litewire.js
CHANGED
|
@@ -97,7 +97,7 @@ class Litewire {
|
|
|
97
97
|
if (!path) return;
|
|
98
98
|
|
|
99
99
|
const cleanPath = path.replace(/^\/+/, '');
|
|
100
|
-
|
|
100
|
+
let url = `${this.baseUrl}/${cleanPath}`;
|
|
101
101
|
|
|
102
102
|
const options = { method: method.toUpperCase(), headers: {} };
|
|
103
103
|
|
|
@@ -106,7 +106,21 @@ class Litewire {
|
|
|
106
106
|
options.headers['X-CSRF-TOKEN'] = csrfToken;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
if (method
|
|
109
|
+
if (method === 'get') {
|
|
110
|
+
const form = el.tagName === 'FORM' ? el : el.closest('form');
|
|
111
|
+
let params = new URLSearchParams();
|
|
112
|
+
|
|
113
|
+
if (form) {
|
|
114
|
+
params = new URLSearchParams(new FormData(form));
|
|
115
|
+
} else if (el.name && el.value !== undefined) {
|
|
116
|
+
params.append(el.name, el.value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const queryString = params.toString();
|
|
120
|
+
if (queryString) {
|
|
121
|
+
url += (url.includes('?') ? '&' : '?') + queryString;
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
110
124
|
const form = el.tagName === 'FORM' ? el : el.closest('form');
|
|
111
125
|
if (form) {
|
|
112
126
|
options.body = new FormData(form);
|