@una-ui/nuxt 0.11.0-beta.1 → 0.12.0-beta.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.
package/README.md CHANGED
@@ -14,6 +14,14 @@
14
14
 
15
15
  Visit https://www.unaui.com for full documentation.
16
16
 
17
+ ## 🌠 Star History
18
+
19
+ <picture>
20
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=una-ui/una-ui&type=Date&theme=dark" />
21
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=una-ui/una-ui&type=Date" />
22
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=una-ui/una-ui&type=Date" />
23
+ </picture>
24
+
17
25
  ## 🌻 Sponsors
18
26
 
19
27
  <p align="center">
package/dist/module.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@una-ui/nuxt",
3
3
  "configKey": "una",
4
- "version": "0.11.0-beta.1",
4
+ "version": "0.12.0-beta.2",
5
5
  "compatibility": {
6
6
  "nuxt": ">=3.0.0"
7
7
  },
8
8
  "builder": {
9
- "@nuxt/module-builder": "0.8.1",
9
+ "@nuxt/module-builder": "0.8.3",
10
10
  "unbuild": "2.0.0"
11
11
  }
12
12
  }
package/dist/module.mjs CHANGED
@@ -7,7 +7,7 @@ import '@una-ui/preset/prefixes';
7
7
  import '@una-ui/extractor-vue-script';
8
8
 
9
9
  const name = "@una-ui/nuxt";
10
- const version = "0.11.0-beta.1";
10
+ const version = "0.12.0-beta.2";
11
11
 
