bestax-migrate 2.2.1 → 2.3.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/README.md +12 -10
- package/dist/sources/_shared/imports.d.ts +28 -0
- package/dist/sources/_shared/imports.d.ts.map +1 -1
- package/dist/sources/_shared/imports.js +62 -0
- package/dist/sources/_shared/jsx-utils.d.ts +17 -0
- package/dist/sources/_shared/jsx-utils.d.ts.map +1 -1
- package/dist/sources/_shared/jsx-utils.js +49 -1
- package/dist/sources/_shared/props.d.ts +17 -0
- package/dist/sources/_shared/props.d.ts.map +1 -1
- package/dist/sources/_shared/props.js +72 -3
- package/dist/sources/_shared/specials-utils.d.ts +49 -3
- package/dist/sources/_shared/specials-utils.d.ts.map +1 -1
- package/dist/sources/_shared/specials-utils.js +165 -5
- package/dist/sources/_shared/viewports.d.ts +17 -0
- package/dist/sources/_shared/viewports.d.ts.map +1 -0
- package/dist/sources/_shared/viewports.js +32 -0
- package/dist/sources/bloomer/deps.d.ts +17 -0
- package/dist/sources/bloomer/deps.d.ts.map +1 -0
- package/dist/sources/bloomer/deps.js +119 -0
- package/dist/sources/bloomer/index.d.ts +3 -0
- package/dist/sources/bloomer/index.d.ts.map +1 -0
- package/dist/sources/bloomer/index.js +10 -0
- package/dist/sources/bloomer/mapping.d.ts +84 -0
- package/dist/sources/bloomer/mapping.d.ts.map +1 -0
- package/dist/sources/bloomer/mapping.js +988 -0
- package/dist/sources/bloomer/responsive.d.ts +39 -0
- package/dist/sources/bloomer/responsive.d.ts.map +1 -0
- package/dist/sources/bloomer/responsive.js +259 -0
- package/dist/sources/bloomer/specials.d.ts +19 -0
- package/dist/sources/bloomer/specials.d.ts.map +1 -0
- package/dist/sources/bloomer/specials.js +774 -0
- package/dist/sources/bloomer/styles.d.ts +13 -0
- package/dist/sources/bloomer/styles.d.ts.map +1 -0
- package/dist/sources/bloomer/styles.js +17 -0
- package/dist/sources/bloomer/transform.d.ts +27 -0
- package/dist/sources/bloomer/transform.d.ts.map +1 -0
- package/dist/sources/bloomer/transform.js +826 -0
- package/dist/sources/rbx/mapping.d.ts.map +1 -1
- package/dist/sources/rbx/mapping.js +20 -18
- package/dist/sources/rbx/responsive.d.ts.map +1 -1
- package/dist/sources/rbx/responsive.js +1 -31
- package/dist/sources/rbx/specials.d.ts.map +1 -1
- package/dist/sources/rbx/specials.js +36 -98
- package/dist/sources/rbx/transform.d.ts.map +1 -1
- package/dist/sources/rbx/transform.js +168 -78
- package/dist/sources/react-bulma-components/mapping.js +4 -4
- package/dist/sources/react-bulma-components/responsive.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/responsive.js +2 -14
- package/dist/sources/react-bulma-components/specials.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/specials.js +45 -18
- package/dist/sources/react-bulma-components/transform.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/transform.js +168 -78
- package/dist/sources/registry.d.ts.map +1 -1
- package/dist/sources/registry.js +2 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAuCnE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAiCtD,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOrD,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAQvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAShE,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAuCnE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAiCtD,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOrD,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAQvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAShE,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAssBpD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA2FhD,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAM3E"}
|
|
@@ -126,7 +126,7 @@ export const MAPPING = {
|
|
|
126
126
|
},
|
|
127
127
|
forwardRefAs: {
|
|
128
128
|
status: 'todo',
|
|
129
|
-
todo: '`forwardRefAs` is rbx-internal and has no counterpart.
|
|
129
|
+
todo: '`forwardRefAs` is rbx-internal and has no counterpart. bestax forwards a ref from the form controls and from `Button`, `LinkButton`, `Modal`, `Dropdown`, `Navbar` (plus `Navbar.Burger` and `Navbar.Link`), `Dialog`, `Sidebar`, `Toast` and `Carousel` — pass `ref` directly on those. Mind the `Navbar.Dropdown` collision: your rbx `Navbar.Dropdown` is the menu and becomes `Navbar.DropdownMenu`, which forwards no ref, while bestax `Navbar.Dropdown` — the container your `<Navbar.Item dropdown>` becomes — does. The rest, `Box` included, are plain function components that forward no ref; put the ref on a wrapping element you control',
|
|
130
130
|
},
|
|
131
131
|
// ---- elements -----------------------------------------------------------
|
|
132
132
|
Block: { status: 'mapped', target: 'Block' },
|
|
@@ -136,6 +136,7 @@ export const MAPPING = {
|
|
|
136
136
|
target: 'Button',
|
|
137
137
|
props: {
|
|
138
138
|
as: AS_OK,
|
|
139
|
+
innerRef: { rename: 'ref' },
|
|
139
140
|
color: {},
|
|
140
141
|
size: {},
|
|
141
142
|
outlined: { booleanToProp: { name: 'isOutlined' } },
|
|
@@ -497,9 +498,7 @@ export const MAPPING = {
|
|
|
497
498
|
managed: {
|
|
498
499
|
todo: 'bestax `Dropdown` is uncontrolled by default; use `active` + `onActiveChange` for controlled behaviour',
|
|
499
500
|
},
|
|
500
|
-
innerRef: {
|
|
501
|
-
todo: 'this bestax component is a plain function component and forwards no ref; drop `innerRef`, or put the ref on a wrapping element you control',
|
|
502
|
-
},
|
|
501
|
+
innerRef: { rename: 'ref' },
|
|
503
502
|
},
|
|
504
503
|
subs: {
|
|
505
504
|
Container: { status: 'mapped', special: 'dropdown-container' },
|
|
@@ -606,25 +605,25 @@ export const MAPPING = {
|
|
|
606
605
|
props: {
|
|
607
606
|
active: {},
|
|
608
607
|
onClose: {},
|
|
609
|
-
closeOnEsc: {
|
|
610
|
-
todo: 'bestax `Modal` implements no Escape handling at all; add your own keydown listener, or drop the prop if the behaviour is not needed',
|
|
611
|
-
},
|
|
608
|
+
closeOnEsc: { rename: 'closeOnEscape' },
|
|
612
609
|
closeOnBlur: {
|
|
613
|
-
todo:
|
|
610
|
+
todo: 'bestax `Modal` closes on background click in its legacy form, where it renders its own background wired to `onClose`; a `Modal.Content` or `Modal.Card` child selects the compound form, which renders only the children you wrote — there, add a `<Modal.Background>` whose `onClick` calls your close handler, or drop the prop if you passed false',
|
|
614
611
|
},
|
|
615
612
|
document: {
|
|
616
|
-
todo: 'bestax `Modal`
|
|
613
|
+
todo: 'bestax `Modal` portals via `portal`, but that takes `true`, a selector or an element — not a `Document`. Pass an element from the document you targeted, or drop the prop if you were passing the default document',
|
|
617
614
|
},
|
|
618
615
|
containerClassName: { rename: 'className' },
|
|
619
|
-
innerRef: {
|
|
620
|
-
todo: 'this bestax component is a plain function component and forwards no ref; drop `innerRef`, or put the ref on a wrapping element you control',
|
|
621
|
-
},
|
|
616
|
+
innerRef: { rename: 'ref' },
|
|
622
617
|
},
|
|
623
618
|
subs: {
|
|
624
619
|
Background: { status: 'mapped', target: 'Modal.Background' },
|
|
625
620
|
Close: { status: 'mapped', target: 'Modal.Close' },
|
|
626
621
|
Content: { status: 'mapped', target: 'Modal.Content' },
|
|
627
|
-
Container: {
|
|
622
|
+
Container: {
|
|
623
|
+
status: 'mapped',
|
|
624
|
+
special: 'modal-container',
|
|
625
|
+
props: { innerRef: { rename: 'ref' } },
|
|
626
|
+
},
|
|
628
627
|
Card: {
|
|
629
628
|
status: 'mapped',
|
|
630
629
|
target: 'Modal.Card',
|
|
@@ -641,7 +640,7 @@ export const MAPPING = {
|
|
|
641
640
|
},
|
|
642
641
|
Portal: {
|
|
643
642
|
status: 'todo',
|
|
644
|
-
todo: '`Modal.Portal` is rbx-internal;
|
|
643
|
+
todo: '`Modal.Portal` is rbx-internal; set `portal` on the `<Modal>` instead — it takes `true`, a selector or an element',
|
|
645
644
|
},
|
|
646
645
|
},
|
|
647
646
|
},
|
|
@@ -659,13 +658,15 @@ export const MAPPING = {
|
|
|
659
658
|
todo: 'bestax `Navbar` is uncontrolled; drop `managed`',
|
|
660
659
|
},
|
|
661
660
|
document: { todo: 'bestax `Navbar` has no `document` prop; drop it' },
|
|
662
|
-
innerRef: {
|
|
663
|
-
todo: 'this bestax component is a plain function component and forwards no ref; drop `innerRef`, or put the ref on a wrapping element you control',
|
|
664
|
-
},
|
|
661
|
+
innerRef: { rename: 'ref' },
|
|
665
662
|
},
|
|
666
663
|
subs: {
|
|
667
664
|
Brand: { status: 'mapped', target: 'Navbar.Brand' },
|
|
668
|
-
Burger: {
|
|
665
|
+
Burger: {
|
|
666
|
+
status: 'mapped',
|
|
667
|
+
target: 'Navbar.Burger',
|
|
668
|
+
props: { innerRef: { rename: 'ref' } },
|
|
669
|
+
},
|
|
669
670
|
Divider: { status: 'mapped', target: 'Navbar.Divider' },
|
|
670
671
|
Menu: { status: 'mapped', target: 'Navbar.Menu' },
|
|
671
672
|
Link: {
|
|
@@ -673,6 +674,7 @@ export const MAPPING = {
|
|
|
673
674
|
target: 'Navbar.Link',
|
|
674
675
|
props: {
|
|
675
676
|
as: AS_OK,
|
|
677
|
+
innerRef: { rename: 'ref' },
|
|
676
678
|
arrowless: {},
|
|
677
679
|
onClick: {},
|
|
678
680
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responsive.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/responsive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,
|
|
1
|
+
{"version":3,"file":"responsive.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/responsive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAUL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAIjC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;AAEnE,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAG3D,CAAC;AA0TF,8DAA8D;AAC9D,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,cAAc,GACnB,IAAI,CAKN"}
|
|
@@ -21,42 +21,12 @@
|
|
|
21
21
|
* here — only the shape changes.
|
|
22
22
|
*/
|
|
23
23
|
import { RESPONSIVE_BREAKPOINTS } from './mapping.js';
|
|
24
|
-
import { addAttr, addTodo, attributesOf, makeAttr, removeAttr, } from '../_shared/jsx-utils.js';
|
|
24
|
+
import { addAttr, addTodo, attributesOf, attrValue, literalOf, makeAttr, objectExpressionOf, propKey, removeAttr, } from '../_shared/jsx-utils.js';
|
|
25
25
|
/** Which specials opt their element into the extra breakpoint shapes. */
|
|
26
26
|
export const RESPONSIVE_KINDS = {
|
|
27
27
|
column: 'column',
|
|
28
28
|
'column-group': 'column-group',
|
|
29
29
|
};
|
|
30
|
-
function literalOf(node) {
|
|
31
|
-
if (!node)
|
|
32
|
-
return undefined;
|
|
33
|
-
if (node.type === 'StringLiteral')
|
|
34
|
-
return node.value;
|
|
35
|
-
if (node.type === 'NumericLiteral')
|
|
36
|
-
return node.value;
|
|
37
|
-
if (node.type === 'BooleanLiteral')
|
|
38
|
-
return node.value;
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Reuse a value node as a JSX attribute value: a string literal can sit bare
|
|
43
|
-
* (`size="one-third"`), anything else needs an expression container.
|
|
44
|
-
*/
|
|
45
|
-
function attrValue(j, node) {
|
|
46
|
-
return node?.type === 'StringLiteral'
|
|
47
|
-
? j.stringLiteral(node.value)
|
|
48
|
-
: j.jsxExpressionContainer(node);
|
|
49
|
-
}
|
|
50
|
-
function propKey(prop) {
|
|
51
|
-
const key = prop.key?.name ?? prop.key?.value;
|
|
52
|
-
return typeof key === 'string' ? key : undefined;
|
|
53
|
-
}
|
|
54
|
-
function objectExpressionOf(value) {
|
|
55
|
-
return value?.type === 'JSXExpressionContainer' &&
|
|
56
|
-
value.expression?.type === 'ObjectExpression'
|
|
57
|
-
? value.expression
|
|
58
|
-
: null;
|
|
59
|
-
}
|
|
60
30
|
/**
|
|
61
31
|
* One `{ value, only }` cell of the universal `responsive` prop. Returns the
|
|
62
32
|
* inner `value` node, or undefined when the cell isn't the expected shape.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specials.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/specials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAO3C,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"specials.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/specials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAO3C,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAUL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,aAAa,EAAE,CAAC;AAs2B9B,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,GACX,aAAa,CAIf"}
|
|
@@ -15,26 +15,9 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { BADGE_PROPS, RESPONSIVE_BREAKPOINTS, TOOLTIP_PROPS, UNIVERSAL_PROPS, } from './mapping.js';
|
|
17
17
|
import { addAttr, addTodo, buildJsxName, attributesOf, findAttr, jsxNameParts, literalValueOf, makeAttr, plainElement, removeAttr, resolveBooleanish, } from '../_shared/jsx-utils.js';
|
|
18
|
-
import { alignTarget, makeStripModifierProps, mergeClassName, parseIconClasses, } from '../_shared/specials-utils.js';
|
|
18
|
+
import { alignTarget, applyIconProps, makeStripModifierProps, makeStructuralHelpers, mergeClassName, modifierClass, parseIconClasses, restrictAsToTargets, } from '../_shared/specials-utils.js';
|
|
19
19
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
20
20
|
const stripModifierProps = makeStripModifierProps(UNIVERSAL_PROPS, RESPONSIVE_BREAKPOINTS);
|
|
21
|
-
/**
|
|
22
|
-
* Turn a literal modifier prop into an `is-*` class fragment for an element
|
|
23
|
-
* on its way to becoming plain HTML. Returns the class (or undefined) and
|
|
24
|
-
* always removes the attribute.
|
|
25
|
-
*/
|
|
26
|
-
function modifierClass(ctx, path, element, prop, base, where) {
|
|
27
|
-
const attr = findAttr(element, prop);
|
|
28
|
-
if (!attr)
|
|
29
|
-
return base;
|
|
30
|
-
const literal = literalValueOf(attr);
|
|
31
|
-
removeAttr(element, attr);
|
|
32
|
-
if (literal.kind === 'string' || literal.kind === 'number') {
|
|
33
|
-
return `${base} is-${literal.value}`;
|
|
34
|
-
}
|
|
35
|
-
addTodo(ctx, path, `prop:${prop}`, `dynamic ${where} \`${prop}\`; add the matching is-* class by hand`);
|
|
36
|
-
return base;
|
|
37
|
-
}
|
|
38
21
|
/**
|
|
39
22
|
* Also strips the universal `responsive` object: responsive.ts would have
|
|
40
23
|
* consumed it, but a `replaced: true` special skips that pass too, and it is
|
|
@@ -68,66 +51,11 @@ function stripHelperComponentProps(ctx, path, attrs, where) {
|
|
|
68
51
|
return kept;
|
|
69
52
|
}
|
|
70
53
|
/**
|
|
71
|
-
* rbx
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* Left/Right/Item where only Item does, Navbar.Item to Item/Dropdown where
|
|
75
|
-
* only Item does. Opting into `as` in the mapping table cannot express that,
|
|
76
|
-
* so the target has to be checked after it is picked.
|
|
77
|
-
*/
|
|
78
|
-
function restrictAsToTargets(ctx, path, element, target, allowed) {
|
|
79
|
-
const asAttr = findAttr(element, 'as');
|
|
80
|
-
if (!asAttr || (target && allowed.includes(target)))
|
|
81
|
-
return;
|
|
82
|
-
removeAttr(element, asAttr);
|
|
83
|
-
addTodo(ctx, path, 'prop:as', `bestax's \`${target}\` has no \`as\` prop (of the targets this can resolve to, only ${allowed
|
|
84
|
-
.map(a => `\`${a}\``)
|
|
85
|
-
.join(' / ')} does); render the tag directly or restructure`);
|
|
86
|
-
ctx.dirty = true;
|
|
87
|
-
}
|
|
88
|
-
/** Replace the element with a plain HTML tag carrying `className`. */
|
|
89
|
-
function replaceWithPlain(ctx, path, element, tag, className, where) {
|
|
90
|
-
const merged = mergeClassName(ctx, path, element, className, where);
|
|
91
|
-
const rest = stripHelperComponentProps(ctx, path, stripModifierProps(ctx, path, attributesOf(element), where), where);
|
|
92
|
-
path.replace(plainElement(ctx.j, tag, merged, rest, element.children ?? []));
|
|
93
|
-
ctx.dirty = true;
|
|
94
|
-
return { replaced: true };
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* rbx wraps several components in a `*.Container` that owns the modifiers,
|
|
98
|
-
* where bestax's component renders that wrapper itself. Move the container's
|
|
99
|
-
* (already-converted) attributes onto its single child and replace the
|
|
100
|
-
* container with it — otherwise both would rename to the same bestax
|
|
101
|
-
* component and nest, which is invalid.
|
|
102
|
-
*
|
|
103
|
-
* Returns null when the element isn't the single-JSX-child shape, so the
|
|
104
|
-
* caller can fall back to keeping the container.
|
|
54
|
+
* rbx's plain-element rewrites strip both the universal helper props and the
|
|
55
|
+
* badge/tooltip/responsive props (which would otherwise ride onto the HTML
|
|
56
|
+
* tag as unknown DOM attributes — see stripHelperComponentProps).
|
|
105
57
|
*/
|
|
106
|
-
|
|
107
|
-
const children = (element.children ?? []).filter((c) => !(c.type === 'JSXText' && c.value.trim() === ''));
|
|
108
|
-
if (children.length !== 1 || children[0].type !== 'JSXElement')
|
|
109
|
-
return null;
|
|
110
|
-
const child = children[0];
|
|
111
|
-
// The child must be the component this container exists to wrap. rbx lets
|
|
112
|
-
// both of these containers hold something else — an `<iframe>` for a ratio
|
|
113
|
-
// box, a native `<select>` — and folding onto that put Bulma modifier props
|
|
114
|
-
// on an intrinsic element and dropped the wrapper the markup needs.
|
|
115
|
-
const childPath = ctx.resolve?.(child.openingElement?.name);
|
|
116
|
-
if (!childPath || childPath.join('.') !== expected)
|
|
117
|
-
return null;
|
|
118
|
-
for (const attr of [...attributesOf(element)]) {
|
|
119
|
-
const name = attr.name.name;
|
|
120
|
-
if (findAttr(child, name)) {
|
|
121
|
-
addTodo(ctx, path, `prop:${name}`, `\`${where}\` folded into its child, but both set \`${name}\`; the child's value was kept — reconcile by hand`);
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
removeAttr(element, attr);
|
|
125
|
-
addAttr(child, attr);
|
|
126
|
-
}
|
|
127
|
-
path.replace(child);
|
|
128
|
-
ctx.dirty = true;
|
|
129
|
-
return { replaced: true };
|
|
130
|
-
}
|
|
58
|
+
const { replaceWithPlain, collapseOntoChild } = makeStructuralHelpers((ctx, path, attrs, where) => stripHelperComponentProps(ctx, path, stripModifierProps(ctx, path, attrs, where), where));
|
|
131
59
|
const SPECIALS = {
|
|
132
60
|
/**
|
|
133
61
|
* rbx's `Heading` is Bulma's `.heading` label (small caps), not a title —
|
|
@@ -171,6 +99,11 @@ const SPECIALS = {
|
|
|
171
99
|
else if (resolved === 'falsy') {
|
|
172
100
|
removeAttr(element, spacedAttr);
|
|
173
101
|
}
|
|
102
|
+
else if (findAttr(element, 'isSpaced')) {
|
|
103
|
+
// `isSpaced` is already set (rbx passes unknown props through), so
|
|
104
|
+
// renaming onto it would emit the attribute twice.
|
|
105
|
+
addTodo(ctx, path, 'prop:spaced', 'dynamic `spaced` alongside an `isSpaced` already on this element; bestax has one prop for both — reconcile by hand');
|
|
106
|
+
}
|
|
174
107
|
else {
|
|
175
108
|
// Dynamic: keep the expression, just rename the prop.
|
|
176
109
|
spacedAttr.name = ctx.j.jsxIdentifier('isSpaced');
|
|
@@ -195,20 +128,10 @@ const SPECIALS = {
|
|
|
195
128
|
const literal = classAttr ? literalValueOf(classAttr) : undefined;
|
|
196
129
|
if (literal?.kind === 'string') {
|
|
197
130
|
const parsed = parseIconClasses(literal.value);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
if (parsed.variant) {
|
|
204
|
-
addAttr(element, makeAttr(ctx.j, 'variant', parsed.variant));
|
|
205
|
-
}
|
|
206
|
-
element.children = [];
|
|
207
|
-
if (element.openingElement) {
|
|
208
|
-
element.openingElement.selfClosing = true;
|
|
209
|
-
element.closingElement = null;
|
|
210
|
-
}
|
|
211
|
-
ctx.dirty = true;
|
|
131
|
+
// An app's own class on the <i> has no home on bestax's glyph, so
|
|
132
|
+
// the child is kept (and flagged below) rather than losing it.
|
|
133
|
+
if (parsed && parsed.leftovers.length === 0) {
|
|
134
|
+
applyIconProps(ctx, path, element, parsed);
|
|
212
135
|
return {};
|
|
213
136
|
}
|
|
214
137
|
}
|
|
@@ -538,15 +461,14 @@ const SPECIALS = {
|
|
|
538
461
|
return { ...result, handledProps: ['align', 'as'] };
|
|
539
462
|
},
|
|
540
463
|
/**
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
* behaves differently, so every conversion is flagged.
|
|
464
|
+
* rbx's Modal portals into `document.body`, closes on Escape and clips
|
|
465
|
+
* document scroll, all by default. bestax matches two of those since #633 —
|
|
466
|
+
* `closeOnEscape` and `lockScroll` both default to `true` — but still
|
|
467
|
+
* renders inline unless `portal` is set. That last difference does not fail
|
|
468
|
+
* loudly, so every conversion is still flagged, now about the portal alone.
|
|
547
469
|
*/
|
|
548
470
|
modal(ctx, path, _element) {
|
|
549
|
-
addTodo(ctx, path, 'component:Modal', 'bestax `Modal`
|
|
471
|
+
addTodo(ctx, path, 'component:Modal', 'bestax `Modal` closes on Escape and locks body scroll by default, matching rbx, but it renders inline: set `portal` if you relied on rbx portalling into document.body');
|
|
550
472
|
return {};
|
|
551
473
|
},
|
|
552
474
|
/** rbx Modal.Container is the modal itself in bestax. */
|
|
@@ -588,6 +510,21 @@ const SPECIALS = {
|
|
|
588
510
|
addTodo(ctx, path, `prop:${prop}`, `bestax \`Navbar.Item\` has no \`${prop}\` prop; restructure or add a class by hand`);
|
|
589
511
|
ctx.dirty = true;
|
|
590
512
|
}
|
|
513
|
+
// bestax's `Navbar.Dropdown` forwards a ref, but it is the one such target
|
|
514
|
+
// the `innerRef: { rename: 'ref' }` entries in mapping.ts cannot reach:
|
|
515
|
+
// that table is keyed on the rbx name (`Navbar.Item`), and only this
|
|
516
|
+
// handler knows which of the two targets was picked. A plain
|
|
517
|
+
// `Navbar.Item` is still a function component, so the rename is
|
|
518
|
+
// conditional — there, `innerRef` is left alone.
|
|
519
|
+
const renamedInnerRef = [];
|
|
520
|
+
if (target === 'Navbar.Dropdown') {
|
|
521
|
+
const innerRefAttr = findAttr(element, 'innerRef');
|
|
522
|
+
if (innerRefAttr) {
|
|
523
|
+
innerRefAttr.name = ctx.j.jsxIdentifier('ref');
|
|
524
|
+
renamedInnerRef.push('innerRef');
|
|
525
|
+
ctx.dirty = true;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
591
528
|
restrictAsToTargets(ctx, path, element, target ?? 'Navbar.Item', [
|
|
592
529
|
'Navbar.Item',
|
|
593
530
|
]);
|
|
@@ -601,6 +538,7 @@ const SPECIALS = {
|
|
|
601
538
|
'expanded',
|
|
602
539
|
'hoverable',
|
|
603
540
|
'managed',
|
|
541
|
+
...renamedInnerRef,
|
|
604
542
|
],
|
|
605
543
|
};
|
|
606
544
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AA2DvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CAmoCpB"}
|