@allxsmith/bestax-bulma 5.57.0 → 5.57.2

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 (63) hide show
  1. package/README.md +2 -2
  2. package/dist/bestax.css +1 -1
  3. package/dist/bestax.css.map +1 -1
  4. package/dist/esm/components/Dropdown.js +4 -1
  5. package/dist/esm/components/Dropdown.js.map +1 -1
  6. package/dist/esm/components/Toast.js +21 -7
  7. package/dist/esm/components/Toast.js.map +1 -1
  8. package/dist/esm/elements/Tr.js.map +1 -1
  9. package/dist/esm/form/Checkbox.js +21 -14
  10. package/dist/esm/form/Checkbox.js.map +1 -1
  11. package/dist/esm/form/CheckboxCard.js +17 -11
  12. package/dist/esm/form/CheckboxCard.js.map +1 -1
  13. package/dist/esm/form/Checkboxes.js +30 -3
  14. package/dist/esm/form/Checkboxes.js.map +1 -1
  15. package/dist/esm/form/FormContext.js +31 -1
  16. package/dist/esm/form/FormContext.js.map +1 -1
  17. package/dist/esm/form/Radio.js +13 -10
  18. package/dist/esm/form/Radio.js.map +1 -1
  19. package/dist/esm/form/RadioCard.js +10 -8
  20. package/dist/esm/form/RadioCard.js.map +1 -1
  21. package/dist/esm/form/Radios.js +15 -3
  22. package/dist/esm/form/Radios.js.map +1 -1
  23. package/dist/esm/form/Rate.js +2 -2
  24. package/dist/esm/form/Rate.js.map +1 -1
  25. package/dist/extras.css +1 -1
  26. package/dist/extras.css.map +1 -1
  27. package/dist/index.cjs +156 -53
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/types/components/Toast.d.ts +14 -3
  30. package/dist/types/elements/Tr.d.ts +3 -3
  31. package/dist/types/form/CheckboxCard.d.ts +1 -1
  32. package/dist/types/form/Checkboxes.d.ts +7 -1
  33. package/dist/types/form/FormContext.d.ts +34 -1
  34. package/dist/types/form/RadioCard.d.ts +1 -1
  35. package/dist/types/form/Radios.d.ts +5 -1
  36. package/dist/types/form/Rate.d.ts +5 -1
  37. package/dist/types-cjs/components/Toast.d.ts +14 -3
  38. package/dist/types-cjs/elements/Tr.d.ts +3 -3
  39. package/dist/types-cjs/form/CheckboxCard.d.ts +1 -1
  40. package/dist/types-cjs/form/Checkboxes.d.ts +7 -1
  41. package/dist/types-cjs/form/FormContext.d.ts +34 -1
  42. package/dist/types-cjs/form/RadioCard.d.ts +1 -1
  43. package/dist/types-cjs/form/Radios.d.ts +5 -1
  44. package/dist/types-cjs/form/Rate.d.ts +5 -1
  45. package/dist/versions/bestax-no-dark-mode.css +1 -1
  46. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  47. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  48. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  49. package/dist/versions/bestax-no-helpers.css +1 -1
  50. package/dist/versions/bestax-no-helpers.css.map +1 -1
  51. package/dist/versions/bestax-prefixed.css +1 -1
  52. package/dist/versions/bestax-prefixed.css.map +1 -1
  53. package/package.json +28 -28
  54. package/src/scss/CLAUDE.md +4 -1
  55. package/src/scss/_selected-row.scss +43 -0
  56. package/src/scss/components/_index.scss +1 -0
  57. package/src/scss/components/_pagination.scss +25 -0
  58. package/src/scss/components/_toast.scss +2 -1
  59. package/src/scss/form/_checkbox.scss +18 -42
  60. package/src/scss/form/_combobox.scss +11 -0
  61. package/src/scss/form/_radio.scss +28 -2
  62. package/src/scss/form/_switch.scss +9 -5
  63. package/src/scss/form/_taginput.scss +6 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allxsmith/bestax-bulma",
3
- "version": "5.57.0",
3
+ "version": "5.57.2",
4
4
  "description": "Component library based on React, Bulma, with Agent Skills and MCP",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.esm.js",
@@ -26,42 +26,42 @@
26
26
  "@mdi/font": "^7.4.47",
27
27
  "@rollup/plugin-commonjs": "^29.0.3",
28
28
  "@rollup/plugin-node-resolve": "^16.0.1",
29
- "@rollup/plugin-typescript": "^12.1.0",
30
- "@storybook/addon-docs": "^10.6.2",
31
- "@storybook/addon-onboarding": "^10.6.2",
32
- "@storybook/react-vite": "^10.6.2",
33
- "@storybook/test-runner": "^0.26.0",
29
+ "@rollup/plugin-typescript": "^12.3.1",
30
+ "@storybook/addon-docs": "^10.6.5",
31
+ "@storybook/addon-onboarding": "^10.6.5",
32
+ "@storybook/addon-vitest": "^10.6.5",
33
+ "@storybook/react-vite": "^10.6.5",
34
34
  "@testing-library/jest-dom": "^7.0.1",
35
35
  "@testing-library/react": "^16.3.3",
36
36
  "@testing-library/user-event": "^14.6.8",
37
- "@types/jest": "^30.0.0",
38
37
  "@types/react": "^19.3.0",
39
38
  "@types/react-dom": "^19.3.0",
