spikijs 1.1.24 → 1.1.25

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
@@ -1,526 +1,304 @@
1
- # Spikijs
1
+ # SpikiJS
2
2
 
3
- Spikijs is a lightweight (~5KB), high-performance JavaScript framework for building interactive interfaces. It works directly with your HTML (no build step required) and uses ES6 Proxies for reactive state management.
3
+ SpikiJS is a lightweight (~5KB), high-performance JavaScript framework for building reactive web applications directly in your HTML without build tools. It utilizes ES6 Proxies for fine-grained reactivity and adheres to a strict Content Security Policy (CSP).
4
4
 
5
- It is designed to be simple, secure (CSP Compliant), and fast.
5
+ ---
6
6
 
7
7
  ## Key Features
8
8
 
9
- * **Tiny Footprint:** Around 5KB gzip. No complex bundlers needed.
10
- * **Zero Inline Logic:** You cannot write JavaScript logic in HTML attributes (e.g., `count++` is forbidden). This enforces clean separation of concerns and complies with strict Content Security Policies (CSP).
11
- * **Deep Reactivity:** Automatically tracks changes in nested objects and arrays using Proxies.
12
- * **Memory Safe:** Explicit `mount()` and `unmount()` methods prevent memory leaks in Single Page Applications.
9
+ - **Tiny Footprint:** Only ~5KB gzip. Works directly in HTML without build tools.
10
+ - **100% CSP Secure:** Safe execution without `eval()` or inline expression vulnerabilities.
11
+ - **Deep Reactivity:** Automatic tracking for nested objects & arrays using ES6 Proxies.
12
+ - **Full SVG Support:** Dynamic attributes and `:class` binding work seamlessly on HTML and SVG.
13
+ - **Auto Loop Context:** `s-for` automatically provides `this.item` and `this.index` in event handlers.
14
+ - **Global Store + `init()`:** Shared state store that automatically runs an `init()` method on registration.
15
+ - **Memory Safe:** Built-in `mount()` and `unmount()` methods to prevent SPA memory leaks.
13
16
 
14
17
  ---
15
18
 
16
- ## Installation
17
-
18
- ### CDN (Browser)
19
- Simply add the script tag to your HTML. Spiki will automatically attach to `window.spiki`.
20
-
21
- ```html
22
- <script src="https://unpkg.com/spikijs"></script>
23
-
24
- ```
25
-
26
- ### NPM (Module)
27
-
28
- Install via package manager.
19
+ ## Content Security Policy (CSP) & Zero Inline Logic
29
20
 
30
- ```bash
31
- npm install spikijs
21
+ SpikiJS enforces strict separation of concerns to comply with modern web security standards:
32
22
 
33
- ```
23
+ 1. **No Inline JS Logic:** Do **NOT** write expressions inside attributes (e.g. `<button s-click="count++">` is forbidden).
24
+ 2. **No Inline Arguments:** Do **NOT** pass function parameters in HTML (e.g. `<button s-click="save(item)">` is forbidden).
25
+ 3. **Method Name Binding:** Always bind function names directly (e.g. `<button s-click="save">`).
26
+ 4. **Access State via `this`:** Mutate and access state properties directly inside component methods via `this.variableName`.
34
27
 
35
28
  ---
36
29
 
37
- ## Usage Strategies
38
-
39
- Choose the initialization method that fits your architecture.
40
-
41
- ### Automatic
42
-
43
- Best for simple websites. Spiki scans the entire document for `s-data` attributes.
44
-
45
- **HTML:**
46
-
47
- ```html
48
- <div s-data="counterApp">
49
- Count: <span s-text="count"></span>
50
- <button s-click="increment">+</button>
51
- </div>
52
-
53
- ```
54
-
55
- **JavaScript:**
56
-
57
- ```javascript
58
- import spiki from 'spikijs';
59
-
60
- // 1. Register Component
61
- spiki.data('counterApp', () => ({
62
- count: 0,
63
- increment() {
64
- this.count++;
65
- }
66
- }));
67
-
68
- // 2. Start Engine (Scans the whole body)
69
- spiki.start();
70
-
71
- ```
72
-
73
- ### Manual Mount
74
-
75
- You control exactly *when* and *where* Spiki starts, and crucially, when it stops to free memory.
30
+ ## Installation
76
31
 
77
- **HTML:**
32
+ ### CDN (Browser)
33
+ Include SpikiJS via script tag. Spiki automatically exposes `window.spiki`:
78
34
 
79
35
  ```html
80
- <div id="my-widget" s-data="counterApp">
81
- Count: <span s-text="count"></span>
82
- <button s-click="increment">+</button>
83
- </div>
84
-
36
+ <script src="https://unpkg.com/spikijs"></script>
85
37
  ```
86
38
 
87
- **JavaScript:**
39
+ ### ESM Module (Modern Browsers / NPM)
40
+ Import SpikiJS directly as an ES module:
88
41
 
89
42
  ```javascript
90
- import spiki from 'spikijs';
91
-
92
- // 1. Register Component logic
93
- spiki.data('counterApp', () => ({
94
- count: 0,
95
- increment() {
96
- this.count++;
97
- }
98
- }));
99
-
100
- // 2. Select the DOM element
101
- const myWidget = document.getElementById('my-widget');
102
-
103
- // 3. Mount Spiki to this specific element
104
- const counterApp = spiki.mount(myWidget);
105
-
106
- // ... later when removing the element or changing pages ...
107
- // 4. Unmount to free memory (Stop watchers and event listeners)
108
- // counterApp.unmount();
109
-
43
+ import spiki from './spikijs/spiki.esm.js';
110
44
  ```
111
45
 
112
46
  ---
113
47
 
114
- ## Quick Start
115
-
116
- 1. **Define HTML**: Add `s-data` to a container.
117
- 2. **Define Logic**: Use `spiki.data()`.
118
- 3. **Start Engine**: Call `spiki.start()`.
119
-
120
- ```html
121
- <div s-data="counterApp">
122
- <h1>Count: <span s-text="count"></span></h1>
123
- <button s-click="increment">Add +1</button>
124
- <button s-click="decrement">Del -1</button>
125
- </div>
126
-
127
- <script src="https://unpkg.com/spikijs"></script>
128
- <script>
129
- // 1. Register Component
130
- spiki.data('counterApp', () => ({
131
- count: 0,
132
- increment() {
133
- this.count++;
134
- },
135
- decrement() {
136
- this.count--;
137
- }
138
- }));
139
-
140
- // 2. Start Spiki
141
- document.addEventListener('DOMContentLoaded', () => {
142
- spiki.start();
143
- });
144
- </script>
145
-
146
- ```
48
+ ## Directives & API Reference
49
+
50
+ | Directive / API | Description | Example |
51
+ | :--- | :--- | :--- |
52
+ | **`s-data`** | Defines component state scope. | `<div s-data="myApp">` |
53
+ | **`s-text`** | Sets safe text content. | `<span s-text="username"></span>` |
54
+ | **`s-html`** | Sets inner HTML (XSS caution). | `<div s-html="richText"></div>` |
55
+ | **`s-if`** | Conditionally mounts/unmounts DOM nodes (supports `!`). | `<div s-if="!isOnline">Offline</div>` |
56
+ | **`:hidden`** | Toggles native `hidden` visibility (replaces `s-show`, supports `!`). | `<div hidden :hidden="!isVisible">Content</div>` |
57
+ | **`s-for`** | Loops array items inside `<template>` tags. | `<template s-for="(item, idx) in list" s-key="id">` |
58
+ | **`s-key`** | Unique key tracking for list items. | `<template ... s-key="id">` |
59
+ | **`s-model`** | Two-way input data binding. | `<input s-model="query">` |
60
+ | **`s-value`** | One-way value binding. | `<input s-value="formattedText" readonly>` |
61
+ | **`s-effect`** | Automatic reactive watcher (runs on state mutations). | `<div s-effect="saveToStorage">` |
62
+ | **`s-ref`** | Registers DOM element reference in `this.$refs`. | `<input s-ref="textInput">` |
63
+ | **`s-init`** | Executes hook on component mount. | `<div s-init="onMount">` |
64
+ | **`s-destroy`** | Executes hook on component unmount. | `<div s-destroy="onUnmount">` |
65
+ | **`s-ignore`** | Skips DOM compilation for static blocks. | `<div s-ignore>` |
66
+ | **`:[attr]`** | Binds dynamic attributes (HTML & SVG). | `<img :src="userAvatar">` |
67
+ | **`:class`** | Binds dynamic classes (HTML & SVG). | `<div :class="activeClass">` |
68
+ | **`s-[event]`** | Attaches event listener (`s-click`, `s-keyup`, etc.). | `<button s-click="submitForm">` |
69
+ | **`this.$root`** | Accesses component's root container element. | `this.$root.classList.add('active');` |
70
+ | **`this.$refs`** | Object containing all `s-ref` DOM elements. | `this.$refs.textInput.focus();` |
71
+ | **`this.$store`** | Accesses registered global stores. | `this.$store.settings.theme` |
72
+ | **`spiki.store()`** | Registers global store (runs `init()` automatically if present). | `spiki.store('settings', { theme: 'dark', init() {} })` |
73
+ | **`spiki.raw()`** | Unwraps Spiki Proxy to a plain JavaScript object. | `const plainObj = spiki.raw(this.user);` |
147
74
 
148
75
  ---
149
76
 
150
- ## Directives Reference
151
-
152
- | Directive | Description | Example |
153
- | --- | --- | --- |
154
- | **`s-data`** | Defines component scope. | `<div s-data="app">` |
155
- | **`s-text`** | Sets text content (Safe). | `<span s-text="msg">` |
156
- | **`s-html`** | Sets innerHTML (Use carefully). | `<div s-html="htmlContent">` |
157
- | **`s-if`** | Conditional rendering. | `<p s-if="showMe">` |
158
- | **`s-for`** | Loops content (requires `<template>`). | `<template s-for="item in list">` |
159
- | **`s-key`** | Unique key for loops (Performance). | `<template ... s-key="id">` |
160
- | **`s-model`** | Two-way binding (Inputs). | `<input s-model="text">` |
161
- | **`s-value`** | One-way value binding. | `<input s-value="text">` |
162
- | **`s-effect`** | Runs function on data change. | `<div s-effect="autoSave">` |
163
- | **`s-ref`** | Stores DOM reference in `$refs`. | `<input s-ref="myInput">` |
164
- | **`s-init`** | Runs on mount. | `<div s-init="onLoad">` |
165
- | **`s-destroy`** | Runs on unmount. | `<div s-destroy="onRemove">` |
166
- | **`s-ignore`** | Skips compilation (Static content). | `<div s-ignore>` |
167
- | **`:[attr]`** | Dynamic attribute binding. | `<img :src="imgUrl">` |
168
- | **`:class`** | Dynamic class toggling. | `<div :class="classConfig">` |
169
- | **`s-[event]`** | Event listener. | `<button s-click="save">` |
170
- | **`this.$root`** | Access the root elm. | `this.$root.classList.add('loaded');` |
171
- | **`this.$store`** | Access the global store. | `this.$store.theme` |
172
- | **`spiki.store()`** | Get or set global store. | `spiki.store('theme', 'dark')` |
173
- | **`spiki.raw()`** | Proxy to original object. | `spiki.raw(this.users)` |
77
+ ## Detailed Feature Documentation
174
78
 
