@fastkit/vui 0.7.46 → 0.7.49
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/vui.cjs.js +414 -3
- package/dist/vui.cjs.prod.js +414 -3
- package/dist/vui.css +230 -1
- package/dist/vui.d.ts +688 -0
- package/dist/vui.min.css +1 -1
- package/dist/vui.min.css.map +1 -1
- package/dist/vui.mjs +408 -6
- package/package.json +6 -6
- package/src/components/.DS_Store +0 -0
- package/src/components/VAvatar/.DS_Store +0 -0
- package/src/components/VAvatar/VAvatar.scss +76 -0
- package/src/components/VAvatar/VAvatar.tsx +81 -0
- package/src/components/VAvatar/index.ts +1 -0
- package/src/components/VBusyImage/VBusyImage.scss +58 -0
- package/src/components/VBusyImage/VBusyImage.tsx +278 -0
- package/src/components/VBusyImage/index.ts +1 -0
- package/src/components/VButton/VButton.scss +2 -1
- package/src/components/VChip/.DS_Store +0 -0
- package/src/components/VChip/VChip.scss +78 -0
- package/src/components/VChip/VChip.tsx +102 -0
- package/src/components/VChip/index.ts +1 -0
- package/src/components/VFormControl/VFormControl.tsx +1 -1
- package/src/components/VSkeltonLoader/.DS_Store +0 -0
- package/src/components/VSkeltonLoader/VSkeltonLoaderBone.scss +31 -0
- package/src/components/VSkeltonLoader/VSkeltonLoaderBone.tsx +25 -0
- package/src/components/VSkeltonLoader/index.ts +1 -0
- package/src/components/VWysiwygEditor/VWysiwygEditor.tsx +5 -4
- package/src/components/index.ts +4 -0
- package/src/styles/variables.scss +19 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.v-busy-image {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-block;
|
|
4
|
+
max-width: 100%;
|
|
5
|
+
vertical-align: bottom;
|
|
6
|
+
|
|
7
|
+
&--clickable {
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&--cover {
|
|
12
|
+
background-repeat: no-repeat;
|
|
13
|
+
background-position: center;
|
|
14
|
+
background-size: cover;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&--loading::before {
|
|
18
|
+
position: absolute;
|
|
19
|
+
top: 0;
|
|
20
|
+
right: 0;
|
|
21
|
+
bottom: 0;
|
|
22
|
+
left: 0;
|
|
23
|
+
display: block;
|
|
24
|
+
content: '';
|
|
25
|
+
background: rgba(0, 0, 0, 0.1);
|
|
26
|
+
animation: v-tiny-image-blink normal 1.5s infinite ease-in-out;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&__node {
|
|
30
|
+
position: relative;
|
|
31
|
+
display: inline-block;
|
|
32
|
+
max-width: 100%;
|
|
33
|
+
vertical-align: bottom;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&__slot {
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: 0;
|
|
39
|
+
left: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@keyframes v-tiny-image-blink {
|
|
47
|
+
0% {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
50% {
|
|
52
|
+
opacity: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
100% {
|
|
56
|
+
opacity: 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import './VBusyImage.scss';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
defineComponent,
|
|
5
|
+
HTMLAttributes,
|
|
6
|
+
ImgHTMLAttributes,
|
|
7
|
+
PropType,
|
|
8
|
+
computed,
|
|
9
|
+
ref,
|
|
10
|
+
watch,
|
|
11
|
+
onMounted,
|
|
12
|
+
onBeforeUnmount,
|
|
13
|
+
CSSProperties,
|
|
14
|
+
} from 'vue';
|
|
15
|
+
import { IN_WINDOW, loadImage } from '@fastkit/helpers';
|
|
16
|
+
import { defineSlotsProps } from '@fastkit/vue-utils';
|
|
17
|
+
|
|
18
|
+
export declare type ImgHTMLAttributesPropOptions = {
|
|
19
|
+
[K in keyof ImgHTMLAttributes]-?: PropType<ImgHTMLAttributes[K]>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const IMAGE_ATTRS = [
|
|
23
|
+
'alt',
|
|
24
|
+
'crossorigin',
|
|
25
|
+
'decoding',
|
|
26
|
+
'sizes',
|
|
27
|
+
'src',
|
|
28
|
+
'srcset',
|
|
29
|
+
'usemap',
|
|
30
|
+
] as const;
|
|
31
|
+
|
|
32
|
+
export function splitAttrs(attrs: ImgHTMLAttributes): {
|
|
33
|
+
el: HTMLAttributes;
|
|
34
|
+
img: ImgHTMLAttributes;
|
|
35
|
+
} {
|
|
36
|
+
const el: HTMLAttributes = { ...attrs };
|
|
37
|
+
const img: ImgHTMLAttributes = {};
|
|
38
|
+
|
|
39
|
+
for (const ATTR of IMAGE_ATTRS) {
|
|
40
|
+
const value = attrs[ATTR];
|
|
41
|
+
if (value != null) {
|
|
42
|
+
img[ATTR] = value as any;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
el,
|
|
48
|
+
img,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type BusyImageLoadState = 'pending' | 'loading' | 'loaded' | 'error';
|
|
53
|
+
|
|
54
|
+
export type BusyImageSizeValue = number | string;
|
|
55
|
+
|
|
56
|
+
const NUMBERISH_PROP = [Number, String] as PropType<BusyImageSizeValue>;
|
|
57
|
+
|
|
58
|
+
const DEFAULT_HEIGHT = 150;
|
|
59
|
+
|
|
60
|
+
const resolveBusyImageSizeValue = (
|
|
61
|
+
source?: BusyImageSizeValue,
|
|
62
|
+
): string | undefined => {
|
|
63
|
+
if (source == null) return;
|
|
64
|
+
return isNaN(source as number) ? String(source) : `${source}px`;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export interface BusyImageRect {
|
|
68
|
+
width?: string;
|
|
69
|
+
height?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface BusyImageRects {
|
|
73
|
+
placeholder: BusyImageRect;
|
|
74
|
+
main: BusyImageRect;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 画像表示用コンポーネント
|
|
79
|
+
* <img /> タグのように振る舞うが、ローディング表示や、表示サイズの調整など、ちょっといい感じにやるためのコンポーネント
|
|
80
|
+
*/
|
|
81
|
+
export const VBusyImage = defineComponent({
|
|
82
|
+
name: 'VBusyImage',
|
|
83
|
+
props: {
|
|
84
|
+
...(undefined as unknown as ImgHTMLAttributesPropOptions),
|
|
85
|
+
aspectRatio: String,
|
|
86
|
+
width: NUMBERISH_PROP,
|
|
87
|
+
height: NUMBERISH_PROP,
|
|
88
|
+
cover: Boolean,
|
|
89
|
+
...defineSlotsProps<{
|
|
90
|
+
default: void;
|
|
91
|
+
}>(),
|
|
92
|
+
},
|
|
93
|
+
emits: {
|
|
94
|
+
load: (ev: Event) => true,
|
|
95
|
+
error: (ev: Event) => true,
|
|
96
|
+
},
|
|
97
|
+
setup(props, ctx) {
|
|
98
|
+
const loadStateRef = ref<BusyImageLoadState>(
|
|
99
|
+
props.cover && isAvairableSrc(ctx.attrs.src as any)
|
|
100
|
+
? 'loading'
|
|
101
|
+
: 'pending',
|
|
102
|
+
);
|
|
103
|
+
const attrsRef = computed(() => splitAttrs(ctx.attrs));
|
|
104
|
+
const isPendingRef = computed(() => loadStateRef.value === 'pending');
|
|
105
|
+
const isLoadingRef = computed(() => loadStateRef.value === 'loading');
|
|
106
|
+
const isLoadedRef = computed(() => loadStateRef.value === 'loaded');
|
|
107
|
+
const isErrorRef = computed(() => loadStateRef.value === 'error');
|
|
108
|
+
const classesRef = computed(() => [
|
|
109
|
+
`v-busy-image--${loadStateRef.value}`,
|
|
110
|
+
{
|
|
111
|
+
'v-busy-image--cover': props.cover,
|
|
112
|
+
'v-busy-image--clickable': typeof ctx.attrs.onClick === 'function',
|
|
113
|
+
},
|
|
114
|
+
]);
|
|
115
|
+
const nodeRef = ref<HTMLImageElement>();
|
|
116
|
+
const coverImageRef = ref<HTMLImageElement>();
|
|
117
|
+
const rectsRef = computed<BusyImageRects>(() => {
|
|
118
|
+
const placeholder: BusyImageRect = {};
|
|
119
|
+
const main: BusyImageRect = {};
|
|
120
|
+
const { cover } = props;
|
|
121
|
+
let { width, height } = props;
|
|
122
|
+
|
|
123
|
+
if (height == null && cover) {
|
|
124
|
+
height = DEFAULT_HEIGHT;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (width == null && cover) {
|
|
128
|
+
width = height;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
width = resolveBusyImageSizeValue(width);
|
|
132
|
+
height = resolveBusyImageSizeValue(height);
|
|
133
|
+
|
|
134
|
+
main.width = width;
|
|
135
|
+
main.height = height;
|
|
136
|
+
|
|
137
|
+
placeholder.width = width;
|
|
138
|
+
placeholder.height = height;
|
|
139
|
+
|
|
140
|
+
if (placeholder.height == null) {
|
|
141
|
+
placeholder.height = resolveBusyImageSizeValue(DEFAULT_HEIGHT);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (placeholder.width == null) {
|
|
145
|
+
placeholder.width = placeholder.height;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
placeholder,
|
|
150
|
+
main,
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const currentRectRef = computed<BusyImageRect>(() =>
|
|
155
|
+
isLoadedRef.value ? rectsRef.value.main : rectsRef.value.placeholder,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const stylesRef = computed<CSSProperties>(() => {
|
|
159
|
+
const { value: coverImage } = coverImageRef;
|
|
160
|
+
const coverSrc = coverImage && coverImage.src;
|
|
161
|
+
const styles: CSSProperties = {
|
|
162
|
+
...currentRectRef.value,
|
|
163
|
+
};
|
|
164
|
+
if (coverSrc) {
|
|
165
|
+
styles.backgroundImage = `url(${coverSrc})`;
|
|
166
|
+
}
|
|
167
|
+
return styles;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
let booted = false;
|
|
171
|
+
|
|
172
|
+
watch(
|
|
173
|
+
() => ctx.attrs.src as string | null | undefined,
|
|
174
|
+
(value) => {
|
|
175
|
+
coverImageRef.value = undefined;
|
|
176
|
+
if (isAvairableSrc(value)) {
|
|
177
|
+
loadStateRef.value = 'loading';
|
|
178
|
+
if (props.cover) {
|
|
179
|
+
loadImage(value)
|
|
180
|
+
.then((image) => {
|
|
181
|
+
coverImageRef.value = image;
|
|
182
|
+
setManualState('load');
|
|
183
|
+
})
|
|
184
|
+
.catch((err) => {
|
|
185
|
+
setManualState('error');
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
loadStateRef.value = 'pending';
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
{ immediate: IN_WINDOW },
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const setManualState = (loadType: 'load' | 'error') => {
|
|
196
|
+
loadStateRef.value = loadType === 'load' ? 'loaded' : 'error';
|
|
197
|
+
|
|
198
|
+
const ev = new Event(loadType, {
|
|
199
|
+
bubbles: false,
|
|
200
|
+
cancelable: false,
|
|
201
|
+
composed: false,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
ctx.emit(loadType as any, ev);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
onMounted(() => {
|
|
208
|
+
if (booted || props.cover) return;
|
|
209
|
+
|
|
210
|
+
const image = nodeRef.value;
|
|
211
|
+
if (!image) return;
|
|
212
|
+
|
|
213
|
+
const loadType = imageIsReady(image);
|
|
214
|
+
|
|
215
|
+
if (loadType) {
|
|
216
|
+
setManualState(loadType);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
onBeforeUnmount(() => {
|
|
221
|
+
coverImageRef.value = undefined;
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const handleLoad = (ev: Event) => {
|
|
225
|
+
booted = true;
|
|
226
|
+
loadStateRef.value = 'loaded';
|
|
227
|
+
ctx.emit('load', ev);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const handleError = (ev: Event) => {
|
|
231
|
+
booted = true;
|
|
232
|
+
loadStateRef.value = 'error';
|
|
233
|
+
ctx.emit('error', ev);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
ctx.expose({
|
|
237
|
+
state: loadStateRef,
|
|
238
|
+
isPending: isPendingRef,
|
|
239
|
+
isLoading: isLoadingRef,
|
|
240
|
+
isLoaded: isLoadedRef,
|
|
241
|
+
isError: isErrorRef,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
return () => {
|
|
245
|
+
const { el: elAttrs, img: imgAttrs } = attrsRef.value;
|
|
246
|
+
const styles = stylesRef.value;
|
|
247
|
+
const children = ctx.slots.default && ctx.slots.default();
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<span
|
|
251
|
+
class={['v-busy-image', classesRef.value]}
|
|
252
|
+
{...elAttrs}
|
|
253
|
+
style={styles}>
|
|
254
|
+
{!props.cover && (
|
|
255
|
+
<img
|
|
256
|
+
key="img"
|
|
257
|
+
ref={nodeRef}
|
|
258
|
+
class="v-busy-image__node"
|
|
259
|
+
{...imgAttrs}
|
|
260
|
+
onLoad={handleLoad}
|
|
261
|
+
onError={handleError}
|
|
262
|
+
/>
|
|
263
|
+
)}
|
|
264
|
+
{!!children && <span class="v-busy-image__slot">{children}</span>}
|
|
265
|
+
</span>
|
|
266
|
+
);
|
|
267
|
+
};
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
function imageIsReady(image: HTMLImageElement): 'load' | 'error' | false {
|
|
272
|
+
if (!image.complete) return false;
|
|
273
|
+
return image.naturalWidth + image.naturalHeight > 0 ? 'load' : 'error';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function isAvairableSrc(src: string | null | undefined): src is string {
|
|
277
|
+
return typeof src === 'string' && src !== '';
|
|
278
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './VBusyImage';
|
|
Binary file
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
@use '../../styles/core.scss';
|
|
2
|
+
|
|
3
|
+
.v-chip {
|
|
4
|
+
@include core.button-reset();
|
|
5
|
+
|
|
6
|
+
$chip-sizes: xs, sm, md, lg, xl;
|
|
7
|
+
|
|
8
|
+
--chip-radius: calc(var(--chip-height) / 2);
|
|
9
|
+
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
height: var(--chip-height);
|
|
14
|
+
padding: 0 var(--chip-padding);
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
font-size: var(--chip-font-size);
|
|
17
|
+
font-weight: var(--chip-font-weight);
|
|
18
|
+
line-height: 1;
|
|
19
|
+
text-align: center;
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
vertical-align: bottom;
|
|
22
|
+
cursor: default;
|
|
23
|
+
border-style: solid;
|
|
24
|
+
border-width: 1px;
|
|
25
|
+
border-radius: var(--chip-radius);
|
|
26
|
+
|
|
27
|
+
--shadow-color: rgba(0, 0, 0, 0) !important; // @TODO layer supports
|
|
28
|
+
--focusShadow-color: rgba(0, 0, 0, 0) !important; // @TODO layer supports
|
|
29
|
+
|
|
30
|
+
&--clickable {
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@each $size in $chip-sizes {
|
|
35
|
+
&--#{$size} {
|
|
36
|
+
--chip-height: var(--chip-height-#{$size});
|
|
37
|
+
--chip-font-size: var(--chip-font-size-#{$size});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&--label {
|
|
42
|
+
--chip-radius: 4px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// &[disabled] {
|
|
46
|
+
// pointer-events: none;
|
|
47
|
+
|
|
48
|
+
// &::before {
|
|
49
|
+
// content: none;
|
|
50
|
+
// }
|
|
51
|
+
// }
|
|
52
|
+
// // noop
|
|
53
|
+
|
|
54
|
+
// img,
|
|
55
|
+
// &__image {
|
|
56
|
+
// display: inline-flex;
|
|
57
|
+
// width: inherit !important;
|
|
58
|
+
// height: inherit !important;
|
|
59
|
+
// border-radius: inherit;
|
|
60
|
+
// object-fit: cover;
|
|
61
|
+
// }
|
|
62
|
+
|
|
63
|
+
&__icon {
|
|
64
|
+
&--start {
|
|
65
|
+
margin-right: calc(var(--chip-padding) * 0.5);
|
|
66
|
+
margin-left: calc(var(--chip-padding) * -0.5);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&--end {
|
|
70
|
+
margin-right: calc(var(--chip-padding) * -0.5);
|
|
71
|
+
margin-left: calc(var(--chip-padding) * 0.5);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.v-avatar {
|
|
76
|
+
--avatar-size: 14px;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import './VChip.scss';
|
|
2
|
+
import { defineComponent, computed, PropType, VNodeChild } from 'vue';
|
|
3
|
+
import {
|
|
4
|
+
navigationableInheritProps,
|
|
5
|
+
useNavigationable,
|
|
6
|
+
renderSlotOrEmpty,
|
|
7
|
+
} from '@fastkit/vue-utils';
|
|
8
|
+
import { colorSchemeProps, useColorClasses } from '@fastkit/vue-color-scheme';
|
|
9
|
+
import { useVui } from '../../injections';
|
|
10
|
+
import type { IconName } from '../VIcon';
|
|
11
|
+
import { VIcon } from '../VIcon';
|
|
12
|
+
|
|
13
|
+
export const CHIP_SIZES = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
|
|
14
|
+
|
|
15
|
+
export type ChipSize = typeof CHIP_SIZES[number];
|
|
16
|
+
|
|
17
|
+
export type VChipIcon = () => VNodeChild;
|
|
18
|
+
|
|
19
|
+
export type RawVChipIcon = IconName | VChipIcon;
|
|
20
|
+
|
|
21
|
+
export function createChipProps() {
|
|
22
|
+
return {
|
|
23
|
+
...colorSchemeProps(),
|
|
24
|
+
...navigationableInheritProps,
|
|
25
|
+
size: {
|
|
26
|
+
type: String as PropType<ChipSize>,
|
|
27
|
+
default: 'md',
|
|
28
|
+
},
|
|
29
|
+
startIcon: [String, Function] as PropType<RawVChipIcon>,
|
|
30
|
+
endIcon: [String, Function] as PropType<RawVChipIcon>,
|
|
31
|
+
label: Boolean,
|
|
32
|
+
disabled: Boolean,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveRawVChipIcon(
|
|
37
|
+
raw: RawVChipIcon | undefined,
|
|
38
|
+
type: 'start' | 'end',
|
|
39
|
+
): VChipIcon | undefined {
|
|
40
|
+
if (!raw) return;
|
|
41
|
+
if (typeof raw === 'function') {
|
|
42
|
+
return () => {
|
|
43
|
+
const child = raw();
|
|
44
|
+
if (child == null) return;
|
|
45
|
+
return (
|
|
46
|
+
<span class={['v-chip__icon', `v-chip__icon--${type}`]}>{child}</span>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return () => (
|
|
51
|
+
<VIcon class={['v-chip__icon', `v-chip__icon--${type}`]} name={raw} />
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const VChip = defineComponent({
|
|
56
|
+
name: 'VChip',
|
|
57
|
+
inheritAttrs: false,
|
|
58
|
+
props: createChipProps(),
|
|
59
|
+
setup(props, ctx) {
|
|
60
|
+
const vui = useVui();
|
|
61
|
+
const defaults = vui.setting('buttonDefault');
|
|
62
|
+
const color = useColorClasses({
|
|
63
|
+
color: () => props.color || defaults.color,
|
|
64
|
+
variant: () => props.variant || defaults.variant,
|
|
65
|
+
});
|
|
66
|
+
const startIcon = computed(() => {
|
|
67
|
+
const _icon = resolveRawVChipIcon(props.startIcon, 'start');
|
|
68
|
+
return _icon && _icon();
|
|
69
|
+
});
|
|
70
|
+
const endIcon = computed(() => {
|
|
71
|
+
const _icon = resolveRawVChipIcon(props.endIcon, 'end');
|
|
72
|
+
return _icon && _icon();
|
|
73
|
+
});
|
|
74
|
+
const navigationable = useNavigationable(ctx, {
|
|
75
|
+
clickableClassName: () => 'v-chip--clickable',
|
|
76
|
+
linkFallbackTag: 'div',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const classes = computed(() => {
|
|
80
|
+
const { size } = props;
|
|
81
|
+
return [
|
|
82
|
+
{
|
|
83
|
+
'v-chip--label': props.label,
|
|
84
|
+
},
|
|
85
|
+
typeof size === 'string' && `v-chip--${size}`,
|
|
86
|
+
];
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return () => {
|
|
90
|
+
const { Tag, attrs } = navigationable.value;
|
|
91
|
+
return (
|
|
92
|
+
<Tag
|
|
93
|
+
{...attrs}
|
|
94
|
+
class={['v-chip', classes.value, color.colorClasses.value]}>
|
|
95
|
+
{startIcon.value}
|
|
96
|
+
<span class="v-chip__content">{renderSlotOrEmpty(ctx.slots)}</span>
|
|
97
|
+
{endIcon.value}
|
|
98
|
+
</Tag>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './VChip';
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
.v-skelton-loader-bone {
|
|
2
|
+
position: relative;
|
|
3
|
+
overflow: hidden;
|
|
4
|
+
cursor: progress;
|
|
5
|
+
background: rgba(0, 0, 0, 0.12);
|
|
6
|
+
border-radius: inherit;
|
|
7
|
+
|
|
8
|
+
&::after {
|
|
9
|
+
position: absolute;
|
|
10
|
+
top: 0;
|
|
11
|
+
right: 0;
|
|
12
|
+
left: 0;
|
|
13
|
+
z-index: 1;
|
|
14
|
+
height: 100%;
|
|
15
|
+
content: '';
|
|
16
|
+
background: linear-gradient(
|
|
17
|
+
90deg,
|
|
18
|
+
hsla(0deg, 0%, 100%, 0),
|
|
19
|
+
hsla(0deg, 0%, 100%, 0.3),
|
|
20
|
+
hsla(0deg, 0%, 100%, 0)
|
|
21
|
+
);
|
|
22
|
+
transform: translateX(-100%);
|
|
23
|
+
animation: v-skelton-loader-bone-loading 1.5s infinite;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@keyframes v-skelton-loader-bone-loading {
|
|
28
|
+
100% {
|
|
29
|
+
transform: translateX(100%);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import './VSkeltonLoaderBone.scss';
|
|
2
|
+
|
|
3
|
+
import { defineComponent } from 'vue';
|
|
4
|
+
import { renderSlotOrEmpty } from '@fastkit/vue-utils';
|
|
5
|
+
|
|
6
|
+
export const VSkeltonLoaderBone = defineComponent({
|
|
7
|
+
name: 'VSkeltonLoaderBone',
|
|
8
|
+
inheritAttrs: false,
|
|
9
|
+
props: {
|
|
10
|
+
tag: {
|
|
11
|
+
type: String,
|
|
12
|
+
default: 'div',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
setup(props, ctx) {
|
|
16
|
+
return () => {
|
|
17
|
+
const TagName = props.tag as 'div';
|
|
18
|
+
return (
|
|
19
|
+
<TagName {...ctx.attrs} class="v-skelton-loader-bone">
|
|
20
|
+
{renderSlotOrEmpty(ctx.slots)}
|
|
21
|
+
</TagName>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './VSkeltonLoaderBone';
|
|
@@ -99,10 +99,10 @@ export const VWysiwygEditor = defineComponent({
|
|
|
99
99
|
watch(
|
|
100
100
|
() => props.modelValue,
|
|
101
101
|
(modelValue) => {
|
|
102
|
-
editor.value
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
const $editor = editor.value;
|
|
103
|
+
if (!$editor) return;
|
|
104
|
+
$editor.commands.setContent(modelValue == null ? '' : modelValue);
|
|
105
|
+
textRef.value = $editor.getText();
|
|
106
106
|
},
|
|
107
107
|
);
|
|
108
108
|
|
|
@@ -120,6 +120,7 @@ export const VWysiwygEditor = defineComponent({
|
|
|
120
120
|
onUpdate: (ev) => {
|
|
121
121
|
inputControl.value = ev.editor.getHTML();
|
|
122
122
|
textRef.value = ev.editor.getText();
|
|
123
|
+
console.log(textRef.value);
|
|
123
124
|
},
|
|
124
125
|
autofocus: props.autofocus,
|
|
125
126
|
content: props.modelValue,
|
package/src/components/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export * from './loading';
|
|
2
2
|
export * from './kits';
|
|
3
|
+
export * from './VSkeltonLoader';
|
|
4
|
+
export * from './VBusyImage';
|
|
3
5
|
export * from './VGrid';
|
|
4
6
|
export * from './VPaper';
|
|
7
|
+
export * from './VAvatar';
|
|
8
|
+
export * from './VChip';
|
|
5
9
|
export * from './VCard';
|
|
6
10
|
export * from './VIcon';
|
|
7
11
|
export * from './VButton';
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
--typo-base-height: 1.5;
|
|
31
31
|
--typo-base-spacing: 0em;
|
|
32
32
|
|
|
33
|
+
// medium
|
|
34
|
+
--typo-medium-weight: 500;
|
|
35
|
+
|
|
33
36
|
// h1
|
|
34
37
|
--typo-h1-size: 2.5rem;
|
|
35
38
|
--typo-h1-weight: 500;
|
|
@@ -123,6 +126,22 @@
|
|
|
123
126
|
// --typo-overline-height: 2.66;
|
|
124
127
|
// --typo-overline-spacing: 0.08333em;
|
|
125
128
|
|
|
129
|
+
// =============================================
|
|
130
|
+
// chips
|
|
131
|
+
// =============================================
|
|
132
|
+
--chip-padding: 0.875em;
|
|
133
|
+
--chip-font-weight: var(--typo-base-weight);
|
|
134
|
+
--chip-height-xs: 16px;
|
|
135
|
+
--chip-font-size-xs: 10px;
|
|
136
|
+
--chip-height-sm: 24px;
|
|
137
|
+
--chip-font-size-sm: 12px;
|
|
138
|
+
--chip-height-md: 32px;
|
|
139
|
+
--chip-font-size-md: 14px;
|
|
140
|
+
--chip-height-lg: 54px;
|
|
141
|
+
--chip-font-size-lg: 16px;
|
|
142
|
+
--chip-height-xl: 66px;
|
|
143
|
+
--chip-font-size-xl: 18px;
|
|
144
|
+
|
|
126
145
|
// =============================================
|
|
127
146
|
// controls
|
|
128
147
|
// =============================================
|