@tak-ps/vue-tabler 4.16.0 → 4.18.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/CHANGELOG.md +12 -0
- package/components/Border.vue +121 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
## Version History
|
|
12
12
|
|
|
13
|
+
### v4.17.0
|
|
14
|
+
|
|
15
|
+
- :rocket: `TablerBorder` now supports `background`, `editable`, `editing`, `editAriaLabel` props plus `actions` and `editor` slots and an `edit` event for inline edit container patterns
|
|
16
|
+
|
|
17
|
+
### v4.16.1
|
|
18
|
+
|
|
19
|
+
- :rocket: Update Core Deps
|
|
20
|
+
|
|
21
|
+
### v4.16.0
|
|
22
|
+
|
|
23
|
+
- :tada: Add `TablerBorder` component for bordered card sections
|
|
24
|
+
|
|
13
25
|
### v4.16.0 - 2026-04-23
|
|
14
26
|
|
|
15
27
|
- :tada: Add Tabler Border Component
|
package/components/Border.vue
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class='card border border-light-subtle'
|
|
4
|
+
:class='{
|
|
5
|
+
"h-100": fillHeight,
|
|
6
|
+
"shadow-sm": shadow,
|
|
7
|
+
"tabler-border--clickable": clickable,
|
|
8
|
+
}'
|
|
9
|
+
:style='backgroundStyle'
|
|
10
|
+
:role='clickable ? "button" : undefined'
|
|
11
|
+
:tabindex='clickable ? 0 : undefined'
|
|
12
|
+
@click='handleClick'
|
|
13
|
+
@keyup.enter='handleClick'
|
|
14
|
+
@keyup.space.prevent='handleClick'
|
|
15
|
+
>
|
|
3
16
|
<div
|
|
4
|
-
class='card-body d-flex flex-column'
|
|
17
|
+
class='card-body d-flex flex-column position-relative'
|
|
5
18
|
:class='{
|
|
6
19
|
"gap-4": gap === "lg",
|
|
7
20
|
"gap-3": gap === "md",
|
|
@@ -9,29 +22,127 @@
|
|
|
9
22
|
}'
|
|
10
23
|
>
|
|
11
24
|
<div
|
|
12
|
-
v-if='label || $slots.header'
|
|
25
|
+
v-if='label || $slots.label || $slots.header'
|
|
13
26
|
class='d-flex align-items-center justify-content-between'
|
|
14
27
|
>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
<slot name='label'>
|
|
29
|
+
<p
|
|
30
|
+
v-if='label'
|
|
31
|
+
class='text-uppercase small mb-0'
|
|
32
|
+
v-text='label'
|
|
33
|
+
/>
|
|
34
|
+
</slot>
|
|
20
35
|
<slot name='header' />
|
|
21
36
|
</div>
|
|
22
|
-
|
|
37
|
+
|
|
38
|
+
<div
|
|
39
|
+
v-if='showActions'
|
|
40
|
+
class='tabler-border__actions position-absolute'
|
|
41
|
+
>
|
|
42
|
+
<slot name='actions'>
|
|
43
|
+
<TablerIconButton
|
|
44
|
+
v-if='editable && !editing'
|
|
45
|
+
:title='resolvedEditAriaLabel'
|
|
46
|
+
@click.stop.prevent='emit("edit")'
|
|
47
|
+
>
|
|
48
|
+
<IconPencil
|
|
49
|
+
:size='24'
|
|
50
|
+
stroke='1'
|
|
51
|
+
/>
|
|
52
|
+
</TablerIconButton>
|
|
53
|
+
</slot>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<slot
|
|
57
|
+
v-if='editing'
|
|
58
|
+
name='editor'
|
|
59
|
+
/>
|
|
60
|
+
<slot v-else />
|
|
23
61
|
</div>
|
|
24
62
|
</div>
|
|
25
63
|
</template>
|
|
26
64
|
|
|
27
65
|
<script setup lang='ts'>
|
|
66
|
+
import { computed, useSlots } from 'vue';
|
|
67
|
+
import TablerIconButton from './IconButton.vue';
|
|
68
|
+
import { IconPencil } from '@tabler/icons-vue';
|
|
69
|
+
|
|
28
70
|
export interface BorderProps {
|
|
29
71
|
label?: string;
|
|
30
72
|
gap?: 'sm' | 'md' | 'lg';
|
|
73
|
+
background?: string;
|
|
74
|
+
shadow?: boolean;
|
|
75
|
+
fillHeight?: boolean;
|
|
76
|
+
editable?: boolean;
|
|
77
|
+
editing?: boolean;
|
|
78
|
+
editAriaLabel?: string;
|
|
31
79
|
}
|
|
32
80
|
|
|
33
|
-
withDefaults(defineProps<BorderProps>(), {
|
|
81
|
+
const props = withDefaults(defineProps<BorderProps>(), {
|
|
34
82
|
label: '',
|
|
35
83
|
gap: 'md',
|
|
84
|
+
background: '',
|
|
85
|
+
shadow: true,
|
|
86
|
+
fillHeight: true,
|
|
87
|
+
editable: false,
|
|
88
|
+
editing: false,
|
|
89
|
+
editAriaLabel: '',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const emit = defineEmits<{
|
|
93
|
+
edit: [];
|
|
94
|
+
}>();
|
|
95
|
+
|
|
96
|
+
const slots = useSlots();
|
|
97
|
+
|
|
98
|
+
const backgroundStyle = computed(() => {
|
|
99
|
+
if (!props.background) return undefined;
|
|
100
|
+
return { backgroundColor: props.background };
|
|
36
101
|
});
|
|
102
|
+
|
|
103
|
+
const clickable = computed(() => props.editable && !props.editing);
|
|
104
|
+
|
|
105
|
+
const showActions = computed(() => {
|
|
106
|
+
if (slots.actions) return true;
|
|
107
|
+
return props.editable && !props.editing;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const resolvedEditAriaLabel = computed(() => {
|
|
111
|
+
if (props.editAriaLabel) return props.editAriaLabel;
|
|
112
|
+
if (props.label) return `Edit ${props.label.toLowerCase()}`;
|
|
113
|
+
return 'Edit';
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
function handleClick(): void {
|
|
117
|
+
if (!clickable.value) return;
|
|
118
|
+
emit('edit');
|
|
119
|
+
}
|
|
37
120
|
</script>
|
|
121
|
+
|
|
122
|
+
<style scoped>
|
|
123
|
+
.tabler-border--clickable {
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.tabler-border--clickable:focus-visible {
|
|
128
|
+
outline: 2px solid rgba(var(--tblr-primary-rgb, 32, 107, 196), 0.7);
|
|
129
|
+
outline-offset: 2px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.tabler-border__actions {
|
|
133
|
+
top: 8px;
|
|
134
|
+
right: 8px;
|
|
135
|
+
opacity: 1;
|
|
136
|
+
transition: opacity 0.15s ease-in-out;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.tabler-border--clickable .tabler-border__actions {
|
|
140
|
+
opacity: 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.tabler-border--clickable:hover .tabler-border__actions,
|
|
144
|
+
.tabler-border--clickable:focus-visible .tabler-border__actions,
|
|
145
|
+
.tabler-border__actions:focus-within {
|
|
146
|
+
opacity: 1;
|
|
147
|
+
}
|
|
148
|
+
</style>
|