@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.
@@ -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-border-radius: var(--svelte-ui-border-radius);
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-bg-color: var(--svelte-ui-skeleton-color);
693
- --svelte-ui-skeleton-text-bg-color: var(--svelte-ui-skeleton-color);
694
- --svelte-ui-skeleton-image-bg-color: var(--svelte-ui-skeleton-color);
695
- --svelte-ui-skeleton-button-bg-color: var(--svelte-ui-skeleton-color);
696
- --svelte-ui-skeleton-input-bg-color: var(--svelte-ui-skeleton-color);
697
- --svelte-ui-skeleton-textarea-bg-color: var(--svelte-ui-skeleton-color);
698
- --svelte-ui-skeleton-avatar-bg-color: var(--svelte-ui-skeleton-color);
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: any) => void;
96
- oninput?: (value: any) => void;
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
- handleChange();
151
+ handleValueChange();
152
152
  });
153
153
  });
154
154
 
@@ -167,10 +167,11 @@
167
167
  // Methods
168
168
  // =========================================================================
169
169
 
170
- const handleChange = (event?: Event): void => {
171
- // 空文字列の場合はそのまま処理
172
- if (localValue && !localValue.startsWith('#')) {
173
- localValue = '#' + localValue;
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 handleInput = (event?: Event): void => {
184
+ const handleValueChange = (): void => {
185
+ handleChange(localValue);
186
+ };
187
+
188
+ const handleInput = (inputValue: string | number): void => {
184
189
  if (disabled) return;
185
- oninput?.(localValue);
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
- handleChange();
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={handleChange}
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: any) => void;
17
- oninput?: (value: any) => void;
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: any) => void;
112
- oninput?: (value: any) => void;
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?.(currentInputValue);
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: any) => void;
24
- oninput?: (value: any) => void;
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
- confirmLabel = 'Confirm',
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
- onConfirm = () => {}, // No params for type inference
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
- confirmLabel?: string;
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
- onConfirm?: () => void;
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 handleConfirm = (): void => {
62
- onConfirm();
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={handleConfirm}
107
+ onclick={handleSubmit}
108
108
  >
109
- {confirmLabel}
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
- confirmLabel?: string;
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
- onConfirm?: () => void;
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: (value: Date | { start: Date; end: Date } | undefined) => void;
56
+ onchange?: (value: Date | { start: Date; end: Date } | undefined) => void;
57
57
  onOpen?: Function;
58
58
  onClose?: Function;
59
59
  } = $props();
@@ -14,7 +14,7 @@ type $$ComponentProps = {
14
14
  maxDate?: Date;
15
15
  id?: string;
16
16
  mode?: 'single' | 'range';
17
- onchange: (value: Date | {
17
+ onchange?: (value: Date | {
18
18
  start: Date;
19
19
  end: Date;
20
20
  } | undefined) => void;
@@ -186,8 +186,8 @@
186
186
  onpointercancel?: Function; // No params for type inference
187
187
 
188
188
  // 入力イベント
189
- onchange?: (value: any) => void;
190
- oninput?: (value: any) => void;
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: any) => void;
65
- oninput?: (value: any) => void;
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;
@@ -92,7 +92,7 @@
92
92
  reducedMotion?: boolean;
93
93
 
94
94
  // 入力イベント
95
- onchange?: (value: any) => void;
95
+ onchange?: (value: string | number | boolean) => void;
96
96
 
97
97
  // フォーカスイベント
98
98
  onfocus?: Function; // No params for type inference
@@ -11,7 +11,7 @@ type $$ComponentProps = {
11
11
  disabled?: boolean;
12
12
  required?: boolean;
13
13
  reducedMotion?: boolean;
14
- onchange?: (value: any) => void;
14
+ onchange?: (value: string | number | boolean) => void;
15
15
  onfocus?: Function;
16
16
  onblur?: Function;
17
17
  onkeydown?: Function;
@@ -128,7 +128,7 @@
128
128
  onpointercancel?: Function; // No params for type inference
129
129
 
130
130
  // 入力イベント
131
- onchange?: (value: any) => void;
131
+ onchange?: (value: string | number | null | undefined) => void;
132
132
 
133
133
  // その他
134
134
  [key: string]: any;
@@ -39,7 +39,7 @@ type $$ComponentProps = {
39
39
  onpointerleave?: Function;
40
40
  onpointermove?: Function;
41
41
  onpointercancel?: Function;
42
- onchange?: (value: any) => void;
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?: Function; // No params for type inference
130
- oninput?: Function; // No params for type inference
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?: Function;
41
- oninput?: Function;
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 = 36,
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: any) => void;
167
- oninput?: (value: any) => void;
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
- const minHeightStyle = $derived(
332
- inline ? 'min-height: 1.6em; min-height: 1lh;' : `min-height: ${minHeight}px;`
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行分の高さを確保するためにダミーの &nbsp; を入れる
353
+ // (placeholder がある場合は :empty::before でプレースホルダを表示したいので空にしておく)
354
+ if (inline && !placeholder) {
355
+ return '&nbsp;';
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="{minHeightStyle} {customStyle}"
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}; {minHeightStyle} {customStyle}"
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="{minHeightStyle} {customStyle}">
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: any) => void;
58
- oninput?: (value: any) => void;
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 = '64px',
23
- itemGap = '24px',
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
- itemGap?: string | number;
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 itemGapStyle = $derived(getStyleFromNumber(itemGap));
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: {itemGapStyle};">
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 = getStyleFromNumber(patternConfig.repeatGap) || '8px'}
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'}
@@ -3,7 +3,7 @@ type $$ComponentProps = {
3
3
  patterns?: SkeletonPatternConfig[];
4
4
  repeat?: number;
5
5
  repeatGap?: string | number;
6
- itemGap?: string | number;
6
+ patternGap?: string | number;
7
7
  className?: string;
8
8
  customStyle?: string;
9
9
  animated?: boolean;
@@ -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
- SkeletonAvatarConfig,
9
- SkeletonTextConfig,
10
- SkeletonAvatarImageConfig
11
- } from '../../types/skeleton';
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
- ...DEFAULT_TEXT_CONFIG,
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-bg-color, #e5e7eb);
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(getStyleFromNumber(mergedHeadingConfig.fontSize));
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, fontSize: fontSizeStyle }} {animated} />
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
- SkeletonMediaConfig,
9
- SkeletonThumbnailConfig,
10
- SkeletonTextConfig
11
- } from '../../types/skeleton';
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
- ...DEFAULT_TEXT_CONFIG,
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: 16px;
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: 8px;
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="1.2em"
51
+ height="var(--svelte-ui-skeleton-text-line-height)"
59
52
  radius="var(--svelte-ui-skeleton-text-border-radius)"
60
53
  {animated}
61
54
  />
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@14ch/svelte-ui",
3
3
  "description": "Modern Svelte UI components library with TypeScript support",
4
4
  "private": false,
5
- "version": "0.0.9",
5
+ "version": "0.0.10",
6
6
  "type": "module",
7
7
  "keywords": [
8
8
  "svelte",