@tsrx/vue 0.0.11 → 0.0.13

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Vue compiler built on @tsrx/core",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.0.11",
6
+ "version": "0.0.13",
7
7
  "type": "module",
8
8
  "publishConfig": {
9
9
  "access": "public"
@@ -20,12 +20,15 @@
20
20
  },
21
21
  "./error-boundary": {
22
22
  "default": "./src/error-boundary.js"
23
+ },
24
+ "./merge-refs": {
25
+ "default": "./src/merge-refs.js"
23
26
  }
24
27
  },
25
28
  "dependencies": {
26
29
  "esrap": "^2.1.0",
27
30
  "zimmerframe": "^1.1.2",
28
- "@tsrx/core": "0.0.16"
31
+ "@tsrx/core": "0.0.18"
29
32
  },
30
33
  "peerDependencies": {
31
34
  "vue": ">=3.5",
@@ -0,0 +1 @@
1
+ export { mergeRefs } from '@tsrx/core/runtime/merge-refs';
package/src/transform.js CHANGED
@@ -25,10 +25,12 @@ const vue_platform = {
25
25
  imports: {
26
26
  suspense: 'vue',
27
27
  errorBoundary: '@tsrx/vue/error-boundary',
28
+ mergeRefs: '@tsrx/vue/merge-refs',
28
29
  },
29
30
  jsx: {
30
31
  rewriteClassAttr: false,
31
32
  acceptedTsxKinds: ['vue'],
33
+ multiRefStrategy: 'merge-refs',
32
34
  },
33
35
  validation: {
34
36
  requireUseServerForAwait: true,
@@ -404,77 +406,31 @@ function is_vue_setup_call(call_expression) {
404
406
  }
405
407
 
406
408
  /**
409
+ * Reject `{ref expr}` on composite (component-like) elements: Vue component
410
+ * refs resolve to the component instance, not the rendered DOM node, so
411
+ * Ripple-style component refs don't have a meaningful DOM target. Multi-ref
412
+ * merging itself is handled by the shared `merge_duplicate_refs` pass via
413
+ * the platform's `multiRefStrategy: 'merge-refs'` config.
414
+ *
407
415
  * @param {any[]} attrs
408
416
  * @param {any} element
409
417
  * @param {any} transform_context
410
418
  * @returns {any[]}
411
419
  */
412
420
  function preprocess_ref_attributes(attrs, element, transform_context) {
413
- /** @type {any[]} */
414
- const result = [];
415
- /** @type {any[]} */
416
- const ref_attrs = [];
417
-
421
+ void transform_context;
422
+ if (!is_component_like_element(element)) {
423
+ return attrs;
424
+ }
418
425
  for (const attr of attrs) {
419
- if (!attr) continue;
420
- if (attr.type === 'RefAttribute') {
421
- ref_attrs.push(attr);
422
- continue;
426
+ if (attr?.type === 'RefAttribute') {
427
+ throw create_compile_error(
428
+ attr,
429
+ '`{ref ...}` on the Vue target is only supported on host elements. Vue component refs resolve to component instances rather than the rendered DOM node, so Ripple-style component refs are not supported here.',
430
+ );
423
431
  }
424
- result.push(attr);
425
432
  }
426
-
427
- if (ref_attrs.length > 0 && is_component_like_element(element)) {
428
- throw create_compile_error(
429
- ref_attrs[0],
430
- '`{ref ...}` on the Vue target is only supported on host elements. Vue component refs resolve to component instances rather than the rendered DOM node, so Ripple-style component refs are not supported here.',
431
- );
432
- }
433
-
434
- if (ref_attrs.length === 1) {
435
- result.push(ref_attrs[0]);
436
- } else if (ref_attrs.length > 1) {
437
- result.push({
438
- type: 'RefAttribute',
439
- argument: create_combined_ref_callback(ref_attrs),
440
- loc: ref_attrs[0].loc,
441
- metadata: { path: [] },
442
- });
443
- }
444
-
445
- return result;
446
- }
447
-
448
- /**
449
- * @param {any[]} ref_attrs
450
- * @returns {any}
451
- */
452
- function create_combined_ref_callback(ref_attrs) {
453
- const node_id = builders.id('node');
454
-
455
- return {
456
- type: 'ArrowFunctionExpression',
457
- params: [node_id],
458
- body: {
459
- type: 'BlockStatement',
460
- body: ref_attrs.map((attr) => ({
461
- type: 'ExpressionStatement',
462
- expression: {
463
- type: 'CallExpression',
464
- callee: attr.argument,
465
- arguments: [clone_identifier(node_id)],
466
- optional: false,
467
- metadata: { path: [] },
468
- },
469
- metadata: { path: [] },
470
- })),
471
- metadata: { path: [] },
472
- },
473
- expression: false,
474
- async: false,
475
- generator: false,
476
- metadata: { path: [] },
477
- };
433
+ return attrs;
478
434
  }
479
435
 
480
436
  /**
@@ -652,15 +608,20 @@ function inject_vue_imports(program, transform_context) {
652
608
  if (transform_context.needs_error_boundary) {
653
609
  ensure_named_import(program, '@tsrx/vue/error-boundary', 'TsrxErrorBoundary');
654
610
  }
611
+
612
+ if (transform_context.needs_merge_refs) {
613
+ ensure_named_import(program, '@tsrx/vue/merge-refs', 'mergeRefs', '__mergeRefs');
614
+ }
655
615
  }
656
616
 
657
617
  /**
658
618
  * @param {import('estree').Program} program
659
619
  * @param {string} source
660
620
  * @param {string} name
621
+ * @param {string} [local]
661
622
  * @returns {void}
662
623
  */
663
- function ensure_named_import(program, source, name) {
624
+ function ensure_named_import(program, source, name, local = name) {
664
625
  for (const statement of program.body) {
665
626
  if (statement.type !== 'ImportDeclaration' || statement.source?.value !== source) {
666
627
  continue;
@@ -670,28 +631,30 @@ function ensure_named_import(program, source, name) {
670
631
  (/** @type {any} */ specifier) =>
671
632
  specifier.type === 'ImportSpecifier' &&
672
633
  specifier.imported?.type === 'Identifier' &&
673
- specifier.imported.name === name,
634
+ specifier.imported.name === name &&
635
+ specifier.local?.name === local,
674
636
  );
675
637
 
676
638
  if (!has_specifier) {
677
- statement.specifiers.push(create_import_specifier(name));
639
+ statement.specifiers.push(create_import_specifier(name, local));
678
640
  }
679
641
 
680
642
  return;
681
643
  }
682
644
 
683
- program.body.unshift(create_import_declaration(source, [create_import_specifier(name)]));
645
+ program.body.unshift(create_import_declaration(source, [create_import_specifier(name, local)]));
684
646
  }
685
647
 
686
648
  /**
687
649
  * @param {string} name
650
+ * @param {string} [local]
688
651
  * @returns {any}
689
652
  */
690
- function create_import_specifier(name) {
653
+ function create_import_specifier(name, local = name) {
691
654
  return {
692
655
  type: 'ImportSpecifier',
693
656
  imported: builders.id(name),
694
- local: builders.id(name),
657
+ local: builders.id(local),
695
658
  importKind: 'value',
696
659
  metadata: { path: [] },
697
660
  };