@sigx/runtime-dom 0.1.5 → 0.1.7
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/dist/Portal.d.ts +58 -0
- package/dist/Portal.d.ts.map +1 -0
- package/dist/directives/show-jsx-types.d.ts +31 -0
- package/dist/directives/show-jsx-types.d.ts.map +1 -0
- package/dist/directives/show.d.ts +19 -0
- package/dist/directives/show.d.ts.map +1 -0
- package/dist/index.d.ts +63 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +240 -40
- package/dist/index.js.map +1 -1
- package/dist/jsx.d.ts +169 -14
- package/dist/jsx.d.ts.map +1 -1
- package/package.json +8 -7
- package/dist/auto-loader.d.ts +0 -104
- package/dist/auto-loader.d.ts.map +0 -1
- package/dist/custom-element.d.ts +0 -15
- package/dist/custom-element.d.ts.map +0 -1
- package/dist/sheet.d.ts +0 -51
- package/dist/sheet.d.ts.map +0 -1
- package/dist/styled.d.ts +0 -15
- package/dist/styled.d.ts.map +0 -1
- package/dist/styles.d.ts +0 -61
- package/dist/styles.d.ts.map +0 -1
package/dist/Portal.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portal component for rendering children to a different DOM location.
|
|
3
|
+
*
|
|
4
|
+
* Uses the `moveBefore` API (Chrome 133+) when available for state-preserving
|
|
5
|
+
* DOM moves. Falls back to `insertBefore` for older browsers.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { Portal } from '@sigx/runtime-dom';
|
|
10
|
+
*
|
|
11
|
+
* // Render to document.body (default)
|
|
12
|
+
* <Portal>
|
|
13
|
+
* <div class="modal">Modal content</div>
|
|
14
|
+
* </Portal>
|
|
15
|
+
*
|
|
16
|
+
* // Render to a specific container
|
|
17
|
+
* <Portal to={document.getElementById('modal-root')}>
|
|
18
|
+
* <div class="modal">Modal content</div>
|
|
19
|
+
* </Portal>
|
|
20
|
+
*
|
|
21
|
+
* // Render to a container by selector
|
|
22
|
+
* <Portal to="#modal-root">
|
|
23
|
+
* <div class="modal">Modal content</div>
|
|
24
|
+
* </Portal>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { DefineProp } from '@sigx/runtime-core';
|
|
28
|
+
/**
|
|
29
|
+
* Check if the browser supports the moveBefore API.
|
|
30
|
+
* moveBefore allows moving DOM nodes without losing state (iframes, videos, focus, etc.)
|
|
31
|
+
*/
|
|
32
|
+
export declare function supportsMoveBefore(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Move or insert a node into a parent, using moveBefore when available
|
|
35
|
+
* for state-preserving moves.
|
|
36
|
+
*
|
|
37
|
+
* @param parent - The target parent element
|
|
38
|
+
* @param node - The node to move/insert
|
|
39
|
+
* @param anchor - Optional reference node to insert before
|
|
40
|
+
*/
|
|
41
|
+
export declare function moveNode(parent: Element, node: Node, anchor?: Node | null): void;
|
|
42
|
+
type PortalProps = DefineProp<'to', string | Element> & DefineProp<'disabled', boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Portal component - renders children to a different DOM location.
|
|
45
|
+
*
|
|
46
|
+
* Props:
|
|
47
|
+
* - `to` - Target container (Element or CSS selector string). Defaults to document.body.
|
|
48
|
+
* - `disabled` - When true, renders children in place instead of portaling
|
|
49
|
+
* - `children` - Content to render in the portal
|
|
50
|
+
*
|
|
51
|
+
* Features:
|
|
52
|
+
* - Uses `moveBefore` API (Chrome 133+) for state-preserving DOM moves
|
|
53
|
+
* - Preserves iframe content, video playback, focus, and CSS animations
|
|
54
|
+
* - Falls back to `insertBefore` for older browsers
|
|
55
|
+
*/
|
|
56
|
+
export declare const Portal: import("@sigx/runtime-core").ComponentFactory<PortalProps, void, {}>;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=Portal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Portal.d.ts","sourceRoot":"","sources":["../src/Portal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAa,UAAU,EAA0C,MAAM,oBAAoB,CAAC;AAInG;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACpB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,IAAI,EACV,MAAM,GAAE,IAAI,GAAG,IAAW,GAC3B,IAAI,CAQN;AAuBD,KAAK,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAExF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,sEA2EG,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSX type augmentation for the `show` directive.
|
|
3
|
+
*
|
|
4
|
+
* Adds `use:show` to `DirectiveAttributeExtensions` so that typing `use:`
|
|
5
|
+
* in JSX triggers IntelliSense with `use:show` as a suggestion.
|
|
6
|
+
*/
|
|
7
|
+
import type { DirectiveDefinition } from '@sigx/runtime-core';
|
|
8
|
+
declare global {
|
|
9
|
+
namespace JSX {
|
|
10
|
+
interface DirectiveAttributeExtensions {
|
|
11
|
+
/**
|
|
12
|
+
* Toggle element visibility via `display` CSS property.
|
|
13
|
+
*
|
|
14
|
+
* The element stays in the DOM — only its `display` is toggled.
|
|
15
|
+
* Preserves original display value (e.g., `flex`, `grid`).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // Shorthand — directive resolved automatically:
|
|
20
|
+
* <div use:show={isVisible}>Content</div>
|
|
21
|
+
*
|
|
22
|
+
* // Explicit tuple form:
|
|
23
|
+
* import { show } from 'sigx';
|
|
24
|
+
* <div use:show={[show, isVisible]}>Content</div>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
'use:show'?: boolean | DirectiveDefinition<boolean, HTMLElement> | [DirectiveDefinition<boolean, HTMLElement>, boolean];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=show-jsx-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show-jsx-types.d.ts","sourceRoot":"","sources":["../../src/directives/show-jsx-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,GAAG,CAAC;QACV,UAAU,4BAA4B;YAClC;;;;;;;;;;;;;;;eAeG;YACH,UAAU,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;SAC3H;KACJ;CACJ"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in `show` directive — toggles element visibility via `display` CSS property.
|
|
3
|
+
*
|
|
4
|
+
* Unlike conditional rendering (ternary in JSX), `use:show` keeps the element in the DOM
|
|
5
|
+
* and only toggles its `display` style. This is useful when toggling is frequent and you
|
|
6
|
+
* want to preserve element state (e.g., scroll position, input focus).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // Shorthand — directive resolved automatically:
|
|
11
|
+
* <div use:show={isVisible}>Content</div>
|
|
12
|
+
*
|
|
13
|
+
* // Explicit tuple form:
|
|
14
|
+
* import { show } from 'sigx';
|
|
15
|
+
* <div use:show={[show, isVisible]}>Content</div>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const show: import("@sigx/runtime-core").DirectiveDefinition<boolean, HTMLElement>;
|
|
19
|
+
//# sourceMappingURL=show.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/directives/show.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,eAAO,MAAM,IAAI,wEAwBf,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,69 @@
|
|
|
1
1
|
import './jsx';
|
|
2
|
-
import './types
|
|
2
|
+
import './types';
|
|
3
|
+
import './directives/show-jsx-types';
|
|
3
4
|
import { RendererOptions } from '@sigx/runtime-core';
|
|
5
|
+
import { type DirectiveDefinition } from '@sigx/runtime-core';
|
|
6
|
+
import type { AppContext } from '@sigx/runtime-core';
|
|
7
|
+
/**
|
|
8
|
+
* A directive definition narrowed to DOM elements.
|
|
9
|
+
* Use this type when defining directives for the DOM renderer.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { defineDirective, type DOMDirective } from 'sigx';
|
|
14
|
+
*
|
|
15
|
+
* const tooltip = defineDirective<string, HTMLElement>({
|
|
16
|
+
* mounted(el, { value }) {
|
|
17
|
+
* el.title = value; // el is HTMLElement, fully typed
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export type DOMDirective<T = any> = DirectiveDefinition<T, HTMLElement>;
|
|
23
|
+
/**
|
|
24
|
+
* Register a built-in directive so it can be used with the shorthand syntax:
|
|
25
|
+
* `<div use:show={value}>` instead of `<div use:show={[show, value]}>`.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export declare function registerBuiltInDirective(name: string, def: DirectiveDefinition): void;
|
|
29
|
+
/**
|
|
30
|
+
* Look up a registered built-in directive by name.
|
|
31
|
+
* Used by SSR renderer to resolve `use:<name>={value}` shorthand.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveBuiltInDirective(name: string): DirectiveDefinition | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Process a `use:*` prop in patchProp.
|
|
37
|
+
* Handles directive created and updated lifecycle hooks.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
declare function patchDirective(el: Element, name: string, prevValue: any, nextValue: any, appContext: AppContext | null): void;
|
|
41
|
+
/**
|
|
42
|
+
* Called after an element is inserted into the DOM.
|
|
43
|
+
* Invokes `mounted` hooks for all directives on the element.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
declare function onElementMounted(el: Element): void;
|
|
4
47
|
declare function patchProp(dom: Element, key: string, prevValue: any, nextValue: any, isSVG?: boolean): void;
|
|
5
48
|
declare const nodeOps: RendererOptions<Node, Element>;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Render a SignalX element to a DOM container.
|
|
51
|
+
* Supports both Element references and CSS selectors.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* import { render } from 'sigx';
|
|
56
|
+
*
|
|
57
|
+
* // Using CSS selector
|
|
58
|
+
* render(<App />, "#app");
|
|
59
|
+
*
|
|
60
|
+
* // Using element reference
|
|
61
|
+
* render(<App />, document.getElementById('app')!);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare const render: (element: any, container: Element | string, appContext?: any) => void;
|
|
9
65
|
export declare const patch: import("@sigx/runtime-core").RendererPatchFn<Node, Element>, mount: import("@sigx/runtime-core").RendererMountFn<Node, Element>, unmount: import("@sigx/runtime-core").RendererUnmountFn<Node, Element>, mountComponent: import("@sigx/runtime-core").RendererMountComponentFn<Node, Element>;
|
|
10
|
-
export { patchProp, nodeOps };
|
|
66
|
+
export { patchProp, patchDirective, onElementMounted, nodeOps };
|
|
11
67
|
/**
|
|
12
68
|
* Mount function for DOM environments.
|
|
13
69
|
* Use this with defineApp().mount() to render to the DOM.
|
|
@@ -23,4 +79,6 @@ export { patchProp, nodeOps };
|
|
|
23
79
|
* ```
|
|
24
80
|
*/
|
|
25
81
|
export declare const domMount: (component: any, container: HTMLElement | Element | ShadowRoot | string, appContext?: any) => (() => void);
|
|
82
|
+
export { Portal, supportsMoveBefore, moveNode } from './Portal.js';
|
|
83
|
+
export { show } from './directives/show.js';
|
|
26
84
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,CAAC;AAEf,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,CAAC;AAEf,OAAO,SAAS,CAAC;AAEjB,OAAO,6BAA6B,CAAC;AACrC,OAAO,EAA0E,eAAe,EAAyB,MAAM,oBAAoB,CAAC;AACpJ,OAAO,EAAe,KAAK,mBAAmB,EAAyB,MAAM,oBAAoB,CAAC;AAClG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,GAAG,IAAI,mBAAmB,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;AAcxE;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAErF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAErF;AA+BD;;;;GAIG;AACH,iBAAS,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAoEtH;AAED;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAS3C;AA+ID,iBAAS,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,OAAO,QAgL5F;AAED,QAAA,MAAM,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,OAAO,CAkC3C,CAAC;AAIF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,GAAI,SAAS,GAAG,EAAE,WAAW,OAAO,GAAG,MAAM,EAAE,aAAa,GAAG,KAAG,IAUpF,CAAC;AAGF,eAAO,MAAQ,KAAK,+DAAE,KAAK,+DAAE,OAAO,iEAAE,cAAc,sEAAa,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,GAAG,EAAE,WAAW,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,EAAE,aAAa,GAAG,KAAG,CAAC,MAAM,IAAI,CAiB9H,CAAC;AAMF,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGnE,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,184 @@
|
|
|
1
|
-
import { createRenderer, setDefaultMount,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Fragment, component as component$1, createRenderer, defineDirective, isDirective, jsx, normalizeSubTree, setDefaultMount, setPlatformModelProcessor } from "@sigx/runtime-core";
|
|
2
|
+
import { effect } from "@sigx/reactivity";
|
|
3
|
+
function supportsMoveBefore() {
|
|
4
|
+
return typeof Node !== "undefined" && "moveBefore" in Node.prototype;
|
|
5
|
+
}
|
|
6
|
+
function moveNode(parent, node, anchor = null) {
|
|
7
|
+
if (supportsMoveBefore()) parent.moveBefore(node, anchor);
|
|
8
|
+
else parent.insertBefore(node, anchor);
|
|
9
|
+
}
|
|
10
|
+
function resolveTarget(target) {
|
|
11
|
+
if (target === void 0) return document.body;
|
|
12
|
+
if (typeof target === "string") {
|
|
13
|
+
const resolved = document.querySelector(target);
|
|
14
|
+
if (!resolved) {
|
|
15
|
+
console.warn(`Portal: Target "${target}" not found, falling back to document.body`);
|
|
16
|
+
return document.body;
|
|
17
|
+
}
|
|
18
|
+
return resolved;
|
|
19
|
+
}
|
|
20
|
+
return target;
|
|
21
|
+
}
|
|
22
|
+
const Portal = component$1(({ props, slots, onMounted, onUnmounted }) => {
|
|
23
|
+
let portalContainer = null;
|
|
24
|
+
let mountedVNode = null;
|
|
25
|
+
let cleanupEffect = null;
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
if (props.disabled) return;
|
|
28
|
+
const targetContainer = resolveTarget(props.to);
|
|
29
|
+
portalContainer = document.createElement("div");
|
|
30
|
+
portalContainer.setAttribute("data-sigx-portal", "");
|
|
31
|
+
moveNode(targetContainer, portalContainer);
|
|
32
|
+
cleanupEffect = effect(() => {
|
|
33
|
+
const children = slots.default();
|
|
34
|
+
if (!portalContainer) return;
|
|
35
|
+
const vnode = normalizeSubTree(children);
|
|
36
|
+
if (mountedVNode) patch(mountedVNode, vnode, portalContainer);
|
|
37
|
+
else mount(vnode, portalContainer);
|
|
38
|
+
mountedVNode = vnode;
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
onUnmounted(() => {
|
|
42
|
+
if (cleanupEffect) {
|
|
43
|
+
cleanupEffect();
|
|
44
|
+
cleanupEffect = null;
|
|
45
|
+
}
|
|
46
|
+
if (mountedVNode && portalContainer) {
|
|
47
|
+
unmount(mountedVNode, portalContainer);
|
|
48
|
+
mountedVNode = null;
|
|
49
|
+
}
|
|
50
|
+
if (portalContainer && portalContainer.parentNode) portalContainer.parentNode.removeChild(portalContainer);
|
|
51
|
+
portalContainer = null;
|
|
52
|
+
});
|
|
53
|
+
return () => {
|
|
54
|
+
if (props.disabled) return jsx(Fragment, { children: slots.default() });
|
|
55
|
+
return null;
|
|
56
|
+
};
|
|
57
|
+
}, { name: "Portal" });
|
|
58
|
+
var ORIGINAL_DISPLAY = Symbol("sigx.show.originalDisplay");
|
|
59
|
+
const show = defineDirective({
|
|
60
|
+
mounted(el, { value }) {
|
|
61
|
+
const showEl = el;
|
|
62
|
+
const saved = showEl.style.display === "none" ? "" : showEl.style.display;
|
|
63
|
+
showEl[ORIGINAL_DISPLAY] = saved;
|
|
64
|
+
showEl.style.display = value ? saved : "none";
|
|
65
|
+
},
|
|
66
|
+
updated(el, { value, oldValue }) {
|
|
67
|
+
if (value !== oldValue) {
|
|
68
|
+
const showEl = el;
|
|
69
|
+
showEl.style.display = value ? showEl[ORIGINAL_DISPLAY] ?? "" : "none";
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
unmounted(el) {
|
|
73
|
+
const showEl = el;
|
|
74
|
+
const original = showEl[ORIGINAL_DISPLAY];
|
|
75
|
+
if (original !== void 0) showEl.style.display = original;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
var builtInDirectives = /* @__PURE__ */ new Map();
|
|
79
|
+
function registerBuiltInDirective(name, def) {
|
|
80
|
+
builtInDirectives.set(name, def);
|
|
81
|
+
}
|
|
82
|
+
function resolveBuiltInDirective(name) {
|
|
83
|
+
return builtInDirectives.get(name);
|
|
84
|
+
}
|
|
85
|
+
var DIRECTIVE_STATE = Symbol.for("sigx.directives");
|
|
86
|
+
function getDirectiveMap(el) {
|
|
87
|
+
let map = el[DIRECTIVE_STATE];
|
|
88
|
+
if (!map) {
|
|
89
|
+
map = /* @__PURE__ */ new Map();
|
|
90
|
+
el[DIRECTIVE_STATE] = map;
|
|
91
|
+
}
|
|
92
|
+
return map;
|
|
93
|
+
}
|
|
94
|
+
function patchDirective(el, name, prevValue, nextValue, appContext) {
|
|
95
|
+
const dirMap = getDirectiveMap(el);
|
|
96
|
+
if (nextValue == null) {
|
|
97
|
+
dirMap.delete(name);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
let def;
|
|
101
|
+
let value;
|
|
102
|
+
if (isDirective(nextValue)) {
|
|
103
|
+
def = nextValue;
|
|
104
|
+
value = void 0;
|
|
105
|
+
} else if (Array.isArray(nextValue) && nextValue.length >= 1 && isDirective(nextValue[0])) {
|
|
106
|
+
def = nextValue[0];
|
|
107
|
+
value = nextValue[1];
|
|
108
|
+
} else {
|
|
109
|
+
const builtIn = builtInDirectives.get(name);
|
|
110
|
+
if (builtIn) {
|
|
111
|
+
def = builtIn;
|
|
112
|
+
value = nextValue;
|
|
113
|
+
} else {
|
|
114
|
+
const custom = appContext?.directives.get(name);
|
|
115
|
+
if (custom) {
|
|
116
|
+
def = custom;
|
|
117
|
+
value = nextValue;
|
|
118
|
+
} else {
|
|
119
|
+
console.warn(`[sigx] Directive "use:${name}" could not be resolved. Make sure to register it via app.directive('${name}', definition) or pass a directive definition directly.`);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const existing = dirMap.get(name);
|
|
125
|
+
if (!existing) {
|
|
126
|
+
const state = {
|
|
127
|
+
def,
|
|
128
|
+
value
|
|
129
|
+
};
|
|
130
|
+
dirMap.set(name, state);
|
|
131
|
+
if (def.created) def.created(el, { value });
|
|
132
|
+
} else {
|
|
133
|
+
const oldValue = existing.value;
|
|
134
|
+
existing.def = def;
|
|
135
|
+
existing.value = value;
|
|
136
|
+
if (def.updated && value !== oldValue) def.updated(el, {
|
|
137
|
+
value,
|
|
138
|
+
oldValue
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function onElementMounted(el) {
|
|
143
|
+
const map = el[DIRECTIVE_STATE];
|
|
144
|
+
if (!map) return;
|
|
145
|
+
for (const [, state] of map) if (state.def.mounted) state.def.mounted(el, { value: state.value });
|
|
146
|
+
}
|
|
147
|
+
function onElementUnmounted(el) {
|
|
148
|
+
const map = el[DIRECTIVE_STATE];
|
|
149
|
+
if (!map) return;
|
|
150
|
+
for (const [, state] of map) {
|
|
151
|
+
if (state.def.unmounted) state.def.unmounted(el, { value: state.value });
|
|
152
|
+
if (state.cleanup) state.cleanup();
|
|
153
|
+
}
|
|
154
|
+
map.clear();
|
|
155
|
+
delete el[DIRECTIVE_STATE];
|
|
156
|
+
}
|
|
157
|
+
var svgNS = "http://www.w3.org/2000/svg";
|
|
158
|
+
setPlatformModelProcessor((type, props, [stateObj, key], originalProps) => {
|
|
159
|
+
const setValue = (v) => {
|
|
160
|
+
const updateHandler = stateObj[`onUpdate:${key}`];
|
|
161
|
+
if (typeof updateHandler === "function") updateHandler(v);
|
|
162
|
+
else stateObj[key] = v;
|
|
163
|
+
};
|
|
5
164
|
if (type === "input" && originalProps.type === "checkbox") {
|
|
6
165
|
const val = stateObj[key];
|
|
7
166
|
if (Array.isArray(val)) {
|
|
8
167
|
props.checked = val.includes(originalProps.value);
|
|
9
|
-
const existingHandler = props["onUpdate:
|
|
10
|
-
props["onUpdate:
|
|
168
|
+
const existingHandler = props["onUpdate:modelValue"];
|
|
169
|
+
props["onUpdate:modelValue"] = (checked) => {
|
|
11
170
|
const currentVal = originalProps.value;
|
|
12
171
|
const currentArr = stateObj[key];
|
|
13
172
|
if (checked) {
|
|
14
|
-
if (!currentArr.includes(currentVal))
|
|
15
|
-
} else
|
|
173
|
+
if (!currentArr.includes(currentVal)) setValue([...currentArr, currentVal]);
|
|
174
|
+
} else setValue(currentArr.filter((i) => i !== currentVal));
|
|
16
175
|
if (existingHandler) existingHandler(checked);
|
|
17
176
|
};
|
|
18
177
|
} else {
|
|
19
178
|
props.checked = val;
|
|
20
|
-
const existingHandler = props["onUpdate:
|
|
21
|
-
props["onUpdate:
|
|
22
|
-
|
|
179
|
+
const existingHandler = props["onUpdate:modelValue"];
|
|
180
|
+
props["onUpdate:modelValue"] = (v) => {
|
|
181
|
+
setValue(v);
|
|
23
182
|
if (existingHandler) existingHandler(v);
|
|
24
183
|
};
|
|
25
184
|
}
|
|
@@ -27,17 +186,46 @@ setPlatformSyncProcessor((type, props, [stateObj, key], originalProps) => {
|
|
|
27
186
|
}
|
|
28
187
|
if (type === "input" && originalProps.type === "radio") {
|
|
29
188
|
props.checked = stateObj[key] === originalProps.value;
|
|
30
|
-
const existingHandler = props["onUpdate:
|
|
31
|
-
props["onUpdate:
|
|
32
|
-
if (checked)
|
|
189
|
+
const existingHandler = props["onUpdate:modelValue"];
|
|
190
|
+
props["onUpdate:modelValue"] = (checked) => {
|
|
191
|
+
if (checked) setValue(originalProps.value);
|
|
33
192
|
if (existingHandler) existingHandler(checked);
|
|
34
193
|
};
|
|
35
194
|
return true;
|
|
36
195
|
}
|
|
196
|
+
if (type === "input") {
|
|
197
|
+
props.value = stateObj[key] ?? "";
|
|
198
|
+
const existingHandler = props["onUpdate:modelValue"];
|
|
199
|
+
props["onUpdate:modelValue"] = (v) => {
|
|
200
|
+
setValue(v);
|
|
201
|
+
if (existingHandler) existingHandler(v);
|
|
202
|
+
};
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
if (type === "textarea") {
|
|
206
|
+
props.value = stateObj[key] ?? "";
|
|
207
|
+
const existingHandler = props["onUpdate:modelValue"];
|
|
208
|
+
props["onUpdate:modelValue"] = (v) => {
|
|
209
|
+
setValue(v);
|
|
210
|
+
if (existingHandler) existingHandler(v);
|
|
211
|
+
};
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
if (type === "select") {
|
|
215
|
+
props.value = stateObj[key] ?? "";
|
|
216
|
+
const existingHandler = props["onUpdate:modelValue"];
|
|
217
|
+
props["onUpdate:modelValue"] = (v) => {
|
|
218
|
+
setValue(v);
|
|
219
|
+
if (existingHandler) existingHandler(v);
|
|
220
|
+
};
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
37
223
|
return false;
|
|
38
224
|
});
|
|
39
225
|
function patchProp(dom, key, prevValue, nextValue, isSVG) {
|
|
226
|
+
if (!dom) return;
|
|
40
227
|
const tagName = dom.tagName.toLowerCase();
|
|
228
|
+
const isSvgElement = isSVG ?? dom instanceof SVGElement;
|
|
41
229
|
const oldValue = prevValue;
|
|
42
230
|
const newValue = nextValue;
|
|
43
231
|
if (key === "children" || key === "key" || key === "ref") return;
|
|
@@ -49,10 +237,10 @@ function patchProp(dom, key, prevValue, nextValue, isSVG) {
|
|
|
49
237
|
else el.style[styleKey] = styleObj[styleKey];
|
|
50
238
|
} else el.style.cssText = String(newValue);
|
|
51
239
|
} else if (key.startsWith("on")) {
|
|
52
|
-
if (key === "onUpdate:
|
|
240
|
+
if (key === "onUpdate:modelValue" && (tagName === "input" || tagName === "textarea" || tagName === "select")) {
|
|
53
241
|
const el = dom;
|
|
54
242
|
if (oldValue) {
|
|
55
|
-
const wrapper = oldValue.
|
|
243
|
+
const wrapper = oldValue.__sigx_model_handler;
|
|
56
244
|
if (wrapper) {
|
|
57
245
|
el.removeEventListener("input", wrapper);
|
|
58
246
|
el.removeEventListener("change", wrapper);
|
|
@@ -68,7 +256,7 @@ function patchProp(dom, key, prevValue, nextValue, isSVG) {
|
|
|
68
256
|
else val = target.value;
|
|
69
257
|
newValue(val);
|
|
70
258
|
};
|
|
71
|
-
newValue.
|
|
259
|
+
newValue.__sigx_model_handler = handler;
|
|
72
260
|
const inputType = dom.type;
|
|
73
261
|
if (tagName === "select" || tagName === "input" && (inputType === "checkbox" || inputType === "radio")) el.addEventListener("change", handler);
|
|
74
262
|
else el.addEventListener("input", handler);
|
|
@@ -99,11 +287,29 @@ function patchProp(dom, key, prevValue, nextValue, isSVG) {
|
|
|
99
287
|
else if (key.startsWith(".")) {
|
|
100
288
|
const propName = key.slice(1);
|
|
101
289
|
dom[propName] = newValue;
|
|
102
|
-
} else if ((
|
|
103
|
-
|
|
290
|
+
} else if (key.startsWith("prop:")) {
|
|
291
|
+
const propName = key.slice(5);
|
|
292
|
+
dom[propName] = newValue;
|
|
293
|
+
} else if (isSvgElement) if (key === "innerHTML" || key === "textContent") dom[key] = newValue ?? "";
|
|
294
|
+
else if (key.startsWith("xlink:")) {
|
|
295
|
+
const xlinkNS = "http://www.w3.org/1999/xlink";
|
|
296
|
+
if (newValue == null) dom.removeAttributeNS(xlinkNS, key.slice(6));
|
|
297
|
+
else dom.setAttributeNS(xlinkNS, key, String(newValue));
|
|
298
|
+
} else if (newValue === true) dom.setAttribute(key, "");
|
|
299
|
+
else if (newValue === false || newValue == null) dom.removeAttribute(key);
|
|
300
|
+
else dom.setAttribute(key, String(newValue));
|
|
301
|
+
else if ((tagName === "input" || tagName === "textarea" || tagName === "select") && (key === "value" || key === "checked")) {
|
|
302
|
+
if (tagName === "select" && key === "value") {
|
|
303
|
+
queueMicrotask(() => {
|
|
304
|
+
dom.value = String(newValue ?? "");
|
|
305
|
+
});
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
104
308
|
if (key === "checked" && tagName === "input") dom.checked = Boolean(newValue);
|
|
105
309
|
else if (key === "value") dom.value = String(newValue ?? "");
|
|
106
|
-
} else if (key in dom)
|
|
310
|
+
} else if (key in dom) if (newValue == null) {
|
|
311
|
+
if (dom.hasAttribute?.(key)) dom.removeAttribute(key);
|
|
312
|
+
} else try {
|
|
107
313
|
dom[key] = newValue;
|
|
108
314
|
} catch (e) {
|
|
109
315
|
dom.setAttribute(key, String(newValue));
|
|
@@ -113,7 +319,7 @@ function patchProp(dom, key, prevValue, nextValue, isSVG) {
|
|
|
113
319
|
else if (newValue === false || newValue == null) dom.removeAttribute(key);
|
|
114
320
|
else dom.setAttribute(key, String(newValue));
|
|
115
321
|
}
|
|
116
|
-
|
|
322
|
+
var nodeOps = {
|
|
117
323
|
insert: (child, parent, anchor) => {
|
|
118
324
|
parent.insertBefore(child, anchor || null);
|
|
119
325
|
},
|
|
@@ -122,6 +328,7 @@ const nodeOps = {
|
|
|
122
328
|
if (parent) parent.removeChild(child);
|
|
123
329
|
},
|
|
124
330
|
createElement: (tag, isSVG, isCustomizedBuiltIn) => {
|
|
331
|
+
if (isSVG) return document.createElementNS(svgNS, tag);
|
|
125
332
|
const is = isCustomizedBuiltIn ? { is: isCustomizedBuiltIn } : void 0;
|
|
126
333
|
return document.createElement(tag, is);
|
|
127
334
|
},
|
|
@@ -138,25 +345,18 @@ const nodeOps = {
|
|
|
138
345
|
querySelector: (selector) => document.querySelector(selector),
|
|
139
346
|
setScopeId: (el, id) => el.setAttribute(id, ""),
|
|
140
347
|
cloneNode: (node) => node.cloneNode(true),
|
|
141
|
-
patchProp
|
|
348
|
+
patchProp,
|
|
349
|
+
patchDirective,
|
|
350
|
+
onElementMounted,
|
|
351
|
+
onElementUnmounted
|
|
352
|
+
};
|
|
353
|
+
var renderer = createRenderer(nodeOps);
|
|
354
|
+
const render = (element, container, appContext) => {
|
|
355
|
+
const target = typeof container === "string" ? document.querySelector(container) : container;
|
|
356
|
+
if (!target) throw new Error(`Render target "${container}" not found.`);
|
|
357
|
+
return renderer.render(element, target, appContext);
|
|
142
358
|
};
|
|
143
|
-
const renderer = createRenderer(nodeOps);
|
|
144
|
-
const { render, createApp } = renderer;
|
|
145
359
|
const { patch, mount, unmount, mountComponent } = renderer;
|
|
146
|
-
/**
|
|
147
|
-
* Mount function for DOM environments.
|
|
148
|
-
* Use this with defineApp().mount() to render to the DOM.
|
|
149
|
-
*
|
|
150
|
-
* @example
|
|
151
|
-
* ```tsx
|
|
152
|
-
* import { defineApp } from '@sigx/runtime-core';
|
|
153
|
-
* import { domMount } from '@sigx/runtime-dom';
|
|
154
|
-
*
|
|
155
|
-
* const app = defineApp(<App />);
|
|
156
|
-
* app.use(routerPlugin)
|
|
157
|
-
* .mount(document.getElementById('app')!, domMount);
|
|
158
|
-
* ```
|
|
159
|
-
*/
|
|
160
360
|
const domMount = (component, container, appContext) => {
|
|
161
361
|
const target = typeof container === "string" ? document.querySelector(container) : container;
|
|
162
362
|
if (!target) throw new Error(`Mount target "${container}" not found.`);
|
|
@@ -166,7 +366,7 @@ const domMount = (component, container, appContext) => {
|
|
|
166
366
|
};
|
|
167
367
|
};
|
|
168
368
|
setDefaultMount(domMount);
|
|
369
|
+
registerBuiltInDirective("show", show);
|
|
370
|
+
export { Portal, domMount, mount, mountComponent, moveNode, nodeOps, onElementMounted, patch, patchDirective, patchProp, registerBuiltInDirective, render, resolveBuiltInDirective, show, supportsMoveBefore, unmount };
|
|
169
371
|
|
|
170
|
-
//#endregion
|
|
171
|
-
export { createApp, domMount, mount, mountComponent, nodeOps, patch, patchProp, render, unmount };
|
|
172
372
|
//# sourceMappingURL=index.js.map
|