@appsbd/vue3-appsbd-ui 1.0.13 → 1.0.15
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/.ai/ai_ref_AbChatBox.md +148 -0
- package/.ai/ai_ref_AbChatInput.md +235 -0
- package/.ai/ai_ref_AbChatInputMenuItem.md +55 -0
- package/.ai/ai_ref_AbDateTimePicker.md +1 -1
- package/.ai/ai_ref_AbFileUploader.md +34 -6
- package/.ai/ai_ref_AbFormCheck.md +71 -12
- package/.ai/ai_ref_AbInputField.md +2 -0
- package/.ai/ai_ref_AbNumberField.md +1 -0
- package/.ai/ai_ref_AbScrollbar.md +27 -0
- package/.ai/ai_ref_abDate.md +58 -0
- package/.ai/ai_ref_global_config.md +39 -4
- package/.ai/ai_ref_migration_guide.md +90 -0
- package/.ai/ai_ref_useFileValidator.md +10 -5
- package/AI_REFERENCE.md +9 -3
- package/CHANGELOG.md +34 -2
- package/dist/style.css +1 -1
- package/dist/vue3-appsbd-ui.cjs.js +106 -76
- package/dist/vue3-appsbd-ui.es.js +12384 -10838
- package/package.json +11 -10
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# AbChatBox — AI Reference
|
|
2
|
+
|
|
3
|
+
A full chat conversation container built on top of `AbChatInput` — header, scrollable message list (with
|
|
4
|
+
empty/typing states), and the composer. Every part is slot-overridable, so pick this over building a chat UI by
|
|
5
|
+
hand whenever you need a message list around `AbChatInput`, not just the composer itself.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Not globally registered — import it explicitly:
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { AbChatBox } from 'vue3-appsbd-ui';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
No extra peer deps beyond `AbChatInput`'s own (`@lucide/vue`).
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
`v-model:messages` holds the conversation array, `v-model` holds the composer's text. Submitting auto-appends the
|
|
20
|
+
user's message and fires `send` — handle that to call your API and push the reply back:
|
|
21
|
+
|
|
22
|
+
```vue
|
|
23
|
+
<template>
|
|
24
|
+
<AbChatBox
|
|
25
|
+
v-model="message"
|
|
26
|
+
v-model:messages="messages"
|
|
27
|
+
title="Support Bot"
|
|
28
|
+
subtitle="Usually replies in a few seconds"
|
|
29
|
+
:loading="loading"
|
|
30
|
+
@send="onSend"
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script setup>
|
|
35
|
+
import { ref } from 'vue';
|
|
36
|
+
import { AbChatBox } from 'vue3-appsbd-ui';
|
|
37
|
+
|
|
38
|
+
const message = ref('');
|
|
39
|
+
const messages = ref([
|
|
40
|
+
{ id: 1, role: 'assistant', name: 'Assistant', text: 'Hi! How can I help you today?' },
|
|
41
|
+
]);
|
|
42
|
+
const loading = ref(false);
|
|
43
|
+
|
|
44
|
+
function onSend({ message, files }) {
|
|
45
|
+
loading.value = true;
|
|
46
|
+
callMyApi(message).then((reply) => {
|
|
47
|
+
loading.value = false;
|
|
48
|
+
messages.value.push({ id: Date.now(), role: 'assistant', text: reply });
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Any `AbChatInput` prop/event/slot works directly on `AbChatBox` — it's forwarded straight to the inner composer:
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<template>
|
|
58
|
+
<AbChatBox
|
|
59
|
+
v-model="message"
|
|
60
|
+
v-model:messages="messages"
|
|
61
|
+
v-model:files="files"
|
|
62
|
+
:max-file-size="2"
|
|
63
|
+
:allowed-extensions="['jpg', 'jpeg', 'png', 'pdf']"
|
|
64
|
+
placeholder="Ask anything"
|
|
65
|
+
>
|
|
66
|
+
<template #single-input="{ addToAttach }">
|
|
67
|
+
<AbChatInputMenuItem :icon="Paperclip" name="Upload file" :action="() => addToAttach()" />
|
|
68
|
+
</template>
|
|
69
|
+
</AbChatBox>
|
|
70
|
+
</template>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Props
|
|
74
|
+
|
|
75
|
+
| Name | Type | Default | Description |
|
|
76
|
+
| --- | --- | --- | --- |
|
|
77
|
+
| `messages` | `Array` | `[]` | v-model:messages. See "Message shape" below. |
|
|
78
|
+
| `modelValue` | `String` | `""` | Two-way-bound composer text — forwarded to the inner `AbChatInput`. |
|
|
79
|
+
| `title` | `String` | `""` | Default header title (translated). |
|
|
80
|
+
| `subtitle` | `String` | `""` | Default header subtitle (translated). |
|
|
81
|
+
| `avatar` | `String` | `""` | Default header avatar image URL. |
|
|
82
|
+
| `loading` | `Boolean` | `false` | Shows the typing indicator at the bottom of the message list. |
|
|
83
|
+
| `emptyText` | `String` | `"Start a conversation"` | Text shown by the default empty state (translated). |
|
|
84
|
+
| `emptyIcon` | `Object \| Function` | `MessageCircle` | Icon shown above `emptyText`. Pass `null` to hide it. |
|
|
85
|
+
| `autoScroll` | `Boolean` | `true` | Auto-scrolls the message list to the bottom on new messages / `loading` changes. |
|
|
86
|
+
| `containerClass` | `String` | `undefined` | Extra class on the root element. |
|
|
87
|
+
|
|
88
|
+
Any other prop not listed above (`placeholder`, `disabled`, `readonly`, `minHeight`, `maxHeight`, `submitOnEnter`,
|
|
89
|
+
`allowNewLine`, `autoFocus`, `autoPreview`, `maxFileSize`, `allowedExtensions`, `borderRadius`,
|
|
90
|
+
`filePreviewWidth`, `filePreviewHeight`, `showFileName`, `showVoiceButton`, ...) falls through untouched to the
|
|
91
|
+
inner `AbChatInput` — see `.ai/ai_ref_AbChatInput.md` for the full list.
|
|
92
|
+
|
|
93
|
+
## Events
|
|
94
|
+
|
|
95
|
+
| Event | Payload | Description |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| `update:messages` | `Message[]` | v-model:messages sync — fires after the user's message is auto-appended, or after `addMessage()`. |
|
|
98
|
+
| `update:modelValue` | `string` | v-model sync for the composer text. |
|
|
99
|
+
| `send` | `{ message: string, files: FileEntry[] }` | Fired right after the user's message is auto-appended to `messages` — hook here to call an API and push the reply. |
|
|
100
|
+
|
|
101
|
+
Any other `AbChatInput` event (`focus`, `blur`, `keydown`, `file-click`, `file-remove`, `file-reject`,
|
|
102
|
+
`voice-start`, `voice-stop`, `voice-cancel`, `voice-error`, `update:files`) is forwarded straight from the inner
|
|
103
|
+
composer — listen for it on `AbChatBox` exactly as you would on `AbChatInput`. Note: `submit` itself is **not**
|
|
104
|
+
forwarded — `AbChatBox` consumes it internally to auto-append + emit `send`.
|
|
105
|
+
|
|
106
|
+
## Slots
|
|
107
|
+
|
|
108
|
+
| Name | Description |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| `header` | Overrides the entire header. Scoped: `{ title, subtitle, avatar }`. |
|
|
111
|
+
| `header-actions` | Adds content to the right side of the default header, without replacing it. |
|
|
112
|
+
| `empty` | Overrides the empty state (shown when `messages` is empty). |
|
|
113
|
+
| `message` | Overrides one message's whole bubble. Scoped: `{ message, index }`. |
|
|
114
|
+
| `message-avatar` | Overrides just the avatar inside the default bubble. Scoped: `{ message }`. |
|
|
115
|
+
| `typing` | Overrides the typing indicator (shown when `loading` is `true`). |
|
|
116
|
+
| `left` / `right` / `send-button` / `menu-trigger` / `single-input` / `multiple-input` | `AbChatInput`'s own slots — forwarded straight through to the inner composer with the same scoped props (`addToAttach`, `addFiles`, `removeFile`, `clearFiles`, `updateText`, `focus`, `submit`). See `.ai/ai_ref_AbChatInput.md`. |
|
|
117
|
+
|
|
118
|
+
## v-model
|
|
119
|
+
|
|
120
|
+
Yes — two v-models: `modelValue` + `update:modelValue` (string, the composer text) and `messages` +
|
|
121
|
+
`update:messages` (`Message[]`, the conversation). A third, `files` + `update:files`, is available by passthrough
|
|
122
|
+
if you use `v-model:files` (forwarded to the inner `AbChatInput`).
|
|
123
|
+
|
|
124
|
+
### Message shape
|
|
125
|
+
|
|
126
|
+
Any plain object works — only `role` is read internally (to align the bubble left/right); everything else is
|
|
127
|
+
just read by the default bubble template (or your own, via `#message`).
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
{
|
|
131
|
+
id, // stable key; auto-generated if omitted
|
|
132
|
+
role, // "user" | "assistant" | "system" — "user" aligns right, others left
|
|
133
|
+
text, // message body
|
|
134
|
+
name, // optional sender name, shown above the text
|
|
135
|
+
avatar, // optional avatar image URL
|
|
136
|
+
time, // optional string, shown below the text
|
|
137
|
+
files, // optional array — rendered as a small attachment list ({ name } or a plain string)
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Exposed methods
|
|
142
|
+
|
|
143
|
+
| Method | Description |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| `addMessage(message)` | Appends a message (fills in a default `id`/`role` if omitted), fires `update:messages`, and auto-scrolls. Returns the stored message. |
|
|
146
|
+
| `scrollToBottom()` | Scrolls the message list to the bottom. |
|
|
147
|
+
| `focus()` | Focuses the composer's textarea. |
|
|
148
|
+
| `chatInput` | Raw template ref to the inner `AbChatInput` — call any of its own exposed methods directly (`submit()`, `addToAttach()`, `startRecording()`, etc). See `.ai/ai_ref_AbChatInput.md`. |
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# AbChatInput — AI Reference
|
|
2
|
+
|
|
3
|
+
A ChatGPT-style auto-growing chat/message composer. Use for AI chat interfaces, comment boxes that need to grow with content, or any message input needing configurable Enter/Shift+Enter/Ctrl+Enter submit behavior. Pair with `AbChatInputMenuItem` for the built-in add/more dropdown.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Not globally registered — import it explicitly:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { AbChatInput, AbChatInputMenuItem } from 'vue3-appsbd-ui';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
No extra peer deps beyond the library's own (`@lucide/vue` for the default "+" icon).
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
A send button (arrow-up icon, `AbButton` with `color="primary"`) renders on the right by default and calls the
|
|
18
|
+
same submit logic as pressing Enter — no manual wiring needed:
|
|
19
|
+
|
|
20
|
+
```vue
|
|
21
|
+
<template>
|
|
22
|
+
<AbChatInput v-model="message" placeholder="Ask anything" @submit="onSubmit" />
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup>
|
|
26
|
+
import { ref } from 'vue';
|
|
27
|
+
import { AbChatInput } from 'vue3-appsbd-ui';
|
|
28
|
+
|
|
29
|
+
const message = ref('');
|
|
30
|
+
function onSubmit({ message, files }) {
|
|
31
|
+
console.log(message, files);
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Override the default send button via the scoped `#send-button` slot (e.g. to add a label, swap the icon, or
|
|
37
|
+
change its color) — call the scoped `submit()` to fire the same `submit` event the default button would:
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<template>
|
|
41
|
+
<AbChatInput v-model="message" @submit="onSubmit">
|
|
42
|
+
<template #send-button="{ submit }">
|
|
43
|
+
<AbButton color="success" is-icon-btn is-rounded size="sm" @click="submit">
|
|
44
|
+
<Send :size="18" />
|
|
45
|
+
</AbButton>
|
|
46
|
+
</template>
|
|
47
|
+
</AbChatInput>
|
|
48
|
+
</template>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Add/more dropdown (0 items = no trigger, 1 item = direct action with no popover, 2+ items = a real dropdown):
|
|
52
|
+
|
|
53
|
+
```vue
|
|
54
|
+
<template>
|
|
55
|
+
<AbChatInput v-model="message">
|
|
56
|
+
<template #multiple-input>
|
|
57
|
+
<AbChatInputMenuItem v-for="item in menuItems" :key="item.name" v-bind="item" />
|
|
58
|
+
</template>
|
|
59
|
+
</AbChatInput>
|
|
60
|
+
</template>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
File attachments — selection stays the consumer's job, validation/storage/preview are internal. Every content
|
|
64
|
+
slot (`left`/`right`/`menu-trigger`/`single-input`/`multiple-input`) is scoped, handing back `addToAttach` (opens
|
|
65
|
+
a native file picker and routes the selection through `addFiles`) among other methods — no template
|
|
66
|
+
`<input type="file">` and no ref needed:
|
|
67
|
+
|
|
68
|
+
```vue
|
|
69
|
+
<template>
|
|
70
|
+
<AbChatInput
|
|
71
|
+
v-model="message"
|
|
72
|
+
v-model:files="attachedFiles"
|
|
73
|
+
:max-file-size="2"
|
|
74
|
+
:allowed-extensions="['jpg', 'jpeg', 'png', 'pdf']"
|
|
75
|
+
>
|
|
76
|
+
<template #single-input="{ addToAttach }">
|
|
77
|
+
<AbChatInputMenuItem
|
|
78
|
+
:icon="Paperclip"
|
|
79
|
+
name="Upload file"
|
|
80
|
+
:action="() => addToAttach({ accept: '.jpg,.jpeg,.png,.pdf' })"
|
|
81
|
+
/>
|
|
82
|
+
</template>
|
|
83
|
+
</AbChatInput>
|
|
84
|
+
</template>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Voice input
|
|
88
|
+
|
|
89
|
+
Uses the browser's native Web Speech API (`SpeechRecognition`) — no extra dependency, no API key. A built-in mic
|
|
90
|
+
button renders in the `right` area (before the `right` slot and the send button) whenever `showVoiceButton` is
|
|
91
|
+
`true` (default).
|
|
92
|
+
Clicking it (or calling `startRecording()`) swaps the whole composer row for a full-width recording bar — a live
|
|
93
|
+
audio-reactive waveform (via `getUserMedia` + `AnalyserNode`) plus three controls:
|
|
94
|
+
|
|
95
|
+
- **✕ cancel** — discards everything spoken this session, reverting `modelValue` to what it was before recording started.
|
|
96
|
+
- **■ stop** — stops recording and keeps the transcribed text in the textarea (no submit).
|
|
97
|
+
- **↑ submit** — stops recording, keeps the text, then fires `submit` immediately.
|
|
98
|
+
|
|
99
|
+
Recognized speech is appended to the existing `modelValue` (not replaced), one final phrase at a time — interim
|
|
100
|
+
(still-speaking) text is not shown live.
|
|
101
|
+
|
|
102
|
+
A small language-code badge (e.g. `EN`, `BN`) sits on the mic button's corner. Clicking it opens an `AbPopover`
|
|
103
|
+
with a searchable list of ~130 BCP-47 locales; picking one sets that recognition session's `SpeechRecognition.lang`
|
|
104
|
+
and persists the choice to `localStorage` (key `apbd-chat-input-voice-lang`) so it's remembered next visit. This
|
|
105
|
+
never touches the browser's own language/locale settings — only this component's own recognizer instance.
|
|
106
|
+
|
|
107
|
+
Not supported in Firefox. On iOS, only Safari itself gets it — Chrome/Firefox/Edge/Opera on iOS run on the same
|
|
108
|
+
underlying WebKit engine and expose the same `webkitSpeechRecognition` constructor, but iOS never grants the mic
|
|
109
|
+
permission for it outside of Safari's own app (no permission prompt ever appears; `.start()` would otherwise fail
|
|
110
|
+
with a confusing, prompt-less "permission denied"), so these are detected via user-agent and treated as unsupported
|
|
111
|
+
too. The mic button still renders in all of these cases but is `disabled`, with a tooltip explaining why. Where it
|
|
112
|
+
is supported, requires the browser's mic permission prompt to be accepted.
|
|
113
|
+
|
|
114
|
+
On Android, the live waveform is skipped (bars stay flat) — recognition and transcription work normally. Android's
|
|
115
|
+
mic hardware only allows one exclusive audio-capture session at a time; a second concurrent `getUserMedia` stream
|
|
116
|
+
for the waveform would starve `SpeechRecognition` of audio (no error, no transcript, ever). This is detected via
|
|
117
|
+
user-agent, not feature-tested.
|
|
118
|
+
|
|
119
|
+
## Props
|
|
120
|
+
|
|
121
|
+
| Name | Type | Default | Description |
|
|
122
|
+
| --- | --- | --- | --- |
|
|
123
|
+
| `modelValue` | `String` | `""` | Two-way-bound message text. |
|
|
124
|
+
| `files` | `Array` | `[]` | v-model:files — see "Attached file shape" below. |
|
|
125
|
+
| `placeholder` | `String` | `""` | Textarea placeholder (translated). |
|
|
126
|
+
| `disabled` | `Boolean` | `false` | Disables the textarea and the menu trigger. |
|
|
127
|
+
| `readonly` | `Boolean` | `false` | Makes the textarea read-only. |
|
|
128
|
+
| `loading` | `Boolean` | `false` | Visual loading state (CSS hook only — does not itself disable input). |
|
|
129
|
+
| `minHeight` | `Number` | `52` | Minimum textarea height in px. Also the threshold: past this, the composer switches to the "grown" stacked layout (see below). |
|
|
130
|
+
| `maxHeight` | `Number` | `200` | Maximum textarea height in px; internal scroll kicks in beyond this. |
|
|
131
|
+
| `submitOnEnter` | `Boolean` | `true` | `true`: Enter submits, Shift+Enter inserts a newline. `false`: Enter inserts a newline, Ctrl+Enter/Cmd+Enter submits. |
|
|
132
|
+
| `allowNewLine` | `Boolean` | `true` | If `false`, Enter never inserts a newline regardless of `submitOnEnter`. |
|
|
133
|
+
| `autoFocus` | `Boolean` | `false` | Focus the textarea on mount. |
|
|
134
|
+
| `autoPreview` | `Boolean` | `true` | When `true`, clicking a file chip opens the built-in preview lightbox. When `false`, only the `file-click` event fires. |
|
|
135
|
+
| `maxFileSize` | `Number` | `null` | Max size in MB per file. `null` = no limit. Enforced by `addFiles()`. |
|
|
136
|
+
| `allowedExtensions` | `Array` | `[]` | Case-insensitive allowed extensions (e.g. `['jpg','png','pdf']`). Empty = all types allowed. Enforced by `addFiles()`. |
|
|
137
|
+
| `containerClass` | `String` | `undefined` | Wrapper class; falls back to `globalConfig.inputContainerClass`. |
|
|
138
|
+
| `borderRadius` | `String` | `"1.5rem"` | Composer roundness — any CSS length (e.g. `"0.5rem"`, `"8px"`, `"1.5rem"`). |
|
|
139
|
+
| `filePreviewWidth` | `Number` | `24` | Width (px) of each attached file's thumbnail/icon in the chip. |
|
|
140
|
+
| `filePreviewHeight` | `Number` | `24` | Height (px) of each attached file's thumbnail/icon in the chip. |
|
|
141
|
+
| `showFileName` | `Boolean` | `true` | Show/hide the filename text next to the chip thumbnail. |
|
|
142
|
+
| `showVoiceButton` | `Boolean` | `true` | Show/hide the built-in mic button (see "Voice input" below). Set `false` to build custom voice UI via slots instead. |
|
|
143
|
+
|
|
144
|
+
## Events
|
|
145
|
+
|
|
146
|
+
| Event | Payload | Description |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `update:modelValue` | `string` | v-model sync. |
|
|
149
|
+
| `update:files` | `FileEntry[]` | v-model:files sync — fired after `addFiles`/`removeFile`/`clearFiles`. |
|
|
150
|
+
| `submit` | `{ message: string, files: FileEntry[] }` | Fired on Enter/Ctrl+Enter/Cmd+Enter per `submitOnEnter`. Not fired when `disabled`/`readonly`. |
|
|
151
|
+
| `focus` / `blur` | `FocusEvent` | Forwarded native events. |
|
|
152
|
+
| `keydown` | `KeyboardEvent` | Forwarded native event; fires before any submit/newline logic runs. |
|
|
153
|
+
| `file-click` | `FileEntry` | A file chip was clicked (fires regardless of `autoPreview`). |
|
|
154
|
+
| `file-remove` | `FileEntry` | A file chip's remove button was clicked. |
|
|
155
|
+
| `file-reject` | `{ file: File, reason: string }` | A file failed `maxFileSize`/`allowedExtensions` validation. A `useToast` error is also shown. |
|
|
156
|
+
| `voice-start` | — | Voice recording started (mic button clicked or `startRecording()` called). |
|
|
157
|
+
| `voice-stop` | — | Recording stopped normally (■ button, ↑ submit button, `stopRecording()`, or the browser ending it on its own) — transcribed text is kept in `modelValue`. |
|
|
158
|
+
| `voice-cancel` | — | Recording was cancelled (✕ button or `cancelRecording()`) — `modelValue` is reverted to what it was before recording started. |
|
|
159
|
+
| `voice-error` | `Error \| SpeechRecognitionErrorEvent` | Mic permission was denied, or the recognition engine errored. A `useToast` error is also shown (except benign `no-speech`/`aborted` errors). |
|
|
160
|
+
|
|
161
|
+
## Slots
|
|
162
|
+
|
|
163
|
+
| Name | Description |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `left` | Left action area (e.g. an attachment button). Scoped — see below. |
|
|
166
|
+
| `right` | Right action area, rendered before the send button (e.g. extra icon buttons). Scoped — see below. |
|
|
167
|
+
| `send-button` | Overrides the default send button (an `AbButton` with an arrow-up icon, `color="primary"`, calling `submit()`). Always rendered — there's no prop to hide it; override this slot with empty content if you don't want one. Scoped — see below. |
|
|
168
|
+
| `menu-trigger` | Overrides the default "+" icon on the add/more trigger. Only rendered when the trigger itself renders (see below). Scoped — see below. |
|
|
169
|
+
| `single-input` | One static `AbChatInputMenuItem` for the add/more dropdown. Scoped — see below. |
|
|
170
|
+
| `multiple-input` | A `v-for`'d set of `AbChatInputMenuItem`s for the add/more dropdown. Scoped — see below. |
|
|
171
|
+
|
|
172
|
+
**All six slots are scoped**, receiving the same props so slot content can drive the composer directly:
|
|
173
|
+
|
|
174
|
+
| Scoped prop | Description |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `addToAttach(options?)` | Opens a native file picker and routes the selection through `addFiles`. `options`: `{ accept, multiple }` (`multiple` defaults to `true`). |
|
|
177
|
+
| `addFiles(files)` | Same as the exposed method — validates and appends an already-obtained `File[]`/`FileList` (drag-drop, paste, etc.). |
|
|
178
|
+
| `removeFile(id)` | Same as the exposed method. |
|
|
179
|
+
| `clearFiles()` | Same as the exposed method. |
|
|
180
|
+
| `updateText(text)` | Replaces the message text (fires `update:modelValue`). |
|
|
181
|
+
| `focus()` | Focuses the textarea. |
|
|
182
|
+
| `submit()` | Same as the exposed method — fires `submit` with `{ message, files }`. No-op when `disabled`/`readonly`. |
|
|
183
|
+
|
|
184
|
+
A single-item `#single-input`/`#multiple-input` action can use these directly — `onMenuTriggerClick`'s no-dropdown
|
|
185
|
+
fast path reads the item's `action` prop with these same bindings applied, so `:action="addToAttach"` works there too.
|
|
186
|
+
|
|
187
|
+
**Layout — single line vs. "grown"**: below `minHeight` worth of content (one line), `left`/textarea/`right` share a single row, centered. Past that, the composer switches to a ChatGPT-style stacked layout: the textarea becomes its own full-width row on top, and `left`/`right` wrap onto a second full-width row below it (`right` stays pinned to that row's end even when `left` isn't rendered at all). This is purely CSS-driven off the same measured content height — no extra prop.
|
|
188
|
+
|
|
189
|
+
**Add/more trigger behavior** is driven by the total count of valid items across `single-input` + `multiple-input` combined, not by which slot they came from:
|
|
190
|
+
- 0 items → no trigger renders at all (fully backward-compatible with plain `left`-slot-only usage).
|
|
191
|
+
- 1 item → the trigger stays the default "+" icon; clicking it calls that item's `action` directly, no dropdown opens.
|
|
192
|
+
- 2+ items → clicking the trigger opens a dropdown (custom-positioned, teleported to `<body>`, matching the composer's full width — not `AbPopover`, which sizes/anchors to the trigger button instead) listing every item (with a divider between the two slot groups if both are non-empty). Opens below by default and flips above (capped to the available space, scrolling internally if needed) when there isn't room below — never clipped by the viewport or a scrolling ancestor.
|
|
193
|
+
|
|
194
|
+
## v-model
|
|
195
|
+
|
|
196
|
+
Yes — `modelValue` + `update:modelValue` (string). Also a second v-model: `files` + `update:files` (`FileEntry[]`).
|
|
197
|
+
|
|
198
|
+
### Attached file shape (`FileEntry`)
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
{
|
|
202
|
+
id, // stable string key, generated internally
|
|
203
|
+
file, // the raw File object
|
|
204
|
+
name,
|
|
205
|
+
size,
|
|
206
|
+
type,
|
|
207
|
+
extension, // lowercased, no dot
|
|
208
|
+
isImage, // boolean — drives chip thumbnail vs icon
|
|
209
|
+
previewKind, // 'image' | 'video' | 'audio' | 'pdf' | 'none' — drives lightbox rendering
|
|
210
|
+
url, // objectURL — revoked automatically on removeFile()/clearFiles()/unmount
|
|
211
|
+
fileIcon, // icon component for non-image chip display
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Exposed methods
|
|
216
|
+
|
|
217
|
+
Same methods as the scoped slot props above (see "Slots"), also available via a template ref for use outside
|
|
218
|
+
any slot — e.g. a toolbar button elsewhere on the page.
|
|
219
|
+
|
|
220
|
+
| Method | Description |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
| `addFiles(files)` | Accepts a `File[]` or `FileList`. Validates each against `maxFileSize`/`allowedExtensions`; rejected files fire `file-reject` + a toast and are never added. Accepted files are appended and `update:files` fires once with the full list. |
|
|
223
|
+
| `removeFile(id)` | Removes one attached file by `id`, revoking its object URL. |
|
|
224
|
+
| `clearFiles()` | Removes all attached files, revoking every object URL. |
|
|
225
|
+
| `addToAttach(options?)` | Opens a native file picker and routes the selection through `addFiles`. `options`: `{ accept, multiple }`. |
|
|
226
|
+
| `updateText(text)` | Replaces the message text (fires `update:modelValue`). |
|
|
227
|
+
| `focus()` | Focuses the textarea. |
|
|
228
|
+
| `submit()` | Fires `submit` with `{ message, files }` (same as clicking the default send button). No-op when `disabled`/`readonly`. |
|
|
229
|
+
| `startRecording()` | Starts voice input (same as clicking the mic button). No-op if unsupported/disabled/readonly/already recording. |
|
|
230
|
+
| `stopRecording()` | Stops recording, keeping the transcribed text (same as the ■ button). |
|
|
231
|
+
| `cancelRecording()` | Stops recording and discards the transcribed text (same as the ✕ button). |
|
|
232
|
+
|
|
233
|
+
## Provides
|
|
234
|
+
|
|
235
|
+
`abChatInputCloseMenu` (no-arg function) — consumed by `AbChatInputMenuItem` to auto-close the dropdown after its `action` fires. Not meant to be consumed by anything else.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# AbChatInputMenuItem — AI Reference
|
|
2
|
+
|
|
3
|
+
A single row (icon + name + optional description) for `AbChatInput`'s add/more dropdown. Not useful outside `AbChatInput` — see [.ai/ai_ref_AbChatInput.md](./ai_ref_AbChatInput.md).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Not globally registered — import it explicitly. Requires `@lucide/vue` (or any icon component) for the `icon` prop.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```vue
|
|
12
|
+
<template>
|
|
13
|
+
<AbChatInput v-model="message">
|
|
14
|
+
<template #single-input>
|
|
15
|
+
<AbChatInputMenuItem :icon="Paperclip" name="Attach a file" description="jpg, png, pdf" :action="onAttach" />
|
|
16
|
+
</template>
|
|
17
|
+
</AbChatInput>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
import { ref } from 'vue';
|
|
22
|
+
import { AbChatInput, AbChatInputMenuItem } from 'vue3-appsbd-ui';
|
|
23
|
+
import { Paperclip } from '@lucide/vue';
|
|
24
|
+
|
|
25
|
+
const message = ref('');
|
|
26
|
+
function onAttach() { /* open a file picker, etc. */ }
|
|
27
|
+
</script>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Props
|
|
31
|
+
|
|
32
|
+
| Name | Type | Default | Description |
|
|
33
|
+
| --- | --- | --- | --- |
|
|
34
|
+
| `icon` | `Object \| Function` | `null` | Icon component (e.g. a `@lucide/vue` icon). |
|
|
35
|
+
| `name` | `String` | `""` | Item title (passed through `translateGetMsg`). |
|
|
36
|
+
| `description` | `String` | `""` | Optional secondary line (passed through `translateGetMsg`). |
|
|
37
|
+
| `action` | `Function` | `null` | Called on click. **Important:** when this item is the only one registered across `#single-input`/`#multiple-input`, `AbChatInput` reads this prop directly off the item's VNode and calls it without mounting the item — always pass a plain function, not something that depends on the component being mounted first. |
|
|
38
|
+
|
|
39
|
+
## Events
|
|
40
|
+
|
|
41
|
+
| Event | Payload | Description |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `click` | — | Fired on click, after `action()`. |
|
|
44
|
+
|
|
45
|
+
## Slots
|
|
46
|
+
|
|
47
|
+
None.
|
|
48
|
+
|
|
49
|
+
## v-model
|
|
50
|
+
|
|
51
|
+
Not applicable — stateless presentational item.
|
|
52
|
+
|
|
53
|
+
## Injects
|
|
54
|
+
|
|
55
|
+
`abChatInputCloseMenu` (optional, no-arg function) — provided by the parent `AbChatInput`; called after `action()`/`click` to close the dropdown. No consumer wiring needed.
|
|
@@ -46,7 +46,7 @@ const datetime = ref(null);
|
|
|
46
46
|
| `monthNames` | `Array` | `undefined` | Custom full month names. |
|
|
47
47
|
| `monthNamesShort` | `Array` | `undefined` | Custom short month names. |
|
|
48
48
|
| `dayNames` | `Array` | `undefined` | Custom day names. |
|
|
49
|
-
| `
|
|
49
|
+
| `digits` | `Array` | `undefined` | 10-character digits array (0-9) for locale digit transliteration (e.g. Bangla digits), overriding `globalConfig.digits`. |
|
|
50
50
|
| `rangeSeparator` | `String` | `undefined` | Display separator between range start/end. |
|
|
51
51
|
| `mode` | `String` | `"date"` | `date`, `time`, or `datetime`. |
|
|
52
52
|
| `is24Hour` | `Boolean` | `undefined` | 24-hour clock. |
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# AbFileUploader — AI Reference
|
|
2
2
|
|
|
3
|
-
File upload input with drag-and-drop, size validation, and preview.
|
|
3
|
+
File upload input with drag-and-drop, size/type validation, and preview. Supports an image-only
|
|
4
|
+
mode (default) or a generic file mode with extension-icon previews. Can render a default uploader
|
|
5
|
+
UI or accept a custom one via slots.
|
|
4
6
|
|
|
5
7
|
> Also available inside `AbCustomField` via the `FU` field type — see [.ai/ai_ref_AbCustomField.md](./ai_ref_AbCustomField.md).
|
|
6
8
|
|
|
@@ -8,9 +10,17 @@ File upload input with drag-and-drop, size validation, and preview. Can render a
|
|
|
8
10
|
|
|
9
11
|
```vue
|
|
10
12
|
<template>
|
|
11
|
-
<ab-file-uploader v-model="
|
|
13
|
+
<ab-file-uploader v-model="avatar" label="Upload avatar" :max-size="1.5" @on-select-files="handleFiles" />
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
<!-- File mode: allowedTypes is required, non-image files show an extension icon -->
|
|
16
|
+
<ab-file-uploader
|
|
17
|
+
v-model="doc"
|
|
18
|
+
type="file"
|
|
19
|
+
:allowed-types="['pdf', 'doc', 'docx', 'xlsx']"
|
|
20
|
+
:max-size="5"
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<ab-file-uploader v-model="avatar" :max-size="5">
|
|
14
24
|
<template #dial>
|
|
15
25
|
<div class="my-drop-zone">Drop files here</div>
|
|
16
26
|
</template>
|
|
@@ -19,7 +29,8 @@ File upload input with drag-and-drop, size validation, and preview. Can render a
|
|
|
19
29
|
|
|
20
30
|
<script setup>
|
|
21
31
|
import { ref } from 'vue';
|
|
22
|
-
const
|
|
32
|
+
const avatar = ref(null);
|
|
33
|
+
const doc = ref(null);
|
|
23
34
|
function handleFiles(files) { console.log('Selected files:', files); }
|
|
24
35
|
</script>
|
|
25
36
|
```
|
|
@@ -32,13 +43,18 @@ function handleFiles(files) { console.log('Selected files:', files); }
|
|
|
32
43
|
| `maxSize` | `Number` | `2.0` | Max file size in MB. |
|
|
33
44
|
| `label` | `String` | `""` | Field label. |
|
|
34
45
|
| `containerClass` | `String` | `undefined` | Wrapper class (falls back to globalConfig.inputContainerClass). |
|
|
46
|
+
| `type` | `'image' \| 'file'` | `'image'` | Upload mode. `image` only accepts images and always shows a thumbnail preview. `file` accepts any file listed in `allowedTypes`; non-image files render an extension icon instead of a preview. |
|
|
47
|
+
| `allowedTypes` | `Array<String>` | `[]` | Allowed extensions, no dot (e.g. `['pdf', 'docx']`). **Required when `type="file"`** — logs a console error and rejects every selected file when empty. Also drives the input's `accept` attribute. Ignored in `image` mode. |
|
|
48
|
+
| `showFileName` | `Boolean` | `null` | Whether to render the filename below the container. `null` auto-picks by `type` (off for `image`, on for `file`); pass `true`/`false` to override either mode. |
|
|
49
|
+
| `width` | `String \| Number` | `undefined` | Container width. Number is treated as px. Falls back to the default `100px`. |
|
|
50
|
+
| `height` | `String \| Number` | `undefined` | Container height. Number is treated as px. Falls back to the default `73px`. |
|
|
35
51
|
|
|
36
52
|
## Events
|
|
37
53
|
|
|
38
54
|
| Event | Payload | Description |
|
|
39
55
|
| --- | --- | --- |
|
|
40
|
-
| `update:modelValue` | `file` | v-model sync. |
|
|
41
|
-
| `onSelectFiles` | `files` | All selected files after
|
|
56
|
+
| `update:modelValue` | `file \| null` | v-model sync. |
|
|
57
|
+
| `onSelectFiles` | `files` | All selected files after validation. |
|
|
42
58
|
|
|
43
59
|
## Slots
|
|
44
60
|
|
|
@@ -47,3 +63,15 @@ function handleFiles(files) { console.log('Selected files:', files); }
|
|
|
47
63
|
| `label` | Custom label. |
|
|
48
64
|
| `dial` | Custom uploader UI (replaces the default design). |
|
|
49
65
|
| `default` | Alternative custom UI slot. |
|
|
66
|
+
|
|
67
|
+
## v-model
|
|
68
|
+
|
|
69
|
+
Yes — `modelValue` + `update:modelValue`. Holds a `File` object (or a URL string for pre-existing
|
|
70
|
+
previews), or `null`.
|
|
71
|
+
|
|
72
|
+
## Notes
|
|
73
|
+
|
|
74
|
+
- Icon mapping for non-image files (pdf, zip, doc/docx, xls/xlsx, ppt/pptx, video) comes from the
|
|
75
|
+
shared `useFileValidator()` composable's `getFileIconByExt`, the same mapping `AbChatInput` uses.
|
|
76
|
+
- In `image` mode, validation is unchanged from before: only jpg/jpeg/png/gif/webp are accepted and
|
|
77
|
+
checked against the file's actual MIME type.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AbFormCheck / AbRadioInput — AI Reference
|
|
2
2
|
|
|
3
|
-
Checkbox or radio group with card, segmented, and pill visual variants. `AbRadioInput` is an alias export of `AbFormCheck`.
|
|
3
|
+
Checkbox or radio group with card, icon-card, card-flat-check, image-radio, segmented, and pill visual variants. `AbRadioInput` is an alias export of `AbFormCheck`.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -17,6 +17,41 @@ Checkbox or radio group with card, segmented, and pill visual variants. `AbRadio
|
|
|
17
17
|
/>
|
|
18
18
|
|
|
19
19
|
<ab-form-check v-model="plan" type="radio" name="plan" variant="card" :options="plans" />
|
|
20
|
+
|
|
21
|
+
<!-- Custom check icon (card-family variants only) -->
|
|
22
|
+
<ab-form-check v-model="plan" type="radio" name="plan2" variant="card" :options="plans" :check-icon-component="Check" />
|
|
23
|
+
|
|
24
|
+
<!-- Flat, shadow-free card with the indicator on the right (card-family variants only) -->
|
|
25
|
+
<ab-form-check v-model="plan" type="radio" name="plan3" variant="card" :options="plans" flat-check check-right />
|
|
26
|
+
|
|
27
|
+
<!-- icon-card: icon centered on top by default (no containerClass needed) -->
|
|
28
|
+
<ab-form-check v-model="plan" type="radio" name="plan4" variant="icon-card" :options="plans" />
|
|
29
|
+
|
|
30
|
+
<!-- card-flat-check: flatCheck styling on by default -->
|
|
31
|
+
<ab-form-check v-model="plan" type="radio" name="plan5" variant="card-flat-check" :options="plans" />
|
|
32
|
+
|
|
33
|
+
<!-- isInline false on a card-family variant: full-width stacked column with a gap between cards -->
|
|
34
|
+
<ab-form-check v-model="plan" type="radio" name="plan6" variant="card" :options="plans" :is-inline="false" />
|
|
35
|
+
|
|
36
|
+
<!-- image-radio: big image tile, native input hidden, check badge overlays a corner -->
|
|
37
|
+
<ab-form-check
|
|
38
|
+
v-model="theme"
|
|
39
|
+
type="radio"
|
|
40
|
+
name="theme"
|
|
41
|
+
variant="image-radio"
|
|
42
|
+
card-width="140px"
|
|
43
|
+
selector-position="top-right"
|
|
44
|
+
:options="[
|
|
45
|
+
{ val: 'light', title: 'Light', img_src: '/light.png' },
|
|
46
|
+
{ val: 'dark', title: 'Dark', img_src: '/dark.png' },
|
|
47
|
+
]"
|
|
48
|
+
/>
|
|
49
|
+
|
|
50
|
+
<!-- image-radio chip mode: isInline=true swaps the big tile for a compact icon+text chip -->
|
|
51
|
+
<ab-form-check v-model="theme" type="radio" name="theme2" variant="image-radio" :options="themes" is-inline />
|
|
52
|
+
|
|
53
|
+
<!-- isBoxShadow: checked state as a colored box-shadow glow instead of a border-color change -->
|
|
54
|
+
<ab-form-check v-model="plan" type="radio" name="plan7" variant="card" :options="plans" is-box-shadow />
|
|
20
55
|
</template>
|
|
21
56
|
```
|
|
22
57
|
|
|
@@ -29,16 +64,26 @@ Checkbox or radio group with card, segmented, and pill visual variants. `AbRadio
|
|
|
29
64
|
| `rules` | `String` | `""` | VeeValidate rules. |
|
|
30
65
|
| `val` | `any` | `null` | Initial value. |
|
|
31
66
|
| `type` | `String` | `"checkbox"` | `"checkbox"` or `"radio"`. |
|
|
32
|
-
| `isInline` | `Boolean` | `false` | Render options inline. |
|
|
33
|
-
| `options` | `Array` | `[]` | Each: `{ val, title, description?, icon?, img_src?, iconComponent?, disable? }`. |
|
|
67
|
+
| `isInline` | `Boolean` | `false` | Render options inline. On `variant="image-radio"` this means something different: options always flow in a wrapping tile grid regardless of this prop; `isInline` instead toggles a compact icon+text chip look (`true`, check badge leads on the left like a normal radio/checkbox and only takes up space once checked) vs. the default big image tile (`false`, check badge overlays the image corner). |
|
|
68
|
+
| `options` | `Array` | `[]` | Each: `{ val, title, description?, icon?, img_src?, iconComponent?, disable?, class? }`. `description` is always rendered via `v-html` — only pass trusted/sanitized HTML. |
|
|
34
69
|
| `name` | `String` | **required** | Field name. |
|
|
35
70
|
| `limit` | `Number` | `0` | Max selections (0 = unlimited). |
|
|
36
|
-
| `containerClass` | `String` | `"mb-3"` | Wrapper class. |
|
|
71
|
+
| `containerClass` | `String` | `"mb-3"` | Wrapper class. `variant="card"`/`"icon-card"`/`"card-flat-check"`/`"image-radio"` layout keywords: `left-top`, `middle-top` (icon position). `icon-card` and `image-radio` default to `middle-top` if neither keyword is passed. |
|
|
37
72
|
| `size` | `String` | `"md"` | Control size. |
|
|
38
73
|
| `iconSize` | `String` | `"24px"` | Icon size (when option has an icon). |
|
|
39
74
|
| `iconGap` | `String` | `"10px"` | Gap between icon and label. |
|
|
40
|
-
| `variant` | `String` | `"default"` | `default`, `card`, `segmented`, `pill`. |
|
|
41
|
-
| `cardWidth` | `String` | `"auto"` | Width of card
|
|
75
|
+
| `variant` | `String` | `"default"` | `default`, `card`, `icon-card` (card with the icon centered on top by default), `card-flat-check` (card with `flatCheck` styling on by default), `image-radio` (image-first card; native input hidden, check badge overlays the image's top-left corner), `segmented`, `pill`. |
|
|
76
|
+
| `cardWidth` | `String` | `"auto"` | Width of the card itself for card-family variants (e.g. `"160px"`, `"50%"`, `"12rem"`). Applies in both inline and stacked (`isInline` set to `false`) layouts. |
|
|
77
|
+
| `checkIcon` | `String` | `undefined` | CSS icon class rendered inside the checked input, replacing the native checkmark/dot. Card-family variants only. |
|
|
78
|
+
| `checkIconComponent` | `Component` | `undefined` | A Vue component (e.g. a Lucide icon) rendered inside the checked input, replacing the native checkmark/dot. Card-family variants only. On `variant="image-radio"`, a built-in circle-check icon is used automatically when neither this nor `checkIcon` is set. |
|
|
79
|
+
| `flatCheck` | `Boolean` | `false` | Shadow-free checked style for card-family variants: border-color change + accent-colored title instead of box-shadow, indicator vertically centered. Always on for `variant="card-flat-check"`. |
|
|
80
|
+
| `checkRight` | `Boolean` | `false` | Moves the checkbox/radio indicator to the right side of the card (card-family variants only). Typically combined with `flatCheck`. |
|
|
81
|
+
| `selectorPosition` | `String` | `"top-left"` | Corner the check badge overlays on the image: `"top-left"`, `"top-right"`, `"bottom-left"`, `"bottom-right"`. `variant="image-radio"` only. |
|
|
82
|
+
| `isBoxShadow` | `Boolean` | `false` | Card-family variants only (`card`, `icon-card`, `card-flat-check`, `image-radio`). Shows checked state as a colored box-shadow glow instead of a border-color change — the border stays transparent throughout, matching the classic `AbImageRadioInput` look. |
|
|
83
|
+
|
|
84
|
+
Card-family variants `card`, `icon-card`, `card-flat-check` with `isInline` set to `false` (the default) stack in a full-width column with a gap between cards, instead of the content-sized cards used when `isInline` set to `true`.
|
|
85
|
+
|
|
86
|
+
`variant="image-radio"` behaves differently from the rest of the card family: options always flow in a wrapping tile grid (never full-width stacked), the native checkbox/radio dot is always hidden, and `isInline` instead switches between two looks — `false` (default): a big image fills the tile with the title below and a check badge overlaying the corner set by `selectorPosition`; `true`: a compact icon+text chip where the check badge leads on the left (like a normal radio/checkbox) instead of overlaying a corner, and only takes up space once an option is checked.
|
|
42
87
|
|
|
43
88
|
## Events
|
|
44
89
|
|
|
@@ -48,12 +93,26 @@ Checkbox or radio group with card, segmented, and pill visual variants. `AbRadio
|
|
|
48
93
|
|
|
49
94
|
## Slots
|
|
50
95
|
|
|
96
|
+
Per-option slots are **not** dynamically named per option (no `-{title}`/`-{val}` suffix) — each is a single
|
|
97
|
+
scoped slot rendered once per option, scoped with `{ check, index }` (`check` is the current `options[index]`
|
|
98
|
+
item). If different options need different content, branch inside the template on `check.val`/`index`:
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<ab-form-check variant="card" :options="plans" v-model="plan" type="radio" name="plan">
|
|
102
|
+
<template #option-label="{ check }">
|
|
103
|
+
<template v-if="check.val === 'pro'">
|
|
104
|
+
<ab-badge variant="danger">Popular</ab-badge> {{ check.title }}
|
|
105
|
+
</template>
|
|
106
|
+
<template v-else>{{ check.title }}</template>
|
|
107
|
+
</template>
|
|
108
|
+
</ab-form-check>
|
|
109
|
+
```
|
|
110
|
+
|
|
51
111
|
| Name | Description |
|
|
52
112
|
| --- | --- |
|
|
53
|
-
| `label` | Group label. |
|
|
54
|
-
| `description` |
|
|
113
|
+
| `label` | Group label (the whole component's `label` prop/heading — not per-option). |
|
|
114
|
+
| `description` | Per-option description, scoped `{ check, index }`. Overrides the option's `description` key (the default content renders it via `v-html`). |
|
|
55
115
|
| `help-text` | Helper text. |
|
|
56
|
-
| `input-
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `description-{option.title}` | Per-option description slot. |
|
|
116
|
+
| `input-icon` | Per-option image/icon area, scoped `{ check, index }` (card-family/segmented/pill variants). Overrides `img_src`/`icon`/`iconComponent`. |
|
|
117
|
+
| `option-label` | Per-option title, scoped `{ check, index }` (card-family/segmented/pill variants). Overrides the option's `title`. Deliberately not named `label` — that name is already the group-level heading slot above. |
|
|
118
|
+
| `check-icon` | Per-option checked-state icon, scoped `{ check, index }` (card-family variants only). Default content falls back to `checkIcon`/`checkIconComponent`; overrides both when provided. |
|
|
@@ -43,6 +43,8 @@ const form = reactive({ email: '' });
|
|
|
43
43
|
| `maxlength` | `any` | `null` | Native `maxlength`. |
|
|
44
44
|
| `isLeftIconBorder` | `Boolean` | `false` | Renders border between the prefix icon and the input. |
|
|
45
45
|
| `isRightIconBorder` | `Boolean` | `false` | Renders border between the postfix icon and the input. |
|
|
46
|
+
|
|
47
|
+
> Set both `isLeftIconBorder` and `isRightIconBorder` to `true` to show a border on both sides at once — the whole input group (icons + field) is treated as one unified box on focus.
|
|
46
48
|
| `passIconPosition` | `String` | `"right"` | Position of the show password icon (`"left"`, `"right"`). |
|
|
47
49
|
| `isHideLabel` | `Boolean` | `false` | Hide the label visually. |
|
|
48
50
|
| `iconPosition` | `String` | `undefined` | Position of the custom `#icon` slot (`"left"`, `"right"`). |
|