bitboss-ui 3.0.0-alpha.6 → 3.0.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/bitboss-ui.mjs +0 -123
- package/dist/ai/BbBaseRating.md +1 -0
- package/dist/ai/BbDatePickerInput.md +7 -3
- package/dist/ai/BbNumberInput.md +5 -2
- package/dist/ai/BbTextInput.md +5 -3
- package/dist/ai/BbTextarea.md +5 -3
- package/dist/ai/BbToast.md +3 -1
- package/dist/ai/changelog.json +1 -1
- package/dist/ai/components.json +66 -7
- package/dist/ai/guides/agent-contract.md +3 -4
- package/dist/ai/guides/component-picker.md +7 -8
- package/dist/ai/guides/installation-and-plugin-setup.md +15 -54
- package/dist/ai/guides/migration/components/bb-intersection.md +70 -0
- package/dist/ai/guides/migration/components/bb-tooltip.md +32 -7
- package/dist/ai/guides/migration/components/use-broadcast-channel-instance.md +56 -0
- package/dist/ai/guides/migration/components/use-confirm.md +18 -10
- package/dist/ai/guides/migration/v2-to-v3.md +13 -1
- package/dist/ai/guides/validated-forms.md +18 -4
- package/dist/ai/index.md +3 -2
- package/dist/ai/source/BbBadge.md +28 -1
- package/dist/ai/source/BbBaseRadioIcon.md +1 -1
- package/dist/ai/source/BbBaseRating.md +36 -2
- package/dist/ai/source/BbBaseSelect.md +33 -4
- package/dist/ai/source/BbBaseSwitchIcon.md +6 -2
- package/dist/ai/source/BbIndicator.md +15 -1
- package/dist/ai/source/BbRating.md +14 -1
- package/dist/ai/source/BbToast.md +10 -4
- package/dist/ai/source/BbToastPortal.md +10 -4
- package/dist/ai/source/BbTooltip.md +11 -2
- package/dist/ai/source/ChipsBox.md +24 -0
- package/dist/ai/source/CommaBox.md +16 -0
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +56 -48
- package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +33 -25
- package/dist/components/BbBaseRating/types.d.ts +8 -0
- package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +35 -32
- package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +28 -26
- package/dist/components/BbTooltip/BbTooltip.vue.d.ts +1 -1
- package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +64 -61
- package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +62 -59
- package/dist/composables/useConfirm.js +6 -4
- package/dist/composables/useLocale.js +2 -2
- package/dist/composables/useToast.js +37 -33
- package/dist/deprecation/ai-deprecations.json.d.ts +44 -0
- package/dist/deprecation/ai-deprecations.json.js +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +50 -51
- package/dist/llms-full.txt +261 -197
- package/dist/llms-medium.txt +25 -66
- package/dist/llms.txt +3 -2
- package/dist/styles.css +1 -1
- package/dist/types/Config.d.ts +8 -17
- package/dist/validated/useValidatedField.js +19 -19
- package/dist/vite-plugin.d.ts +3 -25
- package/dist/vite.js +116 -158
- package/llms.txt +3 -2
- package/package.json +5 -5
- package/scripts/lib/hand-roll-hints.mjs +29 -24
- package/scripts/lib/validate-bb-markup.mjs +118 -1
- package/dist/ai/composables/useBroadcastChannelInstance.md +0 -97
- package/dist/composables/useBroadcastChannelInstance.d.ts +0 -14
- package/dist/composables/useBroadcastChannelInstance.js +0 -39
package/bin/bitboss-ui.mjs
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* - .windsurf/rules/bitboss-ui.md (Windsurf)
|
|
14
14
|
* Accepts an optional --mcp flag (combinable with --update) to also
|
|
15
15
|
* register the `bitboss-ui mcp` server in .mcp.json.
|
|
16
|
-
* locale Generate a custom locale blueprint (.locale.ts)
|
|
17
16
|
* check Validate Bb* markup in .vue/.md files against the installed
|
|
18
17
|
* components.json manifest (unknown props, removed props, bad
|
|
19
18
|
* v-models, unknown `<template #slot>` names, `href`/`to`/
|
|
@@ -36,7 +35,6 @@ import {
|
|
|
36
35
|
writeFileSync,
|
|
37
36
|
} from 'node:fs';
|
|
38
37
|
import { findHandRollHints } from '../scripts/lib/hand-roll-hints.mjs';
|
|
39
|
-
import { createRequire } from 'node:module';
|
|
40
38
|
import { dirname, isAbsolute, join, relative } from 'node:path';
|
|
41
39
|
import { fileURLToPath } from 'node:url';
|
|
42
40
|
import { parseArgs } from 'node:util';
|
|
@@ -285,112 +283,6 @@ function aiInit({ mcp = false } = {}) {
|
|
|
285
283
|
}
|
|
286
284
|
}
|
|
287
285
|
|
|
288
|
-
/**
|
|
289
|
-
* Serialize the blueprint dictionary as a readable TS object literal
|
|
290
|
-
* (single-quoted, tab-indented, matching the library's own locale files).
|
|
291
|
-
*/
|
|
292
|
-
function localeObjectLiteral(dictionary) {
|
|
293
|
-
const quote = (s) =>
|
|
294
|
-
`'${String(s).replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
295
|
-
const sections = Object.entries(dictionary)
|
|
296
|
-
.map(([section, entries]) => {
|
|
297
|
-
const lines = Object.entries(entries)
|
|
298
|
-
.map(([key, value]) => `\t\t${key}: ${quote(value)},`)
|
|
299
|
-
.join('\n');
|
|
300
|
-
return `\t${section}: {\n${lines}\n\t},`;
|
|
301
|
-
})
|
|
302
|
-
.join('\n');
|
|
303
|
-
return `{\n${sections}\n}`;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function localeBlueprint(key) {
|
|
307
|
-
const projectRoot = process.cwd();
|
|
308
|
-
|
|
309
|
-
if (!key) {
|
|
310
|
-
console.error(
|
|
311
|
-
'[bitboss-ui] Usage: npx bitboss-ui locale <key> (e.g. `npx bitboss-ui locale nl`)'
|
|
312
|
-
);
|
|
313
|
-
process.exit(1);
|
|
314
|
-
}
|
|
315
|
-
// Keys double as dayjs module names (`dayjs/locale/<key>`) — keep them tame.
|
|
316
|
-
if (!/^[a-z0-9-]+$/.test(key)) {
|
|
317
|
-
console.error(
|
|
318
|
-
`[bitboss-ui] Invalid locale key '${key}' — use lowercase letters, digits and dashes (it doubles as the dayjs locale name, e.g. 'nl', 'ja', 'zh-cn').`
|
|
319
|
-
);
|
|
320
|
-
process.exit(1);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const blueprintPath = join(PACKAGE_ROOT, 'dist', 'locale-blueprint.json');
|
|
324
|
-
if (!existsSync(blueprintPath)) {
|
|
325
|
-
console.error(
|
|
326
|
-
'[bitboss-ui] dist/locale-blueprint.json not found in the installed package — reinstall bitboss-ui (or run `npm run build` when working in the library repo).'
|
|
327
|
-
);
|
|
328
|
-
process.exit(1);
|
|
329
|
-
}
|
|
330
|
-
const { builtins, template } = JSON.parse(
|
|
331
|
-
readFileSync(blueprintPath, 'utf-8')
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
if (builtins.includes(key)) {
|
|
335
|
-
console.error(
|
|
336
|
-
`[bitboss-ui] '${key}' is a built-in locale — built-ins cannot be overridden; the \`additionalLocales\` option only adds new ones. Just set \`locale: '${key}'\`.`
|
|
337
|
-
);
|
|
338
|
-
process.exit(1);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
const outPath = join(projectRoot, `${key}.locale.ts`);
|
|
342
|
-
if (existsSync(outPath)) {
|
|
343
|
-
console.error(
|
|
344
|
-
`[bitboss-ui] ${key}.locale.ts already exists — delete it first if you want a fresh blueprint.`
|
|
345
|
-
);
|
|
346
|
-
process.exit(1);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Same check the vite plugin performs at build time — surface it here too,
|
|
350
|
-
// while the consumer is still choosing the key.
|
|
351
|
-
let dayjsHint = `Calendar (dayjs) locale '${key}' found — calendars will follow automatically.`;
|
|
352
|
-
try {
|
|
353
|
-
// Consumer's own resolution first; fall back to the installed package's
|
|
354
|
-
// (dayjs is a bitboss-ui dependency, so it's always reachable from here).
|
|
355
|
-
try {
|
|
356
|
-
createRequire(join(projectRoot, 'package.json')).resolve(
|
|
357
|
-
`dayjs/locale/${key}.js`
|
|
358
|
-
);
|
|
359
|
-
} catch {
|
|
360
|
-
createRequire(join(PACKAGE_ROOT, 'package.json')).resolve(
|
|
361
|
-
`dayjs/locale/${key}.js`
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
} catch {
|
|
365
|
-
dayjsHint = `⚠ dayjs ships no locale named '${key}' — calendars will fall back to English (the vite plugin repeats this warning at build time). If a nearby dayjs name exists (e.g. 'zh-cn', 'pt-br'), prefer it as your key: https://github.com/iamkun/dayjs/tree/dev/src/locale`;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
writeFileSync(
|
|
369
|
-
outPath,
|
|
370
|
-
`import type { LocaleOverrides } from 'bitboss-ui';
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* bitboss-ui locale blueprint for '${key}' — generated by \`npx bitboss-ui locale ${key}\`.
|
|
374
|
-
*
|
|
375
|
-
* Translate the English strings below ({0}/{1} placeholders are interpolated
|
|
376
|
-
* arguments — keep them). Keys you delete fall back per-key to the library's
|
|
377
|
-
* default locale. Register it in your vite config:
|
|
378
|
-
*
|
|
379
|
-
* import ${key.replace(/-/g, '_')} from './${key}.locale';
|
|
380
|
-
* bitbossUi({ iconDir: '...', locale: '${key}', additionalLocales: { '${key}': ${key.replace(/-/g, '_')} } })
|
|
381
|
-
*
|
|
382
|
-
* The plugin regenerates \`locale-registry.d.ts\` on build start, making
|
|
383
|
-
* '${key}' a valid \`locale\` value everywhere (run dev once after adding it).
|
|
384
|
-
*/
|
|
385
|
-
export default ${localeObjectLiteral(template)} satisfies LocaleOverrides;
|
|
386
|
-
`,
|
|
387
|
-
'utf-8'
|
|
388
|
-
);
|
|
389
|
-
|
|
390
|
-
console.log(`[bitboss-ui] Wrote ${key}.locale.ts (English blueprint).`);
|
|
391
|
-
console.log(` ${dayjsHint}`);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
286
|
// SNT-007: a bare-segment skip list of `node_modules`/`dist`/`.git` let a
|
|
395
287
|
// default (no-glob) `check` sweep straight through a Laravel-style consumer's
|
|
396
288
|
// `vendor/`, `storage/`, and `public/` trees — hundreds of vendored
|
|
@@ -724,9 +616,6 @@ Commands:
|
|
|
724
616
|
mcp Start a stdio MCP server exposing the dist/ai knowledge
|
|
725
617
|
base (search_components, get_component, list_recipes,
|
|
726
618
|
get_recipe, validate) to MCP-capable agent harnesses.
|
|
727
|
-
locale <key> Generate <key>.locale.ts at the project root — an English
|
|
728
|
-
blueprint dictionary to translate and pass to the plugin's
|
|
729
|
-
\`additionalLocales\` option (additions only; built-ins are refused).
|
|
730
619
|
help Show this help.
|
|
731
620
|
`);
|
|
732
621
|
}
|
|
@@ -804,18 +693,6 @@ switch (command) {
|
|
|
804
693
|
await main();
|
|
805
694
|
break;
|
|
806
695
|
}
|
|
807
|
-
case 'locale': {
|
|
808
|
-
const { positionals } = parseCommandArgs(
|
|
809
|
-
command,
|
|
810
|
-
commandArgs,
|
|
811
|
-
{},
|
|
812
|
-
{
|
|
813
|
-
allowPositionals: true,
|
|
814
|
-
}
|
|
815
|
-
);
|
|
816
|
-
localeBlueprint(positionals[0]);
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
696
|
case 'help':
|
|
820
697
|
case '--help':
|
|
821
698
|
case '-h':
|
package/dist/ai/BbBaseRating.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
| Prop | Type | Default | Required | Description |
|
|
18
18
|
| --- | --- | --- | --- | --- |
|
|
19
19
|
| `ariaDescribedby` | `string \| undefined` | | | Id(s) of elements describing this rating input for assistive technologies. |
|
|
20
|
+
| `ariaLabelledby` | `string \| undefined` | | | Id(s) of the element(s) that NAME this rating group. Supplying one is what promotes the inner container to `role="radiogroup"` (Q4.5): an unnamed `radiogroup` announces as a bare "radio group" and is no better than the role-less `<span>` it… |
|
|
20
21
|
| `autofocus` | `Booleanish \| undefined` | | | Sets autofocus on page load. |
|
|
21
22
|
| `clearable` | `boolean \| undefined` | `false` | | Allows clearing the selected rating by clicking the current value. |
|
|
22
23
|
| `disabled` | `boolean \| undefined` | | | Disable all interactions with the rating. |
|
|
@@ -33,9 +33,13 @@ date (see _Time selection_). `label` is required.
|
|
|
33
33
|
|
|
34
34
|
The shared surface applies:
|
|
35
35
|
|
|
36
|
-
- **`label`** (required)
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
- **`label`** (required) names the field for display and accessibility only —
|
|
37
|
+
it has **no** effect on the native `name` attribute of the segment inputs.
|
|
38
|
+
Leave `name` unset and the rendered segments carry none at all, so a plain
|
|
39
|
+
form post silently drops the value; pass `name` explicitly whenever it's
|
|
40
|
+
submitted via a native form or read from `FormData`. **`hideLabel`** hides
|
|
41
|
+
it visually while keeping the accessible name; **`labelPosition`** aligns
|
|
42
|
+
it; the **`label` slot** replaces it with `{ text, hasErrors }`.
|
|
39
43
|
- **`labelMode`** — `outside` / `floating` / `inside`. When unset it falls back
|
|
40
44
|
to the project-wide `config.defaultInputLabelMode` (library default:
|
|
41
45
|
`outside`), the same resolution as `BbTextInput` and `BbNumberInput`.
|
package/dist/ai/BbNumberInput.md
CHANGED
|
@@ -36,8 +36,11 @@ and locale-separator quirks of native number inputs don't apply here.
|
|
|
36
36
|
|
|
37
37
|
### Label & label modes
|
|
38
38
|
|
|
39
|
-
`label` is required
|
|
40
|
-
|
|
39
|
+
`label` is required, but it names the field for display and accessibility
|
|
40
|
+
only — it has **no** effect on the native `name` attribute. Leave `name`
|
|
41
|
+
unset and the rendered `<input>` carries none at all, so a plain form post
|
|
42
|
+
silently drops the value; pass `name` explicitly whenever it's submitted via
|
|
43
|
+
a native form or read from `FormData`. The shared label controls apply:
|
|
41
44
|
|
|
42
45
|
- **`labelMode`** sets where the label sits: `outside` (default, above),
|
|
43
46
|
`floating` (rests inside like a placeholder, lifts on focus/fill) or `inside`
|
package/dist/ai/BbTextInput.md
CHANGED
|
@@ -29,9 +29,11 @@ Pick a sibling when the shape of the data is different:
|
|
|
29
29
|
|
|
30
30
|
### Label & label modes
|
|
31
31
|
|
|
32
|
-
`label` names the field and
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
`label` names the field for display and accessibility only — it has **no**
|
|
33
|
+
effect on the native `name` attribute. Leave `name` unset and the rendered
|
|
34
|
+
`<input>` carries none at all, so a plain form post silently drops the value.
|
|
35
|
+
Pass `name` explicitly whenever the value is submitted via a native form or
|
|
36
|
+
read from `FormData`.
|
|
35
37
|
|
|
36
38
|
- **`labelMode`** sets where the label sits: `outside` (above the field),
|
|
37
39
|
`floating` (rests inside like a placeholder at reduced opacity, lifts on
|
package/dist/ai/BbTextarea.md
CHANGED
|
@@ -30,9 +30,11 @@ Pick a sibling when the shape of the data is different:
|
|
|
30
30
|
|
|
31
31
|
### Label
|
|
32
32
|
|
|
33
|
-
`label` names the field and
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
`label` names the field for display and accessibility only — it has **no**
|
|
34
|
+
effect on the native `name` attribute. Leave `name` unset and the rendered
|
|
35
|
+
`<textarea>` carries none at all, so a plain form post silently drops the
|
|
36
|
+
value. Pass `name` explicitly whenever the value is submitted via a native
|
|
37
|
+
form or read from `FormData`.
|
|
36
38
|
|
|
37
39
|
- **`hideLabel`** keeps the label for screen readers but removes it visually.
|
|
38
40
|
- **`labelPosition`** aligns the label text `left` / `center` / `right`.
|
package/dist/ai/BbToast.md
CHANGED
|
@@ -165,7 +165,9 @@ Three things worth internalising:
|
|
|
165
165
|
- **Variants tint the icon and set announcement priority — nothing else.** A
|
|
166
166
|
variant toast without an `icon` looks identical to a default one, so pass a
|
|
167
167
|
matching icon (`lucide:circle-check` for success, `lucide:circle-x` for
|
|
168
|
-
destructive…) whenever the tone matters visually. No icon is ever implied
|
|
168
|
+
destructive…) whenever the tone matters visually. No icon is ever implied —
|
|
169
|
+
dev builds warn when a built-in variant is used without one, since the tone
|
|
170
|
+
is otherwise dropped with no trace.
|
|
169
171
|
- `toast(...)` returns the message `id`. Keep it to `update(...)` or
|
|
170
172
|
`dismiss(...)` that toast later; `dismiss()` with no argument clears the
|
|
171
173
|
whole stack.
|
package/dist/ai/changelog.json
CHANGED
package/dist/ai/components.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"library": "bitboss-ui",
|
|
4
|
-
"version": "3.0.0-alpha.
|
|
5
|
-
"generatedAt": "2026-08-
|
|
4
|
+
"version": "3.0.0-alpha.9",
|
|
5
|
+
"generatedAt": "2026-08-24T11:02:05.896Z",
|
|
6
6
|
"composables": [
|
|
7
7
|
{
|
|
8
8
|
"name": "useBbConfig",
|
|
@@ -24,11 +24,6 @@
|
|
|
24
24
|
"description": "Read and drive a BbTabs/BbTabsRoot group from anywhere by id — writable current tab, goTo/select, no template refs.",
|
|
25
25
|
"doc": "ai/composables/useBbTabsContext.md"
|
|
26
26
|
},
|
|
27
|
-
{
|
|
28
|
-
"name": "useBroadcastChannelInstance",
|
|
29
|
-
"description": "Typed cross-tab messaging via the BroadcastChannel API with per-component subscriber lifecycle.",
|
|
30
|
-
"doc": "ai/composables/useBroadcastChannelInstance.md"
|
|
31
|
-
},
|
|
32
27
|
{
|
|
33
28
|
"name": "useConfirm",
|
|
34
29
|
"description": "Promise-based confirm dialogs — await the user's yes/no, with yes/no button configs, async onClick busy states, and portal content. Requires exactly one <BbConfirm /> host, mounted at the app root.",
|
|
@@ -243,6 +238,16 @@
|
|
|
243
238
|
"fix": {
|
|
244
239
|
"kind": "invert"
|
|
245
240
|
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"name": "theme",
|
|
244
|
+
"new": "variant",
|
|
245
|
+
"since": "3.0.0-unreleased",
|
|
246
|
+
"migration": "ai/guides/migration/components/bb-alert.md",
|
|
247
|
+
"silent": true,
|
|
248
|
+
"fix": {
|
|
249
|
+
"kind": "rename"
|
|
250
|
+
}
|
|
246
251
|
}
|
|
247
252
|
],
|
|
248
253
|
"renamed": [
|
|
@@ -254,6 +259,15 @@
|
|
|
254
259
|
"fix": {
|
|
255
260
|
"kind": "invert"
|
|
256
261
|
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"from": "theme",
|
|
265
|
+
"to": "variant",
|
|
266
|
+
"since": "3.0.0-unreleased",
|
|
267
|
+
"migration": "ai/guides/migration/components/bb-alert.md",
|
|
268
|
+
"fix": {
|
|
269
|
+
"kind": "rename"
|
|
270
|
+
}
|
|
257
271
|
}
|
|
258
272
|
]
|
|
259
273
|
},
|
|
@@ -3020,6 +3034,12 @@
|
|
|
3020
3034
|
"required": false,
|
|
3021
3035
|
"description": "Id(s) of elements describing this rating input for assistive technologies."
|
|
3022
3036
|
},
|
|
3037
|
+
{
|
|
3038
|
+
"name": "ariaLabelledby",
|
|
3039
|
+
"type": "string | undefined",
|
|
3040
|
+
"required": false,
|
|
3041
|
+
"description": "Id(s) of the element(s) that NAME this rating group. Supplying one is what\npromotes the inner container to `role=\"radiogroup\"` (Q4.5): an unnamed\n`radiogroup` announces as a bare \"radio group\" and is no better than the\nrole-less `<span>` it replaces, so the role is withheld until a name\nsource exists. `BbRating` wires this to its `<legend>`."
|
|
3042
|
+
},
|
|
3023
3043
|
{
|
|
3024
3044
|
"name": "autofocus",
|
|
3025
3045
|
"type": "Booleanish | undefined",
|
|
@@ -15246,6 +15266,36 @@
|
|
|
15246
15266
|
}
|
|
15247
15267
|
],
|
|
15248
15268
|
"removed": [
|
|
15269
|
+
{
|
|
15270
|
+
"name": "block",
|
|
15271
|
+
"new": null,
|
|
15272
|
+
"since": "3.0.0-unreleased",
|
|
15273
|
+
"migration": "ai/guides/migration/components/bb-tooltip.md",
|
|
15274
|
+
"silent": true,
|
|
15275
|
+
"fix": {
|
|
15276
|
+
"kind": "remove"
|
|
15277
|
+
}
|
|
15278
|
+
},
|
|
15279
|
+
{
|
|
15280
|
+
"name": "showClose",
|
|
15281
|
+
"new": null,
|
|
15282
|
+
"since": "3.0.0-unreleased",
|
|
15283
|
+
"migration": "ai/guides/migration/components/bb-tooltip.md",
|
|
15284
|
+
"silent": true,
|
|
15285
|
+
"fix": {
|
|
15286
|
+
"kind": "remove"
|
|
15287
|
+
}
|
|
15288
|
+
},
|
|
15289
|
+
{
|
|
15290
|
+
"name": "theme",
|
|
15291
|
+
"new": "variant",
|
|
15292
|
+
"since": "3.0.0-unreleased",
|
|
15293
|
+
"migration": "ai/guides/migration/components/bb-tooltip.md",
|
|
15294
|
+
"silent": true,
|
|
15295
|
+
"fix": {
|
|
15296
|
+
"kind": "rename"
|
|
15297
|
+
}
|
|
15298
|
+
},
|
|
15249
15299
|
{
|
|
15250
15300
|
"name": "timeout",
|
|
15251
15301
|
"new": "delay",
|
|
@@ -15258,6 +15308,15 @@
|
|
|
15258
15308
|
}
|
|
15259
15309
|
],
|
|
15260
15310
|
"renamed": [
|
|
15311
|
+
{
|
|
15312
|
+
"from": "theme",
|
|
15313
|
+
"to": "variant",
|
|
15314
|
+
"since": "3.0.0-unreleased",
|
|
15315
|
+
"migration": "ai/guides/migration/components/bb-tooltip.md",
|
|
15316
|
+
"fix": {
|
|
15317
|
+
"kind": "rename"
|
|
15318
|
+
}
|
|
15319
|
+
},
|
|
15261
15320
|
{
|
|
15262
15321
|
"from": "timeout",
|
|
15263
15322
|
"to": "delay",
|
|
@@ -234,11 +234,10 @@ twice.
|
|
|
234
234
|
Symptoms that mean stop: an `<img>` with an initials/icon fallback →
|
|
235
235
|
`BbAvatar` (**circle-only** — a rounded-square avatar really is yours to build);
|
|
236
236
|
a hand-written spin animation → `BbSpinner`; a tinted `<span>` pill standing for
|
|
237
|
-
a status → `BbBadge` with a registered `soft-*` variant
|
|
238
|
-
`new BroadcastChannel(…)` → `useBroadcastChannelInstance`. Full symptom index:
|
|
237
|
+
a status → `BbBadge` with a registered `soft-*` variant. Full symptom index:
|
|
239
238
|
[Component Picker](./component-picker.md) § Am I about to rebuild one of ours?
|
|
240
239
|
|
|
241
|
-
`npx bitboss-ui check` prints the avatar
|
|
240
|
+
`npx bitboss-ui check` prints the avatar and spinner shapes
|
|
242
241
|
as **advisory hints** — never a build failure, because a round `<img>` is
|
|
243
242
|
sometimes a logo — so that much backstops itself on files it scans. The badge
|
|
244
243
|
case is not decidable from markup and has no hint.
|
|
@@ -255,4 +254,4 @@ case is not decidable from markup and has no hint.
|
|
|
255
254
|
- [ ] Uses declarative coherence/dependencies before manual watchers.
|
|
256
255
|
- [ ] Mounts exactly one `<BbToast />` and one `<BbConfirm />` host, at the app root — never inside a page or component.
|
|
257
256
|
- [ ] Confirmed the plugin's `locale` is set explicitly if the app isn't Italian (default is `'it'`) — see Setup-First Rule.
|
|
258
|
-
- [ ] Ran the Rebuild Check over the hand-written markup — nothing reimplements `BbAvatar`, `BbSpinner
|
|
257
|
+
- [ ] Ran the Rebuild Check over the hand-written markup — nothing reimplements `BbAvatar`, `BbSpinner` or `BbBadge`.
|
|
@@ -22,12 +22,11 @@ this picker four times and hand-rolled an avatar twice while `BbAvatar` sat in
|
|
|
22
22
|
the Data Display table below. So this section is indexed by **symptom**: match it
|
|
23
23
|
against the markup you are about to write, not against a need.
|
|
24
24
|
|
|
25
|
-
| You are about to write | Stop — use
|
|
26
|
-
| ------------------------------------------------------------------------------------------- |
|
|
27
|
-
| An `<img>` with an initials/icon fallback branch, `border-radius: 50%`, `object-fit: cover` | [BbAvatar](../BbAvatar.md) — `src`/`alt`/size, initials slot, icon fallback, load-error handling
|
|
28
|
-
| `@keyframes spin` / `animation: … spin` on an element that means "waiting" | [BbSpinner](../BbSpinner.md) — sized off the control scale, honours `prefers-reduced-motion`
|
|
29
|
-
| A `<span>` pill with a tinted background standing for a status | [BbBadge](../BbBadge.md) with a registered `soft-*` variant (design-language § Getting soft semantic badges)
|
|
30
|
-
| `new BroadcastChannel('…')` for cross-tab sync | [useBroadcastChannelInstance](../composables/useBroadcastChannelInstance.md) — a typed wrapper: each call opens its own channel and removes its listeners on unmount |
|
|
25
|
+
| You are about to write | Stop — use |
|
|
26
|
+
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
27
|
+
| An `<img>` with an initials/icon fallback branch, `border-radius: 50%`, `object-fit: cover` | [BbAvatar](../BbAvatar.md) — `src`/`alt`/size, initials slot, icon fallback, load-error handling |
|
|
28
|
+
| `@keyframes spin` / `animation: … spin` on an element that means "waiting" | [BbSpinner](../BbSpinner.md) — sized off the control scale, honours `prefers-reduced-motion` |
|
|
29
|
+
| A `<span>` pill with a tinted background standing for a status | [BbBadge](../BbBadge.md) with a registered `soft-*` variant (design-language § Getting soft semantic badges) |
|
|
31
30
|
|
|
32
31
|
**`BbAvatar` is circle-only.** Its `border-radius: 50%` is in the component's own
|
|
33
32
|
CSS and no prop changes it, so a rounded-**square** avatar genuinely has no answer
|
|
@@ -35,7 +34,7 @@ here — build that one yourself. Everything else about it (fallbacks, load erro
|
|
|
35
34
|
sizing) still applies, so the honest options are "use it and accept a circle" or
|
|
36
35
|
"hand-roll the square one knowingly", not "hand-roll it because you never saw it".
|
|
37
36
|
|
|
38
|
-
`npx bitboss-ui check` prints the avatar
|
|
37
|
+
`npx bitboss-ui check` prints the avatar and spinner rows as
|
|
39
38
|
**advisory hints** — never a build failure, since a round `<img>` is sometimes a
|
|
40
39
|
logo — on every `.vue` file it scans. That is the backstop: it fires without
|
|
41
40
|
anyone thinking to ask. The badge case is not decidable from markup (a tinted
|
|
@@ -244,7 +243,7 @@ compose it or write it yourself.
|
|
|
244
243
|
| `BbTab` (singular) | The consumer API is [BbTabs](../BbTabs.md) / `BbTabsRoot`. `BbTab` appears only as the **v2 "before" side** of the migration diffs. |
|
|
245
244
|
| `BbCard` | Does not exist — a card is a `<div>` with tokens. See [design-language](./design-language.md). |
|
|
246
245
|
| `BbList` / `BbListItem` / `BbDescriptionList` | Do not exist — a list row is an `<li>` with tokens, and [BbBaseButton](../BbBaseButton.md) makes the whole row navigable. See the note under Data Display. |
|
|
247
|
-
| `useLiveFeed` / any polling or cross-tab feed helper | Does not exist
|
|
246
|
+
| `useLiveFeed` / any polling or cross-tab feed helper | Does not exist, and neither does a cross-tab helper — `useBroadcastChannelInstance` was removed (cross-tab messaging is not a UI concern). Use `useBroadcastChannel` from `@vueuse/core`; the polling and the merge are yours. |
|
|
248
247
|
| `BbStepper` / `BbWizard` | Does not exist as a component; the wizard-form recipe composes one. |
|
|
249
248
|
| `BbSkeleton` (standalone) | Only `BbTable` ships skeletons, via the column `skeleton` field. |
|
|
250
249
|
| `BbCommand` / command palette | Does not exist. Compose `BbDialog` + `BbSelectPopover`. |
|
|
@@ -319,7 +319,7 @@ Default label rendering mode for input-like components; set globally instead of
|
|
|
319
319
|
|
|
320
320
|
### `requiredAsterisk?: boolean` (default: `false`)
|
|
321
321
|
|
|
322
|
-
Marks required fields with a red asterisk beside the label/legend. Presentational only — it keys off the standard `required` prop and changes neither validation nor native `required` semantics. The marker is applied by the [`bitboss-ui/validated`](./validated-forms.md) controls
|
|
322
|
+
Marks required fields with a red asterisk beside the label/legend. Presentational only — it keys off the standard `required` prop and changes neither validation nor native `required` semantics. The marker is applied by the [`bitboss-ui/validated`](./validated-forms.md) controls — a field that is `required`, or whose `rules` contain a `required` rule; other rules never raise it, because they only apply once a value exists. Core controls ignore the flag, so on a hand-wired form render the exported `BbAsterisk` in your own label content.
|
|
323
323
|
|
|
324
324
|
### `locale?: LocaleKey` (default: `'it'`)
|
|
325
325
|
|
|
@@ -350,70 +350,31 @@ bitbossUi({
|
|
|
350
350
|
```
|
|
351
351
|
|
|
352
352
|
Your `locale` and `'en'` are always auto-included, so the list never needs to
|
|
353
|
-
repeat them
|
|
354
|
-
belong here.
|
|
353
|
+
repeat them.
|
|
355
354
|
There is deliberately **no catch-all** ("all") value — it would hide the
|
|
356
355
|
bundle cost. Wanting every built-in means writing the list, so the cost is
|
|
357
356
|
visible in your config where reviewers can see it.
|
|
358
357
|
|
|
359
358
|
**Selecting a non-enabled locale is a compile error**, not a silent runtime
|
|
360
|
-
fallback: the generated `locale-registry.d.ts` registers only enabled
|
|
361
|
-
built-ins
|
|
362
|
-
|
|
359
|
+
fallback: the generated `locale-registry.d.ts` registers only the enabled
|
|
360
|
+
built-ins, so `setConfig({ locale: 'ja' })` fails to type-check until `'ja'` is
|
|
361
|
+
enabled. Run dev once after changing the list.
|
|
363
362
|
|
|
364
|
-
###
|
|
363
|
+
### Custom locales are not a supported surface
|
|
365
364
|
|
|
366
|
-
**
|
|
367
|
-
built-in locales cannot be overridden — a built-in key here is a type error,
|
|
368
|
-
and one smuggled past the compiler is ignored with a build-time warning.
|
|
365
|
+
The library ships **22 dictionaries** and that is the whole set:
|
|
369
366
|
|
|
370
|
-
The full flow for adding a locale (using Georgian, which the library doesn't
|
|
371
|
-
ship):
|
|
372
|
-
|
|
373
|
-
```bash
|
|
374
|
-
# 1. Generate a translation blueprint (English strings) at the project root
|
|
375
|
-
npx bitboss-ui locale ka
|
|
376
367
|
```
|
|
377
|
-
|
|
378
|
-
```ts
|
|
379
|
-
// 2. Translate ka.locale.ts, then register it
|
|
380
|
-
import ka from './ka.locale';
|
|
381
|
-
|
|
382
|
-
bitbossUi({
|
|
383
|
-
iconDir: './src/assets/icons',
|
|
384
|
-
locale: 'ka',
|
|
385
|
-
additionalLocales: { ka },
|
|
386
|
-
});
|
|
368
|
+
cs da de el en es fi fr hu it ja ko nb nl pl pt ro ru sv tr uk zh-cn
|
|
387
369
|
```
|
|
388
370
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
- **regenerates `locale-registry.d.ts`**, augmenting `LocaleRegistry` with
|
|
398
|
-
your keys (exactly like the variant registries), so `'ka'` is a valid
|
|
399
|
-
`locale` value everywhere — the plugin option and `setConfig({ locale })`
|
|
400
|
-
alike. Run dev once after adding a key so the file exists.
|
|
401
|
-
- **wires the matching dayjs locale** (`dayjs/locale/ka`) so calendars follow
|
|
402
|
-
your locale's month/day names and week start. Any dayjs-shipped name works.
|
|
403
|
-
If dayjs has no locale under your key, the plugin **warns at build time**
|
|
404
|
-
and calendars fall back to English (there is no runtime warning) — when a
|
|
405
|
-
nearby dayjs name exists (`zh-cn`, `pt-br`, …), prefer it as your key.
|
|
406
|
-
|
|
407
|
-
Keys you delete from the blueprint fall back per-key to the default locale
|
|
408
|
-
(your `locale` when it's a built-in, otherwise `en` — always bundled, always
|
|
409
|
-
complete) — and are reported by the completeness warning above, which is the
|
|
410
|
-
point: partial is allowed, silent-partial is not.
|
|
411
|
-
|
|
412
|
-
Locale dictionaries are **build-time only**: `setConfig` accepts `locale` but
|
|
413
|
-
deliberately not `additionalLocales` — a runtime path would bypass every check
|
|
414
|
-
the plugin performs (built-in collision, completeness verification, dayjs
|
|
415
|
-
wiring, registry typing). Only the active `locale` switches at runtime, among
|
|
416
|
-
what the build enabled.
|
|
371
|
+
There is no `additionalLocales` option and no `npx bitboss-ui locale` blueprint
|
|
372
|
+
generator — both were removed deliberately (owner ruling, 2026-08-08). If your
|
|
373
|
+
language is not on that list, the supported answer is to ask for it to be
|
|
374
|
+
added upstream rather than to author a dictionary in your app.
|
|
375
|
+
|
|
376
|
+
Locale selection is **build-time**: `enabledLocales` decides what ships, and
|
|
377
|
+
only the active `locale` switches at runtime, among what the build enabled.
|
|
417
378
|
|
|
418
379
|
### `toastPosition?: BbToastPosition` (default: `'bottom-right'`)
|
|
419
380
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Migration v2→v3: BbIntersection'
|
|
3
|
+
summary: Removed with no replacement — it wrapped IntersectionObserver and carried no styling; use @vueuse/core's useIntersectionObserver.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# BbIntersection — v2 → v3
|
|
7
|
+
|
|
8
|
+
**`BbIntersection` is removed in v3.** It was a headless wrapper around
|
|
9
|
+
`IntersectionObserver` — no markup of its own beyond a `<div>`, no styling, no
|
|
10
|
+
design-system surface. Everything it did is one composable call, so it is not
|
|
11
|
+
worth a component in a UI library.
|
|
12
|
+
|
|
13
|
+
There is **no `Bb*` replacement**. Two supported paths:
|
|
14
|
+
|
|
15
|
+
1. **`useIntersectionObserver` from `@vueuse/core`** — the direct equivalent,
|
|
16
|
+
and what the library itself would use.
|
|
17
|
+
2. **Copy the v2 component into your app** if you want to keep the exact
|
|
18
|
+
event/slot shape. It was ~40 lines; `git show v2:src/components/BbIntersection/BbIntersection.vue`.
|
|
19
|
+
|
|
20
|
+
## Changes
|
|
21
|
+
|
|
22
|
+
| v2 | v3 | Kind |
|
|
23
|
+
| ----------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| `<BbIntersection>` component | **removed** | no replacement — use `useIntersectionObserver` |
|
|
25
|
+
| `BbIntersectionProps` / `BbIntersectionEvents` type exports | **removed** | delete the imports |
|
|
26
|
+
| `debounceTime?: number` (default `0`) | — | it throttled, despite the name. `useIntersectionObserver` does not throttle; wrap the callback yourself if you relied on it. |
|
|
27
|
+
| `options?: IntersectionObserverInit` | — | passes straight through as `useIntersectionObserver`'s third argument. **The v2 default was `{ root: null, threshold: [0, 0.2, 0.4, 0.6, 0.8, 1] }`** — VueUse's default is a single `0` threshold, so pass the array if you need ratio granularity. |
|
|
28
|
+
| `tag` (default `'div'`) | — | you render the observed element yourself now |
|
|
29
|
+
|
|
30
|
+
### Events and slot props
|
|
31
|
+
|
|
32
|
+
The three events had specific thresholds that are easy to get wrong when
|
|
33
|
+
reimplementing:
|
|
34
|
+
|
|
35
|
+
| v2 | Fired when | Equivalent |
|
|
36
|
+
| --------------------------- | -------------------------------------------------------- | ------------------------------------------- |
|
|
37
|
+
| `@shown` | intersection ratio reaches **exactly 1** (fully visible) | `ratio === 1` |
|
|
38
|
+
| `@hidden` | element leaves the viewport **entirely** | `!entry.isIntersecting` |
|
|
39
|
+
| `@intersected="(pct) => …"` | on every ratio change; payload is **0–100**, not 0–1 | `Math.trunc(entry.intersectionRatio * 100)` |
|
|
40
|
+
|
|
41
|
+
The default slot exposed `{ shown, hidden, percentage }` with the same
|
|
42
|
+
semantics (`percentage` also 0–100).
|
|
43
|
+
|
|
44
|
+
## Edits
|
|
45
|
+
|
|
46
|
+
The common case was an infinite-scroll sentinel:
|
|
47
|
+
|
|
48
|
+
```diff
|
|
49
|
+
- <BbIntersection @shown="loadMore">
|
|
50
|
+
- <span />
|
|
51
|
+
- </BbIntersection>
|
|
52
|
+
+ <span ref="sentinel" />
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { useIntersectionObserver } from '@vueuse/core';
|
|
57
|
+
import { useTemplateRef } from 'vue';
|
|
58
|
+
|
|
59
|
+
const sentinel = useTemplateRef('sentinel');
|
|
60
|
+
|
|
61
|
+
useIntersectionObserver(sentinel, ([entry]) => {
|
|
62
|
+
if (entry?.isIntersecting) loadMore();
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Note the threshold change: `@shown` required **full** visibility, while the
|
|
67
|
+
snippet above fires as soon as any part of the sentinel appears. That is
|
|
68
|
+
usually what you want for infinite scroll — it triggers earlier — but if you
|
|
69
|
+
depended on the stricter behaviour, pass `{ threshold: 1 }` and check
|
|
70
|
+
`entry.intersectionRatio === 1`.
|