175
- ---
79
+ ### 1. Conditional Rendering (`s-if`) & Visibility (`:hidden`)
176
80
 
177
- ## Detailed Usage Examples
81
+ SpikiJS provides two ways to control element display:
178
82
 
179
- ### 1. Displaying Data (`s-text`)
83
+ - **`s-if`**: Completely mounts or unmounts the element from the DOM tree. Supports negation (`!`).
84
+ - **`:hidden`**: Replaces traditional `s-show` by toggling the native `hidden` DOM attribute. Supports negation (`!`).
180
85
 
181
- Updates the `textContent` of an element. This is safe and prevents XSS attacks.
86
+ > **Pro Tip (Prevent FOUC Glitch):** Add the static `hidden` attribute to elements in HTML (`<div hidden :hidden="show">`) so they remain hidden during page load before JS initializes.
182
87
 
183
88
  ```html
184
- <div s-data="textApp">
185
- <p>Message: <span s-text="msg"></span></p>
186
-
187
- <p>Formatted: <span s-text="formatMsg"></span></p>
89
+ <div s-data="visibilityDemo">
90
+ <button s-click="toggle">Toggle Visibility</button>
91
+
92
+ <!-- s-if (Mount/Unmount) -->
93
+ <div s-if="isOnline">Status: Online</div>
94
+ <div s-if="!isOnline">Status: Disconnected (Negation Example)</div>
95
+
96
+ <!-- :hidden (Visibility Toggle with static hidden attribute to prevent flicker) -->
97
+ <div hidden :hidden="!isVisible">Visible Content</div>
188
98
  </div>
189
99
 
190
100
  <script>
191
- spiki.data('textApp', () => ({
192
- msg: 'hello world',
193
-
194
- // Function receives the element as argument
195
- formatMsg(el) {
196
- // You can manipulate 'el' if needed, but return value is used for text
197
- return this.msg.toUpperCase();
101
+ spiki.data('visibilityDemo', () => ({
102
+ isOnline: true,
103
+ isVisible: true,
104
+ toggle() {
105
+ this.isOnline = !this.isOnline;
106
+ this.isVisible = !this.isVisible;
198
107
  }
199
108
  }));
200
109
  </script>
201
-
202
110
  ```
203
111
 
204
- > **Note:** If you bind a function to `s-text`, that function receives the DOM element (`el`) as its first argument.
112
+ ---
205
113
 
206
- ### 2. Inner HTML (`s-html`)
114
+ ### 2. SVG & HTML Dynamic Class Binding (`:class`)
207
115
 
208
- Updates the `innerHTML`. Only use this if you trust the content source.
116
+ Dynamic class binding works seamlessly on both HTML and SVG elements (preventing `SVGAnimatedString` class errors):
209
117
 
210
118
  ```html
211
- <div s-data="htmlApp">
212
- <div s-html="rawHtml"></div>
213
- </div>
119
+ <div s-data="themeApp">
120
+ <!-- HTML Element -->
121
+ <div :class="statusClass">Component Active</div>
214
122
 
215
- <script>
216
- spiki.data('htmlApp', () => ({
217
- rawHtml: '<b>Bold Text</b> and <i>Italic</i>'
218
- }));
219
- </script>
220
-
221
- ```
222
-
223
- > **Note:** Just like `s-text`, if you use a function here, it receives the DOM element (`el`) as an argument.
224
-
225
- ### 3. Dynamic Attributes (`:[attribute]`)
226
-
227
- You can bind ANY HTML attribute to a variable by adding a colon `:` before the attribute name.
123
+ <!-- SVG Element -->
124
+ <svg :class="iconClass" viewBox="0 0 24 24" fill="none" stroke="currentColor">
125
+ <circle cx="12" cy="12" r="10"></circle>
126
+ </svg>
228
127
 
229
- ```html
230
- <div s-data="attrApp">
231
- <img :src="avatarUrl" :alt="avatarAlt">
232
- <a :href="profileLink">View Profile</a>
233
-
234
- <button :disabled="checkStatus">Submit</button>
128
+ <button s-click="toggleStatus">Toggle Theme</button>
235
129
  </div>
236
130
 
237
131
  <script>
238
- spiki.data('attrApp', () => ({
239
- avatarUrl: 'https://via.placeholder.com/150',
240
- avatarAlt: 'User Avatar',
241
- profileLink: '/profile/user1',
242
- isLoading: true,
243
-
244
- checkStatus(el) {
245
- // 'el' is the button element
246
- if (this.isLoading) {
247
- el.style.opacity = '0.5'; // You can touch DOM directly
248
- return true; // Return value sets the attribute
249
- }
250
- el.style.opacity = '1';
251
- return false;
132
+ spiki.data('themeApp', () => ({
133
+ isActive: false,
134
+ toggleStatus() {
135
+ this.isActive = !this.isActive;
136
+ },
137
+ get statusClass() {
138
+ return this.isActive ? 'bg-indigo-600 text-white' : 'bg-slate-200 text-slate-700';
139
+ },
140
+ get iconClass() {
141
+ return this.isActive ? 'stroke-indigo-500 text-indigo-500' : 'stroke-slate-400 text-slate-400';
252
142
  }
253
143
  }));
254
144
  </script>
255
-
256
145
  ```
257
146
 
258
- > **Note:** The function receives the DOM element (`el`) as an argument. You can use this to perform direct DOM manipulation alongside setting the attribute.
147
+ ---
259
148
 
260
- ### 4. Initialization (`s-init`)
149
+ ### 3. List Rendering & Scope Auto-Injection (`s-for`)
261
150
 
262
- Runs a function immediately when the component is mounted. This is the perfect place for API calls or setting up 3rd party libraries.
151
+ Inside `<template s-for="(child, index) in children">`, event handlers do **NOT** require parameters. Spiki automatically injects `this.child` (current item) and `this.index` (current loop index) directly into method execution context:
263
152
 
264
153
  ```html
265
- <div s-data="usersApp" s-init="loadUsers">
266
- <p s-if="isLoading">Loading...</p>
154
+ <div s-data="todoApp">
155
+ <input s-model="newItem" s-keyup="checkAdd" placeholder="Add fruit (e.g. Mango)...">
156
+ <button s-click="addItem">Add</button>
157
+
267
158
  <ul>
268
- <template s-for="user in users" s-key="id">
269
- <li><span s-text="user.name"></span></li>
159
+ <template s-for="(fruit, idx) in fruits" s-key="id">
160
+ <li>
161
+ #<span s-text="idx"></span>: <span s-text="fruit.name"></span>
162
+ <!-- No parameters needed! this.fruit and this.idx are auto-injected -->
163
+ <button s-click="removeItem">Delete</button>
164
+ </li>
270
165
  </template>
271
166
  </ul>
272
167
  </div>
273
168
 
274
169
  <script>
275
- spiki.data('usersApp', () => ({
276
- isLoading: true,
277
- users: [],
278
-
279
- loadUsers(el) {
280
- // 'el' is the div containing s-init
281
- console.log("Component mounted on:", el);
282
-
283
- var self = this;
284
- fetch('https://jsonplaceholder.typicode.com/users')
285
- .then(function(r) { return r.json() })
286
- .then(function(data) {
287
- self.users = data;
288
- self.isLoading = false;
289
- });
170
+ spiki.data('todoApp', () => ({
171
+ newItem: 'Mango',
172
+ fruits: [
173
+ { id: 1, name: 'Apple' },
174
+ { id: 2, name: 'Banana' }
175
+ ],
176
+ checkAdd(e) {
177
+ if (e.key === 'Enter') this.addItem();
178
+ },
179
+ addItem() {
180
+ if (!this.newItem.trim()) return;
181
+ this.fruits.push({ id: Date.now(), name: this.newItem.trim() });
182
+ this.newItem = '';
183
+ },
184
+ removeItem() {
185
+ // Automatically reads this.idx auto-injected by Spiki loop scope
186
+ if (typeof this.idx === 'number') {
187
+ this.fruits.splice(this.idx, 1);
188
+ }
290
189
  }
291
190
  }));
292
191
  </script>
293
-
294
192
  ```
295
193
 
296
- > **Note:** The function receives the element (`el`) where the directive is placed.
194
+ ---
297
195
 
298
- ### 5. Event Listeners (`s-[event]`)
196
+ ### 4. Instance API: `this.$refs` & `this.$root`
299
197
 
300
- Listen to any DOM event using the `s-` prefix.
198
+ Access raw DOM nodes without query selectors using `this.$refs` and `this.$root`:
301
199
 
302
200
  ```html
303
- <div s-data="eventApp">
304
- <button s-click="handleClick">Click Me</button>
201
+ <div s-data="refDemo">
202
+ <input s-ref="textInput" type="text" value="Spiki Ref Input">
203
+ <button s-click="focusInput">Focus</button>
204
+ <button s-click="highlightContainer">Highlight Container</button>
305
205
  </div>
306
206
 
307
207
  <script>
308
- spiki.data('eventApp', () => ({
309
- handleClick(e) {
310
- // 'e' is the standard Native Event Object
311
- // 'e.target' gives you the element
312
- e.preventDefault();
313
- alert('Button Clicked!');
208
+ spiki.data('refDemo', () => ({
209
+ focusInput() {
210
+ // Access raw HTMLInputElement directly
211
+ this.$refs.textInput.focus();
212
+ this.$refs.textInput.select();
213
+ },
214
+ highlightContainer() {
215
+ // Manipulate component container directly
216
+ this.$root.classList.toggle('ring-2');
314
217
  }
315
218
  }));
316
219
  </script>
317
-
318
220
  ```
