create-bestax 4.2.19 → 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.
- package/README.md +13 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +65 -0
- package/dist/project-creator.d.ts +8 -0
- package/dist/project-creator.d.ts.map +1 -1
- package/dist/project-creator.js +58 -2
- package/dist/prompts.d.ts +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +15 -1
- package/package.json +3 -3
- package/templates/skills/bestax-custom-component/references/component-catalog.md +3 -1
- package/templates/skills/bestax-icons/references/icon-libraries.md +14 -1
- package/templates/skills/bestax-layout-scaffold/SKILL.md +15 -0
- package/templates/skills/bestax-migrate/SKILL.md +10 -4
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +1 -1
- package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +4 -1
- package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +49 -15
- package/templates/skills/bestax-migrate/references/bulma-classes/prop-map.md +4 -2
- package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +166 -30
- package/templates/skills/bestax-migrate/references/rbx/prop-map.md +1 -1
- package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +2 -2
- package/templates/skills/bestax-optimize/references/modular-build.md +3 -1
- package/templates/skills/bestax-theming/SKILL.md +13 -10
- package/templates/skills/bestax-theming/examples/dark-mode.tsx +7 -6
- package/templates/skills/bestax-theming/examples/theme-config.tsx +10 -3
- package/templates/skills/bestax-theming/references/css-variables.md +89 -11
- package/templates/skills/bestax-theming/references/themeable-components.md +2 -0
- package/templates/vite/README.md +2 -2
- package/templates/vite/_oxlintrc.json +8 -0
- package/templates/vite/package.json +8 -12
- package/templates/vite/vite.config.js +1 -1
- package/templates/vite-ts/README.md +2 -2
- package/templates/vite-ts/_oxlintrc.json +8 -0
- package/templates/vite-ts/package.json +10 -15
- package/templates/vite/eslint.config.js +0 -29
- package/templates/vite-ts/eslint.config.js +0 -26
package/README.md
CHANGED
|
@@ -44,9 +44,10 @@ You'll be asked to:
|
|
|
44
44
|
1. Enter a project name or path (and, if that directory already holds files, confirm removing
|
|
45
45
|
them; nothing is removed until you have answered the last question)
|
|
46
46
|
2. Select a framework (Vite or Vite + TypeScript)
|
|
47
|
-
3. Choose a
|
|
48
|
-
4.
|
|
49
|
-
5.
|
|
47
|
+
3. Choose a linter (Oxlint or ESLint)
|
|
48
|
+
4. Choose a Bulma CSS flavor (the `--bulma` options below)
|
|
49
|
+
5. Select an icon library (Font Awesome, Material Icons, etc.)
|
|
50
|
+
6. Choose whether to install the bestax AI skills into `.claude/skills/`
|
|
50
51
|
|
|
51
52
|
Every prompt has a flag equivalent, so the whole flow is scriptable and CI-friendly — see the options below.
|
|
52
53
|
|
|
@@ -73,6 +74,11 @@ with or without it.
|
|
|
73
74
|
|
|
74
75
|
- `-t, --template <template>` - Template to use: `vite` or `vite-ts`
|
|
75
76
|
**Default:** `vite`
|
|
77
|
+
- `--lint <linter>` - Linter:
|
|
78
|
+
- `oxlint` - Oxlint, as `npm create vite` sets up. `vite-ts` gets TypeScript 7.
|
|
79
|
+
- `eslint` - ESLint with typescript-eslint, as `npm create vite -- --eslint` sets up.
|
|
80
|
+
typescript-eslint doesn't support TypeScript 7 yet, so `vite-ts` stays on TypeScript 6.
|
|
81
|
+
**Default:** `oxlint`, which a run without a terminal also gets when it leaves `--lint` out
|
|
76
82
|
- `-b, --bulma <flavor>` - Bulma CSS flavor:
|
|
77
83
|
- `complete` - Full Bulma CSS with all components and helpers
|
|
78
84
|
- `prefixed` - Prefixed version for compatibility
|
|
@@ -94,6 +100,7 @@ with or without it.
|
|
|
94
100
|
- `-y, --yes` - Skip prompts and use defaults or provided options.
|
|
95
101
|
When used, the following defaults are selected unless overridden by flags:
|
|
96
102
|
- Template: `vite`
|
|
103
|
+
- Linter: `oxlint`
|
|
97
104
|
- Bulma flavor: `complete`
|
|
98
105
|
- Icon library: `none`
|
|
99
106
|
- AI skills: installed (pass `--no-skills` to opt out)
|
|
@@ -112,6 +119,9 @@ with or without it.
|
|
|
112
119
|
# Create a TypeScript project with Font Awesome icons
|
|
113
120
|
npm create bestax@latest my-app -- -t vite-ts -i fontawesome -b complete
|
|
114
121
|
|
|
122
|
+
# The same, linted with ESLint (and on TypeScript 6)
|
|
123
|
+
npm create bestax@latest my-app -- -t vite-ts -i fontawesome --lint eslint
|
|
124
|
+
|
|
115
125
|
# Use all defaults (skip prompts)
|
|
116
126
|
npm create bestax@latest my-app -- -y
|
|
117
127
|
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EACL,cAAc,EACd,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1E,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,IAAI,cAAc,EAChC,iBAAiB,IAAI,iBAAiB,EACtC,iBAAiB,IAAI,iBAAiB,GACvC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,wBAAsB,cAAc,CAClC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CAGhC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAcD,wBAAgB,SAAS,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EACL,cAAc,EACd,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1E,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,IAAI,cAAc,EAChC,iBAAiB,IAAI,iBAAiB,EACtC,iBAAiB,IAAI,iBAAiB,GACvC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,wBAAsB,cAAc,CAClC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CAGhC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAcD,wBAAgB,SAAS,IAAI,OAAO,CA0CnC;AAED,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAKxE;AAED,wBAAsB,MAAM,CAC1B,IAAI,GAAE,SAAS,MAAM,EAAiB,GACrC,OAAO,CAAC,IAAI,CAAC,CAGf"}
|
package/dist/cli.js
CHANGED
|
@@ -55,6 +55,7 @@ export function createCLI() {
|
|
|
55
55
|
.version(getPackageVersion())
|
|
56
56
|
.argument('[project-directory]', 'project directory to create, a name or a path (its last part names the package)')
|
|
57
57
|
.option('-t, --template <template>', 'template to use (vite, vite-ts)')
|
|
58
|
+
.option('--lint <linter>', 'linter (oxlint, eslint)')
|
|
58
59
|
.option('-b, --bulma <flavor>', 'Bulma CSS flavor (complete, prefixed, no-helpers, no-helpers-prefixed, no-dark-mode)')
|
|
59
60
|
.option('-i, --icon <library>', 'icon library (none, fontawesome, mdi, ionicons, material-icons, material-symbols)')
|
|
60
61
|
.option('--skills', 'install the bestax AI skills into .claude/skills')
|
package/dist/constants.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export declare const LAUNCH_JSON: string;
|
|
|
40
40
|
export declare const PROMPTS: {
|
|
41
41
|
readonly PROJECT_NAME: "Project name:";
|
|
42
42
|
readonly SELECT_FRAMEWORK: "Select a framework:";
|
|
43
|
+
readonly SELECT_LINTER: "Which linter would you like to use?";
|
|
43
44
|
readonly SELECT_ICON_LIBRARY: "Would you like to add an icon library?";
|
|
44
45
|
readonly SELECT_BULMA_FLAVOR: "Which Bulma CSS flavor would you like to use?";
|
|
45
46
|
readonly INSTALL_SKILLS: "Install the bestax AI skills (.claude/skills) for Claude Code and other agents?";
|
|
@@ -71,6 +72,17 @@ export interface BulmaFlavor {
|
|
|
71
72
|
noHelpers?: boolean;
|
|
72
73
|
}
|
|
73
74
|
export declare const BULMA_FLAVORS: BulmaFlavor[];
|
|
75
|
+
export interface Linter {
|
|
76
|
+
name: string;
|
|
77
|
+
display: string;
|
|
78
|
+
description: string;
|
|
79
|
+
color: typeof chalk.yellow;
|
|
80
|
+
}
|
|
81
|
+
export declare const LINTERS: Linter[];
|
|
82
|
+
export declare const ESLINT_DEV_DEPENDENCIES: Record<string, string>;
|
|
83
|
+
export declare const ESLINT_TYPESCRIPT_DEV_DEPENDENCIES: Record<string, string>;
|
|
84
|
+
/** The eslint.config.js create-vite's `--eslint` writes. */
|
|
85
|
+
export declare const ESLINT_CONFIG: (typescript: boolean) => string;
|
|
74
86
|
export declare const CSS_ORDER_COMMENT: string;
|
|
75
87
|
export interface StarterClass {
|
|
76
88
|
prop: string;
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,EAAE,QAAQ,EAG/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAsB,CAAC;AAGtD,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAOpC,eAAO,MAAM,QAAQ;;;;;;+CASe,MAAM,QAAQ,MAAM;6CAEtB,MAAM;;;wCAQX,MAAM,WAAW,MAAM,EAAE;oCAE7B,MAAM;wCAIF,MAAM;gDAKE,MAAM,WAAW,MAAM,EAAE;uCAIlC,MAAM;sCACP,MAAM;4CAEA,MAAM;;;;;wCAMV,MAAM,mBAAmB,MAAM;;;;;CAclD,CAAC;AASX,eAAO,MAAM,WAAW,QAed,CAAC;AAEX,eAAO,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,EAAE,QAAQ,EAG/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAsB,CAAC;AAGtD,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAOpC,eAAO,MAAM,QAAQ;;;;;;+CASe,MAAM,QAAQ,MAAM;6CAEtB,MAAM;;;wCAQX,MAAM,WAAW,MAAM,EAAE;oCAE7B,MAAM;wCAIF,MAAM;gDAKE,MAAM,WAAW,MAAM,EAAE;uCAIlC,MAAM;sCACP,MAAM;4CAEA,MAAM;;;;;wCAMV,MAAM,mBAAmB,MAAM;;;;;CAclD,CAAC;AASX,eAAO,MAAM,WAAW,QAed,CAAC;AAEX,eAAO,MAAM,OAAO;;;;;;;;CASV,CAAC;AAOX,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK9D,CAAC;AAKF,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAkCD,eAAO,MAAM,SAAS,GACpB,aAAa,MAAM,EACnB,8BAA8B,eAAe,KAC5C,MA8HF,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,cAAc,EAAE,WAAW,EA8DvC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IAGtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EA8CtC,CAAC;AAEF,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;CAC5B;AAKD,eAAO,MAAM,OAAO,EAAE,MAAM,EAe3B,CAAC;AAIF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM1D,CAAC;AAKF,eAAO,MAAM,kCAAkC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGrE,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,aAAa,GAAI,YAAY,OAAO,KAAG,MA8BtC,CAAC;AAQf,eAAO,MAAM,iBAAiB,QAEiC,CAAC;AAEhE,MAAM,WAAW,YAAY;IAE3B,IAAI,EAAE,MAAM,CAAC;IAEb,SAAS,EAAE,MAAM,CAAC;IAElB,WAAW,EAAE,MAAM,CAAC;CACrB;AAOD,eAAO,MAAM,0BAA0B,EAAE,YAAY,EAgBpD,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAMjB,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -76,6 +76,7 @@ export const LAUNCH_JSON = JSON.stringify({
|
|
|
76
76
|
export const PROMPTS = {
|
|
77
77
|
PROJECT_NAME: 'Project name:',
|
|
78
78
|
SELECT_FRAMEWORK: 'Select a framework:',
|
|
79
|
+
SELECT_LINTER: 'Which linter would you like to use?',
|
|
79
80
|
SELECT_ICON_LIBRARY: 'Would you like to add an icon library?',
|
|
80
81
|
SELECT_BULMA_FLAVOR: 'Which Bulma CSS flavor would you like to use?',
|
|
81
82
|
INSTALL_SKILLS: 'Install the bestax AI skills (.claude/skills) for Claude Code and other agents?',
|
|
@@ -345,6 +346,70 @@ export const BULMA_FLAVORS = [
|
|
|
345
346
|
importStatement: "import '@allxsmith/bestax-bulma/versions/bestax-no-dark-mode.css';",
|
|
346
347
|
},
|
|
347
348
|
];
|
|
349
|
+
// The templates ship create-vite's default lint setup, Oxlint, and the
|
|
350
|
+
// scaffolder writes create-vite's `--eslint` setup in its place for ESLint
|
|
351
|
+
// (ProjectCreator.setupLinter).
|
|
352
|
+
export const LINTERS = [
|
|
353
|
+
{
|
|
354
|
+
name: 'oxlint',
|
|
355
|
+
display: 'Oxlint (Recommended)',
|
|
356
|
+
description: "create-vite's default, and TypeScript 7 for Vite + TypeScript",
|
|
357
|
+
color: chalk.green,
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: 'eslint',
|
|
361
|
+
display: 'ESLint',
|
|
362
|
+
description: 'with typescript-eslint, which keeps Vite + TypeScript on TypeScript 6',
|
|
363
|
+
color: chalk.blue,
|
|
364
|
+
},
|
|
365
|
+
];
|
|
366
|
+
// The packages create-vite's `--eslint` puts in place of oxlint. When
|
|
367
|
+
// create-vite moves them, these follow (create-bestax/CLAUDE.md).
|
|
368
|
+
export const ESLINT_DEV_DEPENDENCIES = {
|
|
369
|
+
'@eslint/js': '^10.0.1',
|
|
370
|
+
eslint: '^10.13.0',
|
|
371
|
+
'eslint-plugin-react-hooks': '^7.1.1',
|
|
372
|
+
'eslint-plugin-react-refresh': '^0.5.7',
|
|
373
|
+
globals: '^17.13.0',
|
|
374
|
+
};
|
|
375
|
+
// What `--eslint` adds for a TypeScript app. typescript-eslint loads
|
|
376
|
+
// TypeScript's compiler API, which TypeScript 7.0 doesn't ship, and accepts
|
|
377
|
+
// TypeScript below 6.1 only, so the app stays on TypeScript 6 (#394).
|
|
378
|
+
export const ESLINT_TYPESCRIPT_DEV_DEPENDENCIES = {
|
|
379
|
+
typescript: '~6.0.3',
|
|
380
|
+
'typescript-eslint': '^8.72.0',
|
|
381
|
+
};
|
|
382
|
+
/** The eslint.config.js create-vite's `--eslint` writes. */
|
|
383
|
+
export const ESLINT_CONFIG = (typescript) => [
|
|
384
|
+
"import js from '@eslint/js';",
|
|
385
|
+
"import globals from 'globals';",
|
|
386
|
+
"import reactHooks from 'eslint-plugin-react-hooks';",
|
|
387
|
+
"import reactRefresh from 'eslint-plugin-react-refresh';",
|
|
388
|
+
...(typescript ? ["import tseslint from 'typescript-eslint';"] : []),
|
|
389
|
+
"import { defineConfig, globalIgnores } from 'eslint/config';",
|
|
390
|
+
'',
|
|
391
|
+
'export default defineConfig([',
|
|
392
|
+
" globalIgnores(['dist']),",
|
|
393
|
+
' {',
|
|
394
|
+
typescript
|
|
395
|
+
? " files: ['**/*.{ts,tsx}'],"
|
|
396
|
+
: " files: ['**/*.{js,jsx}'],",
|
|
397
|
+
' extends: [',
|
|
398
|
+
' js.configs.recommended,',
|
|
399
|
+
...(typescript ? [' tseslint.configs.recommended,'] : []),
|
|
400
|
+
' reactHooks.configs.flat.recommended,',
|
|
401
|
+
' reactRefresh.configs.vite,',
|
|
402
|
+
' ],',
|
|
403
|
+
' languageOptions: {',
|
|
404
|
+
' globals: globals.browser,',
|
|
405
|
+
...(typescript
|
|
406
|
+
? []
|
|
407
|
+
: [' parserOptions: { ecmaFeatures: { jsx: true } },']),
|
|
408
|
+
' },',
|
|
409
|
+
' },',
|
|
410
|
+
']);',
|
|
411
|
+
'',
|
|
412
|
+
].join('\n');
|
|
348
413
|
// Sits above the stylesheet import in the templates' entry files, and the
|
|
349
414
|
// scaffolder writes it back when it swaps in a flavor's stylesheet, so the
|
|
350
415
|
// reason for the import order survives. The no-helpers classes depend on it.
|
|
@@ -8,6 +8,7 @@ export interface ProjectConfig {
|
|
|
8
8
|
}
|
|
9
9
|
export interface CLIOptions {
|
|
10
10
|
template?: string;
|
|
11
|
+
lint?: string;
|
|
11
12
|
bulma?: string;
|
|
12
13
|
icon?: string;
|
|
13
14
|
skills?: boolean;
|
|
@@ -64,6 +65,13 @@ export declare class ProjectCreator {
|
|
|
64
65
|
* user picked, if any.
|
|
65
66
|
*/
|
|
66
67
|
updateReadme(targetPath: string, iconLibrary: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* The templates ship create-vite's default lint setup, Oxlint. For ESLint,
|
|
70
|
+
* write what create-vite's `--eslint` writes in its place: the config, the
|
|
71
|
+
* packages and the lint script, and for TypeScript, TypeScript 6, since
|
|
72
|
+
* typescript-eslint can't load TypeScript 7 (#394).
|
|
73
|
+
*/
|
|
74
|
+
setupLinter(targetPath: string, linter: string, template: string): Promise<void>;
|
|
67
75
|
setupSkills(targetPath: string, projectName: string, options: ClaudeMdOptions): Promise<void>;
|
|
68
76
|
setupBulmaFlavor(targetPath: string, bulmaFlavor: string, template: string): Promise<void>;
|
|
69
77
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-creator.d.ts","sourceRoot":"","sources":["../src/project-creator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"project-creator.d.ts","sourceRoot":"","sources":["../src/project-creator.ts"],"names":[],"mappings":"AAgCA,OAAO,EAeL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAexB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC;AAEnE,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,CAAC,EAAE,MAAM;IAIjC;;;OAGG;IACG,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAajE;;;;;;;;;;OAUG;IACG,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,qBAAqB,CAAC;IAqCjC;;;;;;OAMG;YACW,qBAAqB;IAanC;;;OAGG;IACH,eAAe,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI;IAwBpD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAInC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,oBAAoB,CACxB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAgBhB;;;;;OAKG;IACG,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E;;;;;OAKG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmCV,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC;IAqBV,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAyDhB;;;;;OAKG;IACG,yBAAyB,CAC7B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmBhB,OAAO,CAAC,WAAW;IA2BnB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAcd,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAsJV,mBAAmB,CACvB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmEV,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA4JtE;;;;;;;;OAQG;YACW,eAAe;CA2B9B"}
|
package/dist/project-creator.js
CHANGED
|
@@ -3,19 +3,21 @@ import { fileURLToPath } from 'url';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import fs from 'fs-extra';
|
|
5
5
|
import { checkDirectoryExists, listDirectoryEntries, findNonDirectoryInPath, realPath, emptyDirectory, ensureDirectory, copyDirectory, updatePackageJson, } from './file-system.js';
|
|
6
|
-
import { promptProjectName, promptOverwriteDirectory, promptTemplate, promptIconLibrary, promptBulmaFlavor, promptInstallSkills, promptTelemetryConsent, } from './prompts.js';
|
|
6
|
+
import { promptProjectName, promptOverwriteDirectory, promptTemplate, promptLinter, promptIconLibrary, promptBulmaFlavor, promptInstallSkills, promptTelemetryConsent, } from './prompts.js';
|
|
7
7
|
import { reportScaffold } from './telemetry.js';
|
|
8
8
|
import { displayHeader, displaySuccess, displayError, displayCancelled, } from './display.js';
|
|
9
9
|
import { validateProjectDirectory, toValidPackageName } from './validators.js';
|
|
10
|
-
import { MESSAGES, TEMPLATES, ICON_LIBRARIES, BULMA_FLAVORS, CLAUDE_MD, LAUNCH_JSON, CONFIG_PROVIDER_ICON_VALUES, NO_HELPERS_STARTER_CLASSES, NO_HELPERS_APP_CSS, CSS_ORDER_COMMENT, } from './constants.js';
|
|
10
|
+
import { MESSAGES, TEMPLATES, ICON_LIBRARIES, BULMA_FLAVORS, LINTERS, ESLINT_CONFIG, ESLINT_DEV_DEPENDENCIES, ESLINT_TYPESCRIPT_DEV_DEPENDENCIES, CLAUDE_MD, LAUNCH_JSON, CONFIG_PROVIDER_ICON_VALUES, NO_HELPERS_STARTER_CLASSES, NO_HELPERS_APP_CSS, CSS_ORDER_COMMENT, } from './constants.js';
|
|
11
11
|
import { detectPackageManager } from './package-manager.js';
|
|
12
12
|
import { LIBRARY, libraryRange } from './library-range.js';
|
|
13
13
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
14
|
// npm strips literal `.gitignore` files from published tarballs, so the
|
|
15
15
|
// templates track `_gitignore` instead and the scaffolder renames it back
|
|
16
16
|
// on copy — otherwise published scaffolds would ship with no .gitignore.
|
|
17
|
+
// The Oxlint config follows create-vite, which names it the same way.
|
|
17
18
|
const TEMPLATE_RENAMES = {
|
|
18
19
|
_gitignore: '.gitignore',
|
|
20
|
+
'_oxlintrc.json': '.oxlintrc.json',
|
|
19
21
|
};
|
|
20
22
|
export class ProjectCreator {
|
|
21
23
|
templatesDir;
|
|
@@ -98,6 +100,10 @@ export class ProjectCreator {
|
|
|
98
100
|
if (options?.template && !validTemplates.includes(options.template)) {
|
|
99
101
|
return `Invalid template: ${options.template}. Valid options are: ${validTemplates.join(', ')}`;
|
|
100
102
|
}
|
|
103
|
+
const validLinters = LINTERS.map(l => l.name);
|
|
104
|
+
if (options?.lint && !validLinters.includes(options.lint)) {
|
|
105
|
+
return `Invalid linter: ${options.lint}. Valid options are: ${validLinters.join(', ')}`;
|
|
106
|
+
}
|
|
101
107
|
const validFlavors = BULMA_FLAVORS.map(f => f.name);
|
|
102
108
|
if (options?.bulma && !validFlavors.includes(options.bulma)) {
|
|
103
109
|
return `Invalid Bulma flavor: ${options.bulma}. Valid options are: ${validFlavors.join(', ')}`;
|
|
@@ -147,6 +153,37 @@ export class ProjectCreator {
|
|
|
147
153
|
}
|
|
148
154
|
await fs.writeFile(readmePath, readme);
|
|
149
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* The templates ship create-vite's default lint setup, Oxlint. For ESLint,
|
|
158
|
+
* write what create-vite's `--eslint` writes in its place: the config, the
|
|
159
|
+
* packages and the lint script, and for TypeScript, TypeScript 6, since
|
|
160
|
+
* typescript-eslint can't load TypeScript 7 (#394).
|
|
161
|
+
*/
|
|
162
|
+
async setupLinter(targetPath, linter, template) {
|
|
163
|
+
if (linter !== 'eslint')
|
|
164
|
+
return;
|
|
165
|
+
const isTypeScript = template.includes('-ts');
|
|
166
|
+
await fs.remove(path.join(targetPath, '.oxlintrc.json'));
|
|
167
|
+
await fs.writeFile(path.join(targetPath, 'eslint.config.js'), ESLINT_CONFIG(isTypeScript));
|
|
168
|
+
const packageJsonPath = path.join(targetPath, 'package.json');
|
|
169
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
170
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
171
|
+
const devDependencies = {
|
|
172
|
+
...packageJson.devDependencies,
|
|
173
|
+
...ESLINT_DEV_DEPENDENCIES,
|
|
174
|
+
...(isTypeScript ? ESLINT_TYPESCRIPT_DEV_DEPENDENCIES : {}),
|
|
175
|
+
};
|
|
176
|
+
delete devDependencies.oxlint;
|
|
177
|
+
packageJson.devDependencies = Object.fromEntries(Object.entries(devDependencies).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
|
|
178
|
+
packageJson.scripts = { ...packageJson.scripts, lint: 'eslint .' };
|
|
179
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
180
|
+
}
|
|
181
|
+
const readmePath = path.join(targetPath, 'README.md');
|
|
182
|
+
if (fs.existsSync(readmePath)) {
|
|
183
|
+
const readme = await fs.readFile(readmePath, 'utf8');
|
|
184
|
+
await fs.writeFile(readmePath, readme.replace(/\bOxlint\b/g, 'ESLint'));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
150
187
|
async setupSkills(targetPath, projectName, options) {
|
|
151
188
|
const skillsSrc = path.join(this.templatesDir, 'skills');
|
|
152
189
|
if (!(await checkDirectoryExists(skillsSrc))) {
|
|
@@ -466,6 +503,24 @@ export class ProjectCreator {
|
|
|
466
503
|
process.exit(1);
|
|
467
504
|
}
|
|
468
505
|
}
|
|
506
|
+
// Select linter (use option or prompt). The question is newer than the
|
|
507
|
+
// others, so a run without a terminal that answers every other one by
|
|
508
|
+
// flag takes the default here rather than stopping, as it did before the
|
|
509
|
+
// question existed (#192).
|
|
510
|
+
let linter;
|
|
511
|
+
if (options?.lint) {
|
|
512
|
+
linter = options.lint;
|
|
513
|
+
}
|
|
514
|
+
else if (options?.yes || !process.stdin.isTTY) {
|
|
515
|
+
linter = 'oxlint'; // default linter
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
linter = await promptLinter();
|
|
519
|
+
if (linter === null) {
|
|
520
|
+
displayCancelled();
|
|
521
|
+
process.exit(1);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
469
524
|
// Select Bulma flavor (use option or prompt)
|
|
470
525
|
let bulmaFlavor;
|
|
471
526
|
if (options?.bulma) {
|
|
@@ -532,6 +587,7 @@ export class ProjectCreator {
|
|
|
532
587
|
await this.setupBulmaFlavor(targetPath, bulmaFlavor, template);
|
|
533
588
|
await this.setupIconLibrary(targetPath, iconLibrary, template);
|
|
534
589
|
await this.setupConfigProvider(targetPath, bulmaFlavor, iconLibrary, template);
|
|
590
|
+
await this.setupLinter(targetPath, linter, template);
|
|
535
591
|
if (installSkills) {
|
|
536
592
|
await this.setupSkills(targetPath, projectName, {
|
|
537
593
|
bulmaFlavor,
|
package/dist/prompts.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare function promptOverwriteDirectory(targetDir: string, entries: str
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function promptInstallSkills(): Promise<boolean | null>;
|
|
10
10
|
export declare function promptTemplate(): Promise<string | null>;
|
|
11
|
+
export declare function promptLinter(): Promise<string | null>;
|
|
11
12
|
export declare function promptIconLibrary(): Promise<string | null>;
|
|
12
13
|
/**
|
|
13
14
|
* Consent for anonymous usage telemetry. Deliberately does NOT call
|
package/dist/prompts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AA0BA,0EAA0E;AAC1E,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWhE;AAED,sFAAsF;AACtF,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAUnE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAa7D;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc3D;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAchE;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA2BtE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBhE"}
|
package/dist/prompts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import prompts from 'prompts';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { TEMPLATES, DEFAULT_PROJECT_NAME, PROMPTS as PROMPT_MESSAGES, MESSAGES, ICON_LIBRARIES, BULMA_FLAVORS, } from './constants.js';
|
|
3
|
+
import { TEMPLATES, DEFAULT_PROJECT_NAME, PROMPTS as PROMPT_MESSAGES, MESSAGES, ICON_LIBRARIES, BULMA_FLAVORS, LINTERS, } from './constants.js';
|
|
4
4
|
import { validateProjectDirectory } from './validators.js';
|
|
5
5
|
import { displayError } from './display.js';
|
|
6
6
|
/**
|
|
@@ -64,6 +64,20 @@ export async function promptTemplate() {
|
|
|
64
64
|
});
|
|
65
65
|
return response.template || null;
|
|
66
66
|
}
|
|
67
|
+
export async function promptLinter() {
|
|
68
|
+
ensureInteractive();
|
|
69
|
+
const response = await prompts({
|
|
70
|
+
type: 'select',
|
|
71
|
+
name: 'linter',
|
|
72
|
+
message: PROMPT_MESSAGES.SELECT_LINTER,
|
|
73
|
+
choices: LINTERS.map(linter => ({
|
|
74
|
+
title: linter.color(`${linter.display} - ${linter.description}`),
|
|
75
|
+
value: linter.name,
|
|
76
|
+
})),
|
|
77
|
+
initial: 0, // Default to 'oxlint'
|
|
78
|
+
});
|
|
79
|
+
return response.linter || null;
|
|
80
|
+
}
|
|
67
81
|
export async function promptIconLibrary() {
|
|
68
82
|
ensureInteractive();
|
|
69
83
|
const response = await prompts({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bestax",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "Create a new bestax-bulma project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"prompts": "^2.4.2",
|
|
42
42
|
"react": "^18.0.0 || ^19.0.0",
|
|
43
43
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
44
|
-
"@allxsmith/bestax-bulma": "^5.
|
|
44
|
+
"@allxsmith/bestax-bulma": "^5.49.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@jest/globals": "^30.0.0",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"clean": "rimraf dist",
|
|
79
79
|
"release": "npx semantic-release"
|
|
80
80
|
},
|
|
81
|
-
"readme": "# create-bestax\n\n[](https://www.npmjs.com/package/create-bestax)\n[](https://www.npmjs.com/package/create-bestax)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/create-bestax/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/create-bestax#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nThe scaffolder for [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — spin up a Vite app pre-wired for the **Bulma v1** React component library in one command. Picks your framework (JS or TypeScript), CSS flavor, and icon library, and can drop in the bestax **AI skills** so an agent like Claude Code knows the library from the first prompt.\n\nPart of the [bestax monorepo](https://github.com/allxsmith/bestax) — see also [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) for the components themselves.\n\n## Requirements\n\n- **Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the\n CLI exits immediately with an explicit upgrade message.\n- npm 10 or newer (ships with Node 22), or yarn/pnpm.\n\n## Usage\n\n### Quick Start\n\n```bash\n# Using npm\nnpm create bestax@latest my-app\n\n# Using npx\nnpx create-bestax@latest my-app\n```\n\n### Interactive Mode\n\nRunning without arguments will prompt you for all options:\n\n```bash\nnpm create bestax@latest\n```\n\nYou'll be asked to:\n\n1. Enter a project name or path (and, if that directory already holds files, confirm removing\n them; nothing is removed until you have answered the last question)\n2. Select a framework (Vite or Vite + TypeScript)\n3. Choose a Bulma CSS flavor (the `--bulma` options below)\n4. Select an icon library (Font Awesome, Material Icons, etc.)\n5. Choose whether to install the bestax AI skills into `.claude/skills/`\n\nEvery prompt has a flag equivalent, so the whole flow is scriptable and CI-friendly — see the options below.\n\n### Command Line Options\n\n```bash\nnpm create bestax@latest [project-directory] -- [options]\n```\n\nPut the options after `--`. npm needs it to pass them on at all, and so does bun, whose\n`bun create` rejects short flags such as `-t` and `-y` itself. pnpm and Yarn 1 accept the options\nwith or without it.\n\n**Arguments:**\n\n- `[project-directory]` - Optional project directory: a name such as `my-app`, or a path,\n absolute or relative, such as `../apps/my-app`, whose missing folders are created. Its last\n part is the project name, held to the same rules as a bare name. It becomes the page title as\n typed, and the `package.json` name lower-cased the way `npm init` does and without a leading\n `_`, since npm rejects both. A path ending in `.` or `..` is refused, like a bare `.` or `..`,\n so name the directory you want.\n\n**Options:**\n\n- `-t, --template <template>` - Template to use: `vite` or `vite-ts` \n **Default:** `vite`\n- `-b, --bulma <flavor>` - Bulma CSS flavor:\n - `complete` - Full Bulma CSS with all components and helpers\n - `prefixed` - Prefixed version for compatibility\n - `no-helpers` - Without helper classes\n - `no-helpers-prefixed` - Prefixed without helpers\n - `no-dark-mode` - Without dark mode support \n **Default:** `complete`\n- `-i, --icon <library>` - Icon library:\n - `none` - No icon library\n - `fontawesome` - Font Awesome\n - `mdi` - Material Design Icons\n - `ionicons` - Ionicons\n - `material-icons` - Material Icons\n - `material-symbols` - Material Symbols \n **Default:** `none`\n- `--skills` / `--no-skills` - Install (or skip) the bestax AI skills into\n `.claude/skills/` (with a `CLAUDE.md`) so a Claude Code session picks them up\n automatically. When omitted you're prompted; with `-y` the default is to install.\n- `-y, --yes` - Skip prompts and use defaults or provided options. \n When used, the following defaults are selected unless overridden by flags:\n - Template: `vite`\n - Bulma flavor: `complete`\n - Icon library: `none`\n - AI skills: installed (pass `--no-skills` to opt out)\n\n `-y` never deletes files. If the target directory is not empty, the run stops, lists what is\n there, and changes nothing; add `--overwrite` to empty it first. Earlier versions emptied the\n directory under `-y` alone, so a script that relied on that now needs `--overwrite`.\n\n- `--overwrite` - Remove existing files if the target directory is not empty, without asking.\n Every other flag is checked first, so a typo stops the run before anything is deleted. It\n never empties the current directory or a folder that holds it, however the path is written.\n\n**Example:**\n\n```bash\n# Create a TypeScript project with Font Awesome icons\nnpm create bestax@latest my-app -- -t vite-ts -i fontawesome -b complete\n\n# Use all defaults (skip prompts)\nnpm create bestax@latest my-app -- -y\n\n# Scaffold into a path; the package is named my-app\nnpm create bestax@latest ../apps/my-app -- -y\n\n# The same with bun\nbun create bestax@latest my-app -- -y\n```\n\n## Templates\n\nAvailable templates:\n\n- `vite` - Vite + JavaScript\n- `vite-ts` - Vite + TypeScript\n\nEach template includes:\n\n- Pre-configured bestax-bulma integration (React 19)\n- The latest `@allxsmith/bestax-bulma`, which ships Bulma v1 automatically\n- Icon library support (Font Awesome, Material Design, etc.)\n- Sample components demonstrating library usage\n- Development and build scripts\n\n## For AI Tools\n\nScaffolding for an AI agent? Pass `--skills` (or accept the prompt) to drop the bestax\nAgent Skills and a `CLAUDE.md` into the new project so Claude Code, Cursor, or Copilot\nbuild the bestax way from the start. The library also ships LLM-optimized docs:\n\n- [LLMs guide](https://bestax.io/docs/guides/llms) — using bestax with Claude Code, Cursor, Copilot\n- [Agent Skills](https://bestax.io/docs/skills/intro) — teach your agent the bestax conventions\n- [llms.txt](https://bestax.io/llms.txt) (curated index) · [llms-full.txt](https://bestax.io/llms-full.txt) (full docs)\n\n## Development\n\n```bash\nnpm run build # Build the CLI\nnpm run dev # Watch mode\nnpm test # Run tests\nnpm run lint # Lint CLI source code\nnpm run typecheck # Type check CLI source code\n```\n\n**Note on Templates:** Template files in `templates/` are excluded from linting. They should be manually validated by scaffolding a test project and running lint/build there before releasing.\n\n## Hardened by default\n\nA scaffolder runs with write access to your filesystem and picks your starting dependencies, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/create-bestax#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, so a compromised action release can't roll silently into a build of this CLI.\n- **CodeQL, Dependency Review, and Dependabot** run continuously, alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`create-bestax` can send one **anonymous** usage event after a successful\nscaffold — only if you opt in when asked (once, at the end of a scaffold). The\nevent is just the choices you made — template, Bulma flavor, icon library,\nskills, package manager — plus the CLI version, Node major version, and OS\nplatform; never names, IPs, machine IDs, paths, or file contents, and no\nidentifier exists that could link two events together. Opt out any time with\n`--no-telemetry`, `BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## Publishing\n\nThis package uses semantic-release with scope-based rules. Only commits with `feat(create-bestax)` or `fix(create-bestax)` will trigger releases.\n"
|
|
81
|
+
"readme": "# create-bestax\n\n[](https://www.npmjs.com/package/create-bestax)\n[](https://www.npmjs.com/package/create-bestax)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/create-bestax/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/create-bestax#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nThe scaffolder for [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — spin up a Vite app pre-wired for the **Bulma v1** React component library in one command. Picks your framework (JS or TypeScript), CSS flavor, and icon library, and can drop in the bestax **AI skills** so an agent like Claude Code knows the library from the first prompt.\n\nPart of the [bestax monorepo](https://github.com/allxsmith/bestax) — see also [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) for the components themselves.\n\n## Requirements\n\n- **Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the\n CLI exits immediately with an explicit upgrade message.\n- npm 10 or newer (ships with Node 22), or yarn/pnpm.\n\n## Usage\n\n### Quick Start\n\n```bash\n# Using npm\nnpm create bestax@latest my-app\n\n# Using npx\nnpx create-bestax@latest my-app\n```\n\n### Interactive Mode\n\nRunning without arguments will prompt you for all options:\n\n```bash\nnpm create bestax@latest\n```\n\nYou'll be asked to:\n\n1. Enter a project name or path (and, if that directory already holds files, confirm removing\n them; nothing is removed until you have answered the last question)\n2. Select a framework (Vite or Vite + TypeScript)\n3. Choose a linter (Oxlint or ESLint)\n4. Choose a Bulma CSS flavor (the `--bulma` options below)\n5. Select an icon library (Font Awesome, Material Icons, etc.)\n6. Choose whether to install the bestax AI skills into `.claude/skills/`\n\nEvery prompt has a flag equivalent, so the whole flow is scriptable and CI-friendly — see the options below.\n\n### Command Line Options\n\n```bash\nnpm create bestax@latest [project-directory] -- [options]\n```\n\nPut the options after `--`. npm needs it to pass them on at all, and so does bun, whose\n`bun create` rejects short flags such as `-t` and `-y` itself. pnpm and Yarn 1 accept the options\nwith or without it.\n\n**Arguments:**\n\n- `[project-directory]` - Optional project directory: a name such as `my-app`, or a path,\n absolute or relative, such as `../apps/my-app`, whose missing folders are created. Its last\n part is the project name, held to the same rules as a bare name. It becomes the page title as\n typed, and the `package.json` name lower-cased the way `npm init` does and without a leading\n `_`, since npm rejects both. A path ending in `.` or `..` is refused, like a bare `.` or `..`,\n so name the directory you want.\n\n**Options:**\n\n- `-t, --template <template>` - Template to use: `vite` or `vite-ts` \n **Default:** `vite`\n- `--lint <linter>` - Linter:\n - `oxlint` - Oxlint, as `npm create vite` sets up. `vite-ts` gets TypeScript 7.\n - `eslint` - ESLint with typescript-eslint, as `npm create vite -- --eslint` sets up.\n typescript-eslint doesn't support TypeScript 7 yet, so `vite-ts` stays on TypeScript 6. \n **Default:** `oxlint`, which a run without a terminal also gets when it leaves `--lint` out\n- `-b, --bulma <flavor>` - Bulma CSS flavor:\n - `complete` - Full Bulma CSS with all components and helpers\n - `prefixed` - Prefixed version for compatibility\n - `no-helpers` - Without helper classes\n - `no-helpers-prefixed` - Prefixed without helpers\n - `no-dark-mode` - Without dark mode support \n **Default:** `complete`\n- `-i, --icon <library>` - Icon library:\n - `none` - No icon library\n - `fontawesome` - Font Awesome\n - `mdi` - Material Design Icons\n - `ionicons` - Ionicons\n - `material-icons` - Material Icons\n - `material-symbols` - Material Symbols \n **Default:** `none`\n- `--skills` / `--no-skills` - Install (or skip) the bestax AI skills into\n `.claude/skills/` (with a `CLAUDE.md`) so a Claude Code session picks them up\n automatically. When omitted you're prompted; with `-y` the default is to install.\n- `-y, --yes` - Skip prompts and use defaults or provided options. \n When used, the following defaults are selected unless overridden by flags:\n - Template: `vite`\n - Linter: `oxlint`\n - Bulma flavor: `complete`\n - Icon library: `none`\n - AI skills: installed (pass `--no-skills` to opt out)\n\n `-y` never deletes files. If the target directory is not empty, the run stops, lists what is\n there, and changes nothing; add `--overwrite` to empty it first. Earlier versions emptied the\n directory under `-y` alone, so a script that relied on that now needs `--overwrite`.\n\n- `--overwrite` - Remove existing files if the target directory is not empty, without asking.\n Every other flag is checked first, so a typo stops the run before anything is deleted. It\n never empties the current directory or a folder that holds it, however the path is written.\n\n**Example:**\n\n```bash\n# Create a TypeScript project with Font Awesome icons\nnpm create bestax@latest my-app -- -t vite-ts -i fontawesome -b complete\n\n# The same, linted with ESLint (and on TypeScript 6)\nnpm create bestax@latest my-app -- -t vite-ts -i fontawesome --lint eslint\n\n# Use all defaults (skip prompts)\nnpm create bestax@latest my-app -- -y\n\n# Scaffold into a path; the package is named my-app\nnpm create bestax@latest ../apps/my-app -- -y\n\n# The same with bun\nbun create bestax@latest my-app -- -y\n```\n\n## Templates\n\nAvailable templates:\n\n- `vite` - Vite + JavaScript\n- `vite-ts` - Vite + TypeScript\n\nEach template includes:\n\n- Pre-configured bestax-bulma integration (React 19)\n- The latest `@allxsmith/bestax-bulma`, which ships Bulma v1 automatically\n- Icon library support (Font Awesome, Material Design, etc.)\n- Sample components demonstrating library usage\n- Development and build scripts\n\n## For AI Tools\n\nScaffolding for an AI agent? Pass `--skills` (or accept the prompt) to drop the bestax\nAgent Skills and a `CLAUDE.md` into the new project so Claude Code, Cursor, or Copilot\nbuild the bestax way from the start. The library also ships LLM-optimized docs:\n\n- [LLMs guide](https://bestax.io/docs/guides/llms) — using bestax with Claude Code, Cursor, Copilot\n- [Agent Skills](https://bestax.io/docs/skills/intro) — teach your agent the bestax conventions\n- [llms.txt](https://bestax.io/llms.txt) (curated index) · [llms-full.txt](https://bestax.io/llms-full.txt) (full docs)\n\n## Development\n\n```bash\nnpm run build # Build the CLI\nnpm run dev # Watch mode\nnpm test # Run tests\nnpm run lint # Lint CLI source code\nnpm run typecheck # Type check CLI source code\n```\n\n**Note on Templates:** Template files in `templates/` are excluded from linting. They should be manually validated by scaffolding a test project and running lint/build there before releasing.\n\n## Hardened by default\n\nA scaffolder runs with write access to your filesystem and picks your starting dependencies, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/create-bestax#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, so a compromised action release can't roll silently into a build of this CLI.\n- **CodeQL, Dependency Review, and Dependabot** run continuously, alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`create-bestax` can send one **anonymous** usage event after a successful\nscaffold — only if you opt in when asked (once, at the end of a scaffold). The\nevent is just the choices you made — template, Bulma flavor, icon library,\nskills, package manager — plus the CLI version, Node major version, and OS\nplatform; never names, IPs, machine IDs, paths, or file contents, and no\nidentifier exists that could link two events together. Opt out any time with\n`--no-telemetry`, `BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## Publishing\n\nThis package uses semantic-release with scope-based rules. Only commits with `feat(create-bestax)` or `fix(create-bestax)` will trigger releases.\n"
|
|
82
82
|
}
|
|
@@ -37,7 +37,7 @@ instead of hand-writing markup.
|
|
|
37
37
|
- Raw `*Base` form exports (`InputBase`, `SelectBase`, `TextAreaBase`, …) are
|
|
38
38
|
escape-hatch variants of the convenience wrappers above them; see the Form docs.
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
106 documented components. Generated from the API docs — every exported
|
|
41
41
|
component is guaranteed to appear (the generator fails if one lacks an API page).
|
|
42
42
|
|
|
43
43
|
## Elements
|
|
@@ -100,6 +100,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
100
100
|
- [Panel](https://bestax.io/docs/api/components/panel) — The `Panel` component implements Bulma's versatile panel block for React.
|
|
101
101
|
- [Popover](https://bestax.io/docs/api/components/popover) — The `Popover` component opens a panel of interactive content, such as a filter form or a set of share options, anchored to the element that toggles it.
|
|
102
102
|
- [Reveal](https://bestax.io/docs/api/components/reveal) — The `Reveal` component animates its content into view as it scrolls into the viewport, backed by `IntersectionObserver`.
|
|
103
|
+
- [ScrollArea](https://bestax.io/docs/api/components/scrollarea) — The `ScrollArea` component renders a box whose content scrolls inside it, on the browser's own scrollbars in Bulma's colors.
|
|
103
104
|
- [SegmentedControl](https://bestax.io/docs/api/components/segmentedcontrol) — The `SegmentedControl` component renders a row of buttons where only one can be on, and tells a screen reader it's a radio group.
|
|
104
105
|
- [Sidebar](https://bestax.io/docs/api/components/sidebar) — The `Sidebar` component provides a slide-out navigation panel that appears from the left or right side of the screen.
|
|
105
106
|
- [Steps](https://bestax.io/docs/api/components/steps) — The `Steps` component provides a multi-step progress indicator for wizard flows, checkout processes, or any multi-step workflow.
|
|
@@ -152,6 +153,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
152
153
|
- [Level](https://bestax.io/docs/api/layout/level) — The `Level` component provides a flexible horizontal layout for your Bulma React UI, perfect for aligning items on the left and right…
|
|
153
154
|
- [Media](https://bestax.io/docs/api/layout/media) — The `Media` component implements Bulma’s powerful media object layout for React.
|
|
154
155
|
- [Section](https://bestax.io/docs/api/layout/section) — The `Section` component provides vertical spacing and visual separation for your Bulma React UI.
|
|
156
|
+
- [Splitter](https://bestax.io/docs/api/layout/splitter) — The `Splitter` component lays out two or more panes side by side or one above the other, with a handle between each pair to drag or move by keyboard.
|
|
155
157
|
|
|
156
158
|
## Helpers
|
|
157
159
|
|
|
@@ -26,9 +26,22 @@ Set it once on `ConfigProvider` and omit `library` everywhere else.
|
|
|
26
26
|
- **Variants** (`variant` → class): `solid` → `fas` (default), `regular` → `far`, `brands` →
|
|
27
27
|
`fab`, `light` → `fal`, `duotone` → `fad`, `thin` → `fat`. The free package includes only
|
|
28
28
|
solid, regular (partial), and brands — light/duotone/thin need a Font Awesome Pro kit.
|
|
29
|
+
Font Awesome 6's long class names (`fa-solid`, `fa-brands`, …) are the same styles, so write
|
|
30
|
+
them as these variants. Font Awesome 4's `fa` is `variant="fa"`, which `Icon` writes as given:
|
|
31
|
+
4 reads nothing else, and 5 and later read it as solid.
|
|
29
32
|
- **Features:** Font Awesome utility classes — `'fa-lg'`, `'fa-2x'`…`'fa-10x'`, `'fa-spin'`,
|
|
30
33
|
`'fa-pulse'`, `'fa-border'`, `'fa-fw'`, `'fa-flip-horizontal'`, `'fa-rotate-90'`.
|
|
31
34
|
- Brand icons **require** `variant="brands"`: `<Icon name="github" variant="brands" />`.
|
|
35
|
+
- **Older names:** 6 and 7 still read most of 5's names, many since renamed (`search` is
|
|
36
|
+
`magnifying-glass` now), and 4's through the v4 shims (`css/v4-shims.min.css`). Two kinds
|
|
37
|
+
draw something else:
|
|
38
|
+
- **4's brand glyphs under `fa`** (`fa fa-github`): 5 moved brands to a style of their own,
|
|
39
|
+
so without the shims they show a missing-glyph box. Write `variant="brands"`, and the
|
|
40
|
+
current name where 5 renamed one (4's `facebook` is `facebook-f`, `linkedin` is
|
|
41
|
+
`linkedin-in`, `youtube-play` is `youtube`).
|
|
42
|
+
- **5's handsets:** 6 turned them round. 5's `phone` and `phone-square` draw as 6's
|
|
43
|
+
`phone-flip` and `square-phone-flip`, and 5's `phone-alt` and `phone-square-alt` as `phone`
|
|
44
|
+
and `square-phone`, so write those names to keep a 5 page's look.
|
|
32
45
|
|
|
33
46
|
## Material Design Icons — `'mdi'`
|
|
34
47
|
|
|
@@ -140,7 +153,7 @@ Docs: https://bestax.io/docs/guides/getting-started/alternative-icons#making-the
|
|
|
140
153
|
3. **The library's CSS/script is actually loaded** — the import in `main.tsx` (or the
|
|
141
154
|
Ionicons script in `index.html`) must exist; bestax ships none of them.
|
|
142
155
|
4. **Variant availability** — Font Awesome free has no `light`/`duotone`/`thin`; brand
|
|
143
|
-
glyphs need `variant="brands"
|
|
156
|
+
glyphs need `variant="brands"`, an old Font Awesome 4 one under `fa` included.
|
|
144
157
|
|
|
145
158
|
## IconText
|
|
146
159
|
|
|
@@ -122,6 +122,21 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
|
|
|
122
122
|
`defaultOpen` on the group holding the current page (or `open`/`onOpenChange` to hold the state).
|
|
123
123
|
Its heading is a real button with `aria-expanded`, and its links stay links, each a tab stop.
|
|
124
124
|
Not `TreeView`, and not a `Collapse` inside a hand-written `<li>`.
|
|
125
|
+
- **Panes the user resizes are `Splitter`** (a file tree beside an editor, a list beside its
|
|
126
|
+
detail, a query above its results), not hand-written drag code or fixed `Columns`:
|
|
127
|
+
`<Splitter height={480}>` with a `<Splitter.Pane label="Files" defaultSize={25} minSize="12rem">`
|
|
128
|
+
per pane. The handles go in on their own, each named by its pane's `label`, so give every pane
|
|
129
|
+
one. Sizes are percentages, limits also take `px` or `rem`, `orientation="vertical"` stacks
|
|
130
|
+
them (and needs a `height`), and `collapsible` with `collapsed`/`onCollapsedChange` lets a
|
|
131
|
+
button hide a pane. Put scrolling content in a `ScrollArea` inside the pane.
|
|
132
|
+
- **Content taller or wider than its space is `ScrollArea`** (release notes in a Card, a sidebar
|
|
133
|
+
longer than the screen, a feed that grows then scrolls, a wide table on a phone), not a `Box`
|
|
134
|
+
with `overflowY="auto"` and a height in a style: `<ScrollArea height={240} aria-label="…">`,
|
|
135
|
+
or `maxHeight="20rem"` to grow with its content first. It needs `aria-label` or
|
|
136
|
+
`aria-labelledby`, since while it overflows it's a region a keyboard user tabs to. The
|
|
137
|
+
helper props and `className` go on its frame and the `ref` on the element that scrolls.
|
|
138
|
+
`hasFade` fades the edges that have more, `orientation="horizontal"` suits a wide table, and
|
|
139
|
+
`onEdgeReach={edge => …}` loads more at an edge.
|
|
125
140
|
- Link lists (footer nav, sidebars): a bare `UnorderedList` of `ListItem`s is already
|
|
126
141
|
marker-less and flush — Bulma's reset unstyles `ul` — so no prop or CSS is needed;
|
|
127
142
|
bullets appear only inside `Content`.
|
|
@@ -52,7 +52,8 @@ Run these steps in order. Don't hand-convert what the codemod converts automatic
|
|
|
52
52
|
Each page becomes a module beside it (`index.tsx`, or `.jsx` when the package isn't
|
|
53
53
|
TypeScript) whose default export is `<Name>Page`, named from the file (its folder's for an
|
|
54
54
|
`index.html`). The page stays as it was, and the codemod never writes over a module that's
|
|
55
|
-
already there, so a re-run writes nothing
|
|
55
|
+
already there, so a re-run on the page writes nothing: after fixing a TODO, re-run on the
|
|
56
|
+
module, which is what each TODO says. Its head, its `<html>` and `<body>` attributes and
|
|
56
57
|
its scripts become `html-*` TODOs: put the app-wide parts in the app's `index.html` and
|
|
57
58
|
entry, and port each script's work into the component. Under `--css bestax` or `--css bulma`
|
|
58
59
|
the module imports the stylesheet in place of the page's Bulma `<link>`.
|
|
@@ -136,9 +137,13 @@ code per the references, or deliberately keep the old markup with `className` st
|
|
|
136
137
|
drift than the 0.9 → 1 guide alone describes.
|
|
137
138
|
- **bulma-classes**: there is no library to remove. An element converts only when the bestax
|
|
138
139
|
component renders the same markup (tag, classes, attributes), so a converted page renders
|
|
139
|
-
the same HTML, but for deliberate exceptions
|
|
140
|
+
the same HTML, but for deliberate exceptions. Font Awesome's own hidden `<i>` in a `.icon`
|
|
140
141
|
that carries nothing else assistive tech reads becomes `Icon`, which hides the `.icon`
|
|
141
|
-
instead, the glyph hidden either way,
|
|
142
|
+
instead, the glyph hidden either way. Such a `.icon` around a bare glyph, in a link or button
|
|
143
|
+
its own `aria-label` names, becomes `Icon` too, which hides it, since the label is what a
|
|
144
|
+
screen reader reads there. Font Awesome 6's long style names (`fa-brands`) become the
|
|
145
|
+
`bestax-icons` skill's `variant` (`brands`), which renders the short name (`fab`), the same
|
|
146
|
+
style. And Bulma 0.9's `is-marginless` and `is-paddingless`,
|
|
142
147
|
which style nothing under v1, become `m="0"` and `p="0"`. Everything else stays as written, with a
|
|
143
148
|
TODO when there is something to decide. Static class strings convert, and so does a `clsx` or
|
|
144
149
|
`classnames` call of strings and conditional classes, where a condition on a flag becomes
|
|
@@ -164,7 +169,8 @@ code per the references, or deliberately keep the old markup with `className` st
|
|
|
164
169
|
|
|
165
170
|
- The codemod is safe to re-run after partial manual work: a library source only touches files
|
|
166
171
|
that still import the library, and `bulma-classes` skips elements that are already
|
|
167
|
-
components
|
|
172
|
+
components, never repeats a TODO it already wrote, and drops one that asked for a re-run once
|
|
173
|
+
it no longer applies.
|
|
168
174
|
- Don't downgrade converted props back to the old names; bestax uses `is*` booleans
|
|
169
175
|
(`isLoading`), string size unions (`textSize="4"`), and `as` rather than `renderAs`.
|
|
170
176
|
- If a component the app uses isn't in the component map, it wasn't part of that library's
|
|
@@ -192,7 +192,7 @@ value is flagged. The same conversion covers the modifiers bestax has no prop fo
|
|
|
192
192
|
bloomer forwarded no refs. bestax forwards a ref from the form controls, plus `Avatar`, `Button`,
|
|
193
193
|
`Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `EmptyState`, `Kbd`, `Kbd.Group`, `Link`,
|
|
194
194
|
`LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`,
|
|
195
|
-
`Navbar.Item`, `Navbar.Link`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Timeline`,
|
|
195
|
+
`Navbar.Item`, `Navbar.Link`, `ScrollArea`, `SegmentedControl`, `SegmentedControl.Segment`, `Sidebar`, `Splitter`, `Splitter.Pane`, `Timeline`,
|
|
196
196
|
`Timeline.Item`, `Toast`, `ToggleButton`, `TreeView` and `TreeView.Item` — pass `ref` directly on
|
|
197
197
|
those. "The form controls" means the inputs themselves: the `Field`, `Field.Label`, `Field.Body`,
|
|
198
198
|
`Checkboxes` and `Radios` wrappers around them forward nothing.
|
|
@@ -62,10 +62,13 @@ and `isSize={n}` becomes a column span:
|
|
|
62
62
|
bloomer's `Modal` was an inert shell: `isActive` toggled the class and nothing else. bestax's
|
|
63
63
|
`Modal` closes on Escape (calling `onClose`), locks body scroll, and traps focus **by default**,
|
|
64
64
|
and renders inline unless `portal` is set. So every conversion changes behaviour, and every one
|
|
65
|
-
is flagged. Pass `onClose`
|
|
65
|
+
is flagged. Pass `onClose` for Escape and `Modal.Close` to close it. `Modal.Background` doesn't
|
|
66
|
+
call `onClose` on its own, so give it the same handler as `onClick` for the background to close
|
|
67
|
+
it too:
|
|
66
68
|
|
|
67
69
|
```jsx
|
|
68
70
|
<Modal active={open} onClose={() => setOpen(false)}>
|
|
71
|
+
<Modal.Background onClick={() => setOpen(false)} />
|
|
69
72
|
```
|
|
70
73
|
|
|
71
74
|
or keep bloomer's inert behaviour with `closeOnEscape={false} lockScroll={false}`. Add
|