@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.
@@ -38,6 +38,7 @@ const qty = ref(1);
38
38
  | `isBorder` | `Boolean` | `false` | Show inner borders between minus/input/plus. Default is a seamless pill. |
39
39
  | `isLeftIconBorder` | `Boolean` | `false` | Render border between the prefix icon and the input. |
40
40
  | `isRightIconBorder` | `Boolean` | `false` | Render border between the postfix icon and the input. |
41
+ | `size` | `String` | `undefined` | Input size: `"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`. Falls back to `globalConfig.size`, then `"md"`. |
41
42
 
42
43
  ## Events
43
44
 
@@ -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
+ ```
@@ -0,0 +1,58 @@
1
+ # abDate (Library)
2
+
3
+ Chhoto, dependency-free date/datetime/time formatting library (dayjs-er moto). Kono timezone conversion kore na — je value deya hoy sheta as-is (wall-clock) format hoy.
4
+
5
+ ## Usage
6
+
7
+ ```javascript
8
+ import { formatDate, formatDateTime, formatTime, formatCustom } from "@vue3-appsbd-ui/libraries/abDate";
9
+
10
+ formatDate("2026-08-17"); // globalConfig.dateDisplayFormat na thakle -> "2026-08-17"
11
+ formatDateTime("2026-08-17 14:05:09"); // globalConfig.datetimeDisplayFormat na thakle -> "2026-08-17 14:05:09"
12
+ formatTime(new Date()); // globalConfig.timeDisplayFormat na thakle -> "14:05:09"
13
+ formatCustom("2026-08-17", "DD/MM/YYYY"); // -> "17/08/2026"
14
+ ```
15
+
16
+ ## Default Format Resolution
17
+
18
+ `formatDate` / `formatDateTime` / `formatTime` resolve their format in this order:
19
+
20
+ 1. Explicit `format` argument.
21
+ 2. `AppsbdUIConfigure`'s `dateDisplayFormat` / `datetimeDisplayFormat` / `timeDisplayFormat` (see [ai_ref_global_config.md](./ai_ref_global_config.md)).
22
+ 3. Built-in MySQL default: `'YYYY-MM-DD'` / `'YYYY-MM-DD HH:mm:ss'` / `'HH:mm:ss'`.
23
+
24
+ ## API Reference
25
+
26
+ ### Functions
27
+
28
+ | Function | Signature | Description |
29
+ |---|---|---|
30
+ | `formatDate` | `(value, format?) => string` | Formats `value` as a date. Falls back to `globalConfig.dateDisplayFormat`, then `'YYYY-MM-DD'`. |
31
+ | `formatDateTime` | `(value, format?) => string` | Formats `value` as a date+time. Falls back to `globalConfig.datetimeDisplayFormat`, then `'YYYY-MM-DD HH:mm:ss'`. |
32
+ | `formatTime` | `(value, format?) => string` | Formats `value` as a time. Falls back to `globalConfig.timeDisplayFormat`, then `'HH:mm:ss'`. |
33
+ | `formatCustom` | `(value, format) => string` | Generic formatter — `format` is required, no default resolution. |
34
+
35
+ ### `value` Input Types
36
+
37
+ - `Date` — used as-is.
38
+ - `number` — treated as an epoch timestamp (`new Date(value)`).
39
+ - `string` — parsed manually (no native `Date` parsing quirks): `YYYY-MM-DD`, `YYYY-MM-DD HH:mm[:ss]`, `YYYY-MM-DDTHH:mm:ss(.sss)(Z|±HH:mm)`, or time-only `HH:mm[:ss]` (attached to today's date). Any trailing `Z`/offset is **ignored**, not applied as a shift. Unrecognized strings fall back to native `new Date(string)`.
40
+ - Falsy or unparseable input → all functions return `''`.
41
+
42
+ ### Format Tokens
43
+
44
+ Same token set as `AbDateTimePicker.vue`, plus real second support (`ss`/`s`):
45
+
46
+ | Token | Meaning | Example |
47
+ |---|---|---|
48
+ | `YYYY` / `YY` | 4/2-digit year | `2026` / `26` |
49
+ | `MMMM` / `MMM` | Full/short month name (uses `globalConfig.monthNames`/`monthNamesShort`, English default) | `August` / `Aug` |
50
+ | `MM` / `M` | 2/1-digit month | `08` / `8` |
51
+ | `DD` / `D` | 2/1-digit day | `17` / `17` |
52
+ | `HH` / `H` | 2/1-digit hour (24h) | `14` / `14` |
53
+ | `hh` / `h` | 2/1-digit hour (12h) | `02` / `2` |
54
+ | `mm` / `m` | 2/1-digit minute | `05` / `5` |
55
+ | `ss` / `s` | 2/1-digit second | `09` / `9` |
56
+ | `A` / `a` | Upper/lowercase AM-PM | `PM` / `pm` |
57
+
58
+ No timezone conversion is performed anywhere in this library.
@@ -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.
@@ -14,10 +14,15 @@ function handleFileUpload(event) {
14
14
  const file = event.target.files[0];
15
15
  if (!file) return;
16
16
 
17
- const validatedFile = getFileInfo(file, 2.0);
18
- if (validatedFile) {
19
- // validatedFile.isImage
20
- // validatedFile.fileIcon
17
+ // Legacy / default: image-only, validated against a static jpg/png/gif/webp mime map.
18
+ const validatedImage = getFileInfo(file, 2.0);
19
+
20
+ // Custom extension list: any extension in the list is allowed (no mime map needed).
21
+ const validatedDoc = getFileInfo(file, 5.0, ["pdf", "doc", "docx", "xlsx"]);
22
+
23
+ if (validatedDoc) {
24
+ // validatedDoc.isImage
25
+ // validatedDoc.fileIcon
21
26
  }
22
27
  }
23
28
  </script>
@@ -27,5 +32,5 @@ function handleFileUpload(event) {
27
32
 
28
33
  | Method | Signature | Description |
29
34
  |---|---|---|
30
- | `getFileInfo(file, sizeLimitMb)` | `Function` | Validates a `File` object against allowed MIME types and max size (`sizeLimitMb`, default `1.0`). If invalid, spawns a toast error and returns `null`. If valid, returns the `file` augmented with `isImage` and `fileIcon` properties. |
35
+ | `getFileInfo(file, sizeLimitMb, allowedExtensions?)` | `Function` | Validates a `File` object and max size (`sizeLimitMb`, default `1.0`). Without `allowedExtensions`, only jpg/jpeg/png/gif/webp are allowed and cross-checked against the file's actual MIME type (legacy, image-only behavior). With `allowedExtensions` (array of extensions, no dot, e.g. `['pdf', 'docx']`), any extension in that list is allowed instead — no MIME cross-check. If invalid, spawns a toast error and returns `null`. If valid, returns the `file` augmented with `isImage` and `fileIcon` properties. |
31
36
  | `getFileIconByExt(ext, type)` | `Function` | Returns `{ isImage: boolean, fileIcon: Component\|String }` based on file extension and MIME type. Uses `@lucide/vue` icons for known formats (pdf, zip, doc, xls, ppt, mp4). |
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"`.
@@ -21,7 +23,7 @@
21
23
  | `AbField` | ✅ | Polymorphic field wrapper - renders any input type via a `type` prop. | [.ai/ai_ref_AbField.md](./.ai/ai_ref_AbField.md) |
