create-bestax 4.2.18 → 4.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.
Files changed (55) hide show
  1. package/README.md +13 -3
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +1 -0
  4. package/dist/constants.d.ts +12 -0
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +69 -1
  7. package/dist/file-system.d.ts +5 -1
  8. package/dist/file-system.d.ts.map +1 -1
  9. package/dist/file-system.js +11 -1
  10. package/dist/library-range.d.ts +16 -0
  11. package/dist/library-range.d.ts.map +1 -0
  12. package/dist/library-range.js +40 -0
  13. package/dist/project-creator.d.ts +8 -0
  14. package/dist/project-creator.d.ts.map +1 -1
  15. package/dist/project-creator.js +62 -3
  16. package/dist/prompts.d.ts +1 -0
  17. package/dist/prompts.d.ts.map +1 -1
  18. package/dist/prompts.js +15 -1
  19. package/package.json +8 -8
  20. package/templates/skills/bestax-custom-component/references/component-catalog.md +5 -1
  21. package/templates/skills/bestax-form/SKILL.md +40 -15
  22. package/templates/skills/bestax-form/references/api.md +10 -8
  23. package/templates/skills/bestax-form/references/patterns.md +68 -0
  24. package/templates/skills/bestax-icons/references/icon-libraries.md +14 -1
  25. package/templates/skills/bestax-layout-scaffold/SKILL.md +31 -5
  26. package/templates/skills/bestax-layout-scaffold/references/archetypes.md +2 -2
  27. package/templates/skills/bestax-layout-scaffold/references/layout-components.md +52 -5
  28. package/templates/skills/bestax-migrate/SKILL.md +19 -5
  29. package/templates/skills/bestax-migrate/references/bloomer/component-map.md +1 -1
  30. package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +9 -6
  31. package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +4 -1
  32. package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +182 -105
  33. package/templates/skills/bestax-migrate/references/bulma-classes/prop-map.md +50 -17
  34. package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +372 -64
  35. package/templates/skills/bestax-migrate/references/css-migration.md +12 -5
  36. package/templates/skills/bestax-migrate/references/rbx/prop-map.md +20 -14
  37. package/templates/skills/bestax-migrate/references/react-bulma-components/prop-map.md +27 -22
  38. package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +3 -3
  39. package/templates/skills/bestax-optimize/references/modular-build.md +59 -17
  40. package/templates/skills/bestax-theming/SKILL.md +22 -8
  41. package/templates/skills/bestax-theming/examples/dark-mode.tsx +100 -17
  42. package/templates/skills/bestax-theming/examples/theme-config.tsx +20 -8
  43. package/templates/skills/bestax-theming/references/css-variables.md +268 -20
  44. package/templates/skills/bestax-theming/references/themeable-components.md +4 -0
  45. package/templates/vite/README.md +2 -2
  46. package/templates/vite/_oxlintrc.json +8 -0
  47. package/templates/vite/package.json +9 -13
  48. package/templates/vite/src/main.jsx +1 -1
  49. package/templates/vite/vite.config.js +1 -1
  50. package/templates/vite-ts/README.md +2 -2
  51. package/templates/vite-ts/_oxlintrc.json +8 -0
  52. package/templates/vite-ts/package.json +11 -16
  53. package/templates/vite-ts/src/main.tsx +1 -1
  54. package/templates/vite/eslint.config.js +0 -29
  55. package/templates/vite-ts/eslint.config.js +0 -26
@@ -4,7 +4,15 @@ For apps that style plain JSX with Bulma's classes (`<div className="columns">`)
4
4
  wrapper library. The codemod converts an element only when the bestax component renders
5
5
  **exactly the markup the element did**: same tag, same classes, same attributes. Anything else
6
6
  stays as written, with a `TODO(bestax-migrate)` when there is something to decide (see
7
- [unmappables.md](unmappables.md)).
7
+ [unmappables.md](unmappables.md)). The exceptions are deliberate. Font Awesome's own
8
+ `<i aria-hidden="true">` alone in a `.icon` that carries nothing assistive tech reads becomes
9
+ `Icon`, which puts that attribute on the `.icon` instead, since the glyph is hidden either way.
10
+ Such a `.icon` around a bare glyph, in a link or button its own `aria-label` or
11
+ `aria-labelledby` names, becomes `Icon` too, which hides it, since the label is what assistive
12
+ tech reads for the control. Font Awesome 6's long name for a style (`fa-brands`) becomes the
13
+ `bestax-icons` skill's `variant` (`brands`), which renders the short name (`fab`), the same
14
+ style (see `.icon` below). And a Bulma 0.9 helper that v1 removed, which styles nothing now,
15
+ becomes the v1 helper that does its job (the [prop map](prop-map.md) lists them).
8
16
 
9
17
  A class the codemod doesn't know, such as the app's own `pricing-card`, rides along in
10
18
  `className`, which every bestax component passes through. So does a Bulma class with no bestax
@@ -17,98 +25,104 @@ test holds it to that table. Render tests hold the table to the library itself.
17
25
  ## Components
18
26
 
19
27
  The **Tags** column is what the codemod converts the class on: an element on any other tag gets
