create-bestax 4.0.2 → 4.1.1

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 (31) hide show
  1. package/LICENSE +21 -0
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.js +3 -1
  4. package/dist/display.d.ts.map +1 -1
  5. package/dist/display.js +6 -2
  6. package/dist/file-system.d.ts +1 -1
  7. package/dist/file-system.d.ts.map +1 -1
  8. package/dist/file-system.js +11 -1
  9. package/dist/index.js +0 -0
  10. package/dist/package-manager.d.ts +5 -0
  11. package/dist/package-manager.d.ts.map +1 -0
  12. package/dist/package-manager.js +9 -0
  13. package/dist/project-creator.d.ts.map +1 -1
  14. package/dist/project-creator.js +7 -1
  15. package/package.json +23 -24
  16. package/templates/skills/bestax-custom-component/SKILL.md +4 -3
  17. package/templates/skills/bestax-custom-component/references/api.md +28 -9
  18. package/templates/skills/bestax-custom-component/references/component-catalog.md +3 -3
  19. package/templates/skills/bestax-form/SKILL.md +7 -2
  20. package/templates/skills/bestax-form/references/api.md +1 -1
  21. package/templates/skills/bestax-layout-scaffold/SKILL.md +12 -8
  22. package/templates/skills/bestax-layout-scaffold/examples/centered.tsx +1 -1
  23. package/templates/skills/bestax-layout-scaffold/references/archetypes.md +5 -2
  24. package/templates/skills/bestax-layout-scaffold/references/layout-components.md +17 -3
  25. package/templates/skills/bestax-migrate/references/prop-map.md +1 -1
  26. package/templates/skills/bestax-theming/SKILL.md +7 -3
  27. package/templates/skills/bestax-theming/references/css-variables.md +8 -7
  28. package/templates/skills/bestax-theming/references/themeable-components.md +3 -3
  29. package/templates/vite/_gitignore +25 -0
  30. package/templates/vite-ts/_gitignore +25 -0
  31. package/templates/vite-ts/tsconfig.json +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Alex Smith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -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;AAEtD,eAAO,MAAM,QAAQ;;;;;;;wCAaQ,MAAM;uCAEP,MAAM;sCACP,MAAM;4CAEA,MAAM;;;;;CAM7B,CAAC;AASX,eAAO,MAAM,WAAW,QAed,CAAC;AAEX,eAAO,MAAM,OAAO;;;;;;CAOV,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;AAED,eAAO,MAAM,SAAS,GACpB,aAAa,MAAM,EACnB,8BAA8B,eAAe,KAC5C,MAkIF,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;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,cAAc,EAAE,WAAW,EA6CvC,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;CACvB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EA4CtC,CAAC"}
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;AAEtD,eAAO,MAAM,QAAQ;;;;;;;wCAaQ,MAAM;uCAEP,MAAM;sCACP,MAAM;4CAEA,MAAM;;;;;CAM7B,CAAC;AASX,eAAO,MAAM,WAAW,QAed,CAAC;AAEX,eAAO,MAAM,OAAO;;;;;;CAOV,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;AAED,eAAO,MAAM,SAAS,GACpB,aAAa,MAAM,EACnB,8BAA8B,eAAe,KAC5C,MAoIF,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;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,cAAc,EAAE,WAAW,EA6CvC,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;CACvB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EA4CtC,CAAC"}
package/dist/constants.js CHANGED
@@ -179,7 +179,9 @@ Read skill \`references/\` files with absolute paths — the shell's cwd is not
179
179
 
180
180
  \`.claude/launch.json\` declares this app's dev server for Claude Code's browser preview
181
181
  (\`npm run dev\` on port 5173, \`--strictPort\`) — start it from there rather than rediscovering
182
- the command.
182
+ the command. \`--strictPort\` failing because 5173 is busy means an orphaned dev server from an
183
+ earlier session owns the port — kill the listener (\`lsof -tiTCP:5173 -sTCP:LISTEN | xargs kill\`)
184
+ and relaunch; don't move the app to another port.
183
185
 
184
186
  ## Docs
185
187
 
@@ -1 +1 @@
1
- {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAIA,wBAAgB,aAAa,IAAI,IAAI,CAMpC;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAwBtD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,IAAI,IAAI,CAMpC;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CA2BtD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
package/dist/display.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import figures from 'figures';
3
3
  import { MESSAGES } from './constants.js';
4
+ import { detectPackageManager } from './package-manager.js';
4
5
  export function displayHeader() {
5
6
  console.log();
6
7
  console.log(chalk.cyan('━'.repeat(50)));
@@ -14,9 +15,12 @@ export function displaySuccess(targetDir) {
14
15
  console.log();
15
16
  console.log(chalk.bold(MESSAGES.NEXT_STEPS));
16
17
  console.log();
18
+ // Mirror the package manager that invoked the CLI — `<pm> install` and
19
+ // `<pm> run dev` are valid for all four supported PMs.
20
+ const pm = detectPackageManager();
17
21
  console.log(chalk.cyan(` cd ${targetDir}`));
18
- console.log(chalk.cyan(' pnpm install'));
19
- console.log(chalk.cyan(' pnpm dev'));
22
+ console.log(chalk.cyan(` ${pm} install`));
23
+ console.log(chalk.cyan(` ${pm} run dev`));
20
24
  console.log();
21
25
  console.log(chalk.gray(' Your app includes a beautiful logo-centric homepage'));
22
26
  console.log(chalk.gray(' showcasing Bestax, Vite, and React branding.'));
@@ -2,7 +2,7 @@ export declare function checkDirectoryExists(targetPath: string): Promise<boolea
2
2
  export declare function isDirectoryEmpty(targetPath: string): Promise<boolean>;
3
3
  export declare function emptyDirectory(targetPath: string): Promise<void>;
4
4
  export declare function ensureDirectory(targetPath: string): Promise<void>;
5
- export declare function copyDirectory(source: string, destination: string): Promise<void>;
5
+ export declare function copyDirectory(source: string, destination: string, renames?: Record<string, string>): Promise<void>;
6
6
  export declare function readJsonFile<T = unknown>(filePath: string): Promise<T>;
7
7
  export declare function writeJsonFile(filePath: string, data: unknown, spaces?: number): Promise<void>;
8
8
  export declare function updatePackageJson(targetPath: string, projectName: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"AAIA,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAM3E;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE5E;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,MAAM,SAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAQf"}
1
+ {"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../src/file-system.ts"],"names":[],"mappings":"AAIA,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAM3E;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAef;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE5E;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,MAAM,SAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAQf"}
@@ -17,11 +17,21 @@ export async function emptyDirectory(targetPath) {
17
17
  export async function ensureDirectory(targetPath) {
18
18
  await fs.ensureDir(targetPath);
19
19
  }
20
- export async function copyDirectory(source, destination) {
20
+ export async function copyDirectory(source, destination, renames) {
21
21
  if (!(await checkDirectoryExists(source))) {
22
22
  throw new Error(MESSAGES.TEMPLATE_NOT_FOUND(source));
23
23
  }
24
24
  await fs.copy(source, destination);
25
+ if (renames) {
26
+ for (const [from, to] of Object.entries(renames)) {
27
+ const copiedPath = path.join(destination, from);
28
+ if (fs.existsSync(copiedPath)) {
29
+ await fs.move(copiedPath, path.join(destination, to), {
30
+ overwrite: true,
31
+ });
32
+ }
33
+ }
34
+ }
25
35
  }
26
36
  export async function readJsonFile(filePath) {
27
37
  return fs.readJson(filePath);
package/dist/index.js CHANGED
File without changes
@@ -0,0 +1,5 @@
1
+ export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
2
+ /** Detect the package manager that invoked the CLI from npm_config_user_agent
3
+ * (e.g. "pnpm/9.12.0 npm/? node/v22 darwin arm64"). Falls back to npm. */
4
+ export declare function detectPackageManager(userAgent?: string | undefined): PackageManager;
5
+ //# sourceMappingURL=package-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../src/package-manager.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAI7D;2EAC2E;AAC3E,wBAAgB,oBAAoB,CAClC,SAAS,GAAE,MAAM,GAAG,SAA6C,GAChE,cAAc,CAKhB"}
@@ -0,0 +1,9 @@
1
+ const KNOWN = ['npm', 'pnpm', 'yarn', 'bun'];
2
+ /** Detect the package manager that invoked the CLI from npm_config_user_agent
3
+ * (e.g. "pnpm/9.12.0 npm/? node/v22 darwin arm64"). Falls back to npm. */
4
+ export function detectPackageManager(userAgent = process.env.npm_config_user_agent) {
5
+ const name = userAgent?.split('/')[0] ?? '';
6
+ return KNOWN.includes(name)
7
+ ? name
8
+ : 'npm';
9
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"project-creator.d.ts","sourceRoot":"","sources":["../src/project-creator.ts"],"names":[],"mappings":"AA2BA,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,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,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,CAAC,EAAE,MAAM;IAI3B,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa3D,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IAkBnB,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;IAgBV,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;IAmDhB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,YAAY;IAYd,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAgJV,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;CAyIvE"}
1
+ {"version":3,"file":"project-creator.d.ts","sourceRoot":"","sources":["../src/project-creator.ts"],"names":[],"mappings":"AA2BA,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAWxB,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,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,CAAC,EAAE,MAAM;IAI3B,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa3D,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IAkBnB,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;IAgBV,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;IAmDhB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,YAAY;IAYd,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAgJV,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;CAyIvE"}
@@ -8,6 +8,12 @@ import { displayHeader, displaySuccess, displayError, displayCancelled, } from '
8
8
  import { validateProjectName } from './validators.js';
9
9
  import { MESSAGES, ICON_LIBRARIES, BULMA_FLAVORS, CLAUDE_MD, LAUNCH_JSON, CONFIG_PROVIDER_ICON_VALUES, } from './constants.js';
10
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ // npm strips literal `.gitignore` files from published tarballs, so the
12
+ // templates track `_gitignore` instead and the scaffolder renames it back
13
+ // on copy — otherwise published scaffolds would ship with no .gitignore.
14
+ const TEMPLATE_RENAMES = {
15
+ _gitignore: '.gitignore',
16
+ };
11
17
  export class ProjectCreator {
12
18
  templatesDir;
13
19
  constructor(templatesDir) {
@@ -43,7 +49,7 @@ export class ProjectCreator {
43
49
  async copyTemplate(template, targetPath) {
44
50
  const templatePath = this.getTemplatePath(template);
45
51
  await ensureDirectory(targetPath);
46
- await copyDirectory(templatePath, targetPath);
52
+ await copyDirectory(templatePath, targetPath, TEMPLATE_RENAMES);
47
53
  }
48
54
  async updateIndexHtmlTitle(targetPath, projectName) {
49
55
  const indexHtmlPath = path.join(targetPath, 'index.html');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bestax",
3
- "version": "4.0.2",
3
+ "version": "4.1.1",
4
4
  "description": "Create a new bestax-bulma project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,25 +10,6 @@
10
10
  "dist",
11
11
  "templates"
12
12
  ],
13
- "scripts": {
14
- "build": "node scripts/sync-skills.mjs && tsc",
15
- "prepack": "node scripts/sync-skills.mjs",
16
- "dev": "tsc --watch",
17
- "test": "NODE_OPTIONS=\"--experimental-vm-modules\" jest",
18
- "test:watch": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --watch",
19
- "test:coverage": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage",
20
- "test:e2e": "playwright test --config=e2e/playwright.config.ts",
21
- "test:e2e:ui": "playwright test --config=e2e/playwright.config.ts --ui",
22
- "test:e2e:headed": "playwright test --config=e2e/playwright.config.ts --headed",
23
- "test:e2e:update": "playwright test --config=e2e/playwright.config.ts --update-snapshots",
24
- "test:e2e:report": "playwright show-report e2e/playwright-report",
25
- "lint": "eslint src e2e/tests e2e/utils",
26
- "typecheck": "tsc --noEmit",
27
- "format": "prettier --write \"src/**/*.{ts,tsx}\"",
28
- "format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
29
- "clean": "rimraf dist",
30
- "release": "npx semantic-release"
31
- },
32
13
  "keywords": [
33
14
  "bestax",
34
15
  "bulma",
@@ -73,7 +54,25 @@
73
54
  "wait-on": "^9.1.0"
74
55
  },
75
56
  "publishConfig": {
76
- "access": "public",
77
- "provenance": true
78
- }
79
- }
57
+ "access": "public"
58
+ },
59
+ "scripts": {
60
+ "build": "node scripts/sync-skills.mjs && tsc",
61
+ "dev": "tsc --watch",
62
+ "test": "NODE_OPTIONS=\"--experimental-vm-modules\" jest",
63
+ "test:watch": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --watch",
64
+ "test:coverage": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage",
65
+ "test:e2e": "playwright test --config=e2e/playwright.config.ts",
66
+ "test:e2e:ui": "playwright test --config=e2e/playwright.config.ts --ui",
67
+ "test:e2e:headed": "playwright test --config=e2e/playwright.config.ts --headed",
68
+ "test:e2e:update": "playwright test --config=e2e/playwright.config.ts --update-snapshots",
69
+ "test:e2e:report": "playwright show-report e2e/playwright-report",
70
+ "lint": "eslint src e2e/tests e2e/utils",
71
+ "typecheck": "tsc --noEmit",
72
+ "format": "prettier --write \"src/**/*.{ts,tsx}\"",
73
+ "format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
74
+ "clean": "rimraf dist",
75
+ "release": "npx semantic-release"
76
+ },
77
+ "readme": "# create-bestax\n\n[![npm version](https://img.shields.io/npm/v/create-bestax.svg)](https://www.npmjs.com/package/create-bestax)\n[![npm downloads](https://img.shields.io/npm/dm/create-bestax.svg)](https://www.npmjs.com/package/create-bestax)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Socket Badge](https://socket.dev/api/badge/npm/package/create-bestax)](https://socket.dev/npm/package/create-bestax/overview)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/allxsmith/bestax/badge)](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[![npm provenance](https://img.shields.io/badge/npm-provenance-3fb950.svg)](https://www.npmjs.com/package/create-bestax#provenance)\n[![Security policy](https://img.shields.io/badge/security-policy-blue.svg)](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# Alternative naming\nnpm create bestax-bulma@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\n2. Select a framework (Vite or Vite + TypeScript)\n3. Choose a Bulma CSS flavor (Complete or Minimal)\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\n**Arguments:**\n\n- `[project-directory]` - Optional project directory name\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**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\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## 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"
78
+ }
@@ -50,11 +50,12 @@ label — use that instead"_ or _"No `ProfileCard` exists; I'll build one compos
50
50
 
51
51
  Build from existing components before writing any CSS: `Box`, `Card`, `Title`, `SubTitle`,
52
52
  `Icon`, `Block`, `Content`, `Tag`, plus the shared Bulma helper props (spacing, color,
53
- typography, flexbox). Compound sub-parts are the exception — `Card.Content`, `Modal.Card`,
54
- `Tabs.Tab`, `Message.Body` take **no Bulma helper props**, just `className` + HTML attributes
53
+ typography, flexbox). Some compound sub-parts are the exception — `Modal.Card`, `Tabs.Tab`,
54
+ `Message.Body` take **no Bulma helper props**, just `className` + HTML attributes
55
55
  plus their own few (`Tabs.Tab` requires `index={i}` and has built-in `disabled` and
56
56
  `icon`/`iconLibrary`/`iconVariant`/`iconSize`/`iconFeatures` — don't nest an `<Icon>` there) —
57
- so put helper props on the parent or on an element inside them, never invent them there. Most "custom components" are a composition function — zero new styles.
57
+ so put helper props on the parent or on an element inside them, never invent them there.
58
+ (`Card.*` sub-parts do take helper props, like `Table.*`/`Menu.*`/`Hero.*`.) Most "custom components" are a composition function — zero new styles.
58
59
  See `examples/stat-card.tsx` for a complete worked example.
59
60
 
60
61
  ## The component spine
@@ -12,11 +12,23 @@ Everything below is public API. Where to import from depends on your context:
12
12
  Turns Bulma helper props into a class string and returns the leftover (non-helper) props.
13
13
 
14
14
  ```ts