40
- "@typescript-eslint/eslint-plugin": "^8.71.2",
41
- "@typescript-eslint/parser": "^8.71.2",
39
+ "@typescript-eslint/eslint-plugin": "^8.72.1",
40
+ "@typescript-eslint/parser": "^8.72.1",
41
+ "@vitest/browser-playwright": "^5.0.5",
42
+ "@vitest/coverage-istanbul": "^5.0.5",
42
43
  "eslint": "^10.13.0",
43
44
  "eslint-config-prettier": "^10.1.5",
44
45
  "eslint-plugin-prettier": "^5.5.7",
45
46
  "eslint-plugin-react-hooks": "^7.1.1",
46
- "eslint-plugin-storybook": "^10.6.2",
47
+ "eslint-plugin-storybook": "^10.6.5",
47
48
  "ionicons": "^8.1.0",
48
- "jest": "^30.2.0",
49
- "jest-environment-jsdom": "^30.2.0",
49
+ "jsdom": "^30.1.3",
50
50
  "material-icons": "^1.13.14",
51
- "material-symbols": "^0.47.6",
51
+ "material-symbols": "^0.48.2",
52
52
  "playwright": "^1.64.1",
53
- "prettier": "^3.9.9",
53
+ "prettier": "^3.9.10",
54
54
  "rimraf": "^6.0.1",
55
- "rollup": "^4.64.10",
55
+ "rollup": "^4.66.0",
56
56
  "rollup-plugin-scss": "^4.0.1",
57
57
  "rollup-plugin-visualizer": "^7.1.1",
58
- "sass": "^1.105.2",
59
- "sass-embedded": "^1.105.2",
60
- "storybook": "^10.6.2",
61
- "ts-jest": "^29.4.15",
58
+ "sass": "^1.107.0",
59
+ "sass-embedded": "^1.107.0",
60
+ "storybook": "^10.6.5",
62
61
  "tslib": "^2.8.0",
63
62
  "typescript": "^6.0.3",
64
- "vite": "^8.3.4"
63
+ "vite": "^8.3.5",
64
+ "vitest": "^5.0.5"
65
65
  },
66
66
  "dependencies": {
67
67
  "bulma": "^1.0.4"
@@ -71,7 +71,7 @@
71
71
  "@mdi/font": "^7.4.47",
72
72
  "ionicons": "^8.0.0",
73
73
  "material-icons": "^1.13.10",
74
- "material-symbols": "^0.34.1 || ^0.45.0 || ^0.46.0 || ^0.47.0",
74
+ "material-symbols": "^0.34.1 || ^0.45.0 || ^0.46.0 || ^0.47.0 || ^0.48.0",
75
75
  "react": "^18.0.0 || ^19.0.0",
76
76
  "react-dom": "^18.0.0 || ^19.0.0"
77
77
  },
@@ -210,11 +210,11 @@
210
210
  "build": "rollup -c",
211
211
  "dev": "rollup -c --watch",
212
212
  "watch": "rollup -c --watch",
213
- "test": "jest",
214
- "test:watch": "jest --watch",
215
- "test:coverage": "jest --coverage",
213
+ "test": "vitest run",
214
+ "test:watch": "vitest",
215
+ "test:coverage": "vitest run --coverage",
216
216
  "bundle:stats": "rollup -c --configPlugin visualizer",
217
- "lint": "eslint src",
217
+ "lint": "eslint src .storybook vitest.config.ts vitest.storybook.config.ts",
218
218
  "typecheck": "tsc --noEmit",
219
219
  "typecheck:tests": "tsc -p tsconfig.test.json --noEmit",
220
220
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
@@ -224,9 +224,9 @@
224
224
  "start": "storybook dev -p 6006",
225
225
  "build-storybook": "storybook build",
226
226
  "release": "npx semantic-release",
227
- "test-storybook": "test-storybook",
228
- "test-storybook:dark": "STORYBOOK_THEME=dark test-storybook",
227
+ "test-storybook": "vitest run --config vitest.storybook.config.ts",
228
+ "test-storybook:dark": "STORYBOOK_THEME=dark vitest run --config vitest.storybook.config.ts",
229
229
  "test-storybook:ci": "node scripts/test-storybook-ci.mjs"
230
230
  },
