@tsrx/core 0.0.26 → 0.0.28
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 +5 -4
- package/src/analyze/validation.js +59 -0
- package/src/index.js +15 -1
- package/src/plugin.js +18 -62
- package/src/runtime/language-helpers.js +57 -0
- package/src/runtime/ref.js +250 -0
- package/src/transform/jsx/ast-builders.js +64 -13
- package/src/transform/jsx/index.js +563 -98
- package/src/transform/segments.js +21 -19
- package/src/transform/stylesheet.js +19 -0
- package/types/index.d.ts +58 -12
- package/types/jsx-platform.d.ts +47 -3
- package/types/runtime/ref.d.ts +32 -0
- package/src/runtime/merge-refs.js +0 -61
- package/types/runtime/merge-refs.d.ts +0 -12
|
@@ -439,7 +439,6 @@ export function convert_source_map_to_mappings(
|
|
|
439
439
|
}
|
|
440
440
|
|
|
441
441
|
/**
|
|
442
|
-
* @typedef {AST.MethodDefinition & {value: {metadata: {is_component: true}}}} MethodIsComponent
|
|
443
442
|
* @typedef {AST.Property & {value: AST.FunctionExpression, method: true} & {value: {metadata: {is_component: true}}}} PropertyIsComponent
|
|
444
443
|
*/
|
|
445
444
|
|
|
@@ -447,7 +446,7 @@ export function convert_source_map_to_mappings(
|
|
|
447
446
|
* Maps `component` to the identifier's location
|
|
448
447
|
* e.g. const obj = { component something() { } }
|
|
449
448
|
* since there is no function keyword in source maps
|
|
450
|
-
* @param {
|
|
449
|
+
* @param {PropertyIsComponent} node
|
|
451
450
|
* @returns {void}
|
|
452
451
|
*/
|
|
453
452
|
function set_component_mapping_to_name(node) {
|
|
@@ -563,16 +562,17 @@ export function convert_source_map_to_mappings(
|
|
|
563
562
|
} else if (node.type === 'JSXIdentifier') {
|
|
564
563
|
// JSXIdentifiers can also be capitalized (for dynamic components)
|
|
565
564
|
if (node.loc && node.name) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
565
|
+
/** @type {Token} */
|
|
566
|
+
const token = {
|
|
567
|
+
source: node.metadata?.is_capitalized ? node.metadata.source_name : node.name,
|
|
568
|
+
generated: node.name,
|
|
569
|
+
loc: node.loc,
|
|
570
|
+
metadata: {},
|
|
571
|
+
};
|
|
572
|
+
if (node.metadata?.disable_verification) {
|
|
573
|
+
token.mappingData = { ...mapping_data, verification: false };
|
|
575
574
|
}
|
|
575
|
+
tokens.push(token);
|
|
576
576
|
}
|
|
577
577
|
return; // Leaf node, don't traverse further
|
|
578
578
|
} else if (node.type === 'Literal') {
|
|
@@ -867,6 +867,15 @@ export function convert_source_map_to_mappings(
|
|
|
867
867
|
// but since we already map the opening - start, we just need the proper end
|
|
868
868
|
// and it was causing some issues with mappings
|
|
869
869
|
mapping.generatedLengths = [mapping.generatedLengths[0] + 1];
|
|
870
|
+
if (!closing && opening.selfClosing) {
|
|
871
|
+
const generated_close_length = '/>;'.length;
|
|
872
|
+
mapping.sourceOffsets = [/** @type {AST.NodeWithLocation} */ (opening).end - 2];
|
|
873
|
+
mapping.lengths = ['/>'.length];
|
|
874
|
+
mapping.generatedOffsets = [
|
|
875
|
+
mapping.generatedOffsets[0] + mapping.generatedLengths[0] - generated_close_length,
|
|
876
|
+
];
|
|
877
|
+
mapping.generatedLengths = [generated_close_length];
|
|
878
|
+
}
|
|
870
879
|
mappings.push(mapping);
|
|
871
880
|
}
|
|
872
881
|
|
|
@@ -1530,15 +1539,8 @@ export function convert_source_map_to_mappings(
|
|
|
1530
1539
|
set_bracket_computed_mapping(node, mappings);
|
|
1531
1540
|
}
|
|
1532
1541
|
|
|
1533
|
-
if (node.value.metadata.is_component) {
|
|
1534
|
-
set_component_mapping_to_name(/** @type {MethodIsComponent} */ (node));
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
1542
|
if (node.key.type === 'Literal') {
|
|
1538
|
-
handle_literal(
|
|
1539
|
-
node.key,
|
|
1540
|
-
/** @type {AST.FunctionExpression} */ (node.value).metadata.is_component,
|
|
1541
|
-
);
|
|
1543
|
+
handle_literal(node.key);
|
|
1542
1544
|
} else {
|
|
1543
1545
|
visit(node.key);
|
|
1544
1546
|
}
|
|
@@ -543,3 +543,22 @@ export function render_stylesheets(stylesheets, minify = false) {
|
|
|
543
543
|
|
|
544
544
|
return css;
|
|
545
545
|
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Render the `{ css, cssHash }` slice of a `CompileResult` from a list of
|
|
549
|
+
* stylesheets. Returns `{ css: '', cssHash: null }` when the list is empty
|
|
550
|
+
* so consumers can pass the result straight into a flat compile result.
|
|
551
|
+
*
|
|
552
|
+
* @param {AST.CSS.StyleSheet[]} stylesheets
|
|
553
|
+
* @param {boolean} [minify]
|
|
554
|
+
* @returns {{ css: string, cssHash: string | null }}
|
|
555
|
+
*/
|
|
556
|
+
export function render_css_result(stylesheets, minify = false) {
|
|
557
|
+
if (stylesheets.length === 0) {
|
|
558
|
+
return { css: '', cssHash: null };
|
|
559
|
+
}
|
|
560
|
+
return {
|
|
561
|
+
css: render_stylesheets(stylesheets, minify),
|
|
562
|
+
cssHash: stylesheets.map((s) => s.hash).join(' '),
|
|
563
|
+
};
|
|
564
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -213,6 +213,7 @@ declare module 'estree' {
|
|
|
213
213
|
Text: TextNode;
|
|
214
214
|
Attribute: Attribute;
|
|
215
215
|
RefAttribute: RefAttribute;
|
|
216
|
+
RefExpression: RefExpression;
|
|
216
217
|
SpreadAttribute: SpreadAttribute;
|
|
217
218
|
ParenthesizedExpression: ParenthesizedExpression;
|
|
218
219
|
ScriptContent: ScriptContent;
|
|
@@ -220,6 +221,7 @@ declare module 'estree' {
|
|
|
220
221
|
|
|
221
222
|
interface ExpressionMap {
|
|
222
223
|
Style: Style;
|
|
224
|
+
RefExpression: RefExpression;
|
|
223
225
|
Text: TextNode;
|
|
224
226
|
JSXEmptyExpression: ESTreeJSX.JSXEmptyExpression;
|
|
225
227
|
ParenthesizedExpression: ParenthesizedExpression;
|
|
@@ -437,6 +439,12 @@ declare module 'estree' {
|
|
|
437
439
|
loc?: AST.SourceLocation;
|
|
438
440
|
}
|
|
439
441
|
|
|
442
|
+
interface RefExpression extends AST.BaseNode {
|
|
443
|
+
type: 'RefExpression';
|
|
444
|
+
argument: AST.Expression;
|
|
445
|
+
loc?: AST.SourceLocation;
|
|
446
|
+
}
|
|
447
|
+
|
|
440
448
|
interface SpreadAttribute extends AST.BaseNode {
|
|
441
449
|
type: 'SpreadAttribute';
|
|
442
450
|
argument: AST.Expression;
|
|
@@ -463,10 +471,6 @@ declare module 'estree' {
|
|
|
463
471
|
body: (Program['body'][number] | Component | FunctionExpression)[];
|
|
464
472
|
}
|
|
465
473
|
|
|
466
|
-
interface TSRXMethodDefinition extends Omit<AST.MethodDefinition, 'value'> {
|
|
467
|
-
value: AST.MethodDefinition['value'] | Component;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
474
|
interface TSRXProperty extends Omit<AST.Property, 'value'> {
|
|
471
475
|
value: AST.Property['value'] | Component;
|
|
472
476
|
}
|
|
@@ -1575,15 +1579,17 @@ export interface VolarMappingsResult {
|
|
|
1575
1579
|
* Result of compilation operation
|
|
1576
1580
|
*/
|
|
1577
1581
|
export interface CompileResult {
|
|
1578
|
-
/** The
|
|
1579
|
-
|
|
1580
|
-
/**
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
map: import('source-map').RawSourceMap;
|
|
1584
|
-
};
|
|
1585
|
-
/** The generated CSS */
|
|
1582
|
+
/** The generated JavaScript code */
|
|
1583
|
+
code: string;
|
|
1584
|
+
/** Source map for the generated code */
|
|
1585
|
+
map: import('source-map').RawSourceMap;
|
|
1586
|
+
/** Rendered CSS for the module, or `''` when the module emits no styles. */
|
|
1586
1587
|
css: string;
|
|
1588
|
+
/**
|
|
1589
|
+
* Space-separated scope hashes for the rendered CSS, or `null` when the
|
|
1590
|
+
* module emits no styles.
|
|
1591
|
+
*/
|
|
1592
|
+
cssHash: string | null;
|
|
1587
1593
|
/**
|
|
1588
1594
|
* Non-fatal errors collected during compilation. Populated only when the
|
|
1589
1595
|
* caller passes `collect: true` or `loose: true`; empty otherwise.
|
|
@@ -1599,6 +1605,46 @@ export interface VolarCompileOptions extends Omit<ParseOptions, 'errors' | 'comm
|
|
|
1599
1605
|
dev?: boolean;
|
|
1600
1606
|
}
|
|
1601
1607
|
|
|
1608
|
+
/**
|
|
1609
|
+
* Common base options accepted by every TSRX target's `compile` entry point.
|
|
1610
|
+
* Targets that need extra knobs (e.g. ripple's `mode`/`dev`/`hmr`, preact's
|
|
1611
|
+
* `suspenseSource`) intersect their own option type with this base when
|
|
1612
|
+
* declaring their `compile` export.
|
|
1613
|
+
*/
|
|
1614
|
+
export interface BaseCompileOptions {
|
|
1615
|
+
collect?: boolean;
|
|
1616
|
+
loose?: boolean;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Shared `compile` signature for every TSRX target package. Per-target
|
|
1621
|
+
* `compile` declarations should be `CompileFn<TOptions, TResult>` so any
|
|
1622
|
+
* drift in the shared contract becomes a typecheck error in every package.
|
|
1623
|
+
*
|
|
1624
|
+
* @template TOptions Per-target options accepted as the third argument.
|
|
1625
|
+
* Defaults to {@link BaseCompileOptions}.
|
|
1626
|
+
* @template TResult Per-target result type. Must extend {@link CompileResult};
|
|
1627
|
+
* targets may add fields (e.g. ripple's deprecated `js` back-compat field)
|
|
1628
|
+
* via intersection.
|
|
1629
|
+
*/
|
|
1630
|
+
export type CompileFn<
|
|
1631
|
+
TOptions = BaseCompileOptions,
|
|
1632
|
+
TResult extends CompileResult = CompileResult,
|
|
1633
|
+
> = (source: string, filename?: string, options?: TOptions) => TResult;
|
|
1634
|
+
|
|
1635
|
+
/**
|
|
1636
|
+
* Shared `compile_to_volar_mappings` signature for every TSRX target package.
|
|
1637
|
+
*
|
|
1638
|
+
* @template TOptions Per-target options accepted as the third argument.
|
|
1639
|
+
* Defaults to {@link ParseOptions}; targets may intersect their own option
|
|
1640
|
+
* type to add e.g. `suspenseSource`.
|
|
1641
|
+
*/
|
|
1642
|
+
export type VolarCompileFn<TOptions = ParseOptions> = (
|
|
1643
|
+
source: string,
|
|
1644
|
+
filename?: string,
|
|
1645
|
+
options?: TOptions,
|
|
1646
|
+
) => VolarMappingsResult;
|
|
1647
|
+
|
|
1602
1648
|
/**
|
|
1603
1649
|
* Source map transformation types
|
|
1604
1650
|
*/
|
package/types/jsx-platform.d.ts
CHANGED
|
@@ -14,7 +14,14 @@ export interface JsxTransformResult {
|
|
|
14
14
|
* downstream Vite / Rollup plugins to chain source maps.
|
|
15
15
|
*/
|
|
16
16
|
map: RawSourceMap;
|
|
17
|
-
|
|
17
|
+
/** Rendered CSS for the module, or `''` when the module emits no styles. */
|
|
18
|
+
css: string;
|
|
19
|
+
/**
|
|
20
|
+
* Space-separated scope hashes for the rendered CSS, or `null` when the
|
|
21
|
+
* module emits no styles. When multiple `<style>` blocks contribute, the
|
|
22
|
+
* hashes appear in source order.
|
|
23
|
+
*/
|
|
24
|
+
cssHash: string | null;
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
/**
|
|
@@ -29,7 +36,10 @@ export interface JsxTransformContext {
|
|
|
29
36
|
needs_error_boundary: boolean;
|
|
30
37
|
needs_suspense: boolean;
|
|
31
38
|
needs_merge_refs: boolean;
|
|
39
|
+
needs_ref_prop: boolean;
|
|
40
|
+
needs_normalize_spread_props: boolean;
|
|
32
41
|
needs_fragment: boolean;
|
|
42
|
+
module_scoped_hook_components: boolean;
|
|
33
43
|
helper_state: {
|
|
34
44
|
base_name: string;
|
|
35
45
|
next_id: number;
|
|
@@ -48,6 +58,8 @@ export interface JsxTransformContext {
|
|
|
48
58
|
errors: CompileError[] | undefined;
|
|
49
59
|
/** Module-level comments used to honor `@tsrx-ignore` / `@tsrx-expect-error`. */
|
|
50
60
|
comments: AST.CommentWithLocation[] | undefined;
|
|
61
|
+
/** True when emitting a type-only virtual TSX module; preserves lazy destructuring patterns. */
|
|
62
|
+
typeOnly: boolean;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
/**
|
|
@@ -80,6 +92,20 @@ export interface JsxTransformOptions {
|
|
|
80
92
|
* `@tsrx-expect-error` line comments.
|
|
81
93
|
*/
|
|
82
94
|
comments?: AST.CommentWithLocation[];
|
|
95
|
+
/**
|
|
96
|
+
* Override whether hook-isolation helper components are emitted directly at
|
|
97
|
+
* module scope. React runtime compilation enables this, while editor tooling
|
|
98
|
+
* can disable it to preserve lexical `typeof` helper prop types.
|
|
99
|
+
*/
|
|
100
|
+
moduleScopedHookComponents?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Emit a type-only virtual TSX module — output is fed to TypeScript for
|
|
103
|
+
* editor diagnostics / completions and never executed. Skips the lazy
|
|
104
|
+
* destructuring rewrite (`&{ a, b }` → `__lazy0: { a: any; b: any }`) so
|
|
105
|
+
* destructuring patterns survive and TypeScript can flow real types to the
|
|
106
|
+
* bindings.
|
|
107
|
+
*/
|
|
108
|
+
typeOnly?: boolean;
|
|
83
109
|
}
|
|
84
110
|
|
|
85
111
|
/**
|
|
@@ -135,6 +161,13 @@ export interface JsxPlatformHooks {
|
|
|
135
161
|
* state behaves like normal component state.
|
|
136
162
|
*/
|
|
137
163
|
wrapHelperComponent?: (helperFn: any, helperId: any, ctx: any, sourceNode: any) => any;
|
|
164
|
+
/**
|
|
165
|
+
* Emit hook-isolation helper components as unique module-scope declarations
|
|
166
|
+
* instead of lazily creating and caching them from the parent component body.
|
|
167
|
+
* React enables this so generated branches stay compatible with the React
|
|
168
|
+
* Compiler's Rules of Hooks validation.
|
|
169
|
+
*/
|
|
170
|
+
moduleScopedHookComponents?: boolean;
|
|
138
171
|
/**
|
|
139
172
|
* Inject module-level imports after the main walk. Default: import
|
|
140
173
|
* `Suspense` from `platform.imports.suspense` and `TsrxErrorBoundary`
|
|
@@ -162,7 +195,7 @@ export interface JsxPlatformHooks {
|
|
|
162
195
|
* Optionally replace the default React-style `.map(...)` lowering for a
|
|
163
196
|
* `for...of` body after the shared transform has already produced its render
|
|
164
197
|
* statements and applied any explicit or implicit keys. Vue uses this to hand
|
|
165
|
-
* the loop to the downstream Vapor JSX compiler as a
|
|
198
|
+
* the loop to the downstream Vapor JSX compiler as a typed `VaporFor` component.
|
|
166
199
|
*/
|
|
167
200
|
renderForOf?: (node: any, loopParams: any[], bodyStatements: any[], ctx: any) => any | null;
|
|
168
201
|
/**
|
|
@@ -259,9 +292,14 @@ export interface JsxPlatform {
|
|
|
259
292
|
* Module to import `mergeRefs` from when an element has more than one
|
|
260
293
|
* `ref` attribute and the platform uses the `'merge-refs'` strategy.
|
|
261
294
|
* Required when `jsx.multiRefStrategy === 'merge-refs'`; ignored
|
|
262
|
-
* otherwise. React: `'@tsrx/react/
|
|
295
|
+
* otherwise. React: `'@tsrx/react/ref'`. Preact: `'@tsrx/preact/ref'`.
|
|
263
296
|
*/
|
|
264
297
|
mergeRefs?: string;
|
|
298
|
+
/**
|
|
299
|
+
* Module to import named-ref-prop helpers from when compiling
|
|
300
|
+
* `prop={ref expr}` or normalizing host spreads containing named refs.
|
|
301
|
+
*/
|
|
302
|
+
refProp?: string;
|
|
265
303
|
};
|
|
266
304
|
|
|
267
305
|
jsx: {
|
|
@@ -289,6 +327,12 @@ export interface JsxPlatform {
|
|
|
289
327
|
* unchanged. The platform's runtime is responsible.
|
|
290
328
|
*/
|
|
291
329
|
multiRefStrategy?: 'merge-refs' | 'array';
|
|
330
|
+
/**
|
|
331
|
+
* Some JSX runtimes do not apply a `ref` that arrives through a props
|
|
332
|
+
* spread. In that case, host spread normalization also emits an
|
|
333
|
+
* explicit `ref={normalized.ref}` attribute.
|
|
334
|
+
*/
|
|
335
|
+
hostSpreadRefStrategy?: 'explicit-ref-attr';
|
|
292
336
|
};
|
|
293
337
|
|
|
294
338
|
validation: {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type MergeableRefCallback<T> = {
|
|
2
|
+
bivarianceHack(node: T | null): void | (() => void);
|
|
3
|
+
}['bivarianceHack'];
|
|
4
|
+
export type MergeableRefObject<T> = { current: T | null };
|
|
5
|
+
export type MergeableVueRef<T> = { value: T | null };
|
|
6
|
+
export type RefProp<T = unknown> = (node: T | null) => void | (() => void);
|
|
7
|
+
|
|
8
|
+
export type MergeableRef<T> =
|
|
9
|
+
| MergeableRefCallback<T>
|
|
10
|
+
| MergeableRefObject<T>
|
|
11
|
+
| MergeableVueRef<T>
|
|
12
|
+
| null
|
|
13
|
+
| undefined;
|
|
14
|
+
|
|
15
|
+
export function mergeRefs<T = any>(...refs: Array<MergeableRef<T>>): (node: T | null) => () => void;
|
|
16
|
+
export function isRefProp(value: unknown): boolean;
|
|
17
|
+
export function create_ref_prop<T>(
|
|
18
|
+
get_ref_value: () => T,
|
|
19
|
+
set_ref_value?: (value: T) => void,
|
|
20
|
+
): RefProp<T>;
|
|
21
|
+
export function apply_ref_value<T>(
|
|
22
|
+
ref_value: unknown,
|
|
23
|
+
node: T | null,
|
|
24
|
+
set_ref_value?: (value: T) => void,
|
|
25
|
+
): void | (() => void);
|
|
26
|
+
export function merge_ref_props<T = any>(
|
|
27
|
+
...refs: unknown[]
|
|
28
|
+
): undefined | ((node: T | null) => void | (() => void));
|
|
29
|
+
export function normalize_spread_props<T extends Record<PropertyKey, any> | null | undefined>(
|
|
30
|
+
props: T,
|
|
31
|
+
...outer_refs: unknown[]
|
|
32
|
+
): T | Record<PropertyKey, any>;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Merge multiple refs (function refs and ref objects) into a single
|
|
3
|
-
* callback ref. Used by the tsrx-react, tsrx-preact, and tsrx-vue
|
|
4
|
-
* compilers when an element has more than one `ref` attribute, since
|
|
5
|
-
* those runtimes treat duplicate `ref` props as a regular duplicate-prop
|
|
6
|
-
* collision (last wins) rather than running both. Solid does not use this
|
|
7
|
-
* helper — its native runtime accepts an array of refs and the compiler
|
|
8
|
-
* emits an array literal directly.
|
|
9
|
-
*
|
|
10
|
-
* The returned callback ref handles four cases per input:
|
|
11
|
-
* - `null` / `undefined`: skipped.
|
|
12
|
-
* - function ref: invoked with the node. If it returns a function, that
|
|
13
|
-
* return value is treated as a React 19 cleanup. Otherwise we record a
|
|
14
|
-
* cleanup that calls the ref with `null` so the legacy unmount contract
|
|
15
|
-
* still fires.
|
|
16
|
-
* - React-style ref object (`{ current }`): assigned on mount, cleared
|
|
17
|
-
* on unmount.
|
|
18
|
-
* - Vue-style ref object (`{ value }`, e.g. `ref()` / `useTemplateRef()`):
|
|
19
|
-
* assigned on mount, cleared on unmount.
|
|
20
|
-
*
|
|
21
|
-
* The merged ref always returns a cleanup. Under React 19 the cleanup
|
|
22
|
-
* runs on unmount and the inner refs are not separately re-invoked with
|
|
23
|
-
* `null`. Under older React, Preact, and Vue the cleanup return value
|
|
24
|
-
* is ignored, so the runtime instead invokes the merged ref a second
|
|
25
|
-
* time with `null` — which re-runs the loop body, calling each inner
|
|
26
|
-
* with `null` and clearing each ref object. Either way every inner ref
|
|
27
|
-
* sees a balanced mount/unmount.
|
|
28
|
-
*
|
|
29
|
-
* @param {...((node: any) => void | (() => void)) | { current: any } | { value: any } | null | undefined} refs
|
|
30
|
-
* @returns {(node: any) => (() => void)}
|
|
31
|
-
*/
|
|
32
|
-
export function mergeRefs(...refs) {
|
|
33
|
-
return (node) => {
|
|
34
|
-
/** @type {Array<() => void>} */
|
|
35
|
-
const cleanups = [];
|
|
36
|
-
for (const ref of refs) {
|
|
37
|
-
if (ref == null) continue;
|
|
38
|
-
if (typeof ref === 'function') {
|
|
39
|
-
const result = ref(node);
|
|
40
|
-
if (typeof result === 'function') {
|
|
41
|
-
cleanups.push(result);
|
|
42
|
-
} else {
|
|
43
|
-
cleanups.push(() => ref(null));
|
|
44
|
-
}
|
|
45
|
-
} else if ('current' in ref) {
|
|
46
|
-
ref.current = node;
|
|
47
|
-
cleanups.push(() => {
|
|
48
|
-
ref.current = null;
|
|
49
|
-
});
|
|
50
|
-
} else if ('value' in ref) {
|
|
51
|
-
ref.value = node;
|
|
52
|
-
cleanups.push(() => {
|
|
53
|
-
ref.value = null;
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return () => {
|
|
58
|
-
for (const cleanup of cleanups) cleanup();
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type MergeableRefCallback<T> = (node: T | null) => void | (() => void);
|
|
2
|
-
export type MergeableRefObject<T> = { current: T | null };
|
|
3
|
-
export type MergeableVueRef<T> = { value: T | null };
|
|
4
|
-
|
|
5
|
-
export type MergeableRef<T> =
|
|
6
|
-
| MergeableRefCallback<T>
|
|
7
|
-
| MergeableRefObject<T>
|
|
8
|
-
| MergeableVueRef<T>
|
|
9
|
-
| null
|
|
10
|
-
| undefined;
|
|
11
|
-
|
|
12
|
-
export function mergeRefs<T = any>(...refs: Array<MergeableRef<T>>): (node: T | null) => () => void;
|