22
24
  | `AbCustomField` | ✅ | Dynamic form scaffold driven by a `fieldInputs` array. | [.ai/ai_ref_AbCustomField.md](./.ai/ai_ref_AbCustomField.md) |
23
25
  | `AbDateTimePicker` | ✅ | Date / time / range picker. Also import `v-calendar/style.css` in consuming app. | [.ai/ai_ref_AbDateTimePicker.md](./.ai/ai_ref_AbDateTimePicker.md) |
24
- | `AbFormCheck` / `AbRadioInput` | ✅ | Checkbox / radio group (default, card, segmented, pill variants). `AbRadioInput` is an alias of `AbFormCheck`. | [.ai/ai_ref_AbFormCheck.md](./.ai/ai_ref_AbFormCheck.md) |
26
+ | `AbFormCheck` / `AbRadioInput` | ✅ | Checkbox / radio group (default, card, icon-card, card-flat-check, image-radio, segmented, pill variants). `AbRadioInput` is an alias of `AbFormCheck`. | [.ai/ai_ref_AbFormCheck.md](./.ai/ai_ref_AbFormCheck.md) |
25
27
  | `AbToggle` | ✅ | Accessible switch/toggle with title & description slots. | [.ai/ai_ref_AbToggle.md](./.ai/ai_ref_AbToggle.md) |
