@omnitend/dashboard-for-laravel 0.41.1 → 0.41.2

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.
@@ -1,8 +1,8 @@
1
1
  {
2
- "generated": "2026-09-27T10:14:02.393Z",
2
+ "generated": "2026-09-30T05:13:05.340Z",
3
3
  "package": {
4
4
  "name": "@omnitend/dashboard-for-laravel",
5
- "version": "0.41.1"
5
+ "version": "0.41.2"
6
6
  },
7
7
  "components": {
8
8
  "base": [
@@ -911,6 +911,16 @@
911
911
  "props": [],
912
912
  "events": [],
913
913
  "slots": [
914
+ {
915
+ "name": "default",
916
+ "description": "",
917
+ "bindings": []
918
+ },
919
+ {
920
+ "name": "actions",
921
+ "description": "",
922
+ "bindings": []
923
+ },
914
924
  {
915
925
  "name": "name",
916
926
  "description": "",
@@ -2737,6 +2747,47 @@
2737
2747
  "slots": [],
2738
2748
  "methods": []
2739
2749
  },
2750
+ {
2751
+ "name": "DXLoading",
2752
+ "category": "extended",
2753
+ "filePath": "resources/js/components/extended/DXLoading.vue",
2754
+ "description": "",
2755
+ "props": [
2756
+ {
2757
+ "name": "text",
2758
+ "type": "string",
2759
+ "required": false,
2760
+ "default": "\"Loading…\"",
2761
+ "description": ""
2762
+ },
2763
+ {
2764
+ "name": "delay",
2765
+ "type": "number",
2766
+ "required": false,
2767
+ "default": "300",
2768
+ "description": ""
2769
+ }
2770
+ ],
2771
+ "events": [],
2772
+ "slots": [],
2773
+ "methods": []
2774
+ },
2775
+ {
2776
+ "name": "DXModalActions",
2777
+ "category": "extended",
2778
+ "filePath": "resources/js/components/extended/DXModalActions.vue",
2779
+ "description": "Shared secondary modal actions; distinct from the modal footer controls.",
2780
+ "props": [],
2781
+ "events": [],
2782
+ "slots": [
2783
+ {
2784
+ "name": "default",
2785
+ "description": "",
2786
+ "bindings": []
2787
+ }
2788
+ ],
2789
+ "methods": []
2790
+ },
2740
2791
  {
2741
2792
  "name": "DXNumericField",
2742
2793
  "category": "extended",
@@ -3079,7 +3130,7 @@
3079
3130
  "name": "DXSwitch",
3080
3131
  "category": "extended",
3081
3132
  "filePath": "resources/js/components/extended/DXSwitch.vue",
3082
- "description": "DXSwitch — a \"filled box\" toggle switch. An opinionated switch built on `DFormCheckbox` (`switch`): a bordered box sized like a `.form-control` with the label on the left and the toggle on the right, colour-coding its state. By default (`onVariant=\"success\"`) it reads the house green-on / red-off style: a light-red box with a grey toggle when off, a soft-green box with a muted green-grey toggle when on. `onVariant=\"neutral\"` (brand primary on / grey off) is for semantically-mixed switches that shouldn't imply good/bad (#158). Used standalone or, internally, by `DXField`'s `switch` field type so a form switch and a lone switch share one look. Usage: ```vue <DXSwitch v-model=\"isCurrent\" label=\"Product is current\" /> ``` For a form field, prefer a `DXField`/`DXForm` `type: 'switch'`; reach for `DXSwitch` directly when you want the styled toggle outside a form. Pass a `label` prop for simple text, or the default slot for richer label content.",
3133
+ "description": "DXSwitch — a \"filled box\" toggle switch. An opinionated switch built on `DFormCheckbox` (`switch`): a bordered box sized like a `.form-control` with the label on the left and the toggle on the right, colour-coding its state. By default (`onVariant=\"success\"`) it reads the house green-on / red-off style: a light-red box with a muted red-grey toggle when off, a soft-green box with a muted green-grey toggle when on. `onVariant=\"neutral\"` (brand primary on / grey off) is for semantically-mixed switches that shouldn't imply good/bad (#158). Used standalone or, internally, by `DXField`'s `switch` field type so a form switch and a lone switch share one look. Usage: ```vue <DXSwitch v-model=\"isCurrent\" label=\"Product is current\" /> ``` For a form field, prefer a `DXField`/`DXForm` `type: 'switch'`; reach for `DXSwitch` directly when you want the styled toggle outside a form. Pass a `label` prop for simple text, or the default slot for richer label content.",
3083
3134
  "props": [
3084
3135
  {
3085
3136
  "name": "modelValue",
@@ -3117,7 +3168,7 @@
3117
3168
  "name": "size",
3118
3169
  "type": "\"sm\"",
3119
3170
  "required": false,
3120
- "description": "`\"sm\"` renders a compact box (a few px shorter than the default, which\nmatches the input height) for dense rows that repeat the switch per item (a\nper-line visibility toggle in a modal). Omit for the standard size, which\nlines the switch up with the `.form-control`\nheight so a switch lines up with inputs beside it."
3171
+ "description": "`\"sm\"` renders a compact rounded pill (a few px shorter than the default, which\nmatches the input height) for dense rows that repeat the switch per item (a\nper-line visibility toggle in a modal). Omit for the standard size, which\nlines the switch up with the `.form-control`\nheight so a switch lines up with inputs beside it."
3121
3172
  }
3122
3173
  ],
3123
3174
  "events": [
@@ -4000,7 +4051,7 @@
4000
4051
  "name": "DXTablePagination",
4001
4052
  "category": "extended",
4002
4053
  "filePath": "resources/js/components/extended/DXTablePagination.vue",
4003
- "description": "Internal pagination + per-page footer for `DXTable`. Renders the pager, the per-page selector, and the \"X to Y out of Z items\" info line (with the \"Filtered from N\" note when a column filter is active). Extracted because `DXTable` used to carry three byte-identical copies of this footer — one per data mode (client-side / inertia / provider) — that differed only in which `PaginationData` object and page-change handler they used, so every footer fix had to be written three times (#123). `DXTable` now derives the active pagination + handler and renders this once. It owns its own `:deep(.pagination …)` styling (rather than leaving it in `DXTable`), because a scoped `:deep()` in `DXTable` would not reach the pager once it lives in a child component — the scope-id doesn't cross the boundary. Anchoring the rules on this component's own `.dx-table-pagination` root (a plain element it owns) gives the scope-id a deterministic host. In a row too narrow for the full windowed pager, the number strip collapses to a \"current / last\" status with Previous/Next either side (#162). The decision is CONTAINER-driven, not viewport-driven — see `compactThreshold`.",
4054
+ "description": "Pagination + per-page footer shared by `DXTable` and standalone tables. Renders the pager, the per-page selector, and the \"X to Y out of Z items\" info line (with the \"Filtered from N\" note when a column filter is active). Extracted because `DXTable` used to carry three byte-identical copies of this footer — one per data mode (client-side / inertia / provider) — that differed only in which `PaginationData` object and page-change handler they used, so every footer fix had to be written three times (#123). `DXTable` now derives the active pagination + handler and renders this once. It owns its own `:deep(.pagination …)` styling (rather than leaving it in `DXTable`), because a scoped `:deep()` in `DXTable` would not reach the pager once it lives in a child component — the scope-id doesn't cross the boundary. Anchoring the rules on this component's own `.dx-table-pagination` root (a plain element it owns) gives the scope-id a deterministic host. In a row too narrow for the full windowed pager, the number strip collapses to a \"current / last\" status with Previous/Next either side (#162). The decision is CONTAINER-driven, not viewport-driven — see `compactThreshold`.",
4004
4055
  "props": [
4005
4056
  {
4006
4057
  "name": "pagination",
@@ -4163,8 +4214,8 @@
4163
4214
  ]
4164
4215
  },
4165
4216
  "stats": {
4166
- "totalComponents": 84,
4217
+ "totalComponents": 86,
4167
4218
  "baseComponents": 60,
4168
- "extendedComponents": 24
4219
+ "extendedComponents": 26
4169
4220
  }
4170
4221
  }
@@ -1,7 +1,7 @@
1
1
  # Documentation Map
2
2
 
3
3
  > Auto-generated hierarchical overview of all documentation
4
- > Last updated: 2026-09-27T10:14:02.445Z
4
+ > Last updated: 2026-09-30T05:13:05.394Z
5
5
 
6
6
  This file provides a complete map of all available documentation for AI agents and developers.
7
7
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Vue 3 dashboard components for Laravel with Bootstrap Vue Next
4
4
  >
5
- > A dual-package library (NPM + Composer) providing 73 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
5
+ > A dual-package library (NPM + Composer) providing 76 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
6
6
 
7
7
  ## Installation
8
8
 
@@ -84,7 +84,7 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
84
84
  - [DToaster](/components/base/dtoaster): Bootstrap Vue Next Toaster wrapper
85
85
  - [DTooltip](/components/base/dtooltip): Bootstrap Vue Next Tooltip wrapper
86
86
 
87
- ## Extended Components (13 components)
87
+ ## Extended Components (16 components)
88
88
 
89
89
  Custom dashboard components with advanced functionality beyond Bootstrap Vue Next.
90
90
 
@@ -96,10 +96,13 @@ Custom dashboard components with advanced functionality beyond Bootstrap Vue Nex
96
96
  - [DXField](/components/extended/dxfield): Single-field renderer for any field type with value/span/info/hint slots
97
97
  - [DXFieldLabel](/components/extended/dxfieldlabel): Extended dashboard component
98
98
  - [DXForm](/components/extended/dxform): Form renderer driven by field definitions, with optional tabs, conditional fields, per-field slots, async options, nested repeaters, and auto error-tab switching
99
+ - [DXLoading](/components/extended/dxloading): Extended dashboard component
100
+ - [DXModalActions](/components/extended/dxmodalactions): Extended dashboard component
99
101
  - [DXRepeater](/components/extended/dxrepeater): Repeatable nested sub-form (field array) primitive
100
102
  - [DXStatCard](/components/extended/dxstatcard): Extended dashboard component
101
103
  - [DXSwitch](/components/extended/dxswitch): Extended dashboard component
102
104
  - [DXTable](/components/extended/dxtable): Data table with pagination, filtering, and sorting
105
+ - [DXTablePagination](/components/extended/dxtablepagination): Extended dashboard component
103
106
  - [DXUserAvatar](/components/extended/dxuseravatar): Extended dashboard component
104
107
 
105
108
  ## Composables
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitend/dashboard-for-laravel",
3
- "version": "0.41.1",
3
+ "version": "0.41.2",
4
4
  "description": "Vue 3 dashboard components for Laravel with Bootstrap Vue Next",
5
5
  "type": "module",
6
6
  "main": "./dist/dashboard-for-laravel.umd.cjs",
@@ -694,6 +694,11 @@ $bootstrap-icons-font-src: url("bootstrap-icons/font/fonts/bootstrap-icons.woff2
694
694
  vertical-align: middle;
695
695
  }
696
696
 
697
+ // Column help uses the table's header colour rather than the form-label ink.
698
+ .table > thead th .dx-field-label__text {
699
+ color: inherit;
700
+ }
701
+
697
702
  .table > thead {
698
703
  vertical-align: middle;
699
704
  }
@@ -750,7 +755,7 @@ $bootstrap-icons-font-src: url("bootstrap-icons/font/fonts/bootstrap-icons.woff2
750
755
  // theme `@import`s `bootstrap-icons/font/bootstrap-icons` (declaring the
751
756
  // `@font-face`), and #77's post-build extraction ships that woff2 with the
752
757
  // stylesheet — so this needs no new dependency and no data-URI. Values signed
753
- // off after one padding iteration in the greendragon interim; the glyph metrics
758
+ // off after one padding iteration in the interim UI; the glyph metrics
754
759
  // are tunable via the variables below.
755
760
  $dx-dropdown-caret-size: 0.75em; // glyph size relative to the label
756
761
  $dx-dropdown-caret-gap: 0.4em; // space between label and chevron
@@ -806,23 +811,16 @@ $dx-switch-on-soft: map.get(map.get($dx-variants, "success"), "soft-bg"); // #cd
806
811
  --dx-switch-off-well: #{color.mix($dx-switch-off, #fff, 10%)};
807
812
  --dx-switch-off-line: #{color.mix($dx-switch-off, #fff, 45%)};
808
813
  --dx-switch-off-ink: #{color.mix($dx-switch-off, #000, 30%)};
809
- --dx-switch-pill: var(--bs-gray-400, #ced4da); // neutral OFF pill
814
+ --dx-switch-pill: var(--bs-gray-400, #ced4da);
815
+ --dx-switch-off-pill: #{color.mix(map.get(map.get($dx-variants, "danger"), "soft-text"), $gray-400, 50%)};
810
816
  --dx-switch-on-pill: #{color.mix(map.get(map.get($dx-variants, "success"), "soft-text"), $gray-400, 50%)};
811
817
  }
812
818
 
813
- // Optically centre the check/radio/switch box against its label's FIRST line.
814
- // Bootstrap's `.25em` top margin is mathematically right for a 1em box in a
815
- // 1.5em line box, but Poppins seats its glyphs low in the line box, so the box
816
- // reads visibly HIGH beside the text (same optical-metrics issue as the B14
817
- // dropdown caret). `0.325em` lands the box centre on Poppins' visual centre —
818
- // judged against a rendered filmstrip (0.25/0.30/0.325/0.35em) with Poppins
819
- // loaded, not from the maths. A top MARGIN (not flex-centring) is deliberate:
820
- // it aligns to the first line, so a multi-line label keeps the box on line one
821
- // rather than floating to the block's vertical centre. DXSwitch is unaffected —
822
- // it flex-centres and zeroes this margin on its inner input at higher
823
- // specificity (`.dx-switch :deep(.form-check-input) { margin: 0 }`).
819
+ // Centre checkboxes/radios on the first label line using their actual size.
820
+ // The old em offset assumed a 1em box; these controls are now 1.25rem tall.
821
+ // A margin keeps wrapped labels aligned to line one rather than the whole block.
824
822
  .form-check-input {
825
- margin-top: 0.325em;
823
+ margin-top: calc((1lh - #{$form-check-input-width}) / 2);
826
824
  }
827
825
 
828
826
  .form-switch .form-check-input {
@@ -1,11 +1,22 @@
1
1
  <template>
2
- <BModal v-bind="$attrs">
3
- <template v-for="(_, name) in $slots" #[name]="slotProps">
2
+ <BModal size="lg" v-bind="$attrs">
3
+ <template #default="slotProps">
4
+ <slot v-bind="slotProps" />
5
+ <DXModalActions v-if="$slots.actions" class="mt-3">
6
+ <slot name="actions" v-bind="slotProps" />
7
+ </DXModalActions>
8
+ </template>
9
+ <template v-for="name in forwardedSlots" #[name]="slotProps">
4
10
  <slot :name="name" v-bind="slotProps" />
5
11
  </template>
6
12
  </BModal>
7
13
  </template>
8
14
 
9
15
  <script setup lang="ts">
16
+ import { computed, useSlots } from "vue";
10
17
  import { BModal } from "bootstrap-vue-next";
18
+ import DXModalActions from "../extended/DXModalActions.vue";
19
+
20
+ const slots = useSlots();
21
+ const forwardedSlots = computed(() => Object.keys(slots).filter(name => name !== "default" && name !== "actions"));
11
22
  </script>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <div
3
+ v-if="isVisible"
4
+ class="dx-loading text-center text-muted py-5"
5
+ role="status"
6
+ aria-live="polite"
7
+ >
8
+ <DSpinner variant="primary" aria-hidden="true" />
9
+ <div class="mt-2">{{ text }}</div>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { onBeforeUnmount, onMounted, ref } from "vue";
15
+ import DSpinner from "../base/DSpinner.vue";
16
+
17
+ const props = withDefaults(
18
+ defineProps<{
19
+ text?: string;
20
+ delay?: number;
21
+ }>(),
22
+ {
23
+ text: "Loading…",
24
+ delay: 300,
25
+ },
26
+ );
27
+
28
+ const isVisible = ref(false);
29
+ let showTimer: ReturnType<typeof setTimeout> | undefined;
30
+
31
+ onMounted(() => {
32
+ if (props.delay <= 0) {
33
+ isVisible.value = true;
34
+ return;
35
+ }
36
+
37
+ showTimer = setTimeout(() => {
38
+ isVisible.value = true;
39
+ }, props.delay);
40
+ });
41
+
42
+ onBeforeUnmount(() => {
43
+ if (showTimer !== undefined) {
44
+ clearTimeout(showTimer);
45
+ }
46
+ });
47
+ </script>
@@ -0,0 +1,13 @@
1
+ <!-- Shared secondary modal actions; distinct from the modal footer controls. -->
2
+ <template>
3
+ <div class="dx-modal-actions"><slot /></div>
4
+ </template>
5
+
6
+ <style scoped>
7
+ .dx-modal-actions {
8
+ display: flex;
9
+ flex-direction: column;
10
+ align-items: stretch;
11
+ gap: 0.75rem;
12
+ }
13
+ </style>
@@ -5,7 +5,7 @@
5
5
  An opinionated switch built on `DFormCheckbox` (`switch`): a bordered box sized
6
6
  like a `.form-control` with the label on the left and the toggle on the right,
7
7
  colour-coding its state. By default (`onVariant="success"`) it reads the house
8
- green-on / red-off style: a light-red box with a grey toggle when off, a
8
+ green-on / red-off style: a light-red box with a muted red-grey toggle when off, a
9
9
  soft-green box with a muted green-grey toggle when on. `onVariant="neutral"` (brand primary on / grey off)
10
10
  is for semantically-mixed switches that shouldn't imply good/bad (#158). Used
11
11
  standalone or, internally, by `DXField`'s `switch` field type so a form switch
@@ -64,7 +64,7 @@ interface Props {
64
64
  */
65
65
  onVariant?: "success" | "neutral";
66
66
  /**
67
- * `"sm"` renders a compact box (a few px shorter than the default, which
67
+ * `"sm"` renders a compact rounded pill (a few px shorter than the default, which
68
68
  * matches the input height) for dense rows that repeat the switch per item (a
69
69
  * per-line visibility toggle in a modal). Omit for the standard size, which
70
70
  * lines the switch up with the `.form-control`
@@ -147,6 +147,7 @@ defineOptions({
147
147
  chrome tightens. */
148
148
  .dx-switch--sm :deep(.form-check) {
149
149
  font-size: 0.875rem;
150
+ border-radius: var(--bs-border-radius-pill, 50rem);
150
151
  min-height: auto;
151
152
  padding: 0.25rem 0.625rem;
152
153
  }
@@ -173,6 +174,10 @@ defineOptions({
173
174
  glance (the house style). `success` (default) is green ON / light-red OFF;
174
175
  `neutral` keeps a brand primary panel for mixed-semantics switches. Pair with
175
176
  `textWhenTrue`/`textWhenFalse` so the LABEL also names each state. */
177
+ .dx-switch--success {
178
+ --dx-switch-pill: var(--dx-switch-off-pill);
179
+ }
180
+
176
181
  .dx-switch--success :deep(.form-check) {
177
182
  background-color: var(--dx-switch-off-bg);
178
183
  border-color: var(--dx-switch-off-line);
@@ -189,14 +194,13 @@ defineOptions({
189
194
 
190
195
  .dx-switch--success.dx-switch--on :deep(.form-check-label) {
191
196
  color: var(--dx-switch-on-ink);
192
- font-weight: 500;
193
197
  }
194
198
 
195
199
  .dx-switch--success.dx-switch--on {
196
200
  --dx-switch-pill: var(--dx-switch-on-pill);
197
201
  }
198
202
 
199
- /* Muted pill with a white sliding thumb: green-grey ON, neutral grey OFF.
203
+ /* Muted pill with a white sliding thumb: green-grey ON, red-grey OFF.
200
204
  The stronger box colour and position continue to communicate the state. Explicit `:checked`/`:focus` selectors so they out-specify the global
201
205
  `.form-switch .form-check-input:checked` rule. */
202
206
  .dx-switch--success :deep(.form-check-input),
@@ -220,6 +224,5 @@ defineOptions({
220
224
 
221
225
  .dx-switch--neutral.dx-switch--on :deep(.form-check-label) {
222
226
  color: var(--bs-primary-text-emphasis);
223
- font-weight: 500;
224
227
  }
225
228
  </style>
@@ -174,7 +174,10 @@
174
174
  <template v-for="field in fields" :key="`head-${field.key}`" #[`head(${field.key})`]="{ label }">
175
175
  <div class="d-flex align-items-center justify-content-between gap-2">
176
176
  <div class="flex-grow-1">
177
- <div class="fw-semibold">{{ headerLabel(field, label) }}</div>
177
+ <div class="fw-semibold">
178
+ <DXFieldLabel v-if="field.info" :label="headerLabel(field, label)" :info="field.info" />
179
+ <template v-else>{{ headerLabel(field, label) }}</template>
180
+ </div>
178
181
  <small v-if="field.hint" class="text-muted d-block" style="font-weight: normal;">{{ field.hint }}</small>
179
182
  </div>
180
183
 
@@ -326,6 +329,7 @@ import DTable from "../base/DTable.vue";
326
329
  import DFormInput from "../base/DFormInput.vue";
327
330
  import DFormSelect from "../base/DFormSelect.vue";
328
331
  import DAutocomplete from "../base/DAutocomplete.vue";
332
+ import DXFieldLabel from "./DXFieldLabel.vue";
329
333
  import DButton from "../base/DButton.vue";
330
334
  import DXTablePagination from "./DXTablePagination.vue";
331
335
  import DXTableEditorModal from "./DXTableEditorModal.vue";
@@ -404,6 +408,8 @@ export interface TableField {
404
408
  filterAllText?: string;
405
409
  sortable?: boolean;
406
410
  hint?: string;
411
+ /** Help revealed from a focusable info icon beside the column label. */
412
+ info?: string;
407
413
  /**
408
414
  * The inline filter control for this column, or `false`/omit for none. See
409
415
  * `FilterType`. `'select'` (typeahead) and `'select-native'` (plain
@@ -1767,6 +1773,7 @@ watch(clientSideLastPage, (lastPage) => {
1767
1773
  // Client-side paginated items (final output)
1768
1774
  const clientSidePaginatedItems = computed<T[]>(() => {
1769
1775
  if (!isClientSideMode.value) return [];
1776
+ if (!props.showPagination) return clientSideSortedItems.value;
1770
1777
 
1771
1778
  const perPage = effectivePerPage.value;
1772
1779
  const start = (clientSidePage.value - 1) * perPage;
@@ -1783,19 +1790,19 @@ const clientSidePagination = computed<PaginationData>(() => {
1783
1790
  const lastPage = clientSideLastPage.value;
1784
1791
 
1785
1792
  // Same clamped page the slice uses — see `clientSidePage` (#118).
1786
- const validPage = clientSidePage.value;
1793
+ const validPage = props.showPagination ? clientSidePage.value : 1;
1787
1794
 
1788
- const from = total > 0 ? (validPage - 1) * perPage + 1 : 0;
1789
- const to = Math.min(validPage * perPage, total);
1795
+ const from = total > 0 ? (props.showPagination ? (validPage - 1) * perPage + 1 : 1) : 0;
1796
+ const to = props.showPagination ? Math.min(validPage * perPage, total) : total;
1790
1797
 
1791
1798
  return {
1792
1799
  current_page: validPage,
1793
- per_page: perPage,
1800
+ per_page: props.showPagination ? perPage : Math.max(1, total),
1794
1801
  total,
1795
1802
  total_unfiltered: totalUnfiltered !== total ? totalUnfiltered : undefined,
1796
1803
  from,
1797
1804
  to,
1798
- last_page: lastPage,
1805
+ last_page: props.showPagination ? lastPage : 1,
1799
1806
  };
1800
1807
  });
1801
1808
 
@@ -1822,7 +1829,7 @@ const handleClientSidePageChange = (page: number) => {
1822
1829
  // Computed: determine if per-page selector should be shown
1823
1830
  // Hide it when total items is less than the smallest page size option
1824
1831
  const shouldShowPerPageSelector = computed(() => {
1825
- if (!props.showPerPageSelector) return false;
1832
+ if (!props.showPagination || !props.showPerPageSelector) return false;
1826
1833
 
1827
1834
  const smallestOption = Math.min(...props.perPageOptions);
1828
1835
  const total = isClientSideMode.value
@@ -1,6 +1,6 @@
1
1
  <!--
2
2
  @component
3
- Internal pagination + per-page footer for `DXTable`. Renders the pager, the
3
+ Pagination + per-page footer shared by `DXTable` and standalone tables. Renders the pager, the
4
4
  per-page selector, and the "X to Y out of Z items" info line (with the
5
5
  "Filtered from N" note when a column filter is active).
6
6
 
@@ -9,6 +9,8 @@ export { default as DXDashboard } from "./components/extended/DXDashboard.vue";
9
9
  export { default as DXForm } from "./components/extended/DXForm.vue";
10
10
  export { default as DXField } from "./components/extended/DXField.vue";
11
11
  export { default as DXFieldLabel } from "./components/extended/DXFieldLabel.vue";
12
+ export { default as DXModalActions } from "./components/extended/DXModalActions.vue";
13
+ export { default as DXLoading } from "./components/extended/DXLoading.vue";
12
14
  export { default as DXSwitch } from "./components/extended/DXSwitch.vue";
13
15
  export { default as DXCurrencyInput } from "./components/extended/DXCurrencyInput.vue";
14
16
  export { default as DXStatCard } from "./components/extended/DXStatCard.vue";
@@ -23,6 +25,7 @@ export { default as DXRepeater } from "./components/extended/DXRepeater.vue";
23
25
  */
24
26
  export { default as DXBasicForm } from "./components/extended/DXBasicForm.vue";
25
27
  export { default as DXTable } from "./components/extended/DXTable.vue";
28
+ export { default as DXTablePagination } from "./components/extended/DXTablePagination.vue";
26
29
  export { default as DXDashboardSidebar } from "./components/extended/DXDashboardSidebar.vue";
27
30
  export { default as DXDashboardNavbar } from "./components/extended/DXDashboardNavbar.vue";
28
31
  export { default as DXUserAvatar } from "./components/extended/DXUserAvatar.vue";