12
12
  const module = defineNuxtModule({
13
13
  meta: {
@@ -76,6 +76,12 @@ const module = defineNuxtModule({
76
76
  global: options.global,
77
77
  watch: nuxt.options.dev
78
78
  });
79
+ addComponentsDir({
80
+ path: resolve(runtimeDir, "components/data", "table"),
81
+ prefix: options.prefix,
82
+ global: options.global,
83
+ watch: nuxt.options.dev
84
+ });
79
85
  if (options.themeable) {
80
86
  addPlugin(resolve(runtimeDir, "plugins", "theme.client"));
81
87
  addPlugin(resolve(runtimeDir, "plugins", "theme.server"));
@@ -0,0 +1,430 @@
1
+ <script setup lang="ts" generic="TData, TValue">
2
+ import type { Ref } from 'vue'
3
+ import { computed, h } from 'vue'
4
+ import type {
5
+ ColumnFiltersState,
6
+ ColumnOrderState,
7
+ ColumnPinningState,
8
+ ExpandedState,
9
+ GroupingState,
10
+ Header,
11
+ PaginationState,
12
+ SortingState,
13
+ VisibilityState,
14
+ } from '@tanstack/vue-table'
15
+
16
+ import {
17
+ FlexRender,
18
+ getCoreRowModel,
19
+ getExpandedRowModel,
20
+ getFilteredRowModel,
21
+ getPaginationRowModel,
22
+ getSortedRowModel,
23
+ useVueTable,
24
+ } from '@tanstack/vue-table'
25
+
26
+ import { cn, pickProps, valueUpdater } from '../../../utils'
27
+
28
+ import Checkbox from '../../forms/Checkbox.vue'
29
+ import Button from '../../elements/Button.vue'
30
+ import Input from '../../forms/Input.vue'
31
+ import type { NTableProps } from '../../../types'
32
+ import TableBody from './TableBody.vue'
33
+ import TableCell from './TableCell.vue'
34
+ import TableEmpty from './TableEmpty.vue'
35
+ import TableFooter from './TableFooter.vue'
36
+ import TableHead from './TableHead.vue'
37
+ import TableHeader from './TableHeader.vue'
38
+ import TableRoot from './TableRoot.vue'
39
+ import TableRow from './TableRow.vue'
40
+ import TableLoading from './TableLoading.vue'
41
+
42
+ const props = withDefaults(defineProps <NTableProps<TData, TValue>>(), {
43
+ enableMultiRowSelection: true,
44
+ })
45
+
46
+ const emit = defineEmits(['select', 'selectAll', 'expand'])
47
+
48
+ const slots = defineSlots()
49
+
50
+ const rowSelection = defineModel<Record<string, boolean>>('modelValue')
51
+ const sorting = defineModel<SortingState>('sorting')
52
+ const columnVisibility = defineModel<VisibilityState>('columnVisibility')
53
+ const columnFilters = defineModel<ColumnFiltersState>('columnFilters')
54
+ const globalFilter = defineModel<string>('globalFilter')
55
+ const columnOrder = defineModel<ColumnOrderState>('columnOrder')
56
+ const columnPinning = defineModel<ColumnPinningState>('columnPinning')
57
+ const expanded = defineModel<ExpandedState>('expanded')
58
+ const grouping = defineModel<GroupingState>('grouping')
59
+ const pagination = defineModel<PaginationState>('pagination', {
60
+ default: () => ({
61
+ pageIndex: 0,
62
+ pageSize: 10,
63
+ }),
64
+ })
65
+
66
+ const columnsWithMisc = computed(() => {
67
+ let data = []
68
+
69
+ // add selection column
70
+ data = props.enableRowSelection
71
+ ? [
72
+ {
73
+ accessorKey: 'selection',
74
+ header: props.enableMultiRowSelection
75
+ ? ({ table }: any) => h(Checkbox, {
76
+ 'modelValue': table.getIsAllPageRowsSelected() ?? false,
77
+ 'onUpdate:modelValue': (value: boolean) => {
78
+ table.toggleAllPageRowsSelected(!!value)
79
+ emit('selectAll', table.getRowModel().rows)
80
+ },
81
+ 'areaLabel': 'Select all rows',
82
+ })
83
+ : '',
84
+ cell: ({ row }: any) => h(Checkbox, {
85
+ 'modelValue': row.getIsSelected() ?? false,
86
+ 'onUpdate:modelValue': (value: boolean) => {
87
+ row.toggleSelected(!!value)
88
+ emit('select', row)
89
+ },
90
+ 'areaLabel': 'Select row',
91
+ }),
92
+ enableSorting: false,
93
+ enableHiding: false,
94
+ },
95
+ ...props.columns,
96
+ ]
97
+ : props.columns
98
+
99
+ // add expanded column
100
+ data = slots.expanded
101
+ ? [
102
+ {
103
+ accessorKey: 'expanded',
104
+ header: '',
105
+ cell: ({ row }: any) => h(Button, {
106
+ size: 'xs',
107
+ icon: true,
108
+ label: 'i-radix-icons-chevron-down',
109
+ onClick: () => {
110
+ row.toggleExpanded()
111
+ emit('expand', row)
112
+ },
113
+ una: {
114
+ btnDefaultVariant: 'btn-ghost-gray btn-square',
115
+ btnIconLabel: cn(
116
+ 'transform transition-transform duration-200',
117
+ row.getIsExpanded() ? '-rotate-180' : 'rotate-0',
118
+ ),
119
+ },
120
+ }),
121
+ enableSorting: false,
122
+ enableHiding: false,
123
+ },
124
+ ...data,
125
+ ]
126
+ : data
127
+
128
+ return data
129
+ })
130
+
131
+ const table = computed(() => {
132
+ return useVueTable({
133
+ get data() {
134
+ return props.data ?? []
135
+ },
136
+ get columns() {
137
+ return columnsWithMisc.value ?? []
138
+ },
139
+ state: {
140
+ get sorting() { return sorting.value },
141
+ get columnFilters() { return columnFilters.value },
142
+ get globalFilter() { return globalFilter.value },
143
+ get rowSelection() { return rowSelection.value },
144
+ get columnVisibility() { return columnVisibility.value },
145
+ get pagination() { return pagination.value },
146
+ get columnOrder() { return columnOrder.value },
147
+ get columnPinning() { return columnPinning.value },
148
+ get expanded() { return expanded.value },
149
+ get grouping() { return grouping.value },
150
+ },
151
+
152
+ enableMultiRowSelection: props.enableMultiRowSelection,
153
+ enableSubRowSelection: props.enableSubRowSelection,
154
+ autoResetAll: props.autoResetAll,
155
+ enableRowSelection: props.enableRowSelection,
156
+ enableColumnFilters: props.enableColumnFilters,
157
+ manualPagination: props.manualPagination,
158
+ manualSorting: props.manualSorting,
159
+ pageCount: props.pageCount,
160
+ rowCount: props.rowCount,
161
+ autoResetPageIndex: props.autoResetPageIndex,
162
+ enableSorting: props.enableSorting,
163
+ enableSortingRemoval: props.enableSortingRemoval,
164
+ enableMultiSort: props.enableMultiSort,
165
+ enableMultiRemove: props.enableMultiRemove,
166
+ maxMultiSortColCount: props.maxMultiSortColCount,
167
+ sortingFns: props.sortingFns,
168
+ isMultiSortEvent: props.isMultiSortEvent,
169
+
170
+ getCoreRowModel: getCoreRowModel(),
171
+ getSortedRowModel: getSortedRowModel(),
172
+ getFilteredRowModel: getFilteredRowModel(),
173
+ getPaginationRowModel: getPaginationRowModel(),
174
+ getRowId: (row: any) => props.rowId ? row[props.rowId] : row.id,
175
+ getExpandedRowModel: getExpandedRowModel(),
176
+
177
+ onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
178
+ onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
179
+ onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
180
+ onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
181
+ onGlobalFilterChange: updaterOrValue => valueUpdater(updaterOrValue, globalFilter),
182
+ onPaginationChange: updaterOrValue => valueUpdater(updaterOrValue, pagination),
183
+ onColumnOrderChange: updaterOrValue => valueUpdater(updaterOrValue, columnOrder),
184
+ onColumnPinningChange: updaterOrValue => valueUpdater(updaterOrValue, columnPinning),
185
+ onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),
186
+ onGroupingChange: updaterOrValue => valueUpdater(updaterOrValue, grouping),
187
+ })
188
+ }) as Ref<ReturnType<typeof useVueTable>>
189
+
190
+ function getHeaderColumnFiltersCount(headers: Header<unknown, unknown>[]) {
191
+ let count = 0
192
+ headers.forEach((header) => {
193
+ if (header.column.columnDef.enableColumnFilter)
194
+ count++
195
+ })
196
+
197
+ return count
198
+ }
199
+
200
+ defineExpose({
201
+ ...table.value,
202
+ })
203
+ </script>
204
+
205
+ <template>
206
+ <TableRoot
207
+ v-bind="pickProps(props, ['class', 'una'])"
208
+ >
209
+ <!-- header -->
210
+ <TableHeader
211
+ :una="una"
212
+ v-bind="props._tableHeader"
213
+ >
214
+ <slot name="header" :table="table">
215
+ <TableRow
216
+ v-for="headerGroup in table.getHeaderGroups()"
217
+ :key="headerGroup.id"
218
+ :una="una"
219
+ v-bind="props._tableRow"
220
+ >
221
+ <!-- headers -->
222
+ <TableHead
223
+ v-for="header in headerGroup.headers"
224
+ :key="header.id"
225
+ :colspan="header.colSpan"
226
+ :data-pinned="header.column.getIsPinned()"
227
+ :una="una"
228
+ v-bind="props._tableHead"
229
+ >
230
+ <Button
231
+ v-if="header.column.columnDef.enableSorting || (header.column.columnDef.enableSorting !== false && enableSorting)"
232
+ btn="ghost-gray"
233
+ size="sm"
234
+ class="font-normal -ml-0.85em"
235
+ :una="{
236
+ btnTrailing: 'text-sm',
237
+ }"
238
+ :trailing="header.column.getIsSorted() === 'asc'
239
+ ? 'i-lucide-arrow-up-wide-narrow' : header.column.getIsSorted() === 'desc'
240
+ ? 'i-lucide-arrow-down-narrow-wide' : 'i-lucide-arrow-up-down'"
241
+ @click="header.column.toggleSorting(
242
+ header.column.getIsSorted() === 'asc' ? undefined : header.column.getIsSorted() !== 'desc',
243
+ enableMultiSort,
244
+ )"
245
+ >
246
+ <slot
247
+ :name="`${header.id}-header`"
248
+ :column="header.column"
249
+ >
250
+ <FlexRender
251
+ v-if="!header.isPlaceholder"
252
+ :render="header.column.columnDef.header"
253
+ :props="header.getContext()"
254
+ />
255
+ </slot>
256
+ </Button>
257
+ <component
258
+ :is="header.id === 'selection' ? 'div' : 'span'"
259
+ v-else
260
+ class="text-sm text-muted"
261
+ >
262
+ <slot
263
+ :name="`${header.id}-header`"
264
+ :column="header.column"
265
+ >
266
+ <FlexRender
267
+ v-if="!header.isPlaceholder"
268
+ :render="header.column.columnDef.header"
269
+ :props="header.getContext()"
270
+ />
271
+ </slot>
272
+ </component>
273
+ </TableHead>
274
+ </TableRow>
275
+
276
+ <!-- column filters -->
277
+ <template
278
+ v-for="headerGroup in table.getHeaderGroups()"
279
+ :key="headerGroup.id"
280
+ >
281
+ <TableRow
282
+ v-if="getHeaderColumnFiltersCount(headerGroup.headers) > 0 || enableColumnFilters"
283
+ data-filter="true"
284
+ :una="una"
285
+ v-bind="props._tableRow"
286
+ >
287
+ <TableHead
288
+ v-for="header in headerGroup.headers"
289
+ :key="header.id"
290
+ :una="una"
291
+ :colspan="header.colSpan"
292
+ :data-pinned="header.column.getIsPinned()"
293
+ v-bind="props._tableHead"
294
+ >
295
+ <slot
296
+ v-if="header.id !== 'selection' && ((header.column.columnDef.enableColumnFilter !== false && enableColumnFilters) || header.column.columnDef.enableColumnFilter)"
297
+ :name="`${header.id}-filter`"
298
+ :column="header.column"
299
+ >
300
+ <Input
301
+ class="w-auto"
302
+ :model-value="header.column.getFilterValue() as string"
303
+ :placeholder="header.column.columnDef.header"
304
+ @update:model-value="header.column.setFilterValue($event)"
305
+ />
306
+ </slot>
307
+ </TableHead>
308
+ </TableRow>
309
+ </template>
310
+ </slot>
311
+
312
+ <TableLoading
313
+ :enabled="props.loading"
314
+ :una="una"
315
+ v-bind="props._tableLoading"
316
+ >
317
+ <slot name="loading" />
318
+ </TableLoading>
319
+ </TableHeader>
320
+
321
+ <!-- body -->
322
+ <TableBody
323
+ :una="una"
324
+ v-bind="props._tableBody"
325
+ >
326
+ <slot name="body" :table="table">
327
+ <template v-if="table.getRowModel().rows?.length">
328
+ <template
329
+ v-for="row in table.getRowModel().rows"
330
+ :key="row.id"
331
+ >
332
+ <TableRow
333
+ :data-state="row.getIsSelected() && 'selected'"
334
+ :una="una"
335
+ v-bind="props._tableRow"
336
+ >
337
+ <slot
338
+ name="row"
339
+ :row="row"
340
+ >
341
+ <!-- rows -->
342
+ <TableCell
343
+ v-for="cell in row.getVisibleCells()"
344
+ :key="cell.id"
345
+ :data-pinned="cell.column.getIsPinned()"
346
+ :una="una"
347
+ v-bind="props._tableCell"
348
+ >
349
+ <slot
350
+ :name="`${cell.column.id}-cell`"
351
+ :cell="cell"
352
+ >
353
+ <FlexRender
354
+ :render="cell.column.columnDef.cell"
355
+ :props="cell.getContext()"
356
+ />
357
+ </slot>
358
+ </TableCell>
359
+ </slot>
360
+ </TableRow>
361
+
362
+ <!-- expanded -->
363
+ <TableRow
364
+ v-if="row.getIsExpanded() && $slots.expanded"
365
+ :una="una"
366
+ v-bind="props._tableRow"
367
+ >
368
+ <TableCell
369
+ :colspan="row.getAllCells().length"
370
+ :una="una"
371
+ v-bind="props._tableCell"
372
+ >
373
+ <slot name="expanded" :row="row" />
374
+ </TableCell>
375
+ </TableRow>
376
+ </template>
377
+ </template>
378
+
379
+ <TableEmpty
380
+ v-else
381
+ :colspan="table.getAllLeafColumns().length"
382
+ :una="una"
383
+ v-bind="props._tableEmpty"
384
+ >
385
+ <slot name="empty" />
386
+ </TableEmpty>
387
+ </slot>
388
+ </TableBody>
389
+
390
+ <!-- footer -->
391
+ <TableFooter
392
+ v-if="table.getFooterGroups().length > 0"
393
+ :una="una"
394
+ v-bind="props._tableFooter"
395
+ >
396
+ <slot name="footer" :table="table">
397
+ <template
398
+ v-for="footerGroup in table.getFooterGroups()"
399
+ :key="footerGroup.id"
400
+ >
401
+ <TableRow
402
+ v-if="footerGroup.headers.length > 0"
403
+ :una="una"
404
+ v-bind="props._tableRow"
405
+ >
406
+ <template
407
+ v-for="header in footerGroup.headers"
408
+ :key="header.id"
409
+ >
410
+ <TableHead
411
+ v-if="header.column.columnDef.footer"
412
+ :colspan="header.colSpan"
413
+ :una="una"
414
+ v-bind="props._tableHead"
415
+ >
416
+ <slot :name="`${header.id}-footer`" :column="header.column">
417
+ <FlexRender
418
+ v-if="!header.isPlaceholder"
419
+ :render="header.column.columnDef.footer"
420
+ :props="header.getContext()"
421
+ />
422
+ </slot>
423
+ </TableHead>
424
+ </template>
425
+ </TableRow>
426
+ </template>
427
+ </slot>
428
+ </TableFooter>
429
+ </TableRoot>
430
+ </template>.
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableBodyProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableBodyProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <tbody
10
+ :class="cn(
11
+ 'table-body',
12
+ props.class,
13
+ props?.una?.tableBody,
14
+ )"
15
+ v-bind="$attrs"
16
+ >
17
+ <slot />
18
+ </tbody>
19
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableCaptionProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableCaptionProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <caption
10
+ :class="cn(
11
+ 'table-caption',
12
+ props.class,
13
+ props?.una?.tableCaption,
14
+ )"
15
+ v-bind="$attrs"
16
+ >
17
+ <slot />
18
+ </caption>
19
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableCellProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableCellProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <td
10
+ :class="
11
+ cn(
12
+ 'table-cell',
13
+ { 'table-cell-pinned': dataPinned },
14
+ dataPinned === 'left' ? 'table-cell-pinned-left' : 'table-cell-pinned-right',
15
+ props.class,
16
+ props?.una?.tableCell,
17
+ )
18
+ "
19
+ v-bind="$attrs"
20
+ >
21
+ <slot />
22
+ </td>
23
+ </template>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { cn, omitProps } from '../../../utils'
4
+ import type { NTableEmptyProps } from '../../../types'
5
+ import TableRow from './TableRow.vue'
6
+ import TableCell from './TableCell.vue'
7
+
8
+ const props = withDefaults(defineProps<NTableEmptyProps>(), {
9
+ colspan: 1,
10
+ })
11
+
12
+ const delegatedProps = computed(() => {
13
+ const { class: _, ...delegated } = props
14
+
15
+ return delegated
16
+ })
17
+ </script>
18
+
19
+ <template>
20
+ <TableRow
21
+ :class="cn(
22
+ 'table-empty-row',
23
+ )"
24
+ v-bind="delegatedProps._tableRow"
25
+ >
26
+ <TableCell
27
+ :class="
28
+ cn(
29
+ 'table-empty-cell',
30
+ )
31
+ "
32
+ :colspan="props.colspan"
33
+ v-bind="delegatedProps._tableCell"
34
+ >
35
+ <div
36
+ :class="cn(
37
+ 'table-empty',
38
+ props.class,
39
+ )"
40
+ v-bind="omitProps(delegatedProps, ['_tableRow', '_tableCell', 'colspan'])"
41
+ >
42
+ <slot>
43
+ <div class="grid place-items-center gap-4">
44
+ <NIcon
45
+ name="i-tabler-database-x"
46
+ size="2xl"
47
+ />
48
+
49
+ <span>
50
+ No results.
51
+ </span>
52
+ </div>
53
+ </slot>
54
+ </div>
55
+ </TableCell>
56
+ </TableRow>
57
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import type { NTableFooterProps } from '../../../types'
3
+ import { cn } from '../../../utils'
4
+
5
+ const props = defineProps<NTableFooterProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <tfoot
10
+ :class="cn(
11
+ 'table-footer',
12
+ props.class,
13
+ props.una?.tableFooter,
14
+ )"
15
+ >
16
+ <slot />
17
+ </tfoot>
18
+ </template>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableHeadProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableHeadProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <th
10
+ :class="cn(
11
+ 'table-head',
12
+ props.class,
13
+ { 'table-head-pinned': props.dataPinned },
14
+ props.dataPinned === 'left' ? 'table-head-pinned-left' : 'table-head-pinned-right',
15
+ )"
16
+ v-bind="$attrs"
17
+ >
18
+ <slot />
19
+ </th>
20
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableHeaderProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableHeaderProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <thead
10
+ :class="cn(
11
+ 'table-header',
12
+ props.class,
13
+ props?.una?.tableHeader,
14
+ )"
15
+ v-bind="$attrs"
16
+ >
17
+ <slot />
18
+ </thead>
19
+ </template>
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { cn } from '../../../utils'
4
+ import type { NTableLoadingProps } from '../../../types'
5
+ import Progress from '../../elements/Progress.vue'
6
+ import TableRow from './TableRow.vue'
7
+
8
+ const props = withDefaults(defineProps<NTableLoadingProps>(), {
9
+ })
10
+
11
+ const delegatedProps = computed(() => {
12
+ const { class: _, ...delegated } = props
13
+
14
+ return delegated
15
+ })
16
+ </script>
17
+
18
+ <template>
19
+ <TableRow
20
+ :class="cn(
21
+ 'table-loading-row',
22
+ )"
23
+ data-loading="true"
24
+ v-bind="delegatedProps._tableRow"
25
+ >
26
+ <td
27
+ :class="
28
+ cn(
29
+ 'table-loading-cell',
30
+ )
31
+ "
32
+ :colspan="0"
33
+ v-bind="delegatedProps._tableCell"
34
+ >
35
+ <div
36
+ v-if="enabled"
37
+ class="table-loading"
38
+ >
39
+ <slot>
40
+ <Progress
41
+ size="3px"
42
+ />
43
+ </slot>
44
+ </div>
45
+ </td>
46
+ </TableRow>
47
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableRootProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableRootProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <div
10
+ :class="cn('table-root-wrapper', props.una?.tableRootWrapper)"
11
+ >
12
+ <table
13
+ :class="cn(
14
+ 'table-root',
15
+ props.class,
16
+ props.una?.tableRoot,
17
+ )"
18
+ >
19
+ <slot />
20
+ </table>
21
+ </div>
22
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '../../../utils'
3
+ import type { NTableRowProps } from '../../../types'
4
+
5
+ const props = defineProps<NTableRowProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <tr
10
+ :class="cn(
11
+ 'table-row',
12
+ props.class,
13
+ props.una?.tableRow,
14
+ )"
15
+ v-bind="$attrs"
16
+ >
17
+ <slot />
18
+ </tr>
19
+ </template>
@@ -103,19 +103,19 @@ const isBaseVariant = computed(() => props.btn?.includes('~'))
103
103
  v-slot="{ open, close }"