26
28
  | `AbInputTag` | ✅ | Multi-tag input with optional option list. | [.ai/ai_ref_AbInputTag.md](./.ai/ai_ref_AbInputTag.md) |
27
29
  | `AbMultiSelect` | ✅ | Searchable single/multi/tag select (custom built-in — replaces `@vueform/multiselect`). | [.ai/ai_ref_AbMultiSelect.md](./.ai/ai_ref_AbMultiSelect.md) |
@@ -39,7 +41,7 @@
39
41
  | `AbMainLayout` | — | Full-page application shell with left/right sidebar drawers, header, body, and footer slots. Mobile-responsive. | [.ai/ai_ref_AbMainLayout.md](./.ai/ai_ref_AbMainLayout.md) |
40
42
  | `AbSlider` | — | Single or range numeric slider. | [.ai/ai_ref_AbSlider.md](./.ai/ai_ref_AbSlider.md) |
41
43
  | `AbColorPicker` | — | Radio-style color swatch picker. | [.ai/ai_ref_AbColorPicker.md](./.ai/ai_ref_AbColorPicker.md) |
42
- | `AbFileUploader` | — | File upload field with drag-and-drop and size validation. | [.ai/ai_ref_AbFileUploader.md](./.ai/ai_ref_AbFileUploader.md) |
44
+ | `AbFileUploader` | — | File upload field with size validation; image mode (default, preview) or file mode (`allowedTypes` + extension icons). | [.ai/ai_ref_AbFileUploader.md](./.ai/ai_ref_AbFileUploader.md) |
43
45
  | `AbFilterPanel` | — | Advanced filter panel with search and scan modes. | [.ai/ai_ref_AbFilterPanel.md](./.ai/ai_ref_AbFilterPanel.md) |
44
46
  | `AbSettingsForm` | — | Settings-style form that auto-registers as a wizard step validator. | [.ai/ai_ref_AbSettingsForm.md](./.ai/ai_ref_AbSettingsForm.md) |
45
47
  | `AbScrollbar` | — | Styled custom scrollbar wrapper with scroll events. | [.ai/ai_ref_AbScrollbar.md](./.ai/ai_ref_AbScrollbar.md) |
@@ -56,16 +58,20 @@
56
58
  | `AbPricingContainer` | — | Layout wrapper for pricing tables. | [.ai/ai_ref_AbPricingContainer.md](./.ai/ai_ref_AbPricingContainer.md) |
57
59
  | `AbPricingTable` | — | Stylized, responsive pricing table component with feature list and package columns. | [.ai/ai_ref_AbPricingTable.md](./.ai/ai_ref_AbPricingTable.md) |
58
60
  | `AbChart` | — | Flexible chart component powered by Apache ECharts. | [.ai/ai_ref_AbChart.md](./.ai/ai_ref_AbChart.md) |
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) |
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) |
59
64
  | `AbDarkModeToggler` | — | Light / dark theme toggle (pairs with `useTheme`). | [.ai/ai_ref_AbDarkModeToggler.md](./.ai/ai_ref_AbDarkModeToggler.md) |
