@appsbd/vue3-appsbd-ui 1.0.14 → 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 +37 -13
- package/.ai/ai_ref_AbDateTimePicker.md +1 -1
- package/.ai/ai_ref_AbScrollbar.md +27 -0
- package/.ai/ai_ref_global_config.md +39 -4
- package/.ai/ai_ref_migration_guide.md +90 -0
- package/AI_REFERENCE.md +3 -0
- package/CHANGELOG.md +15 -0
- package/dist/style.css +1 -1
- package/dist/vue3-appsbd-ui.cjs.js +89 -79
- package/dist/vue3-appsbd-ui.es.js +9724 -9361
- package/package.json +2 -1
|
@@ -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`. |
|
|
@@ -14,21 +14,17 @@ No extra peer deps beyond the library's own (`@lucide/vue` for the default "+" i
|
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
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
|
+
|
|
17
20
|
```vue
|
|
18
21
|
<template>
|
|
19
|
-
<AbChatInput v-model="message" placeholder="Ask anything" @submit="onSubmit"
|
|
20
|
-
<template #right>
|
|
21
|
-
<button type="button" class="btn btn-primary btn-sm rounded-circle">
|
|
22
|
-
<ArrowUp :size="16" />
|
|
23
|
-
</button>
|
|
24
|
-
</template>
|
|
25
|
-
</AbChatInput>
|
|
22
|
+
<AbChatInput v-model="message" placeholder="Ask anything" @submit="onSubmit" />
|
|
26
23
|
</template>
|
|
27
24
|
|
|
28
25
|
<script setup>
|
|
29
26
|
import { ref } from 'vue';
|
|
30
27
|
import { AbChatInput } from 'vue3-appsbd-ui';
|
|
31
|
-
import { ArrowUp } from '@lucide/vue';
|
|
32
28
|
|
|
33
29
|
const message = ref('');
|
|
34
30
|
function onSubmit({ message, files }) {
|
|
@@ -37,6 +33,21 @@ function onSubmit({ message, files }) {
|
|
|
37
33
|
</script>
|
|
38
34
|
```
|
|
39
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
|
+
|
|
40
51
|
Add/more dropdown (0 items = no trigger, 1 item = direct action with no popover, 2+ items = a real dropdown):
|
|
41
52
|
|
|
42
53
|
```vue
|
|
@@ -76,7 +87,8 @@ a native file picker and routes the selection through `addFiles`) among other me
|
|
|
76
87
|
## Voice input
|
|
77
88
|
|
|
78
89
|
Uses the browser's native Web Speech API (`SpeechRecognition`) — no extra dependency, no API key. A built-in mic
|
|
79
|
-
button renders in the `right` area (
|
|
90
|
+
button renders in the `right` area (before the `right` slot and the send button) whenever `showVoiceButton` is
|
|
91
|
+
`true` (default).
|
|
80
92
|
Clicking it (or calling `startRecording()`) swaps the whole composer row for a full-width recording bar — a live
|
|
81
93
|
audio-reactive waveform (via `getUserMedia` + `AnalyserNode`) plus three controls:
|
|
82
94
|
|
|
@@ -92,8 +104,17 @@ with a searchable list of ~130 BCP-47 locales; picking one sets that recognition
|
|
|
92
104
|
and persists the choice to `localStorage` (key `apbd-chat-input-voice-lang`) so it's remembered next visit. This
|
|
93
105
|
never touches the browser's own language/locale settings — only this component's own recognizer instance.
|
|
94
106
|
|
|
95
|
-
Not supported in Firefox
|
|
96
|
-
|
|
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.
|
|
97
118
|
|
|
98
119
|
## Props
|
|
99
120
|
|
|
@@ -142,12 +163,13 @@ why. Requires the browser's mic permission prompt to be accepted.
|
|
|
142
163
|
| Name | Description |
|
|
143
164
|
| --- | --- |
|
|
144
165
|
| `left` | Left action area (e.g. an attachment button). Scoped — see below. |
|
|
145
|
-
| `right` | Right action area (e.g.
|
|
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. |
|
|
146
168
|
| `menu-trigger` | Overrides the default "+" icon on the add/more trigger. Only rendered when the trigger itself renders (see below). Scoped — see below. |
|
|
147
169
|
| `single-input` | One static `AbChatInputMenuItem` for the add/more dropdown. Scoped — see below. |
|
|
148
170
|
| `multiple-input` | A `v-for`'d set of `AbChatInputMenuItem`s for the add/more dropdown. Scoped — see below. |
|
|
149
171
|
|
|
150
|
-
**All
|
|
172
|
+
**All six slots are scoped**, receiving the same props so slot content can drive the composer directly:
|
|
151
173
|
|
|
152
174
|
| Scoped prop | Description |
|
|
153
175
|
| --- | --- |
|
|
@@ -157,6 +179,7 @@ why. Requires the browser's mic permission prompt to be accepted.
|
|
|
157
179
|
| `clearFiles()` | Same as the exposed method. |
|
|
158
180
|
| `updateText(text)` | Replaces the message text (fires `update:modelValue`). |
|
|
159
181
|
| `focus()` | Focuses the textarea. |
|
|
182
|
+
| `submit()` | Same as the exposed method — fires `submit` with `{ message, files }`. No-op when `disabled`/`readonly`. |
|
|
160
183
|
|
|
161
184
|
A single-item `#single-input`/`#multiple-input` action can use these directly — `onMenuTriggerClick`'s no-dropdown
|
|
162
185
|
fast path reads the item's `action` prop with these same bindings applied, so `:action="addToAttach"` works there too.
|
|
@@ -202,6 +225,7 @@ any slot — e.g. a toolbar button elsewhere on the page.
|
|
|
202
225
|
| `addToAttach(options?)` | Opens a native file picker and routes the selection through `addFiles`. `options`: `{ accept, multiple }`. |
|
|
203
226
|
| `updateText(text)` | Replaces the message text (fires `update:modelValue`). |
|
|
204
227
|
| `focus()` | Focuses the textarea. |
|
|
228
|
+
| `submit()` | Fires `submit` with `{ message, files }` (same as clicking the default send button). No-op when `disabled`/`readonly`. |
|
|
205
229
|
| `startRecording()` | Starts voice input (same as clicking the mic button). No-op if unsupported/disabled/readonly/already recording. |
|
|
206
230
|
| `stopRecording()` | Stops recording, keeping the transcribed text (same as the ■ button). |
|
|
207
231
|
| `cancelRecording()` | Stops recording and discards the transcribed text (same as the ✕ button). |
|
|
@@ -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. |
|
|
@@ -36,3 +36,30 @@ Each event payload is an object with `scrollTop`, `scrollHeight`, `scrollRatio`,
|
|
|
36
36
|
| Name | Description |
|
|
37
37
|
| --- | --- |
|
|
38
38
|
| `default` | Scrollable content. |
|
|
39
|
+
|
|
40
|
+
## Exposed methods
|
|
41
|
+
|
|
42
|
+
Available via a template ref, for programmatic scroll control (e.g. scrolling a chat/message list to the bottom on new content):
|
|
43
|
+
|
|
44
|
+
| Method | Description |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `scrollToBottom(behavior?)` | Scrolls to the bottom. `behavior`: `"auto"` (default) or `"smooth"`. |
|
|
47
|
+
| `scrollToTop(behavior?)` | Scrolls to the top. `behavior`: `"auto"` (default) or `"smooth"`. |
|
|
48
|
+
| `scrollTo(options)` | Same as the native `Element.scrollTo(options)` (e.g. `{ top, left, behavior }`). |
|
|
49
|
+
| `scrollArea` | Raw ref to the internal scrollable element, for anything not covered above. |
|
|
50
|
+
|
|
51
|
+
```vue
|
|
52
|
+
<template>
|
|
53
|
+
<AbScrollbar ref="listRef" style="height: 300px">
|
|
54
|
+
<div v-for="m in messages" :key="m.id">{{ m.text }}</div>
|
|
55
|
+
</AbScrollbar>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<script setup>
|
|
59
|
+
import { ref, nextTick } from 'vue';
|
|
60
|
+
const listRef = ref(null);
|
|
61
|
+
function onNewMessage() {
|
|
62
|
+
nextTick(() => listRef.value.scrollToBottom());
|
|
63
|
+
}
|
|
64
|
+
</script>
|
|
65
|
+
```
|
|
@@ -7,13 +7,11 @@ Call `AppsbdUIConfigure` once during app initialization to set library-wide loca
|
|
|
7
7
|
```javascript
|
|
8
8
|
import { AppsbdUIConfigure } from "@vue3-appsbd-ui";
|
|
9
9
|
|
|
10
|
-
const banglaDigits = ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"];
|
|
11
|
-
|
|
12
10
|
AppsbdUIConfigure({
|
|
13
11
|
monthNames: ["জানুয়ারি", "ফেব্রুয়ারি", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর"],
|
|
14
12
|
monthNamesShort: ["জানু", "ফেব্রু", "মার্চ", "এপ্রি", "মে", "জুন", "জুলাই", "আগস্ট", "সেপ্টে", "অক্টো", "নভে", "ডিসে"],
|
|
15
13
|
dayNames: ["শনি", "রবি", "সোম", "মঙ্গল", "বুধ", "বৃহঃ", "শুক্র"],
|
|
16
|
-
|
|
14
|
+
digits: ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"],
|
|
17
15
|
is24Hour: false,
|
|
18
16
|
rangeSeparator: " থেকে ",
|
|
19
17
|
dateDataFormat: "YYYY-MM-DD",
|
|
@@ -32,7 +30,7 @@ AppsbdUIConfigure({
|
|
|
32
30
|
| `monthNames` | `String[]` | English full names | Array of 12 full month names. |
|
|
33
31
|
| `monthNamesShort` | `String[]` | English short names | Array of 12 short month names. |
|
|
34
32
|
| `dayNames` | `String[]` | English 3-letter names | Array of 7 short day names (Sat-first). |
|
|
35
|
-
| `
|
|
33
|
+
| `digits` | `String[]` | `undefined` | Array of 10 digit characters (0-9) for locale digit transliteration (e.g. Bangla digits), applied by `AbDateTimePicker` and `formatCurrency`/`formatAmount`. |
|
|
36
34
|
| `rangeSeparator` | `String` | `' ↔ '` | Separator for date ranges in `AbDateTimePicker`. |
|
|
37
35
|
| `is24Hour` | `Boolean` | `false` | Whether to use 24-hour format in `AbDateTimePicker`. |
|
|
38
36
|
| `dateDataFormat` | `String` | `'YYYY-MM-DD'` | Global format for date data. |
|
|
@@ -56,3 +54,40 @@ AppsbdUIConfigure({
|
|
|
56
54
|
| `button.iconPosition` | `String` | `'left'` | Global default icon position for buttons (`left`, `right`). |
|
|
57
55
|
| `isModalBorder` | `Boolean` | `true` | Global default modal border. |
|
|
58
56
|
| `modalLoader` | `String` | `'AbLoader'` | Global default modal loader component. |
|
|
57
|
+
| `currency` | `String` | `'$'` | Global default currency symbol, used by `formatCurrency`/`formatAmount`. |
|
|
58
|
+
| `currencyPosition` | `String` | `'left'` | Global default currency symbol position: `'left'`, `'right'`, `'left_space'`, `'right_space'`. |
|
|
59
|
+
| `thousandSeparator` | `String` | `','` | Global default thousand separator, used by `formatCurrency`/`formatAmount`. |
|
|
60
|
+
| `decimalSeparator` | `String` | `'.'` | Global default decimal separator, used by `formatCurrency`/`formatAmount`. |
|
|
61
|
+
| `numberOfDecimals` | `Number` | `2` | Global default number of decimal digits, used by `formatCurrency`/`formatAmount`. |
|
|
62
|
+
| `round` | `Boolean` | `false` | Global default: round to `numberOfDecimals` instead of truncating, used by `formatCurrency`/`formatAmount`. |
|
|
63
|
+
|
|
64
|
+
## `formatCurrency` / `formatAmount` utils
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
import { formatCurrency, formatAmount } from "@vue3-appsbd-ui";
|
|
68
|
+
|
|
69
|
+
formatCurrency(1234.5);
|
|
70
|
+
// -> "$1,234.50" (uses globalConfig.currency/currencyPosition/thousandSeparator/decimalSeparator/numberOfDecimals)
|
|
71
|
+
|
|
72
|
+
formatCurrency(1234.5, { currency: "৳", currencyPosition: "right_space", numberOfDecimals: 0 });
|
|
73
|
+
// -> "1,234 ৳"
|
|
74
|
+
|
|
75
|
+
formatAmount(1234.5); // plain number, no currency symbol -> "1,234.50"
|
|
76
|
+
|
|
77
|
+
// round (default false) — extra decimals are truncated, not rounded up:
|
|
78
|
+
formatCurrency(1234.499); // -> "$1,234.49" (truncated)
|
|
79
|
+
formatCurrency(1234.499, { round: true }); // -> "$1,234.50" (rounded)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Any option not passed falls back to `globalConfig`, then to the hardcoded default (prop > global config > built-in default, same resolution order as other components). `digits` (see above, or `options.digits` per-call) is also applied to the formatted output via the internal `formatDigits` util. By default `round` is `false`: `numberOfDecimals` truncates extra digits rather than rounding (`1234.499` at 2 decimals -> `1234.49`, never `1234.50`); pass `round: true` (or `globalConfig.round = true`) for standard rounding.
|
|
83
|
+
|
|
84
|
+
## `formatDigits` util
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
import { formatDigits } from "@vue3-appsbd-ui";
|
|
88
|
+
|
|
89
|
+
formatDigits(123); // no globalConfig.digits set -> "123"
|
|
90
|
+
formatDigits(123, ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"]); // -> "১২৩"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Used internally by `AbDateTimePicker` (`digits` prop) and `formatCurrency`/`formatAmount` (`options.digits`) to transliterate digits; falls back to `globalConfig.digits` when no array is passed, and returns the value unchanged (stringified) when neither is set.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Migration Guide — AI Reference
|
|
2
|
+
|
|
3
|
+
> Read this file when upgrading a consuming project's `@appsbd/vue3-appsbd-ui` version. It exists to drive *automated* upgrades of consumer code — it does not replace `AI_REFERENCE.md` (current API surface) or [`CHANGELOG.md`](../CHANGELOG.md) (full human-readable prose per release). After applying an entry below, re-check the affected component's `.ai/ai_ref_<Name>.md` for its current API shape.
|
|
4
|
+
|
|
5
|
+
## How to apply an upgrade
|
|
6
|
+
|
|
7
|
+
1. Find the consuming project's currently installed version (`package.json` → `@appsbd/vue3-appsbd-ui` / `vue3-appsbd-ui`).
|
|
8
|
+
2. Walk every version section below, **oldest to newest**, strictly after the current version up to and including the target version.
|
|
9
|
+
3. For each **⚠️ Action Required** item: search the consuming project with its **Find** pattern and apply its **Replace** guidance to every match.
|
|
10
|
+
4. **ℹ️ Also shipped** items need no consumer-side change to keep working — they're listed so an upgrade can optionally *adopt* the new capability. Skip them freely.
|
|
11
|
+
5. After applying every version's Action Required items, build/typecheck the consuming project to confirm no remaining references to removed APIs.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## [1.0.15] - 2026-08-24
|
|
16
|
+
|
|
17
|
+
### ⚠️ Action Required — Breaking
|
|
18
|
+
|
|
19
|
+
- **Global config `formatDigit` removed → `digits`.**
|
|
20
|
+
- Find: `formatDigit` inside any `AppsbdUIConfigure({...})` call, or a `formatDigit` / `:format-digit` prop on `<AbDateTimePicker>`.
|
|
21
|
+
- Replace: the `formatDigit: (val) => ...` function with a plain `digits: [...]` array of 10 characters (index 0 = digit `0`, ... index 9 = digit `9`). Example (Bangla): `digits: ['০','১','২','৩','৪','৫','৬','৭','৮','৯']`.
|
|
22
|
+
- Same rename applies to `AbDateTimePicker`'s own `formatDigit` prop → `digits` prop (now an array, not a function).
|
|
23
|
+
|
|
24
|
+
### ℹ️ Also shipped (no action needed)
|
|
25
|
+
|
|
26
|
+
- New `formatCurrency`/`formatAmount` utils + matching global config keys (`currency`, `currencyPosition`, `thousandSeparator`, `decimalSeparator`, `numberOfDecimals`, `round`) — optional to adopt for consumer-side number/currency formatting.
|
|
27
|
+
- New `AbChatBox` component (wraps `AbChatInput` as a full chat UI) and new `AbScrollbar` exposed scroll methods.
|
|
28
|
+
- `AbFormCheck` checked-state label color and `description-text` truncation CSS fixes; a WordPress `.is-flat-check` margin conflict fix.
|
|
29
|
+
- Several `AbChatInput` voice-input (Safari/Android/iOS) and narrow-viewport layout fixes.
|
|
30
|
+
|
|
31
|
+
## [1.0.14] - 2026-08-19
|
|
32
|
+
|
|
33
|
+
### ⚠️ Action Required — Breaking
|
|
34
|
+
|
|
35
|
+
- **`AbFormCheck` per-title dynamic slot names removed.**
|
|
36
|
+
- Find: slot names shaped `input-icon-${title}`, `option-label-${title}`, `description-${title}` used on `<AbFormCheck>`.
|
|
37
|
+
- Replace: use the static scoped slots `input-icon`, `option-label`, `description` instead — each now receives `{ check, index }`; branch inside the slot on `check.title` (or `index`) if per-option content is still needed.
|
|
38
|
+
- Note: the `description` slot's default content now renders as raw HTML (previously plain text) — escape any content that relied on literal `<`/`>` being displayed as text.
|
|
39
|
+
|
|
40
|
+
### ℹ️ Also shipped (no action needed)
|
|
41
|
+
|
|
42
|
+
- `abDate` library (`formatDate`/`formatDateTime`/`formatTime`/`formatCustom`), driven by new `dateDisplayFormat`/`datetimeDisplayFormat`/`timeDisplayFormat` global config keys.
|
|
43
|
+
- `AbFileUploader` `type="file"` mode (`allowedTypes`, `showFileName`, `width`/`height` props).
|
|
44
|
+
- `AbFormCheck` `icon-card`/`card-flat-check`/`image-radio` variants, `selectorPosition`/`isBoxShadow` props; card-family/segmented/pill rows now fully clickable.
|
|
45
|
+
- `AbInputField` `input-group-text-border-both` layout (automatic).
|
|
46
|
+
- `useFileValidator().getFileInfo()` gained an optional `allowedExtensions` param.
|
|
47
|
+
- **Default value change (non-breaking but visible):** `AbChatInput`'s `borderRadius` prop default changed from `"1.5rem"` to `"2.5rem"` — only affects consumers who never explicitly set `borderRadius` and relied on the old default's look.
|
|
48
|
+
- `AbNumberField` increment/decrement disabled-state fix; `AbMainLayout` iPhone Safari full-height fix.
|
|
49
|
+
|
|
50
|
+
## [1.0.13] - 2026-08-11
|
|
51
|
+
|
|
52
|
+
### ℹ️ Also shipped (no action needed)
|
|
53
|
+
|
|
54
|
+
- New `AbChatInput` + `AbChatInputMenuItem` components (chat composer with attachments).
|
|
55
|
+
- `AbChatInput` scoped slots (`left`/`right`/`menu-trigger`/`single-input`/`multiple-input`) now hand back `addToAttach`/`addFiles`/`removeFile`/`clearFiles`/`updateText`/`focus`; also exposed as template-ref methods.
|
|
56
|
+
- `AbChatInput` `borderRadius`/`filePreviewWidth`/`filePreviewHeight`/`showFileName` props.
|
|
57
|
+
- `AbFilterPanel` async `isAjaxSearch`/`onSearch`, multi-select (`isMultiple`) quick-advance `dd` fields, range-filter fix, active-filter badge style change.
|
|
58
|
+
- `AbWizard` `backgroundColor` prop.
|
|
59
|
+
- `useFileValidator().getFileIconByExt()` fallback-icon fix; RTL styling for `AbProgressbar`.
|
|
60
|
+
|
|
61
|
+
## [1.0.12] - 2026-08-09
|
|
62
|
+
|
|
63
|
+
### ℹ️ Also shipped (no action needed)
|
|
64
|
+
|
|
65
|
+
- `AbCustomField` gained `CP`/`FU` field types and forwards `variant`/`card-width`/`icon-size`/`icon-gap` to radio/checkbox fields.
|
|
66
|
+
- `label` option for `AbColorPicker`/`AbFileUploader`; `AbFormCheck` variation cards support a custom width.
|
|
67
|
+
- `AbToggle` switch icon alignment/sizing fix.
|
|
68
|
+
|
|
69
|
+
## [1.0.11] - 2026-07-30
|
|
70
|
+
|
|
71
|
+
### ⚠️ Action Required — Breaking
|
|
72
|
+
|
|
73
|
+
- **Icon peer dependency migrated `lucide-vue-next` → `@lucide/vue`.**
|
|
74
|
+
- Find: `import { ... } from "lucide-vue-next"` anywhere in the consuming project, and the `lucide-vue-next` entry in its `package.json`.
|
|
75
|
+
- Replace: `import { ... } from "@lucide/vue"` (same named icon exports, requires `@lucide/vue >=1.28.0`); swap the npm dependency itself (`npm uninstall lucide-vue-next && npm install @lucide/vue`).
|
|
76
|
+
- The library ships a `/migrate-lucide-icons` slash command specifically to automate this rename in consuming projects — prefer running that over a manual find/replace.
|
|
77
|
+
|
|
78
|
+
### ℹ️ Also shipped (no action needed)
|
|
79
|
+
|
|
80
|
+
- `AbFilterPanel` multi-variant support and documentation.
|
|
81
|
+
|
|
82
|
+
## [1.0.10] and earlier
|
|
83
|
+
|
|
84
|
+
No breaking changes recorded for `1.0.0` through `1.0.10` — every release in that range was purely additive (new components: `AbInputField`, `AbSideMenuItem`, `AbButton`, `AbPopover`, `AbSidebar`, `AbField`, `AbFilterPanel`, `AbCustomField`, `AbBaseAlert`, `AbConfirmPopover`, `AbFileUploader`, `AbModal`, `AbMainLayout`, `AbSettingsForm`, `abVeeRules`, `AbToggle`, `AbResponseMsg`, `AbCard`, `AbChart`, and the initial component/theme/RTL scaffolding) plus docs/CI work. See [CHANGELOG.md](../CHANGELOG.md) for the full per-release prose if needed.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Maintainer note
|
|
89
|
+
|
|
90
|
+
Whenever a new version is added to `CHANGELOG.md`, add a matching section here **only when that version contains a breaking change** (a renamed/removed prop, event, slot, exposed method, global config key, or peer dependency; a changed function signature; a default value change significant enough to alter rendered output) — give it a `### ⚠️ Action Required — Breaking` subsection with **Find**/**Replace** guidance concrete enough for an AI agent to apply mechanically in a consuming project, without needing to read the full CHANGELOG prose. Every version (breaking or not) should still get a one-line-per-item `### ℹ️ Also shipped (no action needed)` list summarizing what else landed, so an upgrading agent can spot optional new capabilities worth adopting. See [[update-ai-ref-with-component-changes]] in project memory for the full doc-sync checklist this file is part of.
|
package/AI_REFERENCE.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
**Version history**: see [CHANGELOG.md](./CHANGELOG.md) for release-by-release notes.
|
|
8
8
|
|
|
9
|
+
**Upgrading a consuming project?** Read [.ai/ai_ref_migration_guide.md](./.ai/ai_ref_migration_guide.md) — per-version breaking-change find/replace steps meant for an AI agent to apply mechanically when bumping this library's version in another project.
|
|
10
|
+
|
|
9
11
|
## Components & APIs
|
|
10
12
|
|
|
11
13
|
✅ = globally registered via `app.use(AppsbdUI)` — all others require `import { X } from "vue3-appsbd-ui"`.
|
|
@@ -58,6 +60,7 @@
|
|
|
58
60
|
| `AbChart` | — | Flexible chart component powered by Apache ECharts. | [.ai/ai_ref_AbChart.md](./.ai/ai_ref_AbChart.md) |
|
|
59
61
|
| `AbChatInput` | — | ChatGPT-style auto-growing composer with an item-count-driven add/more dropdown, internal file attachment preview, and built-in Web Speech API voice input. | [.ai/ai_ref_AbChatInput.md](./.ai/ai_ref_AbChatInput.md) |
|
|
60
62
|
| `AbChatInputMenuItem` | — | Presentational row (icon/name/description/action) for `AbChatInput`'s add/more dropdown. | [.ai/ai_ref_AbChatInputMenuItem.md](./.ai/ai_ref_AbChatInputMenuItem.md) |
|
|
63
|
+
| `AbChatBox` | — | Full chat conversation container (header, message list, empty/typing states) built on `AbChatInput`; every part is slot-overridable. | [.ai/ai_ref_AbChatBox.md](./.ai/ai_ref_AbChatBox.md) |
|
|
61
64
|
| `AbDarkModeToggler` | — | Light / dark theme toggle (pairs with `useTheme`). | [.ai/ai_ref_AbDarkModeToggler.md](./.ai/ai_ref_AbDarkModeToggler.md) |
|
|
62
65
|
| `useAlert` | — | Procedural API to trigger SweetAlert-based modal alerts, notifications, and confirmations. | [.ai/ai_ref_useAlert.md](./.ai/ai_ref_useAlert.md) |
|
|
63
66
|
| `abEventBus` / `emitterObj` | — | Lightweight global event bus using `tiny-emitter`. | [.ai/ai_ref_abEventBus.md](./.ai/ai_ref_abEventBus.md) |
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@appsbd/vue3-appsbd-ui` are documented here. Format loosely follows [Keep a Changelog](https://keepachangelog.com/).
|
|
4
4
|
|
|
5
|
+
## [1.0.15] - 2026-08-24
|
|
6
|
+
|
|
7
|
+
- **Added**: `AbChatBox` — a full chat conversation container built on top of `AbChatInput`: header (title/subtitle/avatar, or fully custom via the `header`/`header-actions` slots), a scrollable message list with a default bubble renderer (overridable per-message via `message`/`message-avatar`), empty and typing states (`empty`/`typing` slots), and the composer docked at the bottom. `v-model:messages` holds the conversation, `v-model` holds the composer text; submitting auto-appends the user's message and fires `send`. Every `AbChatInput` prop, event, and slot (`left`/`right`/`send-button`/`menu-trigger`/`single-input`/`multiple-input`) is forwarded straight through to the inner composer.
|
|
8
|
+
- **Added**: `AbScrollbar` exposed methods — `scrollToBottom(behavior?)`, `scrollToTop(behavior?)`, `scrollTo(options)`, and a raw `scrollArea` ref — for programmatic scroll control via a template ref (used internally by `AbChatBox`'s auto-scroll-to-bottom behavior).
|
|
9
|
+
- **Added**: `formatCurrency`/`formatAmount` utils (`src/utils/formatCurrency.js`) — format a number with configurable `thousandSeparator`, `decimalSeparator`, `numberOfDecimals`, and (for `formatCurrency`) a `currency` symbol at `currencyPosition` (`'left'`, `'right'`, `'left_space'`, `'right_space'`). By default, extra decimals are truncated rather than rounded (`1234.499` at 2 decimals -> `1234.49`); pass `round: true` for standard rounding instead. New global config keys `currency`, `currencyPosition`, `thousandSeparator`, `decimalSeparator`, `numberOfDecimals`, `round` supply the defaults when not passed per call. Documented with a live demo in the `GlobalConfigTest` playground page.
|
|
10
|
+
- **Fixed**: `formatAmount`'s truncation used `Math.trunc(amount * 10**n) / 10**n`, which reintroduces floating-point noise the multiplication itself creates (e.g. `19.9 * 100 === 1989.9999999999998`), silently truncating one digit too far (`19.9` at 2 decimals showed `19.89` instead of `19.90`). Now truncates against the number's own shortest round-trip string representation instead of re-multiplying it.
|
|
11
|
+
- **Changed**: Global config's `formatDigit` (a `Function` consumers had to write themselves) replaced with `digits` — a plain 10-character array (e.g. `['০','১',...,'৯']`); the library now transliterates digits internally via the new `formatDigits` util. `AbDateTimePicker`'s `formatDigit` prop is likewise replaced with a `digits` prop. Breaking change for any consumer passing `formatDigit`.
|
|
12
|
+
- **Fixed**: `AbFormCheck` checked card-family label color now uses `--#{$prefix}theme` instead of `--#{$prefix}apbd-border-color-focus`, matching the selected-state accent elsewhere. `description-text` no longer forces `white-space: nowrap` (was clipping to a single line regardless of card width); truncation now relies on `overflow: hidden` instead of a duplicate nested `text-overflow: ellipsis` rule.
|
|
13
|
+
- **Fixed**: WordPress theme conflict — `.is-flat-check` checkbox/radio inputs now reset `margin: 0` to counter WordPress's default form-control margin.
|
|
14
|
+
- **Fixed**: `AbChatInput` voice input on Safari — `SpeechRecognition` was ending the session after the very first final result despite `continuous: true`, making the mic effectively stop working after one phrase; it now auto-restarts transparently when the browser ends the session on its own (skipped when the last error was permission/hardware-related, to avoid looping).
|
|
15
|
+
- **Fixed**: `AbChatInput` voice input on Android Chrome — the component's own `getUserMedia` call (used only to drive the waveform animation) held a second, concurrent mic-capture session alongside `SpeechRecognition`; Android only allows one exclusive capture session at a time, so the recognizer was starved of audio with no error and no results, even though it started listening. Requesting that stream *after* `recognition.start()` (previous attempt) wasn't sufficient — `.start()` returns before the engine actually acquires the mic, so the race remained. The waveform's `getUserMedia` call is now skipped entirely on Android (detected via user agent); recognition and transcription work normally there, just without the live waveform animation.
|
|
16
|
+
- **Fixed**: `AbChatInput` voice input on iOS browsers other than Safari (Chrome, Firefox, Edge, Opera) — these share Safari's WebKit engine and expose the same `webkitSpeechRecognition` constructor, so the mic button rendered enabled, but iOS never actually grants the mic permission for it outside Safari's own app: tapping it showed no permission prompt at all and immediately surfaced a confusing "Microphone permission denied" toast. Now detected via user agent and treated as unsupported up front (button disabled, tooltip explains why), matching the real platform capability.
|
|
17
|
+
- **Fixed**: `AbChatInput` — voice-transcribed text no longer grew the textarea's height. The recording UI and the normal composer (holding `<textarea ref="textareaRef">`) are mutually exclusive template branches, so the textarea is fully unmounted while listening; every resize triggered by a transcribed phrase silently no-op'd against a null ref, and nothing re-measured it once recording ended and the textarea remounted (typing anything afterward was the only thing that happened to trigger a resize). Now explicitly resizes the moment recording stops.
|
|
18
|
+
- **Fixed**: `AbChatInput` on narrow viewports (e.g. small mobile screens) — with an empty composer, the "grown" (stacked) layout could trigger on mount even with nothing typed. A `<textarea>`'s `scrollHeight` includes its wrapped *placeholder* text; when the left/right icon buttons leave little room, even a short placeholder can wrap onto multiple lines and inflate `scrollHeight` past `minHeight`. The grown/inline decision is now skipped entirely when there's no actual value — the compact single-row layout is forced instead.
|
|
19
|
+
|
|
5
20
|
## [1.0.14] - 2026-08-19
|
|
6
21
|
|
|
7
22
|
- **Added**: `abDate` library — dependency-free date/datetime/time formatter (`formatDate`, `formatDateTime`, `formatTime`, `formatCustom`) with no timezone conversion; resolves its default format from the new `dateDisplayFormat`/`datetimeDisplayFormat`/`timeDisplayFormat` global config keys, falling back to MySQL-style defaults (`YYYY-MM-DD`, `YYYY-MM-DD HH:mm:ss`, `HH:mm:ss`). Same token set as `AbDateTimePicker`, plus real second support (`ss`/`s`). Documented in the new `AbDateTest` playground page.
|