@conduction/nextcloud-vue 0.1.0-beta.2 → 0.1.0-beta.4

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 (153) hide show
  1. package/README.md +226 -226
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs.js +60455 -8755
  4. package/dist/nextcloud-vue.cjs.js.map +1 -1
  5. package/dist/nextcloud-vue.css +2062 -528
  6. package/dist/nextcloud-vue.esm.js +60411 -8731
  7. package/dist/nextcloud-vue.esm.js.map +1 -1
  8. package/package.json +75 -61
  9. package/src/components/CnActionsBar/CnActionsBar.vue +235 -225
  10. package/src/components/CnActionsBar/index.js +1 -1
  11. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +579 -0
  12. package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
  13. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
  14. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +418 -0
  15. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
  16. package/src/components/CnAdvancedFormDialog/index.js +1 -0
  17. package/src/components/CnCardGrid/CnCardGrid.vue +152 -152
  18. package/src/components/CnCardGrid/index.js +1 -1
  19. package/src/components/CnCellRenderer/CnCellRenderer.vue +132 -132
  20. package/src/components/CnCellRenderer/index.js +1 -1
  21. package/src/components/CnChartWidget/CnChartWidget.vue +320 -0
  22. package/src/components/CnChartWidget/index.js +1 -0
  23. package/src/components/CnConfigurationCard/CnConfigurationCard.vue +77 -77
  24. package/src/components/CnConfigurationCard/index.js +1 -1
  25. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +225 -0
  26. package/src/components/CnDashboardGrid/index.js +1 -0
  27. package/src/components/CnDashboardPage/CnDashboardPage.vue +390 -0
  28. package/src/components/CnDashboardPage/index.js +1 -0
  29. package/src/components/CnDataTable/CnDataTable.vue +349 -349
  30. package/src/components/CnDataTable/index.js +1 -1
  31. package/src/components/CnDetailCard/CnDetailCard.vue +214 -0
  32. package/src/components/CnDetailCard/index.js +1 -0
  33. package/src/components/CnDetailPage/CnDetailPage.vue +281 -0
  34. package/src/components/CnDetailPage/index.js +1 -0
  35. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +231 -223
  36. package/src/components/CnFacetSidebar/index.js +1 -1
  37. package/src/components/CnFilterBar/CnFilterBar.vue +152 -152
  38. package/src/components/CnFilterBar/index.js +1 -1
  39. package/src/components/CnIcon/CnIcon.vue +89 -89
  40. package/src/components/CnIcon/index.js +1 -1
  41. package/src/components/CnIndexPage/CnIndexPage.vue +874 -816
  42. package/src/components/CnIndexPage/index.js +1 -1
  43. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +503 -484
  44. package/src/components/CnIndexSidebar/index.js +1 -1
  45. package/src/components/CnItemCard/CnItemCard.vue +132 -0
  46. package/src/components/CnItemCard/index.js +1 -0
  47. package/src/components/CnKpiGrid/CnKpiGrid.vue +89 -89
  48. package/src/components/CnKpiGrid/index.js +1 -1
  49. package/src/components/CnMassActionBar/CnMassActionBar.vue +160 -160
  50. package/src/components/CnMassActionBar/index.js +1 -1
  51. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +320 -320
  52. package/src/components/CnMassCopyDialog/index.js +1 -1
  53. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +238 -238
  54. package/src/components/CnMassDeleteDialog/index.js +1 -1
  55. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +190 -190
  56. package/src/components/CnMassExportDialog/index.js +1 -1
  57. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +491 -491
  58. package/src/components/CnMassImportDialog/index.js +1 -1
  59. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  60. package/src/components/CnNoteCard/index.js +1 -0
  61. package/src/components/CnNotesCard/CnNotesCard.vue +413 -0
  62. package/src/components/CnNotesCard/index.js +1 -0
  63. package/src/components/CnObjectCard/CnObjectCard.vue +292 -292
  64. package/src/components/CnObjectCard/index.js +1 -1
  65. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +876 -0
  66. package/src/components/CnObjectSidebar/index.js +1 -0
  67. package/src/components/CnPageHeader/CnPageHeader.vue +57 -57
  68. package/src/components/CnPageHeader/index.js +1 -1
  69. package/src/components/CnPagination/CnPagination.vue +252 -252
  70. package/src/components/CnPagination/index.js +1 -1
  71. package/src/components/CnRowActions/CnRowActions.vue +73 -73
  72. package/src/components/CnRowActions/index.js +1 -1
  73. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  74. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
  75. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  76. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  77. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  78. package/src/components/CnSchemaFormDialog/index.js +1 -0
  79. package/src/components/CnSettingsCard/CnSettingsCard.vue +92 -92
  80. package/src/components/CnSettingsCard/index.js +1 -1
  81. package/src/components/CnSettingsSection/CnSettingsSection.vue +266 -266
  82. package/src/components/CnSettingsSection/index.js +1 -1
  83. package/src/components/CnStatsBlock/CnStatsBlock.vue +420 -366
  84. package/src/components/CnStatsBlock/index.js +1 -1
  85. package/src/components/CnStatusBadge/CnStatusBadge.vue +77 -77
  86. package/src/components/CnStatusBadge/index.js +1 -1
  87. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +540 -0
  88. package/src/components/CnTabbedFormDialog/index.js +1 -0
  89. package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
  90. package/src/components/CnTasksCard/index.js +1 -0
  91. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  92. package/src/components/CnTileWidget/index.js +1 -0
  93. package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
  94. package/src/components/CnTimelineStages/index.js +1 -0
  95. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
  96. package/src/components/CnUserActionMenu/index.js +1 -0
  97. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +312 -312
  98. package/src/components/CnVersionInfoCard/index.js +1 -1
  99. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  100. package/src/components/CnWidgetRenderer/index.js +1 -0
  101. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +211 -0
  102. package/src/components/CnWidgetWrapper/index.js +1 -0
  103. package/src/components/index.js +43 -29
  104. package/src/composables/index.js +4 -3
  105. package/src/composables/useDashboardView.js +240 -0
  106. package/src/composables/useDetailView.js +289 -132
  107. package/src/composables/useListView.js +363 -153
  108. package/src/composables/useSubResource.js +142 -142
  109. package/src/constants/metadata.js +30 -30
  110. package/src/css/CnSchemaFormDialog.css +546 -0
  111. package/src/css/__sample_nextcloud_tokens.css +110 -0
  112. package/src/css/actions-bar.css +48 -48
  113. package/src/css/badge.css +51 -51
  114. package/src/css/card.css +128 -128
  115. package/src/css/dashboard.css +70 -0
  116. package/src/css/detail-page.css +168 -0
  117. package/src/css/detail.css +68 -68
  118. package/src/css/index-page.css +44 -32
  119. package/src/css/index-sidebar.css +193 -187
  120. package/src/css/index.css +16 -12
  121. package/src/css/layout.css +90 -90
  122. package/src/css/page-header.css +33 -33
  123. package/src/css/pagination.css +72 -72
  124. package/src/css/table.css +142 -142
  125. package/src/css/timeline-stages.css +218 -0
  126. package/src/css/utilities.css +46 -46
  127. package/src/index.js +72 -53
  128. package/src/store/createSubResourcePlugin.js +135 -135
  129. package/src/store/index.js +3 -3
  130. package/src/store/plugins/auditTrails.js +17 -17
  131. package/src/store/plugins/files.js +250 -186
  132. package/src/store/plugins/index.js +7 -5
  133. package/src/store/plugins/lifecycle.js +180 -180
  134. package/src/store/plugins/relations.js +68 -68
  135. package/src/store/plugins/search.js +372 -0
  136. package/src/store/plugins/selection.js +104 -0
  137. package/src/store/useObjectStore.js +829 -686
  138. package/src/types/auditTrail.d.ts +32 -32
  139. package/src/types/file.d.ts +23 -23
  140. package/src/types/index.d.ts +35 -35
  141. package/src/types/notification.d.ts +36 -36
  142. package/src/types/object.d.ts +40 -40
  143. package/src/types/organisation.d.ts +41 -41
  144. package/src/types/register.d.ts +25 -25
  145. package/src/types/schema.d.ts +39 -39
  146. package/src/types/shared.d.ts +79 -79
  147. package/src/types/source.d.ts +14 -14
  148. package/src/types/task.d.ts +31 -31
  149. package/src/utils/errors.js +96 -96
  150. package/src/utils/headers.js +68 -50
  151. package/src/utils/id.js +13 -0
  152. package/src/utils/index.js +3 -3
  153. package/src/utils/schema.js +422 -419