104
104
  as="div"
105
105
  accordion="item"
106
- :default-open="item.defaultOpen ?? defaultOpen"
106
+ :default-open="item.defaultOpen || defaultOpen"
107
107
  :class="una?.accordionItem"
108
108
  >
109
109
  <DisclosureButton
110
110
  :ref="() => (buttonRefs[i] = close)"
111
111
  as="template"
112
- :disabled="item.disabled ?? disabled"
112
+ :disabled="item.disabled || disabled"
113
113
  @click="closeOthers(i)"
114
114
  >
115
115
  <slot name="label" :item="item" :index="i" :open="open" :close="close">
116
116
  <NButton
117
117
  v-bind="mergedProps(item)"
118
- :btn="`~ block ${btn ?? ''}`"
118
+ :btn="`~ block ${btn || ''}`"
119
119
  :class="[
120
120
  { 'accordion-button-default-variant': !hasVariant && !isBaseVariant },
121
121
  { 'accordion-button-padding': !unstyle },
@@ -132,7 +132,7 @@ const isBaseVariant = computed(() => props.btn?.includes('~'))
132
132
  v-if="leading || item.leading"
133
133
  accordion="leading"
134
134
  :class="una?.accordionLeading"
135
- :name="item.leading ?? leading ?? ''"
135
+ :name="item.leading || leading || ''"
136
136
  aria-hidden="true"