15
- const { bulmaHelperClasses, rest } = useBulmaClasses(props);
15
+ const { bulmaHelperClasses, bulmaHelperStyles, rest } = useBulmaClasses(props);
16
16
  // bulmaHelperClasses: e.g. 'has-text-primary is-size-3 m-3'
17
- // rest: every prop that was NOT a recognized helper (safe to spread on the DOM)
17
+ // bulmaHelperStyles: inline styles for scheme-aware values, or undefined (see below)
18
+ // rest: every prop that was NOT a recognized helper; destructure your own
19
+ // component props and `style` before spreading it on a DOM element
18
20
  ```
19
21
 
22
+ `bulmaHelperStyles` is `undefined` unless `backgroundColor` is one of the six
23
+ `validSchemeColors` values (`scheme-main`, `scheme-main-bis`, `scheme-main-ter`,
24
+ `scheme-invert`, `scheme-invert-bis`, `scheme-invert-ter`). Bulma ships no
25
+ `has-background-scheme-*` classes, so those values emit no class; the hook returns
26
+ `{ backgroundColor: 'var(--bulma-<value>)' }` instead — a dark-mode-safe inline style. Put it
27
+ on the root element with `mergeBulmaStyles(bulmaHelperStyles, style)`
28
+ (`helpers/mergeBulmaStyles.ts`): the user's `style` prop wins on conflicts, and the result is
29
+ `undefined` when both are absent so unaffected components keep an attribute-free DOM.
30
+ (`useColorStyles` is the underlying per-concern hook.)
31
+
20
32
  `BulmaClassesProps` is the union of all helper prop groups, composed from per-concern hooks
21
33
  that can also be used on their own:
22
34
 
@@ -31,9 +43,10 @@ that can also be used on their own:
31
43
 
32
44
  Because the component destructures these into `bulmaHelperClasses`, callers get the full Bulma
33
45
  helper surface for free on every component built this way, and `rest` stays clean for DOM
34
- spreading. (Library compound sub-parts — `Card.Content`, `Modal.Card`, `Tabs.Tab`,
46
+ spreading. (Some library compound sub-parts — `Modal.Card`, `Tabs.Tab`,
35
47
  `Message.Body` — do **not** take helper props: just `className`, HTML attributes, and their own
36
- few, e.g. `Tabs.Tab`'s required `index` and its built-in `icon`/`disabled` props.)
48
+ few, e.g. `Tabs.Tab`'s required `index` and its built-in `icon`/`disabled` props. `Card.*`
49
+ sub-parts do take them.)
37
50
 
38
51
  ## `classNames(...)` and friends — `helpers/classNames.ts`
39
52
 
@@ -55,16 +68,22 @@ de-dupes. Related exports:
55
68
  Re-exported through `useBulmaClasses`. Use them to type component-specific props and to drive
56
69
  Storybook `argTypes`/tests:
57
70
 
58
- `validColors`, `validColorShades`, `validSizes`, `validTextSizes`, `validAlignments`,
59
- `validTextTransforms`, `validTextWeights`, `validFontFamilies`, `validDisplays`,
60
- `validVisibilities`, `validFlexDirections`, `validFlexWraps`, `validJustifyContents`,
61
- `validAlignContents`, `validAlignItems`, `validAlignSelfs`, `validFlexGrowShrink`,
62
- `validViewports`.
71
+ `validColors`, `validColorShades`, `validSchemeColors`, `validSizes`, `validTextSizes`,
72
+ `validAlignments`, `validTextTransforms`, `validTextWeights`, `validFontFamilies`,
73
+ `validDisplays`, `validVisibilities`, `validFlexDirections`, `validFlexWraps`,
74
+ `validJustifyContents`, `validAlignContents`, `validAlignItems`, `validAlignSelfs`,
75
+ `validFlexGrowShrink`, `validViewports`.
63
76
 
64
77
  ```ts
