bestax-migrate 2.5.0 → 2.7.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.
@@ -73,7 +73,27 @@ export interface RootEntry {
73
73
  readonly in: string;
74
74
  readonly unless: readonly string[];
75
75
  readonly whenEmpty?: boolean;
76
+ /** Only when the element carries this class (`Field` with `is-horizontal`). */
77
+ readonly when?: string;
76
78
  };
79
+ /**
80
+ * The target provides context bestax's form controls read to skip wrappers
81
+ * of their own, so an element around a bestax component already in the file
82
+ * stays markup: that component would render differently.
83
+ */
84
+ readonly providesContext?: boolean;
85
+ /**
86
+ * Inside one of these bestax components already in the file, the target
87
+ * takes a generated `id` when the element has none of its own.
88
+ */
89
+ readonly adoptsIdFrom?: readonly string[];
90
+ /** The target takes no helper props, so every helper class stays a class. */
91
+ readonly noHelpers?: boolean;
92
+ /**
93
+ * The target drops its own class when it is given a `className`, so the
94
+ * element converts only when it carries no other class.
95
+ */
96
+ readonly ownClassOnly?: boolean;
77
97
  /**
78
98
  * Attributes the target types as numbers. A numeric string (`value="40"`)
79
99
  * becomes a number, which renders the same; any other string refuses.
@@ -1 +1 @@
1
- {"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,MAAM,GAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;IACxC,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxD,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI,CAAC;IAClD,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,iBAAiB,GAAG,IAAI,CAAC;IACxD,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,iDAAiD;IACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAID,eAAO,MAAM,MAAM,+NAoBT,CAAC;AACX,eAAO,MAAM,KAAK,sDAAuD,CAAC;AAC1E,eAAO,MAAM,UAAU,8CAA+C,CAAC;AACvE,eAAO,MAAM,UAAU,qDAAsD,CAAC;AAC9E,eAAO,MAAM,eAAe,8DAKlB,CAAC;AACX,eAAO,MAAM,YAAY,4DAMf,CAAC;AACX,eAAO,MAAM,aAAa,sEAMhB,CAAC;AACX,eAAO,MAAM,QAAQ,6EAOX,CAAC;AACX,eAAO,MAAM,eAAe,6DAKlB,CAAC;AACX,eAAO,MAAM,UAAU,6CAA8C,CAAC;AACtE,eAAO,MAAM,gBAAgB,iIAWnB,CAAC;AACX,eAAO,MAAM,cAAc,2GAQjB,CAAC;AACX,eAAO,MAAM,WAAW,sFAQd,CAAC;AACX,eAAO,MAAM,WAAW,8EAOd,CAAC;AACX,eAAO,MAAM,gBAAgB,yCAA0C,CAAC;AACxE,eAAO,MAAM,SAAS,6HAUZ,CAAC;AAoDX,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKvD;AAuDD,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAkxBrD,CAAC;AAcF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAwCvC,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAAuB,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYrD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAYzE,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtD,CAAC;AAIF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,gBAAgB,GAChB,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AA6DD,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAsGzD,CAAC;AAEH,iEAAiE;AACjE,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAS3C,CAAC;AAIH;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CA8BA,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnE;AAiBD,qCAAqC;AACrC,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAGlE;AAED,qCAAqC;AACrC,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,GACZ,QAAQ,GAAG,SAAS,CAEtB;AAED,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5D;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1D"}
1
+ {"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,MAAM,GAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;IACxC,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxD,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI,CAAC;IAClD,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,iBAAiB,GAAG,IAAI,CAAC;IACxD,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,iDAAiD;IACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAC7B,+EAA+E;QAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAID,eAAO,MAAM,MAAM,+NAoBT,CAAC;AACX,eAAO,MAAM,KAAK,sDAAuD,CAAC;AAC1E,eAAO,MAAM,UAAU,8CAA+C,CAAC;AACvE,eAAO,MAAM,UAAU,qDAAsD,CAAC;AAC9E,eAAO,MAAM,eAAe,8DAKlB,CAAC;AACX,eAAO,MAAM,YAAY,4DAMf,CAAC;AACX,eAAO,MAAM,aAAa,sEAMhB,CAAC;AACX,eAAO,MAAM,QAAQ,6EAOX,CAAC;AACX,eAAO,MAAM,eAAe,6DAKlB,CAAC;AACX,eAAO,MAAM,UAAU,6CAA8C,CAAC;AACtE,eAAO,MAAM,gBAAgB,iIAWnB,CAAC;AACX,eAAO,MAAM,cAAc,2GAQjB,CAAC;AACX,eAAO,MAAM,WAAW,sFAQd,CAAC;AACX,eAAO,MAAM,WAAW,8EAOd,CAAC;AACX,eAAO,MAAM,gBAAgB,yCAA0C,CAAC;AACxE,eAAO,MAAM,SAAS,6HAUZ,CAAC;AAoDX,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKvD;AAuDD,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAw/BrD,CAAC;AAcF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAsDvC,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAQzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYrD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAYzE,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtD,CAAC;AAIF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,gBAAgB,GAChB,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AA6DD,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAsGzD,CAAC;AAEH,iEAAiE;AACjE,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAS3C,CAAC;AAIH;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CA8BA,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnE;AAiBD,qCAAqC;AACrC,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAGlE;AAED,qCAAqC;AACrC,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,GACZ,QAAQ,GAAG,SAAS,CAEtB;AAED,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5D;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1D"}
@@ -547,6 +547,168 @@ export const ROOTS = {
547
547
  ],
548
548
  passThrough: ['onClick'],
549
549
  },
550
+ // Form markup. `Field` and `Control` tell the bestax form controls inside
551
+ // them to skip wrappers of their own, and `InputBase` / `TextAreaBase` are
552
+ // the controls without wrappers (a `Field` with no `label` hands them no id).
553
+ field: {
554
+ ...BASE,
555
+ target: 'Field',
556
+ tag: 'div',
557
+ // `has-addons-centered`, `is-grouped-right` and the like stay classes:
558
+ // the prop values that render them render `has-addons` too.
559
+ modifiers: flags({
560
+ 'is-horizontal': 'horizontal',
561
+ 'is-grouped': 'grouped',
562
+ 'has-addons': 'hasAddons',
563
+ 'is-narrow': 'narrow',
564
+ }),
565
+ wrapsChildren: {
566
+ in: 'field-body',
567
+ unless: ['Field.Label', 'Field.Body'],
568
+ whenEmpty: true,
569
+ when: 'is-horizontal',
570
+ },
571
+ providesContext: true,
572
+ ownProps: [
573
+ 'horizontal',
574
+ 'grouped',
575
+ 'hasAddons',
576
+ 'narrow',
577
+ 'label',
578
+ 'labelSize',
579
+ 'labelProps',
580
+ 'textColor',
581
+ 'color',
582
+ 'bgColor',
583
+ ],
584
+ },
585
+ // Field.Label, Field.Body and Control spread their raw props onto the
586
+ // element as well, so a helper prop would reach it as an attribute too.
587
+ 'field-label': {
588
+ status: 'mapped',
589
+ target: 'Field.Label',
590
+ tag: 'div',
591
+ textColor: null,
592
+ bgColor: null,
593
+ noHelpers: true,
594
+ modifiers: tokens('is-', ['small', 'normal', 'medium', 'large'], 'size'),
595
+ ownProps: ['size', 'textColor', 'color', 'bgColor'],
596
+ },
597
+ 'field-body': {
598
+ status: 'mapped',
599
+ target: 'Field.Body',
600
+ tag: 'div',
601
+ textColor: null,
602
+ bgColor: null,
603
+ noHelpers: true,
604
+ ownProps: ['textColor', 'color', 'bgColor'],
605
+ },
606
+ control: {
607
+ status: 'mapped',
608
+ target: 'Control',
609
+ tag: 'div',
610
+ as: ['div', 'p'],
611
+ textColor: null,
612
+ bgColor: null,
613
+ noHelpers: true,
614
+ modifiers: {
615
+ ...flags({
616
+ 'has-icons-left': 'hasIconsLeft',
617
+ 'has-icons-right': 'hasIconsRight',
618
+ 'is-loading': 'isLoading',
619
+ 'is-expanded': 'isExpanded',
620
+ }),
621
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
622
+ },
623
+ providesContext: true,
624
+ ownProps: [
625
+ 'as',
626
+ 'hasIconsLeft',
627
+ 'hasIconsRight',
628
+ 'isLoading',
629
+ 'isExpanded',
630
+ 'size',
631
+ 'textColor',
632
+ 'color',
633
+ 'bgColor',
634
+ 'iconLeft',
635
+ 'iconRight',
636
+ 'iconLeftName',
637
+ 'iconLeftSize',
638
+ 'iconRightName',
639
+ 'iconRightSize',
640
+ ],
641
+ passThrough: ['ref'],
642
+ },
643
+ input: {
644
+ ...BASE,
645
+ target: 'InputBase',
646
+ tag: 'input',
647
+ // No text color prop, and `backgroundColor` is the one the base reads.
648
+ textColor: null,
649
+ bgColor: 'backgroundColor',
650
+ modifiers: {
651
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
652
+ ...flags({
653
+ 'is-rounded': 'isRounded',
654
+ 'is-static': 'isStatic',
655
+ 'is-hovered': 'isHovered',
656
+ 'is-focused': 'isFocused',
657
+ 'is-loading': 'isLoading',
658
+ }),
659
+ },
660
+ omits: Object.fromEntries(COMPONENT_COLORS.map(color => [
661
+ `is-${color}`,
662
+ '`color` renders `has-text-<color>` on the input as well',
663
+ ])),
664
+ adoptsIdFrom: ['Field'],
665
+ ownProps: [
666
+ 'color',
667
+ 'size',
668
+ 'isRounded',
669
+ 'isStatic',
670
+ 'isHovered',
671
+ 'isFocused',
672
+ 'isLoading',
673
+ ],
674
+ passThrough: ['disabled', 'readOnly', 'ref'],
675
+ },
676
+ textarea: {
677
+ ...BASE,
678
+ target: 'TextAreaBase',
679
+ tag: 'textarea',
680
+ textColor: null,
681
+ bgColor: 'backgroundColor',
682
+ // `isLoading` renders nothing here: Bulma puts `is-loading` on the control.
683
+ modifiers: {
684
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
685
+ ...flags({
686
+ 'is-rounded': 'isRounded',
687
+ 'is-static': 'isStatic',
688
+ 'is-hovered': 'isHovered',
689
+ 'is-focused': 'isFocused',
690
+ 'is-active': 'isActive',
691
+ 'has-fixed-size': 'hasFixedSize',
692
+ }),
693
+ },
694
+ omits: Object.fromEntries(COMPONENT_COLORS.map(color => [
695
+ `is-${color}`,
696
+ '`color` renders `has-text-<color>` on the textarea as well',
697
+ ])),
698
+ adoptsIdFrom: ['Field'],
699
+ ownProps: [
700
+ 'color',
701
+ 'size',
702
+ 'isRounded',
703
+ 'isStatic',
704
+ 'isHovered',
705
+ 'isFocused',
706
+ 'isLoading',
707
+ 'isActive',
708
+ 'hasFixedSize',
709
+ ],
710
+ passThrough: ['disabled', 'readOnly', 'rows', 'ref'],
711
+ },
550
712
  footer: {
551
713
  ...BASE,
552
714
  target: 'Footer',
@@ -650,6 +812,86 @@ export const ROOTS = {
650
812
  tag: 'div',
651
813
  ownProps: ['color', 'bgColor', 'textColor'],
652
814
  },
815
+ // `Navbar` writes Bulma's own `role` and `aria-label`, so an element that
816
+ // already carries them renders the same.
817
+ navbar: {
818
+ ...BASE,
819
+ target: 'Navbar',
820
+ tag: 'nav',
821
+ modifiers: {
822
+ ...tokens('is-', COMPONENT_COLORS, 'color'),
823
+ ...tokens('is-fixed-', ['top', 'bottom'], 'fixed'),
824
+ ...flags({ 'is-transparent': 'transparent' }),
825
+ },
826
+ defaults: { role: 'navigation', 'aria-label': 'main navigation' },
827
+ ownProps: ['textColor', 'color', 'bgColor', 'transparent', 'fixed'],
828
+ },
829
+ // No background prop on these parts. Menu, Start and End spread `textColor`
830
+ // onto the element rather than reading it, and type `color` to six colors,
831
+ // so their text color stays a class.
832
+ 'navbar-brand': {
833
+ ...BASE,
834
+ target: 'Navbar.Brand',
835
+ tag: 'div',
836
+ bgColor: null,
837
+ ownProps: ['textColor', 'color'],
838
+ },
839
+ 'navbar-menu': {
840
+ ...BASE,
841
+ target: 'Navbar.Menu',
842
+ tag: 'div',
843
+ textColor: null,
844
+ bgColor: null,
845
+ modifiers: flags({ 'is-active': 'active' }),
846
+ ownProps: ['textColor', 'color', 'active'],
847
+ },
848
+ 'navbar-start': {
849
+ ...BASE,
850
+ target: 'Navbar.Start',
851
+ tag: 'div',
852
+ textColor: null,
853
+ bgColor: null,
854
+ ownProps: ['textColor', 'color'],
855
+ },
856
+ 'navbar-end': {
857
+ ...BASE,
858
+ target: 'Navbar.End',
859
+ tag: 'div',
860
+ textColor: null,
861
+ bgColor: null,
862
+ ownProps: ['textColor', 'color'],
863
+ },
864
+ // A `.has-dropdown` item stays a `Navbar.Item` with the class: a
865
+ // `Navbar.Dropdown` would hand its `.navbar-link` dropdown semantics.
866
+ 'navbar-item': {
867
+ ...BASE,
868
+ target: 'Navbar.Item',
869
+ tag: 'a',
870
+ as: 'any',
871
+ modifiers: flags({ 'is-active': 'active' }),
872
+ ownProps: ['as', 'active', 'textColor', 'bgColor'],
873
+ },
874
+ 'navbar-dropdown': {
875
+ status: 'mapped',
876
+ target: 'Navbar.DropdownMenu',
877
+ tag: 'div',
878
+ textColor: null,
879
+ bgColor: null,
880
+ noHelpers: true,
881
+ modifiers: flags({ 'is-right': 'right', 'is-up': 'up' }),
882
+ ownProps: ['right', 'up'],
883
+ },
884
+ 'navbar-divider': {
885
+ status: 'mapped',
886
+ target: 'Navbar.Divider',
887
+ tag: 'hr',
888
+ textColor: null,
889
+ bgColor: null,
890
+ noHelpers: true,
891
+ // bulma-ui's Navbar.Divider spreads `className` over its own class.
892
+ ownClassOnly: true,
893
+ ownProps: [],
894
+ },
653
895
  notification: {
654
896
  ...BASE,
655
897
  target: 'Notification',
@@ -790,12 +1032,6 @@ export const ROOTS = {
790
1032
  checkboxes: todo('Checkboxes', 'bestax `Checkboxes` renders its own `.field` and `.control` wrappers'),
791
1033
  radio: todo('Radio', "bestax `Radio` renders its own styled markup, not Bulma's"),
792
1034
  radios: todo('Radios', 'bestax `Radios` renders its own `.field` and `.control` wrappers'),
793
- field: todo('Field', 'bestax form controls render their own `.field` and `.control` wrappers; see the unmappables reference'),
794
- 'field-label': part(),
795
- 'field-body': part(),
796
- control: part(),
797
- input: todo('Input', 'bestax `Input` renders its own `.field` and `.control` wrappers'),
798
- textarea: todo('TextArea', 'bestax `TextArea` renders its own `.field` and `.control` wrappers'),
799
1035
  select: todo('Select', 'bestax `Select` renders the `.select` wrapper and the `<select>` together'),
800
1036
  file: todo('File', 'bestax `File` renders the whole `.file-label` tree itself'),
801
1037
  'file-label': part(),
@@ -827,18 +1063,8 @@ export const ROOTS = {
827
1063
  'modal-card-body': part(),
828
1064
  'modal-card-foot': part(),
829
1065
  'modal-close': part(),
830
- navbar: todo('Navbar', 'bestax `Navbar` adds navigation roles, and its burger renders its own spans'),
831
- 'navbar-brand': part(),
832
- 'navbar-burger': part(),
833
- 'navbar-menu': part(),
834
- 'navbar-start': part(),
835
- 'navbar-end': part(),
836
- 'navbar-item': part(),
837
- 'navbar-link': part(),
838
- 'navbar-dropdown': part(),
839
- 'navbar-divider': part(),
840
- 'navbar-content': part(),
841
- 'navbar-tabs': part(),
1066
+ 'navbar-burger': todo('Navbar.Burger', 'bestax `Navbar.Burger` is a `<button>` that renders its own spans and `aria-expanded`, so rebuild the toggle with it, by hand'),
1067
+ 'navbar-link': todo('Navbar.Link', 'inside a `Navbar.Dropdown`, bestax `Navbar.Link` adds `aria-haspopup`, `aria-expanded` and keyboard handling, so convert the `.has-dropdown` item and its link together, by hand'),
842
1068
  pagination: todo('Pagination', 'bestax `Pagination` renders its own list items and adds navigation roles'),
843
1069
  'pagination-list': part(),
844
1070
  'pagination-link': part(),
@@ -862,6 +1088,8 @@ export const ROOTS = {
862
1088
  loader: plain("bestax `Loading` is an overlay, not Bulma's inline spinner"),
863
1089
  'hero-buttons': plain('a layout class inside `.hero`; bestax has no part for it'),
864
1090
  'hero-video': plain('a layout class inside `.hero`; bestax has no part for it'),
1091
+ 'navbar-content': plain('a layout class inside `.navbar`; bestax has no part for it'),
1092
+ 'navbar-tabs': plain('a layout class inside `.navbar`; bestax has no part for it'),
865
1093
  'theme-dark': plain('a theme scope; bestax sets themes through `Theme`'),
866
1094
  'theme-light': plain('a theme scope; bestax sets themes through `Theme`'),
867
1095
  fa: plain("Font Awesome's own class, styled by Bulma inside `.icon`"),
@@ -909,6 +1137,20 @@ export const PRECEDENCE = [
909
1137
  'card-content',
910
1138
  'card-footer',
911
1139
  'card-footer-item',
1140
+ 'navbar',
1141
+ 'navbar-brand',
1142
+ 'navbar-menu',
1143
+ 'navbar-start',
1144
+ 'navbar-end',
1145
+ 'navbar-item',
1146
+ 'navbar-dropdown',
1147
+ 'navbar-divider',
1148
+ 'field',
1149
+ 'field-label',
1150
+ 'field-body',
1151
+ 'control',
1152
+ 'input',
1153
+ 'textarea',
912
1154
  'buttons',
913
1155
  'tags',
914
1156
  'button',
@@ -924,7 +1166,15 @@ export const PRECEDENCE = [
924
1166
  'block',
925
1167
  ];
926
1168
  /** Refs reach the element only through these targets. */