137
137
  />
138
138
  </template>
@@ -143,8 +143,8 @@ const isBaseVariant = computed(() => props.btn?.includes('~'))
143
143
  accordion="trailing"
144
144
  :class="[
145
145
  trailingClose || (!trailingClose && open)
146
- ? una?.accordionTrailingClose ?? 'accordion-trailing-close'
147
- : una?.accordionTrailingOpen ?? 'accordion-trailing-open',
146
+ ? una?.accordionTrailingClose || 'accordion-trailing-close'
147
+ : una?.accordionTrailingOpen || 'accordion-trailing-open',
148
148
  una?.accordionTrailing,
149
149
  ]"
150
150
  >
@@ -165,14 +165,14 @@ const isBaseVariant = computed(() => props.btn?.includes('~'))
165
165
  </DisclosureButton>
166
166
 
167
167
  <Transition
168
- :enter-active-class="una?.accordionLeaveActive ?? 'accordion-leave-active'"
169
- :leave-active-class="una?.accordionEnterActive ?? 'accordion-enter-active'"
168
+ :enter-active-class="una?.accordionLeaveActive || 'accordion-leave-active'"
169
+ :leave-active-class="una?.accordionEnterActive || 'accordion-enter-active'"
170
170
  @enter="onEnter"
171
171
  @after-enter="onAfterEnter"
