@dolanske/vui 1.4.1 → 1.4.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.
Files changed (140) hide show
  1. package/package.json +1 -2
  2. package/src/App.vue +0 -103
  3. package/src/components/Accordion/Accordion.vue +0 -98
  4. package/src/components/Accordion/AccordionGroup.vue +0 -49
  5. package/src/components/Accordion/accordion.scss +0 -97
  6. package/src/components/Alert/Alert.vue +0 -59
  7. package/src/components/Alert/alert.scss +0 -162
  8. package/src/components/Avatar/Avatar.vue +0 -53
  9. package/src/components/Avatar/avatar.scss +0 -52
  10. package/src/components/Badge/Badge.vue +0 -21
  11. package/src/components/Badge/badge.scss +0 -210
  12. package/src/components/Breadcrumbs/BreadcrumbItem.vue +0 -26
  13. package/src/components/Breadcrumbs/Breadcrumbs.vue +0 -29
  14. package/src/components/Breadcrumbs/breadcrumbs.scss +0 -31
  15. package/src/components/Button/Button.vue +0 -86
  16. package/src/components/Button/button.scss +0 -292
  17. package/src/components/ButtonGroup/ButtonGroup.vue +0 -28
  18. package/src/components/ButtonGroup/button-group.scss +0 -51
  19. package/src/components/Calendar/Calendar.vue +0 -66
  20. package/src/components/Calendar/calendar.scss +0 -88
  21. package/src/components/Card/Card.vue +0 -48
  22. package/src/components/Card/card.scss +0 -55
  23. package/src/components/Checkbox/Checkbox.vue +0 -54
  24. package/src/components/Checkbox/checkbox.scss +0 -80
  25. package/src/components/CopyClipboard/CopyClipboard.vue +0 -98
  26. package/src/components/CopyClipboard/copy-clipboard.scss +0 -25
  27. package/src/components/Divider/Divider.vue +0 -38
  28. package/src/components/Divider/divider.scss +0 -37
  29. package/src/components/Drawer/Drawer.vue +0 -102
  30. package/src/components/Drawer/drawer.scss +0 -37
  31. package/src/components/Dropdown/Dropdown.vue +0 -120
  32. package/src/components/Dropdown/DropdownItem.vue +0 -33
  33. package/src/components/Dropdown/DropdownTitle.vue +0 -14
  34. package/src/components/Dropdown/dropdown-item.scss +0 -84
  35. package/src/components/Dropdown/dropdown.scss +0 -53
  36. package/src/components/Flex/Flex.vue +0 -113
  37. package/src/components/Grid/Grid.vue +0 -87
  38. package/src/components/Input/Color.vue +0 -26
  39. package/src/components/Input/Counter.vue +0 -66
  40. package/src/components/Input/Dropzone.vue +0 -65
  41. package/src/components/Input/File.vue +0 -15
  42. package/src/components/Input/Input.vue +0 -123
  43. package/src/components/Input/Password.vue +0 -35
  44. package/src/components/Input/Textarea.vue +0 -78
  45. package/src/components/Input/input.scss +0 -302
  46. package/src/components/Kbd/Kbd.vue +0 -48
  47. package/src/components/Kbd/KbdGroup.vue +0 -28
  48. package/src/components/Kbd/kbd.scss +0 -19
  49. package/src/components/Modal/Confirm.vue +0 -56
  50. package/src/components/Modal/Modal.vue +0 -103
  51. package/src/components/Modal/modal.scss +0 -54
  52. package/src/components/OTP/OTP.vue +0 -133
  53. package/src/components/OTP/OTPItem.vue +0 -37
  54. package/src/components/OTP/otp.scss +0 -84
  55. package/src/components/Pagination/Pagination.vue +0 -92
  56. package/src/components/Pagination/pagination.ts +0 -78
  57. package/src/components/Popout/Popout.vue +0 -73
  58. package/src/components/Popout/popout.scss +0 -16
  59. package/src/components/Progress/Progress.vue +0 -103
  60. package/src/components/Progress/progress.scss +0 -47
  61. package/src/components/Radio/Radio.vue +0 -38
  62. package/src/components/Radio/RadioGroup.vue +0 -34
  63. package/src/components/Radio/radio.scss +0 -78
  64. package/src/components/Select/Select.vue +0 -212
  65. package/src/components/Select/select.scss +0 -82
  66. package/src/components/Sheet/Sheet.vue +0 -106
  67. package/src/components/Sheet/sheet.scss +0 -71
  68. package/src/components/Sidebar/Sidebar.vue +0 -116
  69. package/src/components/Sidebar/sidebar.scss +0 -124
  70. package/src/components/Skeleton/Skeleton.vue +0 -43
  71. package/src/components/Skeleton/skeleton.scss +0 -14
  72. package/src/components/Spinner/Spinner.vue +0 -42
  73. package/src/components/Spinner/spinner.scss +0 -47
  74. package/src/components/Switch/Switch.vue +0 -31
  75. package/src/components/Switch/switch.scss +0 -93
  76. package/src/components/Table/Cell.vue +0 -23
  77. package/src/components/Table/Head.vue +0 -66
  78. package/src/components/Table/Root.vue +0 -66
  79. package/src/components/Table/SelectAll.vue +0 -23
  80. package/src/components/Table/SelectRow.vue +0 -30
  81. package/src/components/Table/index.ts +0 -7
  82. package/src/components/Table/table.scss +0 -155
  83. package/src/components/Table/table.ts +0 -248
  84. package/src/components/Tabs/Tab.vue +0 -25
  85. package/src/components/Tabs/Tabs.vue +0 -90
  86. package/src/components/Tabs/tabs.scss +0 -87
  87. package/src/components/Toast/Toasts.vue +0 -52
  88. package/src/components/Toast/toast.scss +0 -45
  89. package/src/components/Toast/toast.ts +0 -75
  90. package/src/components/Tooltip/Tooltip.vue +0 -78
  91. package/src/components/Tooltip/tooltip.scss +0 -5
  92. package/src/examples/ExampleAccordions.vue +0 -69
  93. package/src/examples/ExampleAlerts.vue +0 -78
  94. package/src/examples/ExampleAvatars.vue +0 -44
  95. package/src/examples/ExampleBadges.vue +0 -48
  96. package/src/examples/ExampleBreadcrumbs.vue +0 -46
  97. package/src/examples/ExampleButtons.vue +0 -148
  98. package/src/examples/ExampleCalendars.vue +0 -40
  99. package/src/examples/ExampleCards.vue +0 -94
  100. package/src/examples/ExampleCheckboxes.vue +0 -123
  101. package/src/examples/ExampleCopyClipboard.vue +0 -47
  102. package/src/examples/ExampleDividers.vue +0 -39
  103. package/src/examples/ExampleDrawers.vue +0 -67
  104. package/src/examples/ExampleDropdowns.vue +0 -114
  105. package/src/examples/ExampleFlexGrid.vue +0 -124
  106. package/src/examples/ExampleInputs.vue +0 -236
  107. package/src/examples/ExampleKBD.vue +0 -65
  108. package/src/examples/ExampleModals.vue +0 -143
  109. package/src/examples/ExamplePalette.vue +0 -165
  110. package/src/examples/ExamplePopouts.vue +0 -41
  111. package/src/examples/ExampleSheets.vue +0 -77
  112. package/src/examples/ExampleSidebars.vue +0 -276
  113. package/src/examples/ExampleSkeletons.vue +0 -26
  114. package/src/examples/ExampleSpinners.vue +0 -80
  115. package/src/examples/ExampleTables.vue +0 -359
  116. package/src/examples/ExampleTabs.vue +0 -142
  117. package/src/examples/ExampleToasts.vue +0 -96
  118. package/src/examples/ExampleTooltips.vue +0 -70
  119. package/src/examples/shared/ExampleColor.vue +0 -28
  120. package/src/index.ts +0 -116
  121. package/src/internal/Backdrop/Backdrop.vue +0 -22
  122. package/src/internal/Backdrop/backdrop.scss +0 -34
  123. package/src/main.ts +0 -5
  124. package/src/shared/helpers.ts +0 -124
  125. package/src/shared/slots.ts +0 -61
  126. package/src/shared/theme.ts +0 -22
  127. package/src/shared/types.ts +0 -29
  128. package/src/style/animation.scss +0 -50
  129. package/src/style/core.scss +0 -133
  130. package/src/style/fonts.scss +0 -73
  131. package/src/style/layout.scss +0 -179
  132. package/src/style/media-query.scss +0 -29
  133. package/src/style/reset.scss +0 -135
  134. package/src/style/text.scss +0 -137
  135. package/src/style/theme.scss +0 -195
  136. package/src/style/tooltip.scss +0 -146
  137. package/src/style/typography.scss +0 -435
  138. package/src/style/utils.scss +0 -36
  139. package/src/style.scss +0 -1
  140. package/src/vite-env.d.ts +0 -1