20
- a `tag:<Target>` TODO instead of a conversion. A component's own `as` can take more. One exception:
21
- a `<label>` or `<div>` `.panel-block` stays markup with no TODO, since bestax renders those as
22
- `Panel.CheckboxBlock`, `Panel.InputBlock` and `Panel.ButtonBlock`, which build their own contents.
23
-
24
- | Bulma class | bestax-bulma | Tags |
25
- | ---------------------- | --------------------- | -------------------------------------------------------------- |
26
- | `.block` | `Block` | `<div>` only |
27
- | `.box` | `Box` | `<div>` only |
28
- | `.button` | `Button` | `<button>`, any tag via `as` |
29
- | `.buttons` | `Buttons` | `<div>` only |
30
- | `.card` | `Card` | `<div>` only |
31
- | `.card-header` | `Card.Header` | `<header>` only |
32
- | `.card-header-title` | `Card.Header.Title` | `<div>`, `<p>`, `<h2>`, `<h3>`, `<h4>` via `as` |
33
- | `.card-header-icon` | `Card.Header.Icon` | `<button>` only |
34
- | `.card-image` | `Card.Image` | `<div>` only |
35
- | `.card-content` | `Card.Content` | `<div>` only |
36
- | `.card-footer` | `Card.Footer` | `<footer>` only |
37
- | `.card-footer-item` | `Card.FooterItem` | `<span>`, `<a>`, `<button>` via `as` |
38
- | `.columns` | `Columns` | `<div>` only |
39
- | `.column` | `Column` | `<div>` only |
40
- | `.grid` | `Grid` | `<div>` only |
41
- | `.cell` | `Cell` | `<div>` only |
42
- | `.container` | `Container` | `<div>` only |
43
- | `.content` | `Content` | `<div>` only |
44
- | `.delete` | `Delete` | `<button>` only |
45
- | `.field` | `Field` | `<div>` only |
46
- | `.field-label` | `Field.Label` | `<div>` only |
47
- | `.field-body` | `Field.Body` | `<div>` only |
48
- | `.control` | `Control` | `<div>`, `<p>` via `as` |
49
- | `.input` | `InputBase` | `<input>` only |
50
- | `.textarea` | `TextAreaBase` | `<textarea>` only |
51
- | `.select` | `SelectBase` | `<div>` only |
52
- | `.footer` | `Footer` | `<footer>`, `<div>` via `as` |
53
- | `.hero` | `Hero` | `<section>` only |
54
- | `.hero-head` | `Hero.Head` | `<div>` only |
55
- | `.hero-body` | `Hero.Body` | `<div>` only |
56
- | `.hero-foot` | `Hero.Foot` | `<div>` only |
57
- | `.level` | `Level` | `<nav>` only |
58
- | `.level-left` | `Level.Left` | `<div>` only |
59
- | `.level-right` | `Level.Right` | `<div>` only |
60
- | `.level-item` | `Level.Item` | `<div>`, `<p>`, `<a>` via `as` |
61
- | `.media` | `Media` | `<article>`, `<div>` via `as` |
62
- | `.media-left` | `Media.Left` | `<figure>`, `<div>` via `as` |
63
- | `.media-content` | `Media.Content` | `<div>` only |
64
- | `.media-right` | `Media.Right` | `<div>` only |
65
- | `.navbar` | `Navbar` | `<nav>` only |
66
- | `.navbar-brand` | `Navbar.Brand` | `<div>` only |
67
- | `.navbar-menu` | `Navbar.Menu` | `<div>` only |
68
- | `.navbar-start` | `Navbar.Start` | `<div>` only |
69
- | `.navbar-end` | `Navbar.End` | `<div>` only |
70
- | `.navbar-item` | `Navbar.Item` | `<a>`, any tag via `as` |
71
- | `.navbar-dropdown` | `Navbar.DropdownMenu` | `<div>` only |
72
- | `.navbar-divider` | `Navbar.Divider` | `<hr>` only |
73
- | `.notification` | `Notification` | `<div>` only |
74
- | `.progress` | `Progress` | `<progress>` only |
75
- | `.section` | `Section` | `<section>` only |
76
- | `.subtitle` | `SubTitle` | `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>`, `<p>` via `as` |
77
- | `.table` | `Table` | `<table>` only |
78
- | `.tag` | `Tag` | `<span>` only |
79
- | `.tags` | `Tags` | `<div>` only |
80
- | `.title` | `Title` | `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>`, `<p>` via `as` |
81
- | `.breadcrumb` | `Breadcrumb` | `<nav>` only |
82
- | `.skeleton-block` | `Skeleton` | `<div>` only |
83
- | `.skeleton-lines` | `Skeleton` | `<div>` only |
84
- | `.file` | `File` | `<div>` only |
85
- | `.icon` | `Icon` | `<span>` only |
86
- | `.icon-text` | `IconText` | `<span>` only |
87
- | `.image` | `Image` | `<div>`, `<figure>`, `<p>` via `as` |
88
- | `.menu` | `Menu` | `<aside>` only |
89
- | `.menu-label` | `Menu.Label` | `<p>` only |
90
- | `.menu-list` | `Menu.List` | `<ul>` only |
91
- | `.modal-background` | `Modal.Background` | `<div>` only |
92
- | `.modal-content` | `Modal.Content` | `<div>` only |
93
- | `.modal-card` | `Modal.Card` | `<div>` only |
94
- | `.modal-card-head` | `Modal.Card.Head` | `<header>` only |
95
- | `.modal-card-title` | `Modal.Card.Title` | `<p>` only |
96
- | `.modal-card-body` | `Modal.Card.Body` | `<section>` only |
97
- | `.modal-card-foot` | `Modal.Card.Foot` | `<footer>` only |
98
- | `.pagination` | `Pagination` | `<nav>` only |
99
- | `.pagination-list` | `Pagination.List` | `<ul>` only |
100
- | `.pagination-previous` | `Pagination.Previous` | `<a>` only |
101
- | `.pagination-next` | `Pagination.Next` | `<a>` only |
102
- | `.pagination-link` | `Pagination.Link` | `<a>` only |
103
- | `.pagination-ellipsis` | `Pagination.Ellipsis` | `<span>` only |
104
- | `.panel` | `Panel` | `<nav>` only |
105
- | `.panel-heading` | `Panel.Heading` | `<p>` only |
106
- | `.panel-tabs` | `Panel.Tabs` | `<p>` only |
107
- | `.panel-block` | `Panel.Block` | `<a>` only |
108
- | `.tabs` | `Tabs` | `<div>` only |
109
-
110
- An element with two of these (`<div className="column box">`) becomes the layout one
111
- (`Column`), and the other class stays in `className`.
28
+ a `tag:<Target>` TODO instead of a conversion. A component's own `as` can take more.
29
+
30
+ | Bulma class | bestax-bulma | Tags |
31
+ | ---------------------- | --------------------- | ------------------------------------------------------------------------------------------------ |
32
+ | `.block` | `Block` | `<div>` only |
33
+ | `.box` | `Box` | `<div>` only |
34
+ | `.button` | `Button` | `<button>`, any tag via `as` |
35
+ | `.buttons` | `Buttons` | `<div>` only |
36
+ | `.card` | `Card` | `<div>` only |
37
+ | `.card-header` | `Card.Header` | `<header>` only |
38
+ | `.card-header-title` | `Card.Header.Title` | `<div>`, `<p>`, `<h2>`, `<h3>`, `<h4>` via `as` |
39
+ | `.card-header-icon` | `Card.Header.Icon` | `<button>` only |
40
+ | `.card-image` | `Card.Image` | `<div>` only |
41
+ | `.card-content` | `Card.Content` | `<div>` only |
42
+ | `.card-footer` | `Card.Footer` | `<footer>` only |
43
+ | `.card-footer-item` | `Card.FooterItem` | `<span>`, `<a>`, `<button>` via `as` |
44
+ | `.columns` | `Columns` | `<div>` only |
45
+ | `.column` | `Column` | `<div>` only |
46
+ | `.grid` | `Grid` | `<div>` only |
47
+ | `.cell` | `Cell` | `<div>` only |
48
+ | `.container` | `Container` | `<div>`, `<main>`, `<section>`, `<article>`, `<aside>`, `<header>`, `<footer>`, `<nav>` via `as` |
49
+ | `.content` | `Content` | `<div>` only |
50
+ | `.delete` | `Delete` | `<button>` only |
51
+ | `.field` | `Field` | `<div>` only |
52
+ | `.field-label` | `Field.Label` | `<div>` only |
53
+ | `.field-body` | `Field.Body` | `<div>` only |
54
+ | `.control` | `Control` | `<div>`, `<p>` via `as` |
55
+ | `.input` | `InputBase` | `<input>` only |
56
+ | `.textarea` | `TextAreaBase` | `<textarea>` only |
57
+ | `.select` | `SelectBase` | `<div>` only |
58
+ | `.footer` | `Footer` | `<footer>`, `<div>` via `as` |
59
+ | `.hero` | `Hero` | `<section>`, `<div>`, `<main>`, `<header>`, `<footer>`, `<article>`, `<aside>` via `as` |
60
+ | `.hero-head` | `Hero.Head` | `<div>`, `<header>`, `<nav>` via `as` |
61
+ | `.hero-body` | `Hero.Body` | `<div>` only |
62
+ | `.hero-foot` | `Hero.Foot` | `<div>`, `<footer>`, `<nav>` via `as` |
63
+ | `.level` | `Level` | `<nav>` only |
64
+ | `.level-left` | `Level.Left` | `<div>` only |
65
+ | `.level-right` | `Level.Right` | `<div>` only |
66
+ | `.level-item` | `Level.Item` | `<div>`, `<p>`, `<a>` via `as` |
67
+ | `.media` | `Media` | `<article>`, `<div>` via `as` |
68
+ | `.media-left` | `Media.Left` | `<figure>`, `<div>` via `as` |
69
+ | `.media-content` | `Media.Content` | `<div>` only |
70
+ | `.media-right` | `Media.Right` | `<div>` only |
71
+ | `.navbar` | `Navbar` | `<nav>` only |
72
+ | `.navbar-brand` | `Navbar.Brand` | `<div>` only |
73
+ | `.navbar-menu` | `Navbar.Menu` | `<div>` only |
74
+ | `.navbar-start` | `Navbar.Start` | `<div>` only |
75
+ | `.navbar-end` | `Navbar.End` | `<div>` only |
76
+ | `.navbar-item` | `Navbar.Item` | `<a>`, any tag via `as` |
77
+ | `.navbar-dropdown` | `Navbar.DropdownMenu` | `<div>` only |
78
+ | `.navbar-divider` | `Navbar.Divider` | `<hr>` only |
79
+ | `.notification` | `Notification` | `<div>` only |
80
+ | `.progress` | `Progress` | `<progress>` only |
81
+ | `.section` | `Section` | `<section>` only |
82
+ | `.subtitle` | `SubTitle` | `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>`, `<p>` via `as` |
83
+ | `.table` | `Table` | `<table>` only |
84
+ | `.tag` | `Tag` | `<span>` only |
85
+ | `.tags` | `Tags` | `<div>` only |
86
+ | `.title` | `Title` | `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>`, `<p>` via `as` |
87
+ | `.breadcrumb` | `Breadcrumb` | `<nav>` only |
88
+ | `.skeleton-block` | `Skeleton` | `<div>` only |
89
+ | `.skeleton-lines` | `Skeleton` | `<div>` only |
90
+ | `.file` | `File` | `<div>` only |
91
+ | `.icon` | `Icon` | `<span>` only |
92
+ | `.icon-text` | `IconText` | `<span>` only |
93
+ | `.image` | `Image` | `<div>`, `<figure>`, `<p>` via `as` |
94
+ | `.menu` | `Menu` | `<aside>` only |
95
+ | `.menu-label` | `Menu.Label` | `<p>` only |
96
+ | `.menu-list` | `Menu.List` | `<ul>` only |
97
+ | `.modal-background` | `Modal.Background` | `<div>` only |
98
+ | `.modal-content` | `Modal.Content` | `<div>` only |
99
+ | `.modal-card` | `Modal.Card` | `<div>` only |
100
+ | `.modal-card-head` | `Modal.Card.Head` | `<header>` only |
101
+ | `.modal-card-title` | `Modal.Card.Title` | `<p>` only |
102
+ | `.modal-card-body` | `Modal.Card.Body` | `<section>` only |
103
+ | `.modal-card-foot` | `Modal.Card.Foot` | `<footer>` only |
104
+ | `.pagination` | `Pagination` | `<nav>` only |
105
+ | `.pagination-list` | `Pagination.List` | `<ul>` only |
106
+ | `.pagination-previous` | `Pagination.Previous` | `<a>` only |
107
+ | `.pagination-next` | `Pagination.Next` | `<a>` only |
108
+ | `.pagination-link` | `Pagination.Link` | `<a>` only |
109
+ | `.pagination-ellipsis` | `Pagination.Ellipsis` | `<span>` only |
110
+ | `.panel` | `Panel` | `<nav>`, `<article>`, `<section>`, `<aside>`, `<div>` via `as` |
111
+ | `.panel-heading` | `Panel.Heading` | `<p>` only |
112
+ | `.panel-tabs` | `Panel.Tabs` | `<p>` only |
113
+ | `.panel-block` | `Panel.Block` | `<a>`, `<div>`, `<label>` via `as` |
114
+ | `.tabs` | `Tabs` | `<div>` only |
115
+
116
+ An element with two of these (`<div className="column box">`) becomes the one whose component
117
+ fits its tag best, and the other class stays in `className` with a `second-component:<Target>`
118
+ TODO. A component that renders the tag with no `as` beats one that reaches it only through `as`,
119
+ which beats one that can't render it, and between equals the layout one wins (`Column`). So
120
+ `<section className="hero container">` becomes a `Hero`, and `<figure className="image container">`
121
+ an `Image`, which `Container` can't render. The tag a component renders with no `as` is the one
122
+ the element's classes give it: a ratio puts `Image` on a `<figure>`, so
123
+ `<figure className="navbar-item image is-16by9">` becomes an `Image`, and
124
+ `<div className="media-left image is-1by1">` a `Media.Left`, since both reach a `<div>` only
125
+ through `as` there. A heading's size does the same for `Title` and `SubTitle`.
112
126
 