172
172
  @before-leave="onBeforeLeave"
173
173
  @leave="onLeave"
174
174
  >
175
- <DisclosurePanel v-if="!item.mounted ?? !mounted">
175
+ <DisclosurePanel v-if="!item.mounted || !mounted">
176
176
  <ReuseTemplate
177
177
  v-bind="{
178
178
  item,
@@ -10,7 +10,6 @@ import type { NProgressProps } from '../../types'
10
10
  const props = withDefaults(
11
11
  defineProps<NProgressProps>(),
12
12
  {
13
- modelValue: 0,
14
13
  },
15
14
  )
16
15
 
@@ -34,12 +33,33 @@ const delegatedProps = computed(() => {
34
33
  >
35
34
  <slot>
36
35
  <ProgressIndicator
36
+ v-if="props.modelValue !== undefined || props.modelValue === null"
37
37
  :class="cn(
38
38
  'progress-indicator',
39
39
  props.una?.progressIndicator,
40
40
  )"
41
41
  :style="`transform: translateX(-${100 - (props.modelValue ?? 0)}%);`"
42
42
  />
43
+ <template
44
+ v-else
45
+ >
46
+ <ProgressIndicator
47
+ :class="cn(
48
+ 'progress increase progress-indeterminate',
49
+ props.una?.progressIndicator,
50
+ )"
51
+ />
52
+ <ProgressIndicator
53
+ :class="cn(
54
+ 'progress decrease progress-indeterminate',
55
+ props.una?.progressIndicator,
56
+ )"
57
+ />
58
+ </template>
43
59
  </slot>
