@liteforge/runtime 0.1.0
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/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/app.d.ts +38 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +266 -0
- package/dist/app.js.map +1 -0
- package/dist/component.d.ts +45 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +295 -0
- package/dist/component.js.map +1 -0
- package/dist/context.d.ts +66 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +121 -0
- package/dist/context.js.map +1 -0
- package/dist/control-flow.d.ts +119 -0
- package/dist/control-flow.d.ts.map +1 -0
- package/dist/control-flow.js +452 -0
- package/dist/control-flow.js.map +1 -0
- package/dist/h.d.ts +53 -0
- package/dist/h.d.ts.map +1 -0
- package/dist/h.js +282 -0
- package/dist/h.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/template.d.ts +65 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +237 -0
- package/dist/template.js.map +1 -0
- package/dist/types.d.ts +434 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiteForge createComponent
|
|
3
|
+
*
|
|
4
|
+
* The central factory for creating reactive components with full lifecycle support.
|
|
5
|
+
*
|
|
6
|
+
* Lifecycle Flow:
|
|
7
|
+
* 1. setup() - Synchronous, create local signals
|
|
8
|
+
* 2. placeholder - Shown immediately (if load exists)
|
|
9
|
+
* 3. load() - Async data fetching
|
|
10
|
+
* 4. component() - Render (only when load resolved)
|
|
11
|
+
* 5. mounted() - After DOM insertion
|
|
12
|
+
* 6. destroyed() - On unmount
|
|
13
|
+
*/
|
|
14
|
+
import { generateDebugId, emitComponentMount, emitComponentUnmount, } from '@liteforge/core';
|
|
15
|
+
import { use, withContext } from './context.js';
|
|
16
|
+
// Track parent component for debug hierarchy
|
|
17
|
+
let currentParentComponentId;
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Component State Enum
|
|
20
|
+
// ============================================================================
|
|
21
|
+
var ComponentState;
|
|
22
|
+
(function (ComponentState) {
|
|
23
|
+
ComponentState[ComponentState["Created"] = 0] = "Created";
|
|
24
|
+
ComponentState[ComponentState["Loading"] = 1] = "Loading";
|
|
25
|
+
ComponentState[ComponentState["Loaded"] = 2] = "Loaded";
|
|
26
|
+
ComponentState[ComponentState["Error"] = 3] = "Error";
|
|
27
|
+
ComponentState[ComponentState["Mounted"] = 4] = "Mounted";
|
|
28
|
+
ComponentState[ComponentState["Unmounted"] = 5] = "Unmounted";
|
|
29
|
+
})(ComponentState || (ComponentState = {}));
|
|
30
|
+
// Implementation
|
|
31
|
+
export function createComponent(definition) {
|
|
32
|
+
const factory = (inputProps) => {
|
|
33
|
+
return createComponentInstance(definition, inputProps);
|
|
34
|
+
};
|
|
35
|
+
// Mark as LiteForge component for detection
|
|
36
|
+
factory.__liteforge_component = true;
|
|
37
|
+
return factory;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create an instance of a component with full lifecycle management.
|
|
41
|
+
*/
|
|
42
|
+
function createComponentInstance(definition, inputProps) {
|
|
43
|
+
// Debug info - extract component name from definition
|
|
44
|
+
// Priority: 1. explicit name property, 2. component function name (if meaningful), 3. fallback
|
|
45
|
+
// Skip generic names like 'component' or empty strings
|
|
46
|
+
const funcName = definition.component.name;
|
|
47
|
+
const componentName = definition.name
|
|
48
|
+
?? (funcName && funcName !== 'component' && funcName !== '' ? funcName : 'Component');
|
|
49
|
+
const componentId = generateDebugId(componentName);
|
|
50
|
+
const parentId = currentParentComponentId;
|
|
51
|
+
// State
|
|
52
|
+
let state = ComponentState.Created;
|
|
53
|
+
let currentNode = null;
|
|
54
|
+
let parentElement = null;
|
|
55
|
+
let beforeNode = null;
|
|
56
|
+
let props = resolveProps(definition.props, inputProps);
|
|
57
|
+
let setupResult;
|
|
58
|
+
let loadedData;
|
|
59
|
+
let mountedCleanup;
|
|
60
|
+
const hasProvide = Boolean(definition.provide);
|
|
61
|
+
let provideContext;
|
|
62
|
+
// ========================================
|
|
63
|
+
// Phase 1: Setup (synchronous)
|
|
64
|
+
// ========================================
|
|
65
|
+
if (definition.setup) {
|
|
66
|
+
setupResult = definition.setup({ props, use });
|
|
67
|
+
}
|
|
68
|
+
// ========================================
|
|
69
|
+
// Lifecycle Methods
|
|
70
|
+
// ========================================
|
|
71
|
+
function mount(parent, before = null) {
|
|
72
|
+
if (state === ComponentState.Unmounted) {
|
|
73
|
+
throw new Error('Cannot mount an unmounted component');
|
|
74
|
+
}
|
|
75
|
+
parentElement = parent;
|
|
76
|
+
beforeNode = before;
|
|
77
|
+
// Set up provide context if defined
|
|
78
|
+
if (hasProvide && definition.provide) {
|
|
79
|
+
provideContext = definition.provide({ use });
|
|
80
|
+
}
|
|
81
|
+
// Track parent component for nested components
|
|
82
|
+
const previousParentId = currentParentComponentId;
|
|
83
|
+
currentParentComponentId = componentId;
|
|
84
|
+
// Run within context scope
|
|
85
|
+
const mountWithContext = () => {
|
|
86
|
+
if (definition.load) {
|
|
87
|
+
// Has async loading - show placeholder first
|
|
88
|
+
state = ComponentState.Loading;
|
|
89
|
+
renderPlaceholder();
|
|
90
|
+
startLoading();
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// No loading - render directly
|
|
94
|
+
state = ComponentState.Loaded;
|
|
95
|
+
loadedData = undefined;
|
|
96
|
+
renderComponent();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
if (hasProvide && provideContext) {
|
|
100
|
+
withContext(provideContext, mountWithContext);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
mountWithContext();
|
|
104
|
+
}
|
|
105
|
+
// Restore parent component tracking
|
|
106
|
+
currentParentComponentId = previousParentId;
|
|
107
|
+
// Emit mount event (zero cost if debug not enabled)
|
|
108
|
+
emitComponentMount(componentId, componentName, parentId);
|
|
109
|
+
}
|
|
110
|
+
function unmount() {
|
|
111
|
+
if (state === ComponentState.Unmounted)
|
|
112
|
+
return;
|
|
113
|
+
// Run destroyed callback
|
|
114
|
+
if (definition.destroyed) {
|
|
115
|
+
definition.destroyed({ props, setup: setupResult });
|
|
116
|
+
}
|
|
117
|
+
// Run mounted cleanup
|
|
118
|
+
if (mountedCleanup) {
|
|
119
|
+
mountedCleanup();
|
|
120
|
+
mountedCleanup = undefined;
|
|
121
|
+
}
|
|
122
|
+
// Remove from DOM
|
|
123
|
+
if (currentNode && currentNode.parentNode) {
|
|
124
|
+
currentNode.parentNode.removeChild(currentNode);
|
|
125
|
+
}
|
|
126
|
+
currentNode = null;
|
|
127
|
+
parentElement = null;
|
|
128
|
+
state = ComponentState.Unmounted;
|
|
129
|
+
// Emit unmount event (zero cost if debug not enabled)
|
|
130
|
+
emitComponentUnmount(componentId, componentName);
|
|
131
|
+
}
|
|
132
|
+
function getNode() {
|
|
133
|
+
return currentNode;
|
|
134
|
+
}
|
|
135
|
+
function updateProps(newProps) {
|
|
136
|
+
props = resolveProps(definition.props, newProps);
|
|
137
|
+
// In a full implementation, this would trigger a re-render
|
|
138
|
+
// For now, props are static after initial render
|
|
139
|
+
}
|
|
140
|
+
// ========================================
|
|
141
|
+
// Internal Methods
|
|
142
|
+
// ========================================
|
|
143
|
+
function renderPlaceholder() {
|
|
144
|
+
if (!parentElement)
|
|
145
|
+
return;
|
|
146
|
+
let placeholderNode;
|
|
147
|
+
if (definition.placeholder) {
|
|
148
|
+
placeholderNode = definition.placeholder({ props });
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Default placeholder is an empty comment node
|
|
152
|
+
placeholderNode = document.createComment('loading');
|
|
153
|
+
}
|
|
154
|
+
insertNode(placeholderNode);
|
|
155
|
+
}
|
|
156
|
+
function renderComponent() {
|
|
157
|
+
if (!parentElement)
|
|
158
|
+
return;
|
|
159
|
+
if (state === ComponentState.Unmounted)
|
|
160
|
+
return;
|
|
161
|
+
const render = () => {
|
|
162
|
+
const node = definition.component({
|
|
163
|
+
props,
|
|
164
|
+
data: loadedData,
|
|
165
|
+
setup: setupResult,
|
|
166
|
+
use,
|
|
167
|
+
});
|
|
168
|
+
insertNode(node);
|
|
169
|
+
state = ComponentState.Mounted;
|
|
170
|
+
// Phase 4: mounted callback
|
|
171
|
+
if (definition.mounted && currentNode instanceof Element) {
|
|
172
|
+
mountedCleanup = definition.mounted({
|
|
173
|
+
el: currentNode,
|
|
174
|
+
props,
|
|
175
|
+
data: loadedData,
|
|
176
|
+
setup: setupResult,
|
|
177
|
+
use,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
if (hasProvide && provideContext) {
|
|
182
|
+
withContext(provideContext, render);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
render();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function renderError(error) {
|
|
189
|
+
if (!parentElement)
|
|
190
|
+
return;
|
|
191
|
+
if (state === ComponentState.Unmounted)
|
|
192
|
+
return;
|
|
193
|
+
state = ComponentState.Error;
|
|
194
|
+
if (definition.error) {
|
|
195
|
+
const errorNode = definition.error({
|
|
196
|
+
props,
|
|
197
|
+
error,
|
|
198
|
+
retry: () => {
|
|
199
|
+
// Re-attempt loading
|
|
200
|
+
state = ComponentState.Loading;
|
|
201
|
+
renderPlaceholder();
|
|
202
|
+
startLoading();
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
insertNode(errorNode);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// Default error: show a text node with the error message
|
|
209
|
+
const errorNode = document.createTextNode(`Error: ${error.message}`);
|
|
210
|
+
insertNode(errorNode);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function startLoading() {
|
|
214
|
+
if (!definition.load)
|
|
215
|
+
return;
|
|
216
|
+
definition
|
|
217
|
+
.load({
|
|
218
|
+
props,
|
|
219
|
+
setup: setupResult,
|
|
220
|
+
use,
|
|
221
|
+
})
|
|
222
|
+
.then((data) => {
|
|
223
|
+
if (state === ComponentState.Unmounted)
|
|
224
|
+
return;
|
|
225
|
+
loadedData = data;
|
|
226
|
+
state = ComponentState.Loaded;
|
|
227
|
+
renderComponent();
|
|
228
|
+
})
|
|
229
|
+
.catch((error) => {
|
|
230
|
+
if (state === ComponentState.Unmounted)
|
|
231
|
+
return;
|
|
232
|
+
renderError(error instanceof Error ? error : new Error(String(error)));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function insertNode(newNode) {
|
|
236
|
+
if (!parentElement)
|
|
237
|
+
return;
|
|
238
|
+
// Remove old node if exists
|
|
239
|
+
if (currentNode && currentNode.parentNode) {
|
|
240
|
+
currentNode.parentNode.removeChild(currentNode);
|
|
241
|
+
}
|
|
242
|
+
// Insert new node
|
|
243
|
+
if (beforeNode) {
|
|
244
|
+
parentElement.insertBefore(newNode, beforeNode);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
parentElement.appendChild(newNode);
|
|
248
|
+
}
|
|
249
|
+
currentNode = newNode;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
mount,
|
|
253
|
+
unmount,
|
|
254
|
+
getNode,
|
|
255
|
+
updateProps,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
// ============================================================================
|
|
259
|
+
// Prop Resolution
|
|
260
|
+
// ============================================================================
|
|
261
|
+
/**
|
|
262
|
+
* Resolve props with defaults and type checking.
|
|
263
|
+
*/
|
|
264
|
+
function resolveProps(propsSchema, inputProps) {
|
|
265
|
+
if (!propsSchema) {
|
|
266
|
+
return inputProps;
|
|
267
|
+
}
|
|
268
|
+
const resolved = { ...inputProps };
|
|
269
|
+
for (const [key, propDef] of Object.entries(propsSchema)) {
|
|
270
|
+
if (!(key in resolved) || resolved[key] === undefined) {
|
|
271
|
+
// Apply default if available
|
|
272
|
+
if ('default' in propDef) {
|
|
273
|
+
resolved[key] =
|
|
274
|
+
typeof propDef.default === 'function'
|
|
275
|
+
? propDef.default()
|
|
276
|
+
: propDef.default;
|
|
277
|
+
}
|
|
278
|
+
else if (propDef.required) {
|
|
279
|
+
console.warn(`Required prop "${key}" is missing`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return resolved;
|
|
284
|
+
}
|
|
285
|
+
// ============================================================================
|
|
286
|
+
// Utility: Check if value is a component factory
|
|
287
|
+
// ============================================================================
|
|
288
|
+
/**
|
|
289
|
+
* Check if a value is a LiteForge component factory.
|
|
290
|
+
*/
|
|
291
|
+
export function isComponentFactory(value) {
|
|
292
|
+
return (typeof value === 'function' &&
|
|
293
|
+
value.__liteforge_component === true);
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,6CAA6C;AAC7C,IAAI,wBAA4C,CAAC;AAEjD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,IAAW,cAOV;AAPD,WAAW,cAAc;IACvB,yDAAO,CAAA;IACP,yDAAO,CAAA;IACP,uDAAM,CAAA;IACN,qDAAK,CAAA;IACL,yDAAO,CAAA;IACP,6DAAS,CAAA;AACX,CAAC,EAPU,cAAc,KAAd,cAAc,QAOxB;AA2CD,iBAAiB;AACjB,MAAM,UAAU,eAAe,CAI7B,UAAwC;IACxC,MAAM,OAAO,GAAG,CAAC,UAAsB,EAAqB,EAAE;QAC5D,OAAO,uBAAuB,CAAC,UAAU,EAAE,UAAe,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,4CAA4C;IAC3C,OAA2C,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAE1E,OAAO,OAA0C,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAK9B,UAAwC,EACxC,UAAa;IAEb,sDAAsD;IACtD,+FAA+F;IAC/F,uDAAuD;IACvD,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC;IAC3C,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI;WAChC,CAAC,QAAQ,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACxF,MAAM,WAAW,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,wBAAwB,CAAC;IAE1C,QAAQ;IACR,IAAI,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC;IACnC,IAAI,WAAW,GAAgB,IAAI,CAAC;IACpC,IAAI,aAAa,GAAmB,IAAI,CAAC;IACzC,IAAI,UAAU,GAAgB,IAAI,CAAC;IACnC,IAAI,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACvD,IAAI,WAA0B,CAAC;IAC/B,IAAI,UAAyB,CAAC;IAC9B,IAAI,cAAmC,CAAC;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,cAAmD,CAAC;IAExD,2CAA2C;IAC3C,+BAA+B;IAC/B,2CAA2C;IAC3C,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,2CAA2C;IAC3C,oBAAoB;IACpB,2CAA2C;IAE3C,SAAS,KAAK,CAAC,MAAe,EAAE,SAAsB,IAAI;QACxD,IAAI,KAAK,KAAK,cAAc,CAAC,SAAS,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,aAAa,GAAG,MAAM,CAAC;QACvB,UAAU,GAAG,MAAM,CAAC;QAEpB,oCAAoC;QACpC,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACrC,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/C,CAAC;QAED,+CAA+C;QAC/C,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;QAClD,wBAAwB,GAAG,WAAW,CAAC;QAEvC,2BAA2B;QAC3B,MAAM,gBAAgB,GAAG,GAAG,EAAE;YAC5B,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;gBACpB,6CAA6C;gBAC7C,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC;gBAC/B,iBAAiB,EAAE,CAAC;gBACpB,YAAY,EAAE,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,+BAA+B;gBAC/B,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC;gBAC9B,UAAU,GAAG,SAAc,CAAC;gBAC5B,eAAe,EAAE,CAAC;YACpB,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;YACjC,WAAW,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,gBAAgB,EAAE,CAAC;QACrB,CAAC;QAED,oCAAoC;QACpC,wBAAwB,GAAG,gBAAgB,CAAC;QAE5C,oDAAoD;QACpD,kBAAkB,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,OAAO;QACd,IAAI,KAAK,KAAK,cAAc,CAAC,SAAS;YAAE,OAAO;QAE/C,yBAAyB;QACzB,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACzB,UAAU,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,WAAgB,EAAE,CAAC,CAAC;QAC3D,CAAC;QAED,sBAAsB;QACtB,IAAI,cAAc,EAAE,CAAC;YACnB,cAAc,EAAE,CAAC;YACjB,cAAc,GAAG,SAAS,CAAC;QAC7B,CAAC;QAED,kBAAkB;QAClB,IAAI,WAAW,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC1C,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;QAED,WAAW,GAAG,IAAI,CAAC;QACnB,aAAa,GAAG,IAAI,CAAC;QACrB,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC;QAEjC,sDAAsD;QACtD,oBAAoB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,SAAS,OAAO;QACd,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,SAAS,WAAW,CAAC,QAAiC;QACpD,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,KAAK,EAAE,QAAa,CAAC,CAAC;QACtD,2DAA2D;QAC3D,iDAAiD;IACnD,CAAC;IAED,2CAA2C;IAC3C,mBAAmB;IACnB,2CAA2C;IAE3C,SAAS,iBAAiB;QACxB,IAAI,CAAC,aAAa;YAAE,OAAO;QAE3B,IAAI,eAAqB,CAAC;QAE1B,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;YAC3B,eAAe,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACtD,CAAC;QAED,UAAU,CAAC,eAAe,CAAC,CAAC;IAC9B,CAAC;IAED,SAAS,eAAe;QACtB,IAAI,CAAC,aAAa;YAAE,OAAO;QAC3B,IAAI,KAAK,KAAK,cAAc,CAAC,SAAS;YAAE,OAAO;QAE/C,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC;gBAChC,KAAK;gBACL,IAAI,EAAE,UAAe;gBACrB,KAAK,EAAE,WAAgB;gBACvB,GAAG;aACJ,CAAC,CAAC;YAEH,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC;YAE/B,4BAA4B;YAC5B,IAAI,UAAU,CAAC,OAAO,IAAI,WAAW,YAAY,OAAO,EAAE,CAAC;gBACzD,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC;oBAClC,EAAE,EAAE,WAAW;oBACf,KAAK;oBACL,IAAI,EAAE,UAAe;oBACrB,KAAK,EAAE,WAAgB;oBACvB,GAAG;iBACJ,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;YACjC,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,SAAS,WAAW,CAAC,KAAY;QAC/B,IAAI,CAAC,aAAa;YAAE,OAAO;QAC3B,IAAI,KAAK,KAAK,cAAc,CAAC,SAAS;YAAE,OAAO;QAE/C,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC;QAE7B,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC;gBACjC,KAAK;gBACL,KAAK;gBACL,KAAK,EAAE,GAAG,EAAE;oBACV,qBAAqB;oBACrB,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC;oBAC/B,iBAAiB,EAAE,CAAC;oBACpB,YAAY,EAAE,CAAC;gBACjB,CAAC;aACF,CAAC,CAAC;YACH,UAAU,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,yDAAyD;YACzD,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACrE,UAAU,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,SAAS,YAAY;QACnB,IAAI,CAAC,UAAU,CAAC,IAAI;YAAE,OAAO;QAE7B,UAAU;aACP,IAAI,CAAC;YACJ,KAAK;YACL,KAAK,EAAE,WAAgB;YACvB,GAAG;SACJ,CAAC;aACD,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,KAAK,KAAK,cAAc,CAAC,SAAS;gBAAE,OAAO;YAC/C,UAAU,GAAG,IAAI,CAAC;YAClB,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC;YAC9B,eAAe,EAAE,CAAC;QACpB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,IAAI,KAAK,KAAK,cAAc,CAAC,SAAS;gBAAE,OAAO;YAC/C,WAAW,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACP,CAAC;IAED,SAAS,UAAU,CAAC,OAAa;QAC/B,IAAI,CAAC,aAAa;YAAE,OAAO;QAE3B,4BAA4B;QAC5B,IAAI,WAAW,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC1C,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;QAED,kBAAkB;QAClB,IAAI,UAAU,EAAE,CAAC;YACf,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,OAAO;QACL,KAAK;QACL,OAAO;QACP,OAAO;QACP,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E;;GAEG;AACH,SAAS,YAAY,CACnB,WAAkF,EAClF,UAAa;IAEb,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,QAAQ,GAAG,EAAE,GAAG,UAAU,EAA6B,CAAC;IAE9D,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACzD,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACtD,6BAA6B;YAC7B,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;gBACzB,QAAQ,CAAC,GAAG,CAAC;oBACX,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU;wBACnC,CAAC,CAAE,OAAO,CAAC,OAAyB,EAAE;wBACtC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;YACxB,CAAC;iBAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,kBAAkB,GAAG,cAAc,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAa,CAAC;AACvB,CAAC;AAED,+EAA+E;AAC/E,iDAAiD;AACjD,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,CACL,OAAO,KAAK,KAAK,UAAU;QAC1B,KAAmD,CAAC,qBAAqB,KAAK,IAAI,CACpF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiteForge Context System
|
|
3
|
+
*
|
|
4
|
+
* Provides a scoped context chain with no provider components.
|
|
5
|
+
* Context flows from app → parent components → child components.
|
|
6
|
+
*/
|
|
7
|
+
import type { ContextValues, UseFn } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get a value from the context chain.
|
|
10
|
+
* Searches from the current scope up to the app root.
|
|
11
|
+
*
|
|
12
|
+
* @param key - The context key to look up
|
|
13
|
+
* @returns The value associated with the key
|
|
14
|
+
* @throws Error if key is not found in any scope
|
|
15
|
+
*/
|
|
16
|
+
export declare function use<T = unknown>(key: string): T;
|
|
17
|
+
/**
|
|
18
|
+
* Check if a context key exists without throwing.
|
|
19
|
+
*
|
|
20
|
+
* @param key - The context key to check
|
|
21
|
+
* @returns True if the key exists in any scope
|
|
22
|
+
*/
|
|
23
|
+
export declare function hasContext(key: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Push a new context scope onto the stack.
|
|
26
|
+
* Used when entering a component with `provide`.
|
|
27
|
+
*
|
|
28
|
+
* @param values - The context values to add to the scope
|
|
29
|
+
*/
|
|
30
|
+
export declare function pushContext(values: ContextValues): void;
|
|
31
|
+
/**
|
|
32
|
+
* Pop the current context scope from the stack.
|
|
33
|
+
* Used when exiting a component with `provide`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function popContext(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Initialize the app-level context (bottom of stack).
|
|
38
|
+
* Should only be called once by createApp().
|
|
39
|
+
*
|
|
40
|
+
* @param values - The app-level context values
|
|
41
|
+
*/
|
|
42
|
+
export declare function initAppContext(values: ContextValues): void;
|
|
43
|
+
/**
|
|
44
|
+
* Clear all context (used for cleanup/testing).
|
|
45
|
+
*/
|
|
46
|
+
export declare function clearContext(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get the current context depth (for debugging/testing).
|
|
49
|
+
*/
|
|
50
|
+
export declare function getContextDepth(): number;
|
|
51
|
+
/**
|
|
52
|
+
* Run a function with a temporary context scope.
|
|
53
|
+
* The scope is automatically popped after the function completes.
|
|
54
|
+
*
|
|
55
|
+
* @param values - The context values for this scope
|
|
56
|
+
* @param fn - The function to run within the scope
|
|
57
|
+
* @returns The return value of the function
|
|
58
|
+
*/
|
|
59
|
+
export declare function withContext<T>(values: ContextValues, fn: () => T): T;
|
|
60
|
+
/**
|
|
61
|
+
* Create a use function bound to the current context state.
|
|
62
|
+
* This captures the current stack depth so the function works correctly
|
|
63
|
+
* even if called later when the context has changed.
|
|
64
|
+
*/
|
|
65
|
+
export declare function createBoundUse(): UseFn;
|
|
66
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAiBvD;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAU/C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/C;AAMD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAEvD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAI1D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAOpE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,KAAK,CAItC"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiteForge Context System
|
|
3
|
+
*
|
|
4
|
+
* Provides a scoped context chain with no provider components.
|
|
5
|
+
* Context flows from app → parent components → child components.
|
|
6
|
+
*/
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Context Stack
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Stack of context scopes. Each scope is a map of key → value.
|
|
12
|
+
* The bottom of the stack is the app-level context.
|
|
13
|
+
* Components can push their own scope when they have `provide`.
|
|
14
|
+
*/
|
|
15
|
+
const contextStack = [];
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Public API
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Get a value from the context chain.
|
|
21
|
+
* Searches from the current scope up to the app root.
|
|
22
|
+
*
|
|
23
|
+
* @param key - The context key to look up
|
|
24
|
+
* @returns The value associated with the key
|
|
25
|
+
* @throws Error if key is not found in any scope
|
|
26
|
+
*/
|
|
27
|
+
export function use(key) {
|
|
28
|
+
// Search from top of stack (innermost scope) to bottom (app scope)
|
|
29
|
+
for (let i = contextStack.length - 1; i >= 0; i--) {
|
|
30
|
+
const scope = contextStack[i];
|
|
31
|
+
if (scope && key in scope) {
|
|
32
|
+
return scope[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Context key "${key}" not found. Make sure it's provided in createApp() or a parent component's provide().`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if a context key exists without throwing.
|
|
39
|
+
*
|
|
40
|
+
* @param key - The context key to check
|
|
41
|
+
* @returns True if the key exists in any scope
|
|
42
|
+
*/
|
|
43
|
+
export function hasContext(key) {
|
|
44
|
+
for (let i = contextStack.length - 1; i >= 0; i--) {
|
|
45
|
+
const scope = contextStack[i];
|
|
46
|
+
if (scope && key in scope) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Internal API (used by createComponent and createApp)
|
|
54
|
+
// ============================================================================
|
|
55
|
+
/**
|
|
56
|
+
* Push a new context scope onto the stack.
|
|
57
|
+
* Used when entering a component with `provide`.
|
|
58
|
+
*
|
|
59
|
+
* @param values - The context values to add to the scope
|
|
60
|
+
*/
|
|
61
|
+
export function pushContext(values) {
|
|
62
|
+
contextStack.push(values);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Pop the current context scope from the stack.
|
|
66
|
+
* Used when exiting a component with `provide`.
|
|
67
|
+
*/
|
|
68
|
+
export function popContext() {
|
|
69
|
+
contextStack.pop();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Initialize the app-level context (bottom of stack).
|
|
73
|
+
* Should only be called once by createApp().
|
|
74
|
+
*
|
|
75
|
+
* @param values - The app-level context values
|
|
76
|
+
*/
|
|
77
|
+
export function initAppContext(values) {
|
|
78
|
+
// Clear any existing context and set the app context as the base
|
|
79
|
+
contextStack.length = 0;
|
|
80
|
+
contextStack.push(values);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Clear all context (used for cleanup/testing).
|
|
84
|
+
*/
|
|
85
|
+
export function clearContext() {
|
|
86
|
+
contextStack.length = 0;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the current context depth (for debugging/testing).
|
|
90
|
+
*/
|
|
91
|
+
export function getContextDepth() {
|
|
92
|
+
return contextStack.length;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Run a function with a temporary context scope.
|
|
96
|
+
* The scope is automatically popped after the function completes.
|
|
97
|
+
*
|
|
98
|
+
* @param values - The context values for this scope
|
|
99
|
+
* @param fn - The function to run within the scope
|
|
100
|
+
* @returns The return value of the function
|
|
101
|
+
*/
|
|
102
|
+
export function withContext(values, fn) {
|
|
103
|
+
pushContext(values);
|
|
104
|
+
try {
|
|
105
|
+
return fn();
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
popContext();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create a use function bound to the current context state.
|
|
113
|
+
* This captures the current stack depth so the function works correctly
|
|
114
|
+
* even if called later when the context has changed.
|
|
115
|
+
*/
|
|
116
|
+
export function createBoundUse() {
|
|
117
|
+
// The use function always reads from the current stack,
|
|
118
|
+
// which includes any scopes pushed by parent components
|
|
119
|
+
return use;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,YAAY,GAAoB,EAAE,CAAC;AAEzC,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAc,GAAW;IAC1C,mEAAmE;IACnE,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC,GAAG,CAAM,CAAC;QACzB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,wFAAwF,CAAC,CAAC;AAC/H,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,uDAAuD;AACvD,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,MAAqB;IAC/C,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,YAAY,CAAC,GAAG,EAAE,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,iEAAiE;IACjE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IACxB,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,YAAY,CAAC,MAAM,CAAC;AAC7B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAI,MAAqB,EAAE,EAAW;IAC/D,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,UAAU,EAAE,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,wDAAwD;IACxD,wDAAwD;IACxD,OAAO,GAAY,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiteForge Control Flow Components
|
|
3
|
+
*
|
|
4
|
+
* Components for conditional rendering and list iteration.
|
|
5
|
+
* These handle DOM insertion/removal reactively based on signals.
|
|
6
|
+
*/
|
|
7
|
+
import type { ComponentFactory, RenderFunction } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Config for Show component (internal use).
|
|
10
|
+
* Use ShowProps<T> from types.ts for external typing.
|
|
11
|
+
*/
|
|
12
|
+
export interface ShowConfig<T = unknown> {
|
|
13
|
+
when: (() => T) | T;
|
|
14
|
+
fallback?: () => Node;
|
|
15
|
+
children: (value: NonNullable<T>) => Node;
|
|
16
|
+
}
|
|
17
|
+
export declare function Show<T>(config: ShowConfig<T>): Node;
|
|
18
|
+
/**
|
|
19
|
+
* Config for For component (internal use).
|
|
20
|
+
* Use ForProps<T> from types.ts for external typing.
|
|
21
|
+
*/
|
|
22
|
+
export interface ForConfig<T> {
|
|
23
|
+
each: (() => ReadonlyArray<T>) | (() => T[]) | ReadonlyArray<T> | T[];
|
|
24
|
+
key?: keyof T | ((item: T, index: number) => string | number);
|
|
25
|
+
children: (item: T, index: number) => Node;
|
|
26
|
+
fallback?: () => Node;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Render a list of items with keyed reconciliation.
|
|
30
|
+
*
|
|
31
|
+
* @typeParam T - The item type, inferred from the `each` array
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* For({
|
|
36
|
+
* each: () => users(),
|
|
37
|
+
* key: 'id',
|
|
38
|
+
* children: (user, index) => {
|
|
39
|
+
* return document.createTextNode(`${index}: ${user.name}`);
|
|
40
|
+
* },
|
|
41
|
+
* fallback: () => document.createTextNode('No users'),
|
|
42
|
+
* })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function For<T>(config: ForConfig<T>): Node;
|
|
46
|
+
/**
|
|
47
|
+
* A single case in a Switch statement.
|
|
48
|
+
*/
|
|
49
|
+
export interface MatchCase {
|
|
50
|
+
when: (() => boolean) | boolean;
|
|
51
|
+
render: () => Node;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Config for Switch component (internal use).
|
|
55
|
+
* Use SwitchProps from types.ts for external typing.
|
|
56
|
+
*/
|
|
57
|
+
export interface SwitchConfig {
|
|
58
|
+
fallback?: () => Node;
|
|
59
|
+
children: Array<MatchCase>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Config for Match helper.
|
|
63
|
+
*/
|
|
64
|
+
export interface MatchConfig {
|
|
65
|
+
when: (() => boolean) | boolean;
|
|
66
|
+
children: () => Node;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Render the first matching case, or fallback.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* Switch({
|
|
74
|
+
* fallback: () => document.createTextNode('Unknown'),
|
|
75
|
+
* children: [
|
|
76
|
+
* Match({ when: () => status() === 'loading', children: () => Spinner() }),
|
|
77
|
+
* Match({ when: () => status() === 'error', children: () => ErrorView() }),
|
|
78
|
+
* Match({ when: () => status() === 'success', children: () => SuccessView() }),
|
|
79
|
+
* ],
|
|
80
|
+
* })
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function Switch(config: SwitchConfig): Node;
|
|
84
|
+
/**
|
|
85
|
+
* Helper to create a Match case for Switch.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* Match({
|
|
90
|
+
* when: () => status() === 'active',
|
|
91
|
+
* children: () => <span>Active</span>,
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function Match(config: MatchConfig): MatchCase;
|
|
96
|
+
/**
|
|
97
|
+
* Configuration for the Dynamic component.
|
|
98
|
+
* The component prop is a getter that returns either:
|
|
99
|
+
* - RenderFunction: A simple () => Node function
|
|
100
|
+
* - ComponentFactory: A LiteForge component from createComponent()
|
|
101
|
+
* - null: No component to render
|
|
102
|
+
*/
|
|
103
|
+
export interface DynamicConfig<P extends Record<string, unknown>> {
|
|
104
|
+
component: () => RenderFunction | ComponentFactory<P> | null;
|
|
105
|
+
props?: P | (() => P);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Dynamically render a component based on a signal.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* Dynamic({
|
|
113
|
+
* component: () => currentView(),
|
|
114
|
+
* props: () => ({ id: currentId() }),
|
|
115
|
+
* })
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare function Dynamic<P extends Record<string, unknown>>(config: DynamicConfig<P>): Node;
|
|
119
|
+
//# sourceMappingURL=control-flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-flow.d.ts","sourceRoot":"","sources":["../src/control-flow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAqB,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAsCtF;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACrC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CAC3C;AA6BD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CA0EnD;AAMD;;;GAGG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,MAAM,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC,CAAC;IAC9D,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAyJjD;AAMD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,OAAO,CAAC;IAChC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,OAAO,CAAC;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CA6EjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAEpD;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC9D,SAAS,EAAE,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CA2FzF"}
|