319
221
 
320
- > **Note:** Events receive the native Event Object (`e`). You can access the element via `e.target` or `e.currentTarget`.
321
-
322
- ### 6. Side Effects (`s-effect`)
222
+ ---
323
223
 
324
- Use `s-effect` to run a function automatically whenever its dependencies change.
224
+ ### 5. Global Store (`spiki.store()`) with Auto `init()` Execution
325
225
 
326
- ```html
327
- <div s-data="saveApp" s-effect="autoSave">
328
- <textarea s-model="note"></textarea>
329
- <span s-text="status"></span>
330
- </div>
226
+ Register shared global state with `spiki.store('name', stateObject)`. If your store defines an `init()` method, Spiki executes `store.init.call(store)` automatically upon registration:
331
227
 
332
- <script>
333
- spiki.data('saveApp', () => ({
334
- note: localStorage.getItem('note') || '',
335
- status: '',
336
-
337
- autoSave() {
338
- localStorage.setItem('note', this.note);
339
- this.status = 'Saved!';
228
+ ```javascript
229
+ // 1. Register store with automatic init hook
230
+ spiki.store('settings', {
231
+ theme: 'dark',
232
+ initialized: false,
233
+ init() {
234
+ // Runs automatically when store is registered!
235
+ this.theme = localStorage.getItem('theme') || 'dark';
236
+ this.initialized = true;
340
237
  }
341
- }));
342
- </script>
343
-
344
- ```
345
-
346
- > **Note:** The function receives the element (`el`) as an argument. Useful if you need to update something visual on the container when data changes.
347
-
348
- ### 7. Form Inputs (`s-model` vs `s-value`)
349
-
350
- * **`s-model` (Two-Way):** Updates data when user types, and updates input when data changes.
351
- * **`s-value` (One-Way):** Only updates the input when data changes.
352
-
353
- ```html
354
- <div s-data="formApp">
355
- <input type="text" s-model="username">
356
-
357
- <input type="text" s-value="previewName" readonly>
358
- </div>
238
+ });
359
239
 