44
60
  </ProgressRoot>
45
61
  </template>
62
+
63
+ <style scoped>
64
+ .increase.progress-indeterminate{animation:progress-increase 2s ease-in-out infinite}.decrease.progress-indeterminate{animation:progress-indeterminate-decrease 2s ease-in-out .9s infinite}@keyframes progress-decrease{0%{left:-90%;width:90%}to{left:110%;width:10%}}@keyframes progress-increase{0%{left:-5%;width:5%}to{left:130%;width:150%}}
65
+ </style>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { computed, watch } from 'vue'
2
3
  import { useVModel } from '@vueuse/core'
3
- import { computed } from 'vue'
4
4
  import NIcon from '../elements/Icon.vue'
5
5
  import { randomId } from '../../utils'
6
6
  import type { NCheckboxProps } from '../../types/checkbox'
@@ -14,11 +14,9 @@ const props = withDefaults(
14
14
  {
15
15
  modelValue: false,
16
16
  disabled: false,
17
- una: () => ({
18
- checkboxIcon: 'checkbox-icon',
19
- }),
20
17
  },
21
18
  )
19
+
22
20
  const emit = defineEmits<{ (...args: any): void }>()
23
21
 
24
22
  const slots = defineSlots<{
@@ -27,13 +25,17 @@ const slots = defineSlots<{
27
25
  }>()
28
26
 
29
27
  const id = computed(() => props.id ?? randomId('checkbox'))
30
-
31
28
  const checked = useVModel(props, 'modelValue', emit, { passive: true })
29
+
30
+ watch(checked, (value) => {
31
+ emit('onUpdate', value)
32
+ })
32
33
  </script>
33
34
 
34
35
  <template>
35
36
  <label
36
37
  checkbox="wrapper"
38
+ role="checkbox"
37
39
  :for="props.for ?? id"
38
40
  :class="[
39
41
  una?.checkboxWrapper,
@@ -47,13 +49,15 @@ const checked = useVModel(props, 'modelValue', emit, { passive: true })
47
49
  >
48
50
  <input
49
51
  :id="id"
50
- v-model="checked"
52
+ :value="checked"
53
+ :checked="!!checked"
51
54
  type="checkbox"
52
55
  class="peer"
53
56
  checkbox="input"
54
57
  :disabled="disabled"
55
58
  :name="name"
56
59
  @keypress.enter="checked = !checked"
60
+ @click="checked = !checked"
57
61
  >
58
62
  <span
59
63
  :checkbox="checkbox"
@@ -64,10 +68,8 @@ const checked = useVModel(props, 'modelValue', emit, { passive: true })
64
68
  <slot name="icon">
65
69
  <NIcon
66
70
  checkbox="icon-base icon-checked"
67
- :name="una.checkboxIcon!"
68
- :class="[
69
- una.checkboxIconBase,
70
- ]"
71
+ :name="una?.checkboxIcon ?? 'checkbox-icon'"
72
+ :class="una?.checkboxIconBase"
71
73
  />
72
74
  </slot>
73
75
  </span>
@@ -22,6 +22,7 @@ export * from './tabs.js';
22
22
  export * from './select.js';
23
23
  export * from './separator.js';
24
24
  export * from './card.js';
25
+ export * from './table.js';
25
26
  export interface Colors {
26
27
  [key: string]: string;
27
28
  }
@@ -22,3 +22,4 @@ export * from "./tabs.js";
22
22
  export * from "./select.js";
23
23
  export * from "./separator.js";
24
24
  export * from "./card.js";