65
78
  export type MyColor = (typeof validColors)[number];
66
79
  ```
67
80
 
81
+ `validSchemeColors` is the scheme-background tuple consumed by `bulmaHelperStyles` (above).
82
+ Components that support scheme backgrounds widen their own `bgColor` union with
83
+ `(typeof validSchemeColors)[number]` — the widening is deliberate and per-component, so a
84
+ component that has not wired `bulmaHelperStyles` onto its root element must keep the narrow
85
+ union (a compile error beats a silent no-op).
86
+
68
87
  ## `ConfigProvider` / `Theme` — `helpers/Config.tsx`, `helpers/Theme.tsx`
69
88
 
70
89
  `ConfigProvider` provides the runtime `classPrefix` (and `iconLibrary`) consumed via `useConfig`;
@@ -24,8 +24,8 @@ instead of hand-writing markup.
24
24
  - **Compound components** expose sub-parts via dot access (e.g. `Card.Header`,
25
25
  `Navbar.Item`, `Tabs.Tab`, `Hero.Body`, `Columns.Column`, `Table.Tr`); see the
26
26
  component's linked page for the full set. Sub-parts do **not** all take helper
27
- props: the `Table.*`, `Menu.*`, and `Hero.*` families do (most `Navbar.*`
28
- too), but `Card.*`, `Modal.*`, `Tabs.*`, and `Message.*` sub-parts take none —
27
+ props: the `Card.*`, `Table.*`, `Menu.*`, and `Hero.*` families do (most
28
+ `Navbar.*` too), but `Modal.*`, `Tabs.*`, and `Message.*` sub-parts take none —
29
29
  just `className`, HTML attributes, and their own few (`Tabs.Tab` requires
30
30
  `index` and has built-in `icon`/`disabled` props). Put helper props on the
31
31
  parent or on an element inside (`Span`, `Paragraph`, …) instead.
@@ -143,7 +143,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
143
143
 
144
144
  - [ConfigProvider](https://bestax.io/docs/api/helpers/config) — The `ConfigProvider` component provides a React context for configuring global settings across all Bulma UI components.
145
145
  - [Theme](https://bestax.io/docs/api/helpers/theme) — The `Theme` component provides a powerful way to customize Bulma's appearance using CSS custom properties (CSS variables).
146
- - [Valid value constants](https://bestax.io/docs/api/helpers/valid-values) — The `valid*` constant arrays enumerate every accepted value for the shared Bulma helper props — public API you can import to build prop types and validation.
146
+ - [Valid value constants](https://bestax.io/docs/api/helpers/valid-values) — The `valid*` tuples enumerate the core accepted values for the shared Bulma helper props — public API for building prop types and validation.
147
147
  - [classNames](https://bestax.io/docs/api/helpers/classnames) — `classNames` is a utility function for conditionally joining class names together.
148
148
  - [useBulmaClasses](https://bestax.io/docs/api/helpers/usebulmaclasses) — `useBulmaClasses` is a custom React hook that generates Bulma helper class strings from a set of props.
149
149
  - [usePrefixedClassNames](https://bestax.io/docs/api/helpers/useprefixedclassnames) — `usePrefixedClassNames` builds a component class string that honors the `classPrefix` from `ConfigProvider` — the hook every bestax component uses for its own…
@@ -96,6 +96,9 @@ All import from `@allxsmith/bestax-bulma`. Convenience components auto-wrap Fiel
96
96
  | `Taginput` | Tag/chip input; suggestions, confirm keys, closable tags. |
97
97
  | `DateInput` / `TimeInput` / `DateTimeInput` (+ `*Base`) | Date / time / datetime pickers. |
98
98
 
99
+ (`NumberInput` and `TagInput` also exist as deprecated aliases of `Numberinput`/`Taginput` —
100
+ same components; prefer the lowercase-second-word spellings.)
101
+
99
102
  ## Common props
100
103
 
101
104
  Across the convenience inputs (`Input`, `Select`, `TextArea`, and similar):
@@ -116,8 +119,10 @@ Across the convenience inputs (`Input`, `Select`, `TextArea`, and similar):
116
119
  Plus the full Bulma **helper props** (`m`, `p`, `textColor`, `display`, …) on every component
117
120
  via `useBulmaClasses`.
118
121
 
119
- ⚠️ Full-width casing is inconsistent across the library: `Select`, `File`, and `Table` take
120
- `isFullwidth` (lowercase w); `Button` alone takes `isFullWidth`; `Tabs` takes bare `fullwidth`.
122
+ Full-width is `isFullwidth` on every component that supports it (`Button`, `LinkButton`,
123
+ `Select`, `File`, `Table`, `Tabs`, `Sidebar`) always write `isFullwidth`. The deprecated
124
+ spellings compile only where they historically existed: `isFullWidth` everywhere except
125
+ `Sidebar`, `fullwidth` on `Tabs` only, `fullWidth` on `Sidebar` only.
121
126
 
122
127
  The `label` prop on the single-control convenience inputs (`Input`, `Select`, `TextArea`,
123
128
  `File`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`,