231
- "readme": "# @allxsmith/bestax-bulma\n\n[![npm version](https://img.shields.io/npm/v/@allxsmith/bestax-bulma.svg)](https://www.npmjs.com/package/@allxsmith/bestax-bulma)\n[![npm downloads](https://img.shields.io/npm/dm/@allxsmith/bestax-bulma.svg)](https://www.npmjs.com/package/@allxsmith/bestax-bulma)\n[![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue.svg)](https://www.typescriptlang.org/)\n[![Coverage](https://img.shields.io/badge/coverage-99%25-brightgreen.svg)](https://github.com/allxsmith/bestax/blob/main/bulma-ui/jest.config.js)\n[![Bulma](https://img.shields.io/badge/Bulma-v1.0+-00d1b2.svg)](https://bulma.io)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Socket Badge](https://badge.socket.dev/npm/package/@allxsmith/bestax-bulma/latest)](https://socket.dev/npm/package/@allxsmith/bestax-bulma/overview)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/allxsmith/bestax/badge)](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/14361/badge)](https://www.bestpractices.dev/projects/14361)\n[![npm provenance](https://img.shields.io/badge/npm-provenance-3fb950.svg)](https://www.npmjs.com/package/@allxsmith/bestax-bulma#provenance)\n[![Security policy](https://img.shields.io/badge/security-policy-blue.svg)](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nTypeScript-first React component library for the **Bulma v1** CSS framework — 80+ fully typed, tree-shakeable components, including extras like Carousel, Dialog, Sidebar, Steps, and date/time pickers.\n\n**Requires React `^18 || ^19`.** Bulma v1 is the only runtime dependency and installs automatically.\n\nPart of the [bestax monorepo](https://github.com/allxsmith/bestax) — see also [`create-bestax`](https://www.npmjs.com/package/create-bestax) for scaffolding new projects.\n\n---\n\n## 📚 Comprehensive Documentation\n\n**Looking for full documentation, guides, API references, and best practices?** \n👉 **Visit our official docs at [https://bestax.io](https://bestax.io)**\n\n> The documentation site is the best place to learn about all bestax-bulma features, usage patterns, and updates. We strongly recommend using the docs as your primary resource!\n\n---\n\n## 🚀 Getting Started\n\nStarting fresh? Scaffold a ready-to-go app instead: `npm create bestax@latest my-app`.\n\n### 1. Install the package\n\n```bash\nnpm install @allxsmith/bestax-bulma\n# or\npnpm add @allxsmith/bestax-bulma\n```\n\n### 2. Import the CSS\n\nThe library bundles its own CSS (Bulma v1 + the bestax extras). Import it once in your main JS/TS file:\n\n```js\nimport '@allxsmith/bestax-bulma/bestax.css';\n```\n\nPrefer stock Bulma? That works too — add `extras.css` for the bestax-only components' styles:\n\n```js\nimport 'bulma/css/bulma.min.css';\nimport '@allxsmith/bestax-bulma/extras.css';\n```\n\nMore flavors are shipped as subpath exports — prefixed classes (`versions/bestax-prefixed.css` + `<ConfigProvider classPrefix=\"bestax-\">`), no-helpers, no-dark-mode, and raw SCSS at `@allxsmith/bestax-bulma/scss/*`. See the [installation guide](https://bestax.io/docs/guides/getting-started/installation).\n\n### 3. (Optional) Add an Icon Library\n\nFive icon libraries are supported as optional peer dependencies: [Font Awesome](https://fontawesome.com/) (`@fortawesome/fontawesome-free`), Material Design Icons (`@mdi/font`), `ionicons`, `material-icons`, and `material-symbols`.\n\n```bash\nnpm install @fortawesome/fontawesome-free\n```\n\nSet the default for your whole app with [`ConfigProvider`](https://bestax.io/docs/api/helpers/config), e.g. `<ConfigProvider iconLibrary=\"fa\">`.\n\n### 4. Quick Example\n\n```tsx\nimport '@allxsmith/bestax-bulma/bestax.css';\nimport { Button } from '@allxsmith/bestax-bulma';\n\nfunction App() {\n return (\n <Button color=\"primary\" onClick={() => alert('Clicked!')}>\n Click Me\n </Button>\n );\n}\n\nexport default App;\n```\n\n### 5. Theming and Dark Mode\n\nWrap your app in [`Theme`](https://bestax.io/docs/api/helpers/theme) to override Bulma's `--bulma-*` CSS variables and control the color scheme:\n\n```tsx\nimport { Theme } from '@allxsmith/bestax-bulma';\n\n<Theme isRoot colorMode=\"system\">\n {/* colorMode: 'light' | 'dark' | 'system' */}\n <App />\n</Theme>;\n```\n\n---\n\n## ⭐ Why Choose bestax-bulma?\n\n- **Supports the latest Bulma v1.x**\n Other React Bulma libraries are stuck on Bulma 0.9.4 — bestax-bulma is built for the future.\n- **80+ components**\n All of Bulma v1, plus extras: Carousel, Dialog, Sidebar, Steps, Autocomplete, Taginput, DateInput/TimeInput/DateTimeInput pickers, and more. (Migrating from v2? Snackbar merged into [Toast](https://bestax.io/docs/api/components/toast).)\n- **Dark mode & theming built in**\n `Theme colorMode`, `--bulma-*` variable overrides, and prefixed-class builds via `ConfigProvider`.\n- **Just one dependency: Bulma**\n Every Bulma library depends on it — we ship it automatically. Clean install, fewer security concerns.\n- **Tree-shakeable ESM**\n Import only what you use; your bundler drops the rest. A CJS build is there for `require`.\n- **99% unit test coverage**\n Enforced in CI by the [jest config](https://github.com/allxsmith/bestax/blob/main/bulma-ui/jest.config.js) — not just claimed.\n- **100% TypeScript**\n Full type safety for you and your team.\n- **Active developer support**\n Issues? Questions? PRs? Get fast responses and real improvements.\n\n---\n\n## 📦 NPM Package\n\nView the package on npmjs: \n👉 [https://www.npmjs.com/package/@allxsmith/bestax-bulma](https://www.npmjs.com/package/@allxsmith/bestax-bulma)\n\n---\n\n## 🔒 Hardened by default\n\nThis package is one runtime dependency deep (Bulma) and is published under a deliberately strict pipeline:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Verify it in the **Provenance** section of the [npm page](https://www.npmjs.com/package/@allxsmith/bestax-bulma#provenance), or run `npm audit signatures` in your project.\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 package.\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---\n\n## 📚 Documentation\n\n**For full documentation, guides, and best practices, please use our official docs site:**\n\n👉 [https://bestax.io](https://bestax.io)\n\n> **Always refer to the [documentation site](https://bestax.io) first:** \n> It's the most complete and up-to-date source for everything bestax-bulma!\n\n---\n\n## 📖 Storybook\n\nExplore live, interactive component examples in our Storybook:\n\n👉 [https://bestax.io/storybook](https://bestax.io/storybook)\n\n---\n\n## 🤖 For AI Tools\n\nBuilding with an AI agent (Claude Code, Cursor, Copilot)? bestax-bulma ships LLM-optimized docs:\n\n- 📘 **[LLMs guide](https://bestax.io/docs/guides/llms)** — how to use the library with AI tools\n- 📄 **[llms.txt](https://bestax.io/llms.txt)** — curated index · **[llms-full.txt](https://bestax.io/llms-full.txt)** — the full docs in one file · every docs page is also served as raw markdown\n- 📦 **In the npm package** — the tarball ships `llms.txt`, `AGENTS.md`, and `CLAUDE.md` pointer files, so agents exploring `node_modules` land on these resources by filename\n- 🧩 **[Agent Skills](https://bestax.io/docs/skills/intro)** — teach your agent the bestax way:\n\n | Skill | Use it when… |\n | ------------------------- | -------------------------------------------------------------------------------- |\n | `bestax-layout-scaffold` | Turning a high-level request (dashboard, landing page, …) into a responsive page |\n | `bestax-form` | Building forms — Field/Control composition and the full input inventory |\n | `bestax-theming` | Customizing colors, fonts, dark mode via `Theme` and `--bulma-*` variables |\n | `bestax-custom-component` | Building a new custom component beyond stock Bulma, the bestax way |\n | `bestax-icons` | Adding icons — Icon/IconText and the five supported icon libraries |\n | `bestax-optimize` | Shrinking the built CSS — flavor builds, modular Sass, import hygiene |\n | `bestax-migrate` | Moving an app off react-bulma-components (v4) onto bestax-bulma |\n\n ```bash\n npx skills add https://github.com/allxsmith/bestax --skill bestax-layout-scaffold\n ```\n\n New projects get the skills automatically with `npm create bestax@latest my-app --skills` (plus a generated `CLAUDE.md`).\n\n---\n\n## 🙏 Attribution\n\nbestax-bulma is built on top of the incredible [Bulma](https://bulma.io) CSS framework,\n© [Jeremy Thomas](https://github.com/jgthms) and licensed under the\n[MIT License](https://github.com/jgthms/bulma/blob/main/LICENSE), whose notice ships with the\npackage in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). Some example content and documentation is\nadapted from the Bulma website\n([CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)), © Jeremy Thomas.\n\nIf you find Bulma useful, please consider\n[sponsoring Jeremy Thomas](https://github.com/sponsors/jgthms) to support its continued\ndevelopment.\n\n_We are not affiliated with Bulma or Jeremy Thomas in any way — we're just big fans of the\nBulma framework!_\n\n## License\n\nSource code licensed MIT\n"
231
+ "readme": "# @allxsmith/bestax-bulma\n\n[![npm version](https://img.shields.io/npm/v/@allxsmith/bestax-bulma.svg)](https://www.npmjs.com/package/@allxsmith/bestax-bulma)\n[![npm downloads](https://img.shields.io/npm/dm/@allxsmith/bestax-bulma.svg)](https://www.npmjs.com/package/@allxsmith/bestax-bulma)\n[![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue.svg)](https://www.typescriptlang.org/)\n[![Coverage](https://img.shields.io/badge/coverage-99%25-brightgreen.svg)](https://github.com/allxsmith/bestax/blob/main/bulma-ui/vitest.config.ts)\n[![Bulma](https://img.shields.io/badge/Bulma-v1.0+-00d1b2.svg)](https://bulma.io)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Socket Badge](https://badge.socket.dev/npm/package/@allxsmith/bestax-bulma/latest)](https://socket.dev/npm/package/@allxsmith/bestax-bulma/overview)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/allxsmith/bestax/badge)](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/14361/badge)](https://www.bestpractices.dev/projects/14361)\n[![npm provenance](https://img.shields.io/badge/npm-provenance-3fb950.svg)](https://www.npmjs.com/package/@allxsmith/bestax-bulma#provenance)\n[![Security policy](https://img.shields.io/badge/security-policy-blue.svg)](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nTypeScript-first React component library for the **Bulma v1** CSS framework — 80+ fully typed, tree-shakeable components, including extras like Carousel, Dialog, Sidebar, Steps, and date/time pickers.\n\n**Requires React `^18 || ^19`.** Bulma v1 is the only runtime dependency and installs automatically.\n\nPart of the [bestax monorepo](https://github.com/allxsmith/bestax) — see also [`create-bestax`](https://www.npmjs.com/package/create-bestax) for scaffolding new projects.\n\n---\n\n## 📚 Comprehensive Documentation\n\n**Looking for full documentation, guides, API references, and best practices?** \n👉 **Visit our official docs at [https://bestax.io](https://bestax.io)**\n\n> The documentation site is the best place to learn about all bestax-bulma features, usage patterns, and updates. We strongly recommend using the docs as your primary resource!\n\n---\n\n## 🚀 Getting Started\n\nStarting fresh? Scaffold a ready-to-go app instead: `npm create bestax@latest my-app`.\n\n### 1. Install the package\n\n```bash\nnpm install @allxsmith/bestax-bulma\n# or\npnpm add @allxsmith/bestax-bulma\n```\n\n### 2. Import the CSS\n\nThe library bundles its own CSS (Bulma v1 + the bestax extras). Import it once in your main JS/TS file:\n\n```js\nimport '@allxsmith/bestax-bulma/bestax.css';\n```\n\nPrefer stock Bulma? That works too — add `extras.css` for the bestax-only components' styles:\n\n```js\nimport 'bulma/css/bulma.min.css';\nimport '@allxsmith/bestax-bulma/extras.css';\n```\n\nMore flavors are shipped as subpath exports — prefixed classes (`versions/bestax-prefixed.css` + `<ConfigProvider classPrefix=\"bestax-\">`), no-helpers, no-dark-mode, and raw SCSS at `@allxsmith/bestax-bulma/scss/*`. See the [installation guide](https://bestax.io/docs/guides/getting-started/installation).\n\n### 3. (Optional) Add an Icon Library\n\nFive icon libraries are supported as optional peer dependencies: [Font Awesome](https://fontawesome.com/) (`@fortawesome/fontawesome-free`), Material Design Icons (`@mdi/font`), `ionicons`, `material-icons`, and `material-symbols`.\n\n```bash\nnpm install @fortawesome/fontawesome-free\n```\n\nSet the default for your whole app with [`ConfigProvider`](https://bestax.io/docs/api/helpers/config), e.g. `<ConfigProvider iconLibrary=\"fa\">`.\n\n### 4. Quick Example\n\n```tsx\nimport '@allxsmith/bestax-bulma/bestax.css';\nimport { Button } from '@allxsmith/bestax-bulma';\n\nfunction App() {\n return (\n <Button color=\"primary\" onClick={() => alert('Clicked!')}>\n Click Me\n </Button>\n );\n}\n\nexport default App;\n```\n\n### 5. Theming and Dark Mode\n\nWrap your app in [`Theme`](https://bestax.io/docs/api/helpers/theme) to override Bulma's `--bulma-*` CSS variables and control the color scheme:\n\n```tsx\nimport { Theme } from '@allxsmith/bestax-bulma';\n\n<Theme isRoot colorMode=\"system\">\n {/* colorMode: 'light' | 'dark' | 'system' */}\n <App />\n</Theme>;\n```\n\n---\n\n## ⭐ Why Choose bestax-bulma?\n\n- **Supports the latest Bulma v1.x**\n Other React Bulma libraries are stuck on Bulma 0.9.4 — bestax-bulma is built for the future.\n- **80+ components**\n All of Bulma v1, plus extras: Carousel, Dialog, Sidebar, Steps, Autocomplete, Taginput, DateInput/TimeInput/DateTimeInput pickers, and more. (Migrating from v2? Snackbar merged into [Toast](https://bestax.io/docs/api/components/toast).)\n- **Dark mode & theming built in**\n `Theme colorMode`, `--bulma-*` variable overrides, and prefixed-class builds via `ConfigProvider`.\n- **Just one dependency: Bulma**\n Every Bulma library depends on it — we ship it automatically. Clean install, fewer security concerns.\n- **Tree-shakeable ESM**\n Import only what you use; your bundler drops the rest. A CJS build is there for `require`.\n- **99% unit test coverage**\n Enforced in CI by the [Vitest config](https://github.com/allxsmith/bestax/blob/main/bulma-ui/vitest.config.ts) — not just claimed.\n- **100% TypeScript**\n Full type safety for you and your team.\n- **Active developer support**\n Issues? Questions? PRs? Get fast responses and real improvements.\n\n---\n\n## 📦 NPM Package\n\nView the package on npmjs: \n👉 [https://www.npmjs.com/package/@allxsmith/bestax-bulma](https://www.npmjs.com/package/@allxsmith/bestax-bulma)\n\n---\n\n## 🔒 Hardened by default\n\nThis package is one runtime dependency deep (Bulma) and is published under a deliberately strict pipeline:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Verify it in the **Provenance** section of the [npm page](https://www.npmjs.com/package/@allxsmith/bestax-bulma#provenance), or run `npm audit signatures` in your project.\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 package.\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---\n\n## 📚 Documentation\n\n**For full documentation, guides, and best practices, please use our official docs site:**\n\n👉 [https://bestax.io](https://bestax.io)\n\n> **Always refer to the [documentation site](https://bestax.io) first:** \n> It's the most complete and up-to-date source for everything bestax-bulma!\n\n---\n\n## 📖 Storybook\n\nExplore live, interactive component examples in our Storybook:\n\n👉 [https://bestax.io/storybook](https://bestax.io/storybook)\n\n---\n\n## 🤖 For AI Tools\n\nBuilding with an AI agent (Claude Code, Cursor, Copilot)? bestax-bulma ships LLM-optimized docs:\n\n- 📘 **[LLMs guide](https://bestax.io/docs/guides/llms)** — how to use the library with AI tools\n- 📄 **[llms.txt](https://bestax.io/llms.txt)** — curated index · **[llms-full.txt](https://bestax.io/llms-full.txt)** — the full docs in one file · every docs page is also served as raw markdown\n- 📦 **In the npm package** — the tarball ships `llms.txt`, `AGENTS.md`, and `CLAUDE.md` pointer files, so agents exploring `node_modules` land on these resources by filename\n- 🧩 **[Agent Skills](https://bestax.io/docs/skills/intro)** — teach your agent the bestax way:\n\n | Skill | Use it when… |\n | ------------------------- | -------------------------------------------------------------------------------- |\n | `bestax-layout-scaffold` | Turning a high-level request (dashboard, landing page, …) into a responsive page |\n | `bestax-form` | Building forms — Field/Control composition and the full input inventory |\n | `bestax-theming` | Customizing colors, fonts, dark mode via `Theme` and `--bulma-*` variables |\n | `bestax-custom-component` | Building a new custom component beyond stock Bulma, the bestax way |\n | `bestax-icons` | Adding icons — Icon/IconText and the five supported icon libraries |\n | `bestax-optimize` | Shrinking the built CSS — flavor builds, modular Sass, import hygiene |\n | `bestax-migrate` | Moving an app off react-bulma-components (v4) onto bestax-bulma |\n\n ```bash\n npx skills add https://github.com/allxsmith/bestax --skill bestax-layout-scaffold\n ```\n\n New projects get the skills automatically with `npm create bestax@latest my-app --skills` (plus a generated `CLAUDE.md`).\n\n---\n\n## 🙏 Attribution\n\nbestax-bulma is built on top of the incredible [Bulma](https://bulma.io) CSS framework,\n© [Jeremy Thomas](https://github.com/jgthms) and licensed under the\n[MIT License](https://github.com/jgthms/bulma/blob/main/LICENSE), whose notice ships with the\npackage in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). Some example content and documentation is\nadapted from the Bulma website\n([CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)), © Jeremy Thomas.\n\nIf you find Bulma useful, please consider\n[sponsoring Jeremy Thomas](https://github.com/sponsors/jgthms) to support its continued\ndevelopment.\n\n_We are not affiliated with Bulma or Jeremy Thomas in any way — we're just big fans of the\nBulma framework!_\n\n## License\n\nSource code licensed MIT\n"
232
232
  }
