@sigx/runtime-core 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/app-types.d.ts +55 -15
- package/dist/app-types.d.ts.map +1 -1
- package/dist/app.d.ts +4 -8
- package/dist/app.d.ts.map +1 -1
- package/dist/async-context.d.ts +47 -0
- package/dist/async-context.d.ts.map +1 -0
- package/dist/component.d.ts +146 -40
- package/dist/component.d.ts.map +1 -1
- package/dist/compound.d.ts +34 -0
- package/dist/compound.d.ts.map +1 -0
- package/dist/di/factory.d.ts +3 -2
- package/dist/di/factory.d.ts.map +1 -1
- package/dist/di/injectable.d.ts +80 -6
- package/dist/di/injectable.d.ts.map +1 -1
- package/dist/directives.d.ts +111 -0
- package/dist/directives.d.ts.map +1 -0
- package/dist/error-boundary.d.ts +40 -0
- package/dist/error-boundary.d.ts.map +1 -0
- package/dist/hydration/index.d.ts +88 -0
- package/dist/hydration/index.d.ts.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +576 -696
- package/dist/index.js.map +1 -1
- package/dist/jsx-runtime.d.ts +3 -2
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/lazy.d.ts.map +1 -1
- package/dist/model.d.ts +68 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/platform.d.ts +9 -9
- package/dist/platform.d.ts.map +1 -1
- package/dist/renderer.d.ts +18 -3
- package/dist/renderer.d.ts.map +1 -1
- package/dist/utils/is-component.d.ts +30 -0
- package/dist/utils/is-component.d.ts.map +1 -0
- package/dist/utils/normalize.d.ts +4 -1
- package/dist/utils/normalize.d.ts.map +1 -1
- package/dist/utils/props-accessor.d.ts +6 -9
- package/dist/utils/props-accessor.d.ts.map +1 -1
- package/package.json +15 -6
- package/dist/sheet.d.ts +0 -51
- package/dist/sheet.d.ts.map +0 -1
- package/dist/stores/store.d.ts +0 -70
- package/dist/stores/store.d.ts.map +0 -1
- package/dist/styled.d.ts +0 -15
- package/dist/styled.d.ts.map +0 -1
- package/dist/utils/component-helpers.d.ts +0 -38
- package/dist/utils/component-helpers.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,114 +1,206 @@
|
|
|
1
|
-
import { detectAccess, effect,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Set the platform-specific sync processor for intrinsic elements.
|
|
7
|
-
* Called by runtime-dom to handle checkbox/radio/select sync bindings.
|
|
8
|
-
*/
|
|
9
|
-
function setPlatformSyncProcessor(fn) {
|
|
10
|
-
platformSyncProcessor = fn;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Get the current platform sync processor (for internal use).
|
|
14
|
-
*/
|
|
15
|
-
function getPlatformSyncProcessor() {
|
|
16
|
-
return platformSyncProcessor;
|
|
1
|
+
import { detectAccess, effect, isComputed, signal, signal as signal$1, untrack } from "@sigx/reactivity";
|
|
2
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
3
|
+
var platformModelProcessor = null;
|
|
4
|
+
function setPlatformModelProcessor(fn) {
|
|
5
|
+
platformModelProcessor = fn;
|
|
17
6
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
function getPlatformModelProcessor() {
|
|
8
|
+
return platformModelProcessor;
|
|
9
|
+
}
|
|
10
|
+
var plugins = [];
|
|
22
11
|
function registerComponentPlugin(plugin) {
|
|
23
12
|
plugins.push(plugin);
|
|
24
13
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Get all registered plugins (internal use)
|
|
27
|
-
*/
|
|
28
14
|
function getComponentPlugins() {
|
|
29
15
|
return plugins;
|
|
30
16
|
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Register a function that will be called to extend every component context.
|
|
34
|
-
* Extensions are called in order of registration.
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```ts
|
|
38
|
-
* // In @sigx/server-renderer/client
|
|
39
|
-
* registerContextExtension((ctx) => {
|
|
40
|
-
* ctx.ssr = { load: () => {} };
|
|
41
|
-
* });
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
17
|
+
var contextExtensions = [];
|
|
44
18
|
function registerContextExtension(extension) {
|
|
45
19
|
contextExtensions.push(extension);
|
|
46
20
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Apply all registered context extensions to a context object.
|
|
49
|
-
* Called internally by the renderer when creating component contexts.
|
|
50
|
-
*/
|
|
51
21
|
function applyContextExtensions(ctx) {
|
|
52
22
|
for (const extension of contextExtensions) extension(ctx);
|
|
53
23
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
24
|
+
var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
25
|
+
module.exports = {};
|
|
26
|
+
}));
|
|
27
|
+
var asyncLocalStorage = null;
|
|
28
|
+
try {
|
|
29
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined") {
|
|
30
|
+
const nodeAsync = globalThis.process?.versions?.node ? require___vite_browser_external() : null;
|
|
31
|
+
if (nodeAsync?.AsyncLocalStorage) asyncLocalStorage = new nodeAsync.AsyncLocalStorage();
|
|
32
|
+
}
|
|
33
|
+
} catch {}
|
|
34
|
+
var _fallbackContext = {
|
|
35
|
+
currentComponentContext: null,
|
|
36
|
+
currentSuspenseBoundary: null
|
|
37
|
+
};
|
|
38
|
+
function getRequestContext() {
|
|
39
|
+
if (asyncLocalStorage) {
|
|
40
|
+
const store = asyncLocalStorage.getStore();
|
|
41
|
+
if (store) return store;
|
|
42
|
+
}
|
|
43
|
+
return _fallbackContext;
|
|
44
|
+
}
|
|
45
|
+
function getCurrentInstanceSafe() {
|
|
46
|
+
return getRequestContext().currentComponentContext;
|
|
47
|
+
}
|
|
48
|
+
function setCurrentInstanceSafe(ctx) {
|
|
49
|
+
const reqCtx = getRequestContext();
|
|
50
|
+
const prev = reqCtx.currentComponentContext;
|
|
51
|
+
reqCtx.currentComponentContext = ctx;
|
|
52
|
+
return prev;
|
|
53
|
+
}
|
|
54
|
+
function getCurrentSuspenseBoundarySafe() {
|
|
55
|
+
return getRequestContext().currentSuspenseBoundary;
|
|
56
|
+
}
|
|
57
|
+
function setCurrentSuspenseBoundarySafe(boundary) {
|
|
58
|
+
const reqCtx = getRequestContext();
|
|
59
|
+
const prev = reqCtx.currentSuspenseBoundary;
|
|
60
|
+
reqCtx.currentSuspenseBoundary = boundary;
|
|
61
|
+
return prev;
|
|
62
|
+
}
|
|
63
|
+
function runInRequestScope(fn) {
|
|
64
|
+
if (asyncLocalStorage) return asyncLocalStorage.run({
|
|
65
|
+
currentComponentContext: null,
|
|
66
|
+
currentSuspenseBoundary: null
|
|
67
|
+
}, fn);
|
|
68
|
+
return fn();
|
|
69
|
+
}
|
|
70
|
+
function hasRequestIsolation() {
|
|
71
|
+
return asyncLocalStorage !== null;
|
|
72
|
+
}
|
|
73
|
+
var currentComponentContext = null;
|
|
74
|
+
function getCurrentInstance() {
|
|
75
|
+
return getCurrentInstanceSafe() ?? currentComponentContext;
|
|
76
|
+
}
|
|
77
|
+
function setCurrentInstance(ctx) {
|
|
78
|
+
const prevSafe = setCurrentInstanceSafe(ctx);
|
|
79
|
+
const prevModule = currentComponentContext;
|
|
80
|
+
currentComponentContext = ctx;
|
|
81
|
+
return prevSafe ?? prevModule;
|
|
82
|
+
}
|
|
83
|
+
function onMounted(fn) {
|
|
84
|
+
if (currentComponentContext) currentComponentContext.onMounted(fn);
|
|
85
|
+
else console.warn("onMounted called outside of component setup");
|
|
86
|
+
}
|
|
87
|
+
function onUnmounted(fn) {
|
|
88
|
+
if (currentComponentContext) currentComponentContext.onUnmounted(fn);
|
|
89
|
+
else console.warn("onUnmounted called outside of component setup");
|
|
90
|
+
}
|
|
91
|
+
function onCreated(fn) {
|
|
92
|
+
if (currentComponentContext) currentComponentContext.onCreated(fn);
|
|
93
|
+
else console.warn("onCreated called outside of component setup");
|
|
94
|
+
}
|
|
95
|
+
function onUpdated(fn) {
|
|
96
|
+
if (currentComponentContext) currentComponentContext.onUpdated(fn);
|
|
97
|
+
else console.warn("onUpdated called outside of component setup");
|
|
98
|
+
}
|
|
99
|
+
var componentRegistry = /* @__PURE__ */ new Map();
|
|
100
|
+
function getComponentMeta(factory) {
|
|
101
|
+
return componentRegistry.get(factory);
|
|
102
|
+
}
|
|
103
|
+
function createPropsProxy(target, onAccess) {
|
|
104
|
+
return new Proxy(target, { get(obj, prop) {
|
|
105
|
+
if (typeof prop === "string" && onAccess) onAccess(prop);
|
|
106
|
+
return obj[prop];
|
|
107
|
+
} });
|
|
108
|
+
}
|
|
109
|
+
function component(setup, options) {
|
|
110
|
+
const factory = function(props) {
|
|
111
|
+
return {
|
|
112
|
+
type: factory,
|
|
113
|
+
props: props || {},
|
|
114
|
+
key: props?.key || null,
|
|
115
|
+
children: [],
|
|
116
|
+
dom: null
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
factory.__setup = setup;
|
|
120
|
+
factory.__name = options?.name;
|
|
121
|
+
factory.__props = null;
|
|
122
|
+
factory.__events = null;
|
|
123
|
+
factory.__ref = null;
|
|
124
|
+
factory.__slots = null;
|
|
125
|
+
componentRegistry.set(factory, {
|
|
126
|
+
name: options?.name,
|
|
127
|
+
setup
|
|
128
|
+
});
|
|
129
|
+
getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
|
|
130
|
+
return factory;
|
|
131
|
+
}
|
|
132
|
+
var globalInstances = /* @__PURE__ */ new Map();
|
|
133
|
+
var appContextToken = Symbol("sigx:appContext");
|
|
134
|
+
function lookupProvided(token) {
|
|
135
|
+
const ctx = getCurrentInstance();
|
|
136
|
+
if (!ctx) return;
|
|
137
|
+
let current = ctx;
|
|
138
|
+
while (current) {
|
|
139
|
+
if (current.provides && current.provides.has(token)) return current.provides.get(token);
|
|
140
|
+
current = current.parent;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function provideAtComponent(token, value) {
|
|
144
|
+
const ctx = getCurrentInstance();
|
|
145
|
+
if (!ctx) throw new Error("defineProvide must be called inside a component setup function");
|
|
146
|
+
if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
|
|
147
|
+
ctx.provides.set(token, value);
|
|
148
|
+
}
|
|
149
|
+
function defineInjectable(factory) {
|
|
150
|
+
const token = Symbol();
|
|
151
|
+
const useFn = (() => {
|
|
152
|
+
const provided = lookupProvided(token);
|
|
153
|
+
if (provided !== void 0) return provided;
|
|
154
|
+
if (!globalInstances.has(token)) globalInstances.set(token, factory());
|
|
155
|
+
return globalInstances.get(token);
|
|
156
|
+
});
|
|
157
|
+
useFn._factory = factory;
|
|
158
|
+
useFn._token = token;
|
|
159
|
+
return useFn;
|
|
160
|
+
}
|
|
161
|
+
function defineProvide(useFn, factory) {
|
|
162
|
+
const actualFactory = factory ?? useFn._factory;
|
|
163
|
+
const token = useFn._token;
|
|
164
|
+
if (!actualFactory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
|
|
165
|
+
const instance = actualFactory();
|
|
166
|
+
provideAtComponent(token, instance);
|
|
167
|
+
return instance;
|
|
168
|
+
}
|
|
169
|
+
function useAppContext() {
|
|
170
|
+
return lookupProvided(appContextToken) ?? null;
|
|
171
|
+
}
|
|
172
|
+
function getAppContextToken() {
|
|
173
|
+
return appContextToken;
|
|
174
|
+
}
|
|
175
|
+
function provideAppContext(ctx, appContext) {
|
|
176
|
+
if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
|
|
177
|
+
ctx.provides.set(appContextToken, appContext);
|
|
178
|
+
if (appContext.provides) for (const [token, value] of appContext.provides) ctx.provides.set(token, value);
|
|
179
|
+
}
|
|
180
|
+
const __DIRECTIVE__ = Symbol.for("sigx.directive");
|
|
181
|
+
function defineDirective(definition) {
|
|
182
|
+
definition[__DIRECTIVE__] = true;
|
|
183
|
+
return definition;
|
|
184
|
+
}
|
|
185
|
+
function isDirective(value) {
|
|
186
|
+
return value != null && typeof value === "object" && value[__DIRECTIVE__] === true;
|
|
187
|
+
}
|
|
188
|
+
var isDev = typeof process !== "undefined" && process.env.NODE_ENV !== "production" || true;
|
|
189
|
+
var defaultMountFn = null;
|
|
74
190
|
function setDefaultMount(mountFn) {
|
|
75
191
|
defaultMountFn = mountFn;
|
|
76
192
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Get the current default mount function.
|
|
79
|
-
* @internal
|
|
80
|
-
*/
|
|
81
193
|
function getDefaultMount() {
|
|
82
194
|
return defaultMountFn;
|
|
83
195
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Create an application instance.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```tsx
|
|
89
|
-
* import { defineApp, defineInjectable } from '@sigx/runtime-core';
|
|
90
|
-
* import { render } from '@sigx/runtime-dom';
|
|
91
|
-
*
|
|
92
|
-
* // Define an injectable service
|
|
93
|
-
* const useApiConfig = defineInjectable(() => ({ baseUrl: 'https://api.example.com' }));
|
|
94
|
-
*
|
|
95
|
-
* const app = defineApp(<App />);
|
|
96
|
-
*
|
|
97
|
-
* app.use(myPlugin, { option: 'value' });
|
|
98
|
-
*
|
|
99
|
-
* // Provide using the injectable token (works with inject())
|
|
100
|
-
* app.provide(useApiConfig, { baseUrl: 'https://custom.api.com' });
|
|
101
|
-
*
|
|
102
|
-
* app.mount(document.getElementById('app')!, render);
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
196
|
function defineApp(rootComponent) {
|
|
106
197
|
const installedPlugins = /* @__PURE__ */ new Set();
|
|
107
198
|
const context = {
|
|
108
199
|
app: null,
|
|
109
200
|
provides: /* @__PURE__ */ new Map(),
|
|
110
201
|
config: {},
|
|
111
|
-
hooks: []
|
|
202
|
+
hooks: [],
|
|
203
|
+
directives: /* @__PURE__ */ new Map()
|
|
112
204
|
};
|
|
113
205
|
let isMounted = false;
|
|
114
206
|
let container = null;
|
|
@@ -126,16 +218,26 @@ function defineApp(rootComponent) {
|
|
|
126
218
|
else if (isDev) console.warn("Invalid plugin: must be a function or have an install() method.");
|
|
127
219
|
return app;
|
|
128
220
|
},
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
221
|
+
defineProvide(useFn, factory) {
|
|
222
|
+
const actualFactory = factory ?? useFn._factory;
|
|
223
|
+
const token = useFn._token;
|
|
224
|
+
if (!actualFactory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
|
|
225
|
+
const instance = actualFactory();
|
|
226
|
+
context.provides.set(token, instance);
|
|
227
|
+
return instance;
|
|
134
228
|
},
|
|
135
229
|
hook(hooks) {
|
|
136
230
|
context.hooks.push(hooks);
|
|
137
231
|
return app;
|
|
138
232
|
},
|
|
233
|
+
directive(name, definition) {
|
|
234
|
+
if (definition !== void 0) {
|
|
235
|
+
if (isDev && !isDirective(definition)) console.warn(`[sigx] app.directive('${name}', ...) received a value that is not a valid directive definition. Use defineDirective() to create directive definitions.`);
|
|
236
|
+
context.directives.set(name, definition);
|
|
237
|
+
return app;
|
|
238
|
+
}
|
|
239
|
+
return context.directives.get(name);
|
|
240
|
+
},
|
|
139
241
|
mount(target, renderFn) {
|
|
140
242
|
if (isMounted) {
|
|
141
243
|
if (isDev) console.warn("App is already mounted. Call app.unmount() first.");
|
|
@@ -167,15 +269,16 @@ function defineApp(rootComponent) {
|
|
|
167
269
|
},
|
|
168
270
|
get _container() {
|
|
169
271
|
return container;
|
|
272
|
+
},
|
|
273
|
+
get _rootComponent() {
|
|
274
|
+
return rootComponent;
|
|
170
275
|
}
|
|
171
276
|
};
|
|
172
277
|
context.app = app;
|
|
278
|
+
const appContextToken = getAppContextToken();
|
|
279
|
+
context.provides.set(appContextToken, context);
|
|
173
280
|
return app;
|
|
174
281
|
}
|
|
175
|
-
/**
|
|
176
|
-
* Notify all app hooks that a component was created.
|
|
177
|
-
* Called by the renderer after setup() returns.
|
|
178
|
-
*/
|
|
179
282
|
function notifyComponentCreated(context, instance) {
|
|
180
283
|
if (!context) return;
|
|
181
284
|
for (const hooks of context.hooks) try {
|
|
@@ -184,10 +287,6 @@ function notifyComponentCreated(context, instance) {
|
|
|
184
287
|
handleHookError(context, err, instance, "onComponentCreated");
|
|
185
288
|
}
|
|
186
289
|
}
|
|
187
|
-
/**
|
|
188
|
-
* Notify all app hooks that a component was mounted.
|
|
189
|
-
* Called by the renderer after mount hooks run.
|
|
190
|
-
*/
|
|
191
290
|
function notifyComponentMounted(context, instance) {
|
|
192
291
|
if (!context) return;
|
|
193
292
|
for (const hooks of context.hooks) try {
|
|
@@ -196,10 +295,6 @@ function notifyComponentMounted(context, instance) {
|
|
|
196
295
|
handleHookError(context, err, instance, "onComponentMounted");
|
|
197
296
|
}
|
|
198
297
|
}
|
|
199
|
-
/**
|
|
200
|
-
* Notify all app hooks that a component was unmounted.
|
|
201
|
-
* Called by the renderer before cleanup.
|
|
202
|
-
*/
|
|
203
298
|
function notifyComponentUnmounted(context, instance) {
|
|
204
299
|
if (!context) return;
|
|
205
300
|
for (const hooks of context.hooks) try {
|
|
@@ -208,10 +303,6 @@ function notifyComponentUnmounted(context, instance) {
|
|
|
208
303
|
handleHookError(context, err, instance, "onComponentUnmounted");
|
|
209
304
|
}
|
|
210
305
|
}
|
|
211
|
-
/**
|
|
212
|
-
* Notify all app hooks that a component updated.
|
|
213
|
-
* Called by the renderer after re-render.
|
|
214
|
-
*/
|
|
215
306
|
function notifyComponentUpdated(context, instance) {
|
|
216
307
|
if (!context) return;
|
|
217
308
|
for (const hooks of context.hooks) try {
|
|
@@ -220,10 +311,6 @@ function notifyComponentUpdated(context, instance) {
|
|
|
220
311
|
handleHookError(context, err, instance, "onComponentUpdated");
|
|
221
312
|
}
|
|
222
313
|
}
|
|
223
|
-
/**
|
|
224
|
-
* Handle an error in a component. Returns true if the error was handled.
|
|
225
|
-
* Called by the renderer when an error occurs in setup or render.
|
|
226
|
-
*/
|
|
227
314
|
function handleComponentError(context, err, instance, info) {
|
|
228
315
|
if (!context) return false;
|
|
229
316
|
for (const hooks of context.hooks) try {
|
|
@@ -238,104 +325,53 @@ function handleComponentError(context, err, instance, info) {
|
|
|
238
325
|
}
|
|
239
326
|
return false;
|
|
240
327
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Handle errors that occur in hooks themselves
|
|
243
|
-
*/
|
|
244
328
|
function handleHookError(context, err, instance, hookName) {
|
|
245
329
|
console.error(`Error in ${hookName} hook:`, err);
|
|
246
330
|
if (context.config.errorHandler) try {
|
|
247
331
|
context.config.errorHandler(err, instance, `plugin hook: ${hookName}`);
|
|
248
332
|
} catch {}
|
|
249
333
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
//#region src/component.ts
|
|
253
|
-
let currentComponentContext = null;
|
|
254
|
-
function getCurrentInstance() {
|
|
255
|
-
return currentComponentContext;
|
|
256
|
-
}
|
|
257
|
-
function setCurrentInstance(ctx) {
|
|
258
|
-
const prev = currentComponentContext;
|
|
259
|
-
currentComponentContext = ctx;
|
|
260
|
-
return prev;
|
|
334
|
+
function compound(main, sub) {
|
|
335
|
+
return Object.assign(main, sub);
|
|
261
336
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
337
|
+
var MODEL_SYMBOL = Symbol.for("sigx.model");
|
|
338
|
+
function createModel(tuple, updateHandler) {
|
|
339
|
+
const [obj, key] = tuple;
|
|
340
|
+
return {
|
|
341
|
+
get value() {
|
|
342
|
+
return obj[key];
|
|
343
|
+
},
|
|
344
|
+
set value(v) {
|
|
345
|
+
updateHandler(v);
|
|
346
|
+
},
|
|
347
|
+
get binding() {
|
|
348
|
+
return [
|
|
349
|
+
obj,
|
|
350
|
+
key,
|
|
351
|
+
updateHandler
|
|
352
|
+
];
|
|
353
|
+
},
|
|
354
|
+
[MODEL_SYMBOL]: true
|
|
355
|
+
};
|
|
265
356
|
}
|
|
266
|
-
function
|
|
267
|
-
|
|
268
|
-
|
|
357
|
+
function createModelFromBinding(binding) {
|
|
358
|
+
const [obj, key, handler] = binding;
|
|
359
|
+
return createModel([obj, key], handler);
|
|
269
360
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
* Get component metadata (for DevTools)
|
|
273
|
-
*/
|
|
274
|
-
function getComponentMeta(factory) {
|
|
275
|
-
return componentRegistry.get(factory);
|
|
361
|
+
function isModel(value) {
|
|
362
|
+
return value !== null && typeof value === "object" && MODEL_SYMBOL in value && value[MODEL_SYMBOL] === true;
|
|
276
363
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
*/
|
|
280
|
-
function createPropsProxy(target, onAccess) {
|
|
281
|
-
return new Proxy(target, { get(obj, prop) {
|
|
282
|
-
if (typeof prop === "string" && onAccess) onAccess(prop);
|
|
283
|
-
return obj[prop];
|
|
284
|
-
} });
|
|
364
|
+
function getModelSymbol() {
|
|
365
|
+
return MODEL_SYMBOL;
|
|
285
366
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
*
|
|
289
|
-
* @param setup - Setup function that receives context and returns a render function
|
|
290
|
-
* @param options - Optional configuration (e.g., name for DevTools)
|
|
291
|
-
*
|
|
292
|
-
* @example
|
|
293
|
-
* ```tsx
|
|
294
|
-
* type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
|
|
295
|
-
*
|
|
296
|
-
* export const Card = defineComponent<CardProps>((ctx) => {
|
|
297
|
-
* const { title } = ctx.props;
|
|
298
|
-
* const { slots } = ctx;
|
|
299
|
-
*
|
|
300
|
-
* return () => (
|
|
301
|
-
* <div class="card">
|
|
302
|
-
* {slots.header?.() ?? <h2>{title}</h2>}
|
|
303
|
-
* {slots.default()}
|
|
304
|
-
* </div>
|
|
305
|
-
* );
|
|
306
|
-
* });
|
|
307
|
-
* ```
|
|
308
|
-
*/
|
|
309
|
-
function defineComponent(setup, options) {
|
|
310
|
-
const factory = function(props) {
|
|
311
|
-
return {
|
|
312
|
-
type: factory,
|
|
313
|
-
props: props || {},
|
|
314
|
-
key: props?.key || null,
|
|
315
|
-
children: [],
|
|
316
|
-
dom: null
|
|
317
|
-
};
|
|
318
|
-
};
|
|
319
|
-
factory.__setup = setup;
|
|
320
|
-
factory.__name = options?.name;
|
|
321
|
-
factory.__props = null;
|
|
322
|
-
factory.__events = null;
|
|
323
|
-
factory.__ref = null;
|
|
324
|
-
factory.__slots = null;
|
|
325
|
-
componentRegistry.set(factory, {
|
|
326
|
-
name: options?.name,
|
|
327
|
-
setup
|
|
328
|
-
});
|
|
329
|
-
getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
|
|
330
|
-
return factory;
|
|
367
|
+
function isComponent(type) {
|
|
368
|
+
return typeof type === "function" && "__setup" in type;
|
|
331
369
|
}
|
|
332
|
-
|
|
333
|
-
//#endregion
|
|
334
|
-
//#region src/jsx-runtime.ts
|
|
335
370
|
const Fragment = Symbol.for("sigx.Fragment");
|
|
336
371
|
const Text = Symbol.for("sigx.Text");
|
|
337
372
|
function normalizeChildren(children) {
|
|
338
373
|
if (children == null || children === false || children === true) return [];
|
|
374
|
+
if (isComputed(children)) return normalizeChildren(children.value);
|
|
339
375
|
if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren(c));
|
|
340
376
|
if (typeof children === "string" || typeof children === "number") return [{
|
|
341
377
|
type: Text,
|
|
@@ -348,64 +384,92 @@ function normalizeChildren(children) {
|
|
|
348
384
|
if (children.type) return [children];
|
|
349
385
|
return [];
|
|
350
386
|
}
|
|
351
|
-
/**
|
|
352
|
-
* Check if a type is a sigx component (has __setup)
|
|
353
|
-
*/
|
|
354
|
-
function isComponent$1(type) {
|
|
355
|
-
return typeof type === "function" && "__setup" in type;
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* Create a JSX element - this is the core function called by TSX transpilation
|
|
359
|
-
*/
|
|
360
387
|
function jsx(type, props, key) {
|
|
361
388
|
const processedProps = { ...props || {} };
|
|
389
|
+
const models = {};
|
|
390
|
+
const isComponentType = isComponent(type);
|
|
362
391
|
if (props) {
|
|
363
|
-
for (const propKey in props) if (propKey === "
|
|
364
|
-
let
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
392
|
+
for (const propKey in props) if (propKey === "model") {
|
|
393
|
+
let modelBinding = props[propKey];
|
|
394
|
+
let tuple = null;
|
|
395
|
+
let updateHandler = null;
|
|
396
|
+
if (isModel(modelBinding)) {
|
|
397
|
+
const [obj, key, handler] = modelBinding.binding;
|
|
398
|
+
tuple = [obj, key];
|
|
399
|
+
updateHandler = handler;
|
|
400
|
+
} else if (typeof modelBinding === "function") {
|
|
401
|
+
const detected = detectAccess(modelBinding);
|
|
402
|
+
if (detected && typeof detected[1] === "string") tuple = detected;
|
|
403
|
+
} else if (Array.isArray(modelBinding) && modelBinding.length === 2 && typeof modelBinding[1] === "string") tuple = modelBinding;
|
|
404
|
+
if (tuple) {
|
|
405
|
+
const [stateObj, stateKey] = tuple;
|
|
371
406
|
let handled = false;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
stateObj[key$1] = v;
|
|
407
|
+
if (!updateHandler) {
|
|
408
|
+
const existingHandler = processedProps["onUpdate:modelValue"];
|
|
409
|
+
updateHandler = (v) => {
|
|
410
|
+
const customHandler = stateObj[`onUpdate:${stateKey}`];
|
|
411
|
+
if (typeof customHandler === "function") customHandler(v);
|
|
412
|
+
else stateObj[stateKey] = v;
|
|
379
413
|
if (existingHandler) existingHandler(v);
|
|
380
414
|
};
|
|
381
415
|
}
|
|
382
|
-
|
|
416
|
+
const platformProcessor = getPlatformModelProcessor();
|
|
417
|
+
if (typeof type === "string" && platformProcessor) handled = platformProcessor(type, processedProps, tuple, props);
|
|
418
|
+
if (isComponentType) {
|
|
419
|
+
models.model = createModel(tuple, updateHandler);
|
|
420
|
+
processedProps["onUpdate:modelValue"] = updateHandler;
|
|
421
|
+
} else if (!handled) {
|
|
422
|
+
processedProps.modelValue = stateObj[stateKey];
|
|
423
|
+
processedProps["onUpdate:modelValue"] = updateHandler;
|
|
424
|
+
}
|
|
425
|
+
delete processedProps.model;
|
|
383
426
|
}
|
|
384
|
-
} else if (propKey.startsWith("
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
427
|
+
} else if (propKey.startsWith("model:")) {
|
|
428
|
+
let modelBinding = props[propKey];
|
|
429
|
+
const name = propKey.slice(6);
|
|
430
|
+
let tuple = null;
|
|
431
|
+
let updateHandler = null;
|
|
432
|
+
if (isModel(modelBinding)) {
|
|
433
|
+
const [obj, key, handler] = modelBinding.binding;
|
|
434
|
+
tuple = [obj, key];
|
|
435
|
+
updateHandler = handler;
|
|
436
|
+
} else if (typeof modelBinding === "function") {
|
|
437
|
+
const detected = detectAccess(modelBinding);
|
|
438
|
+
if (detected && typeof detected[1] === "string") tuple = detected;
|
|
439
|
+
} else if (Array.isArray(modelBinding) && modelBinding.length === 2 && typeof modelBinding[1] === "string") tuple = modelBinding;
|
|
440
|
+
if (tuple) {
|
|
441
|
+
const [stateObj, stateKey] = tuple;
|
|
390
442
|
const eventName = `onUpdate:${name}`;
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
443
|
+
if (!updateHandler) {
|
|
444
|
+
const existingHandler = processedProps[eventName];
|
|
445
|
+
updateHandler = (v) => {
|
|
446
|
+
const customHandler = stateObj[`onUpdate:${stateKey}`];
|
|
447
|
+
if (typeof customHandler === "function") customHandler(v);
|
|
448
|
+
else stateObj[stateKey] = v;
|
|
449
|
+
if (existingHandler) existingHandler(v);
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
if (isComponentType) {
|
|
453
|
+
models[name] = createModel(tuple, updateHandler);
|
|
454
|
+
processedProps[eventName] = updateHandler;
|
|
455
|
+
} else {
|
|
456
|
+
processedProps[name] = stateObj[stateKey];
|
|
457
|
+
processedProps[eventName] = updateHandler;
|
|
458
|
+
}
|
|
396
459
|
delete processedProps[propKey];
|
|
397
460
|
}
|
|
398
461
|
}
|
|
399
462
|
}
|
|
400
|
-
if (
|
|
401
|
-
|
|
463
|
+
if (Object.keys(models).length > 0) processedProps.$models = models;
|
|
464
|
+
if (isComponent(type)) {
|
|
465
|
+
const { children, ...rest } = processedProps;
|
|
402
466
|
return {
|
|
403
467
|
type,
|
|
404
468
|
props: {
|
|
405
|
-
...rest
|
|
406
|
-
children
|
|
469
|
+
...rest,
|
|
470
|
+
children
|
|
407
471
|
},
|
|
408
|
-
key: key || rest
|
|
472
|
+
key: key || rest.key || null,
|
|
409
473
|
children: [],
|
|
410
474
|
dom: null
|
|
411
475
|
};
|
|
@@ -420,29 +484,13 @@ function jsx(type, props, key) {
|
|
|
420
484
|
dom: null
|
|
421
485
|
};
|
|
422
486
|
}
|
|
423
|
-
/**
|
|
424
|
-
* JSX Factory for fragments
|
|
425
|
-
*/
|
|
426
487
|
function jsxs(type, props, key) {
|
|
427
488
|
return jsx(type, props, key);
|
|
428
489
|
}
|
|
429
490
|
const jsxDEV = jsx;
|
|
430
|
-
|
|
431
|
-
//#endregion
|
|
432
|
-
//#region src/lazy.tsx
|
|
433
|
-
/**
|
|
434
|
-
* Lazy loading utilities for sigx components.
|
|
435
|
-
*
|
|
436
|
-
* Provides runtime-only lazy loading with no build dependencies.
|
|
437
|
-
* Works with any bundler that supports dynamic import().
|
|
438
|
-
*/
|
|
439
|
-
let currentSuspenseBoundary = null;
|
|
440
|
-
/**
|
|
441
|
-
* Register a promise with the current Suspense boundary
|
|
442
|
-
* @internal
|
|
443
|
-
*/
|
|
491
|
+
var currentSuspenseBoundary = null;
|
|
444
492
|
function registerPendingPromise(promise) {
|
|
445
|
-
const boundary = currentSuspenseBoundary;
|
|
493
|
+
const boundary = getCurrentSuspenseBoundarySafe() ?? currentSuspenseBoundary;
|
|
446
494
|
if (boundary) {
|
|
447
495
|
boundary.pending.add(promise);
|
|
448
496
|
promise.finally(() => {
|
|
@@ -453,39 +501,12 @@ function registerPendingPromise(promise) {
|
|
|
453
501
|
}
|
|
454
502
|
return false;
|
|
455
503
|
}
|
|
456
|
-
/**
|
|
457
|
-
* Create a lazy-loaded component wrapper.
|
|
458
|
-
*
|
|
459
|
-
* The component will be loaded on first render. Use with `<Suspense>` to show
|
|
460
|
-
* a fallback while loading.
|
|
461
|
-
*
|
|
462
|
-
* @param loader - Function that returns a Promise resolving to the component
|
|
463
|
-
* @returns A component factory that loads the real component on demand
|
|
464
|
-
*
|
|
465
|
-
* @example
|
|
466
|
-
* ```tsx
|
|
467
|
-
* import { lazy, Suspense } from 'sigx';
|
|
468
|
-
*
|
|
469
|
-
* // Component will be in a separate chunk
|
|
470
|
-
* const HeavyChart = lazy(() => import('./components/HeavyChart'));
|
|
471
|
-
*
|
|
472
|
-
* // Usage
|
|
473
|
-
* <Suspense fallback={<Spinner />}>
|
|
474
|
-
* <HeavyChart data={chartData} />
|
|
475
|
-
* </Suspense>
|
|
476
|
-
*
|
|
477
|
-
* // Preload on hover
|
|
478
|
-
* <button onMouseEnter={() => HeavyChart.preload()}>
|
|
479
|
-
* Show Chart
|
|
480
|
-
* </button>
|
|
481
|
-
* ```
|
|
482
|
-
*/
|
|
483
504
|
function lazy(loader) {
|
|
484
505
|
let Component = null;
|
|
485
506
|
let promise = null;
|
|
486
507
|
let error = null;
|
|
487
508
|
let state = "pending";
|
|
488
|
-
const LazyWrapper =
|
|
509
|
+
const LazyWrapper = component((ctx) => {
|
|
489
510
|
const loadState = ctx.signal({
|
|
490
511
|
state,
|
|
491
512
|
tick: 0
|
|
@@ -534,30 +555,7 @@ function lazy(loader) {
|
|
|
534
555
|
};
|
|
535
556
|
return LazyWrapper;
|
|
536
557
|
}
|
|
537
|
-
|
|
538
|
-
* Suspense boundary component for handling async loading states.
|
|
539
|
-
*
|
|
540
|
-
* Wraps lazy-loaded components and shows a fallback while they load.
|
|
541
|
-
*
|
|
542
|
-
* @example
|
|
543
|
-
* ```tsx
|
|
544
|
-
* import { lazy, Suspense } from 'sigx';
|
|
545
|
-
*
|
|
546
|
-
* const LazyDashboard = lazy(() => import('./Dashboard'));
|
|
547
|
-
*
|
|
548
|
-
* // Basic usage
|
|
549
|
-
* <Suspense fallback={<div>Loading...</div>}>
|
|
550
|
-
* <LazyDashboard />
|
|
551
|
-
* </Suspense>
|
|
552
|
-
*
|
|
553
|
-
* // With spinner component
|
|
554
|
-
* <Suspense fallback={<Spinner size="large" />}>
|
|
555
|
-
* <LazyDashboard />
|
|
556
|
-
* <LazyCharts />
|
|
557
|
-
* </Suspense>
|
|
558
|
-
* ```
|
|
559
|
-
*/
|
|
560
|
-
const Suspense = defineComponent((ctx) => {
|
|
558
|
+
const Suspense = component((ctx) => {
|
|
561
559
|
const { props, slots } = ctx;
|
|
562
560
|
const state = ctx.signal({
|
|
563
561
|
isReady: false,
|
|
@@ -570,14 +568,15 @@ const Suspense = defineComponent((ctx) => {
|
|
|
570
568
|
if (boundary.pending.size === 0) state.isReady = true;
|
|
571
569
|
}
|
|
572
570
|
};
|
|
573
|
-
ctx.
|
|
571
|
+
ctx.onMounted(() => {
|
|
574
572
|
if (boundary.pending.size === 0) state.isReady = true;
|
|
575
573
|
});
|
|
576
574
|
return () => {
|
|
577
575
|
state.isReady;
|
|
578
576
|
state.pendingCount;
|
|
579
|
-
const prevBoundary = currentSuspenseBoundary;
|
|
577
|
+
const prevBoundary = getCurrentSuspenseBoundarySafe() ?? currentSuspenseBoundary;
|
|
580
578
|
currentSuspenseBoundary = boundary;
|
|
579
|
+
setCurrentSuspenseBoundarySafe(boundary);
|
|
581
580
|
try {
|
|
582
581
|
const children = slots.default();
|
|
583
582
|
if (boundary.pending.size > 0) {
|
|
@@ -602,18 +601,41 @@ const Suspense = defineComponent((ctx) => {
|
|
|
602
601
|
throw err;
|
|
603
602
|
} finally {
|
|
604
603
|
currentSuspenseBoundary = prevBoundary;
|
|
604
|
+
setCurrentSuspenseBoundarySafe(prevBoundary);
|
|
605
605
|
}
|
|
606
606
|
};
|
|
607
607
|
}, { name: "Suspense" });
|
|
608
|
-
/**
|
|
609
|
-
* Check if a component is a lazy-loaded component
|
|
610
|
-
*/
|
|
611
608
|
function isLazyComponent(component) {
|
|
612
609
|
return component && component.__lazy === true;
|
|
613
610
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
611
|
+
const ErrorBoundary = component((ctx) => {
|
|
612
|
+
const { fallback } = ctx.props;
|
|
613
|
+
const { slots } = ctx;
|
|
614
|
+
const state = ctx.signal({
|
|
615
|
+
hasError: false,
|
|
616
|
+
error: null
|
|
617
|
+
});
|
|
618
|
+
const retry = () => {
|
|
619
|
+
state.hasError = false;
|
|
620
|
+
state.error = null;
|
|
621
|
+
};
|
|
622
|
+
return () => {
|
|
623
|
+
if (state.hasError && state.error) {
|
|
624
|
+
if (typeof fallback === "function") return fallback(state.error, retry);
|
|
625
|
+
return fallback ?? null;
|
|
626
|
+
}
|
|
627
|
+
try {
|
|
628
|
+
return slots.default();
|
|
629
|
+
} catch (e) {
|
|
630
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
631
|
+
state.hasError = true;
|
|
632
|
+
state.error = error;
|
|
633
|
+
if (process.env.NODE_ENV !== "production") console.error("[ErrorBoundary] Caught error during render:", error);
|
|
634
|
+
if (typeof fallback === "function") return fallback(error, retry);
|
|
635
|
+
return fallback ?? null;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
}, { name: "ErrorBoundary" });
|
|
617
639
|
var Utils = class {
|
|
618
640
|
static isPromise(value) {
|
|
619
641
|
return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
@@ -625,92 +647,29 @@ function guid$1() {
|
|
|
625
647
|
return (c == "x" ? r : r & 3 | 8).toString(16);
|
|
626
648
|
});
|
|
627
649
|
}
|
|
628
|
-
|
|
629
|
-
//#endregion
|
|
630
|
-
//#region src/utils/props-accessor.ts
|
|
631
|
-
/**
|
|
632
|
-
* Creates a props accessor that can be called with defaults or accessed directly.
|
|
633
|
-
* After calling with defaults, direct property access uses those defaults.
|
|
634
|
-
*
|
|
635
|
-
* @example
|
|
636
|
-
* ```ts
|
|
637
|
-
* // In component setup:
|
|
638
|
-
* const props = createPropsAccessor(reactiveProps);
|
|
639
|
-
*
|
|
640
|
-
* // Set defaults
|
|
641
|
-
* props({ count: 0, label: 'Default' });
|
|
642
|
-
*
|
|
643
|
-
* // Access props (falls back to defaults if not provided)
|
|
644
|
-
* const count = props.count;
|
|
645
|
-
* ```
|
|
646
|
-
*/
|
|
647
650
|
function createPropsAccessor(reactiveProps) {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
get(_, key) {
|
|
651
|
+
return new Proxy(reactiveProps, {
|
|
652
|
+
get(target, key) {
|
|
651
653
|
if (typeof key === "symbol") return void 0;
|
|
652
|
-
|
|
653
|
-
return value != null ? value : defaults[key];
|
|
654
|
+
return target[key];
|
|
654
655
|
},
|
|
655
|
-
|
|
656
|
-
if (args[0] && typeof args[0] === "object") defaults = {
|
|
657
|
-
...defaults,
|
|
658
|
-
...args[0]
|
|
659
|
-
};
|
|
660
|
-
return proxy;
|
|
661
|
-
},
|
|
662
|
-
has(_, key) {
|
|
656
|
+
has(target, key) {
|
|
663
657
|
if (typeof key === "symbol") return false;
|
|
664
|
-
return key in
|
|
658
|
+
return key in target;
|
|
665
659
|
},
|
|
666
|
-
ownKeys() {
|
|
667
|
-
return
|
|
660
|
+
ownKeys(target) {
|
|
661
|
+
return Object.keys(target);
|
|
668
662
|
},
|
|
669
|
-
getOwnPropertyDescriptor(
|
|
663
|
+
getOwnPropertyDescriptor(target, key) {
|
|
670
664
|
if (typeof key === "symbol") return void 0;
|
|
671
|
-
if (key in
|
|
665
|
+
if (key in target) return {
|
|
672
666
|
enumerable: true,
|
|
673
667
|
configurable: true,
|
|
674
668
|
writable: false
|
|
675
669
|
};
|
|
676
670
|
}
|
|
677
671
|
});
|
|
678
|
-
return proxy;
|
|
679
672
|
}
|
|
680
|
-
|
|
681
|
-
//#endregion
|
|
682
|
-
//#region src/utils/slots.ts
|
|
683
|
-
/**
|
|
684
|
-
* Slots system for component children.
|
|
685
|
-
* Supports default and named slots with reactivity.
|
|
686
|
-
*/
|
|
687
|
-
/**
|
|
688
|
-
* Create slots object from children and slots prop.
|
|
689
|
-
* Uses a version signal to trigger re-renders when children change.
|
|
690
|
-
*
|
|
691
|
-
* Supports named slots via:
|
|
692
|
-
* - `slots` prop object (e.g., `slots={{ header: () => <div>...</div> }}`)
|
|
693
|
-
* - `slot` prop on children (e.g., `<div slot="header">...</div>`)
|
|
694
|
-
*
|
|
695
|
-
* @example
|
|
696
|
-
* ```tsx
|
|
697
|
-
* // Parent component
|
|
698
|
-
* <Card slots={{ header: () => <h1>Title</h1> }}>
|
|
699
|
-
* <p>Default content</p>
|
|
700
|
-
* <span slot="footer">Footer text</span>
|
|
701
|
-
* </Card>
|
|
702
|
-
*
|
|
703
|
-
* // Card component setup
|
|
704
|
-
* const slots = createSlots(children, slotsFromProps);
|
|
705
|
-
* return () => (
|
|
706
|
-
* <div>
|
|
707
|
-
* {slots.header()}
|
|
708
|
-
* {slots.default()}
|
|
709
|
-
* {slots.footer()}
|
|
710
|
-
* </div>
|
|
711
|
-
* );
|
|
712
|
-
* ```
|
|
713
|
-
*/
|
|
714
673
|
function createSlots(children, slotsFromProps) {
|
|
715
674
|
const versionSignal = signal$1({ v: 0 });
|
|
716
675
|
function extractNamedSlotsFromChildren(c) {
|
|
@@ -757,37 +716,6 @@ function createSlots(children, slotsFromProps) {
|
|
|
757
716
|
};
|
|
758
717
|
} });
|
|
759
718
|
}
|
|
760
|
-
|
|
761
|
-
//#endregion
|
|
762
|
-
//#region src/utils/normalize.ts
|
|
763
|
-
/**
|
|
764
|
-
* VNode normalization utilities.
|
|
765
|
-
* Converts render results into proper VNode structures.
|
|
766
|
-
*/
|
|
767
|
-
/**
|
|
768
|
-
* Normalize render result to a VNode (wrapping arrays in Fragment).
|
|
769
|
-
* Handles null, undefined, false, true by returning an empty Text node.
|
|
770
|
-
*
|
|
771
|
-
* This is used to normalize the return value of component render functions
|
|
772
|
-
* into a consistent VNode structure for the renderer to process.
|
|
773
|
-
*
|
|
774
|
-
* @example
|
|
775
|
-
* ```ts
|
|
776
|
-
* // Conditional rendering returns null/false
|
|
777
|
-
* normalizeSubTree(null) // → empty Text node
|
|
778
|
-
* normalizeSubTree(false) // → empty Text node
|
|
779
|
-
*
|
|
780
|
-
* // Arrays become Fragments
|
|
781
|
-
* normalizeSubTree([<A/>, <B/>]) // → Fragment with children
|
|
782
|
-
*
|
|
783
|
-
* // Primitives become Text nodes
|
|
784
|
-
* normalizeSubTree("hello") // → Text node
|
|
785
|
-
* normalizeSubTree(42) // → Text node
|
|
786
|
-
*
|
|
787
|
-
* // VNodes pass through
|
|
788
|
-
* normalizeSubTree(<div/>) // → same VNode
|
|
789
|
-
* ```
|
|
790
|
-
*/
|
|
791
719
|
function normalizeSubTree(result) {
|
|
792
720
|
if (result == null || result === false || result === true) return {
|
|
793
721
|
type: Text,
|
|
@@ -797,6 +725,7 @@ function normalizeSubTree(result) {
|
|
|
797
725
|
dom: null,
|
|
798
726
|
text: ""
|
|
799
727
|
};
|
|
728
|
+
if (isComputed(result)) return normalizeSubTree(result.value);
|
|
800
729
|
if (Array.isArray(result)) return {
|
|
801
730
|
type: Fragment,
|
|
802
731
|
props: {},
|
|
@@ -814,22 +743,16 @@ function normalizeSubTree(result) {
|
|
|
814
743
|
};
|
|
815
744
|
return result;
|
|
816
745
|
}
|
|
817
|
-
|
|
818
|
-
//#endregion
|
|
819
|
-
//#region src/models/index.ts
|
|
820
746
|
const guid = guid$1;
|
|
821
|
-
let InstanceLifetimes = /* @__PURE__ */ function(InstanceLifetimes
|
|
822
|
-
InstanceLifetimes
|
|
823
|
-
InstanceLifetimes
|
|
824
|
-
InstanceLifetimes
|
|
825
|
-
return InstanceLifetimes
|
|
747
|
+
let InstanceLifetimes = /* @__PURE__ */ function(InstanceLifetimes) {
|
|
748
|
+
InstanceLifetimes[InstanceLifetimes["Transient"] = 0] = "Transient";
|
|
749
|
+
InstanceLifetimes[InstanceLifetimes["Scoped"] = 1] = "Scoped";
|
|
750
|
+
InstanceLifetimes[InstanceLifetimes["Singleton"] = 2] = "Singleton";
|
|
751
|
+
return InstanceLifetimes;
|
|
826
752
|
}({});
|
|
827
753
|
function valueOf(obj) {
|
|
828
754
|
return obj;
|
|
829
755
|
}
|
|
830
|
-
|
|
831
|
-
//#endregion
|
|
832
|
-
//#region src/messaging/index.ts
|
|
833
756
|
function createTopic(options) {
|
|
834
757
|
let subscribers = [];
|
|
835
758
|
const publish = (data) => {
|
|
@@ -842,7 +765,7 @@ function createTopic(options) {
|
|
|
842
765
|
if (idx > -1) subscribers.splice(idx, 1);
|
|
843
766
|
};
|
|
844
767
|
try {
|
|
845
|
-
|
|
768
|
+
onUnmounted(unsubscribe);
|
|
846
769
|
} catch (e) {}
|
|
847
770
|
return { unsubscribe };
|
|
848
771
|
};
|
|
@@ -858,72 +781,10 @@ function createTopic(options) {
|
|
|
858
781
|
function toSubscriber(topic) {
|
|
859
782
|
return { subscribe: (handler) => topic.subscribe(handler) };
|
|
860
783
|
}
|
|
861
|
-
|
|
862
|
-
//#endregion
|
|
863
|
-
//#region src/di/injectable.ts
|
|
864
|
-
function inject(token) {
|
|
865
|
-
const ctx = getCurrentInstance();
|
|
866
|
-
if (!ctx) return void 0;
|
|
867
|
-
let current = ctx;
|
|
868
|
-
while (current) {
|
|
869
|
-
if (current.provides && current.provides.has(token)) return current.provides.get(token);
|
|
870
|
-
current = current.parent;
|
|
871
|
-
}
|
|
872
|
-
const appContext = getAppContext(ctx);
|
|
873
|
-
if (appContext && appContext.provides.has(token)) return appContext.provides.get(token);
|
|
874
|
-
}
|
|
875
|
-
/**
|
|
876
|
-
* Get the app context from the current component context
|
|
877
|
-
*/
|
|
878
|
-
function getAppContext(ctx) {
|
|
879
|
-
let current = ctx;
|
|
880
|
-
while (current) {
|
|
881
|
-
if (current._appContext) return current._appContext;
|
|
882
|
-
current = current.parent;
|
|
883
|
-
}
|
|
884
|
-
return null;
|
|
885
|
-
}
|
|
886
|
-
/**
|
|
887
|
-
* Inject the App instance (useful for plugins)
|
|
888
|
-
*/
|
|
889
|
-
function injectApp() {
|
|
890
|
-
return inject(AppContextKey);
|
|
891
|
-
}
|
|
892
|
-
function provide(token, value) {
|
|
893
|
-
const ctx = getCurrentInstance();
|
|
894
|
-
if (!ctx) {
|
|
895
|
-
console.warn("provide called outside of component setup");
|
|
896
|
-
return;
|
|
897
|
-
}
|
|
898
|
-
if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
|
|
899
|
-
ctx.provides.set(token, value);
|
|
900
|
-
}
|
|
901
|
-
const globalInstances = /* @__PURE__ */ new Map();
|
|
902
|
-
function defineInjectable(factory) {
|
|
903
|
-
const token = factory;
|
|
904
|
-
const useFn = () => {
|
|
905
|
-
const injected = inject(token);
|
|
906
|
-
if (injected) return injected;
|
|
907
|
-
if (!globalInstances.has(token)) globalInstances.set(token, factory());
|
|
908
|
-
return globalInstances.get(token);
|
|
909
|
-
};
|
|
910
|
-
useFn._factory = factory;
|
|
911
|
-
useFn._token = token;
|
|
912
|
-
return useFn;
|
|
913
|
-
}
|
|
914
|
-
function defineProvide(useFn) {
|
|
915
|
-
const factory = useFn._factory;
|
|
916
|
-
const token = useFn._token;
|
|
917
|
-
if (!factory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
|
|
918
|
-
const instance = factory();
|
|
919
|
-
provide(token, instance);
|
|
920
|
-
return instance;
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
//#endregion
|
|
924
|
-
//#region src/di/factory.ts
|
|
925
784
|
var SubscriptionHandler = class {
|
|
926
|
-
|
|
785
|
+
constructor() {
|
|
786
|
+
this.unsubs = [];
|
|
787
|
+
}
|
|
927
788
|
add(unsub) {
|
|
928
789
|
this.unsubs.push(unsub);
|
|
929
790
|
}
|
|
@@ -949,7 +810,7 @@ function defineFactory(setup, lifetime, typeIdentifier) {
|
|
|
949
810
|
};
|
|
950
811
|
if (customDispose) customDispose(dispose);
|
|
951
812
|
else try {
|
|
952
|
-
|
|
813
|
+
onUnmounted(() => dispose());
|
|
953
814
|
} catch (e) {}
|
|
954
815
|
return {
|
|
955
816
|
...result,
|
|
@@ -959,158 +820,62 @@ function defineFactory(setup, lifetime, typeIdentifier) {
|
|
|
959
820
|
if (setup.length <= 1) return defineInjectable(() => factoryCreator());
|
|
960
821
|
return factoryCreator;
|
|
961
822
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
});
|
|
984
|
-
if (!result.name) result.name = id;
|
|
985
|
-
return result;
|
|
986
|
-
}, lifetime);
|
|
987
|
-
}
|
|
988
|
-
function defineActions(actions, storeInstanceName, messages) {
|
|
989
|
-
const events = {};
|
|
990
|
-
const namespace = `${storeInstanceName}.actions.${guid()}`;
|
|
991
|
-
const onDispatching = {};
|
|
992
|
-
const onDispatched = {};
|
|
993
|
-
const onFailure = {};
|
|
994
|
-
const result = {
|
|
995
|
-
onDispatching,
|
|
996
|
-
onDispatched,
|
|
997
|
-
onFailure
|
|
823
|
+
const CLIENT_DIRECTIVE_PREFIX = "client:";
|
|
824
|
+
const CLIENT_DIRECTIVES = [
|
|
825
|
+
"client:load",
|
|
826
|
+
"client:idle",
|
|
827
|
+
"client:visible",
|
|
828
|
+
"client:media",
|
|
829
|
+
"client:only"
|
|
830
|
+
];
|
|
831
|
+
function filterClientDirectives(props) {
|
|
832
|
+
const filtered = {};
|
|
833
|
+
for (const key in props) if (!key.startsWith("client:")) filtered[key] = props[key];
|
|
834
|
+
return filtered;
|
|
835
|
+
}
|
|
836
|
+
function getHydrationDirective(props) {
|
|
837
|
+
if (props["client:load"] !== void 0) return { strategy: "load" };
|
|
838
|
+
if (props["client:idle"] !== void 0) return { strategy: "idle" };
|
|
839
|
+
if (props["client:visible"] !== void 0) return { strategy: "visible" };
|
|
840
|
+
if (props["client:only"] !== void 0) return { strategy: "only" };
|
|
841
|
+
if (props["client:media"] !== void 0) return {
|
|
842
|
+
strategy: "media",
|
|
843
|
+
media: props["client:media"]
|
|
998
844
|
};
|
|
999
|
-
|
|
1000
|
-
const name = `${actionName}.${type}`;
|
|
1001
|
-
if (!events[name]) {
|
|
1002
|
-
events[name] = createTopic({
|
|
1003
|
-
namespace,
|
|
1004
|
-
name
|
|
1005
|
-
});
|
|
1006
|
-
messages.push(events[name]);
|
|
1007
|
-
}
|
|
1008
|
-
return events[name];
|
|
1009
|
-
}
|
|
1010
|
-
Object.keys(actions).forEach((actionName) => {
|
|
1011
|
-
onDispatching[actionName] = { subscribe: (fn) => {
|
|
1012
|
-
return getEvent(actionName, "onDispatching").subscribe(function() {
|
|
1013
|
-
fn.apply(this, arguments[0]);
|
|
1014
|
-
});
|
|
1015
|
-
} };
|
|
1016
|
-
onDispatched[actionName] = { subscribe: (fn) => {
|
|
1017
|
-
return getEvent(actionName, "onDispatched").subscribe(function() {
|
|
1018
|
-
const msg = arguments[0];
|
|
1019
|
-
const allArguments = [msg.result].concat(Array.from(msg.args));
|
|
1020
|
-
fn.apply(this, allArguments);
|
|
1021
|
-
});
|
|
1022
|
-
} };
|
|
1023
|
-
onFailure[actionName] = { subscribe: (fn) => {
|
|
1024
|
-
return getEvent(actionName, "onFailure").subscribe(function() {
|
|
1025
|
-
const msg = arguments[0];
|
|
1026
|
-
const allArguments = [msg.reason].concat(Array.from(msg.args));
|
|
1027
|
-
fn.apply(this, allArguments);
|
|
1028
|
-
});
|
|
1029
|
-
} };
|
|
1030
|
-
result[actionName] = function() {
|
|
1031
|
-
try {
|
|
1032
|
-
const currentArguments = arguments;
|
|
1033
|
-
getEvent(actionName, "onDispatching").publish(currentArguments);
|
|
1034
|
-
const returnedResult = actions[actionName].apply(this, currentArguments);
|
|
1035
|
-
if (Utils.isPromise(returnedResult)) returnedResult.then((result$1) => {
|
|
1036
|
-
getEvent(actionName, "onDispatched").publish({
|
|
1037
|
-
result: returnedResult,
|
|
1038
|
-
args: currentArguments
|
|
1039
|
-
});
|
|
1040
|
-
});
|
|
1041
|
-
else getEvent(actionName, "onDispatched").publish({
|
|
1042
|
-
result: returnedResult,
|
|
1043
|
-
args: currentArguments
|
|
1044
|
-
});
|
|
1045
|
-
return returnedResult;
|
|
1046
|
-
} catch (err) {
|
|
1047
|
-
console.error(err);
|
|
1048
|
-
getEvent(actionName, "onFailure").publish({
|
|
1049
|
-
reason: err,
|
|
1050
|
-
args: arguments
|
|
1051
|
-
});
|
|
1052
|
-
}
|
|
1053
|
-
};
|
|
1054
|
-
});
|
|
1055
|
-
return result;
|
|
845
|
+
return null;
|
|
1056
846
|
}
|
|
1057
|
-
function
|
|
1058
|
-
const
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
console.error(err);
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
|
-
const eventKey = `onMutated${key.charAt(0).toUpperCase()}${key.slice(1)}`;
|
|
1081
|
-
if (!events[eventKey]) {
|
|
1082
|
-
const topic = createTopic({
|
|
1083
|
-
namespace: `${storeInstanceName}.events`,
|
|
1084
|
-
name: eventKey
|
|
1085
|
-
});
|
|
1086
|
-
events[eventKey] = topic;
|
|
1087
|
-
messages.push(topic);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
function triggerEvent(name, value$1) {
|
|
1091
|
-
const keyString = name;
|
|
1092
|
-
events[`onMutated${keyString.charAt(0).toUpperCase()}${keyString.slice(1)}`]?.publish(value$1);
|
|
847
|
+
function hasClientDirective(props) {
|
|
848
|
+
for (const key in props) if (key.startsWith("client:")) return true;
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
851
|
+
function serializeProps(props) {
|
|
852
|
+
const filtered = filterClientDirectives(props);
|
|
853
|
+
const result = {};
|
|
854
|
+
let hasProps = false;
|
|
855
|
+
for (const key in filtered) {
|
|
856
|
+
const value = filtered[key];
|
|
857
|
+
if (key === "children" || key === "key" || key === "ref" || key === "slots") continue;
|
|
858
|
+
if (typeof value === "function") continue;
|
|
859
|
+
if (typeof value === "symbol") continue;
|
|
860
|
+
if (value === void 0) continue;
|
|
861
|
+
if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase()) continue;
|
|
862
|
+
try {
|
|
863
|
+
JSON.stringify(value);
|
|
864
|
+
result[key] = value;
|
|
865
|
+
hasProps = true;
|
|
866
|
+
} catch {}
|
|
1093
867
|
}
|
|
1094
|
-
|
|
1095
|
-
initProperty(key);
|
|
1096
|
-
});
|
|
1097
|
-
return {
|
|
1098
|
-
state,
|
|
1099
|
-
events,
|
|
1100
|
-
mutate
|
|
1101
|
-
};
|
|
868
|
+
return hasProps ? result : void 0;
|
|
1102
869
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
function isComponent(type) {
|
|
1110
|
-
return typeof type === "function" && "__setup" in type;
|
|
870
|
+
function createEmit(reactiveProps) {
|
|
871
|
+
return (event, ...args) => {
|
|
872
|
+
const eventName = `on${event[0].toUpperCase() + event.slice(1)}`;
|
|
873
|
+
const handler = ("value" in reactiveProps ? reactiveProps.value : reactiveProps)?.[eventName];
|
|
874
|
+
if (handler && typeof handler === "function") handler(...args);
|
|
875
|
+
};
|
|
1111
876
|
}
|
|
1112
877
|
function createRenderer(options) {
|
|
1113
|
-
const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent } = options;
|
|
878
|
+
const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent, patchDirective: hostPatchDirective, onElementMounted: hostOnElementMounted, onElementUnmounted: hostOnElementUnmounted } = options;
|
|
1114
879
|
let currentAppContext = null;
|
|
1115
880
|
function render(element, container, appContext) {
|
|
1116
881
|
if (appContext) currentAppContext = appContext;
|
|
@@ -1141,7 +906,72 @@ function createRenderer(options) {
|
|
|
1141
906
|
container._vnode = null;
|
|
1142
907
|
}
|
|
1143
908
|
}
|
|
1144
|
-
|
|
909
|
+
const svgTags = new Set([
|
|
910
|
+
"svg",
|
|
911
|
+
"animate",
|
|
912
|
+
"animateMotion",
|
|
913
|
+
"animateTransform",
|
|
914
|
+
"circle",
|
|
915
|
+
"clipPath",
|
|
916
|
+
"defs",
|
|
917
|
+
"desc",
|
|
918
|
+
"ellipse",
|
|
919
|
+
"feBlend",
|
|
920
|
+
"feColorMatrix",
|
|
921
|
+
"feComponentTransfer",
|
|
922
|
+
"feComposite",
|
|
923
|
+
"feConvolveMatrix",
|
|
924
|
+
"feDiffuseLighting",
|
|
925
|
+
"feDisplacementMap",
|
|
926
|
+
"feDistantLight",
|
|
927
|
+
"feDropShadow",
|
|
928
|
+
"feFlood",
|
|
929
|
+
"feFuncA",
|
|
930
|
+
"feFuncB",
|
|
931
|
+
"feFuncG",
|
|
932
|
+
"feFuncR",
|
|
933
|
+
"feGaussianBlur",
|
|
934
|
+
"feImage",
|
|
935
|
+
"feMerge",
|
|
936
|
+
"feMergeNode",
|
|
937
|
+
"feMorphology",
|
|
938
|
+
"feOffset",
|
|
939
|
+
"fePointLight",
|
|
940
|
+
"feSpecularLighting",
|
|
941
|
+
"feSpotLight",
|
|
942
|
+
"feTile",
|
|
943
|
+
"feTurbulence",
|
|
944
|
+
"filter",
|
|
945
|
+
"foreignObject",
|
|
946
|
+
"g",
|
|
947
|
+
"image",
|
|
948
|
+
"line",
|
|
949
|
+
"linearGradient",
|
|
950
|
+
"marker",
|
|
951
|
+
"mask",
|
|
952
|
+
"metadata",
|
|
953
|
+
"mpath",
|
|
954
|
+
"path",
|
|
955
|
+
"pattern",
|
|
956
|
+
"polygon",
|
|
957
|
+
"polyline",
|
|
958
|
+
"radialGradient",
|
|
959
|
+
"rect",
|
|
960
|
+
"set",
|
|
961
|
+
"stop",
|
|
962
|
+
"switch",
|
|
963
|
+
"symbol",
|
|
964
|
+
"text",
|
|
965
|
+
"textPath",
|
|
966
|
+
"title",
|
|
967
|
+
"tspan",
|
|
968
|
+
"use",
|
|
969
|
+
"view"
|
|
970
|
+
]);
|
|
971
|
+
function isSvgTag(tag) {
|
|
972
|
+
return svgTags.has(tag);
|
|
973
|
+
}
|
|
974
|
+
function mount(vnode, container, before = null, parentIsSVG = false) {
|
|
1145
975
|
if (vnode == null || vnode === false || vnode === true) return;
|
|
1146
976
|
if (vnode.type === Text) {
|
|
1147
977
|
const node = hostCreateText(String(vnode.text));
|
|
@@ -1154,28 +984,34 @@ function createRenderer(options) {
|
|
|
1154
984
|
const anchor = hostCreateComment("");
|
|
1155
985
|
vnode.dom = anchor;
|
|
1156
986
|
hostInsert(anchor, container, before);
|
|
1157
|
-
if (vnode.children) vnode.children.forEach((child) => mount(child, container, anchor));
|
|
987
|
+
if (vnode.children) vnode.children.forEach((child) => mount(child, container, anchor, parentIsSVG));
|
|
1158
988
|
return;
|
|
1159
989
|
}
|
|
1160
990
|
if (isComponent(vnode.type)) {
|
|
1161
991
|
mountComponent(vnode, container, before, vnode.type.__setup);
|
|
1162
992
|
return;
|
|
1163
993
|
}
|
|
1164
|
-
const
|
|
994
|
+
const tag = vnode.type;
|
|
995
|
+
const isSVG = tag === "svg" || parentIsSVG && tag !== "foreignObject";
|
|
996
|
+
const element = hostCreateElement(tag, isSVG);
|
|
1165
997
|
vnode.dom = element;
|
|
1166
998
|
element.__vnode = vnode;
|
|
1167
999
|
if (vnode.props) {
|
|
1168
|
-
for (const key in vnode.props) if (key !== "children" && key !== "key" && key !== "ref")
|
|
1169
|
-
|
|
1000
|
+
for (const key in vnode.props) if (key !== "children" && key !== "key" && key !== "ref") if (key.charCodeAt(0) === 117 && key.startsWith("use:")) {
|
|
1001
|
+
if (hostPatchDirective) hostPatchDirective(element, key.slice(4), null, vnode.props[key], currentAppContext);
|
|
1002
|
+
} else hostPatchProp(element, key, null, vnode.props[key], isSVG);
|
|
1003
|
+
if (vnode.props.ref) untrack(() => {
|
|
1170
1004
|
if (typeof vnode.props.ref === "function") vnode.props.ref(element);
|
|
1171
1005
|
else if (typeof vnode.props.ref === "object") vnode.props.ref.current = element;
|
|
1172
|
-
}
|
|
1006
|
+
});
|
|
1173
1007
|
}
|
|
1008
|
+
const childIsSVG = isSVG && tag !== "foreignObject";
|
|
1174
1009
|
if (vnode.children) vnode.children.forEach((child) => {
|
|
1175
1010
|
child.parent = vnode;
|
|
1176
|
-
mount(child, element);
|
|
1011
|
+
mount(child, element, null, childIsSVG);
|
|
1177
1012
|
});
|
|
1178
1013
|
hostInsert(element, container, before);
|
|
1014
|
+
if (hostOnElementMounted) hostOnElementMounted(element);
|
|
1179
1015
|
}
|
|
1180
1016
|
function unmount(vnode, container) {
|
|
1181
1017
|
const internalVNode = vnode;
|
|
@@ -1185,10 +1021,10 @@ function createRenderer(options) {
|
|
|
1185
1021
|
const subTree = internalVNode._subTree;
|
|
1186
1022
|
if (subTree) unmount(subTree, container);
|
|
1187
1023
|
if (vnode.dom) hostRemove(vnode.dom);
|
|
1188
|
-
if (vnode.props?.ref) {
|
|
1024
|
+
if (vnode.props?.ref) untrack(() => {
|
|
1189
1025
|
if (typeof vnode.props.ref === "function") vnode.props.ref(null);
|
|
1190
1026
|
else if (typeof vnode.props.ref === "object") vnode.props.ref.current = null;
|
|
1191
|
-
}
|
|
1027
|
+
});
|
|
1192
1028
|
return;
|
|
1193
1029
|
}
|
|
1194
1030
|
if (vnode.type === Fragment) {
|
|
@@ -1196,10 +1032,11 @@ function createRenderer(options) {
|
|
|
1196
1032
|
if (vnode.dom) hostRemove(vnode.dom);
|
|
1197
1033
|
return;
|
|
1198
1034
|
}
|
|
1199
|
-
if (vnode.props?.ref) {
|
|
1035
|
+
if (vnode.props?.ref) untrack(() => {
|
|
1200
1036
|
if (typeof vnode.props.ref === "function") vnode.props.ref(null);
|
|
1201
1037
|
else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = null;
|
|
1202
|
-
}
|
|
1038
|
+
});
|
|
1039
|
+
if (hostOnElementUnmounted && vnode.dom) hostOnElementUnmounted(vnode.dom);
|
|
1203
1040
|
if (vnode.children && vnode.children.length > 0) vnode.children.forEach((child) => unmount(child, vnode.dom));
|
|
1204
1041
|
if (vnode.dom) hostRemove(vnode.dom);
|
|
1205
1042
|
}
|
|
@@ -1207,7 +1044,7 @@ function createRenderer(options) {
|
|
|
1207
1044
|
if (oldVNode === newVNode) return;
|
|
1208
1045
|
if (!isSameVNode(oldVNode, newVNode)) {
|
|
1209
1046
|
const parent = hostParentNode(oldVNode.dom) || container;
|
|
1210
|
-
const nextSibling = hostNextSibling(oldVNode.dom);
|
|
1047
|
+
const nextSibling = oldVNode.dom ? hostNextSibling(oldVNode.dom) : null;
|
|
1211
1048
|
unmount(oldVNode, parent);
|
|
1212
1049
|
mount(newVNode, parent, nextSibling);
|
|
1213
1050
|
return;
|
|
@@ -1222,12 +1059,25 @@ function createRenderer(options) {
|
|
|
1222
1059
|
const props = oldInternal._componentProps;
|
|
1223
1060
|
newInternal._componentProps = props;
|
|
1224
1061
|
if (props) {
|
|
1225
|
-
const newProps
|
|
1062
|
+
const newProps = newVNode.props || {};
|
|
1063
|
+
const newModels = newVNode.props?.$models || {};
|
|
1226
1064
|
untrack(() => {
|
|
1227
|
-
for (const key in newProps
|
|
1228
|
-
if (props[key] !== newProps
|
|
1065
|
+
for (const key in newProps) if (key !== "children" && key !== "key" && key !== "ref" && key !== "$models") {
|
|
1066
|
+
if (props[key] !== newProps[key]) props[key] = newProps[key];
|
|
1229
1067
|
}
|
|
1230
|
-
for (const
|
|
1068
|
+
for (const modelKey in newModels) {
|
|
1069
|
+
const newModel = newModels[modelKey];
|
|
1070
|
+
const oldModel = props[modelKey];
|
|
1071
|
+
if (isModel(newModel)) {
|
|
1072
|
+
if (isModel(oldModel)) {
|
|
1073
|
+
const [newObj, newKey] = newModel.binding;
|
|
1074
|
+
const [oldObj, oldKey] = oldModel.binding;
|
|
1075
|
+
if (newObj === oldObj && newKey === oldKey) continue;
|
|
1076
|
+
}
|
|
1077
|
+
props[modelKey] = newModel;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
for (const key in props) if (!(key in newProps) && !(key in newModels) && key !== "children" && key !== "key" && key !== "ref" && key !== "$models") delete props[key];
|
|
1231
1081
|
});
|
|
1232
1082
|
}
|
|
1233
1083
|
const slotsRef = oldInternal._slots;
|
|
@@ -1251,31 +1101,57 @@ function createRenderer(options) {
|
|
|
1251
1101
|
}
|
|
1252
1102
|
if (newVNode.type === Text) {
|
|
1253
1103
|
newVNode.dom = oldVNode.dom;
|
|
1104
|
+
if (!newVNode.dom) {
|
|
1105
|
+
const textNode = hostCreateText(String(newVNode.text));
|
|
1106
|
+
newVNode.dom = textNode;
|
|
1107
|
+
if (container) hostInsert(textNode, container, oldVNode.dom || null);
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1254
1110
|
if (oldVNode.text !== newVNode.text) hostSetText(newVNode.dom, String(newVNode.text));
|
|
1255
1111
|
return;
|
|
1256
1112
|
}
|
|
1257
1113
|
if (newVNode.type === Fragment) {
|
|
1258
|
-
patchChildren(oldVNode, newVNode, container);
|
|
1114
|
+
patchChildren(oldVNode, newVNode, container, false);
|
|
1259
1115
|
return;
|
|
1260
1116
|
}
|
|
1261
1117
|
const element = newVNode.dom = oldVNode.dom;
|
|
1118
|
+
if (!element) {
|
|
1119
|
+
mount(newVNode, container);
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
const tag = newVNode.type;
|
|
1123
|
+
const isSVG = tag === "svg" || isSvgTag(tag);
|
|
1262
1124
|
const oldProps = oldVNode.props || {};
|
|
1263
1125
|
const newProps = newVNode.props || {};
|
|
1264
|
-
for (const key in oldProps) if (!(key in newProps) && key !== "children" && key !== "key" && key !== "ref")
|
|
1126
|
+
for (const key in oldProps) if (!(key in newProps) && key !== "children" && key !== "key" && key !== "ref") if (key.charCodeAt(0) === 117 && key.startsWith("use:")) {
|
|
1127
|
+
if (hostPatchDirective) hostPatchDirective(element, key.slice(4), oldProps[key], null, currentAppContext);
|
|
1128
|
+
} else hostPatchProp(element, key, oldProps[key], null, isSVG);
|
|
1265
1129
|
for (const key in newProps) {
|
|
1266
1130
|
const oldValue = oldProps[key];
|
|
1267
1131
|
const newValue = newProps[key];
|
|
1268
|
-
if (key !== "children" && key !== "key" && key !== "ref" && oldValue !== newValue)
|
|
1132
|
+
if (key !== "children" && key !== "key" && key !== "ref" && oldValue !== newValue) if (key.charCodeAt(0) === 117 && key.startsWith("use:")) {
|
|
1133
|
+
if (hostPatchDirective) hostPatchDirective(element, key.slice(4), oldValue, newValue, currentAppContext);
|
|
1134
|
+
} else hostPatchProp(element, key, oldValue, newValue, isSVG);
|
|
1269
1135
|
}
|
|
1270
|
-
patchChildren(oldVNode, newVNode, element);
|
|
1136
|
+
patchChildren(oldVNode, newVNode, element, isSVG && tag !== "foreignObject");
|
|
1271
1137
|
}
|
|
1272
|
-
function patchChildren(oldVNode, newVNode, container) {
|
|
1138
|
+
function patchChildren(oldVNode, newVNode, container, parentIsSVG = false) {
|
|
1273
1139
|
const oldChildren = oldVNode.children;
|
|
1274
1140
|
const newChildren = newVNode.children;
|
|
1275
1141
|
newChildren.forEach((c) => c.parent = newVNode);
|
|
1276
|
-
reconcileChildrenArray(container, oldChildren, newChildren);
|
|
1142
|
+
reconcileChildrenArray(container, oldChildren, newChildren, parentIsSVG);
|
|
1143
|
+
}
|
|
1144
|
+
function checkDuplicateKeys(children) {
|
|
1145
|
+
if (process.env.NODE_ENV === "production") return;
|
|
1146
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
1147
|
+
for (const child of children) if (child?.key != null) {
|
|
1148
|
+
const keyStr = String(child.key);
|
|
1149
|
+
if (seenKeys.has(keyStr)) console.warn(`[SignalX] Duplicate key "${child.key}" detected in list. Keys should be unique among siblings to ensure correct reconciliation. This may cause unexpected behavior when items are reordered, added, or removed.`);
|
|
1150
|
+
seenKeys.add(keyStr);
|
|
1151
|
+
}
|
|
1277
1152
|
}
|
|
1278
|
-
function reconcileChildrenArray(parent, oldChildren, newChildren) {
|
|
1153
|
+
function reconcileChildrenArray(parent, oldChildren, newChildren, parentIsSVG = false) {
|
|
1154
|
+
if (process.env.NODE_ENV !== "production") checkDuplicateKeys(newChildren);
|
|
1279
1155
|
let oldStartIdx = 0;
|
|
1280
1156
|
let oldEndIdx = oldChildren.length - 1;
|
|
1281
1157
|
let oldStartVNode = oldChildren[0];
|
|
@@ -1317,13 +1193,13 @@ function createRenderer(options) {
|
|
|
1317
1193
|
patch(vnodeToMove, newStartVNode, parent);
|
|
1318
1194
|
oldChildren[idxInOld] = void 0;
|
|
1319
1195
|
if (vnodeToMove.dom && oldStartVNode.dom) hostInsert(vnodeToMove.dom, parent, oldStartVNode.dom);
|
|
1320
|
-
} else mount(newStartVNode, parent, oldStartVNode.dom);
|
|
1196
|
+
} else mount(newStartVNode, parent, oldStartVNode.dom, parentIsSVG);
|
|
1321
1197
|
newStartVNode = newChildren[++newStartIdx];
|
|
1322
1198
|
}
|
|
1323
1199
|
if (oldStartIdx > oldEndIdx) {
|
|
1324
1200
|
if (newStartIdx <= newEndIdx) {
|
|
1325
1201
|
const anchor = newChildren[newEndIdx + 1] == null ? null : newChildren[newEndIdx + 1].dom;
|
|
1326
|
-
for (let i = newStartIdx; i <= newEndIdx; i++) mount(newChildren[i], parent, anchor);
|
|
1202
|
+
for (let i = newStartIdx; i <= newEndIdx; i++) mount(newChildren[i], parent, anchor, parentIsSVG);
|
|
1327
1203
|
}
|
|
1328
1204
|
} else if (newStartIdx > newEndIdx) {
|
|
1329
1205
|
for (let i = oldStartIdx; i <= oldEndIdx; i++) if (oldChildren[i]) unmount(oldChildren[i], parent);
|
|
@@ -1340,7 +1216,11 @@ function createRenderer(options) {
|
|
|
1340
1216
|
const map = /* @__PURE__ */ new Map();
|
|
1341
1217
|
for (let i = beginIdx; i <= endIdx; i++) {
|
|
1342
1218
|
const key = children[i]?.key;
|
|
1343
|
-
if (key != null)
|
|
1219
|
+
if (key != null) {
|
|
1220
|
+
const keyStr = String(key);
|
|
1221
|
+
if (process.env.NODE_ENV !== "production" && map.has(keyStr)) console.warn(`[SignalX] Duplicate key "${key}" detected in list. Keys should be unique among siblings to ensure correct reconciliation. This may cause unexpected behavior when items are reordered, added, or removed.`);
|
|
1222
|
+
map.set(keyStr, i);
|
|
1223
|
+
}
|
|
1344
1224
|
}
|
|
1345
1225
|
return map;
|
|
1346
1226
|
}
|
|
@@ -1355,14 +1235,21 @@ function createRenderer(options) {
|
|
|
1355
1235
|
hostInsert(anchor, container, before);
|
|
1356
1236
|
let exposed = null;
|
|
1357
1237
|
let exposeCalled = false;
|
|
1358
|
-
const { children, slots: slotsFromProps, ...propsData } = vnode.props || {};
|
|
1359
|
-
const
|
|
1238
|
+
const { children, slots: slotsFromProps, $models: modelsData, ...propsData } = vnode.props || {};
|
|
1239
|
+
const propsWithModels = { ...propsData };
|
|
1240
|
+
if (modelsData) for (const modelKey in modelsData) {
|
|
1241
|
+
const modelValue = modelsData[modelKey];
|
|
1242
|
+
if (isModel(modelValue)) propsWithModels[modelKey] = modelValue;
|
|
1243
|
+
}
|
|
1244
|
+
const reactiveProps = signal$1(propsWithModels);
|
|
1360
1245
|
const internalVNode = vnode;
|
|
1361
1246
|
internalVNode._componentProps = reactiveProps;
|
|
1362
1247
|
const slots = createSlots(children, slotsFromProps);
|
|
1363
1248
|
internalVNode._slots = slots;
|
|
1249
|
+
const createdHooks = [];
|
|
1364
1250
|
const mountHooks = [];
|
|
1365
|
-
const
|
|
1251
|
+
const updatedHooks = [];
|
|
1252
|
+
const unmountHooks = [];
|
|
1366
1253
|
const parentInstance = getCurrentInstance();
|
|
1367
1254
|
const componentName = vnode.type.__name;
|
|
1368
1255
|
const ctx = {
|
|
@@ -1370,16 +1257,19 @@ function createRenderer(options) {
|
|
|
1370
1257
|
signal: signal$1,
|
|
1371
1258
|
props: createPropsAccessor(reactiveProps),
|
|
1372
1259
|
slots,
|
|
1373
|
-
emit: (
|
|
1374
|
-
const handler = reactiveProps[`on${event[0].toUpperCase() + event.slice(1)}`];
|
|
1375
|
-
if (handler && typeof handler === "function") handler(...args);
|
|
1376
|
-
},
|
|
1260
|
+
emit: createEmit(reactiveProps),
|
|
1377
1261
|
parent: parentInstance,
|
|
1378
|
-
|
|
1262
|
+
onMounted: (fn) => {
|
|
1379
1263
|
mountHooks.push(fn);
|
|
1380
1264
|
},
|
|
1381
|
-
|
|
1382
|
-
|
|
1265
|
+
onUnmounted: (fn) => {
|
|
1266
|
+
unmountHooks.push(fn);
|
|
1267
|
+
},
|
|
1268
|
+
onCreated: (fn) => {
|
|
1269
|
+
createdHooks.push(fn);
|
|
1270
|
+
},
|
|
1271
|
+
onUpdated: (fn) => {
|
|
1272
|
+
updatedHooks.push(fn);
|
|
1383
1273
|
},
|
|
1384
1274
|
expose: (exposedValue) => {
|
|
1385
1275
|
exposed = exposedValue;
|
|
@@ -1390,7 +1280,7 @@ function createRenderer(options) {
|
|
|
1390
1280
|
};
|
|
1391
1281
|
applyContextExtensions(ctx);
|
|
1392
1282
|
ctx.__name = componentName;
|
|
1393
|
-
if (currentAppContext) ctx
|
|
1283
|
+
if (!parentInstance && currentAppContext) provideAppContext(ctx, currentAppContext);
|
|
1394
1284
|
const componentInstance = {
|
|
1395
1285
|
name: componentName,
|
|
1396
1286
|
ctx,
|
|
@@ -1400,9 +1290,10 @@ function createRenderer(options) {
|
|
|
1400
1290
|
let renderFn;
|
|
1401
1291
|
try {
|
|
1402
1292
|
const setupResult = setup(ctx);
|
|
1403
|
-
if (setupResult && typeof setupResult.then === "function") throw new Error(`Async setup in component "${componentName}" is only supported during SSR. On the client, use pre-loaded data from hydration or fetch in
|
|
1293
|
+
if (setupResult && typeof setupResult.then === "function") throw new Error(`Async setup in component "${componentName}" is only supported during SSR. On the client, use pre-loaded data from hydration or fetch in onMounted.`);
|
|
1404
1294
|
renderFn = setupResult;
|
|
1405
1295
|
notifyComponentCreated(currentAppContext, componentInstance);
|
|
1296
|
+
createdHooks.forEach((hook) => hook());
|
|
1406
1297
|
} catch (err) {
|
|
1407
1298
|
if (!handleComponentError(currentAppContext, err, componentInstance, "setup")) throw err;
|
|
1408
1299
|
} finally {
|
|
@@ -1410,8 +1301,10 @@ function createRenderer(options) {
|
|
|
1410
1301
|
}
|
|
1411
1302
|
if (vnode.props?.ref) {
|
|
1412
1303
|
const refValue = exposeCalled ? exposed : null;
|
|
1413
|
-
|
|
1414
|
-
|
|
1304
|
+
untrack(() => {
|
|
1305
|
+
if (typeof vnode.props.ref === "function") vnode.props.ref(refValue);
|
|
1306
|
+
else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = refValue;
|
|
1307
|
+
});
|
|
1415
1308
|
}
|
|
1416
1309
|
if (renderFn) {
|
|
1417
1310
|
ctx.renderFn = renderFn;
|
|
@@ -1425,6 +1318,7 @@ function createRenderer(options) {
|
|
|
1425
1318
|
if (prevSubTree) {
|
|
1426
1319
|
patch(prevSubTree, subTree, container);
|
|
1427
1320
|
notifyComponentUpdated(currentAppContext, componentInstance);
|
|
1321
|
+
updatedHooks.forEach((hook) => hook());
|
|
1428
1322
|
} else mount(subTree, container, anchor);
|
|
1429
1323
|
internalVNode._subTree = subTree;
|
|
1430
1324
|
} catch (err) {
|
|
@@ -1443,7 +1337,7 @@ function createRenderer(options) {
|
|
|
1443
1337
|
notifyComponentMounted(currentAppContext, componentInstance);
|
|
1444
1338
|
vnode.cleanup = () => {
|
|
1445
1339
|
notifyComponentUnmounted(currentAppContext, componentInstance);
|
|
1446
|
-
|
|
1340
|
+
unmountHooks.forEach((hook) => hook(mountCtx));
|
|
1447
1341
|
};
|
|
1448
1342
|
}
|
|
1449
1343
|
return {
|
|
@@ -1451,23 +1345,9 @@ function createRenderer(options) {
|
|
|
1451
1345
|
patch,
|
|
1452
1346
|
mount,
|
|
1453
1347
|
unmount,
|
|
1454
|
-
mountComponent
|
|
1455
|
-
createApp: (rootComponent) => {
|
|
1456
|
-
return { mount(selectorOrContainer) {
|
|
1457
|
-
let container = null;
|
|
1458
|
-
if (typeof selectorOrContainer === "string") {
|
|
1459
|
-
if (options.querySelector) container = options.querySelector(selectorOrContainer);
|
|
1460
|
-
} else container = selectorOrContainer;
|
|
1461
|
-
if (!container) {
|
|
1462
|
-
console.warn(`Container not found: ${selectorOrContainer}`);
|
|
1463
|
-
return;
|
|
1464
|
-
}
|
|
1465
|
-
render(rootComponent, container);
|
|
1466
|
-
} };
|
|
1467
|
-
}
|
|
1348
|
+
mountComponent
|
|
1468
1349
|
};
|
|
1469
1350
|
}
|
|
1351
|
+
export { CLIENT_DIRECTIVES, CLIENT_DIRECTIVE_PREFIX, ErrorBoundary, Fragment, InstanceLifetimes, SubscriptionHandler, Suspense, Text, Utils, __DIRECTIVE__, applyContextExtensions, component, compound, createEmit, createModel, createModelFromBinding, createPropsAccessor, createPropsProxy, createRenderer, createSlots, createTopic, defineApp, defineDirective, defineFactory, defineInjectable, defineProvide, filterClientDirectives, getAppContextToken, getComponentMeta, getComponentPlugins, getCurrentInstance, getDefaultMount, getHydrationDirective, getModelSymbol, getPlatformModelProcessor, guid, handleComponentError, hasClientDirective, hasRequestIsolation, isComponent, isDirective, isLazyComponent, isModel, jsx, jsxDEV, jsxs, lazy, normalizeSubTree, notifyComponentCreated, notifyComponentMounted, notifyComponentUnmounted, notifyComponentUpdated, onCreated, onMounted, onUnmounted, onUpdated, provideAppContext, registerComponentPlugin, registerContextExtension, registerPendingPromise, runInRequestScope, serializeProps, setCurrentInstance, setDefaultMount, setPlatformModelProcessor, signal, toSubscriber, useAppContext, valueOf };
|
|
1470
1352
|
|
|
1471
|
-
//#endregion
|
|
1472
|
-
export { AppContextKey, Fragment, InstanceLifetimes, SubscriptionHandler, Suspense, Text, Utils, applyContextExtensions, createPropsAccessor, createPropsProxy, createRenderer, createSlots, createTopic, defineApp, defineComponent, defineFactory, defineInjectable, defineProvide, defineStore, getComponentMeta, getComponentPlugins, getCurrentInstance, getDefaultMount, getPlatformSyncProcessor, guid, handleComponentError, inject, injectApp, isLazyComponent, jsx, jsxDEV, jsxs, lazy, normalizeSubTree, notifyComponentCreated, notifyComponentMounted, notifyComponentUnmounted, notifyComponentUpdated, onCleanup, onMount, provide, registerComponentPlugin, registerContextExtension, registerPendingPromise, setCurrentInstance, setDefaultMount, setPlatformSyncProcessor, signal, toSubscriber, valueOf };
|
|
1473
1353
|
//# sourceMappingURL=index.js.map
|