bitboss-ui 3.0.0-beta.21 → 3.0.0-beta.22

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 (183) hide show
  1. package/README.md +55 -3
  2. package/bin/bitboss-ui-mcp.mjs +419 -9
  3. package/bin/bitboss-ui.mjs +293 -22
  4. package/dist/ai/BbAccordion.md +21 -23
  5. package/dist/ai/BbAlert.md +6 -12
  6. package/dist/ai/BbAvatar.md +60 -24
  7. package/dist/ai/BbBadge.md +12 -20
  8. package/dist/ai/BbBaseButton.md +14 -16
  9. package/dist/ai/BbBaseCheckboxIcon.md +6 -10
  10. package/dist/ai/BbBaseRadioIcon.md +6 -10
  11. package/dist/ai/BbBaseSwitchIcon.md +5 -9
  12. package/dist/ai/BbBreadcrumbs.md +23 -34
  13. package/dist/ai/BbButton.md +35 -47
  14. package/dist/ai/BbCheckbox.md +21 -37
  15. package/dist/ai/BbCheckboxGroup.md +13 -13
  16. package/dist/ai/BbCollapsible.md +14 -26
  17. package/dist/ai/BbColorInput.md +13 -23
  18. package/dist/ai/BbColorPalette.md +23 -35
  19. package/dist/ai/BbConfirm.md +17 -32
  20. package/dist/ai/BbDatePickerInput.md +15 -21
  21. package/dist/ai/BbDialog.md +159 -62
  22. package/dist/ai/BbDropdown.md +21 -25
  23. package/dist/ai/BbDropdownButton.md +13 -30
  24. package/dist/ai/BbDropzone.md +9 -11
  25. package/dist/ai/BbIcon.md +44 -33
  26. package/dist/ai/BbIndicator.md +2 -2
  27. package/dist/ai/BbNumberInput.md +18 -20
  28. package/dist/ai/BbOffCanvas.md +42 -42
  29. package/dist/ai/BbPagination.md +21 -23
  30. package/dist/ai/BbPopover.md +15 -17
  31. package/dist/ai/BbProgress.md +40 -51
  32. package/dist/ai/BbRadio.md +9 -9
  33. package/dist/ai/BbRadioGroup.md +7 -11
  34. package/dist/ai/BbRating.md +8 -12
  35. package/dist/ai/BbSelect.md +32 -36
  36. package/dist/ai/BbSelectPopover.md +19 -31
  37. package/dist/ai/BbSlider.md +15 -19
  38. package/dist/ai/BbSmoothHeight.md +16 -31
  39. package/dist/ai/BbSpinner.md +118 -74
  40. package/dist/ai/BbSwitch.md +25 -18
  41. package/dist/ai/BbSwitchGroup.md +9 -14
  42. package/dist/ai/BbTable.md +102 -55
  43. package/dist/ai/BbTabs.md +59 -82
  44. package/dist/ai/BbTag.md +12 -23
  45. package/dist/ai/BbTextInput.md +20 -26
  46. package/dist/ai/BbTextarea.md +28 -34
  47. package/dist/ai/BbToast.md +14 -34
  48. package/dist/ai/BbTooltip.md +22 -20
  49. package/dist/ai/BbTree.md +46 -72
  50. package/dist/ai/changelog.json +169 -62
  51. package/dist/ai/components.json +1467 -9
  52. package/dist/ai/composables/useConfirm.md +5 -2
  53. package/dist/ai/composables/useToast.md +4 -2
  54. package/dist/ai/guides/agent-contract.md +7 -4
  55. package/dist/ai/guides/ai-router.md +37 -22
  56. package/dist/ai/guides/component-picker.md +23 -18
  57. package/dist/ai/guides/design-language.md +141 -13
  58. package/dist/ai/guides/design-tokens.md +29 -4
  59. package/dist/ai/guides/icons-policy.md +46 -21
  60. package/dist/ai/guides/installation-and-plugin-setup.md +253 -17
  61. package/dist/ai/guides/migration/components/bb-rating.md +26 -1
  62. package/dist/ai/guides/migration/components/bb-tooltip.md +18 -0
  63. package/dist/ai/guides/migration/v2-to-v3.md +50 -23
  64. package/dist/ai/index.md +1 -1
  65. package/dist/ai/recipes/inertia/approvals-inbox.md +3 -3
  66. package/dist/ai/recipes/inertia/inline-edit-workspace.md +2 -2
  67. package/dist/ai/recipes/inertia/onboarding.md +2 -2
  68. package/dist/ai/recipes/inertia/ownership-atlas.md +6 -6
  69. package/dist/ai/recipes/inertia/record-form.md +5 -5
  70. package/dist/ai/recipes/inertia/records-workspace.md +4 -4
  71. package/dist/ai/recipes/inertia/upload-center.md +6 -6
  72. package/dist/ai/recipes/inertia/wizard-form.md +5 -5
  73. package/dist/ai/recipes/nuxt/approvals-inbox.md +3 -3
  74. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +2 -2
  75. package/dist/ai/recipes/nuxt/onboarding.md +2 -2
  76. package/dist/ai/recipes/nuxt/record-form.md +5 -5
  77. package/dist/ai/recipes/nuxt/records-workspace.md +4 -4
  78. package/dist/ai/recipes/nuxt/upload-center.md +6 -6
  79. package/dist/ai/recipes/nuxt/wizard-form.md +5 -5
  80. package/dist/ai/recipes/vue/approvals-inbox.md +3 -3
  81. package/dist/ai/recipes/vue/inline-edit-workspace.md +2 -2
  82. package/dist/ai/recipes/vue/onboarding.md +2 -2
  83. package/dist/ai/recipes/vue/record-form.md +10 -10
  84. package/dist/ai/recipes/vue/records-workspace.md +4 -4
  85. package/dist/ai/recipes/vue/upload-center.md +6 -6
  86. package/dist/ai/recipes/vue/wizard-form.md +5 -5
  87. package/dist/ai/source/BbBadge.md +1 -1
  88. package/dist/ai/source/BbBaseCheckbox.md +1 -1
  89. package/dist/ai/source/BbBaseDatePicker.md +5 -5
  90. package/dist/ai/source/BbBaseDatePickerInput.md +2 -2
  91. package/dist/ai/source/BbBaseRadio.md +1 -1
  92. package/dist/ai/source/BbBaseRating.md +5 -5
  93. package/dist/ai/source/BbBaseSelect.md +1 -1
  94. package/dist/ai/source/BbBaseSlider.md +5 -5
  95. package/dist/ai/source/BbBaseSwitch.md +1 -1
  96. package/dist/ai/source/BbBaseTimePickerInput.md +1 -1
  97. package/dist/ai/source/BbBreadcrumbs.md +20 -1
  98. package/dist/ai/source/BbButton.md +2 -2
  99. package/dist/ai/source/BbDialog.md +39 -8
  100. package/dist/ai/source/BbDropdown.md +1 -1
  101. package/dist/ai/source/BbDropzone.md +5 -5
  102. package/dist/ai/source/BbIcon.md +23 -10
  103. package/dist/ai/source/BbOffCanvas.md +50 -28
  104. package/dist/ai/source/BbPagination.md +2 -2
  105. package/dist/ai/source/BbPopover.md +12 -1
  106. package/dist/ai/source/BbSelectPopover.md +45 -7
  107. package/dist/ai/source/BbSpinner.md +2 -2
  108. package/dist/ai/source/BbTable.md +11 -11
  109. package/dist/ai/source/BbTooltip.md +57 -10
  110. package/dist/ai/source/ChipsBox.md +1 -1
  111. package/dist/ai/source/CommaBox.md +1 -1
  112. package/dist/ai/source/GuidesComponent.md +14 -7
  113. package/dist/ai/source/OptionsContainer.md +1 -1
  114. package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +1 -1
  115. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +1 -1
  116. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +1 -1
  117. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +4 -4
  118. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +1 -1
  119. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
  120. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +1 -1
  121. package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +1 -1
  122. package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +3 -3
  123. package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  124. package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +3 -3
  125. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +1 -1
  126. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
  127. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +71 -71
  128. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +2 -2
  129. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +102 -97
  130. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +1 -1
  131. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +58 -58
  132. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +2 -2
  133. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +33 -35
  134. package/dist/components/BbIcon/iconCache.d.ts +30 -0
  135. package/dist/components/BbIcon/iconCache.js +21 -3
  136. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +57 -56
  137. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +2 -2
  138. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +138 -138
  139. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +43 -43
  140. package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +1 -1
  141. package/dist/components/BbSpinner/types.d.ts +1 -1
  142. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +8 -8
  143. package/dist/components/BbTable/BbTableDataRow.js +2 -2
  144. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +62 -62
  145. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +81 -78
  146. package/dist/components/BbTooltip/types.d.ts +8 -1
  147. package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +1 -1
  148. package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +1 -1
  149. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +1 -1
  150. package/dist/composables/useConfirm.d.ts +22 -0
  151. package/dist/composables/useConfirm.js +43 -40
  152. package/dist/composables/useSafeAreaInternal.js +1 -1
  153. package/dist/composables/useToast.d.ts +16 -0
  154. package/dist/composables/useToast.js +20 -16
  155. package/dist/composables/useViewportWidth.d.ts +20 -6
  156. package/dist/composables/useViewportWidth.js +8 -7
  157. package/dist/icon-scan.d.ts +276 -0
  158. package/dist/icon-scan.js +485 -0
  159. package/dist/icons-whitelist.d.ts +5 -4
  160. package/dist/llms-full.txt +1979 -1527
  161. package/dist/llms-medium.txt +461 -74
  162. package/dist/llms.txt +1 -1
  163. package/dist/nuxt.js +10 -7
  164. package/dist/plugin.js +1 -0
  165. package/dist/runtime/nuxt-plugin.js +2 -1
  166. package/dist/styles.css +1 -1
  167. package/dist/types/Config.d.ts +18 -0
  168. package/dist/utils/cssLayers.d.ts +91 -0
  169. package/dist/utils/cssLayers.js +43 -0
  170. package/dist/utils/injectLibraryStyles.d.ts +3 -1
  171. package/dist/utils/injectLibraryStyles.js +24 -23
  172. package/dist/vite-plugin.d.ts +74 -11
  173. package/dist/vite.js +292 -253
  174. package/llms.txt +1 -1
  175. package/package.json +7 -5
  176. package/scripts/lib/ensure-manifest.mjs +28 -5
  177. package/scripts/lib/eslint-plugin.d.ts +35 -0
  178. package/scripts/lib/eslint-plugin.mjs +299 -3
  179. package/scripts/lib/hand-roll-hints.mjs +50 -6
  180. package/scripts/lib/html-attributes.mjs +42 -0
  181. package/scripts/lib/mcp-config.mjs +38 -34
  182. package/scripts/lib/public-type-exports.mjs +246 -0
  183. package/scripts/lib/validate-bb-markup.mjs +205 -12