113
127
  `Card` renders its children inside a `.card-content` of its own unless one of them is one of
114
128
  its parts, and `Card.Header` its children inside a `.card-header-title` unless one of them is a
@@ -144,9 +158,64 @@ component, which could hand it a labelled Field's generated one.
144
158
  A `.tabs` converts around its `<ul>`, and the `<li>`s and `<a>`s inside stay as written: `Tabs.Tab`
145
159
  renders its own `<a>` with tab roles and puts its label in a `<span>`, so converting the tabs
146
160
  themselves is by hand (something that sat beside the text in the `<a>`, a `Tag` say, then wants a
147
- `Span display="flex" alignItems="center"` around it and the label). A `.icon` converts around the
148
- `<i>` inside it when it carries the attribute `Icon` writes otherwise: `aria-hidden` with no name,
149
- no `role` and no `tabIndex`, and `role="img"` beside an `aria-label` or `aria-labelledby`.
161
+ `Span display="flex" alignItems="center"` around it and the label). A `.icon` converts when it
162
+ carries the attribute `Icon` writes otherwise: `aria-hidden` with no name, no `role` and no
163
+ `tabIndex`, and `role="img"` beside an `aria-label` or `aria-labelledby`. Those attributes are
164
+ left out, since `Icon` renders them by itself. When all it holds is a bare, empty `<i>` naming a
165
+ Font Awesome or Material Design Icons glyph, the `<i>` goes and its classes become `Icon`'s
166
+ props, read as `IconText` reads them (below), and the `Icon` closes itself:
167
+
168
+ ```jsx
169
+ <span className="icon is-small" aria-hidden="true">
170
+ <i className="fab fa-github fa-lg"></i>
171
+ </span>
172
+ // becomes, rendering aria-hidden="true" on the .icon
173
+ <Icon name="github" variant="brands" features="fa-lg" size="small" />
174
+ ```
175
+
176
+ Font Awesome's own markup hides the `<i>` instead, and converts the same way when the `.icon`
177
+ carries nothing but its classes, an `id`, a `style` and `data-` attributes: the `aria-hidden`
178
+ moves up onto the `.icon`, where `Icon` writes it, so the glyph is hidden either way. That is a
179
+ place a conversion changes the markup, on purpose:
180
+
181
+ ```jsx
182
+ <span className="icon is-small is-left">
183
+ <i className="fas fa-envelope" aria-hidden="true"></i>
184
+ </span>
185
+ // becomes, rendering aria-hidden="true" on the .icon
186
+ <Icon name="envelope" size="small" className="is-left" />
187
+ ```
188
+
189
+ A `.icon` with no `aria-hidden` converts the same way when it sits in a `<button>`, or in a link
190
+ (an `<a>` with an `href`), that its own `aria-label` or `aria-labelledby` names. That label is
191
+ what assistive tech reads for the control, in place of what it holds, so the icon is decoration
192
+ there, and `Icon` hides it. That is another place a conversion changes the markup, on purpose,
193
+ held to the same shape: a bare glyph, in a `.icon` that carries nothing but its classes, an `id`,
194
+ a `style` and `data-` attributes.
195
+
196
+ ```jsx
197
+ <a className="button" href="https://github.com/" aria-label="GitHub">
198
+ <span className="icon"><i className="fab fa-github"></i></span>
199
+ </a>
200
+ // becomes, rendering aria-hidden="true" on the .icon
201
+ <Button as="a" href="https://github.com/" aria-label="GitHub">
202
+ <Icon name="github" variant="brands" />
203
+ </Button>
204
+ ```
205
+
206
+ Around anything else, an `<i>` with an attribute of its own or an `<svg>` say, it converts around
207
+ what it holds, kept as written.
208
+
209
+ The glyph's props are spelled the way the `bestax-icons` skill writes them. `library` is left out
210
+ for Font Awesome, `Icon`'s default, and written for Material Design Icons. The style is `variant`:
211
+ none for `fas`, and `regular`, `brands`, `light`, `duotone` or `thin` for the others. Font
212
+ Awesome 6's long names for them (`fa-solid`, `fa-brands`, ...) read the same way, and `Icon`
213
+ renders the short name (`fab`), the class Font Awesome 5 knows, which 6 and 7 style the same:
214
+ a third place the markup changes on purpose. Beside `fa-sharp`, whose family Font Awesome 7's
215
+ short name would set back to the classic one, the long name stays as written. Font Awesome 4's
216
+ `fa` reads as `variant="fa"`, which `Icon` renders as written: 4 styles nothing else, and some
217
+ 4 names draw another glyph in 5 and later (the `bestax-icons` skill's
218
+ `references/icon-libraries.md` lists them).
150
219
 
