@14ch/svelte-ui 0.0.9 → 0.0.10
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/assets/styles/variables.scss +15 -16
- package/dist/components/ColorPicker.svelte +16 -11
- package/dist/components/ColorPicker.svelte.d.ts +2 -2
- package/dist/components/Combobox.svelte +3 -3
- package/dist/components/Combobox.svelte.d.ts +2 -2
- package/dist/components/ConfirmDialog.svelte +8 -8
- package/dist/components/ConfirmDialog.svelte.d.ts +2 -2
- package/dist/components/DatepickerCalendar.svelte +1 -1
- package/dist/components/DatepickerCalendar.svelte.d.ts +1 -1
- package/dist/components/Input.svelte +2 -2
- package/dist/components/Input.svelte.d.ts +2 -2
- package/dist/components/Radio.svelte +1 -1
- package/dist/components/Radio.svelte.d.ts +1 -1
- package/dist/components/Select.svelte +1 -1
- package/dist/components/Select.svelte.d.ts +1 -1
- package/dist/components/Slider.svelte +2 -2
- package/dist/components/Slider.svelte.d.ts +2 -2
- package/dist/components/Textarea.svelte +20 -11
- package/dist/components/Textarea.svelte.d.ts +2 -2
- package/dist/components/skeleton/Skeleton.svelte +9 -71
- package/dist/components/skeleton/Skeleton.svelte.d.ts +1 -1
- package/dist/components/skeleton/SkeletonAvatar.svelte +7 -25
- package/dist/components/skeleton/SkeletonBox.svelte +2 -11
- package/dist/components/skeleton/SkeletonButton.svelte +1 -10
- package/dist/components/skeleton/SkeletonHeading.svelte +10 -10
- package/dist/components/skeleton/SkeletonMedia.svelte +9 -30
- package/dist/components/skeleton/SkeletonText.svelte +2 -9
- package/package.json +1 -1
|
@@ -684,18 +684,24 @@
|
|
|
684
684
|
--svelte-ui-snackbar-error-outlined-border-color: var(--svelte-ui-error-color);
|
|
685
685
|
|
|
686
686
|
/* Skeleton */
|
|
687
|
+
--svelte-ui-skeleton-box-height: 240px;
|
|
687
688
|
--svelte-ui-skeleton-box-border-radius: var(--svelte-ui-border-radius);
|
|
688
|
-
--svelte-ui-skeleton-text-border-radius: var(--svelte-ui-border-radius);
|
|
689
|
+
--svelte-ui-skeleton-text-border-radius: var(--svelte-ui-border-radius-rounded);
|
|
690
|
+
--svelte-ui-skeleton-text-line-height: 1em;
|
|
689
691
|
--svelte-ui-skeleton-avatar-image-border-radius: var(--svelte-ui-border-radius-rounded);
|
|
690
|
-
--svelte-ui-skeleton-image-
|
|
692
|
+
--svelte-ui-skeleton-avatar-image-size: 48px;
|
|
693
|
+
--svelte-ui-skeleton-avatar-text-width: 160px;
|
|
691
694
|
--svelte-ui-skeleton-button-border-radius: var(--svelte-ui-border-radius);
|
|
692
|
-
--svelte-ui-skeleton-
|
|
693
|
-
--svelte-ui-skeleton-
|
|
694
|
-
--svelte-ui-skeleton-
|
|
695
|
-
--svelte-ui-skeleton-
|
|
696
|
-
--svelte-ui-skeleton-
|
|
697
|
-
--svelte-ui-skeleton-
|
|
698
|
-
--svelte-ui-skeleton-
|
|
695
|
+
--svelte-ui-skeleton-button-width: 120px;
|
|
696
|
+
--svelte-ui-skeleton-button-height: 36px;
|
|
697
|
+
--svelte-ui-skeleton-media-thumbnail-border-radius: var(--svelte-ui-border-radius);
|
|
698
|
+
--svelte-ui-skeleton-media-thumbnail-width: 160px;
|
|
699
|
+
--svelte-ui-skeleton-media-gap: 16px;
|
|
700
|
+
--svelte-ui-skeleton-media-vertical-gap: 8px;
|
|
701
|
+
--svelte-ui-skeleton-heading-width: 50%;
|
|
702
|
+
--svelte-ui-skeleton-heading-font-size: 2rem;
|
|
703
|
+
--svelte-ui-skeleton-pattern-gap: 16px;
|
|
704
|
+
--svelte-ui-skeleton-repeat-gap: 24px;
|
|
699
705
|
|
|
700
706
|
/* Badge */
|
|
701
707
|
--svelte-ui-badge-font-size: var(--svelte-ui-font-size-sm);
|
|
@@ -821,12 +827,5 @@
|
|
|
821
827
|
/* ===== スケルトンの上書き ===== */
|
|
822
828
|
--svelte-ui-skeleton-color: CanvasText;
|
|
823
829
|
--svelte-ui-skeleton-shimmer-color: Highlight;
|
|
824
|
-
--svelte-ui-skeleton-bg-color: CanvasText;
|
|
825
|
-
--svelte-ui-skeleton-text-bg-color: CanvasText;
|
|
826
|
-
--svelte-ui-skeleton-image-bg-color: CanvasText;
|
|
827
|
-
--svelte-ui-skeleton-button-bg-color: CanvasText;
|
|
828
|
-
--svelte-ui-skeleton-input-bg-color: CanvasText;
|
|
829
|
-
--svelte-ui-skeleton-textarea-bg-color: CanvasText;
|
|
830
|
-
--svelte-ui-skeleton-avatar-bg-color: CanvasText;
|
|
831
830
|
}
|
|
832
831
|
}
|
|
@@ -92,8 +92,8 @@
|
|
|
92
92
|
iconVariant?: IconVariant;
|
|
93
93
|
|
|
94
94
|
// 入力イベント
|
|
95
|
-
onchange?: (value:
|
|
96
|
-
oninput?: (value:
|
|
95
|
+
onchange?: (value: string) => void;
|
|
96
|
+
oninput?: (value: string) => void;
|
|
97
97
|
|
|
98
98
|
// フォーカスイベント
|
|
99
99
|
onfocus?: Function; // No params for type inference
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
localValue = value;
|
|
149
149
|
|
|
150
150
|
/* value が更新されたらonchangeを実行 */
|
|
151
|
-
|
|
151
|
+
handleValueChange();
|
|
152
152
|
});
|
|
153
153
|
});
|
|
154
154
|
|
|
@@ -167,10 +167,11 @@
|
|
|
167
167
|
// Methods
|
|
168
168
|
// =========================================================================
|
|
169
169
|
|
|
170
|
-
const handleChange = (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
const handleChange = (value: string): void => {
|
|
171
|
+
if (value && !value.startsWith('#')) {
|
|
172
|
+
localValue = '#' + value;
|
|
173
|
+
} else {
|
|
174
|
+
localValue = value;
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
if (value !== prevValue || localValue !== prevValue) {
|
|
@@ -180,9 +181,13 @@
|
|
|
180
181
|
}
|
|
181
182
|
};
|
|
182
183
|
|
|
183
|
-
const
|
|
184
|
+
const handleValueChange = (): void => {
|
|
185
|
+
handleChange(localValue);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const handleInput = (inputValue: string | number): void => {
|
|
184
189
|
if (disabled) return;
|
|
185
|
-
oninput?.(
|
|
190
|
+
oninput?.(String(inputValue));
|
|
186
191
|
};
|
|
187
192
|
|
|
188
193
|
const handleFocus = (event: FocusEvent): void => {
|
|
@@ -205,7 +210,7 @@
|
|
|
205
210
|
// Enterキーで色の変更を確定
|
|
206
211
|
if (event.key === 'Enter' && !disabled && !readonly) {
|
|
207
212
|
event.preventDefault();
|
|
208
|
-
|
|
213
|
+
handleValueChange();
|
|
209
214
|
}
|
|
210
215
|
if (disabled) return;
|
|
211
216
|
onkeydown(event);
|
|
@@ -368,7 +373,7 @@
|
|
|
368
373
|
<input
|
|
369
374
|
type="color"
|
|
370
375
|
bind:value
|
|
371
|
-
onchange={
|
|
376
|
+
onchange={handleValueChange}
|
|
372
377
|
onfocus={handleFocus}
|
|
373
378
|
onblur={handleBlur}
|
|
374
379
|
onclick={handleClick}
|
|
@@ -13,8 +13,8 @@ type $$ComponentProps = {
|
|
|
13
13
|
clearable?: boolean;
|
|
14
14
|
clearButtonAriaLabel?: string;
|
|
15
15
|
iconVariant?: IconVariant;
|
|
16
|
-
onchange?: (value:
|
|
17
|
-
oninput?: (value:
|
|
16
|
+
onchange?: (value: string) => void;
|
|
17
|
+
oninput?: (value: string) => void;
|
|
18
18
|
onfocus?: Function;
|
|
19
19
|
onblur?: Function;
|
|
20
20
|
onkeydown?: Function;
|
|
@@ -108,8 +108,8 @@
|
|
|
108
108
|
clearable?: boolean;
|
|
109
109
|
|
|
110
110
|
// 入力イベント
|
|
111
|
-
onchange?: (value:
|
|
112
|
-
oninput?: (value:
|
|
111
|
+
onchange?: (value: string | number | null | undefined) => void;
|
|
112
|
+
oninput?: (value: string | number | null | undefined) => void;
|
|
113
113
|
|
|
114
114
|
// フォーカスイベント
|
|
115
115
|
onfocus?: Function; // No params for type inference
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
// 入力中はvalueを更新しない(入力値をそのまま保持)
|
|
207
207
|
highlightedIndex = -1;
|
|
208
208
|
popupRef?.open();
|
|
209
|
-
oninput?.(
|
|
209
|
+
oninput?.(currentValue ?? null);
|
|
210
210
|
};
|
|
211
211
|
|
|
212
212
|
// 値確定ハンドラー
|
|
@@ -20,8 +20,8 @@ type $$ComponentProps = {
|
|
|
20
20
|
required?: boolean;
|
|
21
21
|
filterable?: boolean;
|
|
22
22
|
clearable?: boolean;
|
|
23
|
-
onchange?: (value:
|
|
24
|
-
oninput?: (value:
|
|
23
|
+
onchange?: (value: string | number | null | undefined) => void;
|
|
24
|
+
oninput?: (value: string | number | null | undefined) => void;
|
|
25
25
|
onfocus?: Function;
|
|
26
26
|
onblur?: Function;
|
|
27
27
|
onkeydown?: Function;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// 基本プロパティ
|
|
14
14
|
title = 'Confirm',
|
|
15
15
|
description = 'Are you sure?',
|
|
16
|
-
|
|
16
|
+
submitLabel = 'Confirm',
|
|
17
17
|
cancelLabel = 'Cancel',
|
|
18
18
|
|
|
19
19
|
// HTML属性
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
closeIfClickOutside = true,
|
|
29
29
|
|
|
30
30
|
// イベントハンドラー
|
|
31
|
-
|
|
31
|
+
onSubmit = () => {}, // No params for type inference
|
|
32
32
|
onCancel = () => {} // No params for type inference
|
|
33
33
|
}: {
|
|
34
34
|
// 基本プロパティ
|
|
35
35
|
title?: string;
|
|
36
36
|
description?: string;
|
|
37
|
-
|
|
37
|
+
submitLabel?: string;
|
|
38
38
|
cancelLabel?: string;
|
|
39
39
|
|
|
40
40
|
// HTML属性
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
closeIfClickOutside?: boolean;
|
|
50
50
|
|
|
51
51
|
// イベントハンドラー
|
|
52
|
-
|
|
52
|
+
onSubmit?: () => void;
|
|
53
53
|
onCancel?: () => void;
|
|
54
54
|
} = $props();
|
|
55
55
|
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
// =========================================================================
|
|
59
59
|
// Methods
|
|
60
60
|
// =========================================================================
|
|
61
|
-
const
|
|
62
|
-
|
|
61
|
+
const handleSubmit = (): void => {
|
|
62
|
+
onSubmit();
|
|
63
63
|
close();
|
|
64
64
|
};
|
|
65
65
|
|
|
@@ -104,9 +104,9 @@
|
|
|
104
104
|
: variant === 'warning'
|
|
105
105
|
? 'var(--svelte-ui-warning-color)'
|
|
106
106
|
: undefined}
|
|
107
|
-
onclick={
|
|
107
|
+
onclick={handleSubmit}
|
|
108
108
|
>
|
|
109
|
-
{
|
|
109
|
+
{submitLabel}
|
|
110
110
|
</Button>
|
|
111
111
|
{/snippet}
|
|
112
112
|
</Dialog>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
type $$ComponentProps = {
|
|
2
2
|
title?: string;
|
|
3
3
|
description?: string;
|
|
4
|
-
|
|
4
|
+
submitLabel?: string;
|
|
5
5
|
cancelLabel?: string;
|
|
6
6
|
id?: string;
|
|
7
7
|
variant?: 'info' | 'warning' | 'danger';
|
|
8
8
|
width?: string | number;
|
|
9
9
|
isOpen?: boolean;
|
|
10
10
|
closeIfClickOutside?: boolean;
|
|
11
|
-
|
|
11
|
+
onSubmit?: () => void;
|
|
12
12
|
onCancel?: () => void;
|
|
13
13
|
};
|
|
14
14
|
declare const ConfirmDialog: import("svelte").Component<$$ComponentProps, {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
mode?: 'single' | 'range';
|
|
54
54
|
|
|
55
55
|
// 入力イベント
|
|
56
|
-
onchange
|
|
56
|
+
onchange?: (value: Date | { start: Date; end: Date } | undefined) => void;
|
|
57
57
|
onOpen?: Function;
|
|
58
58
|
onClose?: Function;
|
|
59
59
|
} = $props();
|
|
@@ -186,8 +186,8 @@
|
|
|
186
186
|
onpointercancel?: Function; // No params for type inference
|
|
187
187
|
|
|
188
188
|
// 入力イベント
|
|
189
|
-
onchange?: (value:
|
|
190
|
-
oninput?: (value:
|
|
189
|
+
onchange?: (value: string | number) => void;
|
|
190
|
+
oninput?: (value: string | number) => void;
|
|
191
191
|
|
|
192
192
|
// アイコンイベント
|
|
193
193
|
onRightIconClick?: Function; // No params for type inference
|
|
@@ -61,8 +61,8 @@ type $$ComponentProps = {
|
|
|
61
61
|
onpointerleave?: Function;
|
|
62
62
|
onpointermove?: Function;
|
|
63
63
|
onpointercancel?: Function;
|
|
64
|
-
onchange?: (value:
|
|
65
|
-
oninput?: (value:
|
|
64
|
+
onchange?: (value: string | number) => void;
|
|
65
|
+
oninput?: (value: string | number) => void;
|
|
66
66
|
onRightIconClick?: Function;
|
|
67
67
|
onLeftIconClick?: Function;
|
|
68
68
|
[key: string]: any;
|
|
@@ -11,7 +11,7 @@ type $$ComponentProps = {
|
|
|
11
11
|
disabled?: boolean;
|
|
12
12
|
required?: boolean;
|
|
13
13
|
reducedMotion?: boolean;
|
|
14
|
-
onchange?: (value:
|
|
14
|
+
onchange?: (value: string | number | boolean) => void;
|
|
15
15
|
onfocus?: Function;
|
|
16
16
|
onblur?: Function;
|
|
17
17
|
onkeydown?: Function;
|
|
@@ -39,7 +39,7 @@ type $$ComponentProps = {
|
|
|
39
39
|
onpointerleave?: Function;
|
|
40
40
|
onpointermove?: Function;
|
|
41
41
|
onpointercancel?: Function;
|
|
42
|
-
onchange?: (value:
|
|
42
|
+
onchange?: (value: string | number | null | undefined) => void;
|
|
43
43
|
[key: string]: any;
|
|
44
44
|
};
|
|
45
45
|
declare const Select: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
@@ -126,8 +126,8 @@
|
|
|
126
126
|
onpointercancel?: Function; // No params for type inference
|
|
127
127
|
|
|
128
128
|
// 入力イベント
|
|
129
|
-
onchange?:
|
|
130
|
-
oninput?:
|
|
129
|
+
onchange?: (value: number) => void;
|
|
130
|
+
oninput?: (value: number) => void;
|
|
131
131
|
|
|
132
132
|
// その他
|
|
133
133
|
[key: string]: any;
|
|
@@ -37,8 +37,8 @@ type $$ComponentProps = {
|
|
|
37
37
|
onpointerleave?: Function;
|
|
38
38
|
onpointermove?: Function;
|
|
39
39
|
onpointercancel?: Function;
|
|
40
|
-
onchange?:
|
|
41
|
-
oninput?:
|
|
40
|
+
onchange?: (value: number) => void;
|
|
41
|
+
oninput?: (value: number) => void;
|
|
42
42
|
[key: string]: any;
|
|
43
43
|
};
|
|
44
44
|
declare const Slider: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
// スタイル/レイアウト
|
|
32
32
|
rows = 3,
|
|
33
|
-
minHeight =
|
|
33
|
+
minHeight = null,
|
|
34
34
|
maxHeight = null,
|
|
35
35
|
inline = false,
|
|
36
36
|
focusStyle = 'outline',
|
|
@@ -163,8 +163,8 @@
|
|
|
163
163
|
onpointercancel?: Function; // No params for type inference
|
|
164
164
|
|
|
165
165
|
// 入力イベント
|
|
166
|
-
onchange?: (value:
|
|
167
|
-
oninput?: (value:
|
|
166
|
+
onchange?: (value: string) => void;
|
|
167
|
+
oninput?: (value: string) => void;
|
|
168
168
|
|
|
169
169
|
// その他
|
|
170
170
|
[key: string]: any;
|
|
@@ -327,9 +327,11 @@
|
|
|
327
327
|
// $derived
|
|
328
328
|
// =========================================================================
|
|
329
329
|
|
|
330
|
-
// min-height
|
|
331
|
-
|
|
332
|
-
|
|
330
|
+
// min-height用CSS変数の上書きスタイル
|
|
331
|
+
// デフォルト値は variables.scss の --svelte-ui-textarea-min-height に委譲し、
|
|
332
|
+
// props で minHeight が指定されたときだけ上書きする
|
|
333
|
+
const minHeightVarStyle = $derived(
|
|
334
|
+
!inline && minHeight != null ? `--svelte-ui-textarea-min-height: ${minHeight}px;` : ''
|
|
333
335
|
);
|
|
334
336
|
|
|
335
337
|
const maxHeightStyle = $derived(getStyleFromNumber(maxHeight));
|
|
@@ -346,6 +348,12 @@
|
|
|
346
348
|
}
|
|
347
349
|
return html;
|
|
348
350
|
} else {
|
|
351
|
+
// inline かつ value が空のとき、placeholder がなければ
|
|
352
|
+
// 1行分の高さを確保するためにダミーの を入れる
|
|
353
|
+
// (placeholder がある場合は :empty::before でプレースホルダを表示したいので空にしておく)
|
|
354
|
+
if (inline && !placeholder) {
|
|
355
|
+
return ' ';
|
|
356
|
+
}
|
|
349
357
|
return '';
|
|
350
358
|
}
|
|
351
359
|
});
|
|
@@ -380,7 +388,7 @@
|
|
|
380
388
|
<div
|
|
381
389
|
class="textarea__display-text"
|
|
382
390
|
data-placeholder={placeholder}
|
|
383
|
-
style="{
|
|
391
|
+
style="{minHeightVarStyle} {customStyle}"
|
|
384
392
|
>
|
|
385
393
|
{@html htmlValue}
|
|
386
394
|
</div>
|
|
@@ -402,7 +410,7 @@
|
|
|
402
410
|
{spellcheck}
|
|
403
411
|
{autocapitalize}
|
|
404
412
|
class:resizable
|
|
405
|
-
style="width: {widthStyle}; {
|
|
413
|
+
style="width: {widthStyle}; {minHeightVarStyle} {customStyle}"
|
|
406
414
|
onchange={handleChange}
|
|
407
415
|
oninput={handleInput}
|
|
408
416
|
onfocus={handleFocus}
|
|
@@ -450,7 +458,7 @@
|
|
|
450
458
|
{/if}
|
|
451
459
|
</div>
|
|
452
460
|
{#if linkify}
|
|
453
|
-
<div class="textarea__link-text" style="{
|
|
461
|
+
<div class="textarea__link-text" style="{minHeightVarStyle} {customStyle}">
|
|
454
462
|
{@html linkHtmlValue}
|
|
455
463
|
</div>
|
|
456
464
|
{/if}
|
|
@@ -687,13 +695,14 @@
|
|
|
687
695
|
* ============================================= */
|
|
688
696
|
.textarea:not(.textarea--inline) {
|
|
689
697
|
.textarea__display-text,
|
|
690
|
-
.textarea__link-text
|
|
698
|
+
.textarea__link-text,
|
|
699
|
+
textarea {
|
|
700
|
+
min-height: var(--svelte-ui-textarea-min-height);
|
|
691
701
|
padding: var(--svelte-ui-textarea-padding);
|
|
692
702
|
}
|
|
693
703
|
|
|
694
704
|
textarea {
|
|
695
705
|
position: static;
|
|
696
|
-
padding: var(--svelte-ui-textarea-padding);
|
|
697
706
|
background-color: var(--svelte-ui-textarea-bg);
|
|
698
707
|
box-shadow: 0 0 0 var(--svelte-ui-border-width) inset var(--svelte-ui-textarea-border-color);
|
|
699
708
|
border: none;
|
|
@@ -54,8 +54,8 @@ type $$ComponentProps = {
|
|
|
54
54
|
onpointerleave?: Function;
|
|
55
55
|
onpointermove?: Function;
|
|
56
56
|
onpointercancel?: Function;
|
|
57
|
-
onchange?: (value:
|
|
58
|
-
oninput?: (value:
|
|
57
|
+
onchange?: (value: string) => void;
|
|
58
|
+
oninput?: (value: string) => void;
|
|
59
59
|
[key: string]: any;
|
|
60
60
|
};
|
|
61
61
|
declare const Textarea: import("svelte").Component<$$ComponentProps, {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { getStyleFromNumber } from '../../utils/style';
|
|
11
11
|
import type { SkeletonPatternConfig, SkeletonPresetConfig } from '../../types/skeleton';
|
|
12
12
|
import { isPresetPattern, isMediaPattern, isAvatarPattern } from '../../types/skeleton';
|
|
13
|
+
import { DEFAULT_PATTERN_CONFIG, PRESET_PATTERNS } from '../../constants/skeleton';
|
|
13
14
|
|
|
14
15
|
// =========================================================================
|
|
15
16
|
// Props
|
|
@@ -19,8 +20,8 @@
|
|
|
19
20
|
// 基本プロパティ
|
|
20
21
|
patterns = [{ type: 'box' }] as SkeletonPatternConfig[],
|
|
21
22
|
repeat = 1,
|
|
22
|
-
repeatGap = '
|
|
23
|
-
|
|
23
|
+
repeatGap = 'var(--svelte-ui-skeleton-repeat-gap)',
|
|
24
|
+
patternGap = 'var(--svelte-ui-skeleton-pattern-gap)',
|
|
24
25
|
className = '',
|
|
25
26
|
customStyle = '',
|
|
26
27
|
animated = true
|
|
@@ -28,77 +29,12 @@
|
|
|
28
29
|
patterns?: SkeletonPatternConfig[];
|
|
29
30
|
repeat?: number;
|
|
30
31
|
repeatGap?: string | number;
|
|
31
|
-
|
|
32
|
+
patternGap?: string | number;
|
|
32
33
|
className?: string;
|
|
33
34
|
customStyle?: string;
|
|
34
35
|
animated?: boolean;
|
|
35
36
|
} = $props();
|
|
36
37
|
|
|
37
|
-
const DEFAULT_PATTERN_CONFIG = {
|
|
38
|
-
repeat: 1,
|
|
39
|
-
repeatDirection: 'vertical' as const,
|
|
40
|
-
repeatGap: '24px'
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// プリセットパターンの定義
|
|
44
|
-
const PRESET_PATTERNS: Record<string, SkeletonPatternConfig[]> = {
|
|
45
|
-
'article-detail': [
|
|
46
|
-
{
|
|
47
|
-
type: 'box'
|
|
48
|
-
},
|
|
49
|
-
{ type: 'avatar', showName: true },
|
|
50
|
-
{
|
|
51
|
-
type: 'text',
|
|
52
|
-
lines: 5,
|
|
53
|
-
repeat: 1
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
|
-
'article-list': [
|
|
57
|
-
{
|
|
58
|
-
type: 'media',
|
|
59
|
-
layout: 'horizontal',
|
|
60
|
-
thumbnailConfig: { width: '160px', aspectRatio: '4/3' },
|
|
61
|
-
textConfig: { lines: 3 },
|
|
62
|
-
repeat: 3
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
'product-list': [
|
|
66
|
-
{
|
|
67
|
-
type: 'media',
|
|
68
|
-
layout: 'vertical',
|
|
69
|
-
thumbnailConfig: { width: '100%', aspectRatio: '1' },
|
|
70
|
-
textConfig: { lines: 2 },
|
|
71
|
-
repeat: 4,
|
|
72
|
-
repeatDirection: 'horizontal'
|
|
73
|
-
}
|
|
74
|
-
],
|
|
75
|
-
'video-list': [
|
|
76
|
-
{
|
|
77
|
-
type: 'media',
|
|
78
|
-
layout: 'vertical',
|
|
79
|
-
thumbnailConfig: { width: '100%', aspectRatio: '16/9' },
|
|
80
|
-
textConfig: { lines: 2 },
|
|
81
|
-
repeat: 3,
|
|
82
|
-
repeatDirection: 'horizontal'
|
|
83
|
-
}
|
|
84
|
-
],
|
|
85
|
-
'user-list': [
|
|
86
|
-
{
|
|
87
|
-
type: 'avatar',
|
|
88
|
-
showName: true
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
'button-group': [
|
|
92
|
-
{
|
|
93
|
-
type: 'button',
|
|
94
|
-
width: '120px',
|
|
95
|
-
repeat: 2,
|
|
96
|
-
repeatDirection: 'horizontal',
|
|
97
|
-
repeatGap: '16px'
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
};
|
|
101
|
-
|
|
102
38
|
// =========================================================================
|
|
103
39
|
// $derived
|
|
104
40
|
// =========================================================================
|
|
@@ -162,17 +98,19 @@
|
|
|
162
98
|
});
|
|
163
99
|
|
|
164
100
|
const repeatGapStyle = $derived(getStyleFromNumber(repeatGap));
|
|
165
|
-
const
|
|
101
|
+
const patternGapStyle = $derived(getStyleFromNumber(patternGap));
|
|
166
102
|
</script>
|
|
167
103
|
|
|
168
104
|
<div class={containerClasses} style={customStyle} data-testid="skeleton">
|
|
169
105
|
<div class="skeleton__items" style="gap: {repeatGapStyle};">
|
|
170
106
|
{#each Array(repeat) as _, index}
|
|
171
|
-
<div class="skeleton__item" style="gap: {
|
|
107
|
+
<div class="skeleton__item" style="gap: {patternGapStyle};">
|
|
172
108
|
{#each mergedPatterns as patternConfig}
|
|
173
109
|
{@const patternRepeat = patternConfig.repeat || 1}
|
|
174
110
|
{@const patternRepeatDirection = patternConfig.repeatDirection || 'vertical'}
|
|
175
|
-
{@const patternRepeatGap =
|
|
111
|
+
{@const patternRepeatGap =
|
|
112
|
+
getStyleFromNumber(patternConfig.repeatGap) ||
|
|
113
|
+
getStyleFromNumber(DEFAULT_PATTERN_CONFIG.repeatGap)}
|
|
176
114
|
<div
|
|
177
115
|
class="skeleton__pattern"
|
|
178
116
|
class:skeleton__pattern--horizontal={patternRepeatDirection === 'horizontal'}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
import SkeletonBox from './SkeletonBox.svelte';
|
|
5
5
|
import SkeletonText from './SkeletonText.svelte';
|
|
6
6
|
import { getStyleFromNumber } from '../../utils/style';
|
|
7
|
-
import type {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
import type { SkeletonAvatarConfig } from '../../types/skeleton';
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_AVATAR_IMAGE_CONFIG,
|
|
10
|
+
DEFAULT_TEXT_CONFIG_AVATAR,
|
|
11
|
+
DEFAULT_AVATAR_CONFIG
|
|
12
|
+
} from '../../constants/skeleton';
|
|
12
13
|
|
|
13
14
|
// =========================================================================
|
|
14
15
|
// Props
|
|
@@ -23,25 +24,6 @@
|
|
|
23
24
|
animated?: boolean;
|
|
24
25
|
} = $props();
|
|
25
26
|
|
|
26
|
-
// デフォルト設定
|
|
27
|
-
const DEFAULT_AVATAR_IMAGE_CONFIG: SkeletonAvatarImageConfig = {
|
|
28
|
-
type: 'avatar-image',
|
|
29
|
-
size: '48px',
|
|
30
|
-
radius: 'var(--svelte-ui-skeleton-avatar-image-border-radius)',
|
|
31
|
-
customStyle: ''
|
|
32
|
-
};
|
|
33
|
-
const DEFAULT_TEXT_CONFIG: SkeletonTextConfig = {
|
|
34
|
-
type: 'text',
|
|
35
|
-
width: '160px',
|
|
36
|
-
lines: 1,
|
|
37
|
-
customStyle: ''
|
|
38
|
-
};
|
|
39
|
-
const DEFAULT_AVATAR_CONFIG: SkeletonAvatarConfig = {
|
|
40
|
-
type: 'avatar',
|
|
41
|
-
avatarImageConfig: DEFAULT_AVATAR_IMAGE_CONFIG,
|
|
42
|
-
textConfig: DEFAULT_TEXT_CONFIG
|
|
43
|
-
};
|
|
44
|
-
|
|
45
27
|
// マージされた設定
|
|
46
28
|
const mergedAvatarImageConfig = $derived({
|
|
47
29
|
...DEFAULT_AVATAR_IMAGE_CONFIG,
|
|
@@ -49,7 +31,7 @@
|
|
|
49
31
|
});
|
|
50
32
|
|
|
51
33
|
const mergedTextConfig = $derived({
|
|
52
|
-
...
|
|
34
|
+
...DEFAULT_TEXT_CONFIG_AVATAR,
|
|
53
35
|
...(avatarConfig.textConfig || {})
|
|
54
36
|
});
|
|
55
37
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<script lang="ts">
|
|
4
4
|
import { getStyleFromNumber } from '../../utils/style';
|
|
5
|
+
import { DEFAULT_BOX_CONFIG } from '../../constants/skeleton';
|
|
5
6
|
|
|
6
7
|
// =========================================================================
|
|
7
8
|
// Props
|
|
@@ -26,16 +27,6 @@
|
|
|
26
27
|
customStyle?: string;
|
|
27
28
|
} = $props();
|
|
28
29
|
|
|
29
|
-
// =========================================================================
|
|
30
|
-
// Constants
|
|
31
|
-
// =========================================================================
|
|
32
|
-
|
|
33
|
-
const DEFAULT_BOX_CONFIG = {
|
|
34
|
-
width: '100%',
|
|
35
|
-
height: '240px',
|
|
36
|
-
radius: 'var(--svelte-ui-skeleton-box-border-radius, 8px)'
|
|
37
|
-
};
|
|
38
|
-
|
|
39
30
|
// =========================================================================
|
|
40
31
|
// $derived
|
|
41
32
|
// =========================================================================
|
|
@@ -86,7 +77,7 @@
|
|
|
86
77
|
.skeleton-box__content {
|
|
87
78
|
width: 100%;
|
|
88
79
|
height: 100%;
|
|
89
|
-
background-color: var(--svelte-ui-skeleton-
|
|
80
|
+
background-color: var(--svelte-ui-skeleton-color);
|
|
90
81
|
display: block;
|
|
91
82
|
}
|
|
92
83
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import SkeletonBox from './SkeletonBox.svelte';
|
|
5
5
|
import { getStyleFromNumber } from '../../utils/style';
|
|
6
6
|
import type { SkeletonButtonConfig } from '../../types/skeleton';
|
|
7
|
+
import { DEFAULT_BUTTON_CONFIG } from '../../constants/skeleton';
|
|
7
8
|
|
|
8
9
|
let {
|
|
9
10
|
buttonConfig = {},
|
|
@@ -13,16 +14,6 @@
|
|
|
13
14
|
animated?: boolean;
|
|
14
15
|
} = $props();
|
|
15
16
|
|
|
16
|
-
// デフォルト設定
|
|
17
|
-
const DEFAULT_BUTTON_CONFIG: SkeletonButtonConfig = {
|
|
18
|
-
type: 'button',
|
|
19
|
-
width: '120px',
|
|
20
|
-
height: '36px',
|
|
21
|
-
radius: 'var(--svelte-ui-skeleton-button-border-radius)',
|
|
22
|
-
align: 'left',
|
|
23
|
-
customStyle: ''
|
|
24
|
-
};
|
|
25
|
-
|
|
26
17
|
// マージされた設定
|
|
27
18
|
const mergedButtonConfig = $derived({
|
|
28
19
|
...DEFAULT_BUTTON_CONFIG,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import SkeletonText from './SkeletonText.svelte';
|
|
5
5
|
import { getStyleFromNumber } from '../../utils/style';
|
|
6
6
|
import type { SkeletonHeadingConfig } from '../../types/skeleton';
|
|
7
|
+
import { DEFAULT_HEADING_CONFIG } from '../../constants/skeleton';
|
|
7
8
|
|
|
8
9
|
// =========================================================================
|
|
9
10
|
// Props
|
|
@@ -17,14 +18,6 @@
|
|
|
17
18
|
animated?: boolean;
|
|
18
19
|
} = $props();
|
|
19
20
|
|
|
20
|
-
// デフォルト設定
|
|
21
|
-
const DEFAULT_HEADING_CONFIG: SkeletonHeadingConfig = {
|
|
22
|
-
type: 'heading',
|
|
23
|
-
width: '50%',
|
|
24
|
-
fontSize: '2rem',
|
|
25
|
-
customStyle: ''
|
|
26
|
-
};
|
|
27
|
-
|
|
28
21
|
// マージされた設定
|
|
29
22
|
const mergedHeadingConfig = $derived({
|
|
30
23
|
...DEFAULT_HEADING_CONFIG,
|
|
@@ -36,11 +29,18 @@
|
|
|
36
29
|
// =========================================================================
|
|
37
30
|
|
|
38
31
|
const widthStyle = $derived(getStyleFromNumber(mergedHeadingConfig.width));
|
|
39
|
-
const fontSizeStyle = $derived(
|
|
32
|
+
const fontSizeStyle = $derived(
|
|
33
|
+
mergedHeadingConfig.fontSize
|
|
34
|
+
? typeof mergedHeadingConfig.fontSize === 'string' &&
|
|
35
|
+
mergedHeadingConfig.fontSize.startsWith('var(')
|
|
36
|
+
? mergedHeadingConfig.fontSize
|
|
37
|
+
: getStyleFromNumber(mergedHeadingConfig.fontSize)
|
|
38
|
+
: DEFAULT_HEADING_CONFIG.fontSize
|
|
39
|
+
);
|
|
40
40
|
</script>
|
|
41
41
|
|
|
42
42
|
<div class="skeleton-heading" style="font-size: {fontSizeStyle}; {mergedHeadingConfig.customStyle}">
|
|
43
|
-
<SkeletonText textConfig={{ width: widthStyle
|
|
43
|
+
<SkeletonText textConfig={{ width: widthStyle }} {animated} />
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
46
|
<style>.skeleton-heading {
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
import SkeletonBox from './SkeletonBox.svelte';
|
|
5
5
|
import SkeletonText from './SkeletonText.svelte';
|
|
6
6
|
import { getStyleFromNumber } from '../../utils/style';
|
|
7
|
-
import type {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
import type { SkeletonMediaConfig } from '../../types/skeleton';
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_MEDIA_CONFIG,
|
|
10
|
+
DEFAULT_THUMBNAIL_CONFIG,
|
|
11
|
+
DEFAULT_TEXT_CONFIG_MEDIA
|
|
12
|
+
} from '../../constants/skeleton';
|
|
12
13
|
|
|
13
14
|
let {
|
|
14
15
|
width = '100%',
|
|
@@ -20,14 +21,6 @@
|
|
|
20
21
|
animated?: boolean;
|
|
21
22
|
} = $props();
|
|
22
23
|
|
|
23
|
-
// デフォルト設定
|
|
24
|
-
const DEFAULT_MEDIA_CONFIG: Partial<SkeletonMediaConfig> = {
|
|
25
|
-
type: 'media',
|
|
26
|
-
layout: 'horizontal',
|
|
27
|
-
thumbnailConfig: { width: '160px', aspectRatio: '16/9' },
|
|
28
|
-
textConfig: { width: '100%', lines: 2 }
|
|
29
|
-
};
|
|
30
|
-
|
|
31
24
|
// マージされた設定
|
|
32
25
|
const mergedMediaConfig = $derived({
|
|
33
26
|
...DEFAULT_MEDIA_CONFIG,
|
|
@@ -37,20 +30,6 @@
|
|
|
37
30
|
// レイアウト方向を取得
|
|
38
31
|
const layoutDirection = $derived(mergedMediaConfig.layout || 'horizontal');
|
|
39
32
|
|
|
40
|
-
// デフォルト設定
|
|
41
|
-
const DEFAULT_THUMBNAIL_CONFIG: SkeletonThumbnailConfig = {
|
|
42
|
-
type: 'thumbnail',
|
|
43
|
-
width: '120px',
|
|
44
|
-
radius: 'var(--svelte-ui-skeleton-button-border-radius)',
|
|
45
|
-
customStyle: ''
|
|
46
|
-
};
|
|
47
|
-
const DEFAULT_TEXT_CONFIG: SkeletonTextConfig = {
|
|
48
|
-
type: 'text',
|
|
49
|
-
width: '100%',
|
|
50
|
-
lines: 2,
|
|
51
|
-
customStyle: ''
|
|
52
|
-
};
|
|
53
|
-
|
|
54
33
|
// マージされた設定
|
|
55
34
|
const mergedThumbnailConfig = $derived({
|
|
56
35
|
...DEFAULT_THUMBNAIL_CONFIG,
|
|
@@ -58,7 +37,7 @@
|
|
|
58
37
|
});
|
|
59
38
|
|
|
60
39
|
const mergedTextConfig = $derived({
|
|
61
|
-
...
|
|
40
|
+
...DEFAULT_TEXT_CONFIG_MEDIA,
|
|
62
41
|
...(mergedMediaConfig.textConfig || {})
|
|
63
42
|
});
|
|
64
43
|
|
|
@@ -103,13 +82,13 @@
|
|
|
103
82
|
.skeleton-media {
|
|
104
83
|
display: grid;
|
|
105
84
|
grid-template-columns: auto 1fr;
|
|
106
|
-
gap:
|
|
85
|
+
gap: var(--svelte-ui-skeleton-media-gap);
|
|
107
86
|
}
|
|
108
87
|
|
|
109
88
|
.skeleton-media--vertical {
|
|
110
89
|
grid-template-columns: 1fr;
|
|
111
90
|
grid-template-rows: auto 1fr;
|
|
112
91
|
justify-items: center;
|
|
113
|
-
gap:
|
|
92
|
+
gap: var(--svelte-ui-skeleton-media-vertical-gap);
|
|
114
93
|
}
|
|
115
94
|
</style>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import SkeletonBox from './SkeletonBox.svelte';
|
|
5
5
|
import { getStyleFromNumber } from '../../utils/style';
|
|
6
6
|
import type { SkeletonTextConfig } from '../../types/skeleton';
|
|
7
|
+
import { DEFAULT_TEXT_CONFIG } from '../../constants/skeleton';
|
|
7
8
|
|
|
8
9
|
// =========================================================================
|
|
9
10
|
// Props
|
|
@@ -18,14 +19,6 @@
|
|
|
18
19
|
animated?: boolean;
|
|
19
20
|
} = $props();
|
|
20
21
|
|
|
21
|
-
// デフォルト設定
|
|
22
|
-
const DEFAULT_TEXT_CONFIG: SkeletonTextConfig = {
|
|
23
|
-
type: 'text',
|
|
24
|
-
width: '100%',
|
|
25
|
-
lines: 1,
|
|
26
|
-
customStyle: ''
|
|
27
|
-
};
|
|
28
|
-
|
|
29
22
|
// マージされた設定
|
|
30
23
|
const mergedTextConfig = $derived({
|
|
31
24
|
...DEFAULT_TEXT_CONFIG,
|
|
@@ -55,7 +48,7 @@
|
|
|
55
48
|
<div class="skeleton-text__line" style="width: {widthStyle}">
|
|
56
49
|
<SkeletonBox
|
|
57
50
|
width="100%"
|
|
58
|
-
height="
|
|
51
|
+
height="var(--svelte-ui-skeleton-text-line-height)"
|
|
59
52
|
radius="var(--svelte-ui-skeleton-text-border-radius)"
|
|
60
53
|
{animated}
|
|
61
54
|
/>
|