@@ -12,7 +12,10 @@ of their own — Bulma provides it. A partial exists only for components that ex
12
12
  - `components/`, `form/`, `elements/`, `layout/`, `helpers/` — one `_foo.scss` partial per extra,
13
13
  **registered in that folder's `_index.scss`** (an unregistered partial silently ships nothing)
14
14
  - `_variables.scss` — `$extras-*` tokens derived from Bulma's HSL channel vars (`--bulma-primary-h/s/l`)
15
- - `_mixins.scss` — shared mixins: `extras-transition`, `extras-focus-outline` (a11y), `extras-sr-only`
15
+ - `_mixins.scss` — shared mixins: `extras-transition`, `extras-focus-outline` (a11y), `extras-sr-only`.
16
+ It loads no Bulma module, since tests compile it with only this folder on the load path
17
+ - `_selected-row.scss` — `extras-selected-table-cell`, the cells Checkbox's and Radio's
18
+ selected-row rules share; it reads Bulma's `$colors`, which is why it isn't in `_mixins.scss`
16
19
  - `versions/` — the flavor builds: `bestax-prefixed`, `bestax-no-helpers`, `bestax-no-dark-mode`,
17
20
  `bestax-no-helpers-prefixed`. A new partial is included by all of them automatically (they reuse
18
21
  the same `_index` imports), but must **work** under each — especially the prefixed build.