151
220
  A `.menu` converts with its `.menu-label`s and `.menu-list`s, and so do the items in a list. An
152
221
  item has no class to go by, so the codemod finds it by where it sits: a `<li>` whose nearest
@@ -243,7 +312,8 @@ go straight inside `Breadcrumb`, and `<figure className="image is-64x64"><img sr
243
312
  one, so the `<ul>` carries nothing and the `.breadcrumb` needs an `aria-label` of its own.
244
313
  - `Image` renders its `<img>` from `src` and `alt`, so the `<img>` carries nothing else, and
245
314
  `is-rounded` on it becomes `isRounded`. The `.image` keeps its own attributes. A ratio
246
- (`is-4by3`) stays a class, since `size` would add `has-ratio` as well. Around anything else (an
315
+ (`is-4by3`) becomes `size` too. `Image` renders a ratio on a `<figure>`, so a `<figure>` needs no
316
+ `as` there and a `<div>` keeps `as="div"`. Around anything else (an
247
317
  `<img>` with more attributes, an `<iframe>`), `Image` renders its children as given, so the
248
318
  `.image` converts around them and they stay as written, as long as they're HTML elements written
249
319
  out. An empty `.image` stays markup, since `Image` would render an `<img>` of its own, and so does
@@ -276,14 +346,16 @@ as `items`.
276
346
  <span>Home</span>
277
347
  </span>
278
348
  // becomes
279
- <IconText iconProps={{ library: "fa", name: "home", "aria-hidden": "true" }}>Home</IconText>
349
+ <IconText iconProps={{ name: "home" }}>Home</IconText>
280
350
  ```