@@ -59,7 +59,7 @@ Wraps a single input; adds icons and loading.
59
59
  ## Select / SelectBase, TextArea / TextAreaBase
60
60
 
61
61
  Same convenience/raw split as Input. `Select` supports `isLoading` (on the control), `color`,
62
- `size`, `isRounded`, `isFullwidth` (lowercase w — Button's is `isFullWidth`), `multiple` +
62
+ `size`, `isRounded`, `isFullwidth`, `multiple` +
63
63
  `multipleSize`, plus the Field/Control/message props. `TextArea` adds `rows` and
64
64
  `hasFixedSize`.
65
65
 
@@ -70,10 +70,15 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
70
70
  `textWeight`, `textSize` directly (their `color` prop colors the cell; for muted cell text
71
71
  wrap content in `Span textColor="grey"`). Set the app-wide icon library once with
72
72
  `<ConfigProvider iconLibrary="…">` at the root rather than `library` on every `<Icon>`.
73
- - **Decorative CSS is budgeted: three compact rules, ≤13 lines per app — comments count:
73
+ - **Alternating section bands are a prop, not CSS: `bgColor="scheme-main-bis"` on every
74
+ other `Section` (next band `scheme-main-ter`).** The scheme values render as a
75
+ dark-mode-safe inline `background-color: var(--bulma-scheme-*)` — zero custom CSS — and
76
+ still never `bgColor="light"`/`"white"`: those are fixed colors that stay light when dark
77
+ mode flips the text.
78
+ - **Decorative CSS is budgeted: two compact rules, ≤10 lines per app — comments count:
74
79
  at most one short inline note, never a file-header comment block — every value derived
75
- from `--bulma-*`.** A marketing page gets at most one hero wash, one alternating section
76
- band, and one featured-card ring, applied via `className` — no resets (Bulma ships one;
80
+ from `--bulma-*`.** A marketing page gets at most one hero wash and one featured-card
81
+ ring, applied via `className` — no resets (Bulma ships one;
77
82
  body/list margins are already zero) and no grid textures, masks, or multi-layer backdrops;
78
83
  the components carry the design:
79
84
 
@@ -85,9 +90,6 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
85
90
  transparent 60%
86
91
  );
87
92
  }