@@ -0,0 +1,43 @@
1
+ // Bestax Extras - the cells of a selected table row
2
+ // A mixin Checkbox and Radio share, so the cells their selected-row rules
3
+ // name can't drift apart. It reads Bulma's `$colors`, so it lives here rather
4
+ // than in `_mixins.scss`, which compiles with no Bulma to load.
5
+
6
+ @use 'sass:list';
7
+ @use 'bulma/sass/utilities/initial-variables' as iv;
8
+ @use 'bulma/sass/utilities/derived-variables' as dv;
9
+
10
+ // The cells of a table that sit on Bulma's selected-row fill (`Tr
11
+ // isSelected`, or a cell with `is-selected`), for a control drawn in the
12
+ // primary color, which the fill is too. Name the step from the cell down to
13
+ // the control in the content with a child combinator (`> .styled-checkbox`):
14
+ // one inside a menu, a card or a table nested in the cell sits on that
15
+ // surface's own background instead.
16
+ //
17
+ // A cell with a color of its own (`Td color="white"`) paints its own
18
+ // background over the row's, and so does every cell of a row with a color
19
+ // (`Tr color="white" isSelected`), which hands its color to its cells. Both
20
+ // are left out. Bulma colors those cells with custom properties alone, which
21
+ // a selector can't read, so the cells are named by class, one for each color
22
+ // Bulma makes them from: its `$colors` map, which its table's `$table-colors`
23
+ // is built from, custom colors included. A selected cell is the row's fill
24
+ // whatever its color, as Bulma paints it.
25
+ @mixin extras-selected-table-cell {
26
+ $colored: ();
27
+ @each $name, $color in dv.$colors {
28
+ $colored: list.append(
29
+ $colored,
30
+ '.#{iv.$class-prefix}is-#{$name}',
31
+ $separator: comma
32
+ );
33
+ }
34
+
35
+ .#{iv.$class-prefix}table {
36
+ tr.#{iv.$class-prefix}is-selected:not(#{$colored}) > td:not(#{$colored}),
37
+ tr.#{iv.$class-prefix}is-selected:not(#{$colored}) > th:not(#{$colored}),
38
+ td.#{iv.$class-prefix}is-selected,
39
+ th.#{iv.$class-prefix}is-selected {
40
+ @content;
41
+ }
42
+ }
43
+ }
@@ -25,3 +25,4 @@
25
25
  @use 'scrollarea';