281
351
 
282
352
  The glyph is read from the `<i>`: its Font Awesome style class (`fas`, `far`, `fa-solid`, ...) or
283
353
  `mdi`, the one class that names the glyph (`fa-home` as `name: "home"`), and the rest as
284
- `features`. `library` is always written, so a `ConfigProvider` with another `iconLibrary` doesn't
285
- change what renders. The `.icon`'s own classes and attributes join the glyph's props as they
286
- would on `Icon`, under their own names.
354
+ `features`, spelled as on `Icon` (above). Like every conversion, this takes the app's
355
+ `ConfigProvider` as unset: one with another `iconLibrary` needs `library: "fa"` written back on
356
+ the Font Awesome ones, as one with a `classPrefix` changes every component's classes. The
357
+ `.icon`'s own classes and attributes join the glyph's props as they would on `Icon`, under their
358
+ own names, but for those `Icon` renders by itself.
287
359
 
288
360
  It converts only when every `.icon` inside converts to `Icon` on its own and holds a bare, empty
289
361
  `<i>` naming a Font Awesome or Material Design Icons glyph, and the only other children are those
@@ -345,7 +417,12 @@ button, the navbar's burger and dropdown link, the panel's icon, Radio and Radio
345
417
  ## Classes left alone
346
418
 
