0x-lang 0.1.16 → 0.1.18
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/compiler.js +1 -1
- package/dist/compiler.js.map +1 -1
- package/dist/generators/react.js +93 -21
- package/dist/generators/react.js.map +1 -1
- package/dist/generators/shared.d.ts +21 -0
- package/dist/generators/shared.js +123 -0
- package/dist/generators/shared.js.map +1 -1
- package/dist/generators/svelte.js +92 -20
- package/dist/generators/svelte.js.map +1 -1
- package/dist/generators/vue.js +88 -22
- package/dist/generators/vue.js.map +1 -1
- package/dist/parser.js +76 -11
- package/dist/parser.js.map +1 -1
- package/package.json +1 -1
package/dist/compiler.js
CHANGED
|
@@ -42,7 +42,7 @@ export function compile(source, options) {
|
|
|
42
42
|
}
|
|
43
43
|
// Post-process: strip source map comments and V3 source map if disabled
|
|
44
44
|
if (options.sourceMap === false) {
|
|
45
|
-
result = { ...result, code: result.code.replace(/\{\/\* 0x:L\d+ \*\/\}/g, '').replace(/<!-- 0x:L\d+ -->/g, ''), sourceMap: undefined };
|
|
45
|
+
result = { ...result, code: result.code.replace(/\{\/\* 0x:L\d+ \*\/\}/g, '').replace(/<!-- 0x:L\d+ -->/g, '').replace(/\/\/ 0x:L\d+\n\s*/g, ''), sourceMap: undefined };
|
|
46
46
|
}
|
|
47
47
|
else if (result.sourceMap) {
|
|
48
48
|
// Append inline sourceMappingURL as base64 data URL
|
package/dist/compiler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.js","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA,uBAAuB;AAEvB,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgB1C,MAAM,UAAU,OAAO,CAAC,MAAc,EAAE,OAAuB;IAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAE1B,8BAA8B;IAC9B,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClG,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,IAAI,MAAqB,CAAC;IAC1B,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,OAAO;YACV,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM;QACR,KAAK,KAAK;YACR,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YAC1B,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM;QACR,KAAK,cAAc;YACjB,MAAM,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM;QACR,KAAK,WAAW;YACd,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,wEAAwE;IACxE,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;QAChC,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"compiler.js","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
|
package/dist/generators/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// 0x → React Code Generator
|
|
2
|
-
import { SIZE_MAP, unquote, capitalize, parseGradient, addPx } from './shared.js';
|
|
2
|
+
import { SIZE_MAP, unquote, capitalize, parseGradient, addPx, getPassthroughProps, KNOWN_LAYOUT_PROPS, KNOWN_TEXT_PROPS, KNOWN_BUTTON_PROPS, KNOWN_INPUT_PROPS, KNOWN_IMAGE_PROPS, KNOWN_LINK_PROPS, KNOWN_TOGGLE_PROPS, KNOWN_SELECT_PROPS } from './shared.js';
|
|
3
3
|
import { SourceMapBuilder } from './source-map.js';
|
|
4
4
|
export function ctx() {
|
|
5
5
|
return {
|
|
@@ -369,7 +369,8 @@ function genDerived(node, c) {
|
|
|
369
369
|
c.readOnly = prevReadOnly;
|
|
370
370
|
const { deps, warning } = extractDepsWithWarning(node.expression, c);
|
|
371
371
|
const warnComment = warning ? ` ${warning}` : '';
|
|
372
|
-
|
|
372
|
+
const sc = node.loc?.line ? `// 0x:L${node.loc.line}\n ` : '';
|
|
373
|
+
return `${sc}${warnComment ? warnComment + '\n ' : ''}const ${node.name} = useMemo(() => ${expr}, [${deps.join(', ')}]);`;
|
|
373
374
|
}
|
|
374
375
|
function genCheck(node, c) {
|
|
375
376
|
const cond = genExpr(node.condition, c);
|
|
@@ -400,32 +401,36 @@ function genFunction(node, c) {
|
|
|
400
401
|
// requires
|
|
401
402
|
const requireChecks = node.requires.map(r => `if (!(${genExpr(r, c)})) throw new Error('Precondition failed');`).join('\n ');
|
|
402
403
|
const allBody = [requireChecks, body].filter(Boolean).join('\n ');
|
|
403
|
-
|
|
404
|
+
const sc = node.loc?.line ? `// 0x:L${node.loc.line}\n ` : '';
|
|
405
|
+
return `${sc}const ${node.name} = ${asyncKw}(${params}) => {\n ${allBody}\n };`;
|
|
404
406
|
}
|
|
405
407
|
// ── Lifecycle ───────────────────────────────────────
|
|
406
408
|
function genOnMount(node, c) {
|
|
407
409
|
c.imports.add('useEffect');
|
|
408
410
|
const body = node.body.map(s => genStatement(s, c)).join('\n ');
|
|
409
411
|
const hasAwait = bodyContainsAwait(node.body);
|
|
412
|
+
const sc = node.loc?.line ? `// 0x:L${node.loc.line}\n ` : '';
|
|
410
413
|
if (hasAwait) {
|
|
411
|
-
return
|
|
414
|
+
return `${sc}useEffect(() => {\n (async () => {\n ${body}\n })();\n }, []);`;
|
|
412
415
|
}
|
|
413
|
-
return
|
|
416
|
+
return `${sc}useEffect(() => {\n ${body}\n }, []);`;
|
|
414
417
|
}
|
|
415
418
|
function genOnDestroy(node, c) {
|
|
416
419
|
c.imports.add('useEffect');
|
|
417
420
|
const body = node.body.map(s => genStatement(s, c)).join('\n ');
|
|
418
|
-
|
|
421
|
+
const sc = node.loc?.line ? `// 0x:L${node.loc.line}\n ` : '';
|
|
422
|
+
return `${sc}useEffect(() => {\n return () => {\n ${body}\n };\n }, []);`;
|
|
419
423
|
}
|
|
420
424
|
function genWatch(node, c) {
|
|
421
425
|
c.imports.add('useEffect');
|
|
422
426
|
const body = node.body.map(s => genStatement(s, c)).join('\n ');
|
|
423
427
|
const vars = (node.variables || [node.variable]).join(', ');
|
|
424
428
|
const hasAwait = bodyContainsAwait(node.body);
|
|
429
|
+
const sc = node.loc?.line ? `// 0x:L${node.loc.line}\n ` : '';
|
|
425
430
|
if (hasAwait) {
|
|
426
|
-
return
|
|
431
|
+
return `${sc}useEffect(() => {\n (async () => {\n ${body}\n })();\n }, [${vars}]);`;
|
|
427
432
|
}
|
|
428
|
-
return
|
|
433
|
+
return `${sc}useEffect(() => {\n ${body}\n }, [${vars}]);`;
|
|
429
434
|
}
|
|
430
435
|
// ── UI Nodes ────────────────────────────────────────
|
|
431
436
|
function srcComment(node) {
|
|
@@ -522,10 +527,14 @@ function genLayout(node, c) {
|
|
|
522
527
|
style['flexDirection'] = node.direction === 'row' ? 'row' : 'column';
|
|
523
528
|
}
|
|
524
529
|
// Process layout props
|
|
530
|
+
let className = null;
|
|
525
531
|
for (const [key, val] of Object.entries(node.props)) {
|
|
526
532
|
const v = genExpr(val, c);
|
|
527
533
|
const isDynamic = val.kind === 'braced' || val.kind === 'ternary' || val.kind === 'binary' || val.kind === 'member' || val.kind === 'call';
|
|
528
534
|
switch (key) {
|
|
535
|
+
case 'class':
|
|
536
|
+
className = unquote(v);
|
|
537
|
+
break;
|
|
529
538
|
case 'gap':
|
|
530
539
|
style['gap'] = addPx(v);
|
|
531
540
|
break;
|
|
@@ -570,9 +579,17 @@ function genLayout(node, c) {
|
|
|
570
579
|
break;
|
|
571
580
|
case 'scroll': {
|
|
572
581
|
const sv = unquote(v);
|
|
573
|
-
|
|
582
|
+
if (sv === 'y')
|
|
583
|
+
style['overflowY'] = 'auto';
|
|
584
|
+
else if (sv === 'x')
|
|
585
|
+
style['overflowX'] = 'auto';
|
|
586
|
+
else
|
|
587
|
+
style['overflow'] = 'auto';
|
|
574
588
|
break;
|
|
575
589
|
}
|
|
590
|
+
case 'wrap':
|
|
591
|
+
style['flexWrap'] = 'wrap';
|
|
592
|
+
break;
|
|
576
593
|
case 'radius':
|
|
577
594
|
style['borderRadius'] = addPx(v);
|
|
578
595
|
break;
|
|
@@ -600,17 +617,23 @@ function genLayout(node, c) {
|
|
|
600
617
|
}
|
|
601
618
|
}
|
|
602
619
|
const styleStr = genStyleObj(style, dynamicKeys);
|
|
620
|
+
const classAttr = className ? ` className="${className}"` : '';
|
|
621
|
+
const extra = getPassthroughProps(node.props, KNOWN_LAYOUT_PROPS, e => genExpr(e, c), 'react');
|
|
603
622
|
const children = node.children.map(ch => genUINode(ch, c)).join('\n');
|
|
604
623
|
const sc = srcComment(node);
|
|
605
|
-
return `${sc}<div style={${styleStr}}>\n${children}\n</div>`;
|
|
624
|
+
return `${sc}<div${classAttr} style={${styleStr}}${extra}>\n${children}\n</div>`;
|
|
606
625
|
}
|
|
607
626
|
function genText(node, c) {
|
|
608
627
|
const style = {};
|
|
609
628
|
const dynamicKeys = new Set();
|
|
629
|
+
let className = null;
|
|
610
630
|
for (const [key, val] of Object.entries(node.props)) {
|
|
611
631
|
const v = genExpr(val, c);
|
|
612
632
|
const isDynamic = val.kind === 'braced' || val.kind === 'ternary' || val.kind === 'binary' || val.kind === 'member' || val.kind === 'call';
|
|
613
633
|
switch (key) {
|
|
634
|
+
case 'class':
|
|
635
|
+
className = unquote(v);
|
|
636
|
+
break;
|
|
614
637
|
case 'size': {
|
|
615
638
|
const uv = unquote(v);
|
|
616
639
|
style['fontSize'] = SIZE_MAP[uv] || `${uv}px`;
|
|
@@ -658,19 +681,21 @@ function genText(node, c) {
|
|
|
658
681
|
}
|
|
659
682
|
}
|
|
660
683
|
const content = genTextContent(node.content, c);
|
|
684
|
+
const classAttr = className ? ` className="${className}"` : '';
|
|
661
685
|
const styleStr = Object.keys(style).length > 0 ? ` style={${genStyleObj(style, dynamicKeys)}}` : '';
|
|
686
|
+
const extra = getPassthroughProps(node.props, KNOWN_TEXT_PROPS, e => genExpr(e, c), 'react');
|
|
662
687
|
// Badge prop: render a badge indicator next to content
|
|
663
688
|
const badgeExpr = node.props['badge'];
|
|
664
689
|
const tooltipExpr = node.props['tooltip'];
|
|
665
690
|
const sc = srcComment(node);
|
|
666
|
-
let result = `${sc}<span${styleStr}>${content}</span>`;
|
|
691
|
+
let result = `${sc}<span${classAttr}${styleStr}${extra}>${content}</span>`;
|
|
667
692
|
if (badgeExpr) {
|
|
668
693
|
const badge = genExpr(badgeExpr, c);
|
|
669
|
-
result = `<span style={{ position: 'relative', display: 'inline-flex', alignItems: 'center' }}>\n<span${styleStr}>${content}</span>\n<span style={{ marginLeft: '6px', padding: '2px 6px', fontSize: '12px', fontWeight: 'bold', borderRadius: '9999px', backgroundColor: '#ef4444', color: '#fff', minWidth: '20px', textAlign: 'center' }}>{${badge}}</span>\n</span>`;
|
|
694
|
+
result = `<span${classAttr} style={{ position: 'relative', display: 'inline-flex', alignItems: 'center' }}>\n<span${styleStr}>${content}</span>\n<span style={{ marginLeft: '6px', padding: '2px 6px', fontSize: '12px', fontWeight: 'bold', borderRadius: '9999px', backgroundColor: '#ef4444', color: '#fff', minWidth: '20px', textAlign: 'center' }}>{${badge}}</span>\n</span>`;
|
|
670
695
|
}
|
|
671
696
|
if (tooltipExpr) {
|
|
672
697
|
const tooltip = genExpr(tooltipExpr, c);
|
|
673
|
-
result = `<span title={${tooltip}}>${badgeExpr ? result.replace(/^<span
|
|
698
|
+
result = `<span${classAttr} title={${tooltip}}>${badgeExpr ? result.replace(/^<span[^>]*>/, '<span>') : `<span${styleStr}>${content}</span>`}</span>`;
|
|
674
699
|
}
|
|
675
700
|
return result;
|
|
676
701
|
}
|
|
@@ -678,24 +703,37 @@ function genButton(node, c) {
|
|
|
678
703
|
const label = genTextContent(node.label, c);
|
|
679
704
|
const actionCode = genActionExpr(node.action, c);
|
|
680
705
|
const styleProps = [];
|
|
706
|
+
let className = null;
|
|
681
707
|
for (const [key, val] of Object.entries(node.props)) {
|
|
682
708
|
const v = genExpr(val, c);
|
|
683
709
|
switch (key) {
|
|
684
|
-
case '
|
|
685
|
-
|
|
710
|
+
case 'class':
|
|
711
|
+
className = unquote(v);
|
|
712
|
+
break;
|
|
713
|
+
case 'style': {
|
|
714
|
+
const sv = unquote(v);
|
|
715
|
+
if (sv === 'primary')
|
|
716
|
+
styleProps.push('style={{ backgroundColor: "#3b82f6", color: "white", border: "none", padding: "8px 16px", borderRadius: "6px", cursor: "pointer" }}');
|
|
717
|
+
else if (sv === 'danger')
|
|
718
|
+
styleProps.push('style={{ backgroundColor: "#ef4444", color: "white", border: "none", padding: "8px 16px", borderRadius: "6px", cursor: "pointer" }}');
|
|
686
719
|
break;
|
|
720
|
+
}
|
|
687
721
|
case 'disabled':
|
|
688
722
|
styleProps.push(`disabled={${v}}`);
|
|
689
723
|
break;
|
|
690
724
|
case 'size': /* handled in style */ break;
|
|
691
725
|
}
|
|
692
726
|
}
|
|
727
|
+
if (className)
|
|
728
|
+
styleProps.push(`className="${className}"`);
|
|
729
|
+
const extra = getPassthroughProps(node.props, KNOWN_BUTTON_PROPS, e => genExpr(e, c), 'react');
|
|
693
730
|
const propsStr = styleProps.join(' ');
|
|
694
731
|
const sc = srcComment(node);
|
|
695
|
-
return `${sc}<button onClick={() => ${actionCode}}${propsStr ? ' ' + propsStr : ''}>${label}</button>`;
|
|
732
|
+
return `${sc}<button onClick={() => ${actionCode}}${propsStr ? ' ' + propsStr : ''}${extra}>${label}</button>`;
|
|
696
733
|
}
|
|
697
734
|
function genInput(node, c) {
|
|
698
735
|
const setter = 'set' + capitalize(node.binding);
|
|
736
|
+
let className = null;
|
|
699
737
|
const props = [
|
|
700
738
|
`value={${node.binding}}`,
|
|
701
739
|
`onChange={e => ${setter}(e.target.value)}`,
|
|
@@ -703,6 +741,9 @@ function genInput(node, c) {
|
|
|
703
741
|
for (const [key, val] of Object.entries(node.props)) {
|
|
704
742
|
const v = genExpr(val, c);
|
|
705
743
|
switch (key) {
|
|
744
|
+
case 'class':
|
|
745
|
+
className = unquote(v);
|
|
746
|
+
break;
|
|
706
747
|
case 'placeholder':
|
|
707
748
|
props.push(`placeholder=${quoteJsx(v)}`);
|
|
708
749
|
break;
|
|
@@ -718,16 +759,23 @@ function genInput(node, c) {
|
|
|
718
759
|
props.push(`onKeyPress={e => ${handler}(e.key)}`);
|
|
719
760
|
}
|
|
720
761
|
}
|
|
762
|
+
if (className)
|
|
763
|
+
props.push(`className="${className}"`);
|
|
764
|
+
const extra = getPassthroughProps(node.props, KNOWN_INPUT_PROPS, e => genExpr(e, c), 'react');
|
|
721
765
|
const sc = srcComment(node);
|
|
722
|
-
return `${sc}<input ${props.join(' ')} />`;
|
|
766
|
+
return `${sc}<input ${props.join(' ')}${extra} />`;
|
|
723
767
|
}
|
|
724
768
|
function genImage(node, c) {
|
|
725
769
|
const src = genExpr(node.src, c);
|
|
726
770
|
const props = [`src={${src}}`];
|
|
727
771
|
const style = {};
|
|
772
|
+
let className = null;
|
|
728
773
|
for (const [key, val] of Object.entries(node.props)) {
|
|
729
774
|
const v = genExpr(val, c);
|
|
730
775
|
switch (key) {
|
|
776
|
+
case 'class':
|
|
777
|
+
className = unquote(v);
|
|
778
|
+
break;
|
|
731
779
|
case 'width':
|
|
732
780
|
props.push(`width="${v}"`);
|
|
733
781
|
break;
|
|
@@ -751,16 +799,26 @@ function genImage(node, c) {
|
|
|
751
799
|
}
|
|
752
800
|
}
|
|
753
801
|
}
|
|
802
|
+
if (className)
|
|
803
|
+
props.push(`className="${className}"`);
|
|
754
804
|
if (Object.keys(style).length > 0) {
|
|
755
805
|
const entries = Object.entries(style).map(([k, v]) => `${k}: ${v}`).join(', ');
|
|
756
806
|
props.push(`style={{ ${entries} }}`);
|
|
757
807
|
}
|
|
758
|
-
|
|
808
|
+
const extra = getPassthroughProps(node.props, KNOWN_IMAGE_PROPS, e => genExpr(e, c), 'react');
|
|
809
|
+
return `<img ${props.join(' ')}${extra} />`;
|
|
759
810
|
}
|
|
760
811
|
function genLink(node, c) {
|
|
761
812
|
const label = genTextContent(node.label, c);
|
|
762
813
|
const href = genExpr(node.href, c);
|
|
763
|
-
|
|
814
|
+
let className = null;
|
|
815
|
+
for (const [key, val] of Object.entries(node.props || {})) {
|
|
816
|
+
if (key === 'class')
|
|
817
|
+
className = unquote(genExpr(val, c));
|
|
818
|
+
}
|
|
819
|
+
const classAttr = className ? ` className="${className}"` : '';
|
|
820
|
+
const extra = getPassthroughProps(node.props || {}, KNOWN_LINK_PROPS, e => genExpr(e, c), 'react');
|
|
821
|
+
return `<a href={${href}}${classAttr}${extra}>${label}</a>`;
|
|
764
822
|
}
|
|
765
823
|
function genToggle(node, c) {
|
|
766
824
|
const binding = node.binding;
|
|
@@ -773,12 +831,26 @@ function genToggle(node, c) {
|
|
|
773
831
|
else {
|
|
774
832
|
setter = `set${capitalize(parts[0])}(prev => ({...prev, ${parts.slice(1).join('.')}: !prev.${parts.slice(1).join('.')}}))`;
|
|
775
833
|
}
|
|
776
|
-
|
|
834
|
+
let className = null;
|
|
835
|
+
for (const [key, val] of Object.entries(node.props || {})) {
|
|
836
|
+
if (key === 'class')
|
|
837
|
+
className = unquote(genExpr(val, c));
|
|
838
|
+
}
|
|
839
|
+
const classAttr = className ? ` className="${className}"` : '';
|
|
840
|
+
const extra = getPassthroughProps(node.props || {}, KNOWN_TOGGLE_PROPS, e => genExpr(e, c), 'react');
|
|
841
|
+
return `<input type="checkbox" checked={${binding}} onChange={() => ${setter}}${classAttr}${extra} />`;
|
|
777
842
|
}
|
|
778
843
|
function genSelect(node, c) {
|
|
779
844
|
const setter = 'set' + capitalize(node.binding);
|
|
780
845
|
const options = genExpr(node.options, c);
|
|
781
|
-
|
|
846
|
+
let className = null;
|
|
847
|
+
for (const [key, val] of Object.entries(node.props || {})) {
|
|
848
|
+
if (key === 'class')
|
|
849
|
+
className = unquote(genExpr(val, c));
|
|
850
|
+
}
|
|
851
|
+
const classAttr = className ? ` className="${className}"` : '';
|
|
852
|
+
const extra = getPassthroughProps(node.props || {}, KNOWN_SELECT_PROPS, e => genExpr(e, c), 'react');
|
|
853
|
+
return `<select value={${node.binding}} onChange={e => ${setter}(e.target.value)}${classAttr}${extra}>\n {${options}.map(opt => <option key={opt} value={opt}>{opt}</option>)}\n</select>`;
|
|
782
854
|
}
|
|
783
855
|
function genComponentCall(node, c) {
|
|
784
856
|
const parts = [];
|