@@ -1,93 +0,0 @@
1
- .vui-switch {
2
- --switch-size: 24px;
3
-
4
- &.checked {
5
- .vui-switch-icon .vui-switch-indicator {
6
- left: calc(100% - 24px);
7
- background-color: var(--color-text);
8
- }
9
-
10
- &.accent .vui-switch-icon .vui-switch-indicator {
11
- background-color: var(--color-accent);
12
- }
13
- }
14
-
15
- &.disabled {
16
- .vui-switch-icon {
17
- opacity: 0.5;
18
- cursor: not-allowed;
19
- }
20
-
21
- input + label .vui-switch-content {
22
- opacity: 0.5;
23
- cursor: not-allowed;
24
- }
25
- }
26
-
27
- .vui-switch-icon {
28
- width: 44px;
29
- height: var(--switch-size);
30
- border-radius: 22px;
31
- background-color: var(--color-bg-raised);
32
- position: relative;
33
- cursor: default;
34
-
35
- .vui-switch-indicator {
36
- display: block;
37
- position: absolute;
38
- left: 2px;
39
- top: 2px;
40
- width: 20px;
41
- height: 20px;
42
- border-radius: 100%;
43
- background-color: var(--color-text-lighter);
44
- transition: var(--transition);
45
- }
46
- }
47
-
48
- input {
49
- width: 1px;
50
- height: 1px;
51
- position: absolute;
52
- overflow: hidden;
53
- outline: none !important;
54
- opacity: 0;
55
-
56
- &:focus-visible + label .vui-switch-icon {
57
- outline: 2px solid var(--color-text);
58
- }
59
-
60
- & + label {
61
- display: grid;
62
- grid-template-columns: 44px 1fr;
63
- gap: 10px;
64
- font-size: var(--font-size-m);
65
- color: var(--color-text);
66
- user-select: none;
67
-
68
- .vui-switch-content {
69
- display: block;
70
-
71
- &:is(p) {
72
- height: var(--switch-size);
73
- line-height: var(--switch-size);
74
- font-size: var(--font-size-m);
75
- }
76
- }
77
- }
78
- }
79
- }
80
-
81
- :root.light {
82
- .vui-switch .vui-switch-icon .vui-switch-indicator {
83
- background-color: var(--color-bg-lowered);
84
- }
85
-
86
- .vui-switch.checked.accent .vui-switch-icon .vui-switch-indicator {
87
- background-color: var(--color-accent);
88
- }
89
-
90
- .vui-switch.checked .vui-switch-icon .vui-switch-indicator {
91
- background-color: var(--color-text);
92
- }
93
- }
@@ -1,23 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, useSlots, useTemplateRef } from 'vue'
3
-
4
- const slots = useSlots()
5
- const contextRef = useTemplateRef<HTMLTableCellElement>('context')
6
- const computedStyle = computed(() => {
7
- if (!slots.context || !window)
8
- return {}
9
- const width = contextRef.value?.getBoundingClientRect().width ?? 0
10
- return {
11
- paddingRight: `${width}px`,
12
- }
13
- })
14
- </script>
15
-
16
- <template>
17
- <td :style="computedStyle">
18
- <slot />
19
- <div v-if="$slots.context" ref="context" class="vui-cell-context">
20
- <slot name="context" />
21
- </div>
22
- </td>
23
- </template>
@@ -1,66 +0,0 @@
1
- <script setup lang="ts">
2
- import type { Header } from './table'
3
- import { computed } from 'vue'
4
- import Button from '../Button/Button.vue'
5
- import Tooltip from '../Tooltip/Tooltip.vue'
6
-
7
- interface Props {
8
- /**
9
- * Main header data. This can be empty in case we are just adding an empty
10
- * padder. It is recommended to just use <th> instead, but this shouldn't fail
11
- * anyway
12
- */
13
- header?: Header
14
- /**
15
- * Enable sorting on this column
16
- */
17
- sort?: boolean
18
- }
19
-
20
- const props = defineProps<Props>()
21
-
22
- const sortStateBind = computed(() => {
23
- if (!props.header)
24
- return
25
- switch (props.header.sortKey) {
26
- case 'asc': return {
27
- icon: 'ph:sort-ascending',
28
- tooltipText: 'Ascending',
29
- }
30
- case 'desc': return {
31
- icon: 'ph:sort-descending',
32
- tooltipText: 'Descending',
33
- }
34
- default: return {
35
- icon: 'ph:arrows-down-up',
36
- tooltipText: 'Sort column',
37
- }
38
- }
39
- })
40
- </script>
41
-
42
- <template>
43
- <th>
44
- <div v-if="props.header || $slots.default" class="vui-table-th-content">
45
- <slot>
46
- {{ props.header?.label }}
47
- </slot>
48
- <template v-if="props.sort && props.header">
49
- <Tooltip placement="top">
50
- <Button
51
- :icon="sortStateBind?.icon"
52
- class="vui-table-sort-button"
53
- size="s"
54
- :plain="!!!props.header.sortKey"
55
- square
56
- variant="gray"
57
- @click="props.header.sortToggle"
58
- />
59
- <template #tooltip>
60
- {{ sortStateBind?.tooltipText }}
61
- </template>
62
- </Tooltip>
63
- </template>
64
- </div>
65
- </th>
66
- </template>
@@ -1,66 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { TableSelectionProvide } from './table'
3
- import { inject } from 'vue'
4
- import { TableSelectionProvideSymbol } from './table'
5
- import './table.scss'
6
-
7
- interface Props {
8
- /**
9
- * Sets the `table-layout` property
10
- */
11
- fixed?: boolean
12
- /**
13
- * Table cells with content overflowing on new line will be cropped
14
- */
15
- nowrap?: boolean
16
- /**
17
- * Add a visual separator between each row
18
- */
19
- separateRows?: boolean
20
- /**
21
- * Add a visual separator between each cell
22
- */
23
- separateCells?: boolean
24
- /**
25
- * Wrap table with a border
26
- */
27
- outerBorder?: boolean
28
- }
29
-
30
- const {
31
- fixed,
32
- nowrap,
33
- separateRows = true,
34
- separateCells = false,
35
- outerBorder = true,
36
- } = defineProps<Props>()
37
- const selecting = inject(TableSelectionProvideSymbol) as TableSelectionProvide
38
- </script>
39
-
40
- <template>
41
- <div
42
- class="vui-table-container"
43
- :class="{
44
- fixed,
45
- nowrap,
46
- 'selecting': selecting.enabled,
47
- 'separated-rows': separateRows,
48
- 'separated-cells': separateCells,
49
- 'outer-border': outerBorder,
50
- }"
51
- >
52
- <table>
53
- <thead v-if="$slots.header">
54
- <tr>
55
- <slot name="header" />
56
- </tr>
57
- </thead>
58
- <tbody>
59
- <slot name="body" />
60
- </tbody>
61
- </table>
62
- <div v-if="$slots.pagination" class="vui-table-pagination-wrap">
63
- <slot name="pagination" />
64
- </div>
65
- </div>
66
- </template>
@@ -1,23 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { TableSelectionProvide } from './table'
3
- import { inject } from 'vue'
4
- import Button from '../Button/Button.vue'
5
- import { TableSelectionProvideSymbol } from './table'
6
-
7
- const {
8
- isSelectedAll,
9
- enabled,
10
- selectAllRows,
11
- } = inject(TableSelectionProvideSymbol) as TableSelectionProvide
12
- </script>
13
-
14
- <template>
15
- <th v-if="enabled" class="vui-table-interactive-cell" :class="{ selected: isSelectedAll }">
16
- <Button
17
- square
18
- plain
19
- :icon="isSelectedAll ? 'ph:check-square-fill' : 'ph:square'"
20
- @click="selectAllRows()"
21
- />
22
- </th>
23
- </template>
@@ -1,30 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { BaseRow, TableSelectionProvide } from './table'
3
- import { computed, inject } from 'vue'
4
- import { isObjectInSet } from '../../shared/helpers'
5
- import Button from '../Button/Button.vue'
6
- import { TableSelectionProvideSymbol } from './table'
7
-
8
- interface Props {
9
- row: BaseRow
10
- }
11
-
12
- const props = defineProps<Props>()
13
- const {
14
- enabled,
15
- selectRow,
16
- selectedRows,
17
- } = inject(TableSelectionProvideSymbol) as TableSelectionProvide
18
- const isSelected = computed(() => isObjectInSet(selectedRows.value, props.row))
19
- </script>
20
-
21
- <template>
22
- <td v-if="enabled" class="vui-table-interactive-cell" :class="{ selected: isSelected }">
23
- <Button
24
- square
25
- plain
26
- :icon="isSelected ? 'ph:check-square-fill' : 'ph:square'"
27
- @click="selectRow(props.row)"
28
- />
29
- </td>
30
- </template>
@@ -1,7 +0,0 @@
1
- import Cell from './Cell.vue'
2
- import Head from './Head.vue'
3
- import Root from './Root.vue'
4
- import SelectAll from './SelectAll.vue'
5
- import SelectRow from './SelectRow.vue'
6
-
7
- export { Cell, Head, Root, SelectAll, SelectRow }
@@ -1,155 +0,0 @@
1
- .vui-table-overflow {
2
- display: block;
3
- max-width: 100%;
4
- overflow-x: auto;
5
- overflow-y: visible;
6
- }
7
-
8
- .vui-table-container {
9
- display: block;
10
- width: 100%;
11
- border-radius: var(--border-radius-m);
12
-
13
- &.fixed table {
14
- table-layout: fixed;
15
- }
16
-
17
- &.outer-border {
18
- border: 1px solid var(--color-border);
19
- }
20
-
21
- &.nowrap table tr {
22
- td {
23
- white-space: nowrap;
24
- overflow: hidden;
25
- text-overflow: ellipsis;
26
- }
27
- }
28
-
29
- &.separated-rows table {
30
- th,
31
- td {
32
- border-bottom: 1px solid var(--color-border);
33
- }
34
- }
35
-
36
- &.separated-cells table {
37
- th,
38
- td {
39
- border-right: 1px solid var(--color-border);
40
-
41
- &:last-of-type {
42
- border-right: none;
43
- }
44
- }
45
- }
46
-
47
- table {
48
- width: 100%;
49
- border-collapse: collapse;
50
- text-indent: 0;
51
- border: none;
52
- overflow: unset;
53
-
54
- tr {
55
- border: none;
56
-
57
- &:first-child td {
58
- border-top: 0 !important;
59
- }
60
-
61
- &:has(.vui-table-interactive-cell.selected) {
62
- td {
63
- background-color: var(--color-bg-raised);
64
- }
65
- }
66
-
67
- &:last-child td {
68
- border-bottom: 0;
69
- }
70
- }
71
-
72
- th {
73
- border-top: 0 !important;
74
- }
75
-
76
- th,
77
- td {
78
- border: none;
79
- border-left: none !important;
80
- transition: var(--transition-fast);
81
- position: relative;
82
- z-index: var(--z-default);
83
-
84
- // Fixed width, only houses a checkbox component
85
- &.vui-table-interactive-cell {
86
- --checkbox-cell-width: calc(calc(var(--space-xs) * 2) + 32px);
87
- width: var(--checkbox-cell-width);
88
- min-width: var(--checkbox-cell-width);
89
- max-width: var(--checkbox-cell-width);
90
- height: auto;
91
- padding-inline: var(--space-xs);
92
- padding-block: 0;
93
- vertical-align: middle;
94
-
95
- &.selected .vui-button.icon .vui-button-slot svg path {
96
- color: var(--color-text) !important;
97
- }
98
-
99
- .vui-button {
100
- vertical-align: middle;
101
- display: inline-flex;
102
-
103
- &.icon .vui-button-slot svg {
104
- width: 22px !important;
105
- height: 22px !important;
106
-
107
- path {
108
- color: var(--color-text-light);
109
- }
110
- }
111
- }
112
- }
113
-
114
- .vui-cell-context {
115
- display: flex;
116
- align-items: center;
117
- justify-content: center;
118
- z-index: var(--z-active);
119
- position: absolute;
120
- inset: 0;
121
- padding: var(--space-xs);
122
- background-color: var(--color-bg);
123
- left: unset;
124
- }
125
- }
126
-
127
- th {
128
- .vui-table-th-content {
129
- color: var(--color-text);
130
- font-size: var(--font-size-xs);
131
- text-transform: uppercase;
132
- font-weight: var(--font-weight-semibold);
133
- display: flex;
134
- justify-content: flex-start;
135
- align-items: center;
136
- gap: var(--space-xs);
137
-
138
- .vui-table-sort-button:not(.active) svg path {
139
- color: var(--color-text-light);
140
- }
141
- }
142
- }
143
- }
144
-
145
- .vui-table-pagination-wrap {
146
- padding: var(--space-xs) var(--space-m);
147
- border-top: 1px solid var(--color-border);
148
- }
149
- }
150
-
151
- :root.light {
152
- .vui-table-container table tr:has(.vui-table-interactive-cell.selected) td {
153
- background-color: var(--color-bg-medium);
154
- }
155
- }
@@ -1,248 +0,0 @@
1
- import type { ComputedRef, InjectionKey, MaybeRefOrGetter, Ref } from 'vue'
2
- import type { DeepRequired } from '../../shared/types'
3
- import { computed, provide, readonly, ref, toValue } from 'vue'
4
- import { searchString } from '../../shared/helpers'
5
- import { paginate } from '../Pagination/pagination'
6
-
7
- export type BaseRow = Record<string, string | number>
8
-
9
- export interface TableSelectionProvide {
10
- selectedRows: Ref<Set<BaseRow>>
11
- selectRow: (row: BaseRow) => void
12
- selectAllRows: () => void
13
- enabled: ComputedRef<boolean>
14
- isSelectedAll: ComputedRef<boolean>
15
- }
16
-
17
- export const TableSelectionProvideSymbol = Symbol('select-row-provide') as InjectionKey<TableSelectionProvide>
18
-
19
- interface Sorting<K> {
20
- key?: K
21
- type: 'asc' | 'desc'
22
- }
23
-
24
- export interface Header {
25
- label: string
26
- sortToggle: () => void
27
- sortKey?: 'asc' | 'desc'
28
-
29
- }
30
-
31
- interface TableOptionsInput {
32
- pagination?: {
33
- enabled?: boolean
34
- perPage?: number
35
- maxPages?: number
36
- }
37
- select?: boolean
38
- }
39
-
40
- // eslint-disable-next-line ts/explicit-function-return-type
41
- export function defineTable<const Dataset extends any[]>(
42
- computedDataset: MaybeRefOrGetter<Dataset>,
43
- tableOptions?: TableOptionsInput,
44
- ) {
45
- const $data = computed(() => toValue(computedDataset))
46
-
47
- //
48
- // Reactive options + defaults
49
- const options = ref(Object.assign({
50
- pagination: {
51
- enabled: false,
52
- perPage: 10,
53
- maxPages: 3,
54
- },
55
- select: false,
56
- }, tableOptions) as DeepRequired<TableOptionsInput>)
57
-
58
- //
59
- // Pagination
60
- const currentPage = ref(1)
61
-
62
- const pagination = computed(() => paginate(
63
- $data.value.length,
64
- currentPage.value,
65
- options.value.pagination?.perPage,
66
- options.value.pagination?.maxPages,
67
- ))
68
-
69
- const canNextPage = computed(() => pagination.value.currentPage < pagination.value.endPage)
70
- const canPrevPage = computed(() => pagination.value.currentPage > pagination.value.startPage)
71
-
72
- /**
73
- * Sets the currently active data page. Please note that you provide the page
74
- * number, no its index. So this is 1-indexed input
75
- *
76
- * @param page Page number
77
- */
78
- const setPage = (page: number): void => {
79
- if ((page > currentPage.value && canNextPage.value)
80
- || (page < currentPage.value && canPrevPage.value)) {
81
- currentPage.value = page
82
- }
83
- }
84
-
85
- //
86
- // Sorting
87
-
88
- const sorting = ref<Sorting<Ref<keyof Dataset[number]>>>({
89
- key: undefined,
90
- type: 'asc',
91
- })
92
-
93
- const setSort = (key: keyof Dataset[number], type: 'asc' | 'desc' | 'toggle' = 'asc'): void => {
94
- sorting.value.key = key
95
- sorting.value.type = type === 'toggle'
96
- // Toggle between descending & ascending whenever the set sort fn is called
97
- ? sorting.value.type === 'asc' ? 'desc' : 'asc'
98
- : type
99
- }
100
-
101
- const clearSort = (): void => {
102
- sorting.value.key = undefined
103
- sorting.value.type = 'asc'
104
- }
105
-
106
- //
107
- // Searching
108
- const search = ref<string>()
109
-
110
- //
111
- // Dataset formatting
112
- const filteredRows = computed(() => {
113
- const searchValue = search.value
114
- let final = $data.value
115
-
116
- if (searchValue) {
117
- final = final.filter((row: Dataset[number]) => {
118
- const matches = Object
119
- .values(row)
120
- .map(row => `${row}`)
121
- return searchString(matches, searchValue)
122
- }) as Dataset
123
- }
124
-
125
- const key = sorting.value.key
126
-
127
- if (key) {
128
- // FIXME: change to `toSorted` when typescript is ok
129
- final = [...final].sort((a: Dataset[number], b: Dataset[number]) => {
130
- const aValue = a[key]
131
- const bValue = b[key]
132
- return sorting.value.type === 'asc'
133
- ? aValue > bValue ? 1 : -1
134
- : aValue > bValue ? -1 : 1
135
- }) as Dataset
136
- }
137
-
138
- return final
139
- })
140
-
141
- const headers = computed(() => Object
142
- .keys($data.value[0] || {})
143
- .map((key) => {
144
- return {
145
- label: key,
146
- sortKey: sorting.value.key === key && sorting.value.type,
147
- sortToggle: () => {
148
- // 3-way toggle asc -> desc -> turn off (reset to undefined)
149
- if (sorting.value.key === key) {
150
- switch (sorting.value.type) {
151
- case 'asc': {
152
- sorting.value.type = 'desc'
153
- break
154
- }
155
- case 'desc': {
156
- sorting.value.key = undefined
157
- sorting.value.key = 'asc'
158
- break
159
- }
160
- default: {
161
- sorting.value.key = key
162
- sorting.value.type = 'asc'
163
- break
164
- }
165
- }
166
- }
167
- else {
168
- setSort(key)
169
- }
170
- },
171
- } as Header
172
- }),
173
- )
174
-
175
- const rows = computed(() => {
176
- if (options.value.pagination?.enabled === true) {
177
- return filteredRows.value.slice(
178
- pagination.value.startIndex,
179
- pagination.value.endIndex + 1,
180
- ) as Dataset
181
- }
182
- return filteredRows.value as Dataset
183
- })
184
-
185
- //
186
- // Row selecting
187
- const selectedRows = ref<Set<BaseRow>>(new Set() as Set<BaseRow>)
188
- const selectingEnabled = computed(() => options.value.select)
189
-
190
- /**
191
- * Accepts either an existing index of a row within the dataset or the dataset
192
- * row itself. If the item is already selected, it will be deselected.
193
- *
194
- * @param row {Number | RowObject}
195
- */
196
- function selectRow(row: Dataset[number]): void {
197
- if (selectedRows.value.has(row)) {
198
- selectedRows.value.delete(row)
199
- }
200
- else {
201
- selectedRows.value.add(row)
202
- }
203
- }
204
-
205
- const isSelectedAll = computed(() => $data.value.length === selectedRows.value.size)
206
-
207
- function selectAllRows(): void {
208
- if (isSelectedAll.value) {
209
- // If the selected indexes have the same length as the data array, we can
210
- // assume all of them are selected. Therefore we toggle it by deselecting
211
- // all of them
212
- selectedRows.value = new Set()
213
- }
214
- else {
215
- const data = new Set<BaseRow>()
216
- for (const item of $data.value) {
217
- data.add(item)
218
- }
219
- selectedRows.value = new Set(data)
220
- }
221
- }
222
-
223
- provide(TableSelectionProvideSymbol, {
224
- selectedRows,
225
- selectRow,
226
- selectAllRows,
227
- enabled: selectingEnabled,
228
- isSelectedAll,
229
- })
230
-
231
- return {
232
- setSort,
233
- clearSort,
234
- search,
235
- rows: readonly(rows),
236
- allRows: readonly(filteredRows),
237
- selectedRows: readonly(selectedRows),
238
- headers: readonly(headers),
239
- pagination,
240
- canPrevPage,
241
- canNextPage,
242
- setPage,
243
- options,
244
- selectRow,
245
- selectAllRows,
246
- isSelectedAll,
247
- }
248
- }