bitboss-ui 3.0.0-beta.62 → 3.0.0-beta.63
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/dist/ai/BbConfirm.md +46 -22
- package/dist/ai/BbForm.md +66 -4
- package/dist/ai/BbHost.md +11 -13
- package/dist/ai/BbPtScope.md +6 -4
- package/dist/ai/BbTable.md +65 -5
- package/dist/ai/changelog.json +28 -4
- package/dist/ai/components.json +5 -5
- package/dist/ai/composables/useConfirm.md +8 -5
- package/dist/ai/guides/agent-contract.md +3 -2
- package/dist/ai/guides/migration/components/bb-host.md +4 -2
- package/dist/ai/guides/migration/components/use-confirm.md +15 -15
- package/dist/ai/guides/migration/v2-to-v3.md +9 -0
- package/dist/ai/guides/passthrough.md +57 -57
- package/dist/ai/guides/validated-forms.md +5 -0
- package/dist/ai/helpers/inertia/manifest.json +1 -1
- package/dist/ai/manifest/components/BbHost.tree.json +1 -2
- package/dist/ai/manifest/components/BbTable.json +2 -0
- package/dist/ai/manifest/index.json +2 -2
- package/dist/ai/manifest/types.advanced.json +1 -1
- package/dist/ai/source/BbConfirm.md +33 -21
- package/dist/ai/source/BbConfirmPortal.md +7 -16
- package/dist/ai/source/BbHost.md +3 -3
- package/dist/ai/source/BbTable.md +37 -9
- package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +83 -74
- package/dist/components/BbConfirm/BbConfirmHost.d.ts +10 -0
- package/dist/components/BbConfirm/BbConfirmHost.js +32 -0
- package/dist/components/BbConfirm/BbConfirmPortal.vue_vue_type_script_setup_true_lang.js +8 -12
- package/dist/components/BbConfirm/confirmEntry.d.ts +4 -0
- package/dist/components/BbConfirm/confirmEntry.js +4 -0
- package/dist/components/BbConfirm/types.d.ts +2 -2
- package/dist/components/BbHost/BbHost.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +426 -380
- package/dist/components/BbTable/BbTableDataRow.js +17 -12
- package/dist/components/BbTable/BbTableSelectToggle.d.ts +1 -1
- package/dist/components/BbTable/types.d.ts +14 -3
- package/dist/components/BbTable/types.js +2 -0
- package/dist/composables/useBbFormContext.d.ts +7 -3
- package/dist/composables/useConfirm.d.ts +327 -33
- package/dist/composables/useConfirm.js +93 -71
- package/dist/llms-full.txt +295 -129
- package/dist/llms-medium.txt +3 -2
- package/dist/styles.css +1 -1
- package/dist/types/passthrough.d.ts +1 -1
- package/dist/types/ptComponentMap.d.ts +1 -1
- package/dist/utils/versionCheck.js +1 -1
- package/package.json +1 -1
package/dist/ai/BbConfirm.md
CHANGED
|
@@ -72,23 +72,21 @@ first — this is that gate.
|
|
|
72
72
|
Mount `<BbHost />` **exactly once, at the app root** (`App.vue` under Vue,
|
|
73
73
|
`app.vue` under Nuxt, the `createInertiaApp` render root under Inertia) — a
|
|
74
74
|
single instance serves the whole app, and `confirm()` can then be called from
|
|
75
|
-
anywhere, components and stores alike. **
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
row show only the second, and the first silently answers "no". If you need both
|
|
79
|
-
questions asked, `await` the first before opening the second.
|
|
75
|
+
anywhere, components and stores alike. **Every call opens its own dialog**,
|
|
76
|
+
and a new one covers the open one, which stays pending and comes back when
|
|
77
|
+
the newer one closes (see [Several confirms at once](#several-confirms-at-once)).
|
|
80
78
|
A second host renders nothing (a dev-mode console warning says so). With no
|
|
81
79
|
host, `await confirm(...)` resolves `false` after one second, with a dev
|
|
82
80
|
warning. A host that unmounts while its dialog is open (a layout the user
|
|
83
81
|
navigated out of) gets the same second to come back; after that the open
|
|
84
82
|
confirm resolves `false` without running a callback, so it never hangs.
|
|
85
83
|
|
|
86
|
-
**Areas with their own look.**
|
|
87
|
-
tokens of the
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
**Areas with their own look.** A confirm takes the passthrough scope and the
|
|
85
|
+
tokens of the component that called `useConfirm()`, wherever the host is
|
|
86
|
+
mounted: a page inside a `<BbPtScope>` ([passthrough guide](./guides/passthrough.md) § Named scopes)
|
|
87
|
+
gets confirms in its area's look with nothing to set up. A component portal
|
|
88
|
+
injects from that component's tree too. A `useConfirm()` called outside a
|
|
89
|
+
component (a store, module level) takes the host's.
|
|
92
90
|
|
|
93
91
|
```vue
|
|
94
92
|
<template>
|
|
@@ -105,10 +103,9 @@ import { BbHost } from 'bitboss-ui';
|
|
|
105
103
|
standalone example has no app root to mount it in.** In a real app the host is
|
|
106
104
|
already mounted at the root; a page that calls `confirm()` mounts nothing.
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
`
|
|
111
|
-
sets its own (see [Size, fullscreen and focus](#size-fullscreen-and-focus)).
|
|
106
|
+
Everything — content, buttons, behavior — travels in the message you pass to
|
|
107
|
+
`confirm()`; the width every confirm defaults to is the plugin's
|
|
108
|
+
`confirm.defaultSize` (see [Size, fullscreen and focus](#size-fullscreen-and-focus)).
|
|
112
109
|
At least one of `title`, `text`, `portal` should be set (dev warning
|
|
113
110
|
otherwise).
|
|
114
111
|
|
|
@@ -402,7 +399,7 @@ the promise `false`, so your `if (ok)` branch is never reached accidentally.
|
|
|
402
399
|
decline-only behavior in `no.onClick`, not in the `if (!ok)` branch. The rule
|
|
403
400
|
that decides whether `no.onClick` runs: **user-initiated** dismissals
|
|
404
401
|
(backdrop, `Escape`, the X) honor `dismissAsNo`; **system-initiated** ones
|
|
405
|
-
(`duration` timeout, owner unmount,
|
|
402
|
+
(`duration` timeout, owner unmount, `dismissAll()`)
|
|
406
403
|
always resolve quietly, never running any callback. The knobs:
|
|
407
404
|
|
|
408
405
|
- `dismissAsNo` (default `true`) — user-initiated implicit dismissals also run
|
|
@@ -435,7 +432,7 @@ the peek closes. For app-lifetime confirms that survive any unmount, call
|
|
|
435
432
|
`useConfirm()` outside a component scope (app setup, a store, module level).
|
|
436
433
|
|
|
437
434
|
`useConfirm()` also returns `dismissAll()` — an imperative escape hatch that
|
|
438
|
-
quietly dismisses
|
|
435
|
+
quietly dismisses every open confirm regardless of owner, for
|
|
439
436
|
app-level events like logout or a global error boundary.
|
|
440
437
|
|
|
441
438
|
The classic case for `persistent` is the unsaved-changes prompt: an accidental
|
|
@@ -511,6 +508,8 @@ By default the dialog closes as soon as the promise settles. Set
|
|
|
511
508
|
- `close()` only hides the dialog; **it never resolves anything**. Calling it
|
|
512
509
|
on a dialog whose buttons haven't run yet leaves that `confirm()` promise
|
|
513
510
|
pending forever — it is a flow terminator, not a substitute for the buttons.
|
|
511
|
+
- `close()` hides the newest open confirm opened through the **same**
|
|
512
|
+
`useConfirm()`, never another component's.
|
|
514
513
|
|
|
515
514
|
**Keep the dialog open across steps**
|
|
516
515
|
|
|
@@ -585,6 +584,31 @@ const exportWorkspace = async () => {
|
|
|
585
584
|
</script>
|
|
586
585
|
```
|
|
587
586
|
|
|
587
|
+
### Several confirms at once
|
|
588
|
+
|
|
589
|
+
Confirms stack. A `confirm()` while another is open (from a button's
|
|
590
|
+
`onClick`, or two calls without an `await` between them) covers the open one
|
|
591
|
+
in place; the one beneath stays pending, and comes back, still waiting for
|
|
592
|
+
its answer, when the newer one closes. Escape and the backdrop answer only
|
|
593
|
+
the one on top. Two un-awaited calls are therefore both asked, newest first:
|
|
594
|
+
`await` each one when the order matters.
|
|
595
|
+
|
|
596
|
+
`stack` picks the `BbDialog` stack a confirm joins (every confirm joins the
|
|
597
|
+
confirms' own by default). Name a dialog's `stack` and the confirm replaces
|
|
598
|
+
that dialog's view while it is open, as a drill-in step would ([BbDialog](./BbDialog.md)
|
|
599
|
+
§ Stacked dialogs); a name no other dialog uses shows it on top of the other
|
|
600
|
+
confirms, each dimming the one beneath.
|
|
601
|
+
|
|
602
|
+
```ts
|
|
603
|
+
// An unsaved-changes question that takes the editor's place, not a layer on it.
|
|
604
|
+
const discard = await confirm({
|
|
605
|
+
title: 'Discard your changes?',
|
|
606
|
+
stack: 'editor', // the editor's <BbDialog stack="editor">
|
|
607
|
+
variant: 'destructive',
|
|
608
|
+
yes: 'Discard',
|
|
609
|
+
});
|
|
610
|
+
```
|
|
611
|
+
|
|
588
612
|
### Rich content with portals
|
|
589
613
|
|
|
590
614
|
When plain `text` isn't enough, render custom content in the dialog body via a
|
|
@@ -740,9 +764,9 @@ The map is typed where you write it by `definePt`, never with an imported
|
|
|
740
764
|
|
|
741
765
|
- **Don't hand-build a yes/no dialog** out of `BbDialog` + buttons — busy
|
|
742
766
|
states, dismissal semantics, ownership and focus handling already live here.
|
|
743
|
-
- **
|
|
744
|
-
|
|
745
|
-
|
|
767
|
+
- **Two `confirm()` calls without an `await` between them ask both, newest
|
|
768
|
+
first** — the second covers the first. `await` each one when the questions
|
|
769
|
+
must come in order.
|
|
746
770
|
- **Don't forget the `await`** — `confirm(...)` without it never gates
|
|
747
771
|
anything.
|
|
748
772
|
- **Don't call `close()` to "cancel"** a dialog whose buttons haven't run —
|
|
@@ -753,8 +777,8 @@ The map is typed where you write it by `definePt`, never with an imported
|
|
|
753
777
|
- With `returning: true`, an implicit dismiss under the default
|
|
754
778
|
`dismissAsNo: true` resolves with `no.onClick`'s return value — give No a
|
|
755
779
|
callback that returns a sensible "declined" value.
|
|
756
|
-
System dismissals (`duration`, `dismissAll()`,
|
|
757
|
-
|
|
780
|
+
System dismissals (`duration`, `dismissAll()`, owner unmount) still resolve
|
|
781
|
+
`false`, so handle `false` too.
|
|
758
782
|
- `confirm()` rejects keys `BbConfirmMessage` doesn't declare, also on a
|
|
759
783
|
message built in a variable first: build it from `BbConfirmMessage` fields
|
|
760
784
|
only (spread a wider object and the extra keys fail to type-check).
|
package/dist/ai/BbForm.md
CHANGED
|
@@ -1076,7 +1076,11 @@ const bodyRules = computed(() => (publishing.value ? 'required' : ''));
|
|
|
1076
1076
|
```
|
|
1077
1077
|
|
|
1078
1078
|
Both switch live: the next validation uses the new schema or rules, and
|
|
1079
|
-
switching back lets a submit through that was blocked a moment ago.
|
|
1079
|
+
switching back lets a submit through that was blocked a moment ago. A message
|
|
1080
|
+
already on screen is not taken down by the switch: it stays until the field
|
|
1081
|
+
validates again (an edit, a blur, the next submit). If the condition lives in
|
|
1082
|
+
another field and the stale message would mislead, show it through
|
|
1083
|
+
[`field-errors`](#a-message-of-your-own-that-comes-and-goes) instead.
|
|
1080
1084
|
|
|
1081
1085
|
### While it saves
|
|
1082
1086
|
|
|
@@ -1353,6 +1357,54 @@ async function save(values: Record<string, unknown>) {
|
|
|
1353
1357
|
}
|
|
1354
1358
|
```
|
|
1355
1359
|
|
|
1360
|
+
##### A message of your own that comes and goes
|
|
1361
|
+
|
|
1362
|
+
The object does not have to come from a server. A check that spans fields is
|
|
1363
|
+
a `computed`: its message shows exactly while the check fails, with no code to
|
|
1364
|
+
clear it. Gate it on a submit attempt so it does not greet an empty form:
|
|
1365
|
+
|
|
1366
|
+
```vue
|
|
1367
|
+
<script setup lang="ts">
|
|
1368
|
+
import { computed, ref } from 'vue';
|
|
1369
|
+
import { BbButton, BbDatePickerInput, BbForm, BbSelect } from 'bitboss-ui';
|
|
1370
|
+
|
|
1371
|
+
const patients = [
|
|
1372
|
+
{ label: 'Anna Rossi', value: 1 },
|
|
1373
|
+
{ label: 'Luca Bianchi', value: 2 },
|
|
1374
|
+
];
|
|
1375
|
+
const visit = ref<{ patient: number | null; date: string | null }>({
|
|
1376
|
+
patient: null,
|
|
1377
|
+
date: null,
|
|
1378
|
+
});
|
|
1379
|
+
const tried = ref(false);
|
|
1380
|
+
const missingDate = computed(() => !visit.value.patient && !visit.value.date);
|
|
1381
|
+
|
|
1382
|
+
const ownErrors = computed(() => ({
|
|
1383
|
+
date:
|
|
1384
|
+
tried.value && missingDate.value
|
|
1385
|
+
? 'Pick a date when no patient is selected.'
|
|
1386
|
+
: undefined,
|
|
1387
|
+
}));
|
|
1388
|
+
|
|
1389
|
+
const save = (values: Record<string, unknown>) => {
|
|
1390
|
+
tried.value = true;
|
|
1391
|
+
if (missingDate.value) return; // field-errors never block a submit
|
|
1392
|
+
console.log('book', values);
|
|
1393
|
+
};
|
|
1394
|
+
</script>
|
|
1395
|
+
|
|
1396
|
+
<template>
|
|
1397
|
+
<BbForm :model="visit" :field-errors="ownErrors" @submit="save">
|
|
1398
|
+
<BbSelect label="Patient" name="patient" :items="patients" clearable />
|
|
1399
|
+
<BbDatePickerInput label="Date" name="date" />
|
|
1400
|
+
<BbButton type="submit">Book</BbButton>
|
|
1401
|
+
</BbForm>
|
|
1402
|
+
</template>
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
Picking a patient takes the message down at once. When the page also holds
|
|
1406
|
+
server errors, pass both: `:field-errors="{ ...form.errors, ...ownErrors }"`.
|
|
1407
|
+
|
|
1356
1408
|
- **The page owns them.** Editing the field does not hide its message; the
|
|
1357
1409
|
next object does (Inertia replaces `form.errors` on every answer and clears
|
|
1358
1410
|
it on success). Want it gone as the user types? Clear it yourself
|
|
@@ -1449,9 +1501,19 @@ const save = async (values: Record<string, unknown>) => {
|
|
|
1449
1501
|
- A request-level message (Laravel's `message`, a 403) has no path: give it a
|
|
1450
1502
|
key no field uses IN THE SAME CALL, `form.setErrors({ ...body.errors, _request: [body.message] })`, and it
|
|
1451
1503
|
shows in the same summary.
|
|
1452
|
-
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1504
|
+
- **`setErrors` hands over one server answer; it never takes a message
|
|
1505
|
+
back.** A field's message stays until the user edits the field or it is
|
|
1506
|
+
validated again. A submit validates every field, so a submit → 422 →
|
|
1507
|
+
`setErrors` round always starts clean. A second call without a submit
|
|
1508
|
+
between them replaces `unmatchedErrors` only: the first call's field
|
|
1509
|
+
messages stay, and `null` or a missing key clears nothing. So put
|
|
1510
|
+
everything one answer says into one map.
|
|
1511
|
+
- **Don't use `setErrors` for a message you will take back yourself**, like
|
|
1512
|
+
your own cross-field check ("a date is required when no patient is
|
|
1513
|
+
selected"). Compute it into [`field-errors`](#a-message-of-your-own-that-comes-and-goes)
|
|
1514
|
+
instead: it shows while its key holds a message and goes the moment it
|
|
1515
|
+
does not. Calling `validate()` to wipe a `setErrors` message runs every
|
|
1516
|
+
rule on every field, so it puts messages on fields the user never touched.
|
|
1455
1517
|
- `setErrors` does not emit `invalid`. It does move focus to the first failing
|
|
1456
1518
|
field on screen, like a failed submit (`{ focus: false }` opts out; see
|
|
1457
1519
|
[A failed submit focuses the first invalid field](#a-failed-submit-focuses-the-first-invalid-field)).
|
package/dist/ai/BbHost.md
CHANGED
|
@@ -87,12 +87,13 @@ The same keys go in the build plugin (`bitbossUi({ confirm, toastPosition })`).
|
|
|
87
87
|
|
|
88
88
|
### Areas with their own look
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
A confirm takes the passthrough scope and tokens of the component that called
|
|
91
|
+
`useConfirm()`, wherever the host sits: nothing to set up. Toasts take the
|
|
92
|
+
scope and tokens of the place the HOST sits. When the app is split into areas
|
|
93
|
+
that each wrap their pages in `<BbPtScope>`
|
|
94
|
+
([passthrough guide](./guides/passthrough.md) § Named scopes) and toasts need
|
|
95
|
+
each area's look, mount one `<BbHost />` inside each area's layout, within its
|
|
96
|
+
scope, and none at the app root. That holds only if **every** page renders inside exactly one of those
|
|
96
97
|
layouts, so there is still one host at a time. See
|
|
97
98
|
[Agent Contract § Global Host Rule](./guides/agent-contract.md).
|
|
98
99
|
|
|
@@ -142,14 +143,11 @@ without a mismatch.
|
|
|
142
143
|
- Listed nodes are the ones `BbHost`'s API reaches or that declare a documented CSS variable; the rest fold into "also mounts". The complete tree, repeats and undocumented locals included, is `manifest/components/BbHost.tree.json`.
|
|
143
144
|
|
|
144
145
|
- `BbHost` _(this component)_
|
|
145
|
-
- `BbConfirm` _(internal — not importable, reach it through `BbConfirm`)_ — its own pt parts (`BbConfirm`): `text` → `div.bb-confirm__text`, `action` → `BbButton`; hands `BbDialog` the pt map `passthrough.forward(DIALOG_PARTS, BB_DIALOG_PT.states)` (ours → theirs)
|
|
146
|
-
- `BbDialog` _(public — [contract](./BbDialog.md))_ — its own pt parts (`BbDialog`): `header` → `div.bb-dialog__header`, `title` → `span.bb-dialog__title`, `description` → `p.bb-dialog__description`, `close` → `CloseButton`, `content` → `div.bb-dialog__content`, `footer` → `div.bb-dialog__footer`; hands `BbOffCanvas` the pt map `{ root: 'root', header: 'header', title: 'title', description: 'description', content: 'content', footer: 'footer', close: 'close', sheet: 'root', }` (ours → theirs); documented CSS variables: `--px`, `--close-size`
|
|
147
|
-
- `CloseButton` _(internal — not importable, reach it through `BbDialog`)_ — documented CSS variables: `--size`, `--p`
|
|
148
|
-
- `BbOffCanvas` _(public — [contract](./BbOffCanvas.md))_ — its own pt parts (`BbOffCanvas`): `header` → `div.bb-offcanvas__header`, `title` → `span.bb-offcanvas__title`, `description` → `p.bb-offcanvas__description`, `close` → `CloseButton`, `content` → `div.bb-offcanvas__content`, `footer` → `div.bb-offcanvas__footer`; documented CSS variables: `--stack-x`, `--snap-y`, `--stack-fill`, `--stack-transition-duration`, `--px`, `--handle-w`, `--handle-h`, `--handle-bg`, `--safe-top`, `--close-size`; also mounts `CloseButton`
|
|
149
|
-
- `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `BbIcon`, `text` → `span.bb-button__text`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring-color`, `--ring-size`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbSpinner`
|
|
150
|
-
- `BbBaseButton` _(public — [contract](./BbBaseButton.md))_ — its own pt parts (`BbBaseButton`): `root` → `RouterComponent`, `root` → `a`, `root` → `component`; also mounts `RouterComponent`
|
|
151
146
|
- `BbToast` _(internal — not importable, reach it through `BbToast`)_ — documented CSS variables: `--gap`, `--offset`, `--width`, `--lift`, `--stack-y`, `--stack-scale`, `--enter-y`, `--swipe-amount`, `--z`, `--r`, `--ring-size`, `--bg`, `--border-color`, `--fg`, `--icon-color`
|
|
152
|
-
- `BbToastRegion` _(internal — not importable, reach it through `BbToast`)_ — its own pt parts (`BbToast`): `root` → `ol.bb-toast
|
|
147
|
+
- `BbToastRegion` _(internal — not importable, reach it through `BbToast`)_ — its own pt parts (`BbToast`): `root` → `ol.bb-toast`
|
|
148
|
+
- `BbToastMessage` _(internal — not importable, reach it through `BbToast`)_ — also mounts `BbIcon`, `BbSpinner`
|
|
149
|
+
- `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `BbIcon`, `text` → `span.bb-button__text`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring-color`, `--ring-size`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbSpinner`
|
|
150
|
+
- `BbBaseButton` _(public — [contract](./BbBaseButton.md))_ — its own pt parts (`BbBaseButton`): `root` → `RouterComponent`, `root` → `a`, `root` → `component`; also mounts `RouterComponent`
|
|
153
151
|
|
|
154
152
|
## See Also
|
|
155
153
|
|
package/dist/ai/BbPtScope.md
CHANGED
|
@@ -96,9 +96,10 @@ The scope follows the **component tree**, not the DOM:
|
|
|
96
96
|
in. A directive written directly in `<BbPtScope>`'s slot, in the same
|
|
97
97
|
template as the scope, sees the scope above it instead — keep the scope in a
|
|
98
98
|
layout or a parent component.
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
- A `confirm()` takes the scope of the component that called `useConfirm()`,
|
|
100
|
+
wherever `<BbHost />` is mounted. Toasts take the scope where the host is
|
|
101
|
+
mounted: for toasts in the area's look, mount one `<BbHost />` inside each
|
|
102
|
+
area's layout, within its scope, and none at the app root — valid only
|
|
102
103
|
when every page renders inside exactly one of those layouts (see
|
|
103
104
|
[Agent Contract § Global Host Rule](./guides/agent-contract.md)).
|
|
104
105
|
|
|
@@ -112,7 +113,8 @@ The scope follows the **component tree**, not the DOM:
|
|
|
112
113
|
|
|
113
114
|
### Works well with
|
|
114
115
|
|
|
115
|
-
- `BbHost` — mount one inside each scoped area layout
|
|
116
|
+
- `BbHost` — mount one inside each scoped area layout when toasts need the
|
|
117
|
+
area's look.
|
|
116
118
|
- The [passthrough guide](./guides/passthrough.md) — grammar, merging and the
|
|
117
119
|
full parts table.
|
|
118
120
|
|
package/dist/ai/BbTable.md
CHANGED
|
@@ -78,7 +78,9 @@ needs is declared here, not in markup:
|
|
|
78
78
|
even when the value is nullish, so a virtual column whose `key` matches no
|
|
79
79
|
field can still compute from `item`; set `formatOnNull: false` when a
|
|
80
80
|
formatter must only see real values.
|
|
81
|
-
- **`placeholder`** fills the cell when the pipeline still ends nullish.
|
|
81
|
+
- **`placeholder`** fills the cell when the pipeline still ends nullish. Its
|
|
82
|
+
cell carries `--placeholder`, a cell with a value `--value`: style a blank
|
|
83
|
+
through those, not a slot ([Empty cells](#empty-cells-value-and-placeholder)).
|
|
82
84
|
- **`align`** (`'left' | 'center' | 'right'`) per column; the table-level
|
|
83
85
|
`align` prop sets the default for the whole table (`left`).
|
|
84
86
|
- **`width`** freezes the column: numbers and bare numeric strings are px
|
|
@@ -102,7 +104,8 @@ needs is declared here, not in markup:
|
|
|
102
104
|
takes them, once, when the page hydrates.) The floors read every row up
|
|
103
105
|
to 2,000; past that, the first 1,000 and a sample across the rest (a
|
|
104
106
|
`virtual` table has no floors at all). No floor on `fixed` or
|
|
105
|
-
`virtual` tables, slot columns, or under a custom `#thead
|
|
107
|
+
`virtual` tables, slot columns, or under a custom `#thead`, so never slot a
|
|
108
|
+
column only to restyle its blank: use [`--placeholder`](#empty-cells-value-and-placeholder). A grid keyword or function is the track as written:
|
|
106
109
|
`'auto'`, `'2fr'`, `'minmax(0, 1fr)'` (a share that may shrink below its
|
|
107
110
|
content), `'fit-content(200px)'`. When _every_ column declares a length, the
|
|
108
111
|
lengths become floors and the surplus is shared in proportion to their
|
|
@@ -3529,6 +3532,60 @@ root (`--cue-w: 0px` turns it off):
|
|
|
3529
3532
|
}
|
|
3530
3533
|
```
|
|
3531
3534
|
|
|
3535
|
+
#### Empty cells: `--value` and `--placeholder`
|
|
3536
|
+
|
|
3537
|
+
Every data cell says what the column's pipeline (`formatter`, then
|
|
3538
|
+
`placeholder`) produced: **`bb-table__cell--value`** when it shows a value,
|
|
3539
|
+
**`bb-table__cell--placeholder`** when the value was empty and the
|
|
3540
|
+
column's `placeholder` shows instead. The same two are `pt` states on
|
|
3541
|
+
`cell`. The class names the outcome, not the text, so a placeholder can read
|
|
3542
|
+
"–", "N/D" or anything else and the styling holds. A cell whose value is empty
|
|
3543
|
+
with no `placeholder` has neither. Slot cells carry it too (the class follows
|
|
3544
|
+
the `content` the slot is handed); the select, drag and actions cells never
|
|
3545
|
+
do.
|
|
3546
|
+
|
|
3547
|
+
```vue
|
|
3548
|
+
<script setup lang="ts">
|
|
3549
|
+
import { BbTable, type BbTableColumn } from 'bitboss-ui';
|
|
3550
|
+
|
|
3551
|
+
type Person = { id: number; name: string; email: string | null; city: string };
|
|
3552
|
+
|
|
3553
|
+
const blank = (value: unknown) =>
|
|
3554
|
+
typeof value === 'string' && value.trim() === '' ? null : value;
|
|
3555
|
+
|
|
3556
|
+
const columns: Array<BbTableColumn<Person>> = [
|
|
3557
|
+
{ key: 'name', label: 'Nome' },
|
|
3558
|
+
{ key: 'email', label: 'Email', placeholder: 'N/D' },
|
|
3559
|
+
{ key: 'city', label: 'Provincia', placeholder: '–', formatter: blank },
|
|
3560
|
+
];
|
|
3561
|
+
|
|
3562
|
+
const people: Person[] = [
|
|
3563
|
+
{ id: 1, name: 'Giulia Bianchi', email: null, city: 'Milano' },
|
|
3564
|
+
{ id: 2, name: 'Marco Rossi', email: 'marco@example.com', city: ' ' },
|
|
3565
|
+
];
|
|
3566
|
+
</script>
|
|
3567
|
+
|
|
3568
|
+
<template>
|
|
3569
|
+
<BbTable
|
|
3570
|
+
:columns="columns"
|
|
3571
|
+
item-value="id"
|
|
3572
|
+
:items="people"
|
|
3573
|
+
pt:cell:placeholder="text-(--bb-text-muted)"
|
|
3574
|
+
/>
|
|
3575
|
+
</template>
|
|
3576
|
+
```
|
|
3577
|
+
|
|
3578
|
+
Or in CSS, once for the whole app:
|
|
3579
|
+
`.bb-table__cell--placeholder { color: var(--bb-text-muted); }`.
|
|
3580
|
+
|
|
3581
|
+
- **The placeholder shows only for `null` / `undefined`.** An empty or
|
|
3582
|
+
whitespace-only string is a value. To treat it as blank, return `null` from
|
|
3583
|
+
the `formatter` (`blank` above), and the placeholder takes over.
|
|
3584
|
+
- **Don't slot a column just to restyle its blank.** A slot column gets no
|
|
3585
|
+
width floor (see Columns), so a wrapper that slots every column to print a
|
|
3586
|
+
muted dash costs every column its floor. `placeholder` plus the class does
|
|
3587
|
+
the same with none of that.
|
|
3588
|
+
|
|
3532
3589
|
#### The table as a card
|
|
3533
3590
|
|
|
3534
3591
|
The root paints no background, border or radius of its own — it is the
|
|
@@ -3578,7 +3635,7 @@ through element names, which match nothing:
|
|
|
3578
3635
|
| header cell | `.bb-table__cell-column-header` (+ `--select`, `--actions`) | `columnheader` |
|
|
3579
3636
|
| body group | `.bb-table__body` | `rowgroup` |
|
|
3580
3637
|
| data row | `.bb-table__row` (+ `--highlighted`) | `row` |
|
|
3581
|
-
| data cell | `.bb-table__cell` (+ `--select`)
|
|
3638
|
+
| data cell | `.bb-table__cell` (+ `--select`; `--value` / `--placeholder`: what the pipeline produced) | `cell` (`gridcell` with `keyboard-navigation`) |
|
|
3582
3639
|
| actions cell | `.bb-table__cell--actions` | `cell` (`gridcell` with `keyboard-navigation`) |
|
|
3583
3640
|
| expand row | `.bb-table-expand__row` > `.bb-table-expand__cell` | `row` > `cell` (`gridcell`) |
|
|
3584
3641
|
| empty state | `.bb-table-empty__row` > `.bb-table-empty__cell` | `row` > `cell` |
|
|
@@ -3721,7 +3778,8 @@ three glyphs: `sort-icon`, `select-icon` (each row's checkbox or radio and
|
|
|
3721
3778
|
the select-all) and `drag-icon` (on the chip a column drag carries). The grid
|
|
3722
3779
|
is `div`s with ARIA roles, so these are parts, not `th` / `td` selectors.
|
|
3723
3780
|
|
|
3724
|
-
States: `loading` and `empty` (the table); `
|
|
3781
|
+
States: `loading` and `empty` (the table); `value` / `placeholder` per data
|
|
3782
|
+
cell (what its pipeline produced, see [Empty cells](#empty-cells-value-and-placeholder)); `selected`, `highlighted`,
|
|
3725
3783
|
`expanded` and `disabled` resolved per row — a cell takes its row's states,
|
|
3726
3784
|
a row's `select-icon` its `selected` / `disabled`, and its `expand` its
|
|
3727
3785
|
`selected` / `highlighted` / `expanded`; `sorted` /
|
|
@@ -4176,7 +4234,7 @@ for a preset that fits any row type (never `<any>`), not an imported
|
|
|
4176
4234
|
|
|
4177
4235
|
| Prop | Type | Default | Required | Description |
|
|
4178
4236
|
| --- | --- | --- | --- | --- |
|
|
4179
|
-
| `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `body`, `caption`, `cell`, `cellColumnHeader`, `dragHandle`, `dragIcon`, `expand`, `firstRow`, `foot`, `head`, `headerRow`, `lastRow`, `root`, `row`, `selectIcon`, `sortIcon`, `table`. States: `disabled`, `empty`, `expanded`, `highlighted`, `indeterminate`, `loading`, `selected`, `sorted`, `sortedDesc`. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbTableProps<Row>['pt']` (`BbTableProps['pt']` for a preset that fits any row type, never `<any>`) (`PtValue` is not exported): § Typing `pt` in `<script>`. |
|
|
4237
|
+
| `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `body`, `caption`, `cell`, `cellColumnHeader`, `dragHandle`, `dragIcon`, `expand`, `firstRow`, `foot`, `head`, `headerRow`, `lastRow`, `root`, `row`, `selectIcon`, `sortIcon`, `table`. States: `disabled`, `empty`, `expanded`, `highlighted`, `indeterminate`, `loading`, `placeholder`, `selected`, `sorted`, `sortedDesc`, `value`. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbTableProps<Row>['pt']` (`BbTableProps['pt']` for a preset that fits any row type, never `<any>`) (`PtValue` is not exported): § Typing `pt` in `<script>`. |
|
|
4180
4238
|
| `accessibleLabel` | `((columns: MappedCell[], item: any) => string) \| undefined` | | | The label of each row's selection checkbox, from `(columns, item)`. Unset: the row's name in the locale's select template (its `rowHeader` cells, else its first column: "Select INV-1041"). The cells arrive in render order: look one up by `key`, never by position. |
|
|
4181
4239
|
| `actionsText` | `string \| undefined` | | | Label used in the header of the actions column. |
|
|
4182
4240
|
| `align` | `"left" \| "center" \| "right" \| undefined` | `"left"` | | Text alignment of the columns. |
|
|
@@ -4263,6 +4321,8 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
4263
4321
|
|
|
4264
4322
|
| State | When it is on |
|
|
4265
4323
|
| --- | --- |
|
|
4324
|
+
| `value` | Per node, on a DATA `cell`: the formatter / placeholder pipeline produced a value (not `null` / `undefined`), slot cells included (`bb-table__cell--value`). Not on the select, drag or actions cells. |
|
|
4325
|
+
| `placeholder` | Per node, on a DATA `cell`: the value was empty and the column's `placeholder` shows instead, whatever its text (`bb-table__cell--placeholder`). A cell with an empty value and no `placeholder` has neither state. |
|
|
4266
4326
|
| `empty` | Component-wide: there are no rows (`bb-table--empty`). |
|
|
4267
4327
|
| `sorted` | Per node, on `cellColumnHeader` and `sortIcon`: the column is sorted, either direction (`bb-table__cell-column-header--sorted`). |
|
|
4268
4328
|
| `sortedDesc` | Per node, on `cellColumnHeader` and `sortIcon`: sorted descending (`bb-table__cell-column-header--sorted-desc`). Ascending is `sorted` alone. |
|
package/dist/ai/changelog.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 3,
|
|
3
3
|
"library": "bitboss-ui",
|
|
4
|
-
"version": "3.0.0-beta.
|
|
4
|
+
"version": "3.0.0-beta.63",
|
|
5
5
|
"upgrade": "v2-to-v3",
|
|
6
6
|
"guide": "ai/guides/migration/v2-to-v3.md",
|
|
7
7
|
"legend": {
|
|
@@ -72,7 +72,8 @@
|
|
|
72
72
|
"3.0.0-beta.59",
|
|
73
73
|
"3.0.0-beta.60",
|
|
74
74
|
"3.0.0-beta.61",
|
|
75
|
-
"3.0.0-beta.62"
|
|
75
|
+
"3.0.0-beta.62",
|
|
76
|
+
"3.0.0-beta.63"
|
|
76
77
|
],
|
|
77
78
|
"unpublished": [
|
|
78
79
|
"3.0.0-alpha.2",
|
|
@@ -95,7 +96,7 @@
|
|
|
95
96
|
],
|
|
96
97
|
"summary": {
|
|
97
98
|
"renames": 220,
|
|
98
|
-
"behaviourBreaks":
|
|
99
|
+
"behaviourBreaks": 231,
|
|
99
100
|
"bySurface": {
|
|
100
101
|
"prop": 15,
|
|
101
102
|
"option": 1,
|
|
@@ -106,7 +107,7 @@
|
|
|
106
107
|
"class": 138
|
|
107
108
|
},
|
|
108
109
|
"unreleased": 0,
|
|
109
|
-
"added":
|
|
110
|
+
"added": 416
|
|
110
111
|
},
|
|
111
112
|
"added": {
|
|
112
113
|
"3.0.0-alpha.1": [
|
|
@@ -2085,6 +2086,16 @@
|
|
|
2085
2086
|
},
|
|
2086
2087
|
"table · keep short multi-word values on one line",
|
|
2087
2088
|
"table · sortable headers describe shift+enter"
|
|
2089
|
+
],
|
|
2090
|
+
"3.0.0-beta.63": [
|
|
2091
|
+
"table · cells name what the pipeline produced, value or placeholder",
|
|
2092
|
+
{
|
|
2093
|
+
"text": "confirm · every confirm() call opens its own dialog",
|
|
2094
|
+
"components": [
|
|
2095
|
+
"BbHost",
|
|
2096
|
+
"BbPtScope"
|
|
2097
|
+
]
|
|
2098
|
+
}
|
|
2088
2099
|
]
|
|
2089
2100
|
},
|
|
2090
2101
|
"breaking": [
|
|
@@ -8487,6 +8498,19 @@
|
|
|
8487
8498
|
"ruling": "owner 2026-10-16 (Q75.3) + 2026-10-21 (Q76.9 e)",
|
|
8488
8499
|
"guide": "v2-to-v3.md § 6 item 96 + BbTable.md § Columns, § Column resize",
|
|
8489
8500
|
"firstReleasedIn": "3.0.0-beta.62"
|
|
8501
|
+
},
|
|
8502
|
+
{
|
|
8503
|
+
"id": "f370",
|
|
8504
|
+
"kind": "behaviour",
|
|
8505
|
+
"summary": "confirm(): every call opens its own dialog; a new one covers the open one instead of resolving it false; it takes the caller's pt scope; new stack option",
|
|
8506
|
+
"components": [
|
|
8507
|
+
"BbConfirm",
|
|
8508
|
+
"BbHost"
|
|
8509
|
+
],
|
|
8510
|
+
"description": "confirm(): every call opens its own dialog, under the caller's provides. A call while another confirm is open COVERS it (a shared confirm BbDialog stack) instead of resolving it false: the first stays pending and comes back when the newer one closes, so two un-awaited calls ask both, newest first; Escape and the backdrop answer only the top one. close() hides the newest open confirm opened through the same useConfirm() (it used to hide THE confirm); dismissAll() dismisses every open one. The dialog takes the <BbPtScope> and tokens of the component that called useConfirm() (a store's: the host's), so areas need no host of their own for confirms; a component portal injects from the caller's tree. New message option stack (join a dialog's stack: the confirm replaces its view)",
|
|
8511
|
+
"ruling": "owner 2026-10-22 (Q75.9)",
|
|
8512
|
+
"guide": "v2-to-v3.md § 6 item 97 + components/use-confirm.md + components/bb-host.md + BbConfirm.md § Several confirms at once + useConfirm.md",
|
|
8513
|
+
"firstReleasedIn": "3.0.0-beta.63"
|
|
8490
8514
|
}
|
|
8491
8515
|
]
|
|
8492
8516
|
}
|