@indielayer/ui 1.0.0-alpha.0 → 1.0.0-alpha.5

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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -72
  3. package/lib/components/avatar/Avatar.vue.d.ts +2 -2
  4. package/lib/components/badge/Badge.vue.d.ts +2 -2
  5. package/lib/components/button/Button.vue.d.ts +2 -2
  6. package/lib/components/button/ButtonGroup.vue.d.ts +2 -2
  7. package/lib/components/checkbox/Checkbox.vue.d.ts +4 -3
  8. package/lib/components/drawer/Drawer.vue.d.ts +2 -2
  9. package/lib/components/icon/Icon.vue.d.ts +7 -3
  10. package/lib/components/index.d.ts +2 -2
  11. package/lib/components/input/Input.vue.d.ts +3 -2
  12. package/lib/components/menu/Menu.vue.d.ts +2 -2
  13. package/lib/components/menu/MenuItem.vue.d.ts +3 -3
  14. package/lib/components/notifications/Notifications.vue.d.ts +2 -2
  15. package/lib/components/pagination/Pagination.vue.d.ts +3 -2
  16. package/lib/components/pagination/PaginationItem.vue.d.ts +2 -2
  17. package/lib/components/radio/Radio.vue.d.ts +2 -2
  18. package/lib/components/select/Select.vue.d.ts +3 -2
  19. package/lib/components/slider/Slider.vue.d.ts +2 -2
  20. package/lib/components/spacer/Spacer.vue.d.ts +1 -1
  21. package/lib/components/spinner/Spinner.vue.d.ts +2 -2
  22. package/lib/components/{tabs → tab}/Tab.vue.d.ts +2 -2
  23. package/lib/components/{tabs/Tabs.vue.d.ts → tab/TabGroup.vue.d.ts} +0 -0
  24. package/lib/components/table/TableBody.vue.d.ts +1 -1
  25. package/lib/components/table/TableHead.vue.d.ts +1 -1
  26. package/lib/components/tag/Tag.vue.d.ts +2 -2
  27. package/lib/components/textarea/Textarea.vue.d.ts +3 -11
  28. package/lib/components/toggle/Toggle.vue.d.ts +2 -2
  29. package/lib/composables/keys.d.ts +1 -0
  30. package/lib/create.d.ts +12 -0
  31. package/lib/index.cjs.js +2 -2
  32. package/lib/index.d.ts +2 -0
  33. package/lib/index.es.js +271 -130
  34. package/lib/install.d.ts +4 -6
  35. package/lib/nuxt.js +15 -16
  36. package/lib/nuxt.plugin.js +8 -0
  37. package/lib/style.css +1 -1
  38. package/lib/version.d.ts +1 -1
  39. package/package.json +21 -15
  40. package/src/components/alert/Alert.vue +164 -0
  41. package/src/components/avatar/Avatar.vue +137 -0
  42. package/src/components/badge/Badge.vue +107 -0
  43. package/src/components/breadcrumbs/Breadcrumbs.vue +60 -0
  44. package/src/components/button/Button.vue +433 -0
  45. package/src/components/button/ButtonGroup.vue +73 -0
  46. package/src/components/card/Card.vue +25 -0
  47. package/src/components/checkbox/Checkbox.vue +205 -0
  48. package/src/components/collapse/Collapse.vue +181 -0
  49. package/src/components/container/Container.vue +23 -0
  50. package/src/components/divider/Divider.vue +52 -0
  51. package/src/components/drawer/Drawer.vue +244 -0
  52. package/src/components/form/Form.vue +111 -0
  53. package/src/components/icon/Icon.vue +123 -0
  54. package/src/components/image/Image.vue +36 -0
  55. package/src/components/index.ts +45 -0
  56. package/src/components/input/Input.vue +199 -0
  57. package/src/components/link/Link.vue +110 -0
  58. package/src/components/menu/Menu.vue +118 -0
  59. package/src/components/menu/MenuItem.vue +277 -0
  60. package/src/components/modal/Modal.vue +175 -0
  61. package/src/components/notifications/Notifications.vue +318 -0
  62. package/src/components/pagination/Pagination.vue +181 -0
  63. package/src/components/pagination/PaginationItem.vue +58 -0
  64. package/src/components/popover/Popover.vue +194 -0
  65. package/src/components/popover/PopoverContainer.vue +23 -0
  66. package/src/components/progress/Progress.vue +86 -0
  67. package/src/components/radio/Radio.vue +220 -0
  68. package/src/components/scroll/Scroll.vue +143 -0
  69. package/src/components/select/Select.vue +408 -0
  70. package/src/components/skeleton/Skeleton.vue +23 -0
  71. package/src/components/slider/Slider.vue +240 -0
  72. package/src/components/spacer/Spacer.vue +11 -0
  73. package/src/components/spinner/Spinner.vue +45 -0
  74. package/src/components/tab/Tab.vue +100 -0
  75. package/src/components/tab/TabGroup.vue +151 -0
  76. package/src/components/table/Table.vue +172 -0
  77. package/src/components/table/TableBody.vue +13 -0
  78. package/src/components/table/TableCell.vue +78 -0
  79. package/src/components/table/TableHead.vue +15 -0
  80. package/src/components/table/TableHeader.vue +94 -0
  81. package/src/components/table/TableRow.vue +43 -0
  82. package/src/components/tag/Tag.vue +98 -0
  83. package/src/components/textarea/Textarea.vue +156 -0
  84. package/src/components/toggle/Toggle.vue +144 -0
  85. package/src/components/tooltip/Tooltip.vue +26 -0
  86. package/src/composables/colors-utils.ts +378 -0
  87. package/src/composables/colors.ts +82 -0
  88. package/src/composables/common.ts +20 -0
  89. package/src/composables/css.ts +45 -0
  90. package/src/composables/index.ts +7 -0
  91. package/src/composables/inputtable.ts +128 -0
  92. package/src/composables/interactive.ts +16 -0
  93. package/src/composables/keys.ts +8 -0
  94. package/src/composables/notification.ts +10 -0
  95. package/src/create.ts +38 -0
  96. package/src/exports/nuxt.js +32 -0
  97. package/src/exports/nuxt.plugin.js +8 -0
  98. package/src/exports/tailwind.preset.js +55 -0
  99. package/src/index.ts +8 -0
  100. package/src/install.ts +8 -0
  101. package/src/shims-vue.d.ts +6 -0
  102. package/src/version.ts +1 -0
  103. package/volar.d.ts +1 -1