927
- export const FORWARDS_REF = ['Button', 'Link'];
1169
+ export const FORWARDS_REF = [
1170
+ 'Button',
1171
+ 'Link',
1172
+ 'Navbar',
1173
+ 'Navbar.Item',
1174
+ 'Control',
1175
+ 'InputBase',
1176
+ 'TextAreaBase',
1177
+ ];
928
1178
  /**
929
1179
  * Plain tags bestax wraps, for an element with helper classes and no root
930
1180
  * (`<p className="has-text-centered">` → `<Paragraph textAlign="centered">`).
@@ -28,6 +28,15 @@ export interface ElementFacts {
28
28
  * counts: one in an expression may not render.
29
29
  */
30
30
  childTargets?: readonly string[];
31
+ /** The bestax components already in the file inside this element. */
32
+ bestaxInside?: readonly string[];
33
+ /** The bestax components already in the file around this element. */
34
+ bestaxAround?: readonly string[];
35
+ /**
36
+ * The other components around this element (not bestax, not a fragment),
37
+ * any of which could render a bestax component around it.
38
+ */
39
+ componentsAround?: readonly string[];
31
40
  /**
32
41
  * The component this element is the only child of, if any (`Link` for
33
42
  * `<Link href="/x"><a className="button">`), since that component can
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AA+BD,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAiQ9C"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AA+BD,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CA8R9C"}
@@ -128,8 +128,21 @@ export function plan(facts) {
128
128
  if (entry.requiresChildren && !facts.hasChildren) {
129
129
  return refuse('children', target, `bestax \`${target}\` requires children, and this element has none; keep it as markup`);
130
130
  }
131
+ if (entry.providesContext && facts.bestaxInside?.length) {
132
+ return refuse('context', target, `bestax \`${target}\` tells the bestax form controls inside it to skip wrappers of their own, and this element already holds \`${facts.bestaxInside[0]}\`, which could render differently inside it; keep this element as markup, or convert it and check that component by hand`);
133
+ }
134
+ if (entry.adoptsIdFrom && !facts.attributes.has('id')) {
135
+ // Context follows the render tree, not the file: a component of the app
136
+ // around the element can render a labelled `Field` around it just as well.
137
+ const around = facts.bestaxAround?.find(name => entry.adoptsIdFrom.includes(name)) ??
138
+ facts.componentsAround?.[0];
139
+ if (around) {
140
+ return refuse('context', target, `this element has no \`id\` and sits inside \`<${around}>\`, which is or could render a bestax \`${entry.adoptsIdFrom.join('` or `')}\` with a \`label\`; bestax \`${target}\` would then take that generated \`id\`; give the element an \`id\` of its own, then re-run`);
141
+ }
142
+ }
131
143
  const wraps = entry.wrapsChildren;
132
144
  if (wraps &&
145
+ (!wraps.when || tokens.includes(wraps.when)) &&
133
146
  (facts.hasChildren || wraps.whenEmpty) &&
134
147
  !facts.childTargets?.some(child => wraps.unless.includes(child))) {
135
148
  const parts = wraps.unless.map(part => `\`${part}\``);
@@ -174,7 +187,7 @@ export function plan(facts) {
174
187
  converted.add(token);
175
188
  continue;
176
189
  }
177
- const helper = HELPER_TOKENS.get(token);
190
+ const helper = entry.noHelpers ? undefined : HELPER_TOKENS.get(token);
178
191
  if (!helper)
179
192
  continue;
180
193
  const prop = helper.group === 'text-color'
@@ -228,6 +241,9 @@ export function plan(facts) {
228
241
  props.push(['as', as]);
229
242
  props.push(...writes);
230
243
  const rest = tokens.filter(token => !converted.has(token));
244
+ if (entry.ownClassOnly && rest.length > 0) {
245
+ return refuse('attr', 'className', `bestax \`${target}\` drops its own class when it is given a \`className\`, so this element's other classes would take the place of \`.${root}\`; keep it as markup`);
246
+ }
231
247
  return {
232
248
  conversion: {
233
249
  target,
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,eAAO,MAAM,KAAK,EAAE,WAAW,CAAC,MAAM,CAYpC,CAAC;AAqBH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1D"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,eAAO,MAAM,KAAK,EAAE,WAAW,CAAC,MAAM,CAapC,CAAC;AAuBH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1D"}
@@ -14,6 +14,7 @@ import { HELPER_PROPS, LEGACY_09, ROOTS, WRAPPERS, WRAPPER_OWN_PROPS, } from './
14
14
  export const KINDS = new Set([
15
15
  'attr',
16
16
  'children',
17
+ 'context',
17
18
  'defaults',
18
19
  'drops',
19
20
  'dynamic-class',
@@ -41,6 +42,8 @@ const VOCABULARY = new Set([
41
42
  ...HELPER_PROPS,
42
43
  // Refused on every target, so no entry lists it.
43
44
  'dangerouslySetInnerHTML',
45
+ // Refused where the target drops its own class for one it is given.
46
+ 'className',
44
47
  ]);
45
48
  export function inVocabulary(token) {
46
49
  return VOCABULARY.has(token);
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmSvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA2SpB"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmSvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA4VpB"}
@@ -308,22 +308,64 @@ export default function transform(fileInfo, api, options = {}) {
308
308
  // a child that is one of its parts.
309
309
  const planned = new Map();
310
310
  const programScope = root.find(j.Program).paths()[0]?.scope;
311
+ /**
312
+ * The bestax component an element already is, when its name is the bestax
313
+ * import and not a local that shadows it; `scopePath` is where the name is
314
+ * looked up.
315
+ */
316
+ const bestaxTarget = (element, scopePath) => {
317
+ const parts = jsxNameParts(element.openingElement.name);
318
+ const owner = parts && bestaxNames.get(parts[0]);
319
+ if (!owner || !resolvesToBinding(scopePath, parts[0], programScope)) {
320
+ return undefined;
321
+ }
322
+ return [...owner, ...parts.slice(1)].join('.');
323
+ };
311
324
  const childTargets = (elementPath) => (elementPath.node.children ?? []).flatMap((child) => {
312
325
  if (child.type !== 'JSXElement')
313
326
  return [];
314
- const target = planned.get(child)?.conversion?.target;
315
- if (target)
316
- return [target];
317
- // A part the file already uses counts when its name is the bestax
318
- // import, not a local that shadows it. A direct child is looked up in
319
- // the element's own scope, which is the child's.
320
- const parts = jsxNameParts(child.openingElement.name);
321
- const owner = parts && bestaxNames.get(parts[0]);
322
- if (!owner || !resolvesToBinding(elementPath, parts[0], programScope)) {
323
- return [];
327
+ const target = planned.get(child)?.conversion?.target ??
328
+ // A direct child is looked up in the element's own scope, the child's.
329
+ bestaxTarget(child, elementPath);
330
+ return target ? [target] : [];
331
+ });
332
+ // For each element, the bestax components already in the file inside it:
333
+ // `Field` and `Control` change how bestax's form controls render.
334
+ const bestaxInside = new Map();
335
+ root.find(j.JSXElement).forEach(elementPath => {
336
+ const target = bestaxTarget(elementPath.node, elementPath);
337
+ if (!target)
338
+ return;
339
+ for (let up = elementPath.parent; up; up = up.parent) {
340
+ if (up.node?.type !== 'JSXElement')
341
+ continue;
342
+ bestaxInside.set(up.node, [...(bestaxInside.get(up.node) ?? []), target]);
324
343
  }
325
- return [[...owner, ...parts.slice(1)].join('.')];
326
344
  });
345
+ /**
346
+ * The components around an element: the bestax ones already in the file,
347
+ * and the rest (not an HTML tag, not a fragment), which could render one.
348
+ */
349
+ const around = (elementPath) => {
350
+ const bestax = [];
351
+ const other = [];
352
+ for (let up = elementPath.parent; up; up = up.parent) {
353
+ if (up.node?.type !== 'JSXElement')
354
+ continue;
355
+ const target = bestaxTarget(up.node, up);
356
+ if (target) {
357
+ bestax.push(target);
358
+ continue;
359
+ }
360
+ const parts = jsxNameParts(up.node.openingElement.name);
361
+ const name = parts?.join('.');
362
+ if (name && !INTRINSIC.test(name) && !name.includes('-')) {
363
+ if (!PASS_THROUGH_PARENTS.has(name))
364
+ other.push(name);
365
+ }
366
+ }
367
+ return { bestax, other };
368
+ };
327
369
  // `converts` is whether the element would become a component with its
328
370
  // classes written out, so it holds for a computed className too.
329
371
  const elements = [];
@@ -346,6 +388,7 @@ export default function transform(fileInfo, api, options = {}) {
346
388
  attributes.set(attributeName(attr), attributeValue(attr));
347
389
  }
348
390
  const className = staticClassName(classAttr);
391
+ const surrounding = around(elementPath);
349
392
  const facts = {
350
393
  tag: name.name,
351
394
  tokens: className === null
@@ -356,6 +399,9 @@ export default function transform(fileInfo, api, options = {}) {
356
399
  hasRef: attributes.has('ref'),
357
400
  hasChildren: (element.children ?? []).some(reachesReact),
358
401
  childTargets: childTargets(elementPath),
402
+ bestaxInside: bestaxInside.get(element) ?? [],
403
+ bestaxAround: surrounding.bestax,
404
+ componentsAround: surrounding.other,
359
405
  onlyChildOf: onlyChildOf(elementPath, bestaxLocals),
360
406
  };
361
407
  let result = plan(facts);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bestax-migrate",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "description": "Codemods for migrating existing React apps from other Bulma libraries to @allxsmith/bestax-bulma",
5
5
  "type": "module",
6
6
  "bin": {