sprintify-ui 0.7.10 → 0.8.0
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/dist/sprintify-ui.es.js +10776 -10630
- package/dist/style.css +1 -1
- package/dist/types/components/BaseAppDialogs.vue.d.ts +1 -0
- package/dist/types/components/BaseDataIterator.vue.d.ts +50 -4
- package/dist/types/components/BaseDataIteratorSectionColumns.vue.d.ts +156 -68
- package/dist/types/components/BaseDataTable.vue.d.ts +86 -6
- package/dist/types/components/BaseDataTableTemplate.vue.d.ts +44 -28
- package/dist/types/components/BaseDialog.vue.d.ts +9 -0
- package/dist/types/components/BaseTable.vue.d.ts +30 -7
- package/dist/types/components/BaseTableCell.vue.d.ts +19 -1
- package/dist/types/components/BaseTableColumn.vue.d.ts +50 -3
- package/dist/types/components/BaseTableHead.vue.d.ts +6 -5
- package/dist/types/components/BaseTableHeader.vue.d.ts +12 -2
- package/dist/types/components/BaseTableRow.vue.d.ts +5 -0
- package/dist/types/composables/isFirstColumn.d.ts +4 -0
- package/dist/types/composables/isLastColumn.d.ts +4 -0
- package/dist/types/composables/paginatedData.d.ts +5 -5
- package/dist/types/services/table/types.d.ts +6 -5
- package/dist/types/types/index.d.ts +9 -2
- package/dist/types/utils/getApiData.d.ts +1 -1
- package/package.json +2 -1
- package/src/assets/main.css +0 -1
- package/src/components/BaseAppDialogs.vue +1 -0
- package/src/components/BaseAvatar.vue +1 -0
- package/src/components/BaseDataIterator.stories.js +96 -1
- package/src/components/BaseDataIterator.vue +135 -11
- package/src/components/BaseDataIteratorSectionColumns.vue +2 -2
- package/src/components/BaseDataTable.stories.js +140 -50
- package/src/components/BaseDataTable.vue +82 -48
- package/src/components/BaseDataTableTemplate.vue +207 -372
- package/src/components/BaseDialog.stories.js +7 -0
- package/src/components/BaseDialog.vue +13 -1
- package/src/components/BaseTable.stories.js +57 -15
- package/src/components/BaseTable.vue +71 -9
- package/src/components/BaseTableBody.vue +1 -1
- package/src/components/BaseTableCell.vue +94 -36
- package/src/components/BaseTableColumn.vue +25 -2
- package/src/components/BaseTableHead.vue +17 -5
- package/src/components/BaseTableHeader.vue +39 -10
- package/src/components/BaseTableRow.vue +27 -6
- package/src/composables/isFirstColumn.ts +31 -0
- package/src/composables/isLastColumn.ts +31 -0
- package/src/composables/paginatedData.ts +22 -10
- package/src/services/table/classes.ts +13 -9
- package/src/services/table/types.ts +6 -5
- package/src/stores/dialogs.ts +1 -0
- package/src/stories/List.stories.js +5 -1
- package/src/types/index.ts +9 -2
- package/src/utils/getApiData.ts +1 -1
- package/src/assets/base-table.css +0 -17
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<th
|
|
3
|
-
|
|
3
|
+
ref="thRef"
|
|
4
|
+
:class="classes"
|
|
4
5
|
:align="align"
|
|
5
6
|
:colspan="colspan"
|
|
7
|
+
:style="style"
|
|
8
|
+
@click="onClick"
|
|
6
9
|
>
|
|
7
|
-
<
|
|
8
|
-
<slot />
|
|
9
|
-
</div>
|
|
10
|
+
<slot />
|
|
10
11
|
</th>
|
|
11
12
|
</template>
|
|
12
13
|
|
|
13
14
|
<script lang="ts" setup>
|
|
15
|
+
import { useIsFirstColumn } from '@/composables/isFirstColumn';
|
|
16
|
+
import { useIsLastColumn } from '@/composables/isLastColumn';
|
|
14
17
|
import { cellClasses } from '@/services/table/classes';
|
|
15
18
|
import { CellConfig, TableProps } from '@/services/table/types';
|
|
16
19
|
import { ClassNameValue, twMerge } from 'tailwind-merge';
|
|
17
|
-
import { ComputedRef } from 'vue';
|
|
20
|
+
import { ComputedRef, StyleValue } from 'vue';
|
|
18
21
|
|
|
19
|
-
const baseTable = inject('
|
|
20
|
-
const baseTableHead = inject('
|
|
22
|
+
const baseTable = inject('table:props') as ComputedRef<TableProps> | undefined;
|
|
23
|
+
const baseTableHead = inject('tableHead:props', undefined);
|
|
24
|
+
const baseTableHorizontalScrolling = inject('table:horizontalScrolling', undefined) as ComputedRef<boolean> | undefined;
|
|
21
25
|
|
|
22
26
|
if (!baseTableHead) {
|
|
23
27
|
throw new Error('BaseTableCell must be used within a BaseTableHead.');
|
|
@@ -27,33 +31,58 @@ defineOptions({
|
|
|
27
31
|
inheritAttrs: false,
|
|
28
32
|
});
|
|
29
33
|
|
|
34
|
+
const emit = defineEmits(['click']);
|
|
35
|
+
|
|
30
36
|
const props = withDefaults(defineProps<{
|
|
31
37
|
class?: ClassNameValue,
|
|
38
|
+
style?: StyleValue,
|
|
32
39
|
align?: 'left' | 'center' | 'right',
|
|
33
40
|
colspan?: number,
|
|
34
41
|
}>(), {
|
|
35
42
|
class: undefined,
|
|
43
|
+
style: undefined,
|
|
36
44
|
align: 'left',
|
|
37
45
|
colspan: undefined,
|
|
38
46
|
});
|
|
39
47
|
|
|
48
|
+
function onClick(event: MouseEvent) {
|
|
49
|
+
emit('click', event);
|
|
50
|
+
}
|
|
51
|
+
|
|
40
52
|
const cellConfig = computed<CellConfig>(() => {
|
|
41
53
|
return {
|
|
42
|
-
|
|
54
|
+
size: baseTable?.value?.size,
|
|
43
55
|
flush: baseTable?.value?.flush,
|
|
44
56
|
head: true,
|
|
45
57
|
}
|
|
46
58
|
});
|
|
47
59
|
|
|
60
|
+
const thRef = ref<HTMLTableCellElement | null>(null);
|
|
61
|
+
|
|
62
|
+
const { isFirstColumn } = useIsFirstColumn(thRef);
|
|
63
|
+
const { isLastColumn } = useIsLastColumn(thRef);
|
|
64
|
+
|
|
65
|
+
|
|
48
66
|
const classes = computed(() => {
|
|
49
67
|
const base = cellClasses(cellConfig.value);
|
|
68
|
+
const baseTh = 'bg-white text-slate-500 border-b border-slate-300 group';
|
|
69
|
+
const sticky = baseTable?.value.fixedHeader ? 'sticky top-0 z-[2]' : '';
|
|
70
|
+
const firstCol = isFirstColumn.value ? 'duration-300 transition-[border] border-r border-r-transparent' : '';
|
|
71
|
+
const horizontalScrolling = baseTable?.value.fixedColumn && baseTableHorizontalScrolling?.value && isFirstColumn.value ? 'sticky z-[3] left-0 border-r-slate-200' : '';
|
|
72
|
+
const flushLeft = baseTable?.value.flush && isFirstColumn.value ? 'pl-0' : '';
|
|
73
|
+
const flushRight = baseTable?.value.flush && isLastColumn.value ? 'pr-0' : '';
|
|
50
74
|
|
|
51
75
|
return twMerge(
|
|
52
|
-
'text-slate-500 font-normal',
|
|
53
76
|
base,
|
|
77
|
+
baseTh,
|
|
78
|
+
sticky,
|
|
79
|
+
firstCol,
|
|
80
|
+
horizontalScrolling,
|
|
81
|
+
flushLeft,
|
|
82
|
+
flushRight,
|
|
54
83
|
props.class,
|
|
55
84
|
);
|
|
56
|
-
})
|
|
85
|
+
});
|
|
57
86
|
|
|
58
87
|
|
|
59
88
|
</script>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<tr
|
|
3
3
|
:class="classes"
|
|
4
|
-
@
|
|
5
|
-
@
|
|
6
|
-
@mouseleave="emit('mouseleave')"
|
|
4
|
+
@mouseenter="onMouseEnter"
|
|
5
|
+
@mouseleave="onMouseLeave"
|
|
7
6
|
>
|
|
8
7
|
<slot />
|
|
9
8
|
</tr>
|
|
@@ -17,7 +16,7 @@ defineOptions({
|
|
|
17
16
|
inheritAttrs: false,
|
|
18
17
|
});
|
|
19
18
|
|
|
20
|
-
const baseTable = inject('
|
|
19
|
+
const baseTable = inject('table:props');
|
|
21
20
|
|
|
22
21
|
if (!baseTable) {
|
|
23
22
|
throw new Error('baseTable must be used within a BaseTable.');
|
|
@@ -31,16 +30,16 @@ const props = withDefaults(defineProps<{
|
|
|
31
30
|
target?: '_blank' | '_self' | '_parent' | '_top',
|
|
32
31
|
title?: string,
|
|
33
32
|
class?: ClassNameValue,
|
|
33
|
+
onClick?: (e: MouseEvent) => void,
|
|
34
34
|
}>(), {
|
|
35
35
|
href: undefined,
|
|
36
36
|
to: undefined,
|
|
37
37
|
target: undefined,
|
|
38
38
|
title: undefined,
|
|
39
39
|
class: undefined,
|
|
40
|
+
onClick: undefined,
|
|
40
41
|
});
|
|
41
42
|
|
|
42
|
-
provide('BaseTableRow', computed(() => props));
|
|
43
|
-
|
|
44
43
|
const classes = computed(() => {
|
|
45
44
|
const base = 'group/row';
|
|
46
45
|
|
|
@@ -50,4 +49,26 @@ const classes = computed(() => {
|
|
|
50
49
|
);
|
|
51
50
|
});
|
|
52
51
|
|
|
52
|
+
const hover = ref(false);
|
|
53
|
+
const hoverForFullRow = ref(false);
|
|
54
|
+
|
|
55
|
+
function setHoverForFullRow(active: boolean) {
|
|
56
|
+
hoverForFullRow.value = active;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function onMouseEnter() {
|
|
60
|
+
emit('mouseenter');
|
|
61
|
+
hover.value = true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function onMouseLeave() {
|
|
65
|
+
emit('mouseleave');
|
|
66
|
+
hover.value = false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
provide('tableRow:props', computed(() => props));
|
|
70
|
+
provide('tableRow:hover', computed(() => hover.value));
|
|
71
|
+
provide('tableRow:setHoverForFullRow', setHoverForFullRow);
|
|
72
|
+
provide('tableRow:hoverForFullRow', computed(() => hoverForFullRow.value));
|
|
73
|
+
|
|
53
74
|
</script>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MaybeRef } from "vue";
|
|
2
|
+
|
|
3
|
+
export function useIsFirstColumn(tdOrTh: MaybeRef<HTMLTableCellElement | null>) {
|
|
4
|
+
|
|
5
|
+
const leftCol = ref<HTMLTableCellElement | null>();
|
|
6
|
+
|
|
7
|
+
onMounted(() => {
|
|
8
|
+
leftCol.value = unref(tdOrTh)?.previousElementSibling as HTMLTableCellElement | null;
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const isFirstColumn = computed(() => {
|
|
12
|
+
|
|
13
|
+
if (!leftCol.value) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (leftCol.value.tagName.toLowerCase() === 'th') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (leftCol.value.tagName.toLowerCase() === 'td') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return true;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
isFirstColumn,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MaybeRef } from "vue";
|
|
2
|
+
|
|
3
|
+
export function useIsLastColumn(tdOrTh: MaybeRef<HTMLTableCellElement | null>) {
|
|
4
|
+
|
|
5
|
+
const rightCol = ref<HTMLTableCellElement | null>();
|
|
6
|
+
|
|
7
|
+
onMounted(() => {
|
|
8
|
+
rightCol.value = unref(tdOrTh)?.nextElementSibling as HTMLTableCellElement | null;
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const isLastColumn = computed(() => {
|
|
12
|
+
|
|
13
|
+
if (!rightCol.value) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (rightCol.value.tagName.toLowerCase() === 'th') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (rightCol.value.tagName.toLowerCase() === 'td') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return true;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
isLastColumn,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ref } from 'vue';
|
|
1
|
+
import { ComputedRef, Ref } from 'vue';
|
|
2
2
|
import {
|
|
3
3
|
Collection,
|
|
4
4
|
PaginatedCollection,
|
|
@@ -9,26 +9,38 @@ import { isArray } from 'lodash';
|
|
|
9
9
|
import { getItems } from '@/utils/getApiData';
|
|
10
10
|
|
|
11
11
|
export function useHasPaginatedData(
|
|
12
|
-
data: Ref<Collection | PaginatedCollection | ResourceCollection | null
|
|
12
|
+
data: Ref<Collection | PaginatedCollection | ResourceCollection | null | undefined>,
|
|
13
|
+
page?: ComputedRef<number>,
|
|
14
|
+
perPage?: ComputedRef<number>,
|
|
13
15
|
) {
|
|
14
16
|
const items = computed(() => {
|
|
15
17
|
return getItems(data.value);
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
const paginationMetadata = computed<PaginationMetadata | null>(() => {
|
|
19
|
-
const defaultMeta = {
|
|
20
|
-
current_page: 1,
|
|
21
|
-
last_page: 1,
|
|
22
|
-
per_page: 1,
|
|
23
|
-
total: 0,
|
|
24
|
-
};
|
|
25
21
|
|
|
26
22
|
if (!data.value) {
|
|
27
|
-
return
|
|
23
|
+
return null;
|
|
28
24
|
}
|
|
25
|
+
|
|
29
26
|
if (isArray(data.value)) {
|
|
30
|
-
|
|
27
|
+
|
|
28
|
+
const perPageUnref = unref(perPage);
|
|
29
|
+
const pageUnref = unref(page);
|
|
30
|
+
|
|
31
|
+
const total = data.value.length;
|
|
32
|
+
const perPageArr = perPageUnref ? perPageUnref : total;
|
|
33
|
+
const pageArr = pageUnref ? pageUnref : 1;
|
|
34
|
+
const lastPage = Math.ceil(total / perPageArr);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
current_page: pageArr,
|
|
38
|
+
last_page: lastPage,
|
|
39
|
+
per_page: perPageArr,
|
|
40
|
+
total: total,
|
|
41
|
+
};
|
|
31
42
|
}
|
|
43
|
+
|
|
32
44
|
if ('meta' in data.value) {
|
|
33
45
|
return data.value.meta;
|
|
34
46
|
}
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { twMerge } from "tailwind-merge";
|
|
2
|
-
import { CellConfig,
|
|
2
|
+
import { CellConfig, CellSize } from "./types";
|
|
3
3
|
|
|
4
4
|
export function cellClasses(config: CellConfig): string {
|
|
5
|
-
const base = '
|
|
6
|
-
const space =
|
|
7
|
-
const flush = config.flush ? 'px-0' : '';
|
|
5
|
+
const base = '';
|
|
6
|
+
const space = size(config.size ?? 'md');
|
|
8
7
|
|
|
9
|
-
return twMerge([base, space
|
|
8
|
+
return twMerge([base, space]);
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
function
|
|
13
|
-
|
|
11
|
+
function size(size: CellSize): string {
|
|
12
|
+
|
|
13
|
+
if (size == 'xs') {
|
|
14
14
|
return 'px-1 py-0.5';
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (
|
|
17
|
+
if (size == 'sm') {
|
|
18
|
+
return 'px-2 py-1';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (size == 'md') {
|
|
18
22
|
return 'px-2 py-2';
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
if (
|
|
25
|
+
if (size == 'lg') {
|
|
22
26
|
return 'px-4 py-3';
|
|
23
27
|
}
|
|
24
28
|
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { RouteLocationRaw } from "vue-router";
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type CellSize = 'none' | 'xs' | 'sm' | 'md' | 'lg';
|
|
4
4
|
|
|
5
5
|
export interface TableProps {
|
|
6
|
-
|
|
6
|
+
size?: CellSize;
|
|
7
7
|
flush?: boolean;
|
|
8
|
+
fixedHeader?: boolean;
|
|
9
|
+
fixedColumn?: boolean;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export type CellConfig =
|
|
11
|
-
flush?: boolean;
|
|
12
|
-
} & TableProps;
|
|
12
|
+
export type CellConfig = TableProps;
|
|
13
13
|
|
|
14
14
|
export interface CellProps {
|
|
15
15
|
title?: string;
|
|
16
16
|
href?: string;
|
|
17
17
|
to?: RouteLocationRaw;
|
|
18
18
|
target?: string;
|
|
19
|
+
onClick?: (e: MouseEvent) => void;
|
|
19
20
|
}
|
package/src/stores/dialogs.ts
CHANGED
|
@@ -17,6 +17,7 @@ export const useDialogsStore = defineStore('dialogs', {
|
|
|
17
17
|
color: options.color ?? 'info',
|
|
18
18
|
title: options.title,
|
|
19
19
|
message: options.message,
|
|
20
|
+
html: options.html ?? false,
|
|
20
21
|
confirmText: options.confirmText ?? t('sui.confirm'),
|
|
21
22
|
cancelText: options.cancelText ?? t('sui.cancel'),
|
|
22
23
|
closeOnOutsideClick: options.closeOnOutsideClick ?? true,
|
|
@@ -125,7 +125,11 @@ const Template = (args) => ({
|
|
|
125
125
|
alert('Cell click: ' + row.id);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
function onRowClick(row) {
|
|
129
|
+
alert('Row click: ' + row.id);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return { args, onCellClick, onRowClick, DateTime };
|
|
129
133
|
},
|
|
130
134
|
});
|
|
131
135
|
|
package/src/types/index.ts
CHANGED
|
@@ -103,15 +103,20 @@ export interface BaseTableColumnData {
|
|
|
103
103
|
field: string;
|
|
104
104
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
105
|
meta: undefined | Record<string, any>;
|
|
106
|
-
newKey:
|
|
106
|
+
newKey: string;
|
|
107
107
|
numeric: boolean;
|
|
108
108
|
position: 'left' | 'right';
|
|
109
109
|
searchable: boolean;
|
|
110
110
|
sortable: boolean;
|
|
111
|
-
|
|
111
|
+
ignoreRowInteractions: boolean;
|
|
112
112
|
toggle: boolean;
|
|
113
113
|
toggleDefault: boolean;
|
|
114
114
|
width: number;
|
|
115
|
+
class?: string | string[];
|
|
116
|
+
to?: (row: Row) => RouteLocationRaw;
|
|
117
|
+
href?: (row: Row) => string;
|
|
118
|
+
target?: '_blank' | '_self' | '_parent' | '_top';
|
|
119
|
+
onClick?: (row: Row, index: number, column: BaseTableColumnData, colIndex: number, event: MouseEvent) => void;
|
|
115
120
|
style: {
|
|
116
121
|
width: undefined | number;
|
|
117
122
|
};
|
|
@@ -150,6 +155,7 @@ export interface DialogOptions {
|
|
|
150
155
|
color?: 'info' | 'success' | 'danger' | 'warning';
|
|
151
156
|
title: string;
|
|
152
157
|
message: string;
|
|
158
|
+
html?: boolean;
|
|
153
159
|
confirmText?: string;
|
|
154
160
|
cancelText?: string;
|
|
155
161
|
closeOnOutsideClick?: boolean;
|
|
@@ -162,6 +168,7 @@ export interface Dialog {
|
|
|
162
168
|
color: 'info' | 'success' | 'danger' | 'warning';
|
|
163
169
|
title: string;
|
|
164
170
|
message: string;
|
|
171
|
+
html: boolean;
|
|
165
172
|
confirmText: string;
|
|
166
173
|
cancelText: string;
|
|
167
174
|
closeOnOutsideClick: boolean;
|
package/src/utils/getApiData.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Collection, PaginatedCollection, ResourceCollection } from "@/types";
|
|
2
2
|
import { isArray } from "lodash";
|
|
3
3
|
|
|
4
|
-
export function getItems(data: Collection | PaginatedCollection | ResourceCollection | null) {
|
|
4
|
+
export function getItems(data: Collection | PaginatedCollection | ResourceCollection | null | undefined) {
|
|
5
5
|
if (!data) {
|
|
6
6
|
return [];
|
|
7
7
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
.base-table {
|
|
2
|
-
.th {
|
|
3
|
-
@apply relative z-[2];
|
|
4
|
-
@apply bg-slate-50;
|
|
5
|
-
@apply border-b border-slate-300;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.base-table--has-max-height .th {
|
|
9
|
-
@apply sticky;
|
|
10
|
-
@apply top-0;
|
|
11
|
-
@apply bg-opacity-75 backdrop-blur backdrop-filter;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
tbody tr.item-row:hover td {
|
|
15
|
-
@apply bg-slate-50;
|
|
16
|
-
}
|
|
17
|
-
}
|