360
- <script>
361
- spiki.data('formApp', () => ({
362
- username: 'john_doe',
363
-
364
- get previewName() {
365
- return this.username.toUpperCase();
240
+ // 2. Consume store inside any component
241
+ spiki.data('headerApp', () => ({
242
+ get currentTheme() {
243
+ return this.$store.settings.theme; // Reactive store subscription!
244
+ },
245
+ toggleTheme() {
246
+ this.$store.settings.theme = this.$store.settings.theme === 'dark' ? 'light' : 'dark';
366
247
  }
367
248
  }));
368
- </script>
369
-
370
249
  ```
371
250
 
372
251
  ---
373
252
 
374
- ## Mastering Lists (`s-for`)
375
-
376
- ### 1. Basic Loop Requirement
377
-
378
- You **MUST** use the `<template>` tag. Spiki uses the template to stamp out copies of your HTML.
379
-
380
- ```html
381
- <ul>
382
- <template s-for="user in users" s-key="id">
383
- <li><span s-text="user.name"></span></li>
384
- </template>
385
- </ul>
386
-
387
- ```
388
-
389
- ### 2. Accessing Data Inside Loop (`this.item`)
390
-
391
- When you trigger an event inside a loop, Spiki automatically injects the current item into `this`. The property name matches your loop alias.
253
+ ### 6. Unwrapping Reactive Proxies (`spiki.raw()`)
392
254
 
393
- ```html
394
- <div s-data="shopApp">
395
- <ul>
396
- <template s-for="product in products" s-key="id">
397
- <li>
398
- <span s-text="product.name"></span>
399
- <button s-click="selectProduct">Select</button>
400
- </li>
401
- </template>
402
- </ul>
403
- </div>
255
+ Spiki wraps state objects in ES6 Proxies. Use `spiki.raw(proxy)` to unwrap state back into plain JavaScript objects before calling `JSON.stringify()`, logging, or sending network payloads:
404
256
 
405
- <script>
406
- spiki.data('shopApp', () => ({
407
- products: [
408
- { id: 1, name: 'Laptop' },
409
- { id: 2, name: 'Phone' }
410
- ],
411
- selectProduct() {
412
- // 'this.product' is automatically available
413
- console.log('You selected:', this.product.name);
414
- }
415
- }));
416
- </script>
417
-
418
- ```
419
-
420
- ### 3. Accessing Index
421
-
422
- You can get the current index by using parentheses: `(item, index) in array`.
423
-
424
- ```html
425
- <template s-for="(item, i) in list" s-key="id">
426
- <button s-click="remove">
427
- Remove Index <span s-text="i"></span>
428
- </button>
429
- </template>
430
-
431
- <script>
432
- spiki.data('listApp', () => ({
433
- list: ['A', 'B', 'C'],
434
- remove() {
435
- // 'this.i' is automatically available
436
- this.list.splice(this.i, 1);
257
+ ```javascript
258
+ spiki.data('userProfile', () => ({
259
+ user: { name: 'Alice', role: 'Admin' },
260
+
261
+ saveUser() {
262
+ // Extract raw, un-proxied JS object
263
+ const plainData = spiki.raw(this.user);
264
+
265
+ fetch('/api/user', {
266
+ method: 'POST',
267
+ headers: { 'Content-Type': 'application/json' },
268
+ body: JSON.stringify(plainData)
269
+ });
437
270
  }
438
271
  }));
439
- </script>
440
-
441
272
  ```
442
273
 
443
274
  ---
444
275
 
445
- ## Advanced Features
276
+ ### 7. Reactive Side Effects (`s-effect`)
446
277
 
447
- ### DOM References (`s-ref`)
278
+ Use `s-effect="handler"` to run automatic reactive watchers.
448
279
 
449
- Sometimes you need to access the raw DOM element (e.g., to focus an input or play a video).
280
+ > **Warning:** Do **NOT** mutate component state properties inside `s-effect` methods (e.g. `this.runs++`), as modifying state read inside an effect causes an infinite loop. Use `s-effect` strictly for external side effects like `localStorage`, network calls, or direct DOM updates.
450
281
 
451
282
  ```html
452
- <div s-data="refApp">
453
- <input s-ref="myInput" type="text">
454
- <button s-click="focusMe">Focus Input</button>
283
+ <div s-data="noteApp" s-effect="autoSave">
284
+ <input type="text" s-model="note">
455
285
  </div>
456
286
 
457
287
  <script>
458
- spiki.data('refApp', () => ({
459
- focusMe() {
460
- // Access DOM element via this.$refs
461
- this.$refs.myInput.focus();
288
+ spiki.data('noteApp', () => ({
289
+ note: 'Hello Spiki',
290
+ autoSave() {
291
+ // Pure side effect: read state and write to localStorage
292
+ try {
293
+ localStorage.setItem('user_note', this.note);
294
+ } catch(e) {}
462
295
  }
463
296
  }));
464
297
  </script>
465
-
466
298
  ```
467
299
 
468
300
  ---
469
301
 
470
- ## Core Concepts
471
-
472
- ### Component Instance (`this`)
473
-
474
- Inside your functions, `this` refers to your component state.
475
-
476
- > **Warning:** Do not use arrow functions for methods (`func: () => {}`) if you need `this`. Use method shorthand (`func() {}`) instead.
477
-
478
- Spiki injects helper properties:
479
-
480
- * **`this.$root`**: The HTML element containing the component.
481
- * **`this.$refs`**: Access elements marked with `s-ref`.
482
- * **`this.$store`**: Access the global store.
483
- * **`this.$parent`**: Access the parent component.
484
-
485
- ### Global Store
486
-
487
- Share state across multiple components.
488
-
489
- ```javascript
490
- // 1. Define Store
491
- spiki.store('user', {
492
- name: 'John Doe',
493
- isLoggedIn: true
494
- });
495
-
496
- // 2. Use in Component
497
- spiki.data('profile', () => ({
498
- get userName() {
499
- return this.$store.user.name; // Reactive!
500
- }
501
- }));
502
-
503
- ```
504
-
505
- ### `spiki.raw(proxy)`
506
-
507
- Get the original object from a Spiki proxy. Useful for console logging or API calls.
508
-
509
- ```javascript
510
- const cleanData = spiki.raw(this.myData);
511
- console.log(cleanData);
512
-
513
- ```
514
-
515
- ---
516
-
517
- ## Browser Support
518
-
519
- Spiki requires a browser that supports **ES6 Proxy**.
520
-
521
- * **Supported:** Chrome, Firefox, Edge, Safari (Modern versions).
522
- * **Not Supported:** Internet Explorer 11.
523
-
524
302
  ## License
525
303
 
526
304
  MIT License.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "spikijs",
3
3
  "license": "MIT",
4
- "version": "1.1.24",
4
+ "version": "1.1.25",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
package/spiki.esm.js CHANGED
@@ -233,7 +233,7 @@ var spiki = (() => {
233
233
  for (var k in val) val[k] ? (obj[k] = 1) : delete obj[k];
234
234
  }
235
235
  var res = Object.keys(obj).join(' ');
236
- if (el.className !== res) el.className = res;
236
+ if ((el.getAttribute('class') || '') !== res) el.setAttribute('class', res);
237
237
  };
238
238
 
239
239
  var mount = (rootElement, parentScope) => {
@@ -328,7 +328,7 @@ var spiki = (() => {
328
328
  var directiveFor = !directiveIf && el.tagName === 'TEMPLATE' && el.getAttribute('s-for');
329
329
  var bindings = [];
330
330
 
331
- if (el.hasAttribute('class') && !el._n) el._n = el.className;
331
+ if (el.hasAttribute('class') && !el._n) el._n = el.getAttribute('class');
332
332
 
333
333
  if (directiveIf) {
334
334
  var end = document.createTextNode('');
package/spiki.esm.min.js CHANGED
@@ -1 +1 @@
1
- var spiki=(()=>{var r,e=Object,t=Array,a=Reflect,n=Promise,o=Node,i=document,l=console,v="length",f="value",s="push",u="forEach",p="indexOf",c="split",_="slice",d="call",y="keys",h="get",m="prototype",g="hasOwnProperty",b="getPrototypeOf",x="defineProperty",P="create",k="isArray",A="getAttribute",N="removeAttribute",w="hasAttribute",E="tagName",S="type",T="name",$="checked",O="parentNode",j="nextSibling",C="textContent",L="innerHTML",q="replaceWith",M="insertBefore",D="cloneNode",F="remove",K="createTextNode",B="addEventListener",H="input",R="checkbox",W="function",z="radio",G="class",I="model",J="object",Q="unshift",U="scope",V="trim",X="cleanups",Y="nodes",Z="deps",rr="className",er="destroy",tr="init",ar="charCodeAt",nr="sched",or="string",ir="unmount",lr="attr",vr="s-data",fr="s-if",sr=e[P](null),ur=[],pr=!1,cr=null,_r=!1,dr=n.resolve(),yr={blur:1,focus:1,scroll:1,load:1,error:1,mouseenter:1,mouseleave:1,toggle:1},hr=r=>{r._q||(r._q=!0,ur[s](r),pr||(pr=!0,dr.then(()=>{var r=ur;ur=[],pr=!1;for(var e=r[v];e--;)r[e]._q=!1,r[e]()})))},mr=(r,e)=>{var a,n=r;if(typeof e===or)a=r?r[e]:void 0;else{for(var o=0,i=e[v];o<i-1&&n;)n=n[e[o++]];a=n?n[e[i-1]]:void 0}if(void 0===a){var f=t[k](e)?e.join("."):e;l.warn("[spikijs] Property undefined: "+f)}return{ctx:n,val:a}},gr={};[s,"pop","shift",Q,"splice","sort","reverse"][u](r=>{gr[r]=function(...e){_r=!0;try{return t[m][r].apply(this,e)}finally{_r=!1,xr(this,v)}}});var br=(r,t)=>{if(cr){var a=r._d||(e[x](r,"_d",{value:e[P](null),writable:!0}),r._d),n=a[t]||(a[t]=[]);-1===n[p](cr)&&(n[s](cr),cr[Z][s](n))}},xr=(r,e)=>{if(!_r&&r._d&&r._d[e])for(var t=r._d[e][_](),a=0,n=t[v];a<n;a++){var o=t[a];o[nr]?o[nr](o):o()}},Pr=r=>{for(var e=r[Z][v];e--;){var t=r[Z][e],a=t[p](r);-1!==a&&(t[a]=t[t[v]-1],t.pop())}r[Z]=[]},kr=(r,e)=>{var t=()=>{Pr(t);var e=cr;cr=t;try{r()}finally{cr=e}};return t[Z]=[],t[nr]=e,t(),()=>Pr(t)},Ar=r=>{if(!r||typeof r!==J||r._y||r instanceof o)return r;if(e[m][g][d](r,"_p"))return r._p;var n=new Proxy(r,{get:(r,n,i)=>{if("_y"===n)return i===r._p;if("_t"===n)return r;if("_d"===n)return r._d;if("_i"===n)return r._i;if(t[k](r)&&gr[g](n))return gr[n];var l=e.getOwnPropertyDescriptor(r,n);if(l&&l[h]){var v="_"+n;return v in r||kr(()=>i[v]=l[h][d](i)),i[v]}br(r,n);var f=a[h](r,n,i);return!f||typeof f!==J||f instanceof o?f:Ar(f)},set:(r,n,o,i)=>{var l=r[n],f=t[k](r),s=f?Number(n)<r[v]:e[m][g][d](r,n);if(r._i&&!s)for(var u=e[b](r);u&&u!==e[m];){if(e[m][g][d](u,n)){var p=a.set(u,n,o);return _r||o===l||xr(r,n),p}u=e[b](u)}return p=a.set(r,n,o,i),!_r&&p&&(s&&o===l||(xr(r,n),f?xr(r,v):s||xr(r,"_k"))),p},deleteProperty:(r,n)=>{var o=e[m][g][d](r,n),i=a.deleteProperty(r,n);return i&&o&&(xr(r,n),t[k](r)?xr(r,v):xr(r,"_k")),i},ownKeys:r=>(br(r,"_k"),a.ownKeys(r))});return e[x](r,"_p",{value:n}),n};r=Ar({});var Nr=e[P](null);Nr.text=(r,e)=>{e=null==e?"":e,r[C]!==String(e)&&(r[C]=e)},Nr.html=(r,e)=>{r[L]!=e&&(r[L]=null==e?"":e)},Nr[f]=(r,e)=>{r[S]===R?r[$]=!!e:r[S]===z?r[$]=r[f]==e:r[f]!=e&&(r[f]=null==e?"":e)},Nr[lr]=(r,e,t)=>{if(null==e||!1===e)r[N](t);else{var a=!0===e?"":String(e);r[A](t)!==a&&r.setAttribute(t,a)}},Nr[G]=(r,t)=>{var a=r._n||"",n=e[P](null);if(a[c](/\s+/)[u](r=>r&&(n[r]=1)),typeof t===or)t[c](/\s+/)[u](r=>r&&(n[r]=1));else if(t)for(var o in t)t[o]?n[o]=1:delete n[o];var i=e[y](n).join(" ");r[rr]!==i&&(r[rr]=i)};var wr=(a,n)=>{if(a._m)return a._m;var o=a[A](vr);if(sr[o]){var l=sr[o]();n&&e.setPrototypeOf(l,n);var h=Ar(l);h.$refs={},h.$root=a,h.$store=r,h.$parent=n;var g=[],b=e[P](null),C=r=>{var t=r.target;if(r[S]!==H||!t._c)for(var n=a[O],o=r[S];t&&t!==n;){var i=t._h&&t._h[o];if(i){var l=t._s;if(!l||l.$root!==h.$root){t=t[O];continue}for(var s=i[v];s--;){var u=i[s],p=u.p;if(u[I]){var c=t[S]===R?t[$]:t[f];if(typeof c===or){var _=c[V]();_&&isFinite(_)&&(48===_[ar](0)&&1!==_[v]&&46!==_[ar](1)||(c=Number(_)))}if(typeof p===or)l&&(l[p]=c);else{for(var y=l,m=0,g=p[v]-1;m<g&&y;)y=y[p[m++]];y&&(y[p[g]]=c)}}else{var b=mr(l,p);typeof b.val===W&&(e[x](r,"currentTarget",{configurable:!0,value:t}),b.val[d](b.ctx,r))}}}t=t[O]}},L=r=>{b[r]||(b[r]=!0,a[B](r,C,!!yr[r]))},Z=(r,n,o)=>{if(1===r.nodeType&&!r[w]("s-ignore"))if(r!==a&&r[w](vr)){var l=wr(r,n);l&&o[s](l[ir])}else{var g=r[A](fr),b=!g&&"TEMPLATE"===r[E]&&r[A]("s-for"),$=[];if(r[w](G)&&!r._n&&(r._n=r[rr]),g){var nr=i[K](""),or=null,sr=[];r[q](nr);var ur="!"===g[0],pr=ur?g[_](1):g,cr=-1===pr[p](".")?pr:pr[c](".");return o[s](()=>{for(var r=sr[v];r--;)sr[r]()}),o[s](kr(()=>{var e=mr(n,cr).val;if(ur&&(e=!e),e)or||((or=r[D](!0))[N](fr),Z(or,n,sr),nr[O][M](or,nr));else if(or){for(var t=sr[v];t--;)sr[t]();sr=[],or[F](),or=null}},hr))}if(b){var _r=b[p](" in ");if(-1!==_r){var dr,yr=b[_](0,_r)[V](),gr=b[_](_r+4)[V](),xr=yr.replace(/[()]/g,"")[c](","),Pr=xr[0][V](),Er=xr[1]?xr[1][V]():null,Sr=-1===gr[p](".")?gr:gr[c]("."),Tr=r[A]("s-key"),$r=Tr?-1===Tr[p](".")?Tr:Tr[c]("."):null,Or=(nr=i[K](""),e[P](null));return r[q](nr),o[s](()=>{for(var r in Or)Or[r][X][u](r=>r())}),o[s](kr(()=>{var a=mr(n,Sr).val||[];"number"==typeof a&&(a=t.from({length:Math.max(0,Math.floor(a))},(r,e)=>e+1)),t[k](a)&&br(a,v);var o=i.createDocumentFragment(),l=nr;dr=e[P](null);for(var f=t[k](a),s=f?a:e[y](a),p=f?a[v]:s[v],c=0;c<p;c++){var h,g=f?c:s[c],b=f?a[c]:a[g];h=null==b||typeof b!==J?String(b):$r?mr(b,$r).val:String(g)+"_o",dr[h]&&(h+="_"+c);var A=Or[h];if(A)A[U][Pr]=b,Er&&(A[U][Er]=g);else{var N=r.content[D](!0),w=e[P](n);e[x](w,"_i",{value:!0});var E=Ar(w);E[Pr]=b,Er&&(E[Er]=g);for(var S=t[m][_][d](N.childNodes),T=[],$=0;$<S[v];$++)Z(S[$],E,T);A={nodes:t[m][_][d](N.childNodes),scope:E,cleanups:T},Or[h]=A}if(A[Y][0]!==l[j]){for($=0;$<A[Y][v];$++)o.appendChild(A[Y][$]);l[O][M](o,l[j])}l=A[Y][A[Y][v]-1],dr[h]=!0}for(var C in Or)dr[C]||(Or[C][X][u](r=>r()),Or[C][Y][u](r=>r[F]()),delete Or[C])},hr))}}if(r.hasAttributes())for(var jr=r.attributes,Cr=jr[v];Cr--;){var Lr=jr[Cr],qr=Lr[T],Mr=Lr[f];if(58===qr[ar](0)){var Dr=qr[_](1),Fr=33===Mr[ar](0),Kr=Fr?Mr[_](1):Mr;cr=-1===Kr[p](".")?Kr:Kr[c]("."),$[s]({type:lr,name:Dr,path:cr,neg:Fr})}else if(115===qr[ar](0)&&45===qr[ar](1)){let e=qr[_](2),t=-1===Mr[p](".")?Mr:Mr[c](".");if(e===tr||e===er)((e,t)=>{var a=mr(n,t);typeof a.val===W&&(e===tr?hr(()=>{var e=a.val[d](a.ctx,r);typeof e===W&&o[s](e)}):o[s](()=>a.val[d](a.ctx,r)))})(e,t);else if("effect"===e)o[s](kr(()=>{var e=mr(n,t);typeof e.val===W&&e.val[d](e.ctx,r)},hr));else if(e===I){$[s]({type:f,path:t}),r._s=n,r._h=r._h||{};var Br=r[S]===R||r[S]===z||"SELECT"===r[E]?"change":H;Br===H&&(r[B]("compositionstart",()=>r._c=!0),r[B]("compositionend",()=>{r._c=!1,C({target:r,type:H})})),(r._h[Br]=r._h[Br]||[])[s]({model:!0,p:t}),L(Br)}else"ref"===e?h.$refs[Mr]=r:Nr[e]?$[s]({type:e,path:t}):(r._s=n,r._h=r._h||{},(r._h[e]=r._h[e]||[])[Q]({p:t}),L(e))}}$[v]&&o[s](kr(()=>{for(var e=$[v];e--;){var t=$[e],a=mr(n,t.path),o=typeof a.val===W?a.val[d](a.ctx,r):a.val;t[S]===lr?(t.neg&&(o=!o),t[T]===G?Nr[G](r,o):Nr[lr](r,o,t[T])):Nr[t[S]](r,o)}},hr));for(var Hr=r.firstChild;Hr;){var Rr=Hr[j];Z(Hr,n,o),Hr=Rr}}};Z(a,h,g),h[tr]&&h[tr]();var nr={unmount:()=>{h[er]&&h[er][d](h);for(var r=g[v];r--;)g[r]();for(var e in b)a.removeEventListener(e,C);a._m=null}};return a._m=nr,nr}},Er=r=>{if(!r||typeof r!==J)return r;var e=r._t||r;if(t[k](e))return e.map(r=>Er(r));var a={};for(var n in e)a[n]=Er(e[n]);return a};return{data:(r,e)=>{sr[r]=e},start:()=>{for(var r=i.querySelectorAll("[s-data]"),e=r[v];e--;)wr(r[e])},store:(e,t)=>{if(void 0===t)return r[e];r[e]=t;var a=r[e];return a&&typeof a[tr]===W&&a[tr][d](a),a},raw:Er,mount:r=>wr(r),unmount:r=>{r&&r._m&&r._m[ir]()}}})();export default spiki;
1
+ var spiki=(()=>{var r,e=Object,t=Array,a=Reflect,n=Promise,o=Node,i=document,l=console,v="length",f="value",s="push",u="forEach",p="indexOf",c="split",_="slice",d="call",y="keys",h="get",m="prototype",g="hasOwnProperty",b="getPrototypeOf",x="defineProperty",P="create",k="isArray",A="getAttribute",N="setAttribute",w="removeAttribute",E="hasAttribute",S="tagName",T="type",$="name",O="checked",j="parentNode",C="nextSibling",L="textContent",q="innerHTML",M="replaceWith",D="insertBefore",F="cloneNode",K="remove",B="createTextNode",H="addEventListener",R="input",W="checkbox",z="function",G="radio",I="class",J="model",Q="object",U="unshift",V="scope",X="trim",Y="cleanups",Z="nodes",rr="deps",er="destroy",tr="init",ar="charCodeAt",nr="sched",or="string",ir="unmount",lr="attr",vr="s-data",fr="s-if",sr=e[P](null),ur=[],pr=!1,cr=null,_r=!1,dr=n.resolve(),yr={blur:1,focus:1,scroll:1,load:1,error:1,mouseenter:1,mouseleave:1,toggle:1},hr=r=>{r._q||(r._q=!0,ur[s](r),pr||(pr=!0,dr.then(()=>{var r=ur;ur=[],pr=!1;for(var e=r[v];e--;)r[e]._q=!1,r[e]()})))},mr=(r,e)=>{var a,n=r;if(typeof e===or)a=r?r[e]:void 0;else{for(var o=0,i=e[v];o<i-1&&n;)n=n[e[o++]];a=n?n[e[i-1]]:void 0}if(void 0===a){var f=t[k](e)?e.join("."):e;l.warn("[spikijs] Property undefined: "+f)}return{ctx:n,val:a}},gr={};[s,"pop","shift",U,"splice","sort","reverse"][u](r=>{gr[r]=function(...e){_r=!0;try{return t[m][r].apply(this,e)}finally{_r=!1,xr(this,v)}}});var br=(r,t)=>{if(cr){var a=r._d||(e[x](r,"_d",{value:e[P](null),writable:!0}),r._d),n=a[t]||(a[t]=[]);-1===n[p](cr)&&(n[s](cr),cr[rr][s](n))}},xr=(r,e)=>{if(!_r&&r._d&&r._d[e])for(var t=r._d[e][_](),a=0,n=t[v];a<n;a++){var o=t[a];o[nr]?o[nr](o):o()}},Pr=r=>{for(var e=r[rr][v];e--;){var t=r[rr][e],a=t[p](r);-1!==a&&(t[a]=t[t[v]-1],t.pop())}r[rr]=[]},kr=(r,e)=>{var t=()=>{Pr(t);var e=cr;cr=t;try{r()}finally{cr=e}};return t[rr]=[],t[nr]=e,t(),()=>Pr(t)},Ar=r=>{if(!r||typeof r!==Q||r._y||r instanceof o)return r;if(e[m][g][d](r,"_p"))return r._p;var n=new Proxy(r,{get:(r,n,i)=>{if("_y"===n)return i===r._p;if("_t"===n)return r;if("_d"===n)return r._d;if("_i"===n)return r._i;if(t[k](r)&&gr[g](n))return gr[n];var l=e.getOwnPropertyDescriptor(r,n);if(l&&l[h]){var v="_"+n;return v in r||kr(()=>i[v]=l[h][d](i)),i[v]}br(r,n);var f=a[h](r,n,i);return!f||typeof f!==Q||f instanceof o?f:Ar(f)},set:(r,n,o,i)=>{var l=r[n],f=t[k](r),s=f?Number(n)<r[v]:e[m][g][d](r,n);if(r._i&&!s)for(var u=e[b](r);u&&u!==e[m];){if(e[m][g][d](u,n)){var p=a.set(u,n,o);return _r||o===l||xr(r,n),p}u=e[b](u)}return p=a.set(r,n,o,i),!_r&&p&&(s&&o===l||(xr(r,n),f?xr(r,v):s||xr(r,"_k"))),p},deleteProperty:(r,n)=>{var o=e[m][g][d](r,n),i=a.deleteProperty(r,n);return i&&o&&(xr(r,n),t[k](r)?xr(r,v):xr(r,"_k")),i},ownKeys:r=>(br(r,"_k"),a.ownKeys(r))});return e[x](r,"_p",{value:n}),n};r=Ar({});var Nr=e[P](null);Nr.text=(r,e)=>{e=null==e?"":e,r[L]!==String(e)&&(r[L]=e)},Nr.html=(r,e)=>{r[q]!=e&&(r[q]=null==e?"":e)},Nr[f]=(r,e)=>{r[T]===W?r[O]=!!e:r[T]===G?r[O]=r[f]==e:r[f]!=e&&(r[f]=null==e?"":e)},Nr[lr]=(r,e,t)=>{if(null==e||!1===e)r[w](t);else{var a=!0===e?"":String(e);r[A](t)!==a&&r[N](t,a)}},Nr[I]=(r,t)=>{var a=r._n||"",n=e[P](null);if(a[c](/\s+/)[u](r=>r&&(n[r]=1)),typeof t===or)t[c](/\s+/)[u](r=>r&&(n[r]=1));else if(t)for(var o in t)t[o]?n[o]=1:delete n[o];var i=e[y](n).join(" ");(r[A](I)||"")!==i&&r[N](I,i)};var wr=(a,n)=>{if(a._m)return a._m;var o=a[A](vr);if(sr[o]){var l=sr[o]();n&&e.setPrototypeOf(l,n);var h=Ar(l);h.$refs={},h.$root=a,h.$store=r,h.$parent=n;var g=[],b=e[P](null),N=r=>{var t=r.target;if(r[T]!==R||!t._c)for(var n=a[j],o=r[T];t&&t!==n;){var i=t._h&&t._h[o];if(i){var l=t._s;if(!l||l.$root!==h.$root){t=t[j];continue}for(var s=i[v];s--;){var u=i[s],p=u.p;if(u[J]){var c=t[T]===W?t[O]:t[f];if(typeof c===or){var _=c[X]();_&&isFinite(_)&&(48===_[ar](0)&&1!==_[v]&&46!==_[ar](1)||(c=Number(_)))}if(typeof p===or)l&&(l[p]=c);else{for(var y=l,m=0,g=p[v]-1;m<g&&y;)y=y[p[m++]];y&&(y[p[g]]=c)}}else{var b=mr(l,p);typeof b.val===z&&(e[x](r,"currentTarget",{configurable:!0,value:t}),b.val[d](b.ctx,r))}}}t=t[j]}},L=r=>{b[r]||(b[r]=!0,a[H](r,N,!!yr[r]))},q=(r,n,o)=>{if(1===r.nodeType&&!r[E]("s-ignore"))if(r!==a&&r[E](vr)){var l=wr(r,n);l&&o[s](l[ir])}else{var g=r[A](fr),b=!g&&"TEMPLATE"===r[S]&&r[A]("s-for"),O=[];if(r[E](I)&&!r._n&&(r._n=r[A](I)),g){var rr=i[B](""),nr=null,or=[];r[M](rr);var sr="!"===g[0],ur=sr?g[_](1):g,pr=-1===ur[p](".")?ur:ur[c](".");return o[s](()=>{for(var r=or[v];r--;)or[r]()}),o[s](kr(()=>{var e=mr(n,pr).val;if(sr&&(e=!e),e)nr||((nr=r[F](!0))[w](fr),q(nr,n,or),rr[j][D](nr,rr));else if(nr){for(var t=or[v];t--;)or[t]();or=[],nr[K](),nr=null}},hr))}if(b){var cr=b[p](" in ");if(-1!==cr){var _r,dr=b[_](0,cr)[X](),yr=b[_](cr+4)[X](),gr=dr.replace(/[()]/g,"")[c](","),xr=gr[0][X](),Pr=gr[1]?gr[1][X]():null,Er=-1===yr[p](".")?yr:yr[c]("."),Sr=r[A]("s-key"),Tr=Sr?-1===Sr[p](".")?Sr:Sr[c]("."):null,$r=(rr=i[B](""),e[P](null));return r[M](rr),o[s](()=>{for(var r in $r)$r[r][Y][u](r=>r())}),o[s](kr(()=>{var a=mr(n,Er).val||[];"number"==typeof a&&(a=t.from({length:Math.max(0,Math.floor(a))},(r,e)=>e+1)),t[k](a)&&br(a,v);var o=i.createDocumentFragment(),l=rr;_r=e[P](null);for(var f=t[k](a),s=f?a:e[y](a),p=f?a[v]:s[v],c=0;c<p;c++){var h,g=f?c:s[c],b=f?a[c]:a[g];h=null==b||typeof b!==Q?String(b):Tr?mr(b,Tr).val:String(g)+"_o",_r[h]&&(h+="_"+c);var A=$r[h];if(A)A[V][xr]=b,Pr&&(A[V][Pr]=g);else{var N=r.content[F](!0),w=e[P](n);e[x](w,"_i",{value:!0});var E=Ar(w);E[xr]=b,Pr&&(E[Pr]=g);for(var S=t[m][_][d](N.childNodes),T=[],$=0;$<S[v];$++)q(S[$],E,T);A={nodes:t[m][_][d](N.childNodes),scope:E,cleanups:T},$r[h]=A}if(A[Z][0]!==l[C]){for($=0;$<A[Z][v];$++)o.appendChild(A[Z][$]);l[j][D](o,l[C])}l=A[Z][A[Z][v]-1],_r[h]=!0}for(var O in $r)_r[O]||($r[O][Y][u](r=>r()),$r[O][Z][u](r=>r[K]()),delete $r[O])},hr))}}if(r.hasAttributes())for(var Or=r.attributes,jr=Or[v];jr--;){var Cr=Or[jr],Lr=Cr[$],qr=Cr[f];if(58===Lr[ar](0)){var Mr=Lr[_](1),Dr=33===qr[ar](0),Fr=Dr?qr[_](1):qr;pr=-1===Fr[p](".")?Fr:Fr[c]("."),O[s]({type:lr,name:Mr,path:pr,neg:Dr})}else if(115===Lr[ar](0)&&45===Lr[ar](1)){let e=Lr[_](2),t=-1===qr[p](".")?qr:qr[c](".");if(e===tr||e===er)((e,t)=>{var a=mr(n,t);typeof a.val===z&&(e===tr?hr(()=>{var e=a.val[d](a.ctx,r);typeof e===z&&o[s](e)}):o[s](()=>a.val[d](a.ctx,r)))})(e,t);else if("effect"===e)o[s](kr(()=>{var e=mr(n,t);typeof e.val===z&&e.val[d](e.ctx,r)},hr));else if(e===J){O[s]({type:f,path:t}),r._s=n,r._h=r._h||{};var Kr=r[T]===W||r[T]===G||"SELECT"===r[S]?"change":R;Kr===R&&(r[H]("compositionstart",()=>r._c=!0),r[H]("compositionend",()=>{r._c=!1,N({target:r,type:R})})),(r._h[Kr]=r._h[Kr]||[])[s]({model:!0,p:t}),L(Kr)}else"ref"===e?h.$refs[qr]=r:Nr[e]?O[s]({type:e,path:t}):(r._s=n,r._h=r._h||{},(r._h[e]=r._h[e]||[])[U]({p:t}),L(e))}}O[v]&&o[s](kr(()=>{for(var e=O[v];e--;){var t=O[e],a=mr(n,t.path),o=typeof a.val===z?a.val[d](a.ctx,r):a.val;t[T]===lr?(t.neg&&(o=!o),t[$]===I?Nr[I](r,o):Nr[lr](r,o,t[$])):Nr[t[T]](r,o)}},hr));for(var Br=r.firstChild;Br;){var Hr=Br[C];q(Br,n,o),Br=Hr}}};q(a,h,g),h[tr]&&h[tr]();var rr={unmount:()=>{h[er]&&h[er][d](h);for(var r=g[v];r--;)g[r]();for(var e in b)a.removeEventListener(e,N);a._m=null}};return a._m=rr,rr}},Er=r=>{if(!r||typeof r!==Q)return r;var e=r._t||r;if(t[k](e))return e.map(r=>Er(r));var a={};for(var n in e)a[n]=Er(e[n]);return a};return{data:(r,e)=>{sr[r]=e},start:()=>{for(var r=i.querySelectorAll("[s-data]"),e=r[v];e--;)wr(r[e])},store:(e,t)=>{if(void 0===t)return r[e];r[e]=t;var a=r[e];return a&&typeof a[tr]===z&&a[tr][d](a),a},raw:Er,mount:r=>wr(r),unmount:r=>{r&&r._m&&r._m[ir]()}}})();export default spiki;
package/spiki.js CHANGED
@@ -236,7 +236,7 @@ var spiki = (() => {
236
236
  for (var k in val) val[k] ? (obj[k] = 1) : delete obj[k];
237
237
  }
238
238
  var res = Object.keys(obj).join(' ');
239
- if (el.className !== res) el.className = res;
239
+ if ((el.getAttribute('class') || '') !== res) el.setAttribute('class', res);
240
240
  };
241
241
 
242
242
  var mount = (rootElement, parentScope) => {
@@ -331,7 +331,7 @@ var spiki = (() => {
331
331
  var directiveFor = !directiveIf && el.tagName === 'TEMPLATE' && el.getAttribute('s-for');
332
332
  var bindings = [];
333
333
 
334
- if (el.hasAttribute('class') && !el._n) el._n = el.className;
334
+ if (el.hasAttribute('class') && !el._n) el._n = el.getAttribute('class');
335
335
 
336
336
  if (directiveIf) {
337
337
  var end = document.createTextNode('');
package/spiki.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{"use strict";var spiki=(()=>{var r,e=Object,t=Array,a=Reflect,n=Promise,o=Node,i=document,l=console,v="length",f="value",s="push",u="forEach",p="indexOf",c="split",_="slice",d="call",y="keys",h="get",m="prototype",g="hasOwnProperty",b="getPrototypeOf",x="defineProperty",P="create",k="isArray",A="getAttribute",N="removeAttribute",w="hasAttribute",E="tagName",S="type",T="name",$="checked",O="parentNode",j="nextSibling",C="textContent",L="innerHTML",q="replaceWith",M="insertBefore",D="cloneNode",F="remove",K="createTextNode",B="addEventListener",H="input",R="checkbox",W="function",z="radio",G="class",I="model",J="object",Q="unshift",U="scope",V="trim",X="cleanups",Y="nodes",Z="deps",rr="className",er="destroy",tr="init",ar="charCodeAt",nr="sched",or="string",ir="unmount",lr="attr",vr="s-data",fr="s-if",sr=e[P](null),ur=[],pr=!1,cr=null,_r=!1,dr=n.resolve(),yr={blur:1,focus:1,scroll:1,load:1,error:1,mouseenter:1,mouseleave:1,toggle:1},hr=r=>{r._q||(r._q=!0,ur[s](r),pr||(pr=!0,dr.then(()=>{var r=ur;ur=[],pr=!1;for(var e=r[v];e--;)r[e]._q=!1,r[e]()})))},mr=(r,e)=>{var a,n=r;if(typeof e===or)a=r?r[e]:void 0;else{for(var o=0,i=e[v];o<i-1&&n;)n=n[e[o++]];a=n?n[e[i-1]]:void 0}if(void 0===a){var f=t[k](e)?e.join("."):e;l.warn("[spikijs] Property undefined: "+f)}return{ctx:n,val:a}},gr={};[s,"pop","shift",Q,"splice","sort","reverse"][u](r=>{gr[r]=function(...e){_r=!0;try{return t[m][r].apply(this,e)}finally{_r=!1,xr(this,v)}}});var br=(r,t)=>{if(cr){var a=r._d||(e[x](r,"_d",{value:e[P](null),writable:!0}),r._d),n=a[t]||(a[t]=[]);-1===n[p](cr)&&(n[s](cr),cr[Z][s](n))}},xr=(r,e)=>{if(!_r&&r._d&&r._d[e])for(var t=r._d[e][_](),a=0,n=t[v];a<n;a++){var o=t[a];o[nr]?o[nr](o):o()}},Pr=r=>{for(var e=r[Z][v];e--;){var t=r[Z][e],a=t[p](r);-1!==a&&(t[a]=t[t[v]-1],t.pop())}r[Z]=[]},kr=(r,e)=>{var t=()=>{Pr(t);var e=cr;cr=t;try{r()}finally{cr=e}};return t[Z]=[],t[nr]=e,t(),()=>Pr(t)},Ar=r=>{if(!r||typeof r!==J||r._y||r instanceof o)return r;if(e[m][g][d](r,"_p"))return r._p;var n=new Proxy(r,{get:(r,n,i)=>{if("_y"===n)return i===r._p;if("_t"===n)return r;if("_d"===n)return r._d;if("_i"===n)return r._i;if(t[k](r)&&gr[g](n))return gr[n];var l=e.getOwnPropertyDescriptor(r,n);if(l&&l[h]){var v="_"+n;return v in r||kr(()=>i[v]=l[h][d](i)),i[v]}br(r,n);var f=a[h](r,n,i);return!f||typeof f!==J||f instanceof o?f:Ar(f)},set:(r,n,o,i)=>{var l=r[n],f=t[k](r),s=f?Number(n)<r[v]:e[m][g][d](r,n);if(r._i&&!s)for(var u=e[b](r);u&&u!==e[m];){if(e[m][g][d](u,n)){var p=a.set(u,n,o);return _r||o===l||xr(r,n),p}u=e[b](u)}return p=a.set(r,n,o,i),!_r&&p&&(s&&o===l||(xr(r,n),f?xr(r,v):s||xr(r,"_k"))),p},deleteProperty:(r,n)=>{var o=e[m][g][d](r,n),i=a.deleteProperty(r,n);return i&&o&&(xr(r,n),t[k](r)?xr(r,v):xr(r,"_k")),i},ownKeys:r=>(br(r,"_k"),a.ownKeys(r))});return e[x](r,"_p",{value:n}),n};r=Ar({});var Nr=e[P](null);Nr.text=(r,e)=>{e=null==e?"":e,r[C]!==String(e)&&(r[C]=e)},Nr.html=(r,e)=>{r[L]!=e&&(r[L]=null==e?"":e)},Nr[f]=(r,e)=>{r[S]===R?r[$]=!!e:r[S]===z?r[$]=r[f]==e:r[f]!=e&&(r[f]=null==e?"":e)},Nr[lr]=(r,e,t)=>{if(null==e||!1===e)r[N](t);else{var a=!0===e?"":String(e);r[A](t)!==a&&r.setAttribute(t,a)}},Nr[G]=(r,t)=>{var a=r._n||"",n=e[P](null);if(a[c](/\s+/)[u](r=>r&&(n[r]=1)),typeof t===or)t[c](/\s+/)[u](r=>r&&(n[r]=1));else if(t)for(var o in t)t[o]?n[o]=1:delete n[o];var i=e[y](n).join(" ");r[rr]!==i&&(r[rr]=i)};var wr=(a,n)=>{if(a._m)return a._m;var o=a[A](vr);if(sr[o]){var l=sr[o]();n&&e.setPrototypeOf(l,n);var h=Ar(l);h.$refs={},h.$root=a,h.$store=r,h.$parent=n;var g=[],b=e[P](null),C=r=>{var t=r.target;if(r[S]!==H||!t._c)for(var n=a[O],o=r[S];t&&t!==n;){var i=t._h&&t._h[o];if(i){var l=t._s;if(!l||l.$root!==h.$root){t=t[O];continue}for(var s=i[v];s--;){var u=i[s],p=u.p;if(u[I]){var c=t[S]===R?t[$]:t[f];if(typeof c===or){var _=c[V]();_&&isFinite(_)&&(48===_[ar](0)&&1!==_[v]&&46!==_[ar](1)||(c=Number(_)))}if(typeof p===or)l&&(l[p]=c);else{for(var y=l,m=0,g=p[v]-1;m<g&&y;)y=y[p[m++]];y&&(y[p[g]]=c)}}else{var b=mr(l,p);typeof b.val===W&&(e[x](r,"currentTarget",{configurable:!0,value:t}),b.val[d](b.ctx,r))}}}t=t[O]}},L=r=>{b[r]||(b[r]=!0,a[B](r,C,!!yr[r]))},Z=(r,n,o)=>{if(1===r.nodeType&&!r[w]("s-ignore"))if(r!==a&&r[w](vr)){var l=wr(r,n);l&&o[s](l[ir])}else{var g=r[A](fr),b=!g&&"TEMPLATE"===r[E]&&r[A]("s-for"),$=[];if(r[w](G)&&!r._n&&(r._n=r[rr]),g){var nr=i[K](""),or=null,sr=[];r[q](nr);var ur="!"===g[0],pr=ur?g[_](1):g,cr=-1===pr[p](".")?pr:pr[c](".");return o[s](()=>{for(var r=sr[v];r--;)sr[r]()}),o[s](kr(()=>{var e=mr(n,cr).val;if(ur&&(e=!e),e)or||((or=r[D](!0))[N](fr),Z(or,n,sr),nr[O][M](or,nr));else if(or){for(var t=sr[v];t--;)sr[t]();sr=[],or[F](),or=null}},hr))}if(b){var _r=b[p](" in ");if(-1!==_r){var dr,yr=b[_](0,_r)[V](),gr=b[_](_r+4)[V](),xr=yr.replace(/[()]/g,"")[c](","),Pr=xr[0][V](),Er=xr[1]?xr[1][V]():null,Sr=-1===gr[p](".")?gr:gr[c]("."),Tr=r[A]("s-key"),$r=Tr?-1===Tr[p](".")?Tr:Tr[c]("."):null,Or=(nr=i[K](""),e[P](null));return r[q](nr),o[s](()=>{for(var r in Or)Or[r][X][u](r=>r())}),o[s](kr(()=>{var a=mr(n,Sr).val||[];"number"==typeof a&&(a=t.from({length:Math.max(0,Math.floor(a))},(r,e)=>e+1)),t[k](a)&&br(a,v);var o=i.createDocumentFragment(),l=nr;dr=e[P](null);for(var f=t[k](a),s=f?a:e[y](a),p=f?a[v]:s[v],c=0;c<p;c++){var h,g=f?c:s[c],b=f?a[c]:a[g];h=null==b||typeof b!==J?String(b):$r?mr(b,$r).val:String(g)+"_o",dr[h]&&(h+="_"+c);var A=Or[h];if(A)A[U][Pr]=b,Er&&(A[U][Er]=g);else{var N=r.content[D](!0),w=e[P](n);e[x](w,"_i",{value:!0});var E=Ar(w);E[Pr]=b,Er&&(E[Er]=g);for(var S=t[m][_][d](N.childNodes),T=[],$=0;$<S[v];$++)Z(S[$],E,T);A={nodes:t[m][_][d](N.childNodes),scope:E,cleanups:T},Or[h]=A}if(A[Y][0]!==l[j]){for($=0;$<A[Y][v];$++)o.appendChild(A[Y][$]);l[O][M](o,l[j])}l=A[Y][A[Y][v]-1],dr[h]=!0}for(var C in Or)dr[C]||(Or[C][X][u](r=>r()),Or[C][Y][u](r=>r[F]()),delete Or[C])},hr))}}if(r.hasAttributes())for(var jr=r.attributes,Cr=jr[v];Cr--;){var Lr=jr[Cr],qr=Lr[T],Mr=Lr[f];if(58===qr[ar](0)){var Dr=qr[_](1),Fr=33===Mr[ar](0),Kr=Fr?Mr[_](1):Mr;cr=-1===Kr[p](".")?Kr:Kr[c]("."),$[s]({type:lr,name:Dr,path:cr,neg:Fr})}else if(115===qr[ar](0)&&45===qr[ar](1)){let e=qr[_](2),t=-1===Mr[p](".")?Mr:Mr[c](".");if(e===tr||e===er)((e,t)=>{var a=mr(n,t);typeof a.val===W&&(e===tr?hr(()=>{var e=a.val[d](a.ctx,r);typeof e===W&&o[s](e)}):o[s](()=>a.val[d](a.ctx,r)))})(e,t);else if("effect"===e)o[s](kr(()=>{var e=mr(n,t);typeof e.val===W&&e.val[d](e.ctx,r)},hr));else if(e===I){$[s]({type:f,path:t}),r._s=n,r._h=r._h||{};var Br=r[S]===R||r[S]===z||"SELECT"===r[E]?"change":H;Br===H&&(r[B]("compositionstart",()=>r._c=!0),r[B]("compositionend",()=>{r._c=!1,C({target:r,type:H})})),(r._h[Br]=r._h[Br]||[])[s]({model:!0,p:t}),L(Br)}else"ref"===e?h.$refs[Mr]=r:Nr[e]?$[s]({type:e,path:t}):(r._s=n,r._h=r._h||{},(r._h[e]=r._h[e]||[])[Q]({p:t}),L(e))}}$[v]&&o[s](kr(()=>{for(var e=$[v];e--;){var t=$[e],a=mr(n,t.path),o=typeof a.val===W?a.val[d](a.ctx,r):a.val;t[S]===lr?(t.neg&&(o=!o),t[T]===G?Nr[G](r,o):Nr[lr](r,o,t[T])):Nr[t[S]](r,o)}},hr));for(var Hr=r.firstChild;Hr;){var Rr=Hr[j];Z(Hr,n,o),Hr=Rr}}};Z(a,h,g),h[tr]&&h[tr]();var nr={unmount:()=>{h[er]&&h[er][d](h);for(var r=g[v];r--;)g[r]();for(var e in b)a.removeEventListener(e,C);a._m=null}};return a._m=nr,nr}},Er=r=>{if(!r||typeof r!==J)return r;var e=r._t||r;if(t[k](e))return e.map(r=>Er(r));var a={};for(var n in e)a[n]=Er(e[n]);return a};return{data:(r,e)=>{sr[r]=e},start:()=>{for(var r=i.querySelectorAll("[s-data]"),e=r[v];e--;)wr(r[e])},store:(e,t)=>{if(void 0===t)return r[e];r[e]=t;var a=r[e];return a&&typeof a[tr]===W&&a[tr][d](a),a},raw:Er,mount:r=>wr(r),unmount:r=>{r&&r._m&&r._m[ir]()}}})();window.spiki=spiki})();
1
+ (()=>{"use strict";var spiki=(()=>{var r,e=Object,t=Array,a=Reflect,n=Promise,o=Node,i=document,l=console,v="length",f="value",s="push",u="forEach",p="indexOf",c="split",_="slice",d="call",y="keys",h="get",m="prototype",g="hasOwnProperty",b="getPrototypeOf",x="defineProperty",P="create",k="isArray",A="getAttribute",N="setAttribute",w="removeAttribute",E="hasAttribute",S="tagName",T="type",$="name",O="checked",j="parentNode",C="nextSibling",L="textContent",q="innerHTML",M="replaceWith",D="insertBefore",F="cloneNode",K="remove",B="createTextNode",H="addEventListener",R="input",W="checkbox",z="function",G="radio",I="class",J="model",Q="object",U="unshift",V="scope",X="trim",Y="cleanups",Z="nodes",rr="deps",er="destroy",tr="init",ar="charCodeAt",nr="sched",or="string",ir="unmount",lr="attr",vr="s-data",fr="s-if",sr=e[P](null),ur=[],pr=!1,cr=null,_r=!1,dr=n.resolve(),yr={blur:1,focus:1,scroll:1,load:1,error:1,mouseenter:1,mouseleave:1,toggle:1},hr=r=>{r._q||(r._q=!0,ur[s](r),pr||(pr=!0,dr.then(()=>{var r=ur;ur=[],pr=!1;for(var e=r[v];e--;)r[e]._q=!1,r[e]()})))},mr=(r,e)=>{var a,n=r;if(typeof e===or)a=r?r[e]:void 0;else{for(var o=0,i=e[v];o<i-1&&n;)n=n[e[o++]];a=n?n[e[i-1]]:void 0}if(void 0===a){var f=t[k](e)?e.join("."):e;l.warn("[spikijs] Property undefined: "+f)}return{ctx:n,val:a}},gr={};[s,"pop","shift",U,"splice","sort","reverse"][u](r=>{gr[r]=function(...e){_r=!0;try{return t[m][r].apply(this,e)}finally{_r=!1,xr(this,v)}}});var br=(r,t)=>{if(cr){var a=r._d||(e[x](r,"_d",{value:e[P](null),writable:!0}),r._d),n=a[t]||(a[t]=[]);-1===n[p](cr)&&(n[s](cr),cr[rr][s](n))}},xr=(r,e)=>{if(!_r&&r._d&&r._d[e])for(var t=r._d[e][_](),a=0,n=t[v];a<n;a++){var o=t[a];o[nr]?o[nr](o):o()}},Pr=r=>{for(var e=r[rr][v];e--;){var t=r[rr][e],a=t[p](r);-1!==a&&(t[a]=t[t[v]-1],t.pop())}r[rr]=[]},kr=(r,e)=>{var t=()=>{Pr(t);var e=cr;cr=t;try{r()}finally{cr=e}};return t[rr]=[],t[nr]=e,t(),()=>Pr(t)},Ar=r=>{if(!r||typeof r!==Q||r._y||r instanceof o)return r;if(e[m][g][d](r,"_p"))return r._p;var n=new Proxy(r,{get:(r,n,i)=>{if("_y"===n)return i===r._p;if("_t"===n)return r;if("_d"===n)return r._d;if("_i"===n)return r._i;if(t[k](r)&&gr[g](n))return gr[n];var l=e.getOwnPropertyDescriptor(r,n);if(l&&l[h]){var v="_"+n;return v in r||kr(()=>i[v]=l[h][d](i)),i[v]}br(r,n);var f=a[h](r,n,i);return!f||typeof f!==Q||f instanceof o?f:Ar(f)},set:(r,n,o,i)=>{var l=r[n],f=t[k](r),s=f?Number(n)<r[v]:e[m][g][d](r,n);if(r._i&&!s)for(var u=e[b](r);u&&u!==e[m];){if(e[m][g][d](u,n)){var p=a.set(u,n,o);return _r||o===l||xr(r,n),p}u=e[b](u)}return p=a.set(r,n,o,i),!_r&&p&&(s&&o===l||(xr(r,n),f?xr(r,v):s||xr(r,"_k"))),p},deleteProperty:(r,n)=>{var o=e[m][g][d](r,n),i=a.deleteProperty(r,n);return i&&o&&(xr(r,n),t[k](r)?xr(r,v):xr(r,"_k")),i},ownKeys:r=>(br(r,"_k"),a.ownKeys(r))});return e[x](r,"_p",{value:n}),n};r=Ar({});var Nr=e[P](null);Nr.text=(r,e)=>{e=null==e?"":e,r[L]!==String(e)&&(r[L]=e)},Nr.html=(r,e)=>{r[q]!=e&&(r[q]=null==e?"":e)},Nr[f]=(r,e)=>{r[T]===W?r[O]=!!e:r[T]===G?r[O]=r[f]==e:r[f]!=e&&(r[f]=null==e?"":e)},Nr[lr]=(r,e,t)=>{if(null==e||!1===e)r[w](t);else{var a=!0===e?"":String(e);r[A](t)!==a&&r[N](t,a)}},Nr[I]=(r,t)=>{var a=r._n||"",n=e[P](null);if(a[c](/\s+/)[u](r=>r&&(n[r]=1)),typeof t===or)t[c](/\s+/)[u](r=>r&&(n[r]=1));else if(t)for(var o in t)t[o]?n[o]=1:delete n[o];var i=e[y](n).join(" ");(r[A](I)||"")!==i&&r[N](I,i)};var wr=(a,n)=>{if(a._m)return a._m;var o=a[A](vr);if(sr[o]){var l=sr[o]();n&&e.setPrototypeOf(l,n);var h=Ar(l);h.$refs={},h.$root=a,h.$store=r,h.$parent=n;var g=[],b=e[P](null),N=r=>{var t=r.target;if(r[T]!==R||!t._c)for(var n=a[j],o=r[T];t&&t!==n;){var i=t._h&&t._h[o];if(i){var l=t._s;if(!l||l.$root!==h.$root){t=t[j];continue}for(var s=i[v];s--;){var u=i[s],p=u.p;if(u[J]){var c=t[T]===W?t[O]:t[f];if(typeof c===or){var _=c[X]();_&&isFinite(_)&&(48===_[ar](0)&&1!==_[v]&&46!==_[ar](1)||(c=Number(_)))}if(typeof p===or)l&&(l[p]=c);else{for(var y=l,m=0,g=p[v]-1;m<g&&y;)y=y[p[m++]];y&&(y[p[g]]=c)}}else{var b=mr(l,p);typeof b.val===z&&(e[x](r,"currentTarget",{configurable:!0,value:t}),b.val[d](b.ctx,r))}}}t=t[j]}},L=r=>{b[r]||(b[r]=!0,a[H](r,N,!!yr[r]))},q=(r,n,o)=>{if(1===r.nodeType&&!r[E]("s-ignore"))if(r!==a&&r[E](vr)){var l=wr(r,n);l&&o[s](l[ir])}else{var g=r[A](fr),b=!g&&"TEMPLATE"===r[S]&&r[A]("s-for"),O=[];if(r[E](I)&&!r._n&&(r._n=r[A](I)),g){var rr=i[B](""),nr=null,or=[];r[M](rr);var sr="!"===g[0],ur=sr?g[_](1):g,pr=-1===ur[p](".")?ur:ur[c](".");return o[s](()=>{for(var r=or[v];r--;)or[r]()}),o[s](kr(()=>{var e=mr(n,pr).val;if(sr&&(e=!e),e)nr||((nr=r[F](!0))[w](fr),q(nr,n,or),rr[j][D](nr,rr));else if(nr){for(var t=or[v];t--;)or[t]();or=[],nr[K](),nr=null}},hr))}if(b){var cr=b[p](" in ");if(-1!==cr){var _r,dr=b[_](0,cr)[X](),yr=b[_](cr+4)[X](),gr=dr.replace(/[()]/g,"")[c](","),xr=gr[0][X](),Pr=gr[1]?gr[1][X]():null,Er=-1===yr[p](".")?yr:yr[c]("."),Sr=r[A]("s-key"),Tr=Sr?-1===Sr[p](".")?Sr:Sr[c]("."):null,$r=(rr=i[B](""),e[P](null));return r[M](rr),o[s](()=>{for(var r in $r)$r[r][Y][u](r=>r())}),o[s](kr(()=>{var a=mr(n,Er).val||[];"number"==typeof a&&(a=t.from({length:Math.max(0,Math.floor(a))},(r,e)=>e+1)),t[k](a)&&br(a,v);var o=i.createDocumentFragment(),l=rr;_r=e[P](null);for(var f=t[k](a),s=f?a:e[y](a),p=f?a[v]:s[v],c=0;c<p;c++){var h,g=f?c:s[c],b=f?a[c]:a[g];h=null==b||typeof b!==Q?String(b):Tr?mr(b,Tr).val:String(g)+"_o",_r[h]&&(h+="_"+c);var A=$r[h];if(A)A[V][xr]=b,Pr&&(A[V][Pr]=g);else{var N=r.content[F](!0),w=e[P](n);e[x](w,"_i",{value:!0});var E=Ar(w);E[xr]=b,Pr&&(E[Pr]=g);for(var S=t[m][_][d](N.childNodes),T=[],$=0;$<S[v];$++)q(S[$],E,T);A={nodes:t[m][_][d](N.childNodes),scope:E,cleanups:T},$r[h]=A}if(A[Z][0]!==l[C]){for($=0;$<A[Z][v];$++)o.appendChild(A[Z][$]);l[j][D](o,l[C])}l=A[Z][A[Z][v]-1],_r[h]=!0}for(var O in $r)_r[O]||($r[O][Y][u](r=>r()),$r[O][Z][u](r=>r[K]()),delete $r[O])},hr))}}if(r.hasAttributes())for(var Or=r.attributes,jr=Or[v];jr--;){var Cr=Or[jr],Lr=Cr[$],qr=Cr[f];if(58===Lr[ar](0)){var Mr=Lr[_](1),Dr=33===qr[ar](0),Fr=Dr?qr[_](1):qr;pr=-1===Fr[p](".")?Fr:Fr[c]("."),O[s]({type:lr,name:Mr,path:pr,neg:Dr})}else if(115===Lr[ar](0)&&45===Lr[ar](1)){let e=Lr[_](2),t=-1===qr[p](".")?qr:qr[c](".");if(e===tr||e===er)((e,t)=>{var a=mr(n,t);typeof a.val===z&&(e===tr?hr(()=>{var e=a.val[d](a.ctx,r);typeof e===z&&o[s](e)}):o[s](()=>a.val[d](a.ctx,r)))})(e,t);else if("effect"===e)o[s](kr(()=>{var e=mr(n,t);typeof e.val===z&&e.val[d](e.ctx,r)},hr));else if(e===J){O[s]({type:f,path:t}),r._s=n,r._h=r._h||{};var Kr=r[T]===W||r[T]===G||"SELECT"===r[S]?"change":R;Kr===R&&(r[H]("compositionstart",()=>r._c=!0),r[H]("compositionend",()=>{r._c=!1,N({target:r,type:R})})),(r._h[Kr]=r._h[Kr]||[])[s]({model:!0,p:t}),L(Kr)}else"ref"===e?h.$refs[qr]=r:Nr[e]?O[s]({type:e,path:t}):(r._s=n,r._h=r._h||{},(r._h[e]=r._h[e]||[])[U]({p:t}),L(e))}}O[v]&&o[s](kr(()=>{for(var e=O[v];e--;){var t=O[e],a=mr(n,t.path),o=typeof a.val===z?a.val[d](a.ctx,r):a.val;t[T]===lr?(t.neg&&(o=!o),t[$]===I?Nr[I](r,o):Nr[lr](r,o,t[$])):Nr[t[T]](r,o)}},hr));for(var Br=r.firstChild;Br;){var Hr=Br[C];q(Br,n,o),Br=Hr}}};q(a,h,g),h[tr]&&h[tr]();var rr={unmount:()=>{h[er]&&h[er][d](h);for(var r=g[v];r--;)g[r]();for(var e in b)a.removeEventListener(e,N);a._m=null}};return a._m=rr,rr}},Er=r=>{if(!r||typeof r!==Q)return r;var e=r._t||r;if(t[k](e))return e.map(r=>Er(r));var a={};for(var n in e)a[n]=Er(e[n]);return a};return{data:(r,e)=>{sr[r]=e},start:()=>{for(var r=i.querySelectorAll("[s-data]"),e=r[v];e--;)wr(r[e])},store:(e,t)=>{if(void 0===t)return r[e];r[e]=t;var a=r[e];return a&&typeof a[tr]===z&&a[tr][d](a),a},raw:Er,mount:r=>wr(r),unmount:r=>{r&&r._m&&r._m[ir]()}}})();window.spiki=spiki})();