elit 3.5.6 → 3.5.8

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.
Files changed (128) hide show
  1. package/Cargo.toml +1 -1
  2. package/README.md +1 -1
  3. package/desktop/build.rs +83 -0
  4. package/desktop/icon.rs +106 -0
  5. package/desktop/lib.rs +2 -0
  6. package/desktop/main.rs +235 -0
  7. package/desktop/native_main.rs +128 -0
  8. package/desktop/native_renderer/action_widgets.rs +184 -0
  9. package/desktop/native_renderer/app_models.rs +171 -0
  10. package/desktop/native_renderer/app_runtime.rs +140 -0
  11. package/desktop/native_renderer/container_rendering.rs +610 -0
  12. package/desktop/native_renderer/content_widgets.rs +634 -0
  13. package/desktop/native_renderer/css_models.rs +371 -0
  14. package/desktop/native_renderer/embedded_surfaces.rs +414 -0
  15. package/desktop/native_renderer/form_controls.rs +516 -0
  16. package/desktop/native_renderer/interaction_dispatch.rs +89 -0
  17. package/desktop/native_renderer/runtime_support.rs +135 -0
  18. package/desktop/native_renderer/utilities.rs +495 -0
  19. package/desktop/native_renderer/vector_drawing.rs +491 -0
  20. package/desktop/native_renderer.rs +4122 -0
  21. package/desktop/runtime/external.rs +422 -0
  22. package/desktop/runtime/mod.rs +67 -0
  23. package/desktop/runtime/quickjs.rs +106 -0
  24. package/desktop/window.rs +383 -0
  25. package/dist/build.d.ts +1 -1
  26. package/dist/cli.cjs +16 -2
  27. package/dist/cli.mjs +16 -2
  28. package/dist/config.d.ts +1 -1
  29. package/dist/coverage.d.ts +1 -1
  30. package/dist/desktop-auto-render.cjs +2370 -0
  31. package/dist/desktop-auto-render.d.ts +13 -0
  32. package/dist/desktop-auto-render.js +2341 -0
  33. package/dist/desktop-auto-render.mjs +2344 -0
  34. package/dist/render-context.cjs +118 -0
  35. package/dist/render-context.d.ts +39 -0
  36. package/dist/render-context.js +77 -0
  37. package/dist/render-context.mjs +87 -0
  38. package/dist/{server-CNgDUgSZ.d.ts → server-FCdUqabc.d.ts} +1 -1
  39. package/dist/server.d.ts +1 -1
  40. package/package.json +26 -3
  41. package/dist/build.d.mts +0 -20
  42. package/dist/chokidar.d.mts +0 -134
  43. package/dist/cli.d.mts +0 -81
  44. package/dist/config.d.mts +0 -254
  45. package/dist/coverage.d.mts +0 -85
  46. package/dist/database.d.mts +0 -52
  47. package/dist/desktop.d.mts +0 -68
  48. package/dist/dom.d.mts +0 -87
  49. package/dist/el.d.mts +0 -208
  50. package/dist/fs.d.mts +0 -255
  51. package/dist/hmr.d.mts +0 -38
  52. package/dist/http.d.mts +0 -169
  53. package/dist/https.d.mts +0 -108
  54. package/dist/index.d.mts +0 -13
  55. package/dist/mime-types.d.mts +0 -48
  56. package/dist/native.d.mts +0 -136
  57. package/dist/path.d.mts +0 -163
  58. package/dist/router.d.mts +0 -49
  59. package/dist/runtime.d.mts +0 -97
  60. package/dist/server-D0Dp4R5z.d.mts +0 -449
  61. package/dist/server.d.mts +0 -7
  62. package/dist/state.d.mts +0 -117
  63. package/dist/style.d.mts +0 -232
  64. package/dist/test-reporter.d.mts +0 -77
  65. package/dist/test-runtime.d.mts +0 -122
  66. package/dist/test.d.mts +0 -39
  67. package/dist/types.d.mts +0 -586
  68. package/dist/universal.d.mts +0 -21
  69. package/dist/ws.d.mts +0 -200
  70. package/dist/wss.d.mts +0 -108
  71. package/src/build.ts +0 -362
  72. package/src/chokidar.ts +0 -427
  73. package/src/cli.ts +0 -1162
  74. package/src/config.ts +0 -509
  75. package/src/coverage.ts +0 -1479
  76. package/src/database.ts +0 -1410
  77. package/src/desktop-auto-render.ts +0 -317
  78. package/src/desktop-cli.ts +0 -1533
  79. package/src/desktop.ts +0 -99
  80. package/src/dev-build.ts +0 -340
  81. package/src/dom.ts +0 -901
  82. package/src/el.ts +0 -183
  83. package/src/fs.ts +0 -609
  84. package/src/hmr.ts +0 -149
  85. package/src/http.ts +0 -856
  86. package/src/https.ts +0 -411
  87. package/src/index.ts +0 -16
  88. package/src/mime-types.ts +0 -222
  89. package/src/mobile-cli.ts +0 -2313
  90. package/src/native-background.ts +0 -444
  91. package/src/native-border.ts +0 -343
  92. package/src/native-canvas.ts +0 -260
  93. package/src/native-cli.ts +0 -414
  94. package/src/native-color.ts +0 -904
  95. package/src/native-estimation.ts +0 -194
  96. package/src/native-grid.ts +0 -590
  97. package/src/native-interaction.ts +0 -1289
  98. package/src/native-layout.ts +0 -568
  99. package/src/native-link.ts +0 -76
  100. package/src/native-render-support.ts +0 -361
  101. package/src/native-spacing.ts +0 -231
  102. package/src/native-state.ts +0 -318
  103. package/src/native-strings.ts +0 -46
  104. package/src/native-transform.ts +0 -120
  105. package/src/native-types.ts +0 -439
  106. package/src/native-typography.ts +0 -254
  107. package/src/native-units.ts +0 -441
  108. package/src/native-vector.ts +0 -910
  109. package/src/native.ts +0 -5606
  110. package/src/path.ts +0 -493
  111. package/src/pm-cli.ts +0 -2498
  112. package/src/preview-build.ts +0 -294
  113. package/src/render-context.ts +0 -138
  114. package/src/router.ts +0 -260
  115. package/src/runtime.ts +0 -97
  116. package/src/server.ts +0 -2294
  117. package/src/state.ts +0 -556
  118. package/src/style.ts +0 -1790
  119. package/src/test-globals.d.ts +0 -184
  120. package/src/test-reporter.ts +0 -609
  121. package/src/test-runtime.ts +0 -1359
  122. package/src/test.ts +0 -368
  123. package/src/types.ts +0 -381
  124. package/src/universal.ts +0 -81
  125. package/src/wapk-cli.ts +0 -3213
  126. package/src/workspace-package.ts +0 -102
  127. package/src/ws.ts +0 -648
  128. package/src/wss.ts +0 -241