88
- .section-alt {
89
- background: var(--bulma-scheme-main-bis); /* next band: -ter */
90
- }
91
93
  .featured-ring {
92
94
  --bulma-shadow: 0 0 0 2px var(--bulma-primary);
93
95
  }
@@ -188,8 +190,10 @@ inline `style`.
188
190
  - [ ] Style with helper props, not inline `style` — translate via the mapping table; values
189
191
  with no helper get a named class in the stylesheet, never `style={{}}`. No raw Bulma
190
192
  `className`s either (`Span`/`Paragraph` wrap bare text; `Th`/`Td` take `textAlign`/`textWeight`).
191
- - [ ] Decorative CSS ≤13 lines total incl. comments — no file-header comment (hero wash +
192
- section band + featured-card ring), `--bulma-*`-derived; no resets — Bulma ships one.
193
+ - [ ] Alternating bands are `bgColor="scheme-main-bis"` (next band `scheme-main-ter`) on
194
+ every other `Section` never band CSS, never `bgColor="light"`/`"white"`.
195
+ - [ ] Decorative CSS ≤10 lines total incl. comments — no file-header comment (hero wash +
196
+ featured-card ring), `--bulma-*`-derived; no resets — Bulma ships one.
193
197
  The ring sets `--bulma-shadow` in a CSS rule; `Theme bulmaVars` has no such key.