26
26
  @use 'command';
27
27
  @use 'datatable';
28
+ @use 'pagination';
@@ -0,0 +1,25 @@
1
+ // Bestax Extras - Pagination Styles
2
+ // Bulma marks the current page link with a fill, a border color and a text
3
+ // color, and nothing else, and forced colors (Windows' contrast themes)
4
+ // replaces all three with the system's, so the current page looks like every
5
+ // other page there. This draws it in Highlight and HighlightText, the pair the
6
+ // system keeps for a selection, the way the themed Checkbox marks a checked
7
+ // box. `forced-color-adjust: none` keeps them. Outside forced colors it
8
+ // changes nothing.
9
+ //
10
+ // It reads the classes Bulma highlights, `is-current` and its other name
11
+ // `is-selected`, so a hand-written current link gets it too, and so does
12
+ // `DataTable`'s pager, which is a `Pagination`. Two classes outrank Bulma's
13
+ // colors for a link, wherever the two stylesheets load.
14
+
15
+ @use 'bulma/sass/utilities/initial-variables' as iv;
16
+
17
+ @media (forced-colors: active) {
18
+ .#{iv.$class-prefix}pagination-link.#{iv.$class-prefix}is-current,
19
+ .#{iv.$class-prefix}pagination-link.#{iv.$class-prefix}is-selected {
20
+ forced-color-adjust: none;
21
+ background-color: Highlight;
22
+ border-color: Highlight;
23
+ color: HighlightText;
24
+ }
25
+ }
@@ -76,7 +76,8 @@ $toast-action-hover-opacity: 0.1 !default;
76
76
  align-items: center;
