@wire-dsl/engine 0.9.0 → 0.10.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/dist/index.cjs +1370 -207
- package/dist/index.d.cts +211 -14
- package/dist/index.d.ts +211 -14
- package/dist/index.js +1368 -207
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -31,10 +31,21 @@ interface PropertySourceMap {
|
|
|
31
31
|
nameRange: CodeRange;
|
|
32
32
|
valueRange: CodeRange;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* SourceMap for a single event handler
|
|
36
|
+
* Captures ranges for event name and the full action expression
|
|
37
|
+
*/
|
|
38
|
+
interface EventSourceMap {
|
|
39
|
+
name: string;
|
|
40
|
+
value: string;
|
|
41
|
+
range: CodeRange;
|
|
42
|
+
nameRange: CodeRange;
|
|
43
|
+
valueRange: CodeRange;
|
|
44
|
+
}
|
|
34
45
|
/**
|
|
35
46
|
* Types of nodes in Wire DSL
|
|
36
47
|
*/
|
|
37
|
-
type SourceMapNodeType = 'project' | 'screen' | 'layout' | 'component' | 'component-definition' | 'layout-definition' | 'cell' | 'style' | 'mocks' | 'colors';
|
|
48
|
+
type SourceMapNodeType = 'project' | 'screen' | 'layout' | 'component' | 'component-definition' | 'layout-definition' | 'cell' | 'tab' | 'modal-body' | 'modal-footer' | 'style' | 'mocks' | 'colors';
|
|
38
49
|
/**
|
|
39
50
|
* Main SourceMap entry - represents one node in the AST
|
|
40
51
|
*/
|
|
@@ -53,6 +64,7 @@ interface SourceMapEntry {
|
|
|
53
64
|
nameRange?: CodeRange;
|
|
54
65
|
bodyRange?: CodeRange;
|
|
55
66
|
properties?: Record<string, PropertySourceMap>;
|
|
67
|
+
events?: Record<string, EventSourceMap>;
|
|
56
68
|
insertionPoint?: InsertionPoint;
|
|
57
69
|
}
|
|
58
70
|
/**
|
|
@@ -138,24 +150,58 @@ interface ASTDefinedComponent {
|
|
|
138
150
|
interface ASTScreen {
|
|
139
151
|
type: 'screen';
|
|
140
152
|
name: string;
|
|
141
|
-
params: Record<string, string | number>;
|
|
153
|
+
params: Record<string, string | number | string[]>;
|
|
142
154
|
layout: ASTLayout;
|
|
143
155
|
_meta?: {
|
|
144
156
|
nodeId: string;
|
|
145
157
|
};
|
|
146
158
|
}
|
|
159
|
+
type ASTEventActionType = 'navigate' | 'show' | 'hide' | 'toggle' | 'enable' | 'disable' | 'setTab';
|
|
160
|
+
interface ASTEventAction {
|
|
161
|
+
type: ASTEventActionType;
|
|
162
|
+
screen?: string;
|
|
163
|
+
targetId?: string;
|
|
164
|
+
tabsId?: string;
|
|
165
|
+
index?: number;
|
|
166
|
+
}
|
|
167
|
+
interface ASTEventHandler {
|
|
168
|
+
event: string;
|
|
169
|
+
actions: ASTEventAction[];
|
|
170
|
+
}
|
|
171
|
+
interface ASTTab {
|
|
172
|
+
type: 'tab';
|
|
173
|
+
children: (ASTComponent | ASTLayout)[];
|
|
174
|
+
_meta?: {
|
|
175
|
+
nodeId: string;
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
interface ASTModalBody {
|
|
179
|
+
type: 'modal-body';
|
|
180
|
+
children: (ASTComponent | ASTLayout)[];
|
|
181
|
+
_meta?: {
|
|
182
|
+
nodeId: string;
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
interface ASTModalFooter {
|
|
186
|
+
type: 'modal-footer';
|
|
187
|
+
children: (ASTComponent | ASTLayout)[];
|
|
188
|
+
_meta?: {
|
|
189
|
+
nodeId: string;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
147
192
|
interface ASTLayout {
|
|
148
193
|
type: 'layout';
|
|
149
194
|
layoutType: string;
|
|
150
|
-
params: Record<string, string | number>;
|
|
151
|
-
|
|
195
|
+
params: Record<string, string | number | string[]>;
|
|
196
|
+
events: ASTEventHandler[];
|
|
197
|
+
children: (ASTComponent | ASTLayout | ASTCell | ASTTab | ASTModalBody | ASTModalFooter)[];
|
|
152
198
|
_meta?: {
|
|
153
199
|
nodeId: string;
|
|
154
200
|
};
|
|
155
201
|
}
|
|
156
202
|
interface ASTCell {
|
|
157
203
|
type: 'cell';
|
|
158
|
-
props: Record<string, string | number>;
|
|
204
|
+
props: Record<string, string | number | string[]>;
|
|
159
205
|
children: (ASTComponent | ASTLayout)[];
|
|
160
206
|
_meta?: {
|
|
161
207
|
nodeId: string;
|
|
@@ -164,7 +210,8 @@ interface ASTCell {
|
|
|
164
210
|
interface ASTComponent {
|
|
165
211
|
type: 'component';
|
|
166
212
|
componentType: string;
|
|
167
|
-
props: Record<string, string | number>;
|
|
213
|
+
props: Record<string, string | number | string[]>;
|
|
214
|
+
events: ASTEventHandler[];
|
|
168
215
|
_meta?: {
|
|
169
216
|
nodeId: string;
|
|
170
217
|
};
|
|
@@ -267,15 +314,49 @@ interface IRScreen {
|
|
|
267
314
|
ref: string;
|
|
268
315
|
};
|
|
269
316
|
}
|
|
317
|
+
type IREventAction = {
|
|
318
|
+
type: 'navigate';
|
|
319
|
+
screen: string;
|
|
320
|
+
} | {
|
|
321
|
+
type: 'show';
|
|
322
|
+
targetId: string;
|
|
323
|
+
} | {
|
|
324
|
+
type: 'hide';
|
|
325
|
+
targetId: string;
|
|
326
|
+
} | {
|
|
327
|
+
type: 'toggle';
|
|
328
|
+
targetId: string;
|
|
329
|
+
} | {
|
|
330
|
+
type: 'enable';
|
|
331
|
+
targetId: string;
|
|
332
|
+
} | {
|
|
333
|
+
type: 'disable';
|
|
334
|
+
targetId: string;
|
|
335
|
+
} | {
|
|
336
|
+
type: 'setTab';
|
|
337
|
+
tabsId: string;
|
|
338
|
+
index: number;
|
|
339
|
+
} | {
|
|
340
|
+
type: 'navigateItems';
|
|
341
|
+
screens: string[];
|
|
342
|
+
};
|
|
343
|
+
type IREventName = 'onClick' | 'onChange' | 'onActive' | 'onInactive' | 'onItemsClick' | 'onItemClick' | 'onRowClick' | 'onClose';
|
|
344
|
+
interface IREventHandler {
|
|
345
|
+
event: IREventName;
|
|
346
|
+
actions: IREventAction[];
|
|
347
|
+
}
|
|
348
|
+
/** Special target id used when event target is self (hide(self), show(self), toggle(self)) */
|
|
349
|
+
declare const SELF_TARGET = "_self";
|
|
270
350
|
type IRNode = IRContainerNode | IRComponentNode | IRInstanceNode;
|
|
271
351
|
interface IRContainerNode {
|
|
272
352
|
id: string;
|
|
273
353
|
kind: 'container';
|
|
274
|
-
containerType: 'stack' | 'grid' | 'split' | 'panel' | 'card';
|
|
275
|
-
params: Record<string, string | number>;
|
|
354
|
+
containerType: 'stack' | 'grid' | 'split' | 'panel' | 'card' | 'tabs' | 'tab' | 'modal' | 'modal-body' | 'modal-footer';
|
|
355
|
+
params: Record<string, string | number | string[]>;
|
|
276
356
|
children: Array<{
|
|
277
357
|
ref: string;
|
|
278
358
|
}>;
|
|
359
|
+
events?: IREventHandler[];
|
|
279
360
|
style: IRNodeStyle;
|
|
280
361
|
meta: IRMeta;
|
|
281
362
|
}
|
|
@@ -283,7 +364,9 @@ interface IRComponentNode {
|
|
|
283
364
|
id: string;
|
|
284
365
|
kind: 'component';
|
|
285
366
|
componentType: string;
|
|
286
|
-
props: Record<string, string | number>;
|
|
367
|
+
props: Record<string, string | number | string[]>;
|
|
368
|
+
userDefinedId?: string;
|
|
369
|
+
events?: IREventHandler[];
|
|
287
370
|
style: IRNodeStyle;
|
|
288
371
|
meta: IRMeta;
|
|
289
372
|
}
|
|
@@ -311,7 +394,7 @@ interface IRInstanceNode {
|
|
|
311
394
|
/** Whether it originated from a `define Component` or `define Layout` */
|
|
312
395
|
definitionKind: 'component' | 'layout';
|
|
313
396
|
/** Props/params passed at the call site (e.g. { text: "Hello" }) */
|
|
314
|
-
invocationProps: Record<string, string | number>;
|
|
397
|
+
invocationProps: Record<string, string | number | string[]>;
|
|
315
398
|
/** Reference to the root IR node produced by expanding the definition */
|
|
316
399
|
expandedRoot: {
|
|
317
400
|
ref: string;
|
|
@@ -350,8 +433,14 @@ declare class IRGenerator {
|
|
|
350
433
|
type: string;
|
|
351
434
|
}>;
|
|
352
435
|
private convertLayout;
|
|
436
|
+
private convertTab;
|
|
437
|
+
private convertModalBody;
|
|
438
|
+
private convertModalFooter;
|
|
353
439
|
private convertCell;
|
|
354
440
|
private convertComponent;
|
|
441
|
+
private convertASTEventAction;
|
|
442
|
+
private convertASTEvents;
|
|
443
|
+
private extractOnItemsClickEvent;
|
|
355
444
|
private expandDefinedComponent;
|
|
356
445
|
private expandDefinedLayout;
|
|
357
446
|
private resolveChildrenSlot;
|
|
@@ -431,6 +520,86 @@ declare function resolveDevicePreset(device: string): {
|
|
|
431
520
|
*/
|
|
432
521
|
declare function isValidDevice(device: string): boolean;
|
|
433
522
|
|
|
523
|
+
/**
|
|
524
|
+
* Wire DSL Play Test State Management
|
|
525
|
+
*
|
|
526
|
+
* Provides the `applyStateChange` function for mutating a copy of the IR
|
|
527
|
+
* during play test sessions. The engine stays 100% static — this module
|
|
528
|
+
* produces a NEW IR (immutable pattern) from a change descriptor.
|
|
529
|
+
*
|
|
530
|
+
* The Wire source is never touched during play test. The canvas keeps a
|
|
531
|
+
* mutable copy of the IR per session and discards it when play test ends.
|
|
532
|
+
*
|
|
533
|
+
* Usage (Wire Studio / Canvas):
|
|
534
|
+
* const newIR = applyStateChange(currentIR, { type: 'setVisible', targetId: 'confirmModal', visible: true });
|
|
535
|
+
* const newSVG = render(newIR, screenName);
|
|
536
|
+
*/
|
|
537
|
+
|
|
538
|
+
type IRStateChange =
|
|
539
|
+
/** Show or hide a node by its userDefinedId (or '_self' resolved from originNodeId) */
|
|
540
|
+
{
|
|
541
|
+
type: 'setVisible';
|
|
542
|
+
targetId: string;
|
|
543
|
+
visible: boolean;
|
|
544
|
+
}
|
|
545
|
+
/** Toggle visibility of a node by its userDefinedId (or '_self') */
|
|
546
|
+
| {
|
|
547
|
+
type: 'toggleVisible';
|
|
548
|
+
targetId: string;
|
|
549
|
+
}
|
|
550
|
+
/** Change the active tab index in a layout tabs container */
|
|
551
|
+
| {
|
|
552
|
+
type: 'setActiveTab';
|
|
553
|
+
tabsId: string;
|
|
554
|
+
index: number;
|
|
555
|
+
}
|
|
556
|
+
/** Set checked state on Checkbox / Radio controls */
|
|
557
|
+
| {
|
|
558
|
+
type: 'setChecked';
|
|
559
|
+
targetId: string;
|
|
560
|
+
checked: boolean;
|
|
561
|
+
}
|
|
562
|
+
/** Toggle checked state on Checkbox / Radio controls */
|
|
563
|
+
| {
|
|
564
|
+
type: 'toggleChecked';
|
|
565
|
+
targetId: string;
|
|
566
|
+
}
|
|
567
|
+
/** Set enabled state on Toggle controls */
|
|
568
|
+
| {
|
|
569
|
+
type: 'setEnabled';
|
|
570
|
+
targetId: string;
|
|
571
|
+
enabled: boolean;
|
|
572
|
+
}
|
|
573
|
+
/** Toggle enabled state on Toggle controls */
|
|
574
|
+
| {
|
|
575
|
+
type: 'toggleEnabled';
|
|
576
|
+
targetId: string;
|
|
577
|
+
}
|
|
578
|
+
/** Set disabled state on any component (enable = disabled false, disable = disabled true) */
|
|
579
|
+
| {
|
|
580
|
+
type: 'setDisabled';
|
|
581
|
+
targetId: string;
|
|
582
|
+
disabled: boolean;
|
|
583
|
+
}
|
|
584
|
+
/** Navigate to a different screen (changes the active screen id in the IR) */
|
|
585
|
+
| {
|
|
586
|
+
type: 'navigateTo';
|
|
587
|
+
screen: string;
|
|
588
|
+
};
|
|
589
|
+
/**
|
|
590
|
+
* Apply a state change to a copy of the IR, returning a new IR object.
|
|
591
|
+
*
|
|
592
|
+
* - Does NOT mutate the input IR
|
|
593
|
+
* - Returns a new IR with the minimal change applied
|
|
594
|
+
* - `originNodeId` is required when `targetId === '_self'` to resolve the self reference
|
|
595
|
+
*
|
|
596
|
+
* @param ir The current IR (from the canvas's mutable session copy)
|
|
597
|
+
* @param change The state change to apply
|
|
598
|
+
* @param originNodeId The nodeId of the element that triggered the event (required for self-target)
|
|
599
|
+
* @returns A new IR with the change applied
|
|
600
|
+
*/
|
|
601
|
+
declare function applyStateChange(ir: IRContract, change: IRStateChange, originNodeId?: string): IRContract;
|
|
602
|
+
|
|
434
603
|
/**
|
|
435
604
|
* Layout Engine
|
|
436
605
|
*
|
|
@@ -463,6 +632,8 @@ declare class LayoutEngine {
|
|
|
463
632
|
private calculateSplit;
|
|
464
633
|
private calculatePanel;
|
|
465
634
|
private calculateCard;
|
|
635
|
+
private calculateTabs;
|
|
636
|
+
private calculateModal;
|
|
466
637
|
/**
|
|
467
638
|
* Calculate layout for an instance node.
|
|
468
639
|
* The instance is a transparent wrapper — its bounding box equals the
|
|
@@ -497,6 +668,11 @@ declare class LayoutEngine {
|
|
|
497
668
|
private calculateChildHeight;
|
|
498
669
|
private calculateChildWidth;
|
|
499
670
|
private estimateTextWidth;
|
|
671
|
+
/**
|
|
672
|
+
* Returns false only when the node has an explicit `visible: 'false'` param/prop.
|
|
673
|
+
* Missing or any other value is treated as visible.
|
|
674
|
+
*/
|
|
675
|
+
private isNodeVisible;
|
|
500
676
|
private parseBooleanProp;
|
|
501
677
|
private adjustNodeYPositions;
|
|
502
678
|
}
|
|
@@ -717,7 +893,8 @@ declare class SVGRenderer {
|
|
|
717
893
|
protected renderSeparate(node: IRComponentNode, _pos: any): string;
|
|
718
894
|
protected renderAlert(node: IRComponentNode, pos: any): string;
|
|
719
895
|
protected renderBadge(node: IRComponentNode, pos: any): string;
|
|
720
|
-
protected
|
|
896
|
+
protected renderModalDecoration(node: IRNode, pos: any, output: string[]): void;
|
|
897
|
+
protected renderModalFooterDecoration(pos: any, output: string[]): void;
|
|
721
898
|
protected renderList(node: IRComponentNode, pos: any): string;
|
|
722
899
|
protected renderGenericComponent(node: IRComponentNode, pos: any): string;
|
|
723
900
|
protected renderStat(node: IRComponentNode, pos: any): string;
|
|
@@ -806,10 +983,17 @@ declare class SVGRenderer {
|
|
|
806
983
|
private buildParentContainerIndex;
|
|
807
984
|
protected escapeXml(text: string): string;
|
|
808
985
|
/**
|
|
809
|
-
* Get data-node-id
|
|
810
|
-
* Enables bidirectional selection between code and canvas
|
|
986
|
+
* Get data-node-id and event data attributes for SVG elements.
|
|
987
|
+
* Enables bidirectional selection between code and canvas (data-node-id)
|
|
988
|
+
* and play test interactivity (data-event-*, data-user-id, data-tabs-id).
|
|
811
989
|
*/
|
|
812
990
|
protected getDataNodeId(node: IRComponentNode | IRContainerNode | IRInstanceNode): string;
|
|
991
|
+
private isScopedEvent;
|
|
992
|
+
private getScopedEventAttrs;
|
|
993
|
+
private getTabsTriggerAttrs;
|
|
994
|
+
private serializeEventHandler;
|
|
995
|
+
private eventNameToDataAttr;
|
|
996
|
+
private serializeEventAction;
|
|
813
997
|
}
|
|
814
998
|
declare function renderToSVG(ir: IRContract, layout: LayoutResult, options?: SVGRenderOptions): string;
|
|
815
999
|
declare function createSVGElement(tag: string, attrs: Record<string, string | number>, children?: string[]): string;
|
|
@@ -1218,6 +1402,19 @@ declare class SourceMapBuilder {
|
|
|
1218
1402
|
separator?: any;
|
|
1219
1403
|
full?: any;
|
|
1220
1404
|
}): PropertySourceMap;
|
|
1405
|
+
/**
|
|
1406
|
+
* Add an event handler to an existing node in the SourceMap
|
|
1407
|
+
* Events have action expressions as values (e.g., "show(modal) & navigate(Home)")
|
|
1408
|
+
*
|
|
1409
|
+
* @param nodeId - ID of the node that owns this event
|
|
1410
|
+
* @param eventName - Name of the event (e.g., "onClick", "onClose")
|
|
1411
|
+
* @param tokens - Captured tokens: name token for event key, CST node for actionChain
|
|
1412
|
+
* @returns The EventSourceMap entry created
|
|
1413
|
+
*/
|
|
1414
|
+
addEvent(nodeId: string, eventName: string, tokens: {
|
|
1415
|
+
name: any;
|
|
1416
|
+
value: any;
|
|
1417
|
+
}): EventSourceMap;
|
|
1221
1418
|
/**
|
|
1222
1419
|
* Push a parent onto the stack (when entering a container node)
|
|
1223
1420
|
*/
|
|
@@ -1404,4 +1601,4 @@ declare class SourceMapResolver {
|
|
|
1404
1601
|
|
|
1405
1602
|
declare const version = "0.0.1";
|
|
1406
1603
|
|
|
1407
|
-
export { type AST, type ASTCell, type ASTComponent, type ASTDefinedComponent, type ASTDefinedLayout, type ASTLayout, type ASTScreen, type CapturedTokens, type CodeRange, DENSITY_TOKENS, DEVICE_PRESETS, type DesignTokens, type DevicePreset, type IRComponent, type IRComponentNode, type IRContainerNode, type IRContract, IRGenerator, type IRInstanceNode, type IRLayout, type IRMeta, type IRMetadata, type IRNode, type IRNodeStyle, type IRProject, type IRScreen, type IRStyle, type IRWireframe, type InsertionPoint, LayoutEngine, type LayoutPosition, type LayoutResult, type ParseDiagnosticsResult, type ParseError, type ParseResult, type ParseWireDSLWithSourceMapOptions, type ParsedComponent, type ParsedWireframe, type Position, type PositionQueryResult, type PropertySourceMap, type SVGComponent, type SVGRenderOptions, SVGRenderer, SkeletonSVGRenderer, SketchSVGRenderer, SourceMapBuilder, type SourceMapEntry, type SourceMapNodeType, SourceMapResolver, buildSVG, calculateLayout, createSVGElement, generateIR, generateStableNodeId, getTypeFromNodeId, isValidDevice, isValidNodeId, parseWireDSL, parseWireDSLWithSourceMap, renderToSVG, resolveDevicePreset, resolveGridPosition, resolveTokens, version };
|
|
1604
|
+
export { type AST, type ASTCell, type ASTComponent, type ASTDefinedComponent, type ASTDefinedLayout, type ASTEventAction, type ASTEventActionType, type ASTEventHandler, type ASTLayout, type ASTModalBody, type ASTModalFooter, type ASTScreen, type ASTTab, type CapturedTokens, type CodeRange, DENSITY_TOKENS, DEVICE_PRESETS, type DesignTokens, type DevicePreset, type EventSourceMap, type IRComponent, type IRComponentNode, type IRContainerNode, type IRContract, type IREventAction, type IREventHandler, type IREventName, IRGenerator, type IRInstanceNode, type IRLayout, type IRMeta, type IRMetadata, type IRNode, type IRNodeStyle, type IRProject, type IRScreen, type IRStateChange, type IRStyle, type IRWireframe, type InsertionPoint, LayoutEngine, type LayoutPosition, type LayoutResult, type ParseDiagnosticsResult, type ParseError, type ParseResult, type ParseWireDSLWithSourceMapOptions, type ParsedComponent, type ParsedWireframe, type Position, type PositionQueryResult, type PropertySourceMap, SELF_TARGET, type SVGComponent, type SVGRenderOptions, SVGRenderer, SkeletonSVGRenderer, SketchSVGRenderer, SourceMapBuilder, type SourceMapEntry, type SourceMapNodeType, SourceMapResolver, applyStateChange, buildSVG, calculateLayout, createSVGElement, generateIR, generateStableNodeId, getTypeFromNodeId, isValidDevice, isValidNodeId, parseWireDSL, parseWireDSLWithSourceMap, renderToSVG, resolveDevicePreset, resolveGridPosition, resolveTokens, version };
|