60
65
  | `useAlert` | — | Procedural API to trigger SweetAlert-based modal alerts, notifications, and confirmations. | [.ai/ai_ref_useAlert.md](./.ai/ai_ref_useAlert.md) |
61
66
  | `abEventBus` / `emitterObj` | — | Lightweight global event bus using `tiny-emitter`. | [.ai/ai_ref_abEventBus.md](./.ai/ai_ref_abEventBus.md) |
62
67
  | `useTheme` | — | Composable for light/dark theme toggling with localStorage and system preference sync. | [.ai/ai_ref_useTheme.md](./.ai/ai_ref_useTheme.md) |
63
68
  | `useToast` | — | Procedural API to spawn toast notifications (success, error, warning, info). | [.ai/ai_ref_useToast.md](./.ai/ai_ref_useToast.md) |
64
- | `useFileValidator` | — | File validation utilities (size, MIME type) and file icon/image resolvers. | [.ai/ai_ref_useFileValidator.md](./.ai/ai_ref_useFileValidator.md) |
69
+ | `useFileValidator` | — | File validation utilities (size, MIME type, or a custom allowed-extensions list) and file icon/image resolvers. | [.ai/ai_ref_useFileValidator.md](./.ai/ai_ref_useFileValidator.md) |
65
70
  | `useResponsive` | — | Real-time viewport width tracker for responsive layout decisions (Bootstrap 5 aligned). | [.ai/ai_ref_useResponsive.md](./.ai/ai_ref_useResponsive.md) |
66
71
  | `abTranslate` | — | Localization utility wrapping `vue3-gettext` with automatic variable interpolation. | [.ai/ai_ref_abTranslate.md](./.ai/ai_ref_abTranslate.md) |
67
72
  | `abVeeRules` | — | Collection of pre-configured VeeValidate validation rules integrated with localization. | [.ai/ai_ref_abVeeRules.md](./.ai/ai_ref_abVeeRules.md) |
68
73
  | `abRequestParam` | — | Data-transfer classes to build structured API request parameters (pagination, sorting, filtering). | [.ai/ai_ref_abRequestParam.md](./.ai/ai_ref_abRequestParam.md) |
74
+ | `abDate` | — | Dependency-free date/datetime/time formatter (dayjs-style); no timezone conversion, defaults from global config. | [.ai/ai_ref_abDate.md](./.ai/ai_ref_abDate.md) |
69
75
 
70
76
  ## Directives & Controller APIs
71
77
 