77
77
  }
78
78
 
79
- // Bottom positions — column-reverse so newer toasts appear nearest the edge
79
+ // Bottom positions: column-reverse, so a stack grows up from the bottom
80
+ // edge as a top one grows down from the top, the first toast nearest it
80
81
  &.#{iv.$class-prefix}is-bottom-right {
81
82
  bottom: 0;
82
83
  right: 0;
@@ -2,11 +2,10 @@
2
2
  // Custom-styled checkbox with colors, sizes, and visual states
3
3
  // Follows Bulma v1 CSS variable convention (see _dialog.scss)
4
4
 
5
- @use "sass:list";
6
5
  @use "bulma/sass/utilities/initial-variables" as iv;
7
6
  @use "bulma/sass/utilities/css-variables" as cv;
8
- @use "bulma/sass/utilities/derived-variables" as dv;
9
7
  @use "bulma/sass/utilities/mixins" as mx;
8
+ @use "../selected-row" as *;
10
9
 
11
10
  // Bulma's horizontal field: `.field-label` takes one part of the row and
12
11
  // `.field-body` five, after the label's `margin-inline-end`. Private, since
@@ -165,9 +164,11 @@ $-check-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
165
164
  }
166
165
  }
167
166
 
168
- // Label text
167
+ // Label text. The gap is on the text's inline start, the side the box is
168
+ // on: the row mirrors on a right-to-left page, and a physical
169
+ // `margin-left` would stay on the far side and leave the text on the box.
169
170
  .#{iv.$class-prefix}control-label {
170
- margin-left: cv.getVar("checkbox-label-gap");
171
+ margin-inline-start: cv.getVar("checkbox-label-gap");
171
172
  line-height: 1.5;
172
173
  }
173
174
  }
@@ -194,44 +195,19 @@ $-check-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
194
195
  // read.
195
196
  //
196
197
  // Only a Checkbox placed straight in one of those cells sits on the row's
197
- // fill, so the rule names each step down to it rather than any checkbox
198
- // below the row. One inside a menu, a card or a table nested in the cell sits
199
- // on that surface's own background, and keeps its own colors there.
200
- //
201
- // A cell with a color of its own (`Td color="white"`) paints its own
202
- // background over the row's, and so does every cell of a row with a color
203
- // (`Tr color="white" isSelected`), which hands its color to its cells. Both
204
- // are left out, and a box there keeps its usual look. Bulma colors those cells with custom properties alone, which a
205
- // selector can't read, so the cells are named by class, one for each color
206
- // Bulma makes them from: its `$colors` map, which its table's
207
- // `$table-colors` is built from, custom colors included. A selected cell is
208
- // the row's fill whatever its color, as Bulma paints it.
209
- $-colored-cells: ();
210
- @each $name, $color in dv.$colors {
211
- $-colored-cells: list.append(
212
- $-colored-cells,
213
- ".#{iv.$class-prefix}is-#{$name}",
214
- $separator: comma
215
- );
216
- }
217
-
218
- .#{iv.$class-prefix}table {
219
- tr.#{iv.$class-prefix}is-selected:not(#{$-colored-cells})
220
- > td:not(#{$-colored-cells}),
221
- tr.#{iv.$class-prefix}is-selected:not(#{$-colored-cells})
222
- > th:not(#{$-colored-cells}),
223
- td.#{iv.$class-prefix}is-selected,
224
- th.#{iv.$class-prefix}is-selected {
225
- > .#{iv.$class-prefix}styled-checkbox {
226
- @include cv.register-vars(
227
- (
228
- "checkbox-border-color": #{cv.getVar("table-row-active-color")},
229
- "checkbox-active-color": #{cv.getVar("table-row-active-color")},
230
- "checkbox-indeterminate-color": #{cv.getVar("table-row-active-color")},
231
- "checkbox-check-color": #{cv.getVar("table-row-active-background-color")},
232
- )
233
- );
234
- }
198
+ // fill, and cells with a color of their own are left out, so a box in a
199
+ // menu, a nested table or a colored cell keeps its usual look. The mixin
200
+ // names the cells, and Radio's rule reads the same list.
201
+ @include extras-selected-table-cell {
202
+ > .#{iv.$class-prefix}styled-checkbox {
203
+ @include cv.register-vars(
204
+ (
205
+ "checkbox-border-color": #{cv.getVar("table-row-active-color")},
206
+ "checkbox-active-color": #{cv.getVar("table-row-active-color")},
207
+ "checkbox-indeterminate-color": #{cv.getVar("table-row-active-color")},
208
+ "checkbox-check-color": #{cv.getVar("table-row-active-background-color")},
209
+ )
210
+ );
235
211
  }
236
212
  }
237
213
 
@@ -284,11 +284,22 @@ $combobox-sizes: (
284
284
  }
285
285
  }
286
286
 