347
419
  `.help`, `.label`, `.hero-buttons`, `.hero-video`, `.theme-dark`, `.theme-light`, `.fa`,
348
- `.marginless`, `.paddingless`, `.navbar-content`, `.navbar-tabs` and `.panel-list` are valid
349
- Bulma with nothing in bestax to convert to. `.loader` is left alone as well, although bestax's
350
- `Loader` renders the same element: swap it in by hand for its progressbar role and accessible name.
351
- An element carrying one stays as written, and gets no TODO.
420
+ `.navbar-content`, `.navbar-tabs` and `.panel-list` are valid Bulma with nothing in bestax to
421
+ convert to. `.loader` is left alone as well, although bestax's `Loader` renders the same
422
+ element: swap it in by hand for its progressbar role and accessible name. An element carrying
423
+ one stays as written, and gets no TODO.
424
+
425
+ v1's `marginless` and `paddingless` are helpers, not components, so they don't hold an element
426
+ back: `<p className="has-text-centered marginless">` becomes
427
+ `<Paragraph textAlign="centered" className="marginless">`. They keep their names, since bestax
428
+ writes the same rules as `m-0` and `p-0`.
@@ -2,7 +2,8 @@
2
2
 
3
3
  Which class becomes which prop, per component, then the helper classes every component takes.
4
4
  A class that becomes no prop stays in `className`. So does a second class for a prop already
5
- written (`is-small is-large` keeps `is-large`), so the element still renders both.
5
+ written (`is-small is-large` keeps `is-large`), so the element still renders both. A second
6
+ color gets a `modifier:<root>` TODO (`modifier:button`), since only one of the two may show.
6
7
 
7
8
  `{viewport}` is one of `mobile`, `tablet`, `desktop`, `widescreen`, `fullhd` unless a row says
8
9
  otherwise, and the prop takes the matching suffix: `is-6-tablet` → `sizeTablet="6"`.
@@ -72,7 +73,10 @@ Sizes are `1` to `12`, `full`, `half`, `one-third`, `two-thirds`, `one-quarter`,
72
73
 
73
74
  bestax picks the heading from `size` (`size="3"` renders an `<h3>`) unless `as="p"`. So on an
74
75
  `<h2>`, `is-4` stays a class and the element becomes `<Title as="h2" className="is-4">`, which
75
- renders the same `<h2>`.
76
+ renders the same `<h2>`. To write it as a prop, `textSize="4"` keeps the `<h2>` and sizes it the
77
+ same: it renders Bulma's `is-size-4`, which has the font size `is-4` gives a title or subtitle,
78
+ and as a Bulma helper it is `!important`, so check a title the page's own CSS sizes. The
79
+ codemod's `modifier:title` (or `modifier:subtitle`) TODO on the element says the same.
76
80
 
77
81
  ### Other components
78
82
 
@@ -85,6 +89,8 @@ renders the same `<h2>`.
85
89
  | `.content` → `Content` | `is-small`, `is-medium`, `is-large` | `size` |
86
90
  | `.delete` → `Delete` | `is-small`, `is-medium`, `is-large` | `size` |
87
91
  | `.field` → `Field` | `is-horizontal`, `is-grouped`, `has-addons`, `is-narrow` | `horizontal`, `grouped`, `hasAddons`, `narrow` |
92
+ | `.field` → `Field` | `has-addons-centered`, `has-addons-right`, beside `has-addons` | `hasAddons="centered"`, `hasAddons="right"`, which render both classes |
93
+ | `.field` → `Field` | `is-grouped-centered`, `is-grouped-right`, `is-grouped-multiline`, beside `is-grouped` | `grouped="centered"`, `grouped="right"`, `grouped="multiline"`, which render both classes |
88
94
  | `.grid` → `Grid` | `is-gap-{step}`, `is-column-gap-{step}`, `is-row-gap-{step}`, `0` to `8` in half steps (`is-gap-1.5`) | `gap`, `columnGap`, `rowGap` |
89
95
  | `.grid` → `Grid` | `is-col-min-{1-32}` | `minCol` (a number: `minCol={8}`) |
90
96
  | `.fixed-grid` → `Grid isFixed` (folded) | `has-{1-12}-cols`, `has-{1-12}-cols-{viewport}`, `has-auto-count` | `fixedCols`, `fixedCols{Viewport}` (numbers: `fixedCols={3}`), `fixedCols="auto"` |
@@ -103,7 +109,8 @@ renders the same `<h2>`.
103
109
  | the `<select>` inside `.select` | `is-hovered`, `is-focused` | `isHovered`, `isFocused` |
104
110
  | `.hero` → `Hero` | `is-primary`, `is-link`, `is-info`, `is-success`, `is-warning`, `is-danger`, `is-black`, `is-white`, `is-light`, `is-dark` | `color` |
105
111
  | `.hero` → `Hero` | `is-small`, `is-medium`, `is-large`, `is-fullheight`, `is-fullheight-with-navbar` | `size` |