package/src/state.ts DELETED
@@ -1,556 +0,0 @@
1
- /**
2
- * Elit - State Management
3
- */
4
-
5
- import type { State, StateOptions, VNode, VirtualListController, Child, Props } from './types';
6
- import { dom } from './dom';
7
-
8
- export type NativeBindingKind = 'value' | 'checked';
9
-
10
- export interface NativeBindingMetadata<T = unknown> {
11
- kind: NativeBindingKind;
12
- state: State<T>;
13
- }
14
-
15
- export const ELIT_NATIVE_BINDING = Symbol.for('elit.native.binding');
16
- const ELIT_INTERNAL_WS_PATH = '/__elit_ws';
17
-
18
- // State management helpers
19
- export const createState = <T>(initial: T, options?: StateOptions): State<T> =>
20
- dom.createState(initial, options);
21
-
22
- export const computed = <T extends any[], R>(
23
- states: { [K in keyof T]: State<T[K]> },
24
- fn: (...values: T) => R
25
- ): State<R> => dom.computed(states, fn);
26
-
27
- export const effect = (fn: () => void): void => dom.effect(fn);
28
-
29
- // Performance helpers
30
- export const batchRender = (container: string | HTMLElement, vNodes: VNode[]): HTMLElement =>
31
- dom.batchRender(container, vNodes);
32
-
33
- export const renderChunked = (
34
- container: string | HTMLElement,
35
- vNodes: VNode[],
36
- chunkSize?: number,
37
- onProgress?: (current: number, total: number) => void
38
- ): HTMLElement => dom.renderChunked(container, vNodes, chunkSize, onProgress);
39
-
40
- export const createVirtualList = <T>(
41
- container: HTMLElement,
42
- items: T[],
43
- renderItem: (item: T, index: number) => VNode,
44
- itemHeight?: number,
45
- bufferSize?: number
46
- ): VirtualListController => dom.createVirtualList(container, items, renderItem, itemHeight, bufferSize);
47
-
48
- export const lazy = <T extends any[], R>(loadFn: () => Promise<(...args: T) => R>) =>
49
- dom.lazy(loadFn);
50
-
51
- export const cleanupUnused = (root: HTMLElement): number =>
52
- dom.cleanupUnusedElements(root);
53
-
54
- // Throttle helper
55
- export const throttle = <T extends any[]>(fn: (...args: T) => void, delay: number) => {
56
- let timer: NodeJS.Timeout | null = null;
57
- return (...args: T) => {
58
- if (!timer) {
59
- timer = setTimeout(() => {
60
- timer = null;
61
- fn(...args);
62
- }, delay);
63
- }
64
- };
65
- };
66
-
67
- // Debounce helper
68
- export const debounce = <T extends any[]>(fn: (...args: T) => void, delay: number) => {
69
- let timer: NodeJS.Timeout | null = null;
70
- return (...args: T) => {
71
- timer && clearTimeout(timer);
72
- timer = setTimeout(() => fn(...args), delay);
73
- };
74
- };
75
-
76
- export function bindValue<T extends string | number | string[]>(state: State<T>): Props {
77
- const props = {
78
- value: state.value,
79
- onInput: (event: Event) => {
80
- const target = event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null;
81
- if (!target) {
82
- return;
83
- }
84
-
85
- if (target instanceof HTMLSelectElement && target.multiple) {
86
- state.value = Array.from(target.selectedOptions).map((option) => option.value) as T;
87
- return;
88
- }
89
-
90
- const nextValue = typeof state.value === 'number'
91
- ? Number(target.value)
92
- : target.value;
93
-
94
- state.value = (typeof state.value === 'number' && Number.isNaN(nextValue))
95
- ? state.value
96
- : nextValue as T;
97
- },
98
- } as Props & { [ELIT_NATIVE_BINDING]: NativeBindingMetadata<T> };
99
-
100
- props[ELIT_NATIVE_BINDING] = {
101
- kind: 'value',
102
- state,
103
- };
104
-
105
- return props;
106
- }
107
-
108
- export function bindChecked(state: State<boolean>): Props {
109
- const props = {
110
- checked: state.value,
111
- onInput: (event: Event) => {
112
- const target = event.target as HTMLInputElement | null;
113
- if (!target) {
114
- return;
115
- }
116
-
117
- state.value = Boolean(target.checked);
118
- },
119
- } as Props & { [ELIT_NATIVE_BINDING]: NativeBindingMetadata<boolean> };
120
-
121
- props[ELIT_NATIVE_BINDING] = {
122
- kind: 'checked',
123
- state,
124
- };
125
-
126
- return props;
127
- }
128
-
129
- // ===== Shared State - syncs with elit-server =====
130
-
131
- type StateChangeCallback<T = any> = (value: T, oldValue: T) => void;
132
-
133
- interface StateMessage {
134
- type: 'state:init' | 'state:update' | 'state:subscribe' | 'state:unsubscribe' | 'state:change';
135
- key: string;
136
- value?: any;
137
- timestamp?: number;
138
- }
139
-
140
- function resolveSharedStateWebSocketUrl(wsUrl?: string): string {
141
- const protocol = typeof location !== 'undefined' && location.protocol === 'https:' ? 'wss:' : 'ws:';
142
- const origin = typeof location !== 'undefined' ? `${protocol}//${location.host}` : `${protocol}//localhost`;
143
-
144
- if (!wsUrl) {
145
- return `${origin}${ELIT_INTERNAL_WS_PATH}`;
146
- }
147
-
148
- if (/^wss?:\/\//i.test(wsUrl)) {
149
- const parsedUrl = new URL(wsUrl);
150
- if (!parsedUrl.pathname || parsedUrl.pathname === '/') {
151
- parsedUrl.pathname = ELIT_INTERNAL_WS_PATH;
152
- }
153
- return parsedUrl.toString();
154
- }
155
-
156
- if (wsUrl.startsWith('/')) {
157
- return `${origin}${wsUrl}`;
158
- }
159
-
160
- return wsUrl;
161
- }
162
-
163
- /**
164
- * Shared State - syncs with elit-server
165
- */
166
- export class SharedState<T = any> {
167
- private localState: State<T>;
168
- private ws: WebSocket | null = null;
169
- private pendingUpdates: T[] = [];
170
- private previousValue: T;
171
-
172
- constructor(
173
- public readonly key: string,
174
- defaultValue: T,
175
- private wsUrl?: string
176
- ) {
177
- this.localState = createState(defaultValue);
178
- this.previousValue = defaultValue;
179
- this.connect();
180
- }
181
-
182
- /**
183
- * Get current value
184
- */
185
- get value(): T {
186
- return this.localState.value;
187
- }
188
-
189
- /**
190
- * Set new value and sync to server
191
- */
192
- set value(newValue: T) {
193
- this.previousValue = this.localState.value;
194
- this.localState.value = newValue;
195
- this.sendToServer(newValue);
196
- }
197
-
198
- /**
199
- * Get the underlying Elit State (for reactive binding)
200
- */
201
- get state(): State<T> {
202
- return this.localState;
203
- }
204
-
205
- /**
206
- * Subscribe to changes (returns Elit State for reactive)
207
- */
208
- onChange(callback: StateChangeCallback<T>): () => void {
209
- return this.localState.subscribe((newValue) => {
210
- const oldValue = this.previousValue;
211
- this.previousValue = newValue;
212
- callback(newValue, oldValue);
213
- });
214
- }
215
-
216
- /**
217
- * Update value using a function
218
- */
219
- update(updater: (current: T) => T): void {
220
- this.value = updater(this.value);
221
- }
222
-
223
- /**
224
- * Connect to WebSocket
225
- */
226
- private connect(): void {
227
- if (typeof window === 'undefined') return;
228
-
229
- const url = resolveSharedStateWebSocketUrl(this.wsUrl);
230
- this.ws = new WebSocket(url);
231
-
232
- this.ws.addEventListener('open', () => {
233
- this.subscribe();
234
-
235
- // Send pending updates
236
- while (this.pendingUpdates.length > 0) {
237
- const value = this.pendingUpdates.shift();
238
- this.sendToServer(value!);
239
- }
240
- });
241
-
242
- this.ws.addEventListener('message', (event) => {
243
- this.handleMessage(event.data);
244
- });
245
-
246
- this.ws.addEventListener('close', () => {
247
- // Reconnect after delay
248
- setTimeout(() => this.connect(), 1000);
249
- });
250
-
251
- this.ws.addEventListener('error', (error) => {
252
- console.error('[SharedState] WebSocket error:', error);
253
- });
254
- }
255
-
256
- /**
257
- * Subscribe to server state
258
- */
259
- private subscribe(): void {
260
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
261
-
262
- this.ws.send(JSON.stringify({
263
- type: 'state:subscribe',
264
- key: this.key
265
- }));
266
- }
267
-
268
- /**
269
- * Handle message from server
270
- */
271
- private handleMessage(data: string): void {
272
- try {
273
- const msg = JSON.parse(data) as StateMessage;
274
-
275
- if (msg.key !== this.key) return;
276
-
277
- if (msg.type === 'state:init' || msg.type === 'state:update') {
278
- // Update local state without sending back to server
279
- this.localState.value = msg.value;
280
- }
281
- } catch (error) {
282
- // Ignore parse errors (could be HMR messages)
283
- }
284
- }
285
-
286
- /**
287
- * Send value to server
288
- */
289
- private sendToServer(value: T): void {
290
- if (!this.ws) return;
291
-
292
- if (this.ws.readyState !== WebSocket.OPEN) {
293
- // Queue update for when connection is ready
294
- this.pendingUpdates.push(value);
295
- return;
296
- }
297
-
298
- this.ws.send(JSON.stringify({
299
- type: 'state:change',
300
- key: this.key,
301
- value
302
- }));
303
- }
304
-
305
- /**
306
- * Disconnect
307
- */
308
- disconnect(): void {
309
- if (this.ws) {
310
- this.ws.close();
311
- this.ws = null;
312
- }
313
- }
314
-
315
- /**
316
- * Destroy state and cleanup
317
- */
318
- destroy(): void {
319
- this.disconnect();
320
- this.localState.destroy();
321
- }
322
- }
323
-
324
- /**
325
- * Create a shared state that syncs with elit-server
326
- */
327
- export function createSharedState<T>(
328
- key: string,
329
- defaultValue: T,
330
- wsUrl?: string
331
- ): SharedState<T> {
332
- return new SharedState(key, defaultValue, wsUrl);
333
- }
334
-
335
- /**
336
- * Shared State Manager for managing multiple shared states
337
- */
338
- class SharedStateManager {
339
- private states = new Map<string, SharedState<any>>();
340
-
341
- /**
342
- * Create or get a shared state
343
- */
344
- create<T>(key: string, defaultValue: T, wsUrl?: string): SharedState<T> {
345
- if (this.states.has(key)) {
346
- return this.states.get(key) as SharedState<T>;
347
- }
348
-
349
- const state = new SharedState<T>(key, defaultValue, wsUrl);
350
- this.states.set(key, state);
351
- return state;
352
- }
353
-
354
- /**
355
- * Get existing state
356
- */
357
- get<T>(key: string): SharedState<T> | undefined {
358
- return this.states.get(key) as SharedState<T>;
359
- }
360
-
361
- /**
362
- * Delete a state
363
- */
364
- delete(key: string): boolean {
365
- const state = this.states.get(key);
366
- if (state) {
367
- state.destroy();
368
- return this.states.delete(key);
369
- }
370
- return false;
371
- }
372
-
373
- /**
374
- * Clear all states
375
- */
376
- clear(): void {
377
- this.states.forEach(state => state.destroy());
378
- this.states.clear();
379
- }
380
- }
381
-
382
- // Export singleton instance
383
- export const sharedStateManager = new SharedStateManager();
384
-
385
- // ===== Reactive Rendering Helpers =====
386
-
387
- // Helper function to schedule RAF updates (reused in reactive and reactiveAs)
388
- const scheduleRAFUpdate = (rafId: number | null, updateFn: () => void): number => {
389
- rafId && cancelAnimationFrame(rafId);
390
- return requestAnimationFrame(() => {
391
- updateFn();
392
- });
393
- };
394
-
395
- // Helper function to render content to fragment (reused in reactive and reactiveAs)
396
- const renderToFragment = (content: VNode | Child | Child[], isVNode?: boolean): DocumentFragment => {
397
- const fragment = document.createDocumentFragment();
398
-
399
- if (Array.isArray(content)) {
400
- // Handle array of children
401
- for (const child of content) {
402
- dom.renderToDOM(child, fragment);
403
- }
404
- } else if (isVNode && content && typeof content === 'object' && 'tagName' in content) {
405
- const { children } = content as VNode;
406
- for (const child of children) {
407
- dom.renderToDOM(child, fragment);
408
- }
409
- } else {
410
- dom.renderToDOM(content, fragment);
411
- }
412
-
413
- return fragment;
414
- };
415
-
416
- // Helper function to update element props (reused in reactive)
417
- const updateElementProps = (element: HTMLElement | SVGElement, props: Props): void => {
418
- for (const key in props) {
419
- const value = props[key];
420
- if (key === 'ref') continue;
421
-
422
- if (key === 'class' || key === 'className') {
423
- (element as HTMLElement).className = Array.isArray(value) ? value.join(' ') : (value || '');
424
- } else if (key === 'style' && typeof value === 'object') {
425
- const s = (element as HTMLElement).style;
426
- for (const k in value) (s as any)[k] = value[k];
427
- } else if (key.startsWith('on')) {
428
- (element as any)[key.toLowerCase()] = value;
429
- } else if (value != null && value !== false) {
430
- element.setAttribute(key, String(value === true ? '' : value));
431
- } else {
432
- element.removeAttribute(key);
433
- }
434
- }
435
- };
436
-
437
- // Reactive element helpers
438
- export const reactive = <T>(state: State<T>, renderFn: (value: T) => VNode | Child | Child[]): VNode => {
439
- let rafId: number | null = null;
440
- let elementRef: HTMLElement | SVGElement | null = null;
441
- let placeholder: Comment | null = null;
442
- let isInDOM = true;
443
-
444
- const initialResult = renderFn(state.value);
445
- const isVNodeResult = initialResult && typeof initialResult === 'object' && 'tagName' in initialResult;
446
- const initialIsNull = initialResult == null || initialResult === false;
447
-
448
- const updateElement = () => {
449
- if (!elementRef && !placeholder) return;
450
-
451
- const newResult = renderFn(state.value);
452
- const resultIsNull = newResult == null || newResult === false;
453
-
454
- if (resultIsNull) {
455
- if (isInDOM && elementRef) {
456
- placeholder = document.createComment('reactive');
457
- elementRef.parentNode?.replaceChild(placeholder, elementRef);
458
- isInDOM = false;
459
- }
460
- } else {
461
- if (!isInDOM && placeholder && elementRef) {
462
- placeholder.parentNode?.replaceChild(elementRef, placeholder);
463
- placeholder = null;
464
- isInDOM = true;
465
- }
466
-
467
- if (elementRef) {
468
- const isCurrentVNode = !!(isVNodeResult && newResult && typeof newResult === 'object' && 'tagName' in newResult);
469
- if (isCurrentVNode) {
470
- const { props } = newResult as VNode;
471
- updateElementProps(elementRef, props);
472
- }
473
- const fragment = renderToFragment(newResult as any, isCurrentVNode);
474
- elementRef.textContent = '';
475
- elementRef.appendChild(fragment);
476
- dom.getElementCache().set(elementRef, true);
477
- }
478
- }
479
- };
480
-
481
- state.subscribe(() => {
482
- rafId = scheduleRAFUpdate(rafId, () => {
483
- updateElement();
484
- rafId = null;
485
- });
486
- });
487
-
488
- const refCallback = (el: HTMLElement | SVGElement) => {
489
- elementRef = el;
490
- if (initialIsNull && el.parentNode) {
491
- placeholder = document.createComment('reactive');
492
- el.parentNode.replaceChild(placeholder, el);
493
- isInDOM = false;
494
- }
495
- };
496
-
497
- if (isVNodeResult) {
498
- const vnode = initialResult as VNode;
499
- return {
500
- tagName: vnode.tagName,
501
- props: { ...vnode.props, ref: refCallback },
502
- children: vnode.children
503
- };
504
- }
505
-
506
- // Handle array result - wrap in fragment-like VNode
507
- const initialChildren = Array.isArray(initialResult) ? initialResult : [initialResult];
508
-
509
- // Use span with display: contents as wrapper (doesn't affect layout)
510
- return { tagName: 'span', props: { ref: refCallback, style: { display: 'contents' } }, children: initialChildren };
511
- };
512
-
513
- // Reactive element with custom wrapper tag
514
- export const reactiveAs = <T>(
515
- tagName: string,
516
- state: State<T>,
517
- renderFn: (value: T) => VNode | Child | Child[],
518
- props: Props = {}
519
- ): VNode => {
520
- let rafId: number | null = null;
521
- let elementRef: HTMLElement | SVGElement | null = null;
522
-
523
- state.subscribe(() => {
524
- rafId = scheduleRAFUpdate(rafId, () => {
525
- if (elementRef) {
526
- const newResult = renderFn(state.value);
527
-
528
- if (newResult == null || newResult === false) {
529
- (elementRef as HTMLElement).style.display = 'none';
530
- elementRef.textContent = '';
531
- } else {
532
- (elementRef as HTMLElement).style.display = '';
533
- const fragment = renderToFragment(newResult as any, false);
534
- elementRef.textContent = '';
535
- elementRef.appendChild(fragment);
536
- }
537
- dom.getElementCache().set(elementRef, true);
538
- }
539
- rafId = null;
540
- });
541
- });
542
-
543
- const refCallback = (el: HTMLElement | SVGElement) => {
544
- elementRef = el;
545
- };
546
-
547
- const initialResult = renderFn(state.value);
548
- const initialChildren = Array.isArray(initialResult) ? initialResult : [initialResult];
549
-
550
- return { tagName, props: { ...props, ref: refCallback }, children: initialChildren };
551
- };
552
-
553
- export const text = (state: State<any> | any): VNode | string =>
554
- (state && state.value !== undefined)
555
- ? reactive(state, v => ({ tagName: 'span', props: {}, children: [String(v)] }))
556
- : String(state);