@@ -0,0 +1 @@
1
+ export { default as CnObjectSidebar } from './CnObjectSidebar.vue'
@@ -1,57 +1,57 @@
1
- <template>
2
- <div class="cn-page-header">
3
- <div v-if="icon || $slots.icon" class="cn-page-header__icon">
4
- <slot name="icon">
5
- <CnIcon :name="icon" :size="iconSize" />
6
- </slot>
7
- </div>
8
- <div class="cn-page-header__text">
9
- <h1 class="cn-page-header__title">{{ title }}</h1>
10
- <p v-if="description" class="cn-page-header__description">{{ description }}</p>
11
- </div>
12
- <slot name="extra" />
13
- </div>
14
- </template>
15
-
16
- <script>
17
- import { CnIcon } from '../CnIcon/index.js'
18
-
19
- /**
20
- * CnPageHeader — Reusable page header with optional icon, title, and description.
21
- *
22
- * @example
23
- * <CnPageHeader title="Clients" description="Manage your clients" icon="AccountGroup" />
24
- */
25
- export default {
26
- name: 'CnPageHeader',
27
-
28
- components: {
29
- CnIcon,
30
- },
31
-
32
- props: {
33
- /** Page title text */
34
- title: {
35
- type: String,
36
- required: true,
37
- },
38
- /** Optional description shown below the title */
39
- description: {
40
- type: String,
41
- default: '',
42
- },
43
- /** Optional MDI icon name (rendered via CnIcon) */
44
- icon: {
45
- type: String,
46
- default: '',
47
- },
48
- /** Icon size in pixels */
49
- iconSize: {
50
- type: Number,
51
- default: 28,
52
- },
53
- },
54
- }
55
- </script>
56
-
57
- <!-- Styles in css/page-header.css -->
1
+ <template>
2
+ <div class="cn-page-header">
3
+ <div v-if="icon || $slots.icon" class="cn-page-header__icon">
4
+ <slot name="icon">
5
+ <CnIcon :name="icon" :size="iconSize" />
6
+ </slot>
7
+ </div>
8
+ <div class="cn-page-header__text">
9
+ <h1 class="cn-page-header__title">{{ title }}</h1>
10
+ <p v-if="description" class="cn-page-header__description">{{ description }}</p>
11
+ </div>
12
+ <slot name="extra" />
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ import { CnIcon } from '../CnIcon/index.js'
18
+
19
+ /**
20
+ * CnPageHeader — Reusable page header with optional icon, title, and description.
21
+ *
22
+ * @example
23
+ * <CnPageHeader title="Clients" description="Manage your clients" icon="AccountGroup" />
24
+ */
25
+ export default {
26
+ name: 'CnPageHeader',
27
+
28
+ components: {
29
+ CnIcon,
30
+ },
31
+
32
+ props: {
33
+ /** Page title text */
34
+ title: {
35
+ type: String,
36
+ required: true,
37
+ },
38
+ /** Optional description shown below the title */
39
+ description: {
40
+ type: String,
41
+ default: '',
42
+ },
43
+ /** Optional MDI icon name (rendered via CnIcon) */
44
+ icon: {
45
+ type: String,
46
+ default: '',
47
+ },
48
+ /** Icon size in pixels */
49
+ iconSize: {
50
+ type: Number,
51
+ default: 28,
52
+ },
53
+ },
54
+ }
55
+ </script>
56
+
57
+ <!-- Styles in css/page-header.css -->
@@ -1 +1 @@
1
- export { default as CnPageHeader } from './CnPageHeader.vue'
1
+ export { default as CnPageHeader } from './CnPageHeader.vue'
@@ -1,252 +1,252 @@
1
- <template>
2
- <div v-if="totalPages > 1 || totalItems > minItemsToShow" class="cn-pagination">
3
- <!-- Page info -->
4
- <div class="cn-pagination__info">
5
- <span class="cn-pagination__page-info">
6
- {{ pageInfoText }}
7
- </span>
8
- </div>
9
-
10
- <!-- Page navigation -->
11
- <div v-if="totalPages > 1" class="cn-pagination__nav">
12
- <NcButton
13
- :disabled="currentPage === 1"
14
- @click="changePage(1)">
15
- {{ firstLabel }}
16
- </NcButton>
17
-
18
- <NcButton
19
- :disabled="currentPage === 1"
20
- @click="changePage(currentPage - 1)">
21
- {{ previousLabel }}
22
- </NcButton>
23
-
24
- <div class="cn-pagination__numbers">
25
- <template v-for="page in visiblePages">
26
- <span v-if="page === '...'" :key="'ellipsis-' + page" class="cn-pagination__ellipsis">...</span>
27
- <NcButton
28
- v-else
29
- :key="page"
30
- :type="page === currentPage ? 'primary' : 'secondary'"
31
- :disabled="page === currentPage"
32
- @click="changePage(page)">
33
- {{ page }}
34
- </NcButton>
35
- </template>
36
- </div>
37
-
38
- <NcButton
39
- :disabled="currentPage === totalPages"
40
- @click="changePage(currentPage + 1)">
41
- {{ nextLabel }}
42
- </NcButton>
43
-
44
- <NcButton
45
- :disabled="currentPage === totalPages"
46
- @click="changePage(totalPages)">
47
- {{ lastLabel }}
48
- </NcButton>
49
- </div>
50
-
51
- <!-- Page size selector -->
52
- <div class="cn-pagination__page-size">
53
- <label :for="pageSizeId">{{ itemsPerPageLabel }}</label>
54
- <NcSelect
55
- :input-id="pageSizeId"
56
- class="cn-pagination__page-size-select"
57
- :value="currentPageSizeOption"
58
- :options="pageSizeOptions"
59
- :clearable="false"
60
- :input-label="itemsPerPageLabel"
61
- @option:selected="changePageSize" />
62
- </div>
63
- </div>
64
- </template>
65
-
66
- <script>
67
- import { NcButton, NcSelect } from '@nextcloud/vue'
68
-
69
- /**
70
- * CnPagination — Full pagination with page numbers, navigation, and page size selector.
71
- *
72
- * Extracted from OpenRegister's PaginationComponent. Zero store dependencies.
73
- * Supports First/Previous/Next/Last buttons, smart page number display with
74
- * ellipsis, and configurable page size.
75
- *
76
- * NL Design tokens used:
77
- * - Inherits from cn-pagination CSS class (see css/pagination.css)
78
- *
79
- * @example
80
- * <CnPagination
81
- * :current-page="page"
82
- * :total-pages="totalPages"
83
- * :total-items="totalItems"
84
- * :current-page-size="limit"
85
- * @page-changed="onPageChange"
86
- * @page-size-changed="onPageSizeChange" />
87
- */
88
- export default {
89
- name: 'CnPagination',
90
-
91
- components: {
92
- NcButton,
93
- NcSelect,
94
- },
95
-
96
- props: {
97
- /** Current page number (1-based) */
98
- currentPage: {
99
- type: Number,
100
- default: 1,
101
- },
102
- /** Total number of pages */
103
- totalPages: {
104
- type: Number,
105
- default: 1,
106
- },
107
- /** Total number of items across all pages */
108
- totalItems: {
109
- type: Number,
110
- default: 0,
111
- },
112
- /** Current items per page */
113
- currentPageSize: {
114
- type: Number,
115
- default: 20,
116
- },
117
- /** Available page size options */
118
- pageSizeOptions: {
119
- type: Array,
120
- default: () => [
121
- { value: 10, label: '10' },
122
- { value: 20, label: '20' },
123
- { value: 50, label: '50' },
124
- { value: 100, label: '100' },
125
- { value: 250, label: '250' },
126
- { value: 500, label: '500' },
127
- { value: 1000, label: '1000' },
128
- ],
129
- },
130
- /** Minimum items before pagination is shown */
131
- minItemsToShow: {
132
- type: Number,
133
- default: 10,
134
- },
135
- /** Label for "First" button */
136
- firstLabel: {
137
- type: String,
138
- default: 'First',
139
- },
140
- /** Label for "Previous" button */
141
- previousLabel: {
142
- type: String,
143
- default: 'Previous',
144
- },
145
- /** Label for "Next" button */
146
- nextLabel: {
147
- type: String,
148
- default: 'Next',
149
- },
150
- /** Label for "Last" button */
151
- lastLabel: {
152
- type: String,
153
- default: 'Last',
154
- },
155
- /** Label for "Items per page:" */
156
- itemsPerPageLabel: {
157
- type: String,
158
- default: 'Items per page:',
159
- },
160
- /**
161
- * Page info format string. Use {current} and {total} as placeholders.
162
- * @example "Page {current} of {total}"
163
- */
164
- pageInfoFormat: {
165
- type: String,
166
- default: 'Page {current} of {total}',
167
- },
168
- },
169
-
170
- computed: {
171
- pageSizeId() {
172
- return 'cn-page-size-' + this._uid
173
- },
174
-
175
- currentPageSizeOption() {
176
- return this.pageSizeOptions.find(
177
- (option) => option.value === this.currentPageSize,
178
- ) || this.pageSizeOptions[1]
179
- },
180
-
181
- pageInfoText() {
182
- return this.pageInfoFormat
183
- .replace('{current}', this.currentPage)
184
- .replace('{total}', this.totalPages)
185
- },
186
-
187
- /**
188
- * Calculate visible page numbers with ellipsis for large page counts.
189
- * Shows up to 7 page numbers at a time.
190
- */
191
- visiblePages() {
192
- const current = this.currentPage
193
- const total = this.totalPages
194
- const pages = []
195
-
196
- if (total <= 7) {
197
- for (let i = 1; i <= total; i++) {
198
- pages.push(i)
199
- }
200
- } else {
201
- pages.push(1)
202
-
203
- if (current <= 4) {
204
- for (let i = 2; i <= 5; i++) {
205
- pages.push(i)
206
- }
207
- pages.push('...')
208
- pages.push(total)
209
- } else if (current >= total - 3) {
210
- pages.push('...')
211
- for (let i = total - 4; i <= total; i++) {
212
- pages.push(i)
213
- }
214
- } else {
215
- pages.push('...')
216
- for (let i = current - 1; i <= current + 1; i++) {
217
- pages.push(i)
218
- }
219
- pages.push('...')
220
- pages.push(total)
221
- }
222
- }
223
-
224
- return pages
225
- },
226
- },
227
-
228
- methods: {
229
- /**
230
- * Navigate to a specific page.
231
- * @param {number} page Target page number
232
- */
233
- changePage(page) {
234
- if (page !== this.currentPage && page >= 1 && page <= this.totalPages) {
235
- /** @event page-changed Emitted when page changes. Payload: new page number. */
236
- this.$emit('page-changed', page)
237
- }
238
- },
239
-
240
- /**
241
- * Change the page size.
242
- * @param {object} option Selected page size option { value, label }
243
- */
244
- changePageSize(option) {
245
- if (option.value !== this.currentPageSize) {
246
- /** @event page-size-changed Emitted when page size changes. Payload: new page size. */
247
- this.$emit('page-size-changed', option.value)
248
- }
249
- },
250
- },
251
- }
252
- </script>
1
+ <template>
2
+ <div v-if="totalPages > 1 || totalItems > minItemsToShow" class="cn-pagination">
3
+ <!-- Page info -->
4
+ <div class="cn-pagination__info">
5
+ <span class="cn-pagination__page-info">
6
+ {{ pageInfoText }}
7
+ </span>
8
+ </div>
9
+
10
+ <!-- Page navigation -->
11
+ <div v-if="totalPages > 1" class="cn-pagination__nav">
12
+ <NcButton
13
+ :disabled="currentPage === 1"
14
+ @click="changePage(1)">
15
+ {{ firstLabel }}
16
+ </NcButton>
17
+
18
+ <NcButton
19
+ :disabled="currentPage === 1"
20
+ @click="changePage(currentPage - 1)">
21
+ {{ previousLabel }}
22
+ </NcButton>
23
+
24
+ <div class="cn-pagination__numbers">
25
+ <template v-for="page in visiblePages">
26
+ <span v-if="page === '...'" :key="'ellipsis-' + page" class="cn-pagination__ellipsis">...</span>
27
+ <NcButton
28
+ v-else
29
+ :key="page"
30
+ :type="page === currentPage ? 'primary' : 'secondary'"
31
+ :disabled="page === currentPage"
32
+ @click="changePage(page)">
33
+ {{ page }}
34
+ </NcButton>
35
+ </template>
36
+ </div>
37
+
38
+ <NcButton
39
+ :disabled="currentPage === totalPages"
40
+ @click="changePage(currentPage + 1)">
41
+ {{ nextLabel }}
42
+ </NcButton>
43
+
44
+ <NcButton
45
+ :disabled="currentPage === totalPages"
46
+ @click="changePage(totalPages)">
47
+ {{ lastLabel }}
48
+ </NcButton>
49
+ </div>
50
+
51
+ <!-- Page size selector -->
52
+ <div class="cn-pagination__page-size">
53
+ <label :for="pageSizeId">{{ itemsPerPageLabel }}</label>
54
+ <NcSelect
55
+ :input-id="pageSizeId"
56
+ class="cn-pagination__page-size-select"
57
+ :value="currentPageSizeOption"
58
+ :options="pageSizeOptions"
59
+ :clearable="false"
60
+ :input-label="itemsPerPageLabel"
61
+ @option:selected="changePageSize" />
62
+ </div>
63
+ </div>
64
+ </template>
65
+
66
+ <script>
67
+ import { NcButton, NcSelect } from '@nextcloud/vue'
68
+
69
+ /**
70
+ * CnPagination — Full pagination with page numbers, navigation, and page size selector.
71
+ *
72
+ * Extracted from OpenRegister's PaginationComponent. Zero store dependencies.
73
+ * Supports First/Previous/Next/Last buttons, smart page number display with
74
+ * ellipsis, and configurable page size.
75
+ *
76
+ * NL Design tokens used:
77
+ * - Inherits from cn-pagination CSS class (see css/pagination.css)
78
+ *
79
+ * @example
80
+ * <CnPagination
81
+ * :current-page="page"
82
+ * :total-pages="totalPages"
83
+ * :total-items="totalItems"
84
+ * :current-page-size="limit"
85
+ * @page-changed="onPageChange"
86
+ * @page-size-changed="onPageSizeChange" />
87
+ */
88
+ export default {
89
+ name: 'CnPagination',
90
+
91
+ components: {
92
+ NcButton,
93
+ NcSelect,
94
+ },
95
+
96
+ props: {
97
+ /** Current page number (1-based) */
98
+ currentPage: {
99
+ type: Number,
100
+ default: 1,
101
+ },
102
+ /** Total number of pages */
103
+ totalPages: {
104
+ type: Number,
105
+ default: 1,
106
+ },
107
+ /** Total number of items across all pages */
108
+ totalItems: {
109
+ type: Number,
110
+ default: 0,
111
+ },
112
+ /** Current items per page */
113
+ currentPageSize: {
114
+ type: Number,
115
+ default: 20,
116
+ },
117
+ /** Available page size options */
118
+ pageSizeOptions: {
119
+ type: Array,
120
+ default: () => [
121
+ { value: 10, label: '10' },
122
+ { value: 20, label: '20' },
123
+ { value: 50, label: '50' },
124
+ { value: 100, label: '100' },
125
+ { value: 250, label: '250' },
126
+ { value: 500, label: '500' },
127
+ { value: 1000, label: '1000' },
128
+ ],
129
+ },
130
+ /** Minimum items before pagination is shown */
131
+ minItemsToShow: {
132
+ type: Number,
133
+ default: 10,
134
+ },
135
+ /** Label for "First" button */
136
+ firstLabel: {
137
+ type: String,
138
+ default: 'First',
139
+ },
140
+ /** Label for "Previous" button */
141
+ previousLabel: {
142
+ type: String,
143
+ default: 'Previous',
144
+ },
145
+ /** Label for "Next" button */
146
+ nextLabel: {
147
+ type: String,
148
+ default: 'Next',
149
+ },
150
+ /** Label for "Last" button */
151
+ lastLabel: {
152
+ type: String,
153
+ default: 'Last',
154
+ },
155
+ /** Label for "Items per page:" */
156
+ itemsPerPageLabel: {
157
+ type: String,
158
+ default: 'Items per page:',
159
+ },
160
+ /**
161
+ * Page info format string. Use {current} and {total} as placeholders.
162
+ * @example "Page {current} of {total}"
163
+ */
164
+ pageInfoFormat: {
165
+ type: String,
166
+ default: 'Page {current} of {total}',
167
+ },
168
+ },
169
+
170
+ computed: {
171
+ pageSizeId() {
172
+ return 'cn-page-size-' + this._uid
173
+ },
174
+
175
+ currentPageSizeOption() {
176
+ return this.pageSizeOptions.find(
177
+ (option) => option.value === this.currentPageSize,
178
+ ) || this.pageSizeOptions[1]
179
+ },
180
+
181
+ pageInfoText() {
182
+ return this.pageInfoFormat
183
+ .replace('{current}', this.currentPage)
184
+ .replace('{total}', this.totalPages)
185
+ },
186
+
187
+ /**
188
+ * Calculate visible page numbers with ellipsis for large page counts.
189
+ * Shows up to 7 page numbers at a time.
190
+ */
191
+ visiblePages() {
192
+ const current = this.currentPage
193
+ const total = this.totalPages
194
+ const pages = []
195
+
196
+ if (total <= 7) {
197
+ for (let i = 1; i <= total; i++) {
198
+ pages.push(i)
199
+ }
200
+ } else {
201
+ pages.push(1)
202
+
203
+ if (current <= 4) {
204
+ for (let i = 2; i <= 5; i++) {
205
+ pages.push(i)
206
+ }
207
+ pages.push('...')
208
+ pages.push(total)
209
+ } else if (current >= total - 3) {
210
+ pages.push('...')
211
+ for (let i = total - 4; i <= total; i++) {
212
+ pages.push(i)
213
+ }
214
+ } else {
215
+ pages.push('...')
216
+ for (let i = current - 1; i <= current + 1; i++) {
217
+ pages.push(i)
218
+ }
219
+ pages.push('...')
220
+ pages.push(total)
221
+ }
222
+ }
223
+
224
+ return pages
225
+ },
226
+ },
227
+
228
+ methods: {
229
+ /**
230
+ * Navigate to a specific page.
231
+ * @param {number} page Target page number
232
+ */
233
+ changePage(page) {
234
+ if (page !== this.currentPage && page >= 1 && page <= this.totalPages) {
235
+ /** @event page-changed Emitted when page changes. Payload: new page number. */
236
+ this.$emit('page-changed', page)
237
+ }
238
+ },
239
+
240
+ /**
241
+ * Change the page size.
242
+ * @param {object} option Selected page size option { value, label }
243
+ */
244
+ changePageSize(option) {
245
+ if (option.value !== this.currentPageSize) {
246
+ /** @event page-size-changed Emitted when page size changes. Payload: new page size. */
247
+ this.$emit('page-size-changed', option.value)
248
+ }
249
+ },
250
+ },
251
+ }
252
+ </script>
@@ -1 +1 @@
1
- export { default as CnPagination } from './CnPagination.vue'
1
+ export { default as CnPagination } from './CnPagination.vue'