@bridge-ui/vue 0.6.0 → 0.8.0

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.
Files changed (129) hide show
  1. package/ai/skills/bridge-ui-forms/SKILL.md +1 -1
  2. package/dist/Adapters/I18n/useI18nAdapter.d.ts +1 -1
  3. package/dist/Adapters/I18n/useI18nAdapter.js +4 -1
  4. package/dist/Components/Accordion/Accordion.vue_vue_type_script_setup_true_lang.js +1 -1
  5. package/dist/Components/Accordion/accordion.types.d.ts +2 -2
  6. package/dist/Components/Alert/Alert.vue_vue_type_script_setup_true_lang.js +13 -13
  7. package/dist/Components/Alert/alert.types.d.ts +7 -4
  8. package/dist/Components/Alert/composables/useAlert.d.ts +1 -0
  9. package/dist/Components/Alert/composables/useAlert.js +60 -57
  10. package/dist/Components/Autocomplete/Autocomplete.vue.d.ts +1 -1
  11. package/dist/Components/Autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js +1 -0
  12. package/dist/Components/Autocomplete/composables/useAutocomplete.d.ts +5 -3
  13. package/dist/Components/BaseField/BaseField.vue_vue_type_script_setup_true_lang.js +33 -28
  14. package/dist/Components/BaseField/BaseFieldCorner.js +5 -0
  15. package/dist/Components/BaseField/BaseFieldCorner.vue.d.ts +17 -0
  16. package/dist/Components/BaseField/BaseFieldCorner.vue_vue_type_script_setup_true_lang.js +17 -0
  17. package/dist/Components/BaseField/baseField.types.d.ts +19 -6
  18. package/dist/Components/BaseField/composables/useBaseField.d.ts +7 -3
  19. package/dist/Components/BaseField/composables/useBaseField.js +71 -68
  20. package/dist/Components/Button/Button.vue_vue_type_script_setup_true_lang.js +24 -25
  21. package/dist/Components/Button/composables/useButton.d.ts +3 -1
  22. package/dist/Components/Button/composables/useButton.js +46 -40
  23. package/dist/Components/Calendar/composables/useCalendar.d.ts +1 -1
  24. package/dist/Components/CalendarDate/composables/useCalendarDate.d.ts +1 -1
  25. package/dist/Components/CalendarMonth/composables/useCalendarMonth.d.ts +1 -1
  26. package/dist/Components/CalendarRange/composables/useCalendarRange.d.ts +1 -1
  27. package/dist/Components/CalendarYear/composables/useCalendarYear.d.ts +1 -1
  28. package/dist/Components/ColorField/ColorField.vue.d.ts +1 -1
  29. package/dist/Components/ColorField/ColorField.vue_vue_type_script_setup_true_lang.js +1 -0
  30. package/dist/Components/ColorField/composables/useColorField.d.ts +6 -4
  31. package/dist/Components/ColorPicker/composables/useColorPicker.d.ts +1 -1
  32. package/dist/Components/DataTable/DataTable.vue_vue_type_script_setup_true_lang.js +154 -131
  33. package/dist/Components/DataTable/DataTablePagination.js +5 -0
  34. package/dist/Components/DataTable/DataTablePagination.vue.d.ts +24 -0
  35. package/dist/Components/DataTable/DataTablePagination.vue_vue_type_script_setup_true_lang.js +40 -0
  36. package/dist/Components/DataTable/composables/useDataTable.d.ts +9 -4
  37. package/dist/Components/DataTable/composables/useDataTable.js +299 -280
  38. package/dist/Components/DataTable/composables/useDataTablePagination.d.ts +69 -0
  39. package/dist/Components/DataTable/composables/useDataTablePagination.js +130 -0
  40. package/dist/Components/DataTable/dataTable.types.d.ts +27 -12
  41. package/dist/Components/DataTable/dataTablePagination.types.d.ts +169 -0
  42. package/dist/Components/DataTable/index.d.ts +2 -1
  43. package/dist/Components/DateField/DateField.vue_vue_type_script_setup_true_lang.js +1 -0
  44. package/dist/Components/DateField/composables/useDateField.d.ts +6 -4
  45. package/dist/Components/DatePicker/composables/useDatePicker.d.ts +1 -1
  46. package/dist/Components/DateRangeField/DateRangeField.vue_vue_type_script_setup_true_lang.js +1 -0
  47. package/dist/Components/DateRangeField/composables/useDateRangeField.d.ts +6 -4
  48. package/dist/Components/DateRangePicker/composables/useDateRangePicker.d.ts +1 -1
  49. package/dist/Components/DateTimeField/DateTimeField.vue_vue_type_script_setup_true_lang.js +1 -0
  50. package/dist/Components/DateTimeField/composables/useDateTimeField.d.ts +6 -4
  51. package/dist/Components/DateTimePicker/composables/useDateTimePicker.d.ts +1 -1
  52. package/dist/Components/DateTimeRangeField/DateTimeRangeField.vue_vue_type_script_setup_true_lang.js +1 -0
  53. package/dist/Components/DateTimeRangeField/composables/useDateTimeRangeField.d.ts +6 -4
  54. package/dist/Components/DateTimeRangePicker/composables/useDateTimeRangePicker.d.ts +1 -1
  55. package/dist/Components/FormControl/composables/useFormControl.d.ts +3 -1
  56. package/dist/Components/FormControl/composables/useFormControl.js +39 -38
  57. package/dist/Components/FormField/FilledFormField.vue.d.ts +7 -7
  58. package/dist/Components/FormField/FilledFormField.vue_vue_type_script_setup_true_lang.js +32 -27
  59. package/dist/Components/FormField/FormFieldCorner.js +5 -0
  60. package/dist/Components/FormField/FormFieldCorner.vue.d.ts +17 -0
  61. package/dist/Components/FormField/FormFieldCorner.vue_vue_type_script_setup_true_lang.js +17 -0
  62. package/dist/Components/FormField/NotchedFormField.vue.d.ts +7 -7
  63. package/dist/Components/FormField/NotchedFormField.vue_vue_type_script_setup_true_lang.js +14 -9
  64. package/dist/Components/FormField/OutlinedFormField.vue.d.ts +7 -7
  65. package/dist/Components/FormField/OutlinedFormField.vue_vue_type_script_setup_true_lang.js +32 -27
  66. package/dist/Components/FormField/StackedFormField.vue.d.ts +6 -6
  67. package/dist/Components/FormField/StackedFormField.vue_vue_type_script_setup_true_lang.js +14 -9
  68. package/dist/Components/FormField/UnderlinedFormField.vue.d.ts +7 -7
  69. package/dist/Components/FormField/UnderlinedFormField.vue_vue_type_script_setup_true_lang.js +32 -27
  70. package/dist/Components/FormField/composables/useFormField.d.ts +8 -4
  71. package/dist/Components/FormField/composables/useFormField.js +153 -143
  72. package/dist/Components/FormField/formField.types.d.ts +18 -6
  73. package/dist/Components/Listbox/Listbox.vue.d.ts +1 -1
  74. package/dist/Components/NumberField/NumberField.vue_vue_type_script_setup_true_lang.js +1 -0
  75. package/dist/Components/NumberField/composables/useNumberField.d.ts +5 -3
  76. package/dist/Components/OtpField/OtpField.vue.d.ts +1 -8
  77. package/dist/Components/OtpField/OtpField.vue_vue_type_script_setup_true_lang.js +7 -6
  78. package/dist/Components/OtpField/composables/useOtpField.d.ts +4 -2
  79. package/dist/Components/Pagination/Pagination.vue_vue_type_script_setup_true_lang.js +6 -6
  80. package/dist/Components/Pagination/composables/usePagination.d.ts +4 -2
  81. package/dist/Components/Pagination/composables/usePagination.js +125 -127
  82. package/dist/Components/Pagination/pagination.types.d.ts +5 -5
  83. package/dist/Components/PasswordField/PasswordField.vue_vue_type_script_setup_true_lang.js +1 -0
  84. package/dist/Components/PasswordField/composables/usePasswordField.d.ts +5 -3
  85. package/dist/Components/Select/Select.vue_vue_type_script_setup_true_lang.js +1 -0
  86. package/dist/Components/Select/composables/useSelect.d.ts +5 -3
  87. package/dist/Components/Sidebar/composables/useSidebarList.js +1 -1
  88. package/dist/Components/Sidebar/composables/useSidebarShell.js +1 -1
  89. package/dist/Components/Slider/Slider.vue_vue_type_script_setup_true_lang.js +1 -0
  90. package/dist/Components/Slider/composables/useSlider.d.ts +5 -3
  91. package/dist/Components/Tabs/Tabs.vue_vue_type_script_setup_true_lang.js +2 -2
  92. package/dist/Components/Tabs/composables/useTabs.js +16 -10
  93. package/dist/Components/Tabs/tabs.types.d.ts +3 -3
  94. package/dist/Components/TextField/TextField.vue_vue_type_script_setup_true_lang.js +1 -0
  95. package/dist/Components/TextField/composables/useTextField.d.ts +5 -3
  96. package/dist/Components/Textarea/Textarea.vue_vue_type_script_setup_true_lang.js +1 -0
  97. package/dist/Components/Textarea/composables/useTextarea.d.ts +5 -3
  98. package/dist/Components/TimeField/TimeField.vue_vue_type_script_setup_true_lang.js +1 -0
  99. package/dist/Components/TimeField/composables/useTimeField.d.ts +6 -4
  100. package/dist/Components/TimePanel/composables/useTimePanel.d.ts +1 -1
  101. package/dist/Components/TimePicker/composables/useTimePicker.d.ts +1 -1
  102. package/dist/Components/TimeRangeField/TimeRangeField.vue_vue_type_script_setup_true_lang.js +1 -0
  103. package/dist/Components/TimeRangeField/composables/useTimeRangeField.d.ts +6 -4
  104. package/dist/Components/TimeRangePicker/composables/useTimeRangePicker.d.ts +1 -1
  105. package/dist/Components/Tooltip/composables/useTooltip.d.ts +1 -1
  106. package/dist/Utils/index.d.ts +11 -2
  107. package/dist/Utils/index.js +31 -27
  108. package/dist/augments.d.ts +8 -8
  109. package/dist/index.d.ts +1 -1
  110. package/dist/index.js +4 -4
  111. package/docs/components/Accordion.md +1 -1
  112. package/docs/components/Alert.md +4 -2
  113. package/docs/components/BaseField.md +19 -18
  114. package/docs/components/BridgeUIProvider.md +14 -7
  115. package/docs/components/DataTable.md +5 -11
  116. package/docs/components/FormControl.md +1 -1
  117. package/docs/components/FormField.md +28 -27
  118. package/docs/components/I18n.md +65 -24
  119. package/docs/components/Pagination.md +5 -3
  120. package/docs/components/Table.md +2 -2
  121. package/docs/components/Tabs.md +24 -6
  122. package/docs/examples/i18n-dictionary.ts +28 -10
  123. package/docs/examples/i18n-vue-i18n.ts +7 -6
  124. package/docs/examples/icon-fontawesome.ts +4 -0
  125. package/docs/examples/icon-heroicons.ts +5 -1
  126. package/docs/examples/icon-lucide.ts +4 -0
  127. package/docs/examples/icon-phosphor.ts +4 -0
  128. package/docs/examples/icon-tabler.ts +4 -0
  129. package/package.json +2 -2
