gonia 0.0.1 → 0.0.3
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 +11 -11
- package/dist/client/hydrate.js +6 -6
- package/dist/directives/class.d.ts +2 -2
- package/dist/directives/class.js +3 -3
- package/dist/directives/for.d.ts +7 -7
- package/dist/directives/for.js +28 -28
- package/dist/directives/html.d.ts +2 -2
- package/dist/directives/html.js +7 -4
- package/dist/directives/if.d.ts +5 -5
- package/dist/directives/if.js +17 -17
- package/dist/directives/model.d.ts +4 -4
- package/dist/directives/model.js +5 -5
- package/dist/directives/on.d.ts +3 -3
- package/dist/directives/on.js +6 -6
- package/dist/directives/show.d.ts +2 -2
- package/dist/directives/show.js +8 -5
- package/dist/directives/slot.d.ts +2 -2
- package/dist/directives/slot.js +3 -3
- package/dist/directives/template.d.ts +1 -1
- package/dist/directives/template.js +2 -2
- package/dist/directives/text.d.ts +2 -2
- package/dist/directives/text.js +7 -4
- package/dist/reactivity.d.ts +1 -1
- package/dist/reactivity.js +1 -1
- package/dist/server/render.d.ts +2 -2
- package/dist/server/render.js +10 -10
- package/dist/types.d.ts +4 -4
- package/dist/types.js +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A lightweight, SSR-first reactive UI library for building web applications with
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **SSR-First Architecture** - Server-side rendering with seamless client hydration
|
|
8
|
-
- **Declarative Directives** - Vue-inspired template syntax (`
|
|
8
|
+
- **Declarative Directives** - Vue-inspired template syntax (`g-text`, `g-for`, `g-if`, etc.)
|
|
9
9
|
- **Fine-Grained Reactivity** - Efficient updates without virtual DOM diffing
|
|
10
10
|
- **Zero Dependencies** - Core library has no runtime dependencies (linkedom for SSR only)
|
|
11
11
|
- **TypeScript Native** - Full type safety with excellent IDE support
|
|
@@ -34,7 +34,7 @@ registerDirective(registry, 'class', cclass);
|
|
|
34
34
|
|
|
35
35
|
// Render HTML with state
|
|
36
36
|
const html = await render(
|
|
37
|
-
'<ul><li
|
|
37
|
+
'<ul><li g-for="item in items" g-text="item"></li></ul>',
|
|
38
38
|
{ items: ['Apple', 'Banana', 'Cherry'] },
|
|
39
39
|
registry
|
|
40
40
|
);
|
|
@@ -76,8 +76,8 @@ directive('my-app', myApp, { scope: true });
|
|
|
76
76
|
|
|
77
77
|
```html
|
|
78
78
|
<my-app>
|
|
79
|
-
<p
|
|
80
|
-
<button
|
|
79
|
+
<p g-text="count"></p>
|
|
80
|
+
<button g-on="click: increment">+1</button>
|
|
81
81
|
</my-app>
|
|
82
82
|
```
|
|
83
83
|
|
|
@@ -85,13 +85,13 @@ directive('my-app', myApp, { scope: true });
|
|
|
85
85
|
|
|
86
86
|
| Directive | Description | Example |
|
|
87
87
|
|-----------|-------------|---------|
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
88
|
+
| `g-text` | Set text content | `<span g-text="message"></span>` |
|
|
89
|
+
| `g-show` | Toggle visibility | `<div g-show="isVisible">...</div>` |
|
|
90
|
+
| `g-if` | Conditional render | `<p g-if="hasError">Error!</p>` |
|
|
91
|
+
| `g-for` | Loop iteration | `<li g-for="item in items">...</li>` |
|
|
92
|
+
| `g-class` | Dynamic classes | `<div g-class="{ active: isActive }">` |
|
|
93
|
+
| `g-model` | Two-way binding | `<input g-model="name">` |
|
|
94
|
+
| `g-on` | Event handling | `<button g-on="click: handleClick">` |
|
|
95
95
|
|
|
96
96
|
## Vite Integration
|
|
97
97
|
|
package/dist/client/hydrate.js
CHANGED
|
@@ -55,7 +55,7 @@ function getSelector(registry) {
|
|
|
55
55
|
if (!cachedSelector) {
|
|
56
56
|
const directiveSelectors = [];
|
|
57
57
|
for (const name of registry.keys()) {
|
|
58
|
-
directiveSelectors.push(`[
|
|
58
|
+
directiveSelectors.push(`[g-${name}]`);
|
|
59
59
|
}
|
|
60
60
|
// Also match native <slot> elements
|
|
61
61
|
directiveSelectors.push('slot');
|
|
@@ -71,7 +71,7 @@ function getSelector(registry) {
|
|
|
71
71
|
function getDirectivesForElement(el, registry) {
|
|
72
72
|
const directives = [];
|
|
73
73
|
for (const [name, directive] of registry) {
|
|
74
|
-
const attr = el.getAttribute(`
|
|
74
|
+
const attr = el.getAttribute(`g-${name}`);
|
|
75
75
|
if (attr !== null) {
|
|
76
76
|
directives.push({ name, directive, expr: attr });
|
|
77
77
|
}
|
|
@@ -175,7 +175,7 @@ function resolveDependencies(directive, expr, el, ctx) {
|
|
|
175
175
|
* @internal
|
|
176
176
|
*/
|
|
177
177
|
function processElement(el, registry) {
|
|
178
|
-
// Skip elements already processed by
|
|
178
|
+
// Skip elements already processed by g-for (they have their own child scope)
|
|
179
179
|
if (el.hasAttribute(FOR_PROCESSED_ATTR)) {
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
@@ -201,7 +201,7 @@ function processElement(el, registry) {
|
|
|
201
201
|
}
|
|
202
202
|
return result;
|
|
203
203
|
};
|
|
204
|
-
// STRUCTURAL directives (like
|
|
204
|
+
// STRUCTURAL directives (like g-for) take ownership of the element.
|
|
205
205
|
// They remove the original and handle other directives on clones themselves.
|
|
206
206
|
const isStructural = directive.priority === DirectivePriority.STRUCTURAL;
|
|
207
207
|
if (chain instanceof Promise) {
|
|
@@ -259,7 +259,7 @@ export function registerDirective(registry, name, fn) {
|
|
|
259
259
|
registry.set(name, fn);
|
|
260
260
|
cachedSelector = null;
|
|
261
261
|
if (document.body && initialized) {
|
|
262
|
-
const selector = `[
|
|
262
|
+
const selector = `[g-${name}]`;
|
|
263
263
|
for (const el of document.querySelectorAll(selector)) {
|
|
264
264
|
processElement(el, registry);
|
|
265
265
|
}
|
|
@@ -400,7 +400,7 @@ export async function init(registry) {
|
|
|
400
400
|
const selector = getSelector(reg);
|
|
401
401
|
// Process existing elements synchronously, collecting promises from async directives.
|
|
402
402
|
// Note: We collect elements first, but some may be removed during processing
|
|
403
|
-
// (e.g.,
|
|
403
|
+
// (e.g., g-for removes its template). Check isConnected before processing.
|
|
404
404
|
const elements = document.querySelectorAll(selector);
|
|
405
405
|
const promises = [];
|
|
406
406
|
for (const el of elements) {
|
|
@@ -14,8 +14,8 @@ import { Directive } from '../types.js';
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```html
|
|
17
|
-
* <div
|
|
18
|
-
* <div
|
|
17
|
+
* <div g-class="{ active: isActive, 'text-red': hasError }">
|
|
18
|
+
* <div g-class="{ [dynamicClass]: true }">
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
export declare const cclass: Directive<['$expr', '$element', '$eval']>;
|
package/dist/directives/class.js
CHANGED
|
@@ -15,8 +15,8 @@ import { effect } from '../reactivity.js';
|
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* ```html
|
|
18
|
-
* <div
|
|
19
|
-
* <div
|
|
18
|
+
* <div g-class="{ active: isActive, 'text-red': hasError }">
|
|
19
|
+
* <div g-class="{ [dynamicClass]: true }">
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
22
|
export const cclass = function cclass($expr, $element, $eval) {
|
|
@@ -39,4 +39,4 @@ export const cclass = function cclass($expr, $element, $eval) {
|
|
|
39
39
|
});
|
|
40
40
|
};
|
|
41
41
|
cclass.$inject = ['$expr', '$element', '$eval'];
|
|
42
|
-
directive('
|
|
42
|
+
directive('g-class', cclass);
|
package/dist/directives/for.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
import { Directive } from '../types.js';
|
|
7
|
-
/** Attribute used to mark elements processed by
|
|
8
|
-
export declare const FOR_PROCESSED_ATTR = "data-
|
|
7
|
+
/** Attribute used to mark elements processed by g-for */
|
|
8
|
+
export declare const FOR_PROCESSED_ATTR = "data-g-for-processed";
|
|
9
9
|
/** Attribute used to mark template content that should be skipped during SSR */
|
|
10
|
-
export declare const FOR_TEMPLATE_ATTR = "data-
|
|
10
|
+
export declare const FOR_TEMPLATE_ATTR = "data-g-for-template";
|
|
11
11
|
/**
|
|
12
12
|
* Iterate over array or object items.
|
|
13
13
|
*
|
|
@@ -17,13 +17,13 @@ export declare const FOR_TEMPLATE_ATTR = "data-c-for-template";
|
|
|
17
17
|
* For objects, provides value and key.
|
|
18
18
|
*
|
|
19
19
|
* On server: wraps template in <template> element, renders items after it.
|
|
20
|
-
* On client: finds <template
|
|
20
|
+
* On client: finds <template g-for>, extracts template, sets up reactive loop.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```html
|
|
24
|
-
* <li
|
|
25
|
-
* <li
|
|
26
|
-
* <div
|
|
24
|
+
* <li g-for="item in items" g-text="item.name"></li>
|
|
25
|
+
* <li g-for="(item, index) in items" g-text="index + ': ' + item.name"></li>
|
|
26
|
+
* <div g-for="(value, key) in object" g-text="key + ': ' + value"></div>
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
export declare const cfor: Directive<['$expr', '$element', '$eval', '$state', '$mode']>;
|
package/dist/directives/for.js
CHANGED
|
@@ -7,7 +7,7 @@ import { directive, DirectivePriority, Mode } from '../types.js';
|
|
|
7
7
|
import { effect, createEffectScope, createScope } from '../reactivity.js';
|
|
8
8
|
import { createContext } from '../context.js';
|
|
9
9
|
/**
|
|
10
|
-
* Parse a
|
|
10
|
+
* Parse a g-for expression.
|
|
11
11
|
*
|
|
12
12
|
* Supports:
|
|
13
13
|
* - `item in items`
|
|
@@ -27,26 +27,26 @@ function parseForExpression(expr) {
|
|
|
27
27
|
iterableName: match[3].trim()
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
-
/** Attribute used to mark elements processed by
|
|
31
|
-
export const FOR_PROCESSED_ATTR = 'data-
|
|
30
|
+
/** Attribute used to mark elements processed by g-for */
|
|
31
|
+
export const FOR_PROCESSED_ATTR = 'data-g-for-processed';
|
|
32
32
|
/** Attribute used to mark template content that should be skipped during SSR */
|
|
33
|
-
export const FOR_TEMPLATE_ATTR = 'data-
|
|
33
|
+
export const FOR_TEMPLATE_ATTR = 'data-g-for-template';
|
|
34
34
|
/**
|
|
35
35
|
* Process directives on a cloned element within a child scope.
|
|
36
36
|
*/
|
|
37
37
|
function processClonedElement(el, parentState, scopeAdditions, mode) {
|
|
38
|
-
// Mark this element as processed by
|
|
38
|
+
// Mark this element as processed by g-for so hydrate skips it
|
|
39
39
|
el.setAttribute(FOR_PROCESSED_ATTR, '');
|
|
40
40
|
const childScope = createScope(parentState, scopeAdditions);
|
|
41
41
|
const childCtx = createContext(mode, childScope);
|
|
42
|
-
// Process
|
|
43
|
-
const textAttr = el.getAttribute('
|
|
42
|
+
// Process g-text directives
|
|
43
|
+
const textAttr = el.getAttribute('g-text');
|
|
44
44
|
if (textAttr) {
|
|
45
45
|
const value = childCtx.eval(textAttr);
|
|
46
46
|
el.textContent = String(value ?? '');
|
|
47
47
|
}
|
|
48
|
-
// Process
|
|
49
|
-
const classAttr = el.getAttribute('
|
|
48
|
+
// Process g-class directives
|
|
49
|
+
const classAttr = el.getAttribute('g-class');
|
|
50
50
|
if (classAttr) {
|
|
51
51
|
const classObj = childCtx.eval(classAttr);
|
|
52
52
|
if (classObj && typeof classObj === 'object') {
|
|
@@ -60,15 +60,15 @@ function processClonedElement(el, parentState, scopeAdditions, mode) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
// Process
|
|
64
|
-
const showAttr = el.getAttribute('
|
|
63
|
+
// Process g-show directives
|
|
64
|
+
const showAttr = el.getAttribute('g-show');
|
|
65
65
|
if (showAttr) {
|
|
66
66
|
const value = childCtx.eval(showAttr);
|
|
67
67
|
el.style.display = value ? '' : 'none';
|
|
68
68
|
}
|
|
69
|
-
// Process
|
|
69
|
+
// Process g-on directives (format: "event: handler") - client only
|
|
70
70
|
if (mode === Mode.CLIENT) {
|
|
71
|
-
const onAttr = el.getAttribute('
|
|
71
|
+
const onAttr = el.getAttribute('g-on');
|
|
72
72
|
if (onAttr) {
|
|
73
73
|
setupEventHandler(el, onAttr, childCtx, childScope);
|
|
74
74
|
}
|
|
@@ -85,7 +85,7 @@ function processClonedElement(el, parentState, scopeAdditions, mode) {
|
|
|
85
85
|
function setupEventHandler(el, expr, ctx, state) {
|
|
86
86
|
const colonIdx = expr.indexOf(':');
|
|
87
87
|
if (colonIdx === -1) {
|
|
88
|
-
console.error(`Invalid
|
|
88
|
+
console.error(`Invalid g-on expression: ${expr}. Expected "event: handler"`);
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
const eventName = expr.slice(0, colonIdx).trim();
|
|
@@ -168,19 +168,19 @@ function removeSSRItems(templateEl) {
|
|
|
168
168
|
* For objects, provides value and key.
|
|
169
169
|
*
|
|
170
170
|
* On server: wraps template in <template> element, renders items after it.
|
|
171
|
-
* On client: finds <template
|
|
171
|
+
* On client: finds <template g-for>, extracts template, sets up reactive loop.
|
|
172
172
|
*
|
|
173
173
|
* @example
|
|
174
174
|
* ```html
|
|
175
|
-
* <li
|
|
176
|
-
* <li
|
|
177
|
-
* <div
|
|
175
|
+
* <li g-for="item in items" g-text="item.name"></li>
|
|
176
|
+
* <li g-for="(item, index) in items" g-text="index + ': ' + item.name"></li>
|
|
177
|
+
* <div g-for="(value, key) in object" g-text="key + ': ' + value"></div>
|
|
178
178
|
* ```
|
|
179
179
|
*/
|
|
180
180
|
export const cfor = function cfor($expr, $element, $eval, $state, $mode) {
|
|
181
181
|
const parsed = parseForExpression($expr);
|
|
182
182
|
if (!parsed) {
|
|
183
|
-
console.error(`Invalid
|
|
183
|
+
console.error(`Invalid g-for expression: ${$expr}`);
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
186
|
const parent = $element.parentNode;
|
|
@@ -192,10 +192,10 @@ export const cfor = function cfor($expr, $element, $eval, $state, $mode) {
|
|
|
192
192
|
if ($mode === Mode.SERVER) {
|
|
193
193
|
// Create a <template> element to hold the original
|
|
194
194
|
const templateWrapper = $element.ownerDocument.createElement('template');
|
|
195
|
-
templateWrapper.setAttribute('
|
|
196
|
-
// Clone the original element (without
|
|
195
|
+
templateWrapper.setAttribute('g-for', $expr);
|
|
196
|
+
// Clone the original element (without g-for attr) into the template
|
|
197
197
|
const templateContent = $element.cloneNode(true);
|
|
198
|
-
templateContent.removeAttribute('
|
|
198
|
+
templateContent.removeAttribute('g-for');
|
|
199
199
|
// Mark as template content so render loop skips it
|
|
200
200
|
templateContent.setAttribute(FOR_TEMPLATE_ATTR, '');
|
|
201
201
|
// Append directly to template element (linkedom doesn't support .content)
|
|
@@ -209,11 +209,11 @@ export const cfor = function cfor($expr, $element, $eval, $state, $mode) {
|
|
|
209
209
|
}
|
|
210
210
|
// Client-side: check if hydrating from SSR or fresh render
|
|
211
211
|
if (isTemplateElement) {
|
|
212
|
-
// Hydrating from SSR: element is <template
|
|
212
|
+
// Hydrating from SSR: element is <template g-for="...">
|
|
213
213
|
const templateWrapper = $element;
|
|
214
214
|
const templateContent = templateWrapper.content.firstElementChild;
|
|
215
215
|
if (!templateContent) {
|
|
216
|
-
console.error('
|
|
216
|
+
console.error('g-for template element has no content');
|
|
217
217
|
return;
|
|
218
218
|
}
|
|
219
219
|
// Remove SSR-rendered items
|
|
@@ -235,12 +235,12 @@ export const cfor = function cfor($expr, $element, $eval, $state, $mode) {
|
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
237
|
else {
|
|
238
|
-
// Fresh client render: element has
|
|
238
|
+
// Fresh client render: element has g-for attribute directly
|
|
239
239
|
// Wrap in template element for consistency
|
|
240
240
|
const templateWrapper = $element.ownerDocument.createElement('template');
|
|
241
|
-
templateWrapper.setAttribute('
|
|
241
|
+
templateWrapper.setAttribute('g-for', $expr);
|
|
242
242
|
const templateContent = $element.cloneNode(true);
|
|
243
|
-
templateContent.removeAttribute('
|
|
243
|
+
templateContent.removeAttribute('g-for');
|
|
244
244
|
templateWrapper.content.appendChild(templateContent);
|
|
245
245
|
parent.replaceChild(templateWrapper, $element);
|
|
246
246
|
// Set up reactive loop
|
|
@@ -262,4 +262,4 @@ export const cfor = function cfor($expr, $element, $eval, $state, $mode) {
|
|
|
262
262
|
};
|
|
263
263
|
cfor.$inject = ['$expr', '$element', '$eval', '$state', '$mode'];
|
|
264
264
|
cfor.priority = DirectivePriority.STRUCTURAL;
|
|
265
|
-
directive('
|
|
265
|
+
directive('g-for', cfor);
|
|
@@ -9,8 +9,8 @@ import { Directive } from '../types.js';
|
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```html
|
|
12
|
-
* <div
|
|
13
|
-
* <div
|
|
12
|
+
* <div g-html="formattedContent"></div>
|
|
13
|
+
* <div g-html="'<strong>' + title + '</strong>'"></div>
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
16
|
export declare const html: Directive<['$expr', '$element', '$eval']>;
|
package/dist/directives/html.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { directive } from '../types.js';
|
|
2
|
+
import { effect } from '../reactivity.js';
|
|
2
3
|
/**
|
|
3
4
|
* Set element's innerHTML from an expression.
|
|
4
5
|
*
|
|
@@ -9,11 +10,13 @@ import { directive } from '../types.js';
|
|
|
9
10
|
*
|
|
10
11
|
* @example
|
|
11
12
|
* ```html
|
|
12
|
-
* <div
|
|
13
|
-
* <div
|
|
13
|
+
* <div g-html="formattedContent"></div>
|
|
14
|
+
* <div g-html="'<strong>' + title + '</strong>'"></div>
|
|
14
15
|
* ```
|
|
15
16
|
*/
|
|
16
17
|
export const html = function html($expr, $element, $eval) {
|
|
17
|
-
|
|
18
|
+
effect(() => {
|
|
19
|
+
$element.innerHTML = String($eval($expr) ?? '');
|
|
20
|
+
});
|
|
18
21
|
};
|
|
19
|
-
directive('
|
|
22
|
+
directive('g-html', html);
|
package/dist/directives/if.d.ts
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
import { Directive } from '../types.js';
|
|
7
|
-
/** Attribute used to mark elements processed by
|
|
8
|
-
export declare const IF_PROCESSED_ATTR = "data-
|
|
7
|
+
/** Attribute used to mark elements processed by g-if */
|
|
8
|
+
export declare const IF_PROCESSED_ATTR = "data-g-if-processed";
|
|
9
9
|
/**
|
|
10
10
|
* Conditionally render an element.
|
|
11
11
|
*
|
|
12
12
|
* @remarks
|
|
13
|
-
* Unlike
|
|
13
|
+
* Unlike g-show which uses display:none, g-if completely removes
|
|
14
14
|
* the element from the DOM when the condition is falsy.
|
|
15
15
|
*
|
|
16
16
|
* On server: evaluates once and removes element if false.
|
|
@@ -18,8 +18,8 @@ export declare const IF_PROCESSED_ATTR = "data-c-if-processed";
|
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```html
|
|
21
|
-
* <div
|
|
22
|
-
* <div
|
|
21
|
+
* <div g-if="isLoggedIn">Welcome back!</div>
|
|
22
|
+
* <div g-if="items.length > 0">Has items</div>
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
export declare const cif: Directive<['$expr', '$element', '$eval', '$state', '$mode']>;
|
package/dist/directives/if.js
CHANGED
|
@@ -7,8 +7,8 @@ import { directive, DirectivePriority, Mode } from '../types.js';
|
|
|
7
7
|
import { effect } from '../reactivity.js';
|
|
8
8
|
import { createContext } from '../context.js';
|
|
9
9
|
import { createScope } from '../reactivity.js';
|
|
10
|
-
/** Attribute used to mark elements processed by
|
|
11
|
-
export const IF_PROCESSED_ATTR = 'data-
|
|
10
|
+
/** Attribute used to mark elements processed by g-if */
|
|
11
|
+
export const IF_PROCESSED_ATTR = 'data-g-if-processed';
|
|
12
12
|
/**
|
|
13
13
|
* Process directives on a conditionally rendered element.
|
|
14
14
|
*/
|
|
@@ -16,14 +16,14 @@ function processConditionalElement(el, parentState, mode) {
|
|
|
16
16
|
el.setAttribute(IF_PROCESSED_ATTR, '');
|
|
17
17
|
const childScope = createScope(parentState, {});
|
|
18
18
|
const childCtx = createContext(mode, childScope);
|
|
19
|
-
// Process
|
|
20
|
-
const textAttr = el.getAttribute('
|
|
19
|
+
// Process g-text directives
|
|
20
|
+
const textAttr = el.getAttribute('g-text');
|
|
21
21
|
if (textAttr) {
|
|
22
22
|
const value = childCtx.eval(textAttr);
|
|
23
23
|
el.textContent = String(value ?? '');
|
|
24
24
|
}
|
|
25
|
-
// Process
|
|
26
|
-
const classAttr = el.getAttribute('
|
|
25
|
+
// Process g-class directives
|
|
26
|
+
const classAttr = el.getAttribute('g-class');
|
|
27
27
|
if (classAttr) {
|
|
28
28
|
const classObj = childCtx.eval(classAttr);
|
|
29
29
|
if (classObj && typeof classObj === 'object') {
|
|
@@ -37,15 +37,15 @@ function processConditionalElement(el, parentState, mode) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
// Process
|
|
41
|
-
const showAttr = el.getAttribute('
|
|
40
|
+
// Process g-show directives
|
|
41
|
+
const showAttr = el.getAttribute('g-show');
|
|
42
42
|
if (showAttr) {
|
|
43
43
|
const value = childCtx.eval(showAttr);
|
|
44
44
|
el.style.display = value ? '' : 'none';
|
|
45
45
|
}
|
|
46
|
-
// Process
|
|
46
|
+
// Process g-on directives (format: "event: handler") - client only
|
|
47
47
|
if (mode === Mode.CLIENT) {
|
|
48
|
-
const onAttr = el.getAttribute('
|
|
48
|
+
const onAttr = el.getAttribute('g-on');
|
|
49
49
|
if (onAttr) {
|
|
50
50
|
const colonIdx = onAttr.indexOf(':');
|
|
51
51
|
if (colonIdx !== -1) {
|
|
@@ -69,7 +69,7 @@ function processConditionalElement(el, parentState, mode) {
|
|
|
69
69
|
* Conditionally render an element.
|
|
70
70
|
*
|
|
71
71
|
* @remarks
|
|
72
|
-
* Unlike
|
|
72
|
+
* Unlike g-show which uses display:none, g-if completely removes
|
|
73
73
|
* the element from the DOM when the condition is falsy.
|
|
74
74
|
*
|
|
75
75
|
* On server: evaluates once and removes element if false.
|
|
@@ -77,8 +77,8 @@ function processConditionalElement(el, parentState, mode) {
|
|
|
77
77
|
*
|
|
78
78
|
* @example
|
|
79
79
|
* ```html
|
|
80
|
-
* <div
|
|
81
|
-
* <div
|
|
80
|
+
* <div g-if="isLoggedIn">Welcome back!</div>
|
|
81
|
+
* <div g-if="items.length > 0">Has items</div>
|
|
82
82
|
* ```
|
|
83
83
|
*/
|
|
84
84
|
export const cif = function cif($expr, $element, $eval, $state, $mode) {
|
|
@@ -94,16 +94,16 @@ export const cif = function cif($expr, $element, $eval, $state, $mode) {
|
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
96
96
|
// Process child directives
|
|
97
|
-
$element.removeAttribute('
|
|
97
|
+
$element.removeAttribute('g-if');
|
|
98
98
|
processConditionalElement($element, $state, $mode);
|
|
99
99
|
}
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
102
|
// Client-side: set up reactive effect
|
|
103
|
-
const placeholder = $element.ownerDocument.createComment(`
|
|
103
|
+
const placeholder = $element.ownerDocument.createComment(` g-if: ${$expr} `);
|
|
104
104
|
parent.insertBefore(placeholder, $element);
|
|
105
105
|
const template = $element.cloneNode(true);
|
|
106
|
-
template.removeAttribute('
|
|
106
|
+
template.removeAttribute('g-if');
|
|
107
107
|
$element.remove();
|
|
108
108
|
let renderedElement = null;
|
|
109
109
|
effect(() => {
|
|
@@ -130,4 +130,4 @@ export const cif = function cif($expr, $element, $eval, $state, $mode) {
|
|
|
130
130
|
};
|
|
131
131
|
cif.$inject = ['$expr', '$element', '$eval', '$state', '$mode'];
|
|
132
132
|
cif.priority = DirectivePriority.STRUCTURAL;
|
|
133
|
-
directive('
|
|
133
|
+
directive('g-if', cif);
|
|
@@ -18,10 +18,10 @@ import { Directive } from '../types.js';
|
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```html
|
|
21
|
-
* <input
|
|
22
|
-
* <input type="checkbox"
|
|
23
|
-
* <select
|
|
24
|
-
* <textarea
|
|
21
|
+
* <input g-model="name">
|
|
22
|
+
* <input type="checkbox" g-model="isActive">
|
|
23
|
+
* <select g-model="selectedOption">
|
|
24
|
+
* <textarea g-model="description"></textarea>
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
export declare const model: Directive<['$expr', '$element', '$eval', '$rootState']>;
|
package/dist/directives/model.js
CHANGED
|
@@ -68,10 +68,10 @@ function getInputType(el) {
|
|
|
68
68
|
*
|
|
69
69
|
* @example
|
|
70
70
|
* ```html
|
|
71
|
-
* <input
|
|
72
|
-
* <input type="checkbox"
|
|
73
|
-
* <select
|
|
74
|
-
* <textarea
|
|
71
|
+
* <input g-model="name">
|
|
72
|
+
* <input type="checkbox" g-model="isActive">
|
|
73
|
+
* <select g-model="selectedOption">
|
|
74
|
+
* <textarea g-model="description"></textarea>
|
|
75
75
|
* ```
|
|
76
76
|
*/
|
|
77
77
|
export const model = function model($expr, $element, $eval, $rootState) {
|
|
@@ -131,4 +131,4 @@ export const model = function model($expr, $element, $eval, $rootState) {
|
|
|
131
131
|
}
|
|
132
132
|
};
|
|
133
133
|
model.$inject = ['$expr', '$element', '$eval', '$rootState'];
|
|
134
|
-
directive('
|
|
134
|
+
directive('g-model', model);
|
package/dist/directives/on.d.ts
CHANGED
|
@@ -13,9 +13,9 @@ import { Directive } from '../types.js';
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```html
|
|
16
|
-
* <button
|
|
17
|
-
* <form
|
|
18
|
-
* <input
|
|
16
|
+
* <button g-on="click: handleClick">Click me</button>
|
|
17
|
+
* <form g-on="submit: save">
|
|
18
|
+
* <input g-on="keydown: onKey">
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
export declare const on: Directive<['$expr', '$element', '$eval', '$rootState']>;
|
package/dist/directives/on.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { directive } from '../types.js';
|
|
7
7
|
/**
|
|
8
|
-
* Parse
|
|
8
|
+
* Parse g-on expression: "event: handler" or "event: handler()"
|
|
9
9
|
*/
|
|
10
10
|
function parseOnExpression(expr) {
|
|
11
11
|
const colonIdx = expr.indexOf(':');
|
|
@@ -28,15 +28,15 @@ function parseOnExpression(expr) {
|
|
|
28
28
|
*
|
|
29
29
|
* @example
|
|
30
30
|
* ```html
|
|
31
|
-
* <button
|
|
32
|
-
* <form
|
|
33
|
-
* <input
|
|
31
|
+
* <button g-on="click: handleClick">Click me</button>
|
|
32
|
+
* <form g-on="submit: save">
|
|
33
|
+
* <input g-on="keydown: onKey">
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
36
|
export const on = function on($expr, $element, $eval, $rootState) {
|
|
37
37
|
const parsed = parseOnExpression($expr);
|
|
38
38
|
if (!parsed) {
|
|
39
|
-
console.error(`Invalid
|
|
39
|
+
console.error(`Invalid g-on expression: ${$expr}. Expected "event: handler"`);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
const { event: eventName, handler: handlerExpr } = parsed;
|
|
@@ -51,4 +51,4 @@ export const on = function on($expr, $element, $eval, $rootState) {
|
|
|
51
51
|
$element.addEventListener(eventName, handler);
|
|
52
52
|
};
|
|
53
53
|
on.$inject = ['$expr', '$element', '$eval', '$rootState'];
|
|
54
|
-
directive('
|
|
54
|
+
directive('g-on', on);
|
|
@@ -8,8 +8,8 @@ import { Directive } from '../types.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```html
|
|
11
|
-
* <div
|
|
12
|
-
* <div
|
|
11
|
+
* <div g-show="isVisible">Visible content</div>
|
|
12
|
+
* <div g-show="items.length > 0">Has items</div>
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
export declare const show: Directive<['$expr', '$element', '$eval']>;
|
package/dist/directives/show.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { directive } from '../types.js';
|
|
2
|
+
import { effect } from '../reactivity.js';
|
|
2
3
|
/**
|
|
3
4
|
* Toggle element visibility based on an expression.
|
|
4
5
|
*
|
|
@@ -8,12 +9,14 @@ import { directive } from '../types.js';
|
|
|
8
9
|
*
|
|
9
10
|
* @example
|
|
10
11
|
* ```html
|
|
11
|
-
* <div
|
|
12
|
-
* <div
|
|
12
|
+
* <div g-show="isVisible">Visible content</div>
|
|
13
|
+
* <div g-show="items.length > 0">Has items</div>
|
|
13
14
|
* ```
|
|
14
15
|
*/
|
|
15
16
|
export const show = function show($expr, $element, $eval) {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
effect(() => {
|
|
18
|
+
const value = $eval($expr);
|
|
19
|
+
$element.style.display = value ? '' : 'none';
|
|
20
|
+
});
|
|
18
21
|
};
|
|
19
|
-
directive('
|
|
22
|
+
directive('g-show', show);
|
|
@@ -27,7 +27,7 @@ import { Directive } from '../types.js';
|
|
|
27
27
|
*
|
|
28
28
|
* Dynamic slot name:
|
|
29
29
|
* ```html
|
|
30
|
-
* <slot
|
|
30
|
+
* <slot g-slot="activeTab"></slot>
|
|
31
31
|
* ```
|
|
32
32
|
*
|
|
33
33
|
* Default slot (no name):
|
|
@@ -41,7 +41,7 @@ export declare const slot: Directive<['$expr', '$element', '$eval']>;
|
|
|
41
41
|
*
|
|
42
42
|
* @remarks
|
|
43
43
|
* This handles native `<slot>` elements in templates,
|
|
44
|
-
* treating them the same as `
|
|
44
|
+
* treating them the same as `g-slot` directives.
|
|
45
45
|
*
|
|
46
46
|
* @internal
|
|
47
47
|
*/
|
package/dist/directives/slot.js
CHANGED
|
@@ -29,7 +29,7 @@ import { findTemplateAncestor, getSavedContent } from './template.js';
|
|
|
29
29
|
*
|
|
30
30
|
* Dynamic slot name:
|
|
31
31
|
* ```html
|
|
32
|
-
* <slot
|
|
32
|
+
* <slot g-slot="activeTab"></slot>
|
|
33
33
|
* ```
|
|
34
34
|
*
|
|
35
35
|
* Default slot (no name):
|
|
@@ -75,13 +75,13 @@ export const slot = function slot($expr, $element, $eval) {
|
|
|
75
75
|
transclude();
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
|
-
directive('
|
|
78
|
+
directive('g-slot', slot);
|
|
79
79
|
/**
|
|
80
80
|
* Process native <slot> elements.
|
|
81
81
|
*
|
|
82
82
|
* @remarks
|
|
83
83
|
* This handles native `<slot>` elements in templates,
|
|
84
|
-
* treating them the same as `
|
|
84
|
+
* treating them the same as `g-slot` directives.
|
|
85
85
|
*
|
|
86
86
|
* @internal
|
|
87
87
|
*/
|
|
@@ -85,7 +85,7 @@ function extractSlotContent(el) {
|
|
|
85
85
|
*
|
|
86
86
|
* @example
|
|
87
87
|
* ```html
|
|
88
|
-
* <div
|
|
88
|
+
* <div g-template="dialog">
|
|
89
89
|
* <span slot="header">Title</span>
|
|
90
90
|
* <p>Body content</p>
|
|
91
91
|
* </div>
|
|
@@ -136,7 +136,7 @@ export const template = async function template($expr, $element, $templates) {
|
|
|
136
136
|
template.$inject = ['$expr', '$element', '$templates'];
|
|
137
137
|
template.transclude = true;
|
|
138
138
|
template.priority = DirectivePriority.TEMPLATE;
|
|
139
|
-
directive('
|
|
139
|
+
directive('g-template', template);
|
|
140
140
|
/**
|
|
141
141
|
* Get the effect scope for an element.
|
|
142
142
|
*
|
|
@@ -8,8 +8,8 @@ import { Directive } from '../types.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```html
|
|
11
|
-
* <span
|
|
12
|
-
* <span
|
|
11
|
+
* <span g-text="user.name"></span>
|
|
12
|
+
* <span g-text="'Hello, ' + user.name + '!'"></span>
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
export declare const text: Directive<['$expr', '$element', '$eval']>;
|
package/dist/directives/text.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { directive } from '../types.js';
|
|
2
|
+
import { effect } from '../reactivity.js';
|
|
2
3
|
/**
|
|
3
4
|
* Set element's text content from an expression.
|
|
4
5
|
*
|
|
@@ -8,11 +9,13 @@ import { directive } from '../types.js';
|
|
|
8
9
|
*
|
|
9
10
|
* @example
|
|
10
11
|
* ```html
|
|
11
|
-
* <span
|
|
12
|
-
* <span
|
|
12
|
+
* <span g-text="user.name"></span>
|
|
13
|
+
* <span g-text="'Hello, ' + user.name + '!'"></span>
|
|
13
14
|
* ```
|
|
14
15
|
*/
|
|
15
16
|
export const text = function text($expr, $element, $eval) {
|
|
16
|
-
|
|
17
|
+
effect(() => {
|
|
18
|
+
$element.textContent = String($eval($expr) ?? '');
|
|
19
|
+
});
|
|
17
20
|
};
|
|
18
|
-
directive('
|
|
21
|
+
directive('g-text', text);
|
package/dist/reactivity.d.ts
CHANGED
|
@@ -75,7 +75,7 @@ export declare function effect(fn: Effect): () => void;
|
|
|
75
75
|
* Create a child reactive scope.
|
|
76
76
|
*
|
|
77
77
|
* @remarks
|
|
78
|
-
* Used by structural directives like
|
|
78
|
+
* Used by structural directives like g-for to create per-item contexts.
|
|
79
79
|
* The child scope inherits from the parent, with additions taking precedence.
|
|
80
80
|
*
|
|
81
81
|
* @typeParam T - Parent object type
|
package/dist/reactivity.js
CHANGED
|
@@ -184,7 +184,7 @@ function cleanup(effectFn) {
|
|
|
184
184
|
* Create a child reactive scope.
|
|
185
185
|
*
|
|
186
186
|
* @remarks
|
|
187
|
-
* Used by structural directives like
|
|
187
|
+
* Used by structural directives like g-for to create per-item contexts.
|
|
188
188
|
* The child scope inherits from the parent, with additions taking precedence.
|
|
189
189
|
*
|
|
190
190
|
* @typeParam T - Parent object type
|
package/dist/server/render.d.ts
CHANGED
|
@@ -51,11 +51,11 @@ export declare function registerService(name: string, service: unknown): void;
|
|
|
51
51
|
* registry.set('text', textDirective);
|
|
52
52
|
*
|
|
53
53
|
* const html = await render(
|
|
54
|
-
* '<span
|
|
54
|
+
* '<span g-text="user.name"></span>',
|
|
55
55
|
* { user: { name: 'Alice' } },
|
|
56
56
|
* registry
|
|
57
57
|
* );
|
|
58
|
-
* // '<span
|
|
58
|
+
* // '<span g-text="user.name">Alice</span>'
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
61
|
export declare function render(html: string, state: Record<string, unknown>, registry: DirectiveRegistry): Promise<string>;
|
package/dist/server/render.js
CHANGED
|
@@ -21,7 +21,7 @@ const selectorCache = new WeakMap();
|
|
|
21
21
|
function getSelector(registry) {
|
|
22
22
|
let selector = selectorCache.get(registry);
|
|
23
23
|
if (!selector) {
|
|
24
|
-
const directiveSelectors = [...registry.keys()].map(n => `[
|
|
24
|
+
const directiveSelectors = [...registry.keys()].map(n => `[g-${n}]`);
|
|
25
25
|
// Also match native <slot> elements
|
|
26
26
|
directiveSelectors.push('slot');
|
|
27
27
|
selector = directiveSelectors.join(',');
|
|
@@ -115,11 +115,11 @@ function resolveDependencies(directive, expr, el, ctx, rootState) {
|
|
|
115
115
|
* registry.set('text', textDirective);
|
|
116
116
|
*
|
|
117
117
|
* const html = await render(
|
|
118
|
-
* '<span
|
|
118
|
+
* '<span g-text="user.name"></span>',
|
|
119
119
|
* { user: { name: 'Alice' } },
|
|
120
120
|
* registry
|
|
121
121
|
* );
|
|
122
|
-
* // '<span
|
|
122
|
+
* // '<span g-text="user.name">Alice</span>'
|
|
123
123
|
* ```
|
|
124
124
|
*/
|
|
125
125
|
export async function render(html, state, registry) {
|
|
@@ -148,7 +148,7 @@ export async function render(html, state, registry) {
|
|
|
148
148
|
continue;
|
|
149
149
|
}
|
|
150
150
|
for (const [name, directive] of registry) {
|
|
151
|
-
const attr = match.getAttribute(`
|
|
151
|
+
const attr = match.getAttribute(`g-${name}`);
|
|
152
152
|
if (attr !== null) {
|
|
153
153
|
index.push({
|
|
154
154
|
el: match,
|
|
@@ -189,25 +189,25 @@ export async function render(html, state, registry) {
|
|
|
189
189
|
}
|
|
190
190
|
// Process elements in tree order
|
|
191
191
|
for (const el of elementOrder) {
|
|
192
|
-
// Skip elements that were removed (e.g., by
|
|
192
|
+
// Skip elements that were removed (e.g., by g-for cloning)
|
|
193
193
|
if (!el.isConnected) {
|
|
194
194
|
processed.add(el);
|
|
195
195
|
continue;
|
|
196
196
|
}
|
|
197
|
-
// Skip elements already processed by structural directives (
|
|
197
|
+
// Skip elements already processed by structural directives (g-for, g-if)
|
|
198
198
|
// These elements have their own scoped processing
|
|
199
199
|
if (el.hasAttribute(FOR_PROCESSED_ATTR) || el.hasAttribute(IF_PROCESSED_ATTR)) {
|
|
200
200
|
processed.add(el);
|
|
201
201
|
continue;
|
|
202
202
|
}
|
|
203
|
-
// Skip template elements with
|
|
203
|
+
// Skip template elements with g-for - these are template wrappers created by g-for
|
|
204
204
|
// and should not be processed as directives (they're for client hydration)
|
|
205
|
-
if (el.tagName === 'TEMPLATE' && el.hasAttribute('
|
|
205
|
+
if (el.tagName === 'TEMPLATE' && el.hasAttribute('g-for')) {
|
|
206
206
|
processed.add(el);
|
|
207
207
|
continue;
|
|
208
208
|
}
|
|
209
209
|
// Skip template content elements - these are inside template wrappers
|
|
210
|
-
// and their directives are processed by
|
|
210
|
+
// and their directives are processed by g-for when rendering items
|
|
211
211
|
if (el.hasAttribute(FOR_TEMPLATE_ATTR)) {
|
|
212
212
|
processed.add(el);
|
|
213
213
|
continue;
|
|
@@ -217,7 +217,7 @@ export async function render(html, state, registry) {
|
|
|
217
217
|
// Sort directives on this element by priority (higher first)
|
|
218
218
|
directives.sort((a, b) => b.priority - a.priority);
|
|
219
219
|
for (const item of directives) {
|
|
220
|
-
// Check if element was disconnected by a previous directive (e.g.,
|
|
220
|
+
// Check if element was disconnected by a previous directive (e.g., g-for replacing it)
|
|
221
221
|
if (!item.el.isConnected) {
|
|
222
222
|
break;
|
|
223
223
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export interface InjectableRegistry {
|
|
|
51
51
|
$state: Record<string, unknown>;
|
|
52
52
|
/** Root reactive state object (shared across all elements) */
|
|
53
53
|
$rootState: Record<string, unknown>;
|
|
54
|
-
/** Template registry for
|
|
54
|
+
/** Template registry for g-template directive */
|
|
55
55
|
$templates: {
|
|
56
56
|
get(name: string): Promise<string>;
|
|
57
57
|
};
|
|
@@ -111,10 +111,10 @@ export interface Context {
|
|
|
111
111
|
*
|
|
112
112
|
* @remarks
|
|
113
113
|
* Higher priority directives run first. Structural directives
|
|
114
|
-
* (like
|
|
114
|
+
* (like g-if, g-for) need to run before behavioral ones.
|
|
115
115
|
*/
|
|
116
116
|
export declare enum DirectivePriority {
|
|
117
|
-
/** Structural directives that control DOM presence (
|
|
117
|
+
/** Structural directives that control DOM presence (g-if, g-for) */
|
|
118
118
|
STRUCTURAL = 1000,
|
|
119
119
|
/** Template/transclusion directives */
|
|
120
120
|
TEMPLATE = 500,
|
|
@@ -314,7 +314,7 @@ export interface DirectiveRegistration {
|
|
|
314
314
|
* The function can be `null` for pure template directives that have no
|
|
315
315
|
* runtime behavior.
|
|
316
316
|
*
|
|
317
|
-
* @param name - The directive name (e.g., '
|
|
317
|
+
* @param name - The directive name (e.g., 'g-text' or 'todo-app')
|
|
318
318
|
* @param fn - The directive function, or null for template-only directives
|
|
319
319
|
* @param options - Registration options
|
|
320
320
|
*
|
package/dist/types.js
CHANGED
|
@@ -18,11 +18,11 @@ export var Mode;
|
|
|
18
18
|
*
|
|
19
19
|
* @remarks
|
|
20
20
|
* Higher priority directives run first. Structural directives
|
|
21
|
-
* (like
|
|
21
|
+
* (like g-if, g-for) need to run before behavioral ones.
|
|
22
22
|
*/
|
|
23
23
|
export var DirectivePriority;
|
|
24
24
|
(function (DirectivePriority) {
|
|
25
|
-
/** Structural directives that control DOM presence (
|
|
25
|
+
/** Structural directives that control DOM presence (g-if, g-for) */
|
|
26
26
|
DirectivePriority[DirectivePriority["STRUCTURAL"] = 1000] = "STRUCTURAL";
|
|
27
27
|
/** Template/transclusion directives */
|
|
28
28
|
DirectivePriority[DirectivePriority["TEMPLATE"] = 500] = "TEMPLATE";
|
|
@@ -42,7 +42,7 @@ const directiveRegistry = new Map();
|
|
|
42
42
|
* The function can be `null` for pure template directives that have no
|
|
43
43
|
* runtime behavior.
|
|
44
44
|
*
|
|
45
|
-
* @param name - The directive name (e.g., '
|
|
45
|
+
* @param name - The directive name (e.g., 'g-text' or 'todo-app')
|
|
46
46
|
* @param fn - The directive function, or null for template-only directives
|
|
47
47
|
* @param options - Registration options
|
|
48
48
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gonia",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "A lightweight, SSR-first reactive UI library with declarative directives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "https://github.com/monokrome/
|
|
19
|
+
"url": "https://github.com/monokrome/gonia"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|