@@ -1,3 +1,4 @@
1
+ import { CssLayersOption } from '../utils/cssLayers';
1
2
  import { Sizes } from './SizeScale';
2
3
  import { BbToastPosition } from '../components/BbToast/types';
3
4
  import { BuiltinLocaleKey, LocaleKey } from '../i18n';
@@ -37,6 +38,23 @@ export type EditableConfig = {
37
38
  locale: LocaleKey;
38
39
  injectStyles: boolean;
39
40
  resetCss: boolean;
41
+ /**
42
+ * Whether the library's own stylesheets are wrapped in CSS cascade layers,
43
+ * and where they sit in your app's layer order.
44
+ *
45
+ * The cascade weighs LAYER before SPECIFICITY, and unlayered CSS outranks
46
+ * every layered rule — so this is the switch that decides who wins a tie
47
+ * between your CSS and ours. See `cssLayers.ts` for the full matrix.
48
+ *
49
+ * Unset (the default) — unlayered, as before. Set it to your app's COMPLETE
50
+ * layer order with `bitboss-ui` in it — and `bitboss-ui-reset` before it
51
+ * when `resetCss` is on (listing it anyway is fine): `TAILWIND_V4_LAYERS`
52
+ * (exported from `bitboss-ui/vite`) for Tailwind v4, or just
53
+ * `['bitboss-ui']` to put the library below all of your CSS. Opt-in; there
54
+ * is no boolean form — `true` used to declare only our layers, which put
55
+ * Tailwind's `base` above the components.
56
+ */
57
+ cssLayers: CssLayersOption | undefined;
40
58
  injectDirectives: boolean;
41
59
  /**
42
60
  * When `true`, form controls render a red asterisk next to the label/legend
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Cascade-layer support for the library's own stylesheets.
3
+ *
4
+ * WHY THIS EXISTS — the cascade compares LAYER before SPECIFICITY, and
5
+ * unlayered CSS outranks every layered rule. That single fact makes one fixed
6
+ * choice wrong for everybody:
7
+ *
8
+ * | library | consumer app | who wins |
9
+ * | --------- | ------------------- | ----------------------------------------- |
10
+ * | unlayered | layered (Tailwind 4)| WE do, per PROPERTY — see the note below |
11
+ * | layered | unlayered | THEY do — a bare `button {}` outranks us |
12
+ * | unlayered | unlayered | source order decides |
13
+ * | layered | layered | layer order decides — predictable |
14
+ *
15
+ * PER PROPERTY, not per component: a layered utility loses only where we declare
16
+ * that exact property on that element. `w-20` on a BbButton applies (we never
17
+ * set `width`); `px-6` does not (we set both padding longhands); and `p-4` HALF
18
+ * applies, because the shorthand's vertical longhands are uncontested while the
19
+ * horizontal ones lose. The half-state is the argument for layers: the fix buys
20
+ * predictability, not capability.
21
+ *
22
+ * The library ships a static stylesheet and cannot inspect the app's CSS, so
23
+ * there is no honest auto-detection. The app declares its order instead, via
24
+ * the `cssLayers` option — and it is opt-in (owner ruling, 2026-09-10).
25
+ *
26
+ * WHY AN ARRAY AND NOTHING ELSE. The first cut also took `false` and `true`.
27
+ * `false` said nothing that leaving the option out did not. `true` was worse:
28
+ * it declared only our two layers, so in the one app we build for — Tailwind
29
+ * v4 — Tailwind's `base` was appended AFTER ours and Preflight outranked every
30
+ * component. An order is the only value that is true in every case, so it is
31
+ * the only value accepted; "put us below all of your CSS" is spelled as the
32
+ * two-name array, which is honest about what it does.
33
+ */
34
+ /** The layer the component stylesheet is wrapped in. */
35
+ export declare const BB_LAYER = "bitboss-ui";
36
+ /** The layer `reset.css` is wrapped in. Always below `BB_LAYER`. */
37
+ export declare const BB_RESET_LAYER = "bitboss-ui-reset";
38
+ /**
39
+ * The two layers the library can emit, lowest first. Every `cssLayers` order
40
+ * must list `bitboss-ui`; `bitboss-ui-reset` is required only when `resetCss`
41
+ * is on, because that is the only time a reset sheet exists to sit in it. An
42
+ * order that lists it anyway is fine — an unused layer is just an empty layer —
43
+ * so `TAILWIND_V4_LAYERS` works in a project with no reset of its own without
44
+ * the author having to know that Tailwind carries one.
45
+ *
46
+ * As a `cssLayers` value on its own it means "below ALL of the app's CSS":
47
+ * every unlayered rule the app writes then outranks the library, whatever its
48
+ * specificity. Right for a plain-CSS app that wants to override freely; wrong
49
+ * for a layered app, whose own layers land after ours (see the trace in
50
+ * `library-only.test.ts`).
51
+ */
52
+ export declare const BB_LAYERS: readonly ["bitboss-ui-reset", "bitboss-ui"];
53
+ /**
54
+ * Tailwind v4's own order (`@import 'tailwindcss'` declares `theme, base,
55
+ * components, utilities`) with ours in the one position that works: after
56
+ * `base`, so Preflight cannot outrank the components, and before
57
+ * `utilities`, so `<BbButton class="px-6">` still wins. Exported so an app
58
+ * can write `cssLayers: TAILWIND_V4_LAYERS` instead of a six-item literal that
59
+ * has to be exactly right — a typo there loses every tie without a symptom.
60
+ */
61
+ export declare const TAILWIND_V4_LAYERS: readonly ["theme", "base", "bitboss-ui-reset", "bitboss-ui", "components", "utilities"];
62
+ /**
63
+ * The app's complete cascade-layer order, ours included. Leave it unset for an
64
+ * unlayered sheet (the default).
65
+ */
66
+ export type CssLayersOption = readonly string[];
67
+ export interface ResolvedCssLayers {
68
+ /** `@layer …;` to emit before any rule, or `''` when unlayered. */
69
+ order: string;
70
+ /** Wraps the component stylesheet; identity when unlayered. */
71
+ wrapStyles: (css: string) => string;
72
+ /** Wraps `reset.css`; identity when unlayered. */
73
+ wrapReset: (css: string) => string;
74
+ }
75
+ /**
76
+ * Build the layer declaration and the two wrappers for a `cssLayers` value.
77
+ *
78
+ * Never throws: an order that omits our layers is reported once and replaced
79
+ * by our own two, because a mis-typed layer name must not blank an app's
80
+ * stylesheet. The build-time validator in the Vite plugin is the loud one.
81
+ */
82
+ export declare const resolveCssLayers: (cssLayers?: CssLayersOption, { resetCss }?: {
83
+ resetCss?: boolean;
84
+ }) => ResolvedCssLayers;
85
+ /**
86
+ * Build-time validation, shared by the Vite plugin and the Nuxt module. Returns
87
+ * an error message, or `null` when the value is usable.
88
+ */
89
+ export declare const validateCssLayers: (cssLayers: unknown, { resetCss }?: {
90
+ resetCss?: boolean;
91
+ }) => string | null;
@@ -0,0 +1,43 @@
1
+ //#region src/utils/cssLayers.ts
2
+ var e = "bitboss-ui", t = "bitboss-ui-reset", n = [t, e], r = [
3
+ "theme",
4
+ "base",
5
+ t,
6
+ e,
7
+ "components",
8
+ "utilities"
9
+ ], i = (e) => e, a = {
10
+ order: "",
11
+ wrapStyles: i,
12
+ wrapReset: i
13
+ }, o = /@property\s+--[\w-]+\s*\{[^{}]*\}/g, s = (e) => (t) => {
14
+ if (!t.trim()) return t;
15
+ let n = t.match(o) ?? [], r = n.length ? t.replace(o, "") : t;
16
+ return `${n.join("\n")}${n.length ? "\n" : ""}@layer ${e} {\n${r}\n}\n`;
17
+ }, c = (e) => e.map((e) => `'${e}'`).join(", "), l = (t) => t ? n : [e], u = (n, { resetCss: i = !1 } = {}) => {
18
+ if (!n || n.length === 0) return a;
19
+ let o = n, u = l(i), d = u.filter((e) => !n.includes(e));
20
+ return d.length && (console.error(`[bitboss-ui] cssLayers is missing ${d.map((e) => `"${e}"`).join(" and ")}. List every layer your app uses, ours included, e.g. cssLayers: [${c(r)}]. Falling back to [${c(u)}], which puts the library below all of your CSS.`), o = u), {
21
+ order: `@layer ${o.join(", ")};\n`,
22
+ wrapStyles: s(e),
23
+ wrapReset: s(t)
24
+ };
25
+ }, d = (i, { resetCss: a = !1 } = {}) => {
26
+ if (i === void 0) return null;
27
+ if (typeof i == "boolean") return `[bitboss-ui] cssLayers no longer takes a boolean.
28
+ Leave it unset for an unlayered sheet (the default).
29
+ To put the library below ALL of your CSS, list just our two layers:
30
+ cssLayers: [${c(n)}]\n To place it among your own layers, list your complete order with ours in it — for Tailwind v4:\n cssLayers: [${c(r)}] // or import TAILWIND_V4_LAYERS from 'bitboss-ui/vite'`;
31
+ if (!Array.isArray(i)) return `[bitboss-ui] cssLayers must be an array of layer names, received ${typeof i}.`;
32
+ if (i.length === 0) return `[bitboss-ui] cssLayers is an empty array. Leave it unset for an unlayered sheet, or list an order that includes ${c(n)}.`;
33
+ let o = i.filter((e) => typeof e != "string" || !/^[\w-]+$/.test(e));
34
+ if (o.length) return `[bitboss-ui] cssLayers contains invalid layer name(s): ${o.map((e) => JSON.stringify(e)).join(", ")}. A layer name is a CSS identifier — letters, digits, - and _.`;
35
+ let s = i.filter((e, t) => i.indexOf(e) !== t);
36
+ if (s.length) return `[bitboss-ui] cssLayers lists ${[...new Set(s)].map((e) => `"${e}"`).join(", ")} more than once — a layer's position is set by its FIRST mention, so the later one does nothing.`;
37
+ let u = l(a).filter((e) => !i.includes(e));
38
+ if (u.length) return `[bitboss-ui] cssLayers does not list ${u.map((e) => `"${e}"`).join(" or ")}, so the library's own CSS would have no position in the order you declared.\n For Tailwind v4:\n cssLayers: [${c(r)}] // or import TAILWIND_V4_LAYERS from 'bitboss-ui/vite'\n Ours belong after 'base' (so Preflight cannot outrank the components) and before 'utilities' (so a utility can still restyle them).` + (a ? `\n '${t}' is required because resetCss is on.` : `\n '${t}' is optional while resetCss is off — listing it anyway is fine.`);
39
+ let d = i.indexOf(t), f = i.indexOf(e);
40
+ return d !== -1 && d > f ? `[bitboss-ui] cssLayers puts "${t}" after "${e}", so the reset would outrank the component styles it is meant to sit under. Swap them.` : null;
41
+ };
42
+ //#endregion
43
+ export { e as BB_LAYER, n as BB_LAYERS, t as BB_RESET_LAYER, r as TAILWIND_V4_LAYERS, u as resolveCssLayers, d as validateCssLayers };
@@ -1,6 +1,8 @@
1
- export declare const injectLibraryStyles: ({ injectStyles, resetCss, resetCssStyles, stylesCss, }: {
1
+ import { CssLayersOption } from './cssLayers';
2
+ export declare const injectLibraryStyles: ({ injectStyles, resetCss, resetCssStyles, stylesCss, cssLayers, }: {
2
3
  injectStyles: boolean;
3
4
  resetCss: boolean;
4
5
  resetCssStyles: string;
5
6
  stylesCss: string;
7
+ cssLayers?: CssLayersOption;
6
8
  }) => void;
@@ -1,38 +1,39 @@
1
+ import { resolveCssLayers as e } from "./cssLayers.js";
1
2
  //#region src/utils/injectLibraryStyles.ts
2
- var e = () => Array.from(document.head.querySelectorAll("style, link[rel=\"stylesheet\"]")), t = (t) => {
3
- let n = e();
4
- return t ? n.find((e) => e !== t) ?? null : n[0] ?? null;
5
- }, n = (e, t) => {
3
+ var t = "bitboss-ui-reset-css", n = "bitboss-ui-styles-css", r = "style, link[rel=\"stylesheet\"]", i = () => Array.from(document.head.querySelectorAll(r)), a = (e) => {
4
+ let t = i();
5
+ return e ? t.find((t) => t !== e) ?? null : t[0] ?? null;
6
+ }, o = (e, t) => {
6
7
  let n = document.getElementById(e);
7
8
  if (n instanceof HTMLStyleElement) return n.textContent !== t && (n.textContent = t), n;
8
9
  n?.remove();
9
10
  let r = document.createElement("style");
10
11
  return r.id = e, r.setAttribute("data-bitboss-ui", e), r.textContent = t, r;
11
- }, r = (e) => {
12
- let n = t(e);
13
- n ? document.head.insertBefore(e, n) : document.head.append(e);
14
- }, i = (t, n) => {
15
- let i = e().filter((e) => e !== t), a = i.indexOf(n);
16
- if (a === -1) {
17
- r(t);
12
+ }, s = (e) => {
13
+ let t = a(e);
14
+ t ? document.head.insertBefore(e, t) : document.head.append(e);
15
+ }, c = (e, t) => {
16
+ let n = i().filter((t) => t !== e), r = n.indexOf(t);
17
+ if (r === -1) {
18
+ s(e);
18
19
  return;
19
20
  }
20
- let o = i[a + 1];
21
- if (o) {
22
- document.head.insertBefore(t, o);
21
+ let a = n[r + 1];
22
+ if (a) {
23
+ document.head.insertBefore(e, a);
23
24
  return;
24
25
  }
25
- document.head.append(t);
26
- }, a = ({ injectStyles: e, resetCss: t, resetCssStyles: a, stylesCss: o }) => {
26
+ document.head.append(e);
27
+ }, l = ({ injectStyles: r, resetCss: i, resetCssStyles: a, stylesCss: l, cssLayers: u }) => {
27
28
  if (typeof document > "u") return;
28
- let s;
29
- if (t && a && (s = n("bitboss-ui-reset-css", a), r(s)), !e || !o) return;
30
- let c = n("bitboss-ui-styles-css", o);
31
- if (s) {
32
- i(c, s);
29
+ let d = e(u, { resetCss: i }), f;
30
+ if (i && a && (f = o(t, d.order + d.wrapReset(a)), s(f)), !r || !l) return;
31
+ let p = o(n, d.order + d.wrapStyles(l));
32
+ if (f) {
33
+ c(p, f);
33
34
  return;
34
35
  }
35
- r(c);
36
+ s(p);
36
37
  };
37
38
  //#endregion
38
- export { a as injectLibraryStyles };
39
+ export { l as injectLibraryStyles };
@@ -12,22 +12,29 @@
12
12
  /// <reference path="./locale-registry.d.ts" />
13
13
  /// <reference path="./toast-variants.d.ts" />
14
14
  /// <reference path="./tooltip-variants.d.ts" />
15
+ import { IconsScannerOptions } from './icon-scan';
15
16
  import { Plugin } from 'vite';
17
+ import { IconifyJSON } from '@iconify/types';
16
18
  import { EditableConfig, ResolvedConfig } from './types/Config';
17
19
  import { BUILTIN_LOCALE_KEYS } from './i18n';
20
+ import { CssLayersOption } from './utils/cssLayers';
21
+ export { DEFAULT_MAX_FILE_SIZE, IconScanner, extractIconCandidates, iconLiteralRegExp, iconScanCacheFile, } from './icon-scan';
22
+ export type { IconsScannerOptions, ScanStats } from './icon-scan';
23
+ export { BB_LAYERS, TAILWIND_V4_LAYERS, type CssLayersOption, } from './utils/cssLayers';
24
+ type DiagnoseFn = (key: string, loaded: Set<string>, known: (prefix: string) => string[], all: (prefix: string) => string[] | null, ip: Set<string>) => string | null;
25
+ /** The diagnosis, as a callable, for the Node side (whitelist validation). */
26
+ export declare const diagnoseMissingIcon: DiagnoseFn;
18
27
  /**
19
- * Source files under `root`, PRUNING excluded directories as it walks.
20
- *
21
- * `readdirSync(root, { recursive: true })` does not prune: it enumerates the
22
- * entire tree `node_modules`, `vendor`, `.git` and alland only then lets
23
- * the caller filter. On this repo that is over two minutes; the same walk with
24
- * the same exclusions applied DURING the descent is 41ms. It runs on every
25
- * production build of every consumer, so the difference is not academic.
26
- *
27
- * Still synchronous: at tens of milliseconds it no longer justifies the
28
- * complexity of an async walk inside a hook that already awaits elsewhere.
28
+ * Expand `iconWhitelist` into concrete `prefix:name` entries. Exact names must
29
+ * resolve; a glob (`tabler:calendar-*`) expands to every matching name of the
30
+ * set and must match at least one. Anything else is an error carrying the same
31
+ * message the dev overlay shows for a missing icon a whitelist entry that
32
+ * cannot ship is a typo, and a typo fails the build.
29
33
  */
30
- export declare function collectSourceFiles(root: string): string[];
34
+ export declare function expandIconWhitelist(whitelist: readonly string[], providerData: ReadonlyMap<string, IconifyJSON>, providerFilter: ReadonlyMap<string, (key: string) => boolean>, iconifyPrefixes: ReadonlySet<string>): {
35
+ icons: string[];
36
+ errors: string[];
37
+ };
31
38
  export { BUILTIN_LOCALE_KEYS };
32
39
  /**
33
40
  * Resolves the built-in locales that actually ship in the consumer bundle.
@@ -148,6 +155,30 @@ export interface BitbossUiOptions extends Partial<EditableConfig> {
148
155
  * @defaultValue `'./assets/icons'` — same convention as the Nuxt module
149
156
  */
150
157
  iconDir?: string;
158
+ /**
159
+ * Tunes the provider-icon source scan. Every file under the Vite root is
160
+ * read as bytes for `<prefix>:<name>` literals of the installed
161
+ * `@iconify-json/*` sets — PHP, Blade, JSON, SQL, Markdown included — except
162
+ * what `.gitignore` ignores, `node_modules`, `vendor`, `storage`, the build
163
+ * `outDir`, hidden paths, binaries and files over `maxFileSize`. The same
164
+ * scan decides what ships in production AND what resolves in dev.
165
+ *
166
+ * - `include`: extra paths or globs scanned in addition to the root
167
+ * (a vendor package, a directory outside the root). Additive.
168
+ * - `exclude`: globs removed from the scan, on top of the defaults.
169
+ * - `maxFileSize`: bytes; only there to keep database dumps out of memory.
170
+ * Default 256 MiB — a real source file is never skipped for its size.
171
+ */
172
+ iconsScanner?: IconsScannerOptions;
173
+ /**
174
+ * Provider icons that ALWAYS ship, scanned or not: exact names
175
+ * (`'tabler:crown'`) and globs (`'tabler:calendar-*'`). This is the home of
176
+ * every name the scanner cannot see as a literal — composed at runtime,
177
+ * stored in a database, chosen by an admin. An entry that resolves in no
178
+ * installed set fails the build with the same message the dev overlay
179
+ * shows for a missing icon.
180
+ */
181
+ iconWhitelist?: string[];
151
182
  /**
152
183
  * When `true`, the dev server registers the bitboss-ui MCP server in each
153
184
  * project-scoped agent-harness config on boot (`.mcp.json` for Claude Code,
@@ -192,6 +223,38 @@ export interface BitbossUiOptions extends Partial<EditableConfig> {
192
223
  * @defaultValue `false`
193
224
  */
194
225
  resetCss?: boolean;
226
+ /**
227
+ * Wrap the library's stylesheets in CSS cascade layers, and say where they
228
+ * sit in your app's layer order.
229
+ *
230
+ * This is the switch that decides who wins a tie between your CSS and ours,
231
+ * because the cascade weighs LAYER before SPECIFICITY: unlayered CSS beats
232
+ * every layered rule no matter how specific the layered one is.
233
+ *
234
+ * Unset (the default) — unlayered. Correct when your app has no layers.
235
+ * Otherwise your COMPLETE layer order, our two layers included:
236
+ *
237
+ * ```ts
238
+ * import { bitbossUi, TAILWIND_V4_LAYERS } from 'bitboss-ui/vite';
239
+ * // Tailwind v4 — ours after `base`, before `utilities`
240
+ * bitbossUi({ cssLayers: TAILWIND_V4_LAYERS })
241
+ * // plain CSS, and you want to override anything: ours below all of yours
242
+ * bitbossUi({ cssLayers: ['bitboss-ui-reset', 'bitboss-ui'] })
243
+ * ```
244
+ *
245
+ * `bitboss-ui` is always required; `bitboss-ui-reset` only when `resetCss`
246
+ * is on. Listing it anyway is fine (an unused layer is just empty), so the
247
+ * constant works whether or not you use our reset. There is no boolean
248
+ * form: `true` used to declare only our layers, which put Tailwind's `base`
249
+ * above the components.
250
+ *
251
+ * You do NOT also add an `@layer …;` line to your CSS — the plugin injects
252
+ * the declaration ahead of its own rules, and a layer's position is fixed by
253
+ * its first mention.
254
+ *
255
+ * A malformed value fails the build with a message naming the fix.
256
+ */
257
+ cssLayers?: CssLayersOption;
195
258
  /**
196
259
  * When enabled, registers the library's global directives (`v-bb-tooltip`,
197
260
  * `v-bb-dropdown`, `v-bb-color`, `v-bb-date`, `v-bb-time`) when the plugin is