25
+ export * from "./table.js";
@@ -0,0 +1,167 @@
1
+ import type { HTMLAttributes } from 'vue';
2
+ import type { ColumnDef, GroupColumnDef } from '@tanstack/vue-table';
3
+ export interface NTableProps<TData, TValue> extends NTableRootProps {
4
+ /**
5
+ * @see https://tanstack.com/table/latest/docs/guide/data
6
+ */
7
+ data: TData[];
8
+ /**
9
+ * @see https://tanstack.com/table/latest/docs/api/core/column
10
+ */
11
+ columns: ColumnDef<TData, TValue>[] | GroupColumnDef<TData, TValue>[];
12
+ /**
13
+ * @see https://tanstack.com/table/latest/docs/api/core/table#getrowid
14
+ */
15
+ rowId?: string;
16
+ /**
17
+ * @see https://tanstack.com/table/latest/docs/api/core/table#autoresetall
18
+ */
19
+ autoResetAll?: boolean;
20
+ /**
21
+ * @see https://tanstack.com/table/latest/docs/api/features/row-selection#enablerowselection
22
+ */
23
+ enableRowSelection?: boolean;
24
+ /**
25
+ * @see https://tanstack.com/table/latest/docs/api/features/row-selection#enablemultirowselection
26
+ */
27
+ enableMultiRowSelection?: boolean;
28
+ /**
29
+ * @see https://tanstack.com/table/latest/docs/api/features/row-selection#enablesubrowselection
30
+ */
31
+ enableSubRowSelection?: boolean;
32
+ /**
33
+ * @see https://tanstack.com/table/latest/docs/api/features/column-filtering#enablecolumnfilters
34
+ */
35
+ enableColumnFilters?: boolean;
36
+ /**
37
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#enablesorting
38
+ */
39
+ enableSorting?: boolean;
40
+ /**
41
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#enablemultisort
42
+ */
43
+ enableMultiSort?: boolean;
44
+ /**
45
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#enablemultiremove
46
+ */
47
+ enableMultiRemove?: boolean;
48
+ /**
49
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#enablesortingremoval
50
+ */
51
+ enableSortingRemoval?: boolean;
52
+ /**
53
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#manualsorting
54
+ */
55
+ manualSorting?: boolean;
56
+ /**
57
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#maxmultisortcolcount
58
+ */
59
+ maxMultiSortColCount?: number;
60
+ /**
61
+ * @see https://tanstack.com/table/latest/docs/api/features/pagination#manualpagination
62
+ */
63
+ manualPagination?: boolean;
64
+ /**
65
+ * @see https://tanstack.com/table/latest/docs/api/features/pagination#pagecount
66
+ */
67
+ pageCount?: number;
68
+ /**
69
+ * @see https://tanstack.com/table/latest/docs/api/features/pagination#rowcount
70
+ */
71
+ rowCount?: number;
72
+ /**
73
+ * @see https://tanstack.com/table/latest/docs/api/features/pagination#autoresetpageindex
74
+ */
75
+ autoResetPageIndex?: boolean;
76
+ /**
77
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#sortingfns
78
+ */
79
+ sortingFns?: Record<string, (a: any, b: any) => number>;
80
+ /**
81
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#sortdescfirst-1
82
+ */
83
+ sortDescFirst?: boolean;
84
+ /**
85
+ * @see https://tanstack.com/table/latest/docs/api/features/sorting#ismultisortevent
86
+ */
87
+ isMultiSortEvent?: (e: unknown) => boolean;
88
+ _tableHead?: NTableHeadProps;
89
+ _tableHeader?: NTableHeaderProps;
90
+ _tableFooter?: NTableFooterProps;
91
+ _tableBody?: NTableBodyProps;
92
+ _tableCaption?: NTableCaptionProps;
93
+ _tableRow?: NTableRowProps;
94
+ _tableCell?: NTableCellProps;
95
+ _tableEmpty?: NTableEmptyProps;
96
+ _tableLoading?: NTableLoadingProps;
97
+ loading?: boolean;
98
+ /**
99
+ * `UnaUI` preset configuration
100
+ *
101
+ * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/table.ts
102
+ */
103
+ una?: NTableUnaProps;
104
+ }
105
+ export interface NTableRootProps {
106
+ class?: HTMLAttributes['class'];
107
+ una?: Pick<NTableUnaProps, 'tableRoot' | 'tableRootWrapper'>;
108
+ }
109
+ export interface NTableBodyProps {
110
+ class?: HTMLAttributes['class'];
111
+ una?: Pick<NTableUnaProps, 'tableBody'>;
112
+ }
113
+ export interface NTableHeadProps {
114
+ class?: HTMLAttributes['class'];
115
+ dataPinned?: 'left' | 'right' | false;
116
+ una?: Pick<NTableUnaProps, 'tableHead'>;
117
+ }
118
+ export interface NTableHeaderProps {
119
+ class?: HTMLAttributes['class'];
120
+ una?: Pick<NTableUnaProps, 'tableHeader'>;
121
+ }
122
+ export interface NTableFooterProps {
123
+ class?: HTMLAttributes['class'];
124
+ una?: Pick<NTableUnaProps, 'tableFooter'>;
125
+ }
126
+ export interface NTableRowProps {
127
+ class?: HTMLAttributes['class'];
128
+ una?: Pick<NTableUnaProps, 'tableRow'>;
129
+ }
130
+ export interface NTableCellProps {
131
+ class?: HTMLAttributes['class'];
132
+ dataPinned?: 'left' | 'right' | false;
133
+ una?: Pick<NTableUnaProps, 'tableCell'>;
134
+ }
135
+ export interface NTableEmptyProps {
136
+ class?: HTMLAttributes['class'];
137
+ colspan?: number;
138
+ _tableCell?: NTableCellProps;
139
+ _tableRow?: NTableRowProps;
140
+ una?: Pick<NTableUnaProps, 'tableEmpty'>;
141
+ }
142
+ export interface NTableLoadingProps {
143
+ enabled?: boolean;
144
+ class?: HTMLAttributes['class'];
145
+ colspan?: number;
146
+ _tableCell?: NTableCellProps;
147
+ _tableRow?: NTableRowProps;
148
+ una?: Pick<NTableUnaProps, 'tableLoading'>;
149
+ }
150
+ export interface NTableCaptionProps {
151
+ class?: HTMLAttributes['class'];
152
+ una?: Pick<NTableUnaProps, 'tableCaption'>;
153
+ }
154
+ interface NTableUnaProps {
155
+ tableRoot?: HTMLAttributes['class'];
156
+ tableRootWrapper?: HTMLAttributes['class'];
157
+ tableBody?: HTMLAttributes['class'];
158
+ tableHead?: HTMLAttributes['class'];
159
+ tableHeader?: HTMLAttributes['class'];
160
+ tableFooter?: HTMLAttributes['class'];
161
+ tableRow?: HTMLAttributes['class'];
162
+ tableCell?: HTMLAttributes['class'];
163
+ tableCaption?: HTMLAttributes['class'];
164
+ tableEmpty?: HTMLAttributes['class'];
165
+ tableLoading?: HTMLAttributes['class'];
166
+ }
167
+ export {};
File without changes
@@ -1,2 +1,5 @@
1
1
  import { type ClassValue } from 'clsx';
