@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.
@@ -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 (next to the `right` slot) whenever `showVoiceButton` is `true` (default).
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/Safari — the mic button still renders there but is `disabled`, with a tooltip explaining
96
- why. Requires the browser's mic permission prompt to be accepted.
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. send/mic 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. |
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 five slots are scoped**, receiving the same props so slot content can drive the composer directly:
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
- | `formatDigit` | `Function` | `undefined` | Locale digit formatter (e.g. Bengali digits). |
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
- formatDigit: (val) => String(val).replace(/\d/g, (d) => banglaDigits[d]),
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
- | `formatDigit` | `Function` | `(val) => String(val)` | Digit formatter applied to `AbNumberField` (display-only) and `AbDateTimePicker`. |
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.