bitboss-ui 3.0.0-beta.45 → 3.0.0-beta.46
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 +6 -1
- package/dist/ai/BbDialog.md +12 -10
- package/dist/ai/BbDropzone.md +2 -2
- package/dist/ai/BbForm.md +2 -2
- package/dist/ai/BbOffCanvas.md +3 -3
- package/dist/ai/BbPopover.md +1 -1
- package/dist/ai/BbRating.md +1 -1
- package/dist/ai/BbTable.md +2 -2
- package/dist/ai/BbTabs.md +4 -4
- package/dist/ai/BbTextInput.md +13 -11
- package/dist/ai/BbTextarea.md +8 -7
- package/dist/ai/changelog.json +17 -3
- package/dist/ai/components.json +5 -4
- package/dist/ai/guides/installation-and-plugin-setup.md +31 -5
- package/dist/ai/guides/migration/v2-to-v3.md +10 -0
- package/dist/ai/guides/validation-libraries.md +7 -4
- package/dist/ai/manifest/components/BbTextInput.json +4 -3
- package/dist/ai/manifest/components/BbTextarea.json +2 -1
- package/dist/ai/manifest/index.json +2 -2
- package/dist/ai/manifest/meta.json +1 -0
- package/dist/ai/manifest/types.advanced.json +1 -0
- package/dist/ai/recipes/inertia/approvals-inbox.md +8 -6
- package/dist/ai/recipes/nuxt/approvals-inbox.md +8 -6
- package/dist/ai/recipes/vue/approvals-inbox.md +8 -6
- package/dist/ai/source/BbTextInput.md +44 -12
- package/dist/ai/source/BbTextarea.md +45 -13
- package/dist/components/BbTextInput/BbTextInput.vue.d.ts +31 -39
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +19 -18
- package/dist/components/BbTextInput/types.d.ts +17 -4
- package/dist/components/BbTextarea/BbTextarea.vue.d.ts +31 -37
- package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +40 -39
- package/dist/components/BbTextarea/types.d.ts +17 -4
- package/dist/composables/useSegmentedFields.js +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/llms-full.txt +120 -70
- package/dist/llms-medium.txt +31 -5
- package/dist/project-dts.d.ts +8 -0
- package/dist/project-dts.js +6 -3
- package/dist/styles.css +1 -1
- package/dist/types/Config.d.ts +26 -8
- package/dist/utils/versionCheck.js +1 -1
- package/dist/vite-plugin.d.ts +6 -4
- package/dist/vite.js +182 -181
- package/package.json +1 -1
- package/scripts/lib/eslint-disable.mjs +2 -0
- package/scripts/lib/eslint-plugin.d.ts +2 -0
- package/scripts/lib/eslint-plugin.mjs +117 -0
- package/scripts/lib/text-null-value.mjs +260 -0
- package/scripts/lib/validate-bb-markup.mjs +4 -0
package/bin/bitboss-ui.mjs
CHANGED
|
@@ -76,6 +76,7 @@ import {
|
|
|
76
76
|
projectLocalBbComponents,
|
|
77
77
|
} from '../scripts/lib/local-components.mjs';
|
|
78
78
|
import { applyBitbossFixes } from '../scripts/lib/check-fix.mjs';
|
|
79
|
+
import { stringControlsFor } from '../scripts/lib/text-null-value.mjs';
|
|
79
80
|
import { cssClassFindings } from '../scripts/lib/css-class-check.mjs';
|
|
80
81
|
import {
|
|
81
82
|
cssLocalFindings,
|
|
@@ -1044,7 +1045,11 @@ async function checkCommand(
|
|
|
1044
1045
|
const content = readText(file);
|
|
1045
1046
|
const { findings: fileFindings } = file.endsWith('.md')
|
|
1046
1047
|
? validateMarkdown(content, manifest, validateOptions)
|
|
1047
|
-
: validateVueSnippet(content, manifest,
|
|
1048
|
+
: validateVueSnippet(content, manifest, {
|
|
1049
|
+
...validateOptions,
|
|
1050
|
+
// The app's null-value policy, from the project bitboss-ui.d.ts.
|
|
1051
|
+
stringControls: stringControlsFor(file),
|
|
1052
|
+
});
|
|
1048
1053
|
// Q46.9: a finding the author silenced for ESLint (`eslint-disable*`,
|
|
1049
1054
|
// usually with a reason) is silenced here too, or `check` cannot gate
|
|
1050
1055
|
// CI next to a lint step that passes. `.md` lines are fence-relative,
|
package/dist/ai/BbDialog.md
CHANGED
|
@@ -99,7 +99,7 @@ back to `false`, which is the same thing.
|
|
|
99
99
|
<template #footer>
|
|
100
100
|
<div class="flex justify-end gap-2">
|
|
101
101
|
<BbButton variant="ghost" @click="open = false">Cancel</BbButton>
|
|
102
|
-
<BbButton :disabled="!name
|
|
102
|
+
<BbButton :disabled="!name?.trim()" variant="primary" @click="create">
|
|
103
103
|
Create
|
|
104
104
|
</BbButton>
|
|
105
105
|
</div>
|
|
@@ -112,7 +112,7 @@ import { ref } from 'vue';
|
|
|
112
112
|
import { BbButton, BbDialog, BbTextInput } from 'bitboss-ui';
|
|
113
113
|
|
|
114
114
|
const open = ref(false);
|
|
115
|
-
const name = ref('');
|
|
115
|
+
const name = ref<string | null>('');
|
|
116
116
|
|
|
117
117
|
// Re-seed on `@show`, not on close — a dismissed dialog may be reopened.
|
|
118
118
|
const reset = () => {
|
|
@@ -442,7 +442,7 @@ const roles = [
|
|
|
442
442
|
];
|
|
443
443
|
|
|
444
444
|
const open = ref(false);
|
|
445
|
-
const email = ref('');
|
|
445
|
+
const email = ref<string | null>('');
|
|
446
446
|
const role = ref('member');
|
|
447
447
|
|
|
448
448
|
// Re-seed on `@show`, not on close — a dismissed dialog may be reopened.
|
|
@@ -452,7 +452,9 @@ const reset = () => {
|
|
|
452
452
|
};
|
|
453
453
|
|
|
454
454
|
// Primary action stays disabled until the email is plausible.
|
|
455
|
-
const canSend = computed(() =>
|
|
455
|
+
const canSend = computed(() =>
|
|
456
|
+
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value ?? '')
|
|
457
|
+
);
|
|
456
458
|
|
|
457
459
|
const send = () => {
|
|
458
460
|
// Send the invite here, then close only on success.
|
|
@@ -600,7 +602,7 @@ element.
|
|
|
600
602
|
<div class="flex justify-end gap-2">
|
|
601
603
|
<!-- Keep a visible way out — never trap the user. -->
|
|
602
604
|
<BbButton variant="ghost" @click="open = false">Skip</BbButton>
|
|
603
|
-
<BbButton :disabled="!company
|
|
605
|
+
<BbButton :disabled="!company?.trim()" variant="primary" @click="save">
|
|
604
606
|
Save
|
|
605
607
|
</BbButton>
|
|
606
608
|
</div>
|
|
@@ -613,8 +615,8 @@ import { ref } from 'vue';
|
|
|
613
615
|
import { BbButton, BbDialog, BbTextInput } from 'bitboss-ui';
|
|
614
616
|
|
|
615
617
|
const open = ref(false);
|
|
616
|
-
const displayName = ref('');
|
|
617
|
-
const company = ref('');
|
|
618
|
+
const displayName = ref<string | null>('');
|
|
619
|
+
const company = ref<string | null>('');
|
|
618
620
|
|
|
619
621
|
// Re-seed on `@show` so a dismissed step reopens clean.
|
|
620
622
|
const reset = () => {
|
|
@@ -676,7 +678,7 @@ automatically; close only once the work resolves:
|
|
|
676
678
|
Cancel
|
|
677
679
|
</BbButton>
|
|
678
680
|
<!-- Returning the promise lets BbButton run its own loading state. -->
|
|
679
|
-
<BbButton :disabled="!draft
|
|
681
|
+
<BbButton :disabled="!draft?.trim()" variant="primary" @click="save">
|
|
680
682
|
Rename
|
|
681
683
|
</BbButton>
|
|
682
684
|
</div>
|
|
@@ -692,7 +694,7 @@ import { BbButton, BbDialog, BbTextInput } from 'bitboss-ui';
|
|
|
692
694
|
const projectName = ref('acme-storefront');
|
|
693
695
|
|
|
694
696
|
const open = ref(false);
|
|
695
|
-
const draft = ref('');
|
|
697
|
+
const draft = ref<string | null>('');
|
|
696
698
|
const saving = ref(false);
|
|
697
699
|
|
|
698
700
|
// Re-seed on `@show` so a dismissed rename never resurfaces half-typed.
|
|
@@ -706,7 +708,7 @@ const save = async () => {
|
|
|
706
708
|
try {
|
|
707
709
|
// Simulated request — replace with your API call.
|
|
708
710
|
await new Promise((resolve) => setTimeout(resolve, 600));
|
|
709
|
-
projectName.value = draft.value.trim();
|
|
711
|
+
projectName.value = (draft.value ?? '').trim();
|
|
710
712
|
// Work first, then close: the transition runs while your UI refreshes.
|
|
711
713
|
open.value = false;
|
|
712
714
|
} finally {
|
package/dist/ai/BbDropzone.md
CHANGED
|
@@ -1269,7 +1269,7 @@ import { ref } from 'vue';
|
|
|
1269
1269
|
import { BbDropzone, BbButton, BbIcon, BbTextInput } from 'bitboss-ui';
|
|
1270
1270
|
import type { DropZoneError } from 'bitboss-ui';
|
|
1271
1271
|
|
|
1272
|
-
const title = ref('');
|
|
1272
|
+
const title = ref<string | null>('');
|
|
1273
1273
|
const documents = ref<File[]>([]);
|
|
1274
1274
|
const errors = ref<string[]>([]);
|
|
1275
1275
|
const submitted = ref<{ field: string; fileCount: number } | null>(null);
|
|
@@ -1298,7 +1298,7 @@ const remove = (file: File) => {
|
|
|
1298
1298
|
model — assemble a FormData and hand it to your request layer. */
|
|
1299
1299
|
const submit = () => {
|
|
1300
1300
|
const body = new FormData();
|
|
1301
|
-
body.append('title', title.value);
|
|
1301
|
+
body.append('title', title.value ?? '');
|
|
1302
1302
|
documents.value.forEach((file) => body.append('documents[]', file));
|
|
1303
1303
|
submitted.value = { field: 'documents[]', fileCount: documents.value.length };
|
|
1304
1304
|
};
|
package/dist/ai/BbForm.md
CHANGED
|
@@ -310,8 +310,8 @@ Four things to know:
|
|
|
310
310
|
- **An emptied text field holds `null` by default**, not `''`. So
|
|
311
311
|
`z.string().min(1, 'Required')` alone answers an emptied field with the
|
|
312
312
|
library's own "expected string, received null". Two ways out:
|
|
313
|
-
- **Set the plugin option `formControls: { textInputNullValue: '',
|
|
314
|
-
textareaNullValue: '' }`.** Emptied fields then emit `''` and the short
|
|
313
|
+
- **Set the plugin option `formControls: { textInputNullValue: 'string',
|
|
314
|
+
textareaNullValue: 'string' }`.** Emptied fields then emit `''` and the short
|
|
315
315
|
schema shows your message as written. Start text values as `''` too (a
|
|
316
316
|
field nobody touched keeps what your page gave it).
|
|
317
317
|
- **Or keep `null` and put the message on the type as well:**
|
package/dist/ai/BbOffCanvas.md
CHANGED
|
@@ -216,7 +216,7 @@ header and footer stay pinned.
|
|
|
216
216
|
<div class="flex justify-end gap-2">
|
|
217
217
|
<BbButton variant="ghost" @click="open = false">Cancel</BbButton>
|
|
218
218
|
<BbButton
|
|
219
|
-
:disabled="!email
|
|
219
|
+
:disabled="!email?.trim()"
|
|
220
220
|
variant="primary"
|
|
221
221
|
@click="open = false"
|
|
222
222
|
>
|
|
@@ -232,7 +232,7 @@ import { ref } from 'vue';
|
|
|
232
232
|
import { BbButton, BbOffCanvas, BbTextInput } from 'bitboss-ui';
|
|
233
233
|
|
|
234
234
|
const open = ref(false);
|
|
235
|
-
const email = ref('');
|
|
235
|
+
const email = ref<string | null>('');
|
|
236
236
|
</script>
|
|
237
237
|
```
|
|
238
238
|
|
|
@@ -951,7 +951,7 @@ import { ref } from 'vue';
|
|
|
951
951
|
import { BbButton, BbOffCanvas, BbTextInput } from 'bitboss-ui';
|
|
952
952
|
|
|
953
953
|
const open = ref(false);
|
|
954
|
-
const reviewer = ref('');
|
|
954
|
+
const reviewer = ref<string | null>('');
|
|
955
955
|
</script>
|
|
956
956
|
```
|
|
957
957
|
|
package/dist/ai/BbPopover.md
CHANGED
package/dist/ai/BbRating.md
CHANGED
|
@@ -273,7 +273,7 @@ import { ref } from 'vue';
|
|
|
273
273
|
import { BbButton, BbRating, BbTextarea } from 'bitboss-ui';
|
|
274
274
|
|
|
275
275
|
const score = ref<number | null>(null);
|
|
276
|
-
const feedback = ref('');
|
|
276
|
+
const feedback = ref<string | null>('');
|
|
277
277
|
const errors = ref<string | undefined>();
|
|
278
278
|
const sent = ref(false);
|
|
279
279
|
|
package/dist/ai/BbTable.md
CHANGED
|
@@ -849,13 +849,13 @@ const catalogue: Invoice[] = [
|
|
|
849
849
|
{ id: '4', number: 'INV-1044', client: 'Umbrella', amount: '€2,750' },
|
|
850
850
|
];
|
|
851
851
|
|
|
852
|
-
const search = ref('');
|
|
852
|
+
const search = ref<string | null>('');
|
|
853
853
|
|
|
854
854
|
// Real apps forward the query to the backend; here we filter a local catalogue
|
|
855
855
|
// after a short simulated round-trip.
|
|
856
856
|
const fetchInvoices = async (): Promise<Invoice[]> => {
|
|
857
857
|
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
858
|
-
const term = search.value.trim().toLowerCase();
|
|
858
|
+
const term = (search.value ?? '').trim().toLowerCase();
|
|
859
859
|
if (!term) return catalogue;
|
|
860
860
|
return catalogue.filter(
|
|
861
861
|
(invoice) =>
|
package/dist/ai/BbTabs.md
CHANGED
|
@@ -418,7 +418,7 @@ nothing when you flip back:
|
|
|
418
418
|
</template>
|
|
419
419
|
<template #preview>
|
|
420
420
|
<div class="grid gap-1.5 pt-3 text-sm whitespace-pre-line">
|
|
421
|
-
<template v-if="draft
|
|
421
|
+
<template v-if="draft?.trim()">
|
|
422
422
|
<p class="font-medium">{{ previewTitle }}</p>
|
|
423
423
|
<p class="text-(--bb-text-muted)">{{ previewBody }}</p>
|
|
424
424
|
</template>
|
|
@@ -442,17 +442,17 @@ const tabs: Array<BbTabsItem<Mode>> = [
|
|
|
442
442
|
{ key: 'preview', label: 'Preview' },
|
|
443
443
|
];
|
|
444
444
|
|
|
445
|
-
const draft = ref(
|
|
445
|
+
const draft = ref<string | null>(
|
|
446
446
|
'## Billing retries\n\nVerified on staging — invoice totals now match the ledger.'
|
|
447
447
|
);
|
|
448
448
|
|
|
449
449
|
const previewTitle = computed(() => {
|
|
450
|
-
const heading = draft.value.match(/^##\s+(.+)$/m);
|
|
450
|
+
const heading = (draft.value ?? '').match(/^##\s+(.+)$/m);
|
|
451
451
|
return heading?.[1] ?? 'Untitled';
|
|
452
452
|
});
|
|
453
453
|
|
|
454
454
|
const previewBody = computed(() =>
|
|
455
|
-
draft.value.replace(/^##\s+.+$/m, '').trim()
|
|
455
|
+
(draft.value ?? '').replace(/^##\s+.+$/m, '').trim()
|
|
456
456
|
);
|
|
457
457
|
</script>
|
|
458
458
|
```
|
package/dist/ai/BbTextInput.md
CHANGED
|
@@ -62,7 +62,7 @@ Pick a sibling when the shape of the data is different:
|
|
|
62
62
|
- calendar dates → `BbDatePickerInput`;
|
|
63
63
|
- choosing from a known set of options → `BbSelect` / `BbRadioGroup`.
|
|
64
64
|
|
|
65
|
-
`v-model` binds a `string | null` — an emptied field emits `null` by default, or `''` when the plugin option `formControls`
|
|
65
|
+
`v-model` binds a `string | null` — an emptied field emits `null` by default, or `''` when the plugin option `formControls` sets the `'string'` policy (see the installation guide § `formControls`). One field can differ from the app with `null-value="string"` or `null-value="null"`; the `update:modelValue` payload types to match (`string` with `'string'`).
|
|
66
66
|
`label` is required (hide it visually with `hideLabel`, never drop it).
|
|
67
67
|
|
|
68
68
|
### Label & label modes
|
|
@@ -233,7 +233,7 @@ name. The slot alone is enough: no `description` prop needed.
|
|
|
233
233
|
import { ref } from 'vue';
|
|
234
234
|
import { BbTextInput } from 'bitboss-ui';
|
|
235
235
|
|
|
236
|
-
const subdomain = ref('');
|
|
236
|
+
const subdomain = ref<string | null>('');
|
|
237
237
|
</script>
|
|
238
238
|
```
|
|
239
239
|
|
|
@@ -403,8 +403,9 @@ const apiKey = 'sk_live_51Hn3x8Kj2';
|
|
|
403
403
|
### Clearable & loading
|
|
404
404
|
|
|
405
405
|
`clearable` reveals a clear button while the field has a value and is hovered
|
|
406
|
-
or focused; clicking it emits `update:modelValue` with `null`
|
|
407
|
-
input. There is no separate `clear` event — watch
|
|
406
|
+
or focused; clicking it emits `update:modelValue` with the empty value (`null`
|
|
407
|
+
by default) and refocuses the input. There is no separate `clear` event — watch
|
|
408
|
+
the model for the empty value. The
|
|
408
409
|
button is suppressed on `disabled`/`readonly` fields.
|
|
409
410
|
|
|
410
411
|
`loading` shows a spinner in the append position. It is **visual only** — the
|
|
@@ -416,7 +417,7 @@ The classic pairing is a signup handle checker: debounce keystrokes, flip
|
|
|
416
417
|
`loading` while the (simulated) availability call runs, then land the result
|
|
417
418
|
in `errors` or `hint`. Because the field stays editable during the check, the
|
|
418
419
|
handler tags each request and drops stale responses. Watching the model —
|
|
419
|
-
rather than listening to `input` — means the clear button's
|
|
420
|
+
rather than listening to `input` — means the clear button's empty value also resets
|
|
420
421
|
the status.
|
|
421
422
|
|
|
422
423
|
**Async username check**
|
|
@@ -501,7 +502,7 @@ Pass a [maska](https://beholdr.github.io/maska/v3) config to `mask` to format
|
|
|
501
502
|
as the user types — card numbers, phone numbers, license keys. By default
|
|
502
503
|
`v-model` receives the _unmasked_ value (`'4242424242424242'` for the card
|
|
503
504
|
below); set `emitMasked` to persist the formatted string instead. A fully
|
|
504
|
-
emptied masked field emits the empty value (`null` by default, `''` with `
|
|
505
|
+
emptied masked field emits the empty value (`null` by default, `''` with the `'string'` policy), like every other state of this component.
|
|
505
506
|
|
|
506
507
|
The mask is live-reactive: changing the `mask` options at runtime reformats the
|
|
507
508
|
current value, and toggling `emitMasked` re-emits the model in the new format.
|
|
@@ -611,7 +612,7 @@ const revealed = ref(false);
|
|
|
611
612
|
|
|
612
613
|
### Events & v-model
|
|
613
614
|
|
|
614
|
-
- `update:modelValue` — every value change; `string`, or the empty value when emptied (`null`
|
|
615
|
+
- `update:modelValue` — every value change; `string`, or the empty value when emptied (the `null-value` policy, else `formControls`, else `'null'`; `'string'` emits `''`)
|
|
615
616
|
(with a mask: the unmasked/masked string per `emitMasked`).
|
|
616
617
|
- `focus` / `blur` — forwarded `FocusEvent`s; they also drive the hint's
|
|
617
618
|
show-on-focus behavior.
|
|
@@ -1194,7 +1195,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
1194
1195
|
|
|
1195
1196
|
### Gotchas & anti-patterns
|
|
1196
1197
|
|
|
1197
|
-
- An emptied field emits `null` by default (`''` with the `formControls` plugin option) — write `value ?? ''` when feeding
|
|
1198
|
+
- An emptied field emits `null` by default (`''` with `null-value="string"` or the `formControls` plugin option) — write `value ?? ''` when feeding
|
|
1198
1199
|
APIs that require strings.
|
|
1199
1200
|
- `layout` is ignored under `labelMode="floating"`/`"inside"` — those modes
|
|
1200
1201
|
embed the label in the field and force the vertical layout (see _Density &
|
|
@@ -1256,7 +1257,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
1256
1257
|
| `hint` | `string \| undefined` | | | Text box to be displayed near the input, usually to indicate instructions. |
|
|
1257
1258
|
| `id` | `string \| undefined` | | | The `id` of the native control; the label's `for` and the description and message ids derive from it. Generated when omitted. |
|
|
1258
1259
|
| `inputAlign` | `'top'` \| `'center'` \| `'bottom'` | | | Vertical position of the control in a side-by-side row; not `inputPosition`, the horizontal one. Omitted, the control's first line meets the label's. |
|
|
1259
|
-
| `inputMode` | `"text" \| "none" \| "search" \| "
|
|
1260
|
+
| `inputMode` | `"text" \| "none" \| "search" \| "tel" \| "url" \| "email" \| "numeric" \| "decimal" \| undefined` | | | The inputmode of the input. |
|
|
1260
1261
|
| `label` | `string` | | yes | Text content of the label of the element. |
|
|
1261
1262
|
| `labelAlign` | `'top'` \| `'center'` \| `'bottom'` | | | Vertical position of the label block in a side-by-side row; not `labelPosition`, the horizontal one. Omitted, the label's first line meets the control's. |
|
|
1262
1263
|
| `labelMode` | `"outside" \| "floating" \| "inside" \| undefined` | | | Label rendering mode. |
|
|
@@ -1266,6 +1267,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
1266
1267
|
| `mask` | `MaskInputOptions \| undefined` | | | The mask to be applied to the input. Please visit https://beholdr.github.io/maska/v3 for syntax examples. |
|
|
1267
1268
|
| `modelValue` | `string \| null \| undefined` | | | Used by v-model. |
|
|
1268
1269
|
| `name` | `string \| undefined` | | | Defines the name of the input. |
|
|
1270
|
+
| `nullValue` | `E \| undefined` | | | What the field emits once the user empties it (typing it empty, the clear button, a mask with nothing in it): `'null'` emits `null`, `'string'` emits `''`. Unset, the app's `formControls.textInputNullValue` applies (`'null'` by default). Also types the `update:modelValue` payload: with `'string'` it is `string`. |
|
|
1269
1271
|
| `persistentHint` | `boolean \| undefined` | `false` | | Keeps the hint displayed. |
|
|
1270
1272
|
| `placeholder` | `string \| undefined` | | | String displayed when there's no data. |
|
|
1271
1273
|
| `prepend:icon` | `string \| undefined` | | | Name of the icon to be added at the start of the input. |
|
|
@@ -1273,7 +1275,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
1273
1275
|
| `required` | `boolean \| undefined` | `false` | | Sets the input as required. |
|
|
1274
1276
|
| `reverse` | `boolean \| undefined` | `false` | | Reverses the layout. Applicable in every direction the order of the label and the input is swapped. |
|
|
1275
1277
|
| `rules` | `RuleExpression<string \| null>` | | | vee-validate rules for this field. Only inside a `BbForm`. |
|
|
1276
|
-
| `type` | `"text" \| "search" \| "
|
|
1278
|
+
| `type` | `"text" \| "search" \| "tel" \| "url" \| "email" \| "password" \| undefined` | `"text"` | | Type of the input. Restricted to the textual input types this component supports — use `BbNumberInput` for numbers and `BbDatePickerInput` for dates. |
|
|
1277
1279
|
| `validationLabel` | `string \| undefined` | | | The field's name in validation messages (`{field}`): "Email is not valid". Defaults to the `label` (or `legend`), then "This field"; the field's `name` never shows. Set it when the label is not a good noun for a sentence (an icon-only label, a question) or is hidden. Only inside a `BbForm`. |
|
|
1278
1280
|
| `validationMode` | `'aggressive'` \| `'balanced'` \| `'lazy'` \| `'submit-only'` \| `'submit-live'` | | | When this field checks itself while the user works: `aggressive` (every change), `balanced` (on leave, then every change while it shows an error), `lazy` (on leave only), `submit-only` (on submit only) or `submit-live` (on submit, then every change while it shows an error). "Leave" is blur for a text-like control, and focus leaving the whole control for a picker or a group; a checkbox or switch commits on click. Unset, the enclosing `BbForm`'s `validation-mode` applies, then the app's `formControls.validationMode` (`'balanced'`). Only inside a `BbForm`. |
|
|
1279
1281
|
| `variant` | `'outline'` \| `'secondary'` \| `'none'` \| `'ghost'` | `'outline'` | | Visual variant of the field box — the same names and tokens as the `BbButton` variants. Colours only: height, padding and border width are identical across variants, so a form never reflows when one changes. `'ghost'` has no border in any state (errors and warnings show through the icon and the messages); every variant keeps the focus ring. Register extra names with the plugin's `inputVariants` option. `'none'` is a blank starting point: the field keeps its structure and behaviour but takes no look, so your own classes don't fight a built-in one. You then own hover, focus, disabled and the error / warning states. Fine for a one-off; keep inline styling short, and register a real variant (`inputVariants`) when the look recurs. |
|
|
@@ -1326,7 +1328,7 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
1326
1328
|
- `mousedown` — `(event: MouseEvent): void` — Emitted when a pointing device button is pressed over the input. Forwards the original DOM `MouseEvent`.
|
|
1327
1329
|
- `mouseup` — `(event: MouseEvent): void` — Emitted when a pointing device button is released over the input. Forwards the original DOM `MouseEvent`.
|
|
1328
1330
|
- `paste` — `(event: ClipboardEvent): void` — Emitted when content is pasted into the input. Forwards the original DOM `ClipboardEvent`.
|
|
1329
|
-
- `update:modelValue` — `(value: string \|
|
|
1331
|
+
- `update:modelValue` — `(value: string \| NullValueOf<E>): void` — Emitted when the value changes. Carries the new string, or the empty value (`null-value`, else the app's, `null` by default) when emptied. When `mask` is set, emits the masked or unmasked string depending on `emitMasked`.
|
|
1330
1332
|
|
|
1331
1333
|
## Slots
|
|
1332
1334
|
|
package/dist/ai/BbTextarea.md
CHANGED
|
@@ -63,7 +63,7 @@ Pick a sibling when the shape of the data is different:
|
|
|
63
63
|
- a calendar date → `BbDatePickerInput`;
|
|
64
64
|
- a value from a known set → `BbSelect` / `BbRadioGroup`.
|
|
65
65
|
|
|
66
|
-
`v-model` binds a `string | null` — an emptied field emits `null` by default, or `''` when the plugin option `formControls`
|
|
66
|
+
`v-model` binds a `string | null` — an emptied field emits `null` by default, or `''` when the plugin option `formControls` sets the `'string'` policy (see the installation guide § `formControls`). One field can differ from the app with `null-value="string"` or `null-value="null"`; the `update:modelValue` payload types to match (`string` with `'string'`).
|
|
67
67
|
`label` is required (hide it visually with `hideLabel`, never drop it).
|
|
68
68
|
|
|
69
69
|
### Label
|
|
@@ -608,9 +608,9 @@ const snippet = 'npx bitboss-ui ai-init';
|
|
|
608
608
|
### Clearable & loading
|
|
609
609
|
|
|
610
610
|
`clearable` reveals a clear button while the field has a value and is hovered or
|
|
611
|
-
focused; clicking it emits `update:modelValue` with `null`
|
|
612
|
-
`disabled`/`readonly` fields. There is no separate
|
|
613
|
-
model for
|
|
611
|
+
focused; clicking it emits `update:modelValue` with the empty value (`null` by
|
|
612
|
+
default) and is suppressed on `disabled`/`readonly` fields. There is no separate
|
|
613
|
+
`clear` event — watch the model for the empty value.
|
|
614
614
|
|
|
615
615
|
`loading` shows a spinner in the append position. It is **visual only** — the
|
|
616
616
|
field stays editable, so pair it with your own guard if the value must not
|
|
@@ -803,7 +803,7 @@ const notes = ref<string | null>(null);
|
|
|
803
803
|
|
|
804
804
|
### Events & v-model
|
|
805
805
|
|
|
806
|
-
- `update:modelValue` — every value change; `string`, or the empty value when emptied (`null`
|
|
806
|
+
- `update:modelValue` — every value change; `string`, or the empty value when emptied (the `null-value` policy, else `formControls`, else `'null'`; `'string'` emits `''`).
|
|
807
807
|
- `focus` / `blur` — forwarded `FocusEvent`s; they also drive the hint's
|
|
808
808
|
show-on-focus behavior.
|
|
809
809
|
- `input` — every keystroke (raw DOM event); `change` — on commit (blur), the
|
|
@@ -979,7 +979,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
979
979
|
floor; the field starts there and never shrinks below it.
|
|
980
980
|
- Avoid `labelMode="floating"` with `placeholder` — the resting label and the
|
|
981
981
|
placeholder occupy the same spot.
|
|
982
|
-
- An emptied field emits `null` by default (`''` with the `formControls` plugin option) — write `value ?? ''` when feeding
|
|
982
|
+
- An emptied field emits `null` by default (`''` with `null-value="string"` or the `formControls` plugin option) — write `value ?? ''` when feeding
|
|
983
983
|
APIs that require strings.
|
|
984
984
|
- `counter` counts what `maxlength` counts: UTF-16 code units, so an emoji
|
|
985
985
|
counts 2, and a line break counts 1 in the browser but 2 once a form
|
|
@@ -1044,6 +1044,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
1044
1044
|
| `loading` | `boolean \| undefined` | `false` | | Sets the component in a loading state, usually triggering some visual styles. |
|
|
1045
1045
|
| `modelValue` | `string \| null \| undefined` | | | Used by v-model. |
|
|
1046
1046
|
| `name` | `string \| undefined` | | | Defines the name of the input. |
|
|
1047
|
+
| `nullValue` | `E \| undefined` | | | What the field emits once the user empties it (typing it empty, the clear button): `'null'` emits `null`, `'string'` emits `''`. Unset, the app's `formControls.textareaNullValue` applies (`'null'` by default). Also types the `update:modelValue` payload: with `'string'` it is `string`. |
|
|
1047
1048
|
| `persistentHint` | `boolean \| undefined` | `false` | | Keeps the hint displayed. |
|
|
1048
1049
|
| `placeholder` | `string \| undefined` | | | String displayed when there's no data. |
|
|
1049
1050
|
| `prepend:icon` | `string \| undefined` | | | Name of the icon to be added at the start of the input. |
|
|
@@ -1104,7 +1105,7 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
1104
1105
|
- `mousedown` — `(event: MouseEvent): void` — Emitted when a pointing device button is pressed over the textarea. Forwards the original DOM `MouseEvent`.
|
|
1105
1106
|
- `mouseup` — `(event: MouseEvent): void` — Emitted when a pointing device button is released over the textarea. Forwards the original DOM `MouseEvent`.
|
|
1106
1107
|
- `paste` — `(event: ClipboardEvent): void` — Native clipboard paste. Forwards the original DOM `ClipboardEvent`.
|
|
1107
|
-
- `update:modelValue` — `(value: string \|
|
|
1108
|
+
- `update:modelValue` — `(value: string \| NullValueOf<E>): void` — Emitted when the value changes. Carries the new text, or the empty value (`null-value`, else the app's, `null` by default) when emptied.
|
|
1108
1109
|
|
|
1109
1110
|
## Slots
|
|
1110
1111
|
|
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.46",
|
|
5
5
|
"upgrade": "v2-to-v3",
|
|
6
6
|
"guide": "ai/guides/migration/v2-to-v3.md",
|
|
7
7
|
"legend": {
|
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
"3.0.0-beta.42",
|
|
57
57
|
"3.0.0-beta.43",
|
|
58
58
|
"3.0.0-beta.44",
|
|
59
|
-
"3.0.0-beta.45"
|
|
59
|
+
"3.0.0-beta.45",
|
|
60
|
+
"3.0.0-beta.46"
|
|
60
61
|
],
|
|
61
62
|
"unpublished": [
|
|
62
63
|
"3.0.0-alpha.2",
|
|
@@ -77,7 +78,7 @@
|
|
|
77
78
|
],
|
|
78
79
|
"summary": {
|
|
79
80
|
"renames": 213,
|
|
80
|
-
"behaviourBreaks":
|
|
81
|
+
"behaviourBreaks": 169,
|
|
81
82
|
"bySurface": {
|
|
82
83
|
"prop": 15,
|
|
83
84
|
"option": 1,
|
|
@@ -5541,6 +5542,19 @@
|
|
|
5541
5542
|
"ruling": "owner 2026-10-01 (popover-in-dialog close)",
|
|
5542
5543
|
"guide": "v2-to-v3.md § 6 item 41 + BbDialog.guide.md / BbOffCanvas.guide.md § Lifecycle events",
|
|
5543
5544
|
"firstReleasedIn": "3.0.0-beta.44"
|
|
5545
|
+
},
|
|
5546
|
+
{
|
|
5547
|
+
"id": "f302",
|
|
5548
|
+
"kind": "behaviour",
|
|
5549
|
+
"summary": "`formControls.textInputNullValue` / `textareaNullValue` values `null` / `''` → `'null'` / `'string'`; an old `''` falls back to `null`",
|
|
5550
|
+
"components": [
|
|
5551
|
+
"BbTextInput",
|
|
5552
|
+
"BbTextarea"
|
|
5553
|
+
],
|
|
5554
|
+
"description": "formControls.textInputNullValue / textareaNullValue take a policy instead of the value: 'null' (the default) emits null, 'string' emits '' (it was null / ''). An old '' now falls back to null silently; TypeScript flags it in vite.config / app.use. The new per-field null-value prop takes the same values, and the Vite option also types update:modelValue (string with 'string') through the project bitboss-ui.d.ts",
|
|
5555
|
+
"ruling": "owner 2026-10-05 (null-value policy)",
|
|
5556
|
+
"guide": "v2-to-v3.md § 6 item 42 + installation-and-plugin-setup.md § formControls",
|
|
5557
|
+
"firstReleasedIn": "3.0.0-beta.46"
|
|
5544
5558
|
}
|
|
5545
5559
|
]
|
|
5546
5560
|
}
|