2
+ import type { Updater } from '@tanstack/vue-table';
3
+ import type { Ref } from 'vue';
2
4
  export declare function cn(...inputs: ClassValue[]): string;
5
+ export declare function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref): void;
@@ -3,3 +3,6 @@ import { twMerge } from "tailwind-merge";
3
3
  export function cn(...inputs) {
4
4
  return twMerge(clsx(inputs));
5
5
  }
6
+ export function valueUpdater(updaterOrValue, ref) {
7
+ ref.value = typeof updaterOrValue === "function" ? updaterOrValue(ref.value) : updaterOrValue;
8
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@una-ui/nuxt",
3
3
  "type": "module",
4
- "version": "0.11.0-beta.1",
4
+ "version": "0.12.0-beta.2",
5
5
  "description": "Nuxt module for @una-ui",
6
6
  "author": "Phojie Rengel <phojrengel@gmail.com>",
7
7
  "license": "MIT",
@@ -34,6 +34,7 @@
34
34
  "@iconify-json/tabler": "^1.1.120",
35
35
  "@nuxt/kit": "^3.12.4",
36
36
  "@nuxtjs/color-mode": "^3.4.2",
37
+ "@tanstack/vue-table": "^8.20.4",
37
38
  "@unocss/core": "^0.61.9",
38
39
  "@unocss/nuxt": "^0.61.9",
39
40
  "@unocss/preset-attributify": "^0.61.9",
@@ -47,8 +48,8 @@
47
48
  "tailwind-merge": "^2.5.1",
48
49
  "unocss": "^0.61.9",
49
50
  "unocss-preset-animations": "^1.1.0",
50
- "@una-ui/extractor-vue-script": "^0.11.0-beta.1",
51
- "@una-ui/preset": "^0.11.0-beta.1"
51
+ "@una-ui/extractor-vue-script": "^0.12.0-beta.2",
52
+ "@una-ui/preset": "^0.12.0-beta.2"
52
53
  },
53
54
  "devDependencies": {
54
55
  "@nuxt/module-builder": "^0.8.1",
@@ -30,6 +30,7 @@ interface _GlobalComponents {
30
30
  'NSeparator': typeof import("../../src/runtime/components/elements/Separator.vue")['default']
31
31
  'NSkeleton': typeof import("../../src/runtime/components/elements/Skeleton.vue")['default']
32
32
  'NCard': typeof import("../../src/runtime/components/elements/card/Card.vue")['default']
33
+ 'NCardAbout': typeof import("../../src/runtime/components/elements/card/CardAbout.vue")['default']
33
34
  'NCardContent': typeof import("../../src/runtime/components/elements/card/CardContent.vue")['default']
34
35
  'NCardDescription': typeof import("../../src/runtime/components/elements/card/CardDescription.vue")['default']
35
36
  'NCardFooter': typeof import("../../src/runtime/components/elements/card/CardFooter.vue")['default']
@@ -412,6 +413,7 @@ interface _GlobalComponents {
412
413
  'LazyNSeparator': typeof import("../../src/runtime/components/elements/Separator.vue")['default']
413
414
  'LazyNSkeleton': typeof import("../../src/runtime/components/elements/Skeleton.vue")['default']
414
415
  'LazyNCard': typeof import("../../src/runtime/components/elements/card/Card.vue")['default']
416
+ 'LazyNCardAbout': typeof import("../../src/runtime/components/elements/card/CardAbout.vue")['default']
415
417
  'LazyNCardContent': typeof import("../../src/runtime/components/elements/card/CardContent.vue")['default']
416
418
  'LazyNCardDescription': typeof import("../../src/runtime/components/elements/card/CardDescription.vue")['default']
417
419
  'LazyNCardFooter': typeof import("../../src/runtime/components/elements/card/CardFooter.vue")['default']
@@ -808,6 +810,7 @@ export const NProgress: typeof import("../../src/runtime/components/elements/Pro
808
810
  export const NSeparator: typeof import("../../src/runtime/components/elements/Separator.vue")['default']
809
811
  export const NSkeleton: typeof import("../../src/runtime/components/elements/Skeleton.vue")['default']
810
812
  export const NCard: typeof import("../../src/runtime/components/elements/card/Card.vue")['default']
813
+ export const NCardAbout: typeof import("../../src/runtime/components/elements/card/CardAbout.vue")['default']
811
814
  export const NCardContent: typeof import("../../src/runtime/components/elements/card/CardContent.vue")['default']
812
815
  export const NCardDescription: typeof import("../../src/runtime/components/elements/card/CardDescription.vue")['default']
813
816
  export const NCardFooter: typeof import("../../src/runtime/components/elements/card/CardFooter.vue")['default']
@@ -1190,6 +1193,7 @@ export const LazyNProgress: typeof import("../../src/runtime/components/elements
1190
1193
  export const LazyNSeparator: typeof import("../../src/runtime/components/elements/Separator.vue")['default']
1191
1194
  export const LazyNSkeleton: typeof import("../../src/runtime/components/elements/Skeleton.vue")['default']
1192
1195
  export const LazyNCard: typeof import("../../src/runtime/components/elements/card/Card.vue")['default']
1196
+ export const LazyNCardAbout: typeof import("../../src/runtime/components/elements/card/CardAbout.vue")['default']
1193
1197
  export const LazyNCardContent: typeof import("../../src/runtime/components/elements/card/CardContent.vue")['default']
1194
1198
  export const LazyNCardDescription: typeof import("../../src/runtime/components/elements/card/CardDescription.vue")['default']
1195
1199
  export const LazyNCardFooter: typeof import("../../src/runtime/components/elements/card/CardFooter.vue")['default']