287
+ // A line between a group and whatever comes before it, and between a group
288
+ // and items with no group after it, which would otherwise read as the group's
289
+ // last items. It's a border, which forced colors keeps.
287
290
  .#{iv.$class-prefix}combobox-group:not(:first-child) {
288
291
  border-top: 1px solid cv.getVar('combobox-divider-color');
289
292
  margin-top: cv.getVar('combobox-item-padding-y');
290
293
  }
291
294
 
295
+ .#{iv.$class-prefix}combobox-group:has(
296
+ + :not(.#{iv.$class-prefix}combobox-group)
297
+ ) {
298
+ border-bottom: 1px solid cv.getVar('combobox-divider-color');
299
+ margin-bottom: cv.getVar('combobox-item-padding-y');
300
+ padding-bottom: cv.getVar('combobox-item-padding-y');
301
+ }
302
+
292
303
  .#{iv.$class-prefix}combobox-group-label {
293
304
  padding: cv.getVar('combobox-item-padding-y')
294
305
  cv.getVar('combobox-item-padding-x') 0.125rem;
@@ -5,6 +5,7 @@
5
5
  @use "bulma/sass/utilities/initial-variables" as iv;
6
6
  @use "bulma/sass/utilities/css-variables" as cv;
7
7
  @use "bulma/sass/utilities/mixins" as mx;
8
+ @use "../selected-row" as *;
8
9
 
9
10
  // Bulma's horizontal field: `.field-label` takes one part of the row and
10
11
  // `.field-body` five, after the label's `margin-inline-end`. Private, since
@@ -124,9 +125,12 @@ $radio-transition-duration: cv.getVar("duration") !default;
124
125
  }
125
126
  }
126
127
 
127
- // Label text
128
+ // Label text. The gap is on the text's inline start, the side the circle
129
+ // is on: the row mirrors on a right-to-left page, and a physical
130
+ // `margin-left` would stay on the far side and leave the text on the
131
+ // circle.
128
132
  .#{iv.$class-prefix}control-label {
129
- margin-left: cv.getVar("radio-label-gap");
133
+ margin-inline-start: cv.getVar("radio-label-gap");
130
134
  line-height: 1.5;
131
135
  }
132
136
  }
@@ -142,6 +146,28 @@ $radio-transition-duration: cv.getVar("duration") !default;
142
146
  }
143
147
  }
144
148
 
149
+ // On Bulma's selected table row (`Tr isSelected`, or a cell with
150
+ // `is-selected`), the row's fill is the same color a checked radio draws its
151
+ // ring and its dot in, so the radio would vanish into it. There the ring and
152
+ // the dot take the row's text color, as Checkbox's box does, and so does an
153
+ // unchecked ring. This outranks the color variants on purpose: the row's own
154
+ // pair is the one Bulma made to read on that fill.
155
+ //
156
+ // Only a Radio placed straight in one of those cells sits on the row's fill,
157
+ // and cells with a color of their own are left out, so a radio in a menu, a
158
+ // nested table or a colored cell keeps its usual look. The mixin names the
159
+ // cells, and Checkbox's rule reads the same list.
160
+ @include extras-selected-table-cell {
161
+ > .#{iv.$class-prefix}styled-radio {
162
+ @include cv.register-vars(
163
+ (
164
+ "radio-border-color": #{cv.getVar("table-row-active-color")},
165
+ "radio-active-color": #{cv.getVar("table-row-active-color")},
166
+ )
167
+ );
168
+ }
169
+ }
170
+
145
171
  // Size variants
146
172
  .#{iv.$class-prefix}styled-radio.#{iv.$class-prefix}is-small {
147
173
  font-size: cv.getVar("size-small");
@@ -131,19 +131,23 @@ $switch-thin-circle-size: 1.25em !default;
131
131
  }
132
132
  }
133
133
 
134
- // Label text
134
+ // Label text. The gap is on the text's inline start, the side the track
135
+ // is on: the row mirrors on a right-to-left page, and a physical
136
+ // `margin-left` would stay on the far side and leave the text on the
137
+ // track.
135
138
  .#{iv.$class-prefix}control-label {
136
- margin-left: cv.getVar("switch-label-gap");
139
+ margin-inline-start: cv.getVar("switch-label-gap");
137
140
  line-height: cv.getVar("switch-height");
138
141
  }
139
142
 
140
- // RTL support
143
+ // Label first: the reversed row puts the track on the text's inline end,
144
+ // in either page direction, so the gap moves there.
141
145
  &.#{iv.$class-prefix}is-rtl {
142
146
  flex-direction: row-reverse;
143
147
 
144
148
  .#{iv.$class-prefix}control-label {
145
- margin-left: 0;
146
- margin-right: cv.getVar("switch-label-gap");
149
+ margin-inline-start: 0;
150
+ margin-inline-end: cv.getVar("switch-label-gap");
147
151
  }
148
152
  }
149
153
  }
@@ -128,9 +128,13 @@ $taginput-transition-duration: cv.getVar("duration") !default;
128
128
  align-items: center;
129
129
  gap: cv.getVar("taginput-tag-gap");
130
130
 
131
+ // The remove button comes after the text, so its gap is on its inline
132
+ // start and it reaches into the tag's padding on its inline end, as
133
+ // Bulma's own tag does it. Physical margins put the gap on the far
134
+ // side on a right-to-left page, and the button on the text.
131
135
  .#{iv.$class-prefix}delete {
132
- margin-left: 0.25rem;
133
- margin-right: -0.25rem;
136
+ margin-inline-start: 0.25rem;
137
+ margin-inline-end: -0.25rem;
134
138
  }
135
139
  }
136
140
  }