@@ -0,0 +1,318 @@
1
+ <script lang="ts">
2
+ import { defineComponent, ref, provide, watch, type PropType } from 'vue'
3
+ import { injectNotificationKey } from '../../composables/keys'
4
+ import { useColors } from '../../composables/colors'
5
+ import { useCSS } from '../../composables/css'
6
+
7
+ import XIcon from '../../components/icon/Icon.vue'
8
+
9
+ const validators = {
10
+ align: ['left','right'],
11
+ position: ['bottom','top'],
12
+ }
13
+
14
+ export type NotificationAlign = 'left' | 'right'
15
+ export type NotificationPosition = 'bottom' | 'top'
16
+ export type NotificationAction = {
17
+ onClick: ()=> void,
18
+ label: string,
19
+ color?: string
20
+ }
21
+ export type NotificationEvent = {
22
+ id?: number,
23
+ icon?: string,
24
+ action?: NotificationAction,
25
+ iconColor?: string,
26
+ title?: string,
27
+ style?: string,
28
+ message?: string,
29
+ timeout?: number,
30
+ removable?: boolean,
31
+ align?: NotificationAlign,
32
+ position?: NotificationPosition
33
+ }
34
+
35
+ export default defineComponent({
36
+ name: 'XNotifications',
37
+
38
+ components: {
39
+ XIcon,
40
+ },
41
+
42
+ validators,
43
+
44
+ props: {
45
+ ...useColors.props('primary'),
46
+ align: {
47
+ type: String as PropType<NotificationAlign>,
48
+ default: 'right',
49
+ validator: (value: string) => validators.align.includes(value),
50
+ },
51
+ position: {
52
+ type: String as PropType<NotificationPosition>,
53
+ default: 'bottom',
54
+ validator: (value: string) => validators.position.includes(value),
55
+ },
56
+ timeout: {
57
+ type: Number,
58
+ default: 3500,
59
+ },
60
+ removable: {
61
+ type: Boolean,
62
+ default: true,
63
+ },
64
+ },
65
+
66
+ expose: ['log', 'info', 'success', 'warn', 'warning', 'error'],
67
+
68
+ setup(props) {
69
+ const internalAlign = ref(props.align)
70
+ const internalPosition = ref(props.position)
71
+ const notifications = ref<NotificationEvent []>([])
72
+ const listRef = ref<HTMLElement | null>(null)
73
+ const css = useCSS('notification')
74
+ const colors = useColors()
75
+
76
+ const removeIcon = '<path d="M6 18L18 6M6 6l12 12" />'
77
+
78
+ provide(injectNotificationKey, {
79
+ log,
80
+ info,
81
+ warn,
82
+ error,
83
+ warning: warn,
84
+ success,
85
+ })
86
+
87
+ watch(() => props.align, (align) => { internalAlign.value = align })
88
+ watch(() => props.position, (position) => { internalPosition.value = position })
89
+
90
+ function log(notification: NotificationEvent | string) {
91
+ const isMessage = typeof notification === 'string'
92
+ const preset = {
93
+ message: isMessage ? notification : undefined,
94
+ }
95
+
96
+ add(isMessage ? preset : {
97
+ ...preset,
98
+ ...notification,
99
+ })
100
+ }
101
+
102
+ function info(notification: NotificationEvent | string) {
103
+ const isMessage = typeof notification === 'string'
104
+ const preset = {
105
+ icon: '<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />',
106
+ iconColor: 'sky',
107
+ message: isMessage ? notification : undefined,
108
+ }
109
+
110
+ add(isMessage ? preset : {
111
+ ...preset,
112
+ ...notification,
113
+ })
114
+ }
115
+
116
+ function success(notification: NotificationEvent | string) {
117
+ const isMessage = typeof notification === 'string'
118
+ const preset = {
119
+ icon: '<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />',
120
+ iconColor: 'success',
121
+ message: isMessage ? notification : undefined,
122
+ }
123
+
124
+ add(isMessage ? preset : {
125
+ ...preset,
126
+ ...notification,
127
+ })
128
+ }
129
+
130
+ function warn(notification: NotificationEvent | string) {
131
+ const isMessage = typeof notification === 'string'
132
+ const preset = {
133
+ icon: '<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />',
134
+ iconColor: 'warning',
135
+ message: isMessage ? notification : undefined,
136
+ }
137
+
138
+ add(isMessage ? preset : {
139
+ ...preset,
140
+ ...notification,
141
+ })
142
+ }
143
+
144
+ function error(notification: NotificationEvent | string) {
145
+ const isMessage = typeof notification === 'string'
146
+ const preset = {
147
+ icon: '<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />',
148
+ iconColor: 'error',
149
+ message: isMessage ? notification : undefined,
150
+ }
151
+
152
+ add(isMessage ? preset : {
153
+ ...preset,
154
+ ...notification,
155
+ })
156
+ }
157
+
158
+ function add(notification: NotificationEvent) {
159
+ const mergeProps = {
160
+ id: Date.now(),
161
+ iconColor: props.color,
162
+ timeout: props.timeout,
163
+ align: internalAlign.value,
164
+ position: internalPosition.value,
165
+ removable: props.removable,
166
+ }
167
+
168
+ const merged = {
169
+ ...mergeProps,
170
+ ...notification,
171
+ }
172
+
173
+ internalAlign.value = merged.align
174
+ internalPosition.value = merged.position
175
+
176
+ const color = colors.getPalette(merged.iconColor)
177
+ const colorAction = colors.getPalette(merged.action?.color || 'primary')
178
+
179
+ const cssVariables = css.variables({
180
+ icon: color[400],
181
+ action: colorAction[400],
182
+ hover: {
183
+ action: colorAction[500],
184
+ },
185
+ dark: {
186
+ icon: color[500],
187
+ action: colorAction[500],
188
+ hover: {
189
+ action: colorAction[600],
190
+ },
191
+ },
192
+ })
193
+
194
+ merged.style = Object.keys(cssVariables).map((key) => `${key}: ${cssVariables[key]}`).join(';')
195
+
196
+ notifications.value.push(merged)
197
+
198
+ listRef.value?.scrollTo({ top: 0, behavior: 'smooth' })
199
+
200
+ if (merged.timeout) setTimer(merged, merged.timeout)
201
+ }
202
+
203
+ function remove(event: NotificationEvent) {
204
+ notifications.value = notifications.value.filter((e) => e.id !== event.id)
205
+ }
206
+
207
+ function setTimer(notification: NotificationEvent, timeout: number) {
208
+ setTimeout(() => {
209
+ remove(notification)
210
+ }, timeout)
211
+ }
212
+
213
+ return {
214
+ notifications,
215
+ listRef,
216
+ remove,
217
+ log,
218
+ info,
219
+ warn,
220
+ error,
221
+ warning: warn,
222
+ success,
223
+ removeIcon,
224
+ internalAlign,
225
+ internalPosition,
226
+ }
227
+ },
228
+
229
+ })
230
+ </script>
231
+
232
+ <template>
233
+ <slot></slot>
234
+ <Teleport to="body">
235
+ <div
236
+ ref="listRef"
237
+ class="fixed z-40 w-full sm:w-auto overflow-y-auto max-h-screen"
238
+ :class="{
239
+ // align
240
+ 'left-0': internalAlign === 'left',
241
+ 'right-0': internalAlign === 'right',
242
+ // position
243
+ 'top-0': internalPosition === 'top',
244
+ 'bottom-0': internalPosition === 'bottom',
245
+ }"
246
+ >
247
+ <transition-group
248
+ tag="ul"
249
+ class="flex flex-col items-end"
250
+ :class="{ 'flex-col-reverse': internalPosition }"
251
+ enter-active-class="transition ease-out duration-200"
252
+ leave-active-class="transition ease-out duration-100"
253
+ enter-class="transform translate-y-2 opacity-0"
254
+ enter-to-class="transform translate-y-0 opacity-100"
255
+ leave-class="transform translate-y-0 opacity-100"
256
+ leave-to-class="transform translate-y-2 opacity-0"
257
+ move-class="ease-in-out duration-200"
258
+ mode="out-in"
259
+ >
260
+ <li
261
+ v-for="notification in notifications"
262
+ :key="notification.id"
263
+ class="w-full sm:w-[520px]"
264
+ :class="[
265
+ 'px-4',
266
+ {
267
+ 'pb-2': internalPosition === 'bottom',
268
+ 'pt-2': internalPosition === 'top',
269
+ }
270
+ ]"
271
+ :style="notification.style"
272
+ >
273
+ <div
274
+ class="flex items-center rounded-md px-4 py-3 bg-gray-800 dark:bg-gray-50 text-white dark:text-gray-900"
275
+ >
276
+ <x-icon
277
+ v-if="notification.icon"
278
+ filled
279
+ :icon="notification.icon"
280
+ class="
281
+ mr-4 shrink-0
282
+ text-[color:var(--x-notification-icon)]
283
+ dark:text-[color:var(--x-dark-notification-icon)]
284
+ "
285
+ viewBox="0 0 20 20"
286
+ />
287
+ <div class="flex items-center flex-wrap">
288
+ <span v-if="notification.title" class="font-semibold mr-2">{{ notification.title }}</span>
289
+ <span>{{ notification.message }}</span>
290
+ </div>
291
+ <x-spacer/>
292
+ <div
293
+ v-if="notification.action"
294
+ class="
295
+ ml-3
296
+ font-semibold
297
+ cursor-pointer
298
+ text-[color:var(--x-notification-action)]
299
+ hover:text-[color:var(--x-notification-action-hover)]
300
+ dark:text-[color:var(--x-dark-notification-action)]
301
+ dark:hover:text-[color:var(--x-dark-notification-action-hover)]
302
+ "
303
+ @click="notification.action.onClick"
304
+ >
305
+ {{ notification.action.label }}
306
+ </div>
307
+ <x-icon
308
+ v-if="notification.removable"
309
+ :icon="removeIcon"
310
+ class="text-gray-400 hover:text-gray-500 ml-3 shrink-0 cursor-pointer"
311
+ @click="() => {remove(notification)}"
312
+ />
313
+ </div>
314
+ </li>
315
+ </transition-group>
316
+ </div>
317
+ </Teleport>
318
+ </template>
@@ -0,0 +1,181 @@
1
+ <script lang="ts">
2
+ import { computed, defineComponent, ref, watch, type PropType } from 'vue'
3
+ import { useCSS } from '../../composables/css'
4
+ import { useCommon } from '../../composables/common'
5
+ import { useColors } from '../../composables/colors'
6
+
7
+ import XIcon from '../../components/icon/Icon.vue'
8
+ import XButton from '../../components/button/Button.vue'
9
+ import XPaginationItem from './PaginationItem.vue'
10
+
11
+ export default defineComponent({
12
+ name: 'XPagination',
13
+
14
+ components: {
15
+ XIcon,
16
+ XButton,
17
+ XPaginationItem,
18
+ },
19
+
20
+ validators: {
21
+ ...useCommon.validators(),
22
+ },
23
+
24
+ props: {
25
+ ...useCommon.props(),
26
+ links: Boolean,
27
+ totalPages: {
28
+ type: Number,
29
+ default: 1,
30
+ },
31
+ modelValue: {
32
+ type: Number,
33
+ default: 1,
34
+ },
35
+ variant: {
36
+ type: String as PropType<'simple' | 'quick' | 'dots'>,
37
+ default: 'simple',
38
+ },
39
+ },
40
+
41
+ emits: ['update:modelValue'],
42
+
43
+ setup(props, { emit }) {
44
+ const pages = computed(() => {
45
+ if (props.totalPages === 3) return [2]
46
+ if (props.totalPages > 2) {
47
+ if (props.modelValue === 1 || props.modelValue === 2) return [2, 3]
48
+ if (props.modelValue === props.totalPages || props.modelValue === props.totalPages - 1) return [props.totalPages - 2, props.totalPages - 1]
49
+
50
+ return [props.modelValue - 1, props.modelValue, props.modelValue + 1]
51
+ }
52
+
53
+ return []
54
+ })
55
+
56
+ const dotsClass = computed(() => {
57
+ if (props.size === 'xs') return 'h-2 w-2'
58
+ else if (props.size === 'sm') return 'h-3 w-3'
59
+ else if (props.size === 'lg') return 'h-4 w-4'
60
+ else if (props.size === 'xl') return 'h-5 w-5'
61
+
62
+ return 'h-3 w-3'
63
+ })
64
+
65
+ const css = useCSS('pagination')
66
+ const colors = useColors()
67
+ const color = colors.getPalette('primary')
68
+ const style = css.get('bg', color[500])
69
+
70
+ const quickInput = ref<string>(props.modelValue + '')
71
+
72
+ function onQuickInput() {
73
+ const number = parseInt(quickInput.value)
74
+
75
+ if (number >= 0 && number <= props.totalPages) {
76
+ emit('update:modelValue', number)
77
+ } else {
78
+ quickInput.value = props.modelValue + ''
79
+ }
80
+ }
81
+
82
+ watch(() => props.modelValue, (value) => {
83
+ quickInput.value = props.modelValue + ''
84
+ })
85
+
86
+ function prevPage() {
87
+ if (props.modelValue > 1) emit('update:modelValue', props.modelValue - 1)
88
+ }
89
+
90
+ function nextPage() {
91
+ if (props.modelValue < props.totalPages) emit('update:modelValue', props.modelValue + 1)
92
+ }
93
+
94
+ const dotsIcon = '<path d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z" />'
95
+ const prevIcon = '<path d="M15 19l-7-7 7-7" />'
96
+ const nextIcon = '<path d="M9 5l7 7-7 7" />'
97
+
98
+ const quickButtonSize = computed(() => {
99
+ if (props.size === 'xs') return 'xs'
100
+ else if (props.size === 'sm') return 'sm'
101
+ else if (props.size === 'lg') return 'md'
102
+ else if (props.size === 'xl') return 'lg'
103
+
104
+ return 'sm'
105
+ })
106
+
107
+ return {
108
+ pages,
109
+ dotsIcon,
110
+ dotsClass,
111
+ prevIcon,
112
+ nextIcon,
113
+ quickInput,
114
+ quickButtonSize,
115
+ style,
116
+ onQuickInput,
117
+ prevPage,
118
+ nextPage,
119
+ }
120
+ },
121
+ })
122
+ </script>
123
+
124
+ <template>
125
+ <ul v-if="variant === 'quick'" class="flex items-center">
126
+ <x-button
127
+ :icon="prevIcon"
128
+ :size="quickButtonSize"
129
+ :disabled="modelValue <= 1"
130
+ @click="prevPage"
131
+ />
132
+ <div class="mx-9 flex items-center">
133
+ <span class="text-gray-600 mr-2">Page</span>
134
+ <x-input v-model="quickInput" :size="size" class="w-[2.75rem] text-center" @keydown.enter="onQuickInput" />
135
+ <span class="text-gray-600 ml-2">of {{ totalPages }}</span>
136
+ </div>
137
+ <x-button
138
+ :icon="nextIcon"
139
+ :size="quickButtonSize"
140
+ :disabled="modelValue >= totalPages"
141
+ @click="nextPage"
142
+ />
143
+ </ul>
144
+ <ul v-else-if="variant === 'simple'" class="flex items-center space-x-2">
145
+ <x-pagination-item
146
+ :value="1"
147
+ :links="links"
148
+ :size="size"
149
+ :selected="modelValue === 1"
150
+ @input="(value: Event) => $emit('update:modelValue', value)"
151
+ />
152
+ <x-icon v-if="totalPages > 3 && modelValue > 3" class="mx-1" :icon="dotsIcon" :size="size"/>
153
+ <x-pagination-item
154
+ v-for="i in pages"
155
+ :key="i"
156
+ :value="i"
157
+ :links="links"
158
+ :size="size"
159
+ :selected="modelValue === i"
160
+ @input="(value: Event) => $emit('update:modelValue', value)"
161
+ />
162
+ <x-icon v-if="totalPages > 3 && modelValue < totalPages - 2" class="mx-1" :icon="dotsIcon" :size="size"/>
163
+ <x-pagination-item
164
+ v-if="totalPages > 1"
165
+ :value="totalPages"
166
+ :links="links"
167
+ :size="size"
168
+ :selected="modelValue === totalPages"
169
+ @input="(value: Event) => $emit('update:modelValue', value)"
170
+ />
171
+ </ul>
172
+ <ul v-else-if="variant === 'dots'" class="flex space-x-6" :style="style">
173
+ <li
174
+ v-for="i in totalPages"
175
+ :key="i"
176
+ class="rounded-full cursor-pointer"
177
+ :class="[dotsClass, i === modelValue ? 'bg-[color:var(--x-pagination-bg)]': 'bg-gray-100 hover:bg-gray-200']"
178
+ @click="$emit('update:modelValue', i)"
179
+ ></li>
180
+ </ul>
181
+ </template>
@@ -0,0 +1,58 @@
1
+ <script lang="ts">
2
+ import { computed, defineComponent } from 'vue'
3
+ import { useCommon } from '../../composables/common'
4
+
5
+ import XButton from '../../components/button/Button.vue'
6
+
7
+ export default defineComponent({
8
+ name: 'XPaginationItem',
9
+
10
+ components: {
11
+ XButton,
12
+ },
13
+
14
+ validators: {
15
+ ...useCommon.validators(),
16
+ },
17
+
18
+ props: {
19
+ ...useCommon.props(),
20
+ value: {
21
+ type: Number,
22
+ default: 0,
23
+ },
24
+ selected: Boolean,
25
+ links: Boolean,
26
+ },
27
+
28
+ emits: ['input'],
29
+
30
+ setup(props) {
31
+ const classes = computed(() => {
32
+ if (props.size === 'xs') return '!leading-none !p-1 min-w-[1.375rem]'
33
+ else if (props.size === 'sm') return '!leading-none !p-2 min-w-[2rem]'
34
+ else if (props.size === 'lg') return '!leading-none !p-3 min-w-[2.75rem]'
35
+ else if (props.size === 'xl') return '!leading-none !p-4 min-w-[3.375rem]'
36
+
37
+ return '!leading-none !p-2 min-w-[2.125rem]'
38
+ })
39
+
40
+ return {
41
+ classes,
42
+ }
43
+ },
44
+ })
45
+ </script>
46
+
47
+ <template>
48
+ <li>
49
+ <x-button
50
+ :to="links ? `?page=${value}` : undefined"
51
+ :size="size"
52
+ :class="classes"
53
+ :outlined="!selected"
54
+ :color="selected ? 'primary' : undefined"
55
+ @click="!selected ? $emit('input', value) : null"
56
+ >{{ value }}</x-button>
57
+ </li>
58
+ </template>