srcdev-nuxt-components 6.1.30 → 6.1.32
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.
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="props.chip ? DisplayChip : as"
|
|
4
|
+
tag="div"
|
|
5
|
+
v-bind="props.chip ? (typeof props.chip === 'object' ? { config: props.chip } : { config: chipDefaultConfig }) : {}"
|
|
6
|
+
class="display-avatar"
|
|
7
|
+
:class="[size, elementClasses]"
|
|
8
|
+
:style-class-passthrough="elementClasses"
|
|
9
|
+
>
|
|
10
|
+
<slot name="default">
|
|
11
|
+
<NuxtImg v-if="src" :src :alt="alt || 'Avatar'" width="100%" height="100%" class="avatar-image" />
|
|
12
|
+
<span v-else>{{ fallback }}</span>
|
|
13
|
+
</slot>
|
|
14
|
+
<slot name="icon"></slot>
|
|
15
|
+
</component>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script lang="ts">
|
|
19
|
+
import DisplayChip from "../display-chip/DisplayChip.vue"
|
|
20
|
+
import type { DisplayChipProps, DisplayChipConfig } from "../../types"
|
|
21
|
+
export interface AvatarProps {
|
|
22
|
+
as?: any
|
|
23
|
+
src?: string
|
|
24
|
+
alt?: string
|
|
25
|
+
text?: string
|
|
26
|
+
size?: "xs" | "s" | "md" | "lg" | "xl" | string
|
|
27
|
+
chip?: boolean | DisplayChipProps
|
|
28
|
+
class?: any
|
|
29
|
+
style?: any
|
|
30
|
+
styleClassPassthrough?: string | string[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface AvatarSlots {
|
|
34
|
+
default(props?: {}): any
|
|
35
|
+
icon(props?: {}): any
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<script setup lang="ts">
|
|
40
|
+
const props = withDefaults(defineProps<AvatarProps>(), {
|
|
41
|
+
as: "span",
|
|
42
|
+
size: "md",
|
|
43
|
+
styleClassPassthrough: () => [],
|
|
44
|
+
})
|
|
45
|
+
defineSlots<AvatarSlots>()
|
|
46
|
+
|
|
47
|
+
const { elementClasses, resetElementClasses, updateElementClasses } = useStyleClassPassthrough(
|
|
48
|
+
props.styleClassPassthrough
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if (props.chip && typeof props.chip === "object" && !("styleClassPassthrough" in props.chip)) {
|
|
52
|
+
updateElementClasses(["display-avatar", props.size])
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const fallback = computed(
|
|
56
|
+
() =>
|
|
57
|
+
props.text ||
|
|
58
|
+
(props.alt || "")
|
|
59
|
+
.split(" ")
|
|
60
|
+
.map((word) => word.charAt(0))
|
|
61
|
+
.join("")
|
|
62
|
+
.substring(0, 2)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
const chipDefaultConfig = {
|
|
66
|
+
size: "12px",
|
|
67
|
+
maskWidth: "4px",
|
|
68
|
+
offset: "0px",
|
|
69
|
+
angle: "90deg",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
watch(
|
|
73
|
+
() => props.styleClassPassthrough,
|
|
74
|
+
() => {
|
|
75
|
+
resetElementClasses(props.styleClassPassthrough)
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<style lang="css">
|
|
81
|
+
.display-avatar {
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
border-radius: 50%;
|
|
86
|
+
color: var(--gray-3);
|
|
87
|
+
|
|
88
|
+
isolation: isolate;
|
|
89
|
+
|
|
90
|
+
&.xs {
|
|
91
|
+
width: 24px;
|
|
92
|
+
height: 24px;
|
|
93
|
+
font-size: 0.75rem;
|
|
94
|
+
}
|
|
95
|
+
&.s {
|
|
96
|
+
width: 32px;
|
|
97
|
+
height: 32px;
|
|
98
|
+
font-size: 0.875rem;
|
|
99
|
+
}
|
|
100
|
+
&.md {
|
|
101
|
+
width: 40px;
|
|
102
|
+
height: 40px;
|
|
103
|
+
font-size: 1rem;
|
|
104
|
+
}
|
|
105
|
+
&.lg {
|
|
106
|
+
width: 48px;
|
|
107
|
+
height: 48px;
|
|
108
|
+
font-size: 1.125rem;
|
|
109
|
+
}
|
|
110
|
+
&.xl {
|
|
111
|
+
width: 56px;
|
|
112
|
+
height: 56px;
|
|
113
|
+
font-size: 1.25rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.avatar-image {
|
|
117
|
+
width: 100%;
|
|
118
|
+
border-radius: 50%;
|
|
119
|
+
object-fit: cover;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<component :is="tag" class="display-chip-core" :class="[shape, elementClasses]" :style="chipStyles">
|
|
3
|
-
<slot></slot>
|
|
3
|
+
<slot name="default"></slot>
|
|
4
|
+
<Icon v-if="config?.icon" :name="config.icon" class="chip-icon" />
|
|
5
|
+
<span v-if="config?.label" class="chip-label" :class="`length-${config.label.length}`">{{ validatedLabel }}</span>
|
|
4
6
|
</component>
|
|
5
7
|
</template>
|
|
6
8
|
|
|
@@ -10,17 +12,20 @@ export interface DisplayChipConfig {
|
|
|
10
12
|
maskWidth: string
|
|
11
13
|
offset: string
|
|
12
14
|
angle: string
|
|
15
|
+
icon?: string
|
|
16
|
+
label?: string
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export interface DisplayChipProps {
|
|
16
20
|
tag?: "div" | "span"
|
|
17
21
|
shape?: "circle" | "square"
|
|
22
|
+
config?: DisplayChipConfig
|
|
18
23
|
styleClassPassthrough?: string | string[]
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export interface ChipSlots {
|
|
22
27
|
default(props?: {}): any
|
|
23
|
-
content(props?: {}): any
|
|
28
|
+
// content(props?: {}): any
|
|
24
29
|
}
|
|
25
30
|
</script>
|
|
26
31
|
|
|
@@ -28,33 +33,40 @@ export interface ChipSlots {
|
|
|
28
33
|
const props = withDefaults(defineProps<DisplayChipProps>(), {
|
|
29
34
|
tag: "div",
|
|
30
35
|
shape: "circle",
|
|
31
|
-
|
|
32
|
-
})
|
|
33
|
-
defineSlots<ChipSlots>()
|
|
34
|
-
|
|
35
|
-
const chipConfig = defineModel<DisplayChipConfig>({
|
|
36
|
-
type: Object as PropType<{
|
|
37
|
-
size: string
|
|
38
|
-
maskWidth: string
|
|
39
|
-
offset: string
|
|
40
|
-
angle: string
|
|
41
|
-
}>,
|
|
42
|
-
default: () => ({
|
|
36
|
+
config: () => ({
|
|
43
37
|
size: "12px",
|
|
44
38
|
maskWidth: "4px",
|
|
45
39
|
offset: "0px",
|
|
46
40
|
angle: "90deg",
|
|
41
|
+
icon: undefined,
|
|
42
|
+
label: undefined,
|
|
47
43
|
}),
|
|
48
|
-
|
|
44
|
+
styleClassPassthrough: () => [],
|
|
49
45
|
})
|
|
46
|
+
const slots = defineSlots<ChipSlots>()
|
|
47
|
+
// const slots = useSlots()
|
|
50
48
|
|
|
51
49
|
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
52
50
|
|
|
51
|
+
// Validate and truncate label to max 3 characters
|
|
52
|
+
const validatedLabel = computed(() => {
|
|
53
|
+
if (!props.config?.label) return props.config?.label
|
|
54
|
+
if (props.config.label.length > 3) {
|
|
55
|
+
console.warn(
|
|
56
|
+
`DisplayChip: label "${
|
|
57
|
+
props.config.label
|
|
58
|
+
}" exceeds maximum length of 3 characters. Truncating to "${props.config.label.slice(0, 3)}"`
|
|
59
|
+
)
|
|
60
|
+
return props.config.label.slice(0, 3)
|
|
61
|
+
}
|
|
62
|
+
return props.config.label
|
|
63
|
+
})
|
|
64
|
+
|
|
53
65
|
const chipStyles = computed(() => ({
|
|
54
|
-
"--chip-size":
|
|
55
|
-
"--chip-mask-width":
|
|
56
|
-
"--chip-offset":
|
|
57
|
-
"--chip-angle":
|
|
66
|
+
"--chip-size": props.config?.size,
|
|
67
|
+
"--chip-mask-width": props.config?.maskWidth,
|
|
68
|
+
"--chip-offset": props.config?.offset,
|
|
69
|
+
"--chip-angle": props.config?.angle,
|
|
58
70
|
}))
|
|
59
71
|
</script>
|
|
60
72
|
|
|
@@ -92,6 +104,43 @@ const chipStyles = computed(() => ({
|
|
|
92
104
|
position: absolute;
|
|
93
105
|
width: var(--chip-size);
|
|
94
106
|
border-radius: 100%;
|
|
107
|
+
z-index: 1;
|
|
108
|
+
}
|
|
109
|
+
.chip-icon {
|
|
110
|
+
position: absolute;
|
|
111
|
+
width: var(--chip-size);
|
|
112
|
+
height: var(--chip-size);
|
|
113
|
+
border-radius: 100%;
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
justify-content: center;
|
|
117
|
+
color: black;
|
|
118
|
+
z-index: 2;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.chip-label {
|
|
122
|
+
--_font-size-adjust: 0.7;
|
|
123
|
+
position: absolute;
|
|
124
|
+
width: var(--chip-size);
|
|
125
|
+
height: var(--chip-size);
|
|
126
|
+
border-radius: 100%;
|
|
127
|
+
display: flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
color: black;
|
|
131
|
+
z-index: 2;
|
|
132
|
+
font-size: calc(var(--chip-size) * var(--_font-size-adjust));
|
|
133
|
+
line-height: 1;
|
|
134
|
+
letter-spacing: -0.05rem;
|
|
135
|
+
user-select: none;
|
|
136
|
+
|
|
137
|
+
&.length-2 {
|
|
138
|
+
--_font-size-adjust: 0.6;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
&.length-3 {
|
|
142
|
+
--_font-size-adjust: 0.5;
|
|
143
|
+
}
|
|
95
144
|
}
|
|
96
145
|
|
|
97
146
|
& > * {
|
|
@@ -101,23 +150,29 @@ const chipStyles = computed(() => ({
|
|
|
101
150
|
psuedo-element ::after
|
|
102
151
|
*/
|
|
103
152
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
var(--computed-position-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
153
|
+
&:not(.chip-icon, .chip-label) {
|
|
154
|
+
mask-image: radial-gradient(
|
|
155
|
+
var(--computed-mask-diameter) var(--computed-mask-diameter) at var(--computed-position-x)
|
|
156
|
+
var(--computed-position-y),
|
|
157
|
+
transparent calc(50% - 0.5px),
|
|
158
|
+
black calc(50% + 0.5px)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
110
161
|
}
|
|
111
162
|
|
|
112
163
|
&.circle {
|
|
113
|
-
&::after
|
|
164
|
+
&::after,
|
|
165
|
+
.chip-icon,
|
|
166
|
+
.chip-label {
|
|
114
167
|
top: calc(var(--computed-position-y) - (var(--chip-size) / 2));
|
|
115
168
|
left: calc(var(--computed-position-x) - (var(--chip-size) / 2));
|
|
116
169
|
}
|
|
117
170
|
}
|
|
118
171
|
|
|
119
172
|
&.square {
|
|
120
|
-
&::after
|
|
173
|
+
&::after,
|
|
174
|
+
.chip-icon,
|
|
175
|
+
.chip-label {
|
|
121
176
|
top: calc(var(--computed-position-y) - (var(--chip-size) / 2));
|
|
122
177
|
left: calc(var(--computed-position-x) - (var(--chip-size) / 2));
|
|
123
178
|
}
|
|
@@ -138,9 +193,5 @@ const chipStyles = computed(() => ({
|
|
|
138
193
|
background-color: var(--color-dnd);
|
|
139
194
|
}
|
|
140
195
|
}
|
|
141
|
-
|
|
142
|
-
.chip-label {
|
|
143
|
-
display: none;
|
|
144
|
-
}
|
|
145
196
|
}
|
|
146
197
|
</style>
|
package/package.json
CHANGED