106
- | `.image` → `Image` | `is-16x16`, `is-24x24`, `is-32x32`, `is-48x48`, `is-64x64`, `is-96x96`, `is-128x128`, `is-square` | `size` (a ratio such as `is-4by3` stays a class, since `size` would add `has-ratio`) |
112
+ | `.image` → `Image` | `is-16x16`, `is-24x24`, `is-32x32`, `is-48x48`, `is-64x64`, `is-96x96`, `is-128x128`, `is-square` | `size` |
113
+ | `.image` → `Image` | `is-{ratio}`, for each of the Ratios under Helper classes (`is-16by9`), but not `is-square` (see below) | `size`, on the `<figure>` it renders with no `as` (see below) |
107
114
  | the `<img>` inside `.image` | `is-rounded` | `isRounded` |
108
115
  | `.icon` → `Icon` | `is-small`, `is-medium`, `is-large` | `size` |
109
116
  | `.tabs` → `Tabs` | `is-centered`, `is-right`, `is-left` | `align` |
@@ -116,7 +123,7 @@ renders the same `<h2>`.
116
123
  | `.level` → `Level` | `is-mobile` | `isMobile` |
117
124
  | `.navbar` → `Navbar` | the ten `.hero` colors | `color` |
118
125
  | `.navbar` → `Navbar` | `is-fixed-top`, `is-fixed-bottom` | `fixed` (`top`, `bottom`) |
119
- | `.navbar` → `Navbar` | `is-transparent` | `transparent` |
126
+ | `.navbar` → `Navbar` | `is-transparent`, `is-spaced`, `has-shadow` | `transparent`, `isSpaced`, `hasShadow` |
120
127
  | `.navbar-menu` → `Navbar.Menu`, `.navbar-item` → `Navbar.Item` | `is-active` | `active` |
121
128
  | `.navbar-dropdown` → `Navbar.DropdownMenu` | `is-right`, `is-up` | `right`, `up` |
122
129
  | `.notification` → `Notification` | `is-primary`, `is-link`, `is-info`, `is-success`, `is-warning`, `is-danger`, `is-black`, `is-white`, `is-dark` | `color` |
@@ -130,6 +137,16 @@ renders the same `<h2>`.
130
137
  | `.tag` → `Tag` | `is-light`, `is-rounded`, `is-hoverable` | `isLight`, `isRounded`, `isHoverable` |
131
138
  | `.tag` → `Tag` | `is-medium`, `is-large` | `size` |
132
139
 
140
+ `is-square` sits with the fixed sizes, not the ratios. Bulma sizes it like `is-1by1`, but `Image`
141
+ renders `size="square"` on a `<div>`, as it does a fixed size. So
142
+ `<figure className="image is-square">` becomes `<Image as="figure" size="square">`, while
143
+ `<figure className="image is-1by1">` becomes `<Image size="1by1">`.
144
+
145
+ A ratio converts to identical markup only on a bestax-bulma whose `Image` writes nothing but the
146
+ ratio class on its container. An older one also writes `has-ratio` there, which Bulma reads only
147
+ on a child, so the page looks the same, unless that `.image` sits inside another ratio `.image`,
148
+ which then stretches it to fill. Upgrade bestax-bulma, or keep that ratio as a class.
149
+
133
150
  `Progress` takes `value` and `max` as numbers: `value="40"` becomes `value={40}`. An
134
151
  expression (`value={percent}`) carries over as written, so if it holds a string the migrated
135
152
  file fails to typecheck while still rendering the same; wrap it in `Number(…)`. `Delete`
