bitboss-ui 3.0.0-beta.61 → 3.0.0-beta.62
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-mcp.mjs +103 -15
- package/bin/bitboss-ui.mjs +3 -1
- package/dist/ai/BbAlert.md +3 -0
- package/dist/ai/BbForm.md +2 -1
- package/dist/ai/BbTable.md +116 -43
- package/dist/ai/BbToast.md +2 -1
- package/dist/ai/changelog.json +46 -4
- package/dist/ai/components.json +4 -4
- package/dist/ai/composables/useToast.md +15 -15
- package/dist/ai/guides/eslint-rules.md +2 -0
- package/dist/ai/guides/inertia-helpers.md +39 -7
- package/dist/ai/guides/installation-and-plugin-setup.md +2 -1
- package/dist/ai/guides/migration/v2-to-v3.md +14 -0
- package/dist/ai/guides/migration/v3-beta-tooling.md +6 -0
- package/dist/ai/guides/passthrough.md +2 -2
- package/dist/ai/guides/validated-forms.md +3 -2
- package/dist/ai/helpers/inertia/manifest.json +18 -10
- package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +11 -2
- package/dist/ai/helpers/inertia/usePromiseForm.ts +17 -3
- package/dist/ai/helpers/inertia/useResourceContext.ts +1 -2
- package/dist/ai/manifest/components/BbTable.json +9 -7
- package/dist/ai/manifest/components/BbTable.tree.json +4 -1
- package/dist/ai/manifest/index.json +2 -2
- package/dist/ai/manifest/types.advanced.json +1 -1
- package/dist/ai/recipes/inertia/onboarding.md +10 -6
- package/dist/ai/recipes/inertia/record-form.md +6 -2
- package/dist/ai/recipes/inertia/wizard-form.md +9 -5
- package/dist/ai/source/BbDatePickerInput.md +6 -1
- package/dist/ai/source/BbForm.md +7 -2
- package/dist/ai/source/BbTable.md +403 -111
- package/dist/ai/source/BbTimePickerInput.md +5 -1
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +211 -210
- package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +3 -1
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1252 -1180
- package/dist/components/BbTable/BbTableExpandRow.d.ts +1 -1
- package/dist/components/BbTable/BbTableExpandRow.js +29 -25
- package/dist/components/BbTable/types.d.ts +37 -15
- package/dist/components/BbTable/types.js +1 -0
- package/dist/components/BbTable/utils.d.ts +73 -13
- package/dist/components/BbTable/utils.js +148 -37
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +108 -106
- package/dist/composables/useFormBinding.d.ts +5 -0
- package/dist/composables/useFormBinding.js +2 -1
- package/dist/i18n/locales/cs.json +1 -0
- package/dist/i18n/locales/da.json +1 -0
- package/dist/i18n/locales/de-CH.json +1 -0
- package/dist/i18n/locales/de.json +1 -0
- package/dist/i18n/locales/el.json +1 -0
- package/dist/i18n/locales/en-GB.json +1 -0
- package/dist/i18n/locales/en.json +1 -0
- package/dist/i18n/locales/es-MX.json +1 -0
- package/dist/i18n/locales/es.json +1 -0
- package/dist/i18n/locales/fi.json +1 -0
- package/dist/i18n/locales/fr.json +1 -0
- package/dist/i18n/locales/hu.json +1 -0
- package/dist/i18n/locales/it.json +1 -0
- package/dist/i18n/locales/ja.json +1 -0
- package/dist/i18n/locales/ko.json +1 -0
- package/dist/i18n/locales/nb.json +1 -0
- package/dist/i18n/locales/nl.json +1 -0
- package/dist/i18n/locales/pl.json +1 -0
- package/dist/i18n/locales/pt-BR.json +1 -0
- package/dist/i18n/locales/pt-PT.json +1 -0
- package/dist/i18n/locales/ro.json +1 -0
- package/dist/i18n/locales/ru.json +1 -0
- package/dist/i18n/locales/sv.json +1 -0
- package/dist/i18n/locales/tr.json +1 -0
- package/dist/i18n/locales/uk.json +1 -0
- package/dist/i18n/locales/zh-CN.json +1 -0
- package/dist/i18n/locales/zh-HK.json +1 -0
- package/dist/i18n/locales/zh-TW.json +1 -0
- package/dist/llms-full.txt +231 -85
- package/dist/llms-medium.txt +2 -1
- package/dist/locale-blueprint.json +1 -0
- package/dist/styles.css +2 -2
- package/dist/types/ptComponentMap.d.ts +1 -1
- package/dist/utils/versionCheck.js +1 -1
- package/package.json +8 -4
- package/scripts/lib/doc-sections.mjs +26 -6
- package/scripts/lib/eslint-disable.mjs +2 -0
- package/scripts/lib/eslint-plugin.d.ts +2 -0
- package/scripts/lib/eslint-plugin.mjs +105 -0
- package/scripts/lib/validate-bb-markup.mjs +182 -66
package/bin/bitboss-ui-mcp.mjs
CHANGED
|
@@ -1923,9 +1923,17 @@ let cachedDocIndex = null;
|
|
|
1923
1923
|
function docIndex() {
|
|
1924
1924
|
if (cachedDocIndex) return cachedDocIndex;
|
|
1925
1925
|
const entries = [];
|
|
1926
|
-
|
|
1926
|
+
// What a document says before its first `##` (its lead), and then every
|
|
1927
|
+
// section. The lead used to be skipped, and a composable was cut at 4000
|
|
1928
|
+
// chars: useToast's object-form row sat past the cut (2026-10-20).
|
|
1929
|
+
// `check-mcp` walks dist/ai and fails on any doc unit left out of here.
|
|
1930
|
+
const addSections = (source, markdown, read, lead, skip = () => false) => {
|
|
1931
|
+
const intro = stripFrontmatter(markdown).split(/^## /m)[0].trim();
|
|
1932
|
+
if (lead && intro.length >= 40)
|
|
1933
|
+
entries.push({ source, ...lead, text: intro });
|
|
1927
1934
|
for (const section of splitSections(markdown)) {
|
|
1928
|
-
|
|
1935
|
+
// `skip` first: it tracks the `##` it is under, even a bare one.
|
|
1936
|
+
if (skip(section) || section.own.length < 40) continue;
|
|
1929
1937
|
entries.push({
|
|
1930
1938
|
source,
|
|
1931
1939
|
section: section.title,
|
|
@@ -1936,13 +1944,18 @@ function docIndex() {
|
|
|
1936
1944
|
};
|
|
1937
1945
|
const guidesDir = join(AI_ROOT, 'guides');
|
|
1938
1946
|
for (const path of collectGuidePaths(guidesDir)) {
|
|
1947
|
+
const markdown = readFileSync(join(guidesDir, path), 'utf-8');
|
|
1939
1948
|
addSections(
|
|
1940
1949
|
`guide ${path}`,
|
|
1941
|
-
|
|
1950
|
+
markdown,
|
|
1942
1951
|
(title) => ({
|
|
1943
1952
|
tool: 'get_guide',
|
|
1944
1953
|
args: { name: path, sections: [title] },
|
|
1945
|
-
})
|
|
1954
|
+
}),
|
|
1955
|
+
{
|
|
1956
|
+
section: frontmatter(markdown).title ?? path,
|
|
1957
|
+
read: { tool: 'get_guide', args: { name: path } },
|
|
1958
|
+
}
|
|
1946
1959
|
);
|
|
1947
1960
|
}
|
|
1948
1961
|
const composablesDir = join(AI_ROOT, 'composables');
|
|
@@ -1952,16 +1965,22 @@ function docIndex() {
|
|
|
1952
1965
|
)) {
|
|
1953
1966
|
const markdown = readFileSync(join(composablesDir, file), 'utf-8');
|
|
1954
1967
|
const name = file.slice(0, -3);
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1968
|
+
addSections(
|
|
1969
|
+
`composable ${name}`,
|
|
1970
|
+
markdown,
|
|
1971
|
+
(title) => ({
|
|
1972
|
+
tool: 'get_composable',
|
|
1973
|
+
args: { name, sections: [title] },
|
|
1974
|
+
}),
|
|
1975
|
+
{
|
|
1976
|
+
section: frontmatter(markdown).summary ?? name,
|
|
1977
|
+
read: { tool: 'get_composable', args: { name } },
|
|
1978
|
+
}
|
|
1979
|
+
);
|
|
1961
1980
|
}
|
|
1962
1981
|
}
|
|
1963
1982
|
const manifest = loadComponentsManifest();
|
|
1964
|
-
for (const component of manifest.components
|
|
1983
|
+
for (const component of manifest.components) {
|
|
1965
1984
|
const path = join(PACKAGE_ROOT, 'dist', component.contract ?? '');
|
|
1966
1985
|
if (component.contract && existsSync(path)) {
|
|
1967
1986
|
for (const section of contractGuideSections(
|
|
@@ -1979,6 +1998,11 @@ function docIndex() {
|
|
|
1979
1998
|
});
|
|
1980
1999
|
}
|
|
1981
2000
|
}
|
|
2001
|
+
// BbToast and BbConfirm are reference-only (a composable drives them)
|
|
2002
|
+
// but their guides are the docs: § Variant icons never ranked
|
|
2003
|
+
// (progetto-32, 2026-10-20). Internals have no guide, so nothing else
|
|
2004
|
+
// comes in; their props stay out.
|
|
2005
|
+
if (component.referenceOnly) continue;
|
|
1982
2006
|
for (const prop of component.props) {
|
|
1983
2007
|
if (prop.name.startsWith('pt')) continue;
|
|
1984
2008
|
entries.push({
|
|
@@ -2003,6 +2027,45 @@ function docIndex() {
|
|
|
2003
2027
|
},
|
|
2004
2028
|
});
|
|
2005
2029
|
}
|
|
2030
|
+
// Slots, v-models and pt parts / states: `members` serves each row, and
|
|
2031
|
+
// "BbSelect option slot" had nothing to find.
|
|
2032
|
+
const member = (section, text, name) =>
|
|
2033
|
+
entries.push({
|
|
2034
|
+
source: `component ${component.name}`,
|
|
2035
|
+
section,
|
|
2036
|
+
text,
|
|
2037
|
+
read: {
|
|
2038
|
+
tool: 'get_component',
|
|
2039
|
+
args: { name: component.name, members: [name] },
|
|
2040
|
+
},
|
|
2041
|
+
});
|
|
2042
|
+
for (const slot of component.slots ?? [])
|
|
2043
|
+
member(
|
|
2044
|
+
`slot #${slot.name}`,
|
|
2045
|
+
`#${slot.name} slot. ${slot.description ?? ''}`,
|
|
2046
|
+
`#${slot.name}`
|
|
2047
|
+
);
|
|
2048
|
+
for (const model of component.models ?? []) {
|
|
2049
|
+
const name =
|
|
2050
|
+
model.name === 'modelValue' ? 'v-model' : `v-model:${model.name}`;
|
|
2051
|
+
member(
|
|
2052
|
+
name,
|
|
2053
|
+
`${name}: ${model.type ?? ''}. ${model.description ?? ''}`,
|
|
2054
|
+
name
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
for (const part of component.pt?.parts ?? [])
|
|
2058
|
+
member(
|
|
2059
|
+
`pt part ${part.name}`,
|
|
2060
|
+
`pt:${part.name} part. ${part.description ?? ''}`,
|
|
2061
|
+
`pt:${part.name}`
|
|
2062
|
+
);
|
|
2063
|
+
for (const state of component.pt?.states ?? [])
|
|
2064
|
+
member(
|
|
2065
|
+
`pt state ${state.name}`,
|
|
2066
|
+
`pt state ${state.name}. ${state.description ?? ''}`,
|
|
2067
|
+
`pt:${state.name}`
|
|
2068
|
+
);
|
|
2006
2069
|
/*
|
|
2007
2070
|
* The rename registry: an agent upgrading an app searches the OLD name
|
|
2008
2071
|
* (`enabled-while-loading`, `pt:input`, `#no-data`), which no current
|
|
@@ -2053,6 +2116,22 @@ function docIndex() {
|
|
|
2053
2116
|
text: frontmatter(markdown).summary ?? name,
|
|
2054
2117
|
read: { tool: 'get_recipe', args: { platform, name } },
|
|
2055
2118
|
});
|
|
2119
|
+
// The prose sections; the code files under "The code" are `files`.
|
|
2120
|
+
let inCode = false;
|
|
2121
|
+
addSections(
|
|
2122
|
+
`recipe ${platform}/${name}`,
|
|
2123
|
+
markdown,
|
|
2124
|
+
(title) => ({
|
|
2125
|
+
tool: 'get_recipe',
|
|
2126
|
+
args: { platform, name, sections: [title] },
|
|
2127
|
+
}),
|
|
2128
|
+
null,
|
|
2129
|
+
(section) => {
|
|
2130
|
+
if (section.level === 2)
|
|
2131
|
+
inCode = /^the (code|files)\b/i.test(section.title);
|
|
2132
|
+
return inCode;
|
|
2133
|
+
}
|
|
2134
|
+
);
|
|
2056
2135
|
}
|
|
2057
2136
|
}
|
|
2058
2137
|
// Class renames (the sweep map rows of changelog.json): an app's
|
|
@@ -2151,10 +2230,18 @@ function docIndex() {
|
|
|
2151
2230
|
if (existsSync(readme)) {
|
|
2152
2231
|
// Served by get_guide under the name 'README' (it used to point at a
|
|
2153
2232
|
// "read file" call, which is not a tool).
|
|
2154
|
-
addSections(
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2233
|
+
addSections(
|
|
2234
|
+
'README',
|
|
2235
|
+
readFileSync(readme, 'utf-8'),
|
|
2236
|
+
(title) => ({
|
|
2237
|
+
tool: 'get_guide',
|
|
2238
|
+
args: { name: 'README', sections: [title] },
|
|
2239
|
+
}),
|
|
2240
|
+
{
|
|
2241
|
+
section: 'README',
|
|
2242
|
+
read: { tool: 'get_guide', args: { name: 'README' } },
|
|
2243
|
+
}
|
|
2244
|
+
);
|
|
2158
2245
|
}
|
|
2159
2246
|
cachedDocIndex = entries;
|
|
2160
2247
|
return entries;
|
|
@@ -3341,6 +3428,7 @@ export {
|
|
|
3341
3428
|
SERVER_INSTRUCTIONS,
|
|
3342
3429
|
searchComponents,
|
|
3343
3430
|
searchDocs,
|
|
3431
|
+
docIndex,
|
|
3344
3432
|
getComposable,
|
|
3345
3433
|
getComponent,
|
|
3346
3434
|
listTokens,
|
package/bin/bitboss-ui.mjs
CHANGED
|
@@ -1735,7 +1735,9 @@ Commands:
|
|
|
1735
1735
|
\`warnings[]\` (never fail the run) use the same shape with
|
|
1736
1736
|
\`severity: "warning"\`: \`likely-squashed-slot\` (a slot
|
|
1737
1737
|
name that looks like a camelCase key squashed, e.g.
|
|
1738
|
-
\`#createdat\`), \`
|
|
1738
|
+
\`#createdat\`), \`computed-slot-key\` (a computed slot
|
|
1739
|
+
name over keys \`check\` cannot see, not spelled
|
|
1740
|
+
through \`slotKey(…)\`), \`local-bb-component\` (your own
|
|
1739
1741
|
component uses the \`Bb\` prefix; rename it),
|
|
1740
1742
|
\`single-reason\` (an \`items\` provider that tests
|
|
1741
1743
|
\`reason\` against one cause other than \`'search'\`;
|
package/dist/ai/BbAlert.md
CHANGED
|
@@ -107,6 +107,9 @@ distinct success tone.
|
|
|
107
107
|
|
|
108
108
|
#### Variant icons
|
|
109
109
|
|
|
110
|
+
A default icon per variant, set once for the whole app: the object form of
|
|
111
|
+
the plugin's `alertVariants` option.
|
|
112
|
+
|
|
110
113
|
```ts
|
|
111
114
|
// vite.config.ts (Nuxt: the `bitboss` key)
|
|
112
115
|
bitbossUi({
|
package/dist/ai/BbForm.md
CHANGED
|
@@ -1617,7 +1617,8 @@ The `id` is also the `<form>`'s own (it follows a BbForm; a plain `<form>`
|
|
|
1617
1617
|
submits but has no save state to follow), so a `<BbButton form="id" type="submit">`
|
|
1618
1618
|
outside it submits it too, through the same validation, and spins while the
|
|
1619
1619
|
save runs exactly like a submit button inside (`disable-auto-loading` opts
|
|
1620
|
-
out): no `:loading` to bind.
|
|
1620
|
+
out): no `:loading` to bind. Server errors (`setErrors`, `field-errors`) then
|
|
1621
|
+
focus the first failing field, as they do after a submit from inside.
|
|
1621
1622
|
|
|
1622
1623
|
```vue
|
|
1623
1624
|
<script setup lang="ts">
|
package/dist/ai/BbTable.md
CHANGED
|
@@ -88,11 +88,21 @@ needs is declared here, not in markup:
|
|
|
88
88
|
(the table is a CSS grid — the tracks are the width API, there is no
|
|
89
89
|
`table-layout`). An unfrozen text column also has a **floor estimated from
|
|
90
90
|
what it shows**: short values (IDs, emails, dates) ask for one line, prose
|
|
91
|
-
for about three, fitted to the room the sized columns leave
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
a
|
|
95
|
-
|
|
91
|
+
for about three, fitted to the room the sized columns leave. Values a line
|
|
92
|
+
break would harm stay whole: a short name or status ("Poltrona 10", "In
|
|
93
|
+
attesa di verifica"), an amount with its currency, a range or pair ("0,00 € /
|
|
94
|
+
450,00 €"), a date or code ("16/10/2026", a grouped IBAN). When room runs
|
|
95
|
+
short, longer values wrap first, then prose narrows, then a long heading of
|
|
96
|
+
several words takes two lines; a table that scrolls sideways anyway keeps
|
|
97
|
+
all of those whole. Only a table that would otherwise _start_ scrolling
|
|
98
|
+
wraps them, and long-form text never runs wider than a readable measure.
|
|
99
|
+
You rarely need `whitespace-nowrap` in a `td-class`. The header is always
|
|
100
|
+
part of that floor, so a heading never clips. (On a server-rendered page
|
|
101
|
+
the server cannot know the width: a table whose headings need two lines
|
|
102
|
+
takes them, once, when the page hydrates.) The floors read every row up
|
|
103
|
+
to 2,000; past that, the first 1,000 and a sample across the rest (a
|
|
104
|
+
`virtual` table has no floors at all). No floor on `fixed` or
|
|
105
|
+
`virtual` tables, slot columns, or under a custom `#thead`. A grid keyword or function is the track as written:
|
|
96
106
|
`'auto'`, `'2fr'`, `'minmax(0, 1fr)'` (a share that may shrink below its
|
|
97
107
|
content), `'fit-content(200px)'`. When _every_ column declares a length, the
|
|
98
108
|
lengths become floors and the surplus is shared in proportion to their
|
|
@@ -354,7 +364,9 @@ not sure — write the name through the function instead of by hand:
|
|
|
354
364
|
`#[slotKey('Qualità')]`, with `import { slotKey } from 'bitboss-ui'`; the same
|
|
355
365
|
goes for slot names built in code (columns from config, a dynamic `<template>`
|
|
356
366
|
loop). A hand copy that differs by one character makes the slot silently never
|
|
357
|
-
match; `bitboss-ui check` catches it when `columns` is in the same file
|
|
367
|
+
match; `bitboss-ui check` catches it when `columns` is in the same file, and
|
|
368
|
+
warns on a loop over keys it cannot see (`#[column.key]` over a prop) until
|
|
369
|
+
the name goes through `slotKey`. Keep the column in `columns`
|
|
358
370
|
even when you fully slot it: label, alignment and width still come from there.
|
|
359
371
|
|
|
360
372
|
Body cell scope: `content` (the formatted value), `item` (raw row), `value`
|
|
@@ -692,7 +704,9 @@ empty the table shows its empty row — localized default text, overridable via
|
|
|
692
704
|
`empty-text` or fully via the `#empty` slot. That slot fills the table's own
|
|
693
705
|
full-width empty-state cell (already centred, already spanning every column),
|
|
694
706
|
so pass the content — a message, a "clear filters" button — not a row of your
|
|
695
|
-
own.
|
|
707
|
+
own. On a table that scrolls sideways (wide columns at phone width) the
|
|
708
|
+
content centres in the visible part, not on the whole grid, and stays there
|
|
709
|
+
as the table scrolls.
|
|
696
710
|
|
|
697
711
|
`loading-text` is the loading row's `aria-live` announcement. Like
|
|
698
712
|
`empty-text` it has a **localized default** (`common.loadingText` —
|
|
@@ -1096,13 +1110,19 @@ scriptable from anywhere via `useBbTableContext`
|
|
|
1096
1110
|
Mark columns `sortable` and bind `v-model:sort` — an ordered
|
|
1097
1111
|
`BbTableSortEntry[]` (`[columnKey, 'asc' | 'desc']`). A click anywhere on a
|
|
1098
1112
|
sortable header (its whitespace included — AG Grid parity; the built-in
|
|
1099
|
-
button is the keyboard/AT control)
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1113
|
+
button is the keyboard/AT control), or Enter on it, sorts by **that column
|
|
1114
|
+
alone**, cycling it unsorted → asc → desc → removed (`[]`).
|
|
1115
|
+
|
|
1116
|
+
**Shift+click** (or Shift+Enter) adds the column instead: it joins the end of
|
|
1117
|
+
the model, a direction flip updates its entry in place (it keeps its priority)
|
|
1118
|
+
and its third click removes it alone; the other entries are never touched. Set
|
|
1119
|
+
`multi-sort` when a plain click should add too. The array order **is** the
|
|
1120
|
+
priority: first entry sorts first. A several-entry model you write yourself
|
|
1121
|
+
is shown as is in either mode; the next plain click replaces it.
|
|
1122
|
+
|
|
1123
|
+
The table only reports the model; **apply it to your data** (client-side, as
|
|
1124
|
+
below) or forward it to the server as `orderBy` and refetch via
|
|
1125
|
+
`dependencies`.
|
|
1106
1126
|
|
|
1107
1127
|
The affordance is one arrow: nothing at rest, a faint arrow previewed while
|
|
1108
1128
|
the header is hovered or focused, solid once the column is sorted (up for
|
|
@@ -1114,9 +1134,9 @@ third click.
|
|
|
1114
1134
|
```vue
|
|
1115
1135
|
<template>
|
|
1116
1136
|
<div class="flex max-w-2xl flex-col gap-1.5">
|
|
1117
|
-
<!-- Mark columns `sortable` and bind `v-model:sort`.
|
|
1118
|
-
|
|
1119
|
-
the data. -->
|
|
1137
|
+
<!-- Mark columns `sortable` and bind `v-model:sort`. A click sorts by
|
|
1138
|
+
that column (asc → desc → off), Shift+click adds it; the table only
|
|
1139
|
+
REPORTS the model — you sort the data. -->
|
|
1120
1140
|
<div
|
|
1121
1141
|
class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
|
|
1122
1142
|
>
|
|
@@ -1189,7 +1209,9 @@ const sortedInvoices = computed(() => {
|
|
|
1189
1209
|
|
|
1190
1210
|
A custom `#<key>:header` slot replaces the built-in sort button, but its scope
|
|
1191
1211
|
hands you `sortOrder` and `toggleSort` so your header can keep sorting alive
|
|
1192
|
-
(render your own button
|
|
1212
|
+
(render your own button with `@click="toggleSort"`: given the event, Shift adds
|
|
1213
|
+
the column like on the built-in header; `toggleSort()` with no event sorts by
|
|
1214
|
+
that column alone). To merely add something next
|
|
1193
1215
|
to the control — a resize handle, a filter icon — use
|
|
1194
1216
|
`#<key>:header:prepend/append` instead and keep the built-in button (see
|
|
1195
1217
|
"Custom cells and headers"). The column-level `sorted`
|
|
@@ -1211,7 +1233,8 @@ it **renders** in — an array of column keys, the same split as `sortable` +
|
|
|
1211
1233
|
Grid style, a chip with the label follows), release to commit. The same
|
|
1212
1234
|
header row is also one keyboard tab stop (the AG Grid grammar): ←/→ move
|
|
1213
1235
|
focus between headers, **Shift+←/→** move the column one slot
|
|
1214
|
-
(Shift+Home/End to the ends), Enter sorts a sortable header
|
|
1236
|
+
(Shift+Home/End to the ends), Enter sorts a sortable header (Shift+Enter
|
|
1237
|
+
adds it to the sort).
|
|
1215
1238
|
Each committed move writes the model once and is announced.
|
|
1216
1239
|
|
|
1217
1240
|
The model's contract is what makes a column panel trivial:
|
|
@@ -2014,6 +2037,33 @@ fixed first track).
|
|
|
2014
2037
|
The actions-column toggle remains valid — prefer it when expansion reveals
|
|
2015
2038
|
_detail about the row_ rather than _children of it_.
|
|
2016
2039
|
|
|
2040
|
+
#### Styling the detail area
|
|
2041
|
+
|
|
2042
|
+
The cell that holds `#expand` (it spans every column) is the `expand`
|
|
2043
|
+
passthrough part. It has no padding of its own, so the slot's content sits
|
|
2044
|
+
flush; give the area a surface or an inset there:
|
|
2045
|
+
|
|
2046
|
+
```vue
|
|
2047
|
+
<BbTable
|
|
2048
|
+
v-model:expanded-items="open"
|
|
2049
|
+
:columns="columns"
|
|
2050
|
+
:items="invoices"
|
|
2051
|
+
item-value="id"
|
|
2052
|
+
pt:expand="bg-(--bb-surface-hover) px-4 py-3"
|
|
2053
|
+
pt:expand:highlighted="bg-(--bb-muted)"
|
|
2054
|
+
>
|
|
2055
|
+
<template #expand="{ item }">…</template>
|
|
2056
|
+
</BbTable>
|
|
2057
|
+
```
|
|
2058
|
+
|
|
2059
|
+
It takes the data row's `selected`, `highlighted` and `expanded` (always
|
|
2060
|
+
on), and, like `pt:row`, a
|
|
2061
|
+
per-item function: `:pt:expand="({ item }) => item.overdue && 'bg-red-50'"`.
|
|
2062
|
+
It is not a `cell`, so `pt:cell` never reaches it: a table that moves its row
|
|
2063
|
+
rules off the cells (`pt:cell="border-b-0"`, a top rule on `pt:row`) takes
|
|
2064
|
+
the expand cell's off too (`pt:expand="border-b-0"`), or the line under each
|
|
2065
|
+
open row is drawn twice.
|
|
2066
|
+
|
|
2017
2067
|
### Reordering rows
|
|
2018
2068
|
|
|
2019
2069
|
`reorderable-rows` adds a slim drag handle at the start of every row: the user drags
|
|
@@ -2214,10 +2264,12 @@ keeps until that column's `width` changes:
|
|
|
2214
2264
|
- A resized width is always px; `width` still accepts `'20%'` / `'12rem'`
|
|
2215
2265
|
for what you declare yourself.
|
|
2216
2266
|
|
|
2217
|
-
Headers
|
|
2218
|
-
own heading — the label is the table's size hint, so an empty or
|
|
2219
|
-
with a long heading still reads on a narrow screen
|
|
2220
|
-
|
|
2267
|
+
Headers stay on one line. A column you have not sized is never narrower
|
|
2268
|
+
than its own heading — the label is the table's size hint, so an empty or
|
|
2269
|
+
slim column with a long heading still reads on a narrow screen. The one
|
|
2270
|
+
exception: a long heading of several words ("Numero e data emissione") takes
|
|
2271
|
+
two lines when the alternative is the table scrolling sideways; short
|
|
2272
|
+
headings never do, and no `pt` class is needed for it. Once a track is a length (a declared `width`, a user resize) the
|
|
2221
2273
|
label cannot widen it: squeezed, it ellipsizes and the sort arrow stays; at
|
|
2222
2274
|
the narrowest only the arrow (and the handle) survive, and the column is
|
|
2223
2275
|
still resizable. The data cells of a resized column clip with an ellipsis
|
|
@@ -3312,7 +3364,7 @@ const columns = [
|
|
|
3312
3364
|
];
|
|
3313
3365
|
```
|
|
3314
3366
|
|
|
3315
|
-
|
|
3367
|
+
Four rules:
|
|
3316
3368
|
|
|
3317
3369
|
- **The pin is the column's.** Under `order` / `reorderable` it travels with
|
|
3318
3370
|
the cell, and a `hidden` pinned column pins nothing. The offset is still
|
|
@@ -3327,6 +3379,15 @@ Three rules:
|
|
|
3327
3379
|
- **Nested tables pin against the ancestor scrollport.** A child that
|
|
3328
3380
|
inherits the parent's tracks has no scrollport of its own, so both tables'
|
|
3329
3381
|
pins land on the same visible edge (see Nested tables).
|
|
3382
|
+
- **Pinned cells sit at `z-index: 2`.** Body and header cells alike; under
|
|
3383
|
+
`fixed-headers` the stuck header band and its pinned headers sit at `3`,
|
|
3384
|
+
and so do the `fixed-first` / `fixed-last` rows; column resize handles sit
|
|
3385
|
+
at `1`. Cell content that sets its own `z-index` (a positioned badge with
|
|
3386
|
+
`z-10`, say) paints over the pinned column as it scrolls under it: keep
|
|
3387
|
+
such content at `z-index: 1` or lower, or put `isolate` on its wrapper so
|
|
3388
|
+
its layers stay inside it. The table root opens no stacking context of
|
|
3389
|
+
its own, so these values also count against the page: a sticky app bar
|
|
3390
|
+
that a scrolled table must pass under needs `z-index: 4` or more.
|
|
3330
3391
|
|
|
3331
3392
|
### Virtual rows
|
|
3332
3393
|
|
|
@@ -3652,21 +3713,24 @@ object form, a style and attributes — optionally only while a state is on.
|
|
|
3652
3713
|
Parts: `root` (the container), `caption` (the visible caption), `table` (the
|
|
3653
3714
|
grid), `head` / `body` / `foot` (the row groups), `header-row`,
|
|
3654
3715
|
`cell-column-header` (every header cell — the select and actions ones
|
|
3655
|
-
included, a broadcast), `row` (every DATA row, a broadcast)
|
|
3656
|
-
data cell — the select and actions cells included, a broadcast),
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3716
|
+
included, a broadcast), `row` (every DATA row, a broadcast), `cell` (every
|
|
3717
|
+
data cell — the select and actions cells included, a broadcast), `expand`
|
|
3718
|
+
(the cell holding an open row's `#expand`), `first-row` / `last-row` (the
|
|
3719
|
+
edge rows), `drag-handle` (each row's grip under `reorderable-rows`), and
|
|
3720
|
+
three glyphs: `sort-icon`, `select-icon` (each row's checkbox or radio and
|
|
3721
|
+
the select-all) and `drag-icon` (on the chip a column drag carries). The grid
|
|
3722
|
+
is `div`s with ARIA roles, so these are parts, not `th` / `td` selectors.
|
|
3660
3723
|
|
|
3661
3724
|
States: `loading` and `empty` (the table); `selected`, `highlighted`,
|
|
3662
3725
|
`expanded` and `disabled` resolved per row — a cell takes its row's states,
|
|
3663
|
-
|
|
3726
|
+
a row's `select-icon` its `selected` / `disabled`, and its `expand` its
|
|
3727
|
+
`selected` / `highlighted` / `expanded`; `sorted` /
|
|
3664
3728
|
`sorted-desc` per header, on its cell and its `sort-icon`; `indeterminate` on
|
|
3665
3729
|
the select-all glyph. **`disabled` means the row cannot be selected**
|
|
3666
3730
|
(`selectable` rejects it, or the table is `disabled`): the row still clicks,
|
|
3667
|
-
highlights and expands, and a table without selection never has it.
|
|
3668
|
-
|
|
3669
|
-
|
|
3731
|
+
highlights and expands, and a table without selection never has it. The
|
|
3732
|
+
empty row and the skeleton are not parts — `pt:body:empty` covers the usual
|
|
3733
|
+
ask.
|
|
3670
3734
|
|
|
3671
3735
|
The selectable invoices table above, restyled through those parts: muted
|
|
3672
3736
|
type on `pt:head`, weight on `pt:row:selected` (Globex is checked), a muted
|
|
@@ -3843,8 +3907,9 @@ A value that depends on the ITEM — a danger wash on overdue rows — is a
|
|
|
3843
3907
|
**per-item function** on `pt:row`: `({ item, highlighted }) => …`, called
|
|
3844
3908
|
with the row's item and every state as a boolean for it, its result merged after the
|
|
3845
3909
|
state entries (so the overdue wash below steps aside while the row is
|
|
3846
|
-
highlighted). `
|
|
3847
|
-
per render; `pt:cell` takes no function
|
|
3910
|
+
highlighted). `pt:expand` takes one the same way. `rowClass` still works and
|
|
3911
|
+
is computed once per row rather than per render; `pt:cell` takes no function
|
|
3912
|
+
(`tdClass` is the per-cell hook).
|
|
3848
3913
|
|
|
3849
3914
|
**pt:row as a function — overdue invoices washed by status**
|
|
3850
3915
|
|
|
@@ -4048,7 +4113,13 @@ for a preset that fits any row type (never `<any>`), not an imported
|
|
|
4048
4113
|
- Set `item-value` so selection, expansion and highlight track rows by stable
|
|
4049
4114
|
identity rather than object reference.
|
|
4050
4115
|
- Sortable headers set `aria-sort` and render real buttons; custom header
|
|
4051
|
-
slots should keep a button calling `toggleSort`.
|
|
4116
|
+
slots should keep a button calling `toggleSort`. Enter sorts by the column
|
|
4117
|
+
alone and **Shift+Enter adds it** to a multi-column sort. The sortable
|
|
4118
|
+
header's accessible description says so (on the sort button, or on the
|
|
4119
|
+
header cell when the header row is a keyboard surface, after the
|
|
4120
|
+
reorder / resize instructions); with `multi-sort` there is no hint, since a
|
|
4121
|
+
plain Enter adds. A custom `#<key>:header` button carries no hint: describe
|
|
4122
|
+
it yourself if it should.
|
|
4052
4123
|
- **The role follows the keyboard.** A plain table is `role="table"` with
|
|
4053
4124
|
`cell`s. `keyboard-navigation` makes it `role="grid"` (the APG data grid:
|
|
4054
4125
|
one tab stop, cell focus, `gridcell`s, `aria-selected` on selectable rows
|
|
@@ -4105,7 +4176,7 @@ for a preset that fits any row type (never `<any>`), not an imported
|
|
|
4105
4176
|
|
|
4106
4177
|
| Prop | Type | Default | Required | Description |
|
|
4107
4178
|
| --- | --- | --- | --- | --- |
|
|
4108
|
-
| `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`, `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>`. |
|
|
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>`. |
|
|
4109
4180
|
| `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. |
|
|
4110
4181
|
| `actionsText` | `string \| undefined` | | | Label used in the header of the actions column. |
|
|
4111
4182
|
| `align` | `"left" \| "center" \| "right" \| undefined` | `"left"` | | Text alignment of the columns. |
|
|
@@ -4142,6 +4213,7 @@ for a preset that fits any row type (never `<any>`), not an imported
|
|
|
4142
4213
|
| `max` | `number \| undefined` | `Infinity` | | Maximum number of items that can be selected. |
|
|
4143
4214
|
| `modelValue` | `any` | `[]` | | Used by v-model. Can be any serializable type. |
|
|
4144
4215
|
| `multiple` | `boolean \| undefined` | `true` | | Allows the selection of multiple items. |
|
|
4216
|
+
| `multiSort` | `boolean \| undefined` | `false` | | A plain click on a sortable header adds the column to the sort, as Shift+click always does. Off, a plain click makes the sort that column alone. |
|
|
4145
4217
|
| `name` | `string \| undefined` | | | Defines the name of the input. |
|
|
4146
4218
|
| `order` | `string[] \| undefined` | `[]` | | Used by `v-model:order`: the column keys in render order. Columns it omits follow in declaration order; unknown keys stay put. A `reorderable` move writes it back complete. Works unbound, like `sort`; never holds `select` / `actions`. |
|
|
4147
4219
|
| `page` | `string \| number \| undefined` | | | Current page (from 1), for the rows' `aria-rowindex` and a `BbPagination` paired through `id`. Doesn't slice `items`: pass the current page's rows. Numeric strings are coerced. |
|
|
@@ -4177,8 +4249,9 @@ for a preset that fits any row type (never `<any>`), not an imported
|
|
|
4177
4249
|
| `cellColumnHeader` | Every column header cell (`role="columnheader"`), the select and actions headers included — a broadcast resolved per header. Not a `<th>`: the grid is `div`s with ARIA roles. |
|
|
4178
4250
|
| `sortIcon` | A sortable column's sort arrow, resolved per header. |
|
|
4179
4251
|
| `body` | The body row group. |
|
|
4180
|
-
| `row` | Every DATA row — a broadcast resolved per row.
|
|
4252
|
+
| `row` | Every DATA row — a broadcast resolved per row. The skeleton is not a part, and an expand row is styled through `expand`. Also takes a per-item function, called with the row's raw item, once per rendered row: keep it cheap. |
|
|
4181
4253
|
| `cell` | Every data cell, the select and actions cells included — a broadcast resolved with its row's states (`role="cell"`, `gridcell` under `keyboardNavigation`) — and the cells of the `firstRow` / `lastRow`, with no row state. Takes no function: use `tdClass` for a per-cell hook. |
|
|
4254
|
+
| `expand` | The cell under an open row that holds the `#expand` slot and spans every column — resolved with its data row's `selected`, `highlighted` and `expanded` (always on: the cell exists only while its row is open). Not a `cell`, so `pt:cell` never reaches it: a rule taken off the cells (`pt:cell="border-b-0"`) needs `pt:expand="border-b-0"` too. Also takes a per-item function, called with the open row's raw item. |
|
|
4182
4255
|
| `firstRow` | The row of `#<key>:first` cells, before the data rows. |
|
|
4183
4256
|
| `lastRow` | The row of `#<key>:last` cells, after the data rows (a totals row: `pt:lastRow="font-semibold"`). |
|
|
4184
4257
|
| `selectIcon` | The selection glyph: each row's checkbox (radio with single selection) and the select-all checkbox — resolved per node. Not rendered when the `select` / `select:header` slots replace them. |
|
|
@@ -4193,11 +4266,11 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
4193
4266
|
| `empty` | Component-wide: there are no rows (`bb-table--empty`). |
|
|
4194
4267
|
| `sorted` | Per node, on `cellColumnHeader` and `sortIcon`: the column is sorted, either direction (`bb-table__cell-column-header--sorted`). |
|
|
4195
4268
|
| `sortedDesc` | Per node, on `cellColumnHeader` and `sortIcon`: sorted descending (`bb-table__cell-column-header--sorted-desc`). Ascending is `sorted` alone. |
|
|
4196
|
-
| `selected` | Per node, on `row`, its cells and its `selectIcon`: a checked row; on the select-all glyph, every row is selected. |
|
|
4269
|
+
| `selected` | Per node, on `row`, its cells, its `expand` and its `selectIcon`: a checked row; on the select-all glyph, every row is selected. |
|
|
4197
4270
|
| `indeterminate` | Per node, on the select-all `selectIcon`: some rows are selected, not all. |
|
|
4198
4271
|
| `disabled` | Per node, on `row`, its cells and its `selectIcon`: the row cannot be SELECTED — `selectable` rejects it, or the table is `disabled` (`bb-table__row--disabled`). It still clicks, highlights and expands. Never on a table without selection. The select-all glyph takes it from the table's `disabled`. |
|
|
4199
|
-
| `expanded` | Per node, on `row
|
|
4200
|
-
| `highlighted` | Per node, on `row
|
|
4272
|
+
| `expanded` | Per node, on `row`, its cells and its `expand`: the row's expand row is open (`bb-table__row--expanded`). |
|
|
4273
|
+
| `highlighted` | Per node, on `row`, its cells and its `expand`: the highlighted row. |
|
|
4201
4274
|
| `loading` | Component-wide: the table is `loading`. |
|
|
4202
4275
|
|
|
4203
4276
|
## Events
|
|
@@ -4224,8 +4297,8 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
4224
4297
|
- `actions:header` — scope: `{ text: string; }` — Replaces the default actions header cell content.
|
|
4225
4298
|
- `empty` — scope: `{ error: unknown; }` — Content shown when there are no rows and nothing is loading, inside the table's own full-width cell: pass content, never a row. `error` is what the latest failed load threw (`null` when none).
|
|
4226
4299
|
- `expand` — scope: `{ expanded: boolean; expandProps?: ExpandControllerProps \| undefined; toggleExpanded: () => void; highlighted?: boolean \| undefined; toggleHighlighted?: (() =…` — Full-width expandable content row rendered below each main row when expanded.
|
|
4227
|
-
- `header:append` — scope: `BbTableHeaderAffixSlotProps<Item>` `{ classes?: Classes; columnKey: string; items?: Item[]; label?: string; sortable?: boolean; sortOrder?: "asc" \| "desc" \| null; toggleSort?: (() => void); hideColumn?: (() => void) }` — Content after every data column's header content (the label + sort control, or its own `<key>:header` replacement). A column's `<key>:header:append` wins over this for that column; they never stack. Branch on `columnKey` for per-column output.
|
|
4228
|
-
- `header:prepend` — scope: `BbTableHeaderAffixSlotProps<Item>` `{ classes?: Classes; columnKey: string; items?: Item[]; label?: string; sortable?: boolean; sortOrder?: "asc" \| "desc" \| null; toggleSort?: (() => void); hideColumn?: (() => void) }` — Content before every data column's header content (the label + sort control, or its own `<key>:header` replacement). A column's `<key>:header:prepend` wins over this for that column; they never stack. Branch on `columnKey` for per-column output.
|
|
4300
|
+
- `header:append` — scope: `BbTableHeaderAffixSlotProps<Item>` `{ classes?: Classes; columnKey: string; items?: Item[]; label?: string; sortable?: boolean; sortOrder?: "asc" \| "desc" \| null; toggleSort?: ((event?: MouseEvent \| KeyboardEvent \| undefined) => void); hideColumn?: (() => void) }` — Content after every data column's header content (the label + sort control, or its own `<key>:header` replacement). A column's `<key>:header:append` wins over this for that column; they never stack. Branch on `columnKey` for per-column output.
|
|
4301
|
+
- `header:prepend` — scope: `BbTableHeaderAffixSlotProps<Item>` `{ classes?: Classes; columnKey: string; items?: Item[]; label?: string; sortable?: boolean; sortOrder?: "asc" \| "desc" \| null; toggleSort?: ((event?: MouseEvent \| KeyboardEvent \| undefined) => void); hideColumn?: (() => void) }` — Content before every data column's header content (the label + sort control, or its own `<key>:header` replacement). A column's `<key>:header:prepend` wins over this for that column; they never stack. Branch on `columnKey` for per-column output.
|
|
4229
4302
|
- `loading` — scope: `{ items: Item[]; }` — Content shown while table rows are loading (replaces the skeleton rows).
|
|
4230
4303
|
- `select` — scope: `{ item: Item; value: any; checked: boolean; disabled: boolean; inputName: string; readonly: boolean; toggleSelected?: (() => void) \| undefined; }` — Replaces the default checkbox/radio in the selection cell for each row.
|
|
4231
4304
|
- `select:header` — scope: `{ multiple: boolean; selectAll: boolean; text: string; }` — Replaces the default selection header cell content (checkbox or radio label).
|
package/dist/ai/BbToast.md
CHANGED
|
@@ -191,7 +191,8 @@ Three things worth internalising:
|
|
|
191
191
|
|
|
192
192
|
#### Variant icons
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
A default icon per variant, set once: the object form of the plugin's
|
|
195
|
+
`toastVariants` option sets each variant's icon for
|
|
195
196
|
the whole app. A toast without its own `icon` uses its variant's; its own
|
|
196
197
|
`icon` wins; `hideIcon: true` hides either (and does nothing when there is no
|
|
197
198
|
icon). The loading spinner still shows with `hideIcon`: it is state, not
|
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.62",
|
|
5
5
|
"upgrade": "v2-to-v3",
|
|
6
6
|
"guide": "ai/guides/migration/v2-to-v3.md",
|
|
7
7
|
"legend": {
|
|
@@ -71,7 +71,8 @@
|
|
|
71
71
|
"3.0.0-beta.58",
|
|
72
72
|
"3.0.0-beta.59",
|
|
73
73
|
"3.0.0-beta.60",
|
|
74
|
-
"3.0.0-beta.61"
|
|
74
|
+
"3.0.0-beta.61",
|
|
75
|
+
"3.0.0-beta.62"
|
|
75
76
|
],
|
|
76
77
|
"unpublished": [
|
|
77
78
|
"3.0.0-alpha.2",
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
],
|
|
95
96
|
"summary": {
|
|
96
97
|
"renames": 220,
|
|
97
|
-
"behaviourBreaks":
|
|
98
|
+
"behaviourBreaks": 230,
|
|
98
99
|
"bySurface": {
|
|
99
100
|
"prop": 15,
|
|
100
101
|
"option": 1,
|
|
@@ -105,7 +106,7 @@
|
|
|
105
106
|
"class": 138
|
|
106
107
|
},
|
|
107
108
|
"unreleased": 0,
|
|
108
|
-
"added":
|
|
109
|
+
"added": 414
|
|
109
110
|
},
|
|
110
111
|
"added": {
|
|
111
112
|
"3.0.0-alpha.1": [
|
|
@@ -2067,6 +2068,23 @@
|
|
|
2067
2068
|
"BbSelectPopover"
|
|
2068
2069
|
]
|
|
2069
2070
|
}
|
|
2071
|
+
],
|
|
2072
|
+
"3.0.0-beta.62": [
|
|
2073
|
+
{
|
|
2074
|
+
"text": "bbtable · pt:expand part for the expand cell",
|
|
2075
|
+
"components": [
|
|
2076
|
+
"BbTable"
|
|
2077
|
+
]
|
|
2078
|
+
},
|
|
2079
|
+
"table · single sort by default, shift+click adds",
|
|
2080
|
+
{
|
|
2081
|
+
"text": "check · warn on computed slot names that skip slotKey",
|
|
2082
|
+
"components": [
|
|
2083
|
+
"BbTable"
|
|
2084
|
+
]
|
|
2085
|
+
},
|
|
2086
|
+
"table · keep short multi-word values on one line",
|
|
2087
|
+
"table · sortable headers describe shift+enter"
|
|
2070
2088
|
]
|
|
2071
2089
|
},
|
|
2072
2090
|
"breaking": [
|
|
@@ -8445,6 +8463,30 @@
|
|
|
8445
8463
|
"ruling": "owner 2026-10-16 (Q75.1 R7 reading b, R2, G4, G5, G7)",
|
|
8446
8464
|
"guide": "v2-to-v3.md § 6 item 94 + BbSelect.md § Rows the form already holds",
|
|
8447
8465
|
"firstReleasedIn": "3.0.0-beta.59"
|
|
8466
|
+
},
|
|
8467
|
+
{
|
|
8468
|
+
"id": "f368",
|
|
8469
|
+
"kind": "behaviour",
|
|
8470
|
+
"summary": "BbTable: a plain header click sorts by that column alone; Shift+click adds a column; multi-sort makes a plain click add",
|
|
8471
|
+
"components": [
|
|
8472
|
+
"BbTable"
|
|
8473
|
+
],
|
|
8474
|
+
"description": "BbTable sorts by ONE column by default: a plain click (or Enter / Space) on a sortable header makes v-model:sort that column alone at its next state (unsorted → asc → desc → []); Shift+click / Shift+Enter adds the column or cycles it in place, leaving the other entries (a plain click's old behaviour). multi-sort (new, default false) makes a plain click add too. The model's shape is unchanged and a several-entry model written from outside is shown as is (the next plain click replaces it). The header slots' toggleSort takes the event (@click=\"toggleSort\" gets Shift); toggleSort() sorts single. Tables that want click-adds set multi-sort",
|
|
8475
|
+
"ruling": "owner 2026-10-21 (Q76.9 b)",
|
|
8476
|
+
"guide": "v2-to-v3.md § 6 item 95 + BbTable.md § Sorting",
|
|
8477
|
+
"firstReleasedIn": "3.0.0-beta.62"
|
|
8478
|
+
},
|
|
8479
|
+
{
|
|
8480
|
+
"id": "f369",
|
|
8481
|
+
"kind": "behaviour",
|
|
8482
|
+
"summary": "BbTable: unsized text columns keep names, statuses, amounts, ranges, dates and codes on one line; a long heading may take two lines instead of a sideways scroll",
|
|
8483
|
+
"components": [
|
|
8484
|
+
"BbTable"
|
|
8485
|
+
],
|
|
8486
|
+
"description": "BbTable: an unsized text column keeps the values a line break would harm on ONE line (short names and statuses, an amount with its currency, a pair or range, a spelled-out date, a code or IBAN; voted by a five-lens panel on a 392-value corpus, widthCorpus.*.json), and a table that scrolls sideways anyway no longer squeezes them. A table that fitted before still fits: only then do those values give way. A long heading of several words takes two lines when the alternative is a sideways scroll (--wrap, Q76.9 e); short headings never wrap, and the pt:cell-column-header=\"whitespace-normal\" workaround is no longer needed. The floors are converted at the body text's size (they used the table root's 16px, ~14% wide), and structural columns (drag handle, selection, actions) no longer count as room. Unsized columns change width (wider for units, narrower otherwise)",
|
|
8487
|
+
"ruling": "owner 2026-10-16 (Q75.3) + 2026-10-21 (Q76.9 e)",
|
|
8488
|
+
"guide": "v2-to-v3.md § 6 item 96 + BbTable.md § Columns, § Column resize",
|
|
8489
|
+
"firstReleasedIn": "3.0.0-beta.62"
|
|
8448
8490
|
}
|
|
8449
8491
|
]
|
|
8450
8492
|
}
|