@appsbd/vue3-appsbd-ui 1.0.16 → 1.0.17
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_AbDateTimePicker.md +3 -0
- package/.ai/ai_ref_AbFilterPanel.md +11 -1
- package/.ai/ai_ref_AbInputField.md +3 -0
- package/.ai/ai_ref_AbMultiSelect.md +3 -0
- package/.ai/ai_ref_abTranslate.md +10 -0
- package/.ai/ai_ref_abVeeRules.md +54 -12
- package/.ai/ai_ref_migration_guide.md +23 -0
- package/CHANGELOG.md +14 -0
- package/dist/style.css +1 -1
- package/dist/vue3-appsbd-ui.cjs.js +65 -65
- package/dist/vue3-appsbd-ui.es.js +11614 -11207
- package/package.json +1 -1
|
@@ -33,6 +33,9 @@ const datetime = ref(null);
|
|
|
33
33
|
| `isRange` | `Boolean` | `false` | Enable date-range mode. |
|
|
34
34
|
| `size` | `String` | `"md"` | Adjusts component size (`xs`, `sm`, `md`, `lg`, `xl`, `xxl`). |
|
|
35
35
|
| `containerClass` | `String` | `"mb-3"` | Wrapper class. |
|
|
36
|
+
| `width` | `String \| Number` | `undefined` | Explicit width on the `.apbd-date-time-container` wrapper. A number is treated as px (e.g. `220` -> `220px`); a string is used as-is (e.g. `"50%"`). |
|
|
37
|
+
| `minWidth` | `String \| Number` | `undefined` | `min-width` on the wrapper (same number/string rules as `width`). |
|
|
38
|
+
| `maxWidth` | `String \| Number` | `undefined` | `max-width` on the wrapper (same number/string rules as `width`) — caps growth inside a flex/grid parent without a fixed `width`. |
|
|
36
39
|
| `hints` | `String` | `""` | Helper text. |
|
|
37
40
|
| `isDisable` | `Boolean` | `false` | Disable the picker. |
|
|
38
41
|
| `visibility` | `String` | `"click"` | v-calendar popover trigger. |
|
|
@@ -4,6 +4,12 @@ Advanced filter panel for list and table views. Supports quick/advance modes, si
|
|
|
4
4
|
|
|
5
5
|
`isMultiple` is functional in `isQuickAdvance` mode for `dd` fields: selections toggle on/off and render as removable tag chips on the popover trigger (no `AbMultiSelect` involved). The popover's option list is searchable — locally against `options`, or via `isAjaxSearch` + `onSearch` for server-side search.
|
|
6
6
|
|
|
7
|
+
`isBuilderFilter` is a Shopify-style filter builder: no field is visible until the user clicks the `+` button. That opens a popover which first lists every not-yet-applied `filterOptions` entry by `name`; picking one swaps the same popover to a value editor matching that field's `type` (`dd`→`AbMultiSelect`, `t`→`AbInputField`, `tr`→min/max inputs, `d`/`dr`→`AbDateTimePicker`) plus Cancel/Apply Filter buttons. Apply pushes it in as a removable chip (e.g. "Email contains gmail") and immediately fires `searchFilter` — there's no global Search button in this mode, only Reset (clears every applied chip and value at once). A field's `operators` is fixed by its schema entry, same as other modes — this mode does not add an is/is-not/contains operator picker, only the value input changes per `type`.
|
|
8
|
+
|
|
9
|
+
Standard-search, advance-search, and quick-advance field layouts are all plain flex (`d-flex flex-wrap gap-2`) — no Bootstrap grid. Each field grows/shrinks on its own, which means a field left alone on the last row will stretch to fill the remaining row width; give a `filterOptions` entry a `width`, `minWidth`, and/or `maxWidth` key (`String | Number` — a number is px, e.g. `maxWidth: 280`, or a CSS string like `"50%"`) to control that specific field's size. All three are forwarded straight to the underlying `AbInputField`/`AbMultiSelect`/`AbDateTimePicker`'s own same-named props, and also constrain that field's flex-item wrapper directly (`width` sets `flex: 0 0 <width>` so it stops growing/shrinking; `minWidth`/`maxWidth` clamp it while it keeps growing/shrinking with its siblings).
|
|
10
|
+
|
|
11
|
+
The standard-mode property-selector (and the scan field it swaps for) isn't part of `filterOptions` — it's not tied to one field, it lists all of them — so it has no `width`/`minWidth`/`maxWidth` key to set. It's also the only item in its row until a property is picked (or whenever `showScanFld` is on), so without sizing it it'll stretch to fill the row the same way an unsized `filterOptions` field would. Use the panel-level `propertySelectWidth`/`propertySelectMinWidth`/`propertySelectMaxWidth` props for that slot instead.
|
|
12
|
+
|
|
7
13
|
## Usage
|
|
8
14
|
|
|
9
15
|
```vue
|
|
@@ -37,6 +43,7 @@ function handleSearch(data) {
|
|
|
37
43
|
| -------------------------- | --------- | --------------- | ---------------------------------------------------------- |
|
|
38
44
|
| `isAdvance` | `Boolean` | `false` | Show all filters in an expanded layout. |
|
|
39
45
|
| `isQuickAdvance` | `Boolean` | `false` | Quick advance mode. |
|
|
46
|
+
| `isBuilderFilter` | `Boolean` | `false` | Shopify-style "+" add-filter builder — see mode description above. |
|
|
40
47
|
| `isSingle` | `Boolean` | `false` | Single-field search mode. |
|
|
41
48
|
| `isAutoSearch` | `Boolean` | `false` | Auto search on input change (single mode). |
|
|
42
49
|
| `isAllowed` | `Boolean` | `false` | Permission flag consumed by the template. |
|
|
@@ -49,7 +56,10 @@ function handleSearch(data) {
|
|
|
49
56
|
| `isSearchable` | `Boolean` | `false` | Allow searching within option lists. |
|
|
50
57
|
| `isMaxDate` | `Boolean` | `true` | Limit date pickers to today as max. |
|
|
51
58
|
| `size` | `String` | `"xs"` | Control size. |
|
|
52
|
-
| `advanceContainerClass` | `String` | `"
|
|
59
|
+
| `advanceContainerClass` | `String` | `""` | Extra class on each field's flex-item wrapper in advance mode (base sizing is `flex: 1 1 240px`, wraps as needed — not a Bootstrap grid). To fix a single field's width instead, use that field's own `width` prop (`AbInputField`/`AbMultiSelect`/`AbDateTimePicker`). |
|
|
60
|
+
| `propertySelectWidth` | `String` \| `Number` | `undefined` | Width of the standard-mode property-selector / scan-field slot (number = px). |
|
|
61
|
+
| `propertySelectMinWidth` | `String` \| `Number` | `undefined` | `min-width` of that same slot. |
|
|
62
|
+
| `propertySelectMaxWidth` | `String` \| `Number` | `undefined` | `max-width` of that same slot — it's the only item in its row until a property is picked (or in scan mode), so it stretches to fill it without one. |
|
|
53
63
|
| `isQuickAdvanceAutoSearch` | `Boolean` | `false` | Fire search automatically on field change (quick advance). |
|
|
54
64
|
| `defaultFilterId` | `String` \| `Number` | `""` | Pre-selects a default filter property in standard search mode (when `!isSingle && !isAdvance && !isQuickAdvance`). |
|
|
55
65
|
|
|
@@ -37,6 +37,9 @@ const form = reactive({ email: '' });
|
|
|
37
37
|
| `size` | `String` | `undefined` | Adjusts component size (`xs`, `sm`, `md`, `lg`, `xl`, `xxl`). |
|
|
38
38
|
| `rules` | `String \| Object` | `""` | VeeValidate rules. |
|
|
39
39
|
| `containerClass` | `String` | `undefined` | Class on the wrapper `<div>`. |
|
|
40
|
+
| `width` | `String \| Number` | `undefined` | Explicit width on the wrapper `<div>`. A number is treated as px (e.g. `220` -> `220px`); a string is used as-is (e.g. `"50%"`). |
|
|
41
|
+
| `minWidth` | `String \| Number` | `undefined` | `min-width` on the wrapper `<div>` (same number/string rules as `width`). |
|
|
42
|
+
| `maxWidth` | `String \| Number` | `undefined` | `max-width` on the wrapper `<div>` (same number/string rules as `width`) — caps growth inside a flex/grid parent without a fixed `width`. |
|
|
40
43
|
| `hints` | `String` | `""` | Helper text beneath the input. |
|
|
41
44
|
| `prefix` | `String` | `""` | Prefix text/icon (shortcut for `#prefix` slot). |
|
|
42
45
|
| `postfix` | `String` | `""` | Postfix text/icon. |
|
|
@@ -27,6 +27,9 @@ Searchable single/multi/tag select. Custom built-in replacement for `@vueform/mu
|
|
|
27
27
|
| `name` | `String` | `""` | VeeValidate field name. |
|
|
28
28
|
| `rules` | `String \| Object` | `""` | VeeValidate rules. |
|
|
29
29
|
| `containerClass` | `String` | `undefined` | Wrapper class. |
|
|
30
|
+
| `width` | `String \| Number` | `undefined` | Explicit width on the wrapper `<div>`. A number is treated as px (e.g. `220` -> `220px`); a string is used as-is (e.g. `"50%"`). |
|
|
31
|
+
| `minWidth` | `String \| Number` | `undefined` | `min-width` on the wrapper `<div>` (same number/string rules as `width`). |
|
|
32
|
+
| `maxWidth` | `String \| Number` | `undefined` | `max-width` on the wrapper `<div>` (same number/string rules as `width`) — caps growth inside a flex/grid parent without a fixed `width`. |
|
|
30
33
|
| `hints` | `String` | `""` | Helper text. |
|
|
31
34
|
| `multiple` | `Boolean` | `false` | Deprecated — use `mode` instead. |
|
|
32
35
|
| `searchable` | `Boolean` | `false` | Enable option search/filter. |
|
|
@@ -46,3 +46,13 @@ translateGetMsg("Error code: %{code}", { code: "404" });
|
|
|
46
46
|
| `initTranslate(gettextInstance)` | `Function` | Registers an existing gettext instance for use outside Vue components. |
|
|
47
47
|
| `translateGettext(msg, params)` | `Function` | Translates `msg` and interpolates `params`; also translates param values. |
|
|
48
48
|
| `translateGetMsg(msg, params)` | `Function` | Interpolates `params` into `msg` without translating. |
|
|
49
|
+
|
|
50
|
+
## Message-key convention
|
|
51
|
+
|
|
52
|
+
`msg` doesn't have to be a literal English sentence — it can be any string used as the `translations` lookup key (`msgid`), including a short dotted key like `"field.required"`. This is the pattern the library's own [`abVeeRules`](./ai_ref_abVeeRules.md) uses internally, and is the recommended approach for any reusable code (composables, utils) that needs translated messages: pick stable keys once, then supply the actual text per language in `translations`. A key with no matching entry for the active language is returned as-is (untranslated), so an unmapped key fails visibly instead of silently.
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
translateGettext("field.required", { fld_name: "Email" });
|
|
56
|
+
// → looks up translations[currentLang]["field.required"], interpolates %{fld_name}
|
|
57
|
+
// → falls back to the literal string "field.required" if that key isn't defined
|
|
58
|
+
```
|
package/.ai/ai_ref_abVeeRules.md
CHANGED
|
@@ -19,15 +19,57 @@ Object.keys(abAllRules).forEach(rule => {
|
|
|
19
19
|
|
|
20
20
|
Validation functions conforming to VeeValidate's custom rule signature `(value, params, field)`.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
On failure, each rule calls `translateGettext(key, params)` with a short, stable **message key** (not a literal English sentence) — the key is the `msgid` that must exist in the consuming app's `translations` object (see `abTranslate`) for that key to render translated; otherwise the raw key string is returned as-is (untranslated).
|
|
23
|
+
|
|
24
|
+
Included rules and their message key:
|
|
25
|
+
|
|
26
|
+
| Rule | Message key | Interpolation params |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `required` | `field.required` | `fld_name` |
|
|
29
|
+
| `numeric` | `field.numeric` | `fld_name` |
|
|
30
|
+
| `email` | `field.valid.email` | `fld_name` |
|
|
31
|
+
| `min` | — (native `min` rule, no translated message) | — |
|
|
32
|
+
| `min_value` | `field.min.value` | `fld_name`, `value` (the configured min) |
|
|
33
|
+
| `max` | — (native `max` rule, no translated message) | — |
|
|
34
|
+
| `max_value` | `field.max.value` | `fld_name`, `value` (the configured max) |
|
|
35
|
+
| `confirmed` | `field.confirm.password` | `fld_name` |
|
|
36
|
+
| `url` | `field.valid.url` | `fld_name` |
|
|
37
|
+
| `isUnique` | Custom stub for async uniqueness check (currently always passes). |
|
|
38
|
+
| `isValid` | Custom stub for async validity check; on the `'custom'` param path with too-short input, uses `field.valid.length` (`fld_name`). |
|
|
39
|
+
|
|
40
|
+
## Adding/overriding these messages in a consuming app
|
|
41
|
+
|
|
42
|
+
These keys are **not translated out of the box** — they resolve to the bare key unless the app's `abCreateGettext({ translations })` config defines them for the active language. Add one entry per key, per language, with the interpolation params above as `%{param}` placeholders:
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
import { abCreateGettext } from "@vue3-appsbd-ui";
|
|
46
|
+
|
|
47
|
+
const gettext = abCreateGettext({
|
|
48
|
+
availableLanguages: { bn_BD: "Bengali Bangladesh", en_EN: "English" },
|
|
49
|
+
defaultLanguage: "bn_BD",
|
|
50
|
+
translations: {
|
|
51
|
+
bn_BD: {
|
|
52
|
+
"field.required": "%{fld_name} প্রয়োজনীয়",
|
|
53
|
+
"field.valid.email": "%{fld_name} সঠিক ইমেইল নয়",
|
|
54
|
+
"field.numeric": "%{fld_name} সংখ্যা হতে হবে",
|
|
55
|
+
"field.min.value": "%{fld_name} অবশ্যই %{value} এর বেশি হতে হবে",
|
|
56
|
+
"field.max.value": "%{fld_name} অবশ্যই %{value} এর কম হতে হবে",
|
|
57
|
+
"field.confirm.password": "%{fld_name} পাসওয়ার্ড এর সাথে মিলছে না",
|
|
58
|
+
"field.valid.url": "%{fld_name} সঠিক ইউআরএল নয়",
|
|
59
|
+
"field.valid.length": "%{fld_name} এর দৈর্ঘ্য সঠিক নয়, দয়া করে এটি পরীক্ষা করুন",
|
|
60
|
+
},
|
|
61
|
+
en_EN: {
|
|
62
|
+
"field.required": "%{fld_name} required",
|
|
63
|
+
"field.valid.email": "%{fld_name} is not a valid email",
|
|
64
|
+
"field.numeric": "%{fld_name} must be a number",
|
|
65
|
+
"field.min.value": "%{fld_name} must be greater than %{value}",
|
|
66
|
+
"field.max.value": "%{fld_name} must be less than %{value}",
|
|
67
|
+
"field.confirm.password": "%{fld_name} password does not match",
|
|
68
|
+
"field.valid.url": "%{fld_name} is not a valid url",
|
|
69
|
+
"field.valid.length": "%{fld_name} length is not valid, please check it",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Only override the keys actually needed — an omitted key just falls back to being displayed as the bare key string.
|
|
@@ -12,6 +12,29 @@
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
## [Unreleased]
|
|
16
|
+
|
|
17
|
+
### ⚠️ Action Required — Breaking
|
|
18
|
+
|
|
19
|
+
- **`AbFilterPanel`'s standard-search and advance-search field layouts switched from a Bootstrap `.row`/`.col-*` grid to plain flex; `advanceContainerClass` default changed from `"col-6"` to `""`.**
|
|
20
|
+
- Find: `<AbFilterPanel ...>` usages in either default (standard) mode or `is-advance`/`isAdvance` mode that relied on the Bootstrap grid for field widths — either the default 2-columns-per-row layout, or an explicit `advance-container-class`/`advanceContainerClass` Bootstrap grid class (e.g. `"col-12 col-sm-6"`).
|
|
21
|
+
- Replace: nothing required to keep working — fields now lay out via flex (`flex: 1 1 240px`, wraps automatically), which also fixes long field labels getting clipped. A Bootstrap grid class passed to `advance-container-class` no longer has a `.row` ancestor to size against and should be replaced with either a plain width class/CSS, or the new `width` prop on the individual field component (`AbInputField`/`AbMultiSelect`/`AbDateTimePicker`) inside `filterOptions`.
|
|
22
|
+
|
|
23
|
+
### ℹ️ Also shipped (no action needed)
|
|
24
|
+
|
|
25
|
+
- `AbFilterPanel`'s `.apbd-filter-chip-group` (quick-advance multi-select popover trigger) height fixed to match input-field heights at every size (`xs`…`xxl`), and no longer changes height (grows or shrinks) once a tag is selected — a `min-height` per size acts as a floor while still allowing the box to grow when tags wrap onto a second line.
|
|
26
|
+
- New `width`, `minWidth`, `maxWidth` props (`String | Number`) on `AbInputField`, `AbMultiSelect`, `AbDateTimePicker` for sizing a single field directly; `AbFilterPanel` forwards a `width`/`minWidth`/`maxWidth` key from any `filterOptions` entry to that field's props and its flex-item wrapper.
|
|
27
|
+
- New `AbFilterPanel` `propertySelectWidth`/`propertySelectMinWidth`/`propertySelectMaxWidth` props for the standard-mode property-selector/scan-field slot, which isn't a `filterOptions` entry so the field-level keys above can't reach it.
|
|
28
|
+
|
|
29
|
+
## [1.0.17] - 2026-08-30
|
|
30
|
+
|
|
31
|
+
### ⚠️ Action Required — Breaking
|
|
32
|
+
|
|
33
|
+
- **`abVeeRules` translation message keys renamed from literal English sentences to short dotted keys.**
|
|
34
|
+
- Find: any entry in a `translations[<lang>]` object (passed to `abCreateGettext`) keyed by one of the old literal sentences — `"%{fld_name} is required"`, `"%{fld_name} should be numeric"`, `"%{fld_name} not a valid email address"`, `"%{fld_name} should be more than " + <value>` (min), `"%{fld_name} should be less than " + <value>` (max), `"%{fld_name} does not match with its password"`, `"%{fld_name} is invalid"` (url), `"%{fld_name} length is not valid, please check it"`.
|
|
35
|
+
- Replace: rename the key to, respectively, `"field.required"`, `"field.numeric"`, `"field.valid.email"`, `"field.min.value"`, `"field.max.value"`, `"field.confirm.password"`, `"field.valid.url"`, `"field.valid.length"`. For `field.min.value`/`field.max.value`, the value is now a separate `%{value}` interpolation param instead of being concatenated into the key/message — the value text should include `%{value}` where the limit belongs (e.g. `"%{fld_name} should be more than %{value}"`), not a hardcoded number.
|
|
36
|
+
- See [`.ai/ai_ref_abVeeRules.md`](./ai_ref_abVeeRules.md) for the full key list and a working example.
|
|
37
|
+
|
|
15
38
|
## [1.0.15] - 2026-08-24
|
|
16
39
|
|
|
17
40
|
### ⚠️ Action Required — Breaking
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
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.17]
|
|
6
|
+
|
|
7
|
+
- **Fixed**: `AbFilterPanel`'s `isBuilderFilter` popup editor was too narrow (`max-width: 320px`, no `width`) for longer values like a `"dr"` (date range) field's `"01/09/2026 - 15/09/2026"`-style text, which got clipped inside its input. Raising just `max-width` didn't help on its own — `AbPopover`'s content box is `position: absolute; width: auto`, which sizes to shrink-to-fit, and a shrink-to-fit box ignores a percentage-width child (`AbInputField`'s `.form-control` is `width: 100%`) when computing that fit, so the box never actually grew to use the extra ceiling. Giving it an explicit `width` fixed that, but the first pass (`340px`) was tuned tight enough against one specific date pair that it broke again on a different one — Bengali numeral glyphs (০-৯) aren't uniform-width (e.g. "৪"/"৬" render wider than "১"), so a range using wider digits needed more room than the one used to size it. Now `width: 400px` (`min-width: 280px` / `max-width: 440px` as clamps) with real margin instead of a pixel-exact fit; the popover's own default 400px cap is also raised to 480px so it isn't clipped from outside.
|
|
8
|
+
- **Fixed**: `AbFilterPanel`'s `"tr"` (text range) field's Min/arrow/Max row (`.range-input-panel`, shared by standard, advance, and the new `isBuilderFilter` mode) was built from raw `<div class="input-group">` + `<input class="form-control">` markup instead of `AbInputField`, so it never scaled with the panel's `size` prop — the label/input join used a hardcoded `input-group-sm`, and a copy-paste bug hardcoded the **Max** input to `form-control-sm` specifically (while Min correctly used the dynamic size) — so Min and Max could literally render at two different heights. The row also had no flex layout CSS at all: each `.form-control`'s default `width: 100%` forced Min/Max onto separate stacked lines instead of sitting side by side, and the separator `<svg>` had no explicit size (rendering at the browser's 300×150px SVG default) since the `w-4`/`h-4` classes on it aren't real classes in this project (Bootstrap has no such utilities). Now built from two `AbInputField`s (the first carrying the field's name as its `prefix`, matching every other field type) in a proper flex row with `1em` icon sizing — sizes correctly with the panel's `size` prop like every other field. This had never been visually exercised before — no existing playground demo used a `"tr"` field until `isBuilderFilter`'s "Revenue" example.
|
|
9
|
+
- **Added**: `AbFilterPanel` `isBuilderFilter` prop — a Shopify-style filter builder mode. No field is shown until the user clicks a `+` button; that opens a popover which first lists every not-yet-applied `filterOptions` entry, then (once one is picked) swaps to a value editor matching that field's `type` plus Cancel/Apply Filter buttons. Apply adds it as a removable chip (e.g. "Email contains gmail") and immediately fires `searchFilter`; there's no global Search button in this mode, only Reset (clears every applied chip/value at once). A field's `operators` stays fixed by its schema entry, same as other modes — this mode doesn't add an is/is-not/contains operator picker. The applied-filter chip's height/padding scales with the panel's `size` prop, same as its `+`/Reset buttons.
|
|
10
|
+
- **Fixed**: `AbPopover`'s outside-click-to-close listened on `click`, which races with anything inside its content that reacts on `mousedown` and removes/moves itself before that later `click` fires — e.g. `AbMultiSelect` selecting a single option closes its own dropdown on `mousedown`, so by the time `click` arrived its real target was already whatever sat behind the now-collapsed dropdown, closing the outer popover too (hit when nesting an `AbMultiSelect` with `append-to-body="false"` inside an `AbPopover`, as `AbFilterPanel`'s new `isBuilderFilter` mode does for its dropdown-type fields). Outside detection now runs on `mousedown`, before such handlers can react, and reads `event.composedPath()` instead of `event.target` + `.contains()` so it's also correct when a same-tick handler swaps out the clicked element.
|
|
11
|
+
- **Fixed**: `AbPopover` closed immediately (with no selection) when clicking inside a *nested* `AbPopover` in its content — e.g. an `AbDateTimePicker` (which opens its calendar through its own `AbPopover`) placed inside `AbFilterPanel`'s `isBuilderFilter` editor: any date click, or even changing the calendar's month, closed the outer popover before the inner one could react, because the inner popover's floating content always renders through its own `<Teleport to="body">` and so never sits inside the outer popover's own floating element in the DOM. `AbPopover` now tracks every mounted popover (via the existing `popoverManager`) and treats a click as "inside" when it lands on another popover's floating content whose trigger is nested inside its own — so a calendar (or any `AbPopover`-based control) opened from within another popover's content no longer closes its parent.
|
|
12
|
+
- **Fixed**: `AbFilterPanel`'s `.apbd-filter-chip-group` (the quick-advance multi-select popover trigger) had an inconsistent height across sizes — only `xs`/`sm` had explicit padding, `md`/`lg`/`xl`/`xxl` fell through to browser-default padding/line-height. Every size (`xs` `sm` `md` `lg` `xl` `xxl`) now computes to the same height as `AbInputField`/`AbMultiSelect` at that size (28/36/40/44/48/60px) through the shared padding + line-height tokens — never a hardcoded `height` — and the font-size is now constant across all sizes instead of shrinking at `xs`/`sm`. Border-radius and background also switched from an undefined CSS variable (silently falling back to a hardcoded value) to the real `--#{$prefix}border-radius*`/`--#{$prefix}apbd-input-bg-color` tokens, matching input fields in dark mode too.
|
|
13
|
+
- **Fixed**: `AbFilterPanel`'s `.apbd-filter-chip-group` didn't keep a consistent height once a tag was selected — the selected-tag pill (`.apbd-filter-tag`) inheriting the container's line-height plus its own border + padding first made the box grow taller than its siblings; capping the tag to `line-height: 1` then let the box shrink *shorter* than its siblings instead, since the container has no explicit `height` and was sizing itself off whatever child happened to be present. Each size class now also carries a `min-height` matching that size's target (28/36/40/44/48/60px for `xs`…`xxl`) as a floor — the box can still grow taller than that when tags wrap onto a second line, it just never renders shorter than a same-size input field regardless of what's inside it.
|
|
14
|
+
- **Changed** (breaking): `AbFilterPanel`'s standard-search (default mode) and advance-search (`isAdvance` mode) field layouts — both used Bootstrap's `.row`/`.col-*` grid (nested two levels deep in standard mode); a `.col-*` class doesn't do anything meaningful without a `.row` ancestor, and `.row`'s negative margins could overflow the outer flex wrapper and clip long field labels. Both are now a plain `d-flex flex-wrap gap-2` layout with no grid columns at all — each field is a flex item (`flex: 1 1 240px`, class `apbd-advance-filter-item`) that grows/shrinks and wraps on its own; `advanceContainerClass` default changed from `"col-6"` to `""` since a grid column class no longer does anything useful here. To fix a specific field's width instead, use that field's own new `width` prop.
|
|
15
|
+
- **Added**: `width`, `minWidth`, and `maxWidth` props (`String | Number`) on `AbInputField`, `AbMultiSelect`, and `AbDateTimePicker` — set an explicit width / `min-width` / `max-width` on the field's outer container (a number is treated as px, e.g. `width="220"` or `max-width="50%"`). `AbFilterPanel` forwards all three too: give any entry in `filterOptions` a `width`/`minWidth`/`maxWidth` key and it's passed straight to that field's own same-named prop *and* used to size that field's flex-item wrapper directly — the way to fix (or just bound) a specific field's size now that its layouts have no Bootstrap grid column to size against. Without one, a field left alone on the last row (nothing else to share the row with) stretches to fill it, since each field is a `flex: 1 1 240px` item.
|
|
16
|
+
- **Added**: `AbFilterPanel` `propertySelectWidth`/`propertySelectMinWidth`/`propertySelectMaxWidth` props (`String | Number`) — the standard-mode property selector (and the scan field it swaps for) isn't one of the `filterOptions` entries, so the `width`/`minWidth`/`maxWidth` field keys above don't reach it; it's also the sole item in its row until a property is picked (or whenever `showScanFld` is on), so it stretches to fill the row the same way any unsized flex field does. These three props size that slot directly.
|
|
17
|
+
- **Changed**: `abVeeRules`' built-in validation messages now translate through short, stable message keys (e.g. `field.required`, `field.numeric`, `field.valid.email`, `field.min.value`, `field.max.value`, `field.confirm.password`, `field.valid.url`, `field.valid.length`) instead of literal English sentences — `min_value`/`max_value` also now pass their configured limit as an interpolated `value` param instead of concatenating it directly into the message-key string (which previously produced a different, untranslatable key per limit value). Breaking change for any consumer whose `translations` object overrode these messages by their old literal-sentence key (e.g. `"%{fld_name} is required"`) — those entries must be renamed to the new keys, see `.ai/ai_ref_abVeeRules.md`.
|
|
18
|
+
|
|
5
19
|
## [1.0.16] - 2026-08-27
|
|
6
20
|
|
|
7
21
|
- **Fixed**: WordPress theme conflict — `AbFormCheck`'s enhanced (`.apbd-radio-input-container`) checkbox/radio inputs now reset `margin: 0` to counter WordPress's default form-control margin. (Previously targeted `.is-flat-check`, which only covers the `card-flat-check` variant and missed the other enhanced variants.)
|