package/CHANGELOG.md CHANGED
@@ -2,8 +2,40 @@
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
- ## [Unreleased] (1.0.13)
6
-
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
+
20
+ ## [1.0.14] - 2026-08-19
21
+
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.
23
+ - **Added**: `AbFileUploader` `type` prop (`"image"` default | `"file"`) for generic (non-image) uploads, showing an extension icon instead of a thumbnail for non-image files; `allowedTypes` prop (required in `type="file"` mode, also drives the input's `accept` attribute); `showFileName` prop (auto on for `file` mode, off for `image` mode); `width`/`height` props for the container.
24
+ - **Changed**: `useFileValidator().getFileInfo(file, sizeLimitMb, allowedExtensions?)` accepts an optional `allowedExtensions` array to validate against a custom extension list instead of the built-in image MIME map (used internally by `AbFileUploader`'s new `file` mode).
25
+ - **Added**: `AbFormCheck` `icon-card`, `card-flat-check`, and `image-radio` variants; `selectorPosition` prop (which corner the check badge overlays on `image-radio`) and `isBoxShadow` prop (colored box-shadow glow instead of a border-color change, card-family variants).
26
+ - **Changed**: `AbFormCheck` card-family/segmented/pill rows are now clickable anywhere in the card (not just the label text) to toggle the option; per-option `input-icon`/`option-label`/`description` slots are now static and scoped with `:check`/`:index`, replacing the old per-title dynamic slot names (`input-icon-${title}` etc.); the `description` slot's default content now renders as HTML.
27
+ - **Fixed**: `AbNumberField` increment/decrement buttons were incorrectly disabled whenever the field was empty (no value yet), even with no `min`/`max` set; now only disabled once a value is present and actually reaches the configured `min`/`max`.
28
+ - **Added**: `AbInputField` `input-group-text-border-both` layout — applied automatically when both a left and right icon/prefix/postfix are present, giving the combined input-group a single bordered outline with shared focus and error box-shadow states (previously only one side could be borderless-adjacent).
29
+ - **Changed**: `AbChatInput` `borderRadius` prop default changed from `"1.5rem"` to `"2.5rem"`.
30
+ - **Fixed**: `AbMainLayout` (`.apbd-container`) full-height on iPhone Safari — `100vh`/`100vw` were declared *after* `100dvh`/`100dvw`, so the plain viewport units always won the cascade and negated the dynamic-viewport fallback; the container was sized to the toolbar-hidden max viewport, overflowing and forcing the whole page to scroll when the address bar was visible. Reordered so `dvh`/`dvw` override last, and added the missing `100dvh` to the mobile (`max-width: 575.98px`) breakpoint.
31
+
32
+ ## [1.0.13] - 2026-08-11
33
+
34
+ - **Added**: `AbChatInput` + `AbChatInputMenuItem` — a ChatGPT-style auto-growing chat composer with an item-count-driven add/more dropdown (custom-positioned, matching the composer's full width, opens below by default and flips above without ever clipping when there isn't room below), a stacked "grown" layout (textarea full-width on top, left/right controls on their own row below once content passes one line), and internally-validated file attachment preview (no 3rd-party libraries).
35
+ - **Added**: `AbChatInput`'s `left`/`right`/`menu-trigger`/`single-input`/`multiple-input` slots are now scoped, handing back `addToAttach`/`addFiles`/`removeFile`/`clearFiles`/`updateText`/`focus` — slot content (e.g. a dropdown menu item's `action`) can drive the composer directly with no template `<input type="file">` and no manual template refs. Also exposed as template-ref methods for use outside any slot.
36
+ - **Added**: `AbChatInput` `borderRadius` (any CSS length, default `1.5rem`), `filePreviewWidth`/`filePreviewHeight` (px, default `24`), and `showFileName` (default `true`) props, for customizing the composer's roundness and each attached file chip's thumbnail/icon size and filename visibility.
37
+ - **Fixed**: `AbChatInput` — eliminated a flicker during real (keystroke-by-keystroke) typing right at the single-line/multi-line boundary, where the textarea had already grown taller but the row's layout hadn't switched to the stacked mode yet, leaving the button visually stuck mid-block instead of dropping below.
38
+ - **Fixed**: `useFileValidator().getFileIconByExt()` — the fallback icon for extensions with no dedicated case (e.g. `.txt`, `.csv`, `.json`) was a legacy icon-font CSS class string, not a component; `AbChatInput` renders it via `<component :is>`, so those files silently failed to render a file chip. Now falls back to a proper `File` icon component from `@lucide/vue`.
7
39
  - **Added**: `AbFilterPanel` `isAjaxSearch` + async `onSearch(query)` support on quick-advance `dd` fields, fetching remote options as the user types in the popover search box.
8
40
  - **Added**: `AbFilterPanel` multi-select (`isMultiple`) support for quick-advance `dd` fields, with `operators: "in"` array values.
9
41
  - **Added**: `AbWizard` `backgroundColor` prop to set an explicit background on the wizard root/modal-content; a nested `AbSettingsForm` automatically goes transparent to match it.