@@ -81,7 +81,7 @@ app.use(
81
81
 
82
82
  Set `global.formDefaults` to apply shared `size` / `rounded` to form controls (TextField, Select, Checkbox, Slider, OtpField, …). Does not affect Button, Progress, Modal, etc.
83
83
 
84
- Merge order: instance props → `components.{Name}.defaultProps` → `formDefaults` → library defaults.
84
+ Merge order: instance props → `components.{Name}.defaultProps` → chrome (`FormField` / `FormControl` / `BaseField` / `TimePanel`) → `formDefaults` → library defaults.
85
85
 
86
86
  Radio and Switch receive `size` only — their `rounded` stays shape-driven (`full`) unless overridden per component.
87
87
 
@@ -97,19 +97,26 @@ app.use(
97
97
  );
98
98
  ```
99
99
 
100
- ### Nested chrome tokens
100
+ ### Shared chrome
101
101
 
102
- Building blocks (`FormField`, `FormControl`, `BaseField`) are not registry keys. Theme chrome under the public parent. Dropdown tokens live on `components.Listbox`:
102
+ `FormField`, `FormControl`, `BaseField`, and `TimePanel` are registry keys. Set them once to theme a family; a public entry still overrides `defaultProps`. Chrome tokens live on the shared key (`components.FormField.tokens`, `components.BaseField.tokens`). Dropdown tokens live on `components.Listbox`.
103
103
 
104
104
  ```ts
105
105
  app.use(
106
106
  createBridgeUI({
107
107
  components: {
108
- Slider: {
108
+ FormField: {
109
+ defaultProps: {
110
+ variant: "filled",
111
+ color: "secondary",
112
+ },
113
+ },
114
+ TextField: {
115
+ defaultProps: { variant: "outline" },
116
+ },
117
+ BaseField: {
109
118
  tokens: {
110
- baseField: {
111
- size: { md: { text: "text-base", group: "gap-3" } },
112
- },
119
+ size: { md: { text: "text-base", group: "gap-3" } },
113
120
  },
114
121
  },
115
122
  Checkbox: {
@@ -26,7 +26,7 @@ import { DataTable } from "@bridge-ui/vue/Components/DataTable";
26
26
 
27
27
  ### Variants
28
28
 
29
- DataTable chrome (`plain` / `ghost` / `bordered`). Built-in `Pagination` follows the matching variant unless the `pagination` slot overrides it:
29
+ DataTable chrome (`plain` / `ghost` / `bordered`). The built-in footer pager is first / previous / next / last and does not follow table variant:
30
30
 
31
31
  ```vue
32
32
  <DataTable :rows="users" variant="plain" :columns="columns" />
@@ -34,12 +34,6 @@ DataTable chrome (`plain` / `ghost` / `bordered`). Built-in `Pagination` follows
34
34
  <DataTable :rows="users" variant="bordered" :columns="columns" />
35
35
  ```
36
36
 
37
- | DataTable `variant` | Pagination `variant` |
38
- | ------------------- | -------------------- |
39
- | `plain` | `text` |
40
- | `ghost` | `ghost` |
41
- | `bordered` | `outlined` |
42
-
43
37
  `striped` is independent of variant:
44
38
 
45
39
  ```vue
@@ -66,7 +60,7 @@ DataTable chrome (`plain` / `ghost` / `bordered`). Built-in `Pagination` follows
66
60
 
67
61
  ### Selection + pagination
68
62
 
69
- Built-in Pagination when `page` is set with `page-count` or `total-count` (server fetch stays in the app). `page` + `per-page` without those totals slices `rows` locally. `per-page` also renders a Select (`per-page-options`, default 10 / 25 / 50 / 100). `#pagination` and `#perPage` replace each control:
63
+ The chrome footer shows a selection summary when `selection` is bound, a per-page Select when `per-page` is set (`per-page-options`, default 10 / 25 / 50 / 100), and a first / previous / next / last pager when `page` is set with `page-count` or `total-count` (server fetch stays in the app). `page` + `per-page` without those totals slices `rows` locally. `#selected`, `#pagination`, and `#perPage` replace each control:
70
64
 
71
65
  ```vue
72
66
  <DataTable
@@ -98,7 +92,7 @@ Client paging slices `rows`. Server paging with a total uses `total-count` inste
98
92
  />
99
93
  ```
100
94
 
101
- Slot replaces the built-in Pagination and/or per-page Select (`#pagination` / `#perPage`; slot props match the built-ins):
95
+ Slot replaces the built-in footer controls (`#selected` / `#pagination` / `#perPage`; slot props match the built-ins):
102
96
 
103
97
  ```vue
104
98
  <DataTable :rows="users" :columns="columns" :get-row-id="(row) => row.id">
@@ -141,7 +135,7 @@ When `page` and `page-count` (or `total-count`) are set, DataTable does not sort
141
135
 
142
136
  ### Empty, loading, and footer
143
137
 
144
- Empty rows render `EmptyState` at the table `size`, with the semantic `inbox` icon and the i18n title `"No data"`. `#empty` replaces it. `loading` keeps the table visible. `loadingVariant="overlay"` (default) dims the table with a spin; `loadingVariant="bar"` dims the table and draws a progress line under the header. `#loading` replaces the indicator. `#footer` renders below the table, above pagination:
138
+ Empty rows render `EmptyState` at the table `size`, with the semantic `inbox` icon and the i18n title `"No data"`. `#empty` replaces it. `loading` keeps the table visible. `loadingVariant="overlay"` (default) dims the table with a spin; `loadingVariant="bar"` dims the table and draws a progress line under the header. `#loading` replaces the indicator. `#footer` renders below the table, above the chrome footer:
145
139
 
146
140
  ```vue
147
141
  <DataTable :rows="[]" :columns="columns" :loading="isLoading">
@@ -180,7 +174,7 @@ const columns = [
180
174
  ];
181
175
  ```
182
176
 
183
- Table-level slots stay `empty` / `expanded` / `footer` / `item.{id}` / `item` / `loading` / `pagination` / `perPage` / `search` / `toolbar` / `toolbarActions`. `#item` is a catch-all when `#item.{id}` is not set.
177
+ Table-level slots stay `empty` / `expanded` / `footer` / `item.{id}` / `item` / `loading` / `pagination` / `perPage` / `search` / `selected` / `toolbar` / `toolbarActions`. `#item` is a catch-all when `#item.{id}` is not set.
184
178
 
185
179
  ### Selection
186
180
 
@@ -1,6 +1,6 @@
1
1
  # FormControl
2
2
 
3
- > Building block for toggle-row chrome. Prefer `Checkbox`, `Radio`, and `Switch` in apps; FormControl remains exported for advanced composition. Not a registry key — theme chrome via `tokens.formControl` on the public parent (e.g. `components.Checkbox.tokens.formControl`).
3
+ > Building block for toggle-row chrome. Prefer `Checkbox`, `Radio`, and `Switch` in apps; FormControl remains exported for advanced composition. Theme shared chrome via `components.FormControl`; override per public control (`components.Checkbox`, …).
4
4
 
5
5
  Low-level form control chrome (labels, description, error) for Checkbox, Radio, and Switch.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # FormField
2
2
 
3
- > Building block for field chrome. Prefer public fields (`TextField`, `Select`, …) in apps; FormField remains exported for advanced composition. Not a `BridgeUIComponentsConfig` key theme via the public parent (`components.TextField`, `components.Select`, …).
3
+ > Building block for field chrome. Prefer public fields (`TextField`, `Select`, …) in apps; FormField remains exported for advanced composition. Theme all fields via `components.FormField`; override per public field (`components.TextField`, …).
4
4
 
5
5
  Form field chrome (label, adornments, error) used by TextField, Select, and other inputs.
6
6
 
@@ -39,32 +39,33 @@ import { FormField } from "@bridge-ui/vue";
39
39
 
40
40
  ## Props
41
41
 
42
- | Prop | Type | Default | Description |
43
- | ------------------ | ---------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
44
- | `classes` | `FormFieldClasses` | — | Classes for the field chrome and the control (includes label, container, adornments). |
45
- | `color` | `FormFieldColor` | "primary" | The color to apply to the field control. |
46
- | `controlId` | `string` | — | Associates labels and helper text with a form control. When omitted, an id is generated automatically. |
47
- | `corner` | `string` | — | Secondary label text at the inline end of the header row. |
48
- | `customProps` | `FormFieldCustomProps` | — | Extra props for internal parts (`header`, `label`, `input`, `container`, …). |
49
- | `description` | `string` | — | Helper text below the control (hidden when the field is invalid). |
50
- | `disabled` | `boolean` | `false` | Whether the control is disabled. |
51
- | `end` | `string` | — | Inline-end text inside the field (suffix), e.g. `@mail.com`. |
52
- | `endIcon` | `LucideIcon` | — | Icon at the **inline end** (physical right in `ltr`, physical left in `rtl`). |
53
- | `error` | `boolean` | `false` | When `true`, applies invalid styling on the label and hides description. |
54
- | `errorIcon` | `LucideIcon` | CircleAlert | Icon used when `showErrorIcon` is enabled and the field is invalid. |
55
- | `errorMessage` | `string` | — | Error message below the control. Shown only when set (or via `#errorMessage` slot). |
56
- | `field` | `UseFormFieldReturn` | — | Pre-composed field API from a parent composable (e.g. `useTextField`). Used by `<FormField :field="…" />`; not set on field wrappers such as TextField. |
57
- | `hideErrorMessage` | `boolean` | `false` | When `true`, does not reserve space below the control for error messages. |
58
- | `label` | `string` | — | The primary label text above the control. |
59
- | `readonly` | `boolean` | `false` | Whether the control is read-only. |
60
- | `required` | `boolean` | `false` | Shows a red asterisk on the label. |
61
- | `rounded` | `FormFieldRounded` | "md" | The roundedness of the field control. |
62
- | `showErrorIcon` | `boolean` | `true` | When `true` and the field is invalid, shows an error icon at the inline end when no `endIcon` or `end` slot is present. |
63
- | `size` | `FormFieldSize` | "md" | Typography scale for label, corner, description, and error message, and control sizing (input, container, icons). |
64
- | `slots` | `FormFieldSlots` | | Chrome slots (`label`, `description`, `errorMessage`, …) via `#slot` or prop; inline adornments use `#start` / `#end`. |
65
- | `start` | `string` | — | Inline-start text inside the field (prefix), e.g. `https://`. |
66
- | `startIcon` | `LucideIcon` | — | Icon at the **inline start** (physical left in `ltr`, physical right in `rtl`). |
67
- | `variant` | `FormFieldVariant` | "outline" | The visual variant of the field shell and control. |
42
+ | Prop | Type | Default | Description |
43
+ | ------------------------ | ---------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
44
+ | `classes` | `FormFieldClasses` | — | Classes for the field chrome and the control (includes label, container, adornments). |
45
+ | `color` | `FormFieldColor` | "primary" | The color to apply to the field control. |
46
+ | `controlId` | `string` | — | Associates labels and helper text with a form control. When omitted, an id is generated automatically. |
47
+ | `corner` | `string` | — | Secondary label text at the inline end of the header row. |
48
+ | `customProps` | `FormFieldCustomProps` | — | Extra props for internal parts (`header`, `label`, `input`, `container`, …). |
49
+ | `description` | `string` | — | Helper text below the control. Hidden when `error` and an error message are set, unless `showDescriptionOnError`. |
50
+ | `disabled` | `boolean` | `false` | Whether the control is disabled. |
51
+ | `end` | `string` | — | Inline-end text inside the field (suffix), e.g. `@mail.com`. |
52
+ | `endIcon` | `LucideIcon` | — | Icon at the **inline end** (physical right in `ltr`, physical left in `rtl`). |
53
+ | `error` | `boolean` | `false` | When `true`, applies invalid styling on the label. Hides description when an error message is shown, unless `showDescriptionOnError`. |
54
+ | `errorIcon` | `LucideIcon` | CircleAlert | Icon used when `showErrorIcon` is enabled and the field is invalid. |
55
+ | `errorMessage` | `string` | — | Error message below the control. Shown only when set (or via `#errorMessage` slot). |
56
+ | `field` | `UseFormFieldReturn` | — | Pre-composed field API from a parent composable (e.g. `useTextField`). Used by `<FormField :field="…" />`; not set on field wrappers such as TextField. |
57
+ | `hideErrorMessage` | `boolean` | `false` | When `true`, does not reserve the error row. That row is also omitted while a description is shown. |
58
+ | `label` | `string` | — | The primary label text above the control. |
59
+ | `readonly` | `boolean` | `false` | Whether the control is read-only. |
60
+ | `required` | `boolean` | `false` | Shows a red asterisk on the label. |
61
+ | `rounded` | `FormFieldRounded` | "md" | The roundedness of the field control. |
62
+ | `showDescriptionOnError` | `boolean` | `false` | When `true`, keeps the description visible while the field is invalid. |
63
+ | `showErrorIcon` | `boolean` | `true` | When `true` and the field is invalid, shows an error icon at the inline end when no `endIcon` or `end` slot is present. |
64
+ | `size` | `FormFieldSize` | "md" | Typography scale for label, corner, description, and error message, and control sizing (input, container, icons). |
65
+ | `slots` | `FormFieldSlots` | — | Chrome slots (`label`, `description`, `errorMessage`, ) via `#slot` or prop; inline adornments use `#start` / `#end`. |
66
+ | `start` | `string` | — | Inline-start text inside the field (prefix), e.g. `https://`. |
67
+ | `startIcon` | `LucideIcon` | | Icon at the **inline start** (physical left in `ltr`, physical right in `rtl`). |
68
+ | `variant` | `FormFieldVariant` | "outline" | The visual variant of the field shell and control. |
68
69
 
69
70
  ## Related components
70
71
 
@@ -1,6 +1,6 @@
1
1
  # i18n
2
2
 
3
- Bridge chrome strings (aria-labels, empty/loading copy) resolve through an optional i18n adapter on `BridgeUIProvider` / `createBridgeUI` (`global.i18n`). Without an adapter, the English source string is returned as-is.
3
+ Bridge chrome strings (aria-labels, empty/loading copy) resolve through an optional i18n adapter on `BridgeUIProvider` / `createBridgeUI` (`global.i18n`). Without an adapter, the English source string is returned, with `{{name}}` replaced from `params`, and `|` plural forms when `count` is set.
4
4
 
5
5
  Lookup is **gettext-style**: the source English text is the key. Multi-locale
6
6
  adapters can keep the active locale internally via optional `setLocale`.
@@ -11,10 +11,14 @@ const resolveMessage = useResolveMessage();
11
11
  resolveMessage("Hide password");
12
12
  ```
13
13
 
14
- `useResolveMessage` reads the active adapter from context. **Interpolation and
15
- pluralization are the adapter’s job** (vue-i18n, i18next, or a custom `t`).
16
- Bridge `setLocale` updates `global.locale` and calls optional `adapter.setLocale`
17
- persistence (localStorage, backend) stays in the app.
14
+ `useResolveMessage` reads the active adapter from context. **Pluralization
15
+ uses the `count` argument** on `t(message, count, params)`: vue-i18n / i18next
16
+ handle it in `t`; dictionary adapters call `selectPluralMessage` on `|` forms
17
+ (`one | other`). Without an adapter, `resolveMessage` still replaces `{{name}}`
18
+ and picks `|` forms when `count` is set. Adapters that used `t(message, params)`
19
+ should move interpolation vars to the third argument. Bridge `setLocale`
20
+ updates `global.locale` and calls optional `adapter.setLocale` — persistence
21
+ (localStorage, backend) stays in the app.
18
22
 
19
23
  Implement `I18nAdapter` as a plain object — Bridge only defines the interface.
20
24
 
@@ -44,8 +48,9 @@ const resolveMessage = useResolveMessage();
44
48
 
45
49
  ### Dictionary adapter
46
50
 
47
- Locale-keyed source→string map (no replace/plural). Optional `setLocale`
48
- updates the active locale used by `t`.
51
+ Locale-keyed source→string map with `{{name}}` replace. Plural values use
52
+ `one | other` (or `zero | one | other`). Optional `setLocale` updates the
53
+ active locale used by `t`.
49
54
 
50
55
  ```ts
51
56
  import { createBridgeUI } from "@bridge-ui/vue";
@@ -61,14 +66,20 @@ const bridge = createBridgeUI({
61
66
  ### Custom adapter
62
67
 
63
68
  ```ts
64
- import { get } from "es-toolkit/compat";
65
- import type { I18nAdapter } from "@bridge-ui/vue";
69
+ import { get, isNil } from "es-toolkit/compat";
70
+ import {
71
+ interpolateMessage,
72
+ selectPluralMessage,
73
+ type I18nAdapter,
74
+ } from "@bridge-ui/vue";
66
75
 
67
76
  const messages: Record<string, Record<string, string>> = {
68
77
  "pt-BR": {
69
78
  Close: "Fechar",
70
79
  "Hide password": "Ocultar senha",
71
80
  "Clear selection": "Limpar seleção",
81
+ "{{selected}} of {{total}} row(s) selected.":
82
+ "{{selected}} de {{total}} linha selecionada. | {{selected}} de {{total}} linhas selecionadas.",
72
83
  },
73
84
  };
74
85
 
@@ -78,8 +89,13 @@ const i18n: I18nAdapter = {
78
89
  setLocale(next) {
79
90
  locale = next;
80
91
  },
81
- t(message) {
82
- return get(messages, [locale, message], message);
92
+ t(message, count, params) {
93
+ const translated = get(messages, [locale, message], message);
94
+ const template = isNil(count)
95
+ ? translated
96
+ : selectPluralMessage(translated, count);
97
+
98
+ return interpolateMessage(template, params);
83
99
  },
84
100
  };
85
101
  ```
@@ -94,7 +110,7 @@ const vueI18n = createI18n({ legacy: false, locale: "en-US", messages: {} });
94
110
  const i18n = createVueI18nAdapter(vueI18n.global);
95
111
 
96
112
  const resolveMessage = useResolveMessage();
97
- resolveMessage("{count} item", { count: 3 });
113
+ resolveMessage("{count} item", 3);
98
114
  // → vue-i18n handles interpolation / plural rules
99
115
 
100
116
  setLocale("pt-BR"); // Bridge locale + i18n.locale via adapter.setLocale
@@ -104,22 +120,47 @@ Other ready examples:
104
120
 
105
121
  | File | Library | Replace / plural |
106
122
  | -------------------- | -------------------- | ---------------- |
107
- | `i18n-dictionary.ts` | In-memory dictionary | No (static map) |
123
+ | `i18n-dictionary.ts` | In-memory dictionary | Yes (`\|` forms) |
108
124
  | `i18n-vue-i18n.ts` | vue-i18n | Yes (via lib) |
109
125
 
110
126
  ## Chrome strings
111
127
 
112
- | Source (key) |
113
- | ----------------- |
114
- | `Close` |
115
- | `Loading...` |
116
- | `No options` |
117
- | `Show password` |
118
- | `Hide password` |
119
- | `Clear selection` |
120
- | `Increment value` |
121
- | `Decrement value` |
128
+ | Source (key) |
129
+ | -------------------------------------------- |
130
+ | `OK` |
131
+ | `Next` |
132
+ | `Close` |
133
+ | `Reset` |
134
+ | `Search` |
135
+ | `Columns` |
136
+ | `Loading` |
137
+ | `No data` |
138
+ | `Previous` |
139
+ | `Last page` |
140
+ | `Expand row` |
141
+ | `First page` |
142
+ | `Loading...` |
143
+ | `No options` |
144
+ | `Pagination` |
145
+ | `Select row` |
146
+ | `Filter column` |
147
+ | `Hide password` |
148
+ | `Rows per page` |
149
+ | `Show password` |
150
+ | `Cancel sorting` |
151
+ | `Sort ascending` |
152
+ | `Clear selection` |
153
+ | `Decrement value` |
154
+ | `Increment value` |
155
+ | `Select all rows` |
156
+ | `Sort descending` |
157
+ | `Select all items` |
158
+ | `Page {{page}} of {{count}}` |
159
+ | `{{selected}} of {{total}} row(s) selected.` |
160
+
161
+ The selection summary calls `t` with `count` (selected rows). Dictionary
162
+ values for that key use `one | other`.
122
163
 
123
164
  ## Related components
124
165
 
125
- BridgeUIProvider, PasswordField, NumberField, Select, Listbox, Snackbar
166
+ BridgeUIProvider, DataTable, Pagination, PasswordField, NumberField, Select, Listbox, Snackbar
@@ -1,6 +1,6 @@
1
1
  # Pagination
2
2
 
3
- Page controls for lists and tables: previous/next, page numbers, and a simple cursor-friendly prev/next mode.
3
+ Page controls for lists and tables: previous/next with labels, page numbers, and a simple cursor-friendly prev/next mode. `Previous` and `Next` resolve through the i18n adapter.
4
4
 
5
5
  ## Import
6
6
 
@@ -27,15 +27,17 @@ const page = ref(1);
27
27
 
28
28
  ### Variants
29
29
 
30
+ `ghost` (default), `text`, `outlined`.
31
+
30
32
  ```vue
31
- <Pagination :count="12" v-model="page" variant="text" />
32
33
  <Pagination :count="12" v-model="page" variant="ghost" />
34
+ <Pagination :count="12" v-model="page" variant="text" />
33
35
  <Pagination :count="12" v-model="page" variant="outlined" />
34
36
  ```
35
37
 
36
38
  ### Rounded
37
39
 
38
- Applies to `ghost` item corners and the `outlined` group / edge controls.
40
+ Applies to `ghost` and `text` item corners and the `outlined` group / edge controls.
39
41
 
40
42
  ```vue
41
43
  <Pagination :count="12" rounded="lg" v-model="page" variant="ghost" />
@@ -46,7 +46,7 @@ Same three chrome treatments as `DataTable`. Pair with `Pagination` under the ta
46
46
 
47
47
  ```vue
48
48
  <Table variant="plain" />
49
- <Pagination :count="12" v-model="page" variant="text" />
49
+ <Pagination :count="12" v-model="page" variant="ghost" />
50
50
 
51
51
  <Table variant="ghost" />
52
52
  <Pagination :count="12" v-model="page" variant="ghost" />
@@ -57,7 +57,7 @@ Same three chrome treatments as `DataTable`. Pair with `Pagination` under the ta
57
57
 
58
58
  | Table `variant` | Pagination `variant` |
59
59
  | --------------- | -------------------- |
60
- | `plain` | `text` |
60
+ | `plain` | `ghost` |
61
61
  | `ghost` | `ghost` |
62
62
  | `bordered` | `outlined` |
63
63
 
@@ -1,6 +1,6 @@
1
1
  # Tabs
2
2
 
3
- Organize related content into tabbed views. Use with `TabList`, `Tab`, and `TabPanel`. Selected accent uses the semantic `color` palette; inactive tabs use `dark-*`.
3
+ Organize related content into tabbed views. Use with `TabList`, `Tab`, and `TabPanel`. The selected tab uses a quiet surface from `variant`; `color` optionally tints selected text and the `line` / `solid` / `enclosed` indicator.
4
4
 
5
5
  ## Import
6
6
 
@@ -90,10 +90,28 @@ import { TabPanel } from "@bridge-ui/vue/Components/TabPanel";
90
90
 
91
91
  ### Variants
92
92
 
93
- `line` (default), `plain`, `pill`, `solid`, `enclosed`.
93
+ `pill` (default), `line`, `plain`, `solid`, `enclosed`.
94
94
 
95
95
  ```vue
96
- <Tabs v-model="tab" variant="line" color="primary">
96
+ <Tabs v-model="tab">
97
+ <TabList>
98
+ <Tab value="one">One</Tab>
99
+ <Tab value="two">Two</Tab>
100
+ </TabList>
101
+ <TabPanel value="one">First</TabPanel>
102
+ <TabPanel value="two">Second</TabPanel>
103
+ </Tabs>
104
+
105
+ <Tabs v-model="tab" variant="line">
106
+ <TabList>
107
+ <Tab value="one">One</Tab>
108
+ <Tab value="two">Two</Tab>
109
+ </TabList>
110
+ <TabPanel value="one">First</TabPanel>
111
+ <TabPanel value="two">Second</TabPanel>
112
+ </Tabs>
113
+
114
+ <Tabs v-model="tab" variant="plain">
97
115
  <TabList>
98
116
  <Tab value="one">One</Tab>
99
117
  <Tab value="two">Two</Tab>
@@ -102,7 +120,7 @@ import { TabPanel } from "@bridge-ui/vue/Components/TabPanel";
102
120
  <TabPanel value="two">Second</TabPanel>
103
121
  </Tabs>
104
122
 
105
- <Tabs color="dark" v-model="tab" variant="pill">
123
+ <Tabs v-model="tab" variant="solid">
106
124
  <TabList>
107
125
  <Tab value="one">One</Tab>
108
126
  <Tab value="two">Two</Tab>
@@ -152,11 +170,11 @@ import { TabPanel } from "@bridge-ui/vue/Components/TabPanel";
152
170
  | Prop | Type | Default |
153
171
  | ------------- | ----------------- | -------------- |
154
172
  | `activation` | `TabsActivation` | `"automatic"` |
155
- | `color` | `TabsColor` | `"primary"` |
173
+ | `color` | `TabsColor` | `"dark"` |
156
174
  | `keepMounted` | `boolean` | `true` |
157
175
  | `orientation` | `TabsOrientation` | `"horizontal"` |
158
176
  | `size` | `TabsSize` | `"md"` |
159
- | `variant` | `TabsVariant` | `"line"` |
177
+ | `variant` | `TabsVariant` | `"pill"` |
160
178
 
161
179
  ### v-model
162
180
 
@@ -5,15 +5,19 @@
5
5
  *
6
6
  * Source English strings are the lookup keys (same strings Bridge passes to
7
7
  * `resolveMessage`). Messages are keyed by locale; optional `setLocale` updates
8
- * the active locale used by `t`. For replace / pluralization, wrap vue-i18n (or
9
- * similar) instead.
8
+ * the active locale used by `t`. `t` replaces `{{name}}` from `params` and
9
+ * picks `|` plural forms when `count` is set (`one | other`).
10
10
  */
11
11
 
12
12
  // ** External Imports
13
- import { get } from "es-toolkit/compat";
13
+ import { get, isNil } from "es-toolkit/compat";
14
14
 
15
15
  // ** Core Imports
16
- import type { I18nAdapter } from "@bridge-ui/core/Adapters";
16
+ import {
17
+ interpolateMessage,
18
+ selectPluralMessage,
19
+ type I18nAdapter,
20
+ } from "@bridge-ui/core/Adapters";
17
21
 
18
22
  // prettier-ignore
19
23
  const MESSAGES: Record<string, Record<string, string>> = {
@@ -21,25 +25,34 @@ const MESSAGES: Record<string, Record<string, string>> = {
21
25
  "pt-BR": {
22
26
  "OK": "OK",
23
27
  "Close": "Fechar",
24
- "Reset": "Redefinir",
28
+ "Next": "Próxima",
25
29
  "Columns": "Colunas",
30
+ "Reset": "Redefinir",
26
31
  "Search": "Pesquisar",
27
32
  "No data": "Sem dados",
28
- "Per page:": "Por página:",
33
+ "Previous": "Anterior",
34
+ "Loading": "Carregando",
35
+ "Pagination": "Paginação",
36
+ "Last page": "Última página",
29
37
  "Loading...": "Carregando...",
30
38
  "No options": "Nenhuma opção",
31
- "Select row": "Selecionar linha",
39
+ "Expand row": "Expandir linha",
40
+ "First page": "Primeira página",
32
41
  "Hide password": "Ocultar senha",
42
+ "Select row": "Selecionar linha",
33
43
  "Show password": "Mostrar senha",
34
44
  "Filter column": "Filtrar coluna",
35
45
  "Clear selection": "Limpar seleção",
36
46
  "Decrement value": "Diminuir valor",
37
47
  "Increment value": "Aumentar valor",
48
+ "Rows per page": "Linhas por página",
38
49
  "Sort ascending": "Ordenar crescente",
39
50
  "Cancel sorting": "Cancelar ordenação",
40
51
  "Sort descending": "Ordenar decrescente",
41
- "Select all rows": "Selecionar todas as linhas",
42
52
  "Select all items": "Selecionar todos os itens",
53
+ "Select all rows": "Selecionar todas as linhas",
54
+ "Page {{page}} of {{count}}": "Página {{page}} de {{count}}",
55
+ "{{selected}} of {{total}} row(s) selected.": "{{selected}} de {{total}} linha selecionada. | {{selected}} de {{total}} linhas selecionadas.",
43
56
  },
44
57
  };
45
58
 
@@ -54,8 +67,13 @@ export function createDictionaryI18nAdapter(): I18nAdapter {
54
67
  setLocale(next) {
55
68
  locale = next;
56
69
  },
57
- t(message) {
58
- return get(MESSAGES, [locale, message], message);
70
+ t(message, count, params) {
71
+ const translated = get(MESSAGES, [locale, message], message);
72
+ const template = isNil(count)
73
+ ? translated
74
+ : selectPluralMessage(translated, count);
75
+
76
+ return interpolateMessage(template, params);
59
77
  },
60
78
  };
61
79
  }
@@ -3,12 +3,13 @@
3
3
  * Copy into your app or wire via `BridgeUIProvider` / `createBridgeUI` `global.i18n`.
4
4
  * Not published as an npm package.
5
5
  *
6
- * Passes Bridge source strings and `params` straight to `i18n.t`
7
- * (interpolation, pluralization, etc. stay in vue-i18n).
6
+ * Passes Bridge source strings, `count`, and `params` to `i18n.t`
7
+ * (interpolation and `|` pluralization stay in vue-i18n).
8
8
  * `setLocale` on the adapter is invoked by Bridge `setLocale`.
9
9
  */
10
10
 
11
11
  // ** External Imports
12
+ import { isNil } from "es-toolkit/compat";
12
13
  import type { Composer } from "vue-i18n";
13
14
 
14
15
  // ** Core Imports
@@ -23,12 +24,12 @@ export function createVueI18nAdapter(i18n: Composer): I18nAdapter {
23
24
  setLocale(locale) {
24
25
  i18n.locale.value = locale;
25
26
  },
26
- t(message, params) {
27
- if (params) {
28
- return i18n.t(message, params);
27
+ t(message, count, params) {
28
+ if (isNil(count)) {
29
+ return params ? i18n.t(message, params) : i18n.t(message);
29
30
  }
30
31
 
31
- return i18n.t(message);
32
+ return params ? i18n.t(message, count, params) : i18n.t(message, count);
32
33
  },
33
34
  };
34
35
  }
@@ -10,6 +10,8 @@
10
10
  // ** External Imports
11
11
  import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
12
12
  import {
13
+ faAnglesLeft,
14
+ faAnglesRight,
13
15
  faBell,
14
16
  faCalendarDays,
15
17
  faCheck,
@@ -117,7 +119,9 @@ const icons = {
117
119
  alert: faCircleExclamation,
118
120
  chevronDown: faChevronDown,
119
121
  chevronLeft: faChevronLeft,
122
+ chevronsLeft: faAnglesLeft,
120
123
  chevronRight: faChevronRight,
124
+ chevronsRight: faAnglesRight,
121
125
  warning: faTriangleExclamation,
122
126
  } satisfies Record<SemanticIconName, unknown>;
123
127
 
@@ -13,6 +13,8 @@ import {
13
13
  CalendarDaysIcon,
14
14
  CheckCircleIcon,
15
15
  CheckIcon,
16
+ ChevronDoubleLeftIcon,
17
+ ChevronDoubleRightIcon,
16
18
  ChevronDownIcon,
17
19
  ChevronLeftIcon,
18
20
  ChevronRightIcon,
@@ -67,8 +69,10 @@ const icons = {
67
69
  chevronDown: ChevronDownIcon,
68
70
  chevronLeft: ChevronLeftIcon,
69
71
  chevronRight: ChevronRightIcon,
70
- warning: ExclamationTriangleIcon,
71
72
  chevronUpDown: ChevronUpDownIcon,
73
+ warning: ExclamationTriangleIcon,
74
+ chevronsLeft: ChevronDoubleLeftIcon,
75
+ chevronsRight: ChevronDoubleRightIcon,
72
76
  } satisfies Record<SemanticIconName, unknown>;
73
77
 
74
78
  /**
@@ -12,6 +12,8 @@ import {
12
12
  ChevronDown,
13
13
  ChevronLeft,
14
14
  ChevronRight,
15
+ ChevronsLeft,
16
+ ChevronsRight,
15
17
  ChevronsUpDown,
16
18
  ChevronUp,
17
19
  CircleAlert,
@@ -68,6 +70,8 @@ const icons = {
68
70
  chevronDown: ChevronDown,
69
71
  chevronLeft: ChevronLeft,
70
72
  chevronRight: ChevronRight,
73
+ chevronsLeft: ChevronsLeft,
74
+ chevronsRight: ChevronsRight,
71
75
  chevronUpDown: ChevronsUpDown,
72
76
  } satisfies Record<SemanticIconName, unknown>;
73
77
 
@@ -8,6 +8,8 @@
8
8
  import {
9
9
  PhBell,
10
10
  PhCalendarDots,
11
+ PhCaretDoubleLeft,
12
+ PhCaretDoubleRight,
11
13
  PhCaretDown,
12
14
  PhCaretLeft,
13
15
  PhCaretRight,
@@ -69,6 +71,8 @@ const icons = {
69
71
  download: PhDownloadSimple,
70
72
  chevronRight: PhCaretRight,
71
73
  chevronUpDown: PhCaretUpDown,
74
+ chevronsLeft: PhCaretDoubleLeft,
75
+ chevronsRight: PhCaretDoubleRight,
72
76
  } satisfies Record<SemanticIconName, unknown>;
73
77
 
74
78
  /**