@@ -137,14 +154,14 @@ converts only with `type` and `aria-label` set (see `defaults:<Target>` in the u
137
154
  and a `type="button"` is dropped, since bestax renders it by itself. `Card.Header.Icon` likewise
138
155
  converts only with an `aria-label` and a `type` of `button`, `submit` or `reset`, since it renders
139
156
  `aria-label="more options"` and `type="button"` otherwise.
140
- `.tag`'s `is-delete` stays a class: `isDelete` turns the tag into a `<button>`. `.navbar`'s
141
- `is-spaced` and `has-shadow`, and a `.navbar-item`'s `has-dropdown` and `is-hoverable`, stay
142
- classes too: bestax has no prop for them on those components. So do a `.field`'s
143
- `has-addons-centered`, `has-addons-right` and `is-grouped-*`, because the `hasAddons` and
144
- `grouped` values that render them render `has-addons` and `is-grouped` as well, and an input's,
145
- textarea's or select's color, because `color` renders `has-text-<color>` on it too. On a
146
- `.columns`, the gap helpers (`is-gap-*`, `is-column-gap-*`, `is-row-gap-*`) stay classes as well:
147
- `Columns`' own `gap` is its gutter (`is-<step>`), and it leaves the column and row gap helpers out.
157
+ `.tag`'s `is-delete` stays a class: `isDelete` turns the tag into a `<button>`. A
158
+ `.navbar-item`'s `has-dropdown` and `is-hoverable` stay classes too, since bestax has no prop for
159
+ them on that component. So do a `.field`'s `has-addons-centered`, `has-addons-right` and
160
+ `is-grouped-*` without `has-addons` or `is-grouped` beside them, because the `hasAddons` and
161
+ `grouped` values that render them render those as well, and an input's, textarea's or select's
162
+ color, because `color` renders `has-text-<color>` on it too. On a `.columns`, the gap helpers
163
+ (`is-gap-*`, `is-column-gap-*`, `is-row-gap-*`) stay classes as well: `Columns`' own `gap` is its
164
+ gutter (`is-<step>`), and it leaves the column and row gap helpers out.
148
165
 
149
166
  ## Helper classes
150
167
 
@@ -152,7 +169,10 @@ These convert on every component above and on the plain-tag wrappers.
152
169
 
153
170
  Colors are `primary`, `link`, `info`, `success`, `warning`, `danger`, `black`, `black-bis`,
154
171
  `black-ter`, `grey-darker`, `grey-dark`, `grey`, `grey-light`, `grey-lighter`, `white`,
155
- `white-bis`, `white-ter`, `light`, `dark`, `inherit` and `current`. Gap steps are `0` to `8` in
172
+ `white-bis`, `white-ter`, `light`, `dark`, `inherit` and `current`. Shades are `00` to `95` in
173
+ steps of five, `invert`, `light`, `dark`, `soft`, `bold` and `on-scheme`, on the colors Bulma
174
+ shades: `primary`, `link`, `info`, `success`, `warning`, `danger`, `black`, `white`, `light` and
175
+ `dark`. Gap steps are `0` to `8` in
156
176
  half steps (`0`, `0.5`, `1`, … `7.5`, `8`). Overflow values are `auto`, `clip`, `hidden`, `scroll`
157
177
  and `visible`. Ratios are `1by1`, `5by4`, `4by3`, `3by2`, `5by3`, `16by9`, `2by1`, `3by1`,
158
178
  `4by5`, `3by4`, `2by3`, `3by5`, `9by16`, `1by2` and `1by3`.
@@ -161,8 +181,10 @@ and `visible`. Ratios are `1by1`, `5by4`, `4by3`, `3by2`, `5by3`, `16by9`, `2by1
161
181
  | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
162
182
  | `m-{n}`, `mt-{n}`, `mr-{n}`, `mb-{n}`, `ml-{n}`, `mx-{n}`, `my-{n}` (`0` to `6`, `auto`) | `m`, `mt`, `mr`, `mb`, `ml`, `mx`, `my` |
163
183
  | `p-{n}`, `pt-{n}`, `pr-{n}`, `pb-{n}`, `pl-{n}`, `px-{n}`, `py-{n}` | `p`, `pt`, `pr`, `pb`, `pl`, `px`, `py` |
184
+ | `is-marginless`, `is-paddingless` (Bulma 0.9's, which v1 removed) | `m="0"`, `p="0"`, which render v1's `m-0` and `p-0` |
164
185
  | `has-text-{color}` | `textColor` (on `Menu`, `Menu.Label`, `Menu.List` and `Table`, `color`) |
165
186
  | `has-background-{color}` | `bgColor` (on `Menu`, `Menu.Label`, `Menu.List`, `Tag`, `File`, `InputBase`, `TextAreaBase` and `SelectBase`, `backgroundColor`) |
187
+ | `has-text-{color}-{shade}`, `has-background-{color}-{shade}` | the same color prop, with `colorShade` or `backgroundColorShade` (`textColor="primary" colorShade="on-scheme"`) |
166
188
  | `is-size-1` … `is-size-7`, and `-{viewport}` | `textSize`, `textSize{Viewport}` |
167
189
  | `has-text-centered`, `-justified`, `-left`, `-right`, and `-{viewport}` | `textAlign`, `textAlign{Viewport}` |
168
190
  | `is-capitalized`, `is-lowercase`, `is-uppercase`, `is-italic` | `textTransform` |
@@ -221,10 +243,21 @@ Some classes stay put because of how bestax renders them:
221
243
  instead of as its own class.
222
244
  - `is-hidden` becomes `visibility="hidden"`, which renders the same class and doesn't interact
223
245
  with `display`.
246
+ - `is-marginless` and `is-paddingless` are the only classes a conversion changes: they style
247
+ nothing under v1, so they become the prop of the v1 helper that does their job. A live class
248
+ for the same prop keeps it, whichever is written first, so beside `p-2` the class stays with a
249
+ `legacy:` TODO, and so it does wherever the element stays markup. Beside a class for another
250
+ prop, such as `px-2`, it still converts: v1 puts every side and axis class after `p-0`, so
251
+ `px-2` keeps its sides.
224
252
 
225
253
  ## Classes that stay classes
226
254
 
227
- Color shades (`has-text-primary-65`), the `-touch` and `-only` breakpoints of text size and
228
- alignment, Grid and `.image` modifiers away from their own element, an `.image` ratio, and the
229
- Bulma helpers bestax has no prop for (`is-display-*`, `is-visibility-*`, `is-float-*`,
230
- `is-clear-*`, …) stay in `className`. They render exactly as before.
255
+ A color shade one color and one shade can't write (`has-text-primary-100`, the `-invert` of a
256
+ shade such as `has-text-primary-30-invert`, a shade of the `text` color), a shade or color for a
257
+ prop another class already wrote (`has-text-primary-30 has-text-info-40` keeps the second), the
258
+ palettes and `is-bold` and `is-soft`, the `-touch` and `-only` breakpoints of text size and
259
+ alignment, Grid and `.image` modifiers away from their own element, v1's `marginless` and
260
+ `paddingless` (the rules of `m-0` and `p-0` under other names), and the Bulma helpers bestax has
261
+ no prop for (`is-display-*`, `is-visibility-*`, `is-float-*`, `is-clear-*`, …) stay in
262
+ `className`. They render exactly as before. An `.image` size or ratio away from its `.image` also
263
+ gets a `modifier:image` TODO, since Bulma styles it only there.