194
198
  - [ ] Set the icon library once via `<ConfigProvider iconLibrary="…">` at the root.
195
199
  - [ ] Site built? ~800 KB raw / ~82 KB gzip CSS is the expected default-flavor size — to shrink
@@ -44,7 +44,7 @@ export default function LoginPage() {
44
44
  iconLeftName="lock"
45
45
  placeholder="••••••••"
46
46
  />
47
- <Button color="primary" isFullWidth mt="4">
47
+ <Button color="primary" isFullwidth mt="4">
48
48
  Sign in
49
49
  </Button>
50
50
  </Box>
@@ -155,8 +155,11 @@ the `Hero`; if it's `fixed="top"`, the same `<html class="has-navbar-fixed-top">
155
155
  applies here too.
156
156
 
157
157
  **Alternating section bands:** tint every other `Section` with a scheme step —
158
- `.section-alt { background: var(--bulma-scheme-main-bis); }` (next step `-ter`) — not
159
- `bgColor="light"`/`"white"`: those are fixed colors that stay light when dark mode flips the text.
158
+ `bgColor="scheme-main-bis"` (next step `scheme-main-ter`) — not `bgColor="light"`/`"white"`:
159
+ those are fixed colors that stay light when dark mode flips the text. Scheme values emit no
160
+ class; the component renders a dark-mode-safe inline `background-color: var(--bulma-scheme-*)`
161
+ style, so bands cost zero custom CSS. The same values work on `Hero` (and its
162
+ `Head`/`Body`/`Foot`), `Footer`, `Container`, `Box`, and `Card`.
160
163
 
161
164
  **Hero CTAs:** on a colored hero use **filled** buttons only — `color="light"` for the primary
162
165
  CTA and `color="primary" isInverted` (solid white, primary text) for a secondary. A thin
@@ -118,6 +118,18 @@ The responsive grid. `Columns` is the row; `Column` is a cell (also reachable as
118
118
  ```ts
119
119
  type BulmaColumnSize =
120
120
  | number // 1–12
121
+ | '1'
122
+ | '2'
123
+ | '3'
124
+ | '4'
125
+ | '5'
126
+ | '6'
127
+ | '7'
128
+ | '8'
129
+ | '9'
130
+ | '10'
131
+ | '11'
132
+ | '12' // string form, equivalent
121
133
  | 'full'
122
134
  | 'half'
123
135
  | 'one-third'
@@ -130,8 +142,8 @@ type BulmaColumnSize =
130
142
  | 'four-fifths';
131
143
  ```
132
144
 
133
- Numeric sizes are **numbers** — `sizeDesktop={7}`, never `"7"`; only the fraction names are
134
- strings. (`gap` is the exception that accepts number **or** string.)
145
+ Numeric sizes accept a number **or** its string form — `sizeDesktop={7}` and
146
+ `sizeDesktop="7"` are equivalent, and the fraction names are strings.
135
147
 
136
148
  > Columns **stack on mobile** by default and go side-by-side at the tablet breakpoint and up.
137
149
  > Use the per-breakpoint `size*` props to control how many cells share a row at each width.
@@ -157,7 +169,9 @@ the column's auto height). Make the `Column` a flex container and let the card g
157
169
  ```
158
170
 
159
171
  `display`, `flexDirection`, and `flexGrow` are helper props every component accepts;
160
- `flexGrow` takes a string (`"1"`).
172
+ `flexGrow` takes a string (`"1"`). `Card.*` sub-parts accept helper props too, so pinning a
173
+ footer inside a card is `<Card display="flex" flexDirection="column">` +
174
+ `<Card.Content flexGrow="1">` — no `Box` swap needed.
161
175
 
162
176
  ## Grid / Cell
163
177
 
@@ -32,7 +32,7 @@ this automatically for literal values; dynamic values get TODOs.
32
32
  ## Boolean modifier convention
33
33
 
34
34
  RBC uses bare booleans (`loading`, `outlined`, `rounded`, `fullwidth`); bestax prefixes
35
- with `is`/`has` (`isLoading`, `isOutlined`, `isRounded`, `isFullWidth`). Per-component
35
+ with `is`/`has` (`isLoading`, `isOutlined`, `isRounded`, `isFullwidth`). Per-component
36
36
  tables live in [component-map.md](component-map.md).
37
37
 
38
38
  ## Responsive breakpoint objects → flat per-viewport props
@@ -44,9 +44,13 @@ color tokens or fixed-color surfaces exist:
44
44
  (`--my-canvas: var(--bulma-scheme-main)`) — or flip them yourself under **both** dark-mode
45
45
  paths: `[data-theme='dark']` **and** `@media (prefers-color-scheme: dark)` scoped to
46
46
  `:root:not([data-theme])`, since `colorMode="system"` removes the attribute (snippets in
47
- `references/css-variables.md`). Alternating/tinted section bands are this case:
48
- `background: var(--bulma-scheme-main-bis)` (then `-ter`), never `bgColor="light"`
49
- `light`/`white`/grey helper backgrounds are fixed colors that fight dark mode.
47
+ `references/css-variables.md`). Alternating/tinted section bands are first-class props:
48
+ `bgColor="scheme-main-bis"` (then `"scheme-main-ter"`) on `Section` (also `Hero`, `Footer`,
49
+ `Container`, `Box`, `Card`) renders a scheme-tracking inline background never
50
+ `bgColor="light"`: `light`/`white`/grey helper backgrounds are fixed colors that fight
51
+ dark mode. Keep the derive-from-scheme-vars CSS for other custom surfaces. `Theme
52
+ bulmaVars` now accepts `--bulma-scheme-main`/`-bis`/`-ter` (and the `-invert` trio)
53
+ overrides, so one Theme re-tints every band at once.
50
54
  - **Fixed-color surface → fixed-color content.** On a surface that never changes (a dark hero,
51
55
  a brand banner), pin the content's colors too: solid/filled buttons and explicit text colors,
52
56
  never scheme-derived defaults or thin outlines that depend on the flipping scheme.
@@ -81,13 +81,14 @@ and numeric shades `--bulma-<c>-00` … `--bulma-<c>-95`.
81
81
 
82
82
  ## Scheme, text, background, border (light/dark surfaces)
83
83
 
84
- | Variable | Role |
85
- | --------------------------------------------------------------------------- | ----------------------------------------------------- |
86
- | `--bulma-scheme-h`, `--bulma-scheme-s` | scheme hue/saturation (`Theme`: `schemeH`, `schemeS`) |
87
- | `--bulma-scheme-main`, `--bulma-scheme-main-bis`, `--bulma-scheme-main-ter` | page/surface backgrounds (main + subtle steps) |
88
- | `--bulma-background` | secondary background |
89
- | `--bulma-text`, `--bulma-text-strong`, `--bulma-text-weak` | body / emphasized / muted text |
90
- | `--bulma-border`, `--bulma-border-weak` | borders |
84
+ | Variable | Role |
85
+ | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
86
+ | `--bulma-scheme-h`, `--bulma-scheme-s` | scheme hue/saturation (`Theme`: `schemeH`, `schemeS`) |
87
+ | `--bulma-scheme-main`, `--bulma-scheme-main-bis`, `--bulma-scheme-main-ter` | page/surface backgrounds (main + subtle steps); `Theme bulmaVars`-overridable, and the scheme `bgColor` values render them inline |
88
+ | `--bulma-scheme-invert`, `--bulma-scheme-invert-bis`, `--bulma-scheme-invert-ter` | inverted scheme surfaces; `Theme bulmaVars`-overridable, and the scheme `bgColor` values render them inline (pair with a foreground — see the color guide) |
89
+ | `--bulma-background` | secondary background |
90
+ | `--bulma-text`, `--bulma-text-strong`, `--bulma-text-weak` | body / emphasized / muted text |
91
+ | `--bulma-border`, `--bulma-border-weak` | borders |
91
92
 
92
93
  ## Radius, typography
93
94
 
@@ -50,14 +50,14 @@ Shades (`colorShade` / `backgroundColorShade`): `00, 05, 10, … 95, invert, lig
50
50
  | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
51
51
  | `Button` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black \| text \| ghost` | `small \| normal \| medium \| large` | adds `text`, `ghost`; also `isLight`, `isOutlined`, `isInverted`, `isRounded` |
52
52
  | `Notification` | the 17 `validColors` (`black-bis`, `black-ter`, and greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | — | also `isLight` |
53
- | `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `normal \| medium \| large` | also `isRounded`, `isDelete`, `isHoverable` — **no `isLight`** |
53
+ | `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `normal \| medium \| large` | also `isLight`, `isRounded`, `isDelete`, `isHoverable` |
54
54
  | `Box` | `primary \| link \| info \| success \| warning \| danger` | — | `color` renders `has-text-<color>`, same as `textColor` (which wins when both are set; no `.box.is-*` ships — tint via `bgColor`); also `hasShadow` |
55
55
  | `Message` | `primary \| link \| info \| success \| warning \| danger` | — | the 6 only |
56
56
  | `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
57
57
  | `Avatar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `16x16 \| 24x24 \| 32x32 \| 48x48 \| 64x64 \| 96x96 \| 128x128 \| number` | initials/icon background (auto-derived from `name` when unset); also `shape` |
58
58
  | `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | pill background; default `danger` |
59
- | `Title` | — (no `color`; use `textColor`) | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | also `isSpaced` |
60
- | `SubTitle` | — (no `color`; use `textColor`) | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | — |
59
+ | `Title` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | also `isSpaced` |
60
+ | `SubTitle` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | — |
61
61
  | `Autocomplete` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
62
62
  | `Checkbox` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
63
63
  | `DateInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
@@ -0,0 +1,25 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+ *.tsbuildinfo
15
+
16
+ # Editor directories and files
17
+ .vscode/*
18
+ !.vscode/extensions.json
19
+ .idea
20
+ .DS_Store
21
+ *.suo
22
+ *.ntvs*
23
+ *.njsproj
24
+ *.sln
25
+ *.sw?
@@ -0,0 +1,25 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+ *.tsbuildinfo
15
+
16
+ # Editor directories and files
17
+ .vscode/*
18
+ !.vscode/extensions.json
19
+ .idea
20
+ .DS_Store
21
+ *.suo
22
+ *.ntvs*
23
+ *.njsproj
24
+ *.sln
25
+ *.sw?
@@ -5,6 +5,7 @@
5
5
  "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
6
  "module": "ESNext",
7
7
  "skipLibCheck": true,
8
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
8
9
 
9
10
  /* Bundler mode */
10
11
  "moduleResolution": "bundler",