@14ch/svelte-ui 0.0.19 → 0.0.21

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.
@@ -635,8 +635,8 @@
635
635
  --svelte-ui-drawer-description-color: var(--svelte-ui-text-subtle-color);
636
636
 
637
637
  /* LoadingSpinner */
638
- --svelte-ui-loadingspinner-color: var(--svelte-ui-primary-color);
639
- --svelte-ui-loadingspinner-size: 32px;
638
+ --svelte-ui-loading-spinner-color: var(--svelte-ui-primary-color);
639
+ --svelte-ui-loading-spinner-size: 32px;
640
640
 
641
641
  /* Snackbar */
642
642
  --svelte-ui-snackbar-min-width: 300px;
@@ -141,7 +141,7 @@
141
141
  onkeyup = () => {}, // No params for type inference
142
142
 
143
143
  // マウスイベント
144
- onclick,
144
+ onclick = () => {}, // No params for type inference
145
145
  onmousedown = () => {}, // No params for type inference
146
146
  onmouseup = () => {}, // No params for type inference
147
147
  onmouseenter = () => {}, // No params for type inference
@@ -328,9 +328,10 @@
328
328
  {type}
329
329
  disabled={isDisabled}
330
330
  class={buttonClasses}
331
- style="color: {textColors[variant]}; background-color: {backgroundColors[variant]};
332
- min-width: {minWidthStyle};
333
- {customStyle ?? ''};"
331
+ style:color={textColors[variant]}
332
+ style:background-color={backgroundColors[variant]}
333
+ style:min-width={minWidthStyle}
334
+ style={customStyle}
334
335
  onclick={handleClick}
335
336
  onauxclick={handleAuxClick}
336
337
  onfocus={handleFocus}
@@ -37,9 +37,6 @@
37
37
  // ARIA/アクセシビリティ
38
38
  reducedMotion?: boolean;
39
39
 
40
- // 入力イベント
41
- onchange?: (value: boolean) => void;
42
-
43
40
  // フォーカスイベント
44
41
  onfocus?: FocusHandler;
45
42
  onblur?: FocusHandler;
@@ -73,6 +70,9 @@
73
70
  onpointermove?: PointerHandler;
74
71
  onpointercancel?: PointerHandler;
75
72
 
73
+ // 入力イベント
74
+ onchange?: (value: boolean) => void;
75
+
76
76
  // その他
77
77
  [key: string]: any;
78
78
  };
@@ -100,9 +100,6 @@
100
100
  // ARIA/アクセシビリティ
101
101
  reducedMotion = false,
102
102
 
103
- // 入力イベント
104
- onchange = () => {}, // No params for type inference
105
-
106
103
  // フォーカスイベント
107
104
  onfocus = () => {}, // No params for type inference
108
105
  onblur = () => {}, // No params for type inference
@@ -136,6 +133,9 @@
136
133
  onpointermove = () => {}, // No params for type inference
137
134
  onpointercancel = () => {}, // No params for type inference
138
135
 
136
+ // 入力イベント
137
+ onchange = () => {}, // No params for type inference
138
+
139
139
  // その他
140
140
  ...restProps
141
141
  }: CheckboxProps = $props();
@@ -12,7 +12,6 @@ export type CheckboxProps = {
12
12
  disabled?: boolean;
13
13
  required?: boolean;
14
14
  reducedMotion?: boolean;
15
- onchange?: (value: boolean) => void;
16
15
  onfocus?: FocusHandler;
17
16
  onblur?: FocusHandler;
18
17
  onkeydown?: KeyboardHandler;
@@ -36,6 +35,7 @@ export type CheckboxProps = {
36
35
  onpointerleave?: PointerHandler;
37
36
  onpointermove?: PointerHandler;
38
37
  onpointercancel?: PointerHandler;
38
+ onchange?: (value: boolean) => void;
39
39
  [key: string]: any;
40
40
  };
41
41
  declare const Checkbox: import("svelte").Component<CheckboxProps, {}, "value" | "indeterminate">;
@@ -87,11 +87,10 @@
87
87
 
88
88
  <ul
89
89
  class="checkbox-group"
90
- style="--svelte-ui-checkbox-group-flex-direction: {direction === 'vertical' ? 'column' : 'row'};
91
- {gapStyle ? `--svelte-ui-checkbox-group-gap: ${gapStyle};` : ''}
92
- --svelte-ui-checkbox-group-wrap: {wrap ? 'wrap' : 'none'};
93
- --svelte-ui-checkbox-group-min-option-width: {minOptionWidthStyle}
94
- "
90
+ style:--internal-checkbox-group-flex-direction={direction === 'vertical' ? 'column' : 'row'}
91
+ style:--internal-checkbox-group-gap={gapStyle}
92
+ style:--internal-checkbox-group-wrap={wrap ? 'wrap' : 'none'}
93
+ style:--internal-checkbox-group-min-option-width={minOptionWidthStyle}
95
94
  >
96
95
  {#each options as option (option.value)}
97
96
  {#if localValues[String(option.value)] !== undefined}
@@ -114,12 +113,18 @@
114
113
  <style>
115
114
  .checkbox-group {
116
115
  display: flex;
117
- flex-direction: var(--svelte-ui-checkbox-group-flex-direction);
118
- gap: var(--svelte-ui-checkbox-group-gap);
119
- flex-wrap: var(--svelte-ui-checkbox-group-wrap);
116
+ flex-direction: var(
117
+ --internal-checkbox-group-flex-direction,
118
+ var(--svelte-ui-checkbox-group-flex-direction)
119
+ );
120
+ gap: var(--internal-checkbox-group-gap, var(--svelte-ui-checkbox-group-gap));
121
+ flex-wrap: var(--internal-checkbox-group-wrap, var(--svelte-ui-checkbox-group-wrap));
120
122
  }
121
123
 
122
124
  .checkbox-group__option {
123
- min-width: var(--svelte-ui-checkbox-group-min-option-width);
125
+ min-width: var(
126
+ --internal-checkbox-group-min-option-width,
127
+ var(--svelte-ui-checkbox-group-min-option-width)
128
+ );
124
129
  }
125
130
  </style>
@@ -307,10 +307,11 @@
307
307
  class:fab--shadow={shadow}
308
308
  class:fab--loading={loading}
309
309
  class:fab--no-motion={reducedMotion}
310
- style="color: {textColors[variant]}; background-color: {backgroundColors[variant]};
311
- --fab-bottom: {bottomOffsetStyle};
312
- --fab-side: {sideOffsetStyle};
313
- {customStyle ?? ''};"
310
+ style:color={textColors[variant]}
311
+ style:background-color={backgroundColors[variant]}
312
+ style:--internal-fab-bottom={bottomOffsetStyle}
313
+ style:--internal-fab-side={sideOffsetStyle}
314
+ style={customStyle}
314
315
  onclick={handleClick}
315
316
  onfocus={handleFocus}
316
317
  onblur={handleBlur}
@@ -368,7 +369,7 @@
368
369
  justify-content: center;
369
370
  align-items: center;
370
371
  position: fixed;
371
- bottom: var(--fab-bottom, 24px);
372
+ bottom: var(--internal-fab-bottom, 24px);
372
373
  height: 56px;
373
374
  padding: 0 20px;
374
375
  background-color: transparent;
@@ -385,17 +386,17 @@
385
386
  transition-duration: var(--svelte-ui-transition-duration);
386
387
  }
387
388
  .fab.fab--left {
388
- left: var(--fab-side, 24px);
389
+ left: var(--internal-fab-side, 24px);
389
390
  }
390
391
  .fab.fab--center {
391
392
  left: 50%;
392
393
  transform: translateX(-50%);
393
394
  }
394
395
  .fab.fab--right {
395
- right: var(--fab-side, 24px);
396
+ right: var(--internal-fab-side, 24px);
396
397
  }
397
398
  .fab.fab--safe-area {
398
- bottom: calc(var(--fab-bottom, 24px) + env(safe-area-inset-bottom, 0px));
399
+ bottom: calc(var(--internal-fab-bottom, 24px) + env(safe-area-inset-bottom, 0px));
399
400
  }
400
401
  .fab > * {
401
402
  z-index: 1;
@@ -259,6 +259,7 @@
259
259
  // $derived
260
260
  // =========================================================================
261
261
  const widthStyle = $derived(getStyleFromNumber(width) || '100%');
262
+ const heightStyle = $derived(getStyleFromNumber(height));
262
263
  </script>
263
264
 
264
265
  <button
@@ -266,10 +267,8 @@
266
267
  class="file-uploader"
267
268
  class:file-uploader--hover={isHover}
268
269
  class:rounded
269
- style="
270
- --svelte-ui-file-uploader-width: {widthStyle};
271
- --svelte-ui-file-uploader-height: {height}px
272
- "
270
+ style:--internal-file-uploader-width={widthStyle}
271
+ style:--internal-file-uploader-height={heightStyle}
273
272
  data-testid="file-uploader"
274
273
  onclick={handleClick}
275
274
  onfocus={handleFocus}
@@ -380,8 +379,14 @@
380
379
  align-items: center;
381
380
  gap: 16px;
382
381
  position: relative;
383
- width: var(--svelte-ui-file-uploader-width, 100%);
384
- height: var(--svelte-ui-file-uploader-height);
382
+ width: var(
383
+ --internal-file-uploader-width,
384
+ var(--svelte-ui-file-uploader-width, 100%)
385
+ );
386
+ height: var(
387
+ --internal-file-uploader-height,
388
+ var(--svelte-ui-file-uploader-height, auto)
389
+ );
385
390
  min-height: 100px;
386
391
  padding: 16px;
387
392
  background-color: var(--svelte-ui-file-uploader-bg);
@@ -76,24 +76,24 @@
76
76
  `'FILL' ${filled ? 1 : 0}, 'wght' ${weight}, 'GRAD' ${grade}, 'opsz' ${opticalSize}`
77
77
  );
78
78
 
79
+ const sizeStyle = $derived(getStyleFromNumber(size));
80
+ const colorStyle = $derived(color || undefined);
81
+
79
82
  const ariaAttributes = $derived({
80
83
  'aria-hidden': decorative && !ariaLabel ? true : undefined,
81
84
  'aria-label': ariaLabel || undefined,
82
85
  role: !decorative && ariaLabel ? 'img' : undefined
83
86
  });
84
-
85
- const iconStyle = $derived.by(() => {
86
- const sizeStyle = getStyleFromNumber(size);
87
- return `width: ${sizeStyle}; height: ${sizeStyle}; font-size: ${sizeStyle};
88
- color: ${color};
89
- font-variation-settings: ${fontVariationSettings};
90
- ${customStyle}`;
91
- });
92
87
  </script>
93
88
 
94
89
  <i
95
90
  class={iconClasses}
96
- style={iconStyle}
91
+ style:width={sizeStyle}
92
+ style:height={sizeStyle}
93
+ style:font-size={sizeStyle}
94
+ style:color={colorStyle}
95
+ style:font-variation-settings={fontVariationSettings}
96
+ style={customStyle}
97
97
  {title}
98
98
  {...ariaAttributes}
99
99
  {...restProps}
@@ -106,6 +106,8 @@
106
106
  <!-- Unicode文字での代替表示 -->
107
107
  <span
108
108
  class="icon-fallback-text"
109
+ style:font-size={sizeStyle}
110
+ style:color={colorStyle}
109
111
  style={customStyle}
110
112
  {...ariaAttributes}
111
113
  {...restProps}
@@ -337,10 +337,8 @@
337
337
  class:image-uploader--multiple={multiple}
338
338
  class:image-uploader--rounded={rounded}
339
339
  class:image-uploader--adaptive={previewAdaptive}
340
- style="
341
- --svelte-ui-image-uploader-button-width: {previewWidthStyle};
342
- --svelte-ui-image-uploader-button-height: {previewHeightStyle};
343
- "
340
+ style:--internal-image-uploader-button-width={previewWidthStyle}
341
+ style:--internal-image-uploader-button-height={previewHeightStyle}
344
342
  data-testid="image-uploader"
345
343
  >
346
344
  {#if multiple}
@@ -446,8 +444,14 @@
446
444
  align-items: center;
447
445
  position: relative;
448
446
  max-width: 100%;
449
- min-width: var(--svelte-ui-image-uploader-button-width);
450
- min-height: var(--svelte-ui-image-uploader-button-height);
447
+ min-width: var(
448
+ --internal-image-uploader-button-width,
449
+ var(--svelte-ui-image-uploader-button-width)
450
+ );
451
+ min-height: var(
452
+ --internal-image-uploader-button-height,
453
+ var(--svelte-ui-image-uploader-button-height)
454
+ );
451
455
  padding: 16px;
452
456
  background-color: var(--svelte-ui-form-bg);
453
457
  border-radius: var(--svelte-ui-border-radius);
@@ -672,7 +672,9 @@
672
672
  class:input--readonly={readonly}
673
673
  class:input--focused={isFocused}
674
674
  data-testid="input"
675
- style="width: {widthStyle}; max-width: {maxWidthStyle}; min-width: {minWidthStyle}"
675
+ style:width={widthStyle}
676
+ style:max-width={maxWidthStyle}
677
+ style:min-width={minWidthStyle}
676
678
  >
677
679
  <!-- 表示用テキスト -->
678
680
  <div class="input__display-text" style={customStyle}>
@@ -887,7 +889,6 @@
887
889
  text-align: inherit;
888
890
 
889
891
  &[type='number'] {
890
- text-align: right;
891
892
  &::-webkit-outer-spin-button,
892
893
  &::-webkit-inner-spin-button {
893
894
  -webkit-appearance: none;
@@ -916,10 +917,15 @@
916
917
  transition: none;
917
918
  }
918
919
 
920
+ .input__display-text-content {
921
+ width: 100%;
922
+ }
923
+
919
924
  .input__link-text {
920
925
  position: absolute;
921
926
  top: 0;
922
927
  left: 0;
928
+ width: 100%;
923
929
  height: 100%;
924
930
  pointer-events: none;
925
931
  z-index: 1;
@@ -1127,13 +1133,6 @@
1127
1133
  /* =============================================
1128
1134
  * タイプ別スタイル
1129
1135
  * ============================================= */
1130
- /* type-number */
1131
- .input--type-number {
1132
- .input__display-text {
1133
- justify-content: flex-end;
1134
- }
1135
- }
1136
-
1137
1136
  /* type-password: セキュリティのため常にinputを表示(display-textは非表示) */
1138
1137
  .input--type-password {
1139
1138
  /* inputを常に表示(表示制御の非フォーカス時の不可視化を上書き) */
@@ -44,13 +44,13 @@
44
44
  <div
45
45
  class="loading-spinner"
46
46
  class:spinner--no-motion={reducedMotion}
47
- style:--svelte-ui-loading-spinner-grow-duration="{growDuration}s"
48
- style:--svelte-ui-loading-spinner-rotate-duration="{rotateDuration}s"
49
- style:--svelte-ui-loading-spinner-size="{size}px"
50
- style:--svelte-ui-loading-spinner-color={color}
51
- style:--svelte-ui-loading-spinner-circumference={circumference}
52
- style:--svelte-ui-loading-spinner-half-circumference={halfCircumference}
53
- style:--svelte-ui-loading-spinner-negative-half-circumference={negativeHalfCircumference}
47
+ style:--internal-loading-spinner-grow-duration="{growDuration}s"
48
+ style:--internal-loading-spinner-rotate-duration="{rotateDuration}s"
49
+ style:--internal-loading-spinner-size="{size}px"
50
+ style:--internal-loading-spinner-color={color}
51
+ style:--internal-loading-spinner-circumference={circumference}
52
+ style:--internal-loading-spinner-half-circumference={halfCircumference}
53
+ style:--internal-loading-spinner-negative-half-circumference={negativeHalfCircumference}
54
54
  data-testid="loading-spinner"
55
55
  >
56
56
  <svg viewBox="0 0 {size} {size}" width={size} height={size}>
@@ -60,23 +60,26 @@
60
60
 
61
61
  <style>
62
62
  .loading-spinner {
63
- width: var(--svelte-ui-loading-spinner-size, var(--svelte-ui-loadingspinner-size));
64
- height: var(--svelte-ui-loading-spinner-size, var(--svelte-ui-loadingspinner-size));
63
+ display: flex;
64
+ justify-content: center;
65
+ align-items: center;
66
+ width: 100%;
67
+ height: 100px;
65
68
  line-height: 1px;
66
69
  }
67
70
 
68
71
  .loading-spinner svg {
69
- width: 100%;
70
- height: 100%;
72
+ width: var(--internal-loading-spinner-size, var(--svelte-ui-loading-spinner-size));
73
+ height: var(--internal-loading-spinner-size, var(--svelte-ui-loading-spinner-size));
71
74
  transform: rotate(-90deg);
72
- animation: rotate var(--svelte-ui-loading-spinner-rotate-duration, 0.8s) linear infinite;
75
+ animation: rotate var(--internal-loading-spinner-rotate-duration, 0.8s) linear infinite;
73
76
  }
74
77
 
75
78
  .loading-spinner circle {
76
79
  fill: none;
77
- stroke: var(--svelte-ui-loading-spinner-color, var(--svelte-ui-loadingspinner-color));
80
+ stroke: var(--internal-loading-spinner-color, var(--svelte-ui-loading-spinner-color));
78
81
  stroke-linecap: butt;
79
- animation: complex-grow var(--svelte-ui-loading-spinner-grow-duration, 1.6s) linear infinite;
82
+ animation: complex-grow var(--internal-loading-spinner-grow-duration, 1.6s) linear infinite;
80
83
  transform-origin: center;
81
84
  }
82
85
 
@@ -92,17 +95,17 @@
92
95
  @keyframes complex-grow {
93
96
  /* 負の値も別のCSS変数として定義 */
94
97
  0% {
95
- stroke-dasharray: 0 var(--svelte-ui-loading-spinner-circumference);
96
- stroke-dashoffset: var(--svelte-ui-loading-spinner-negative-half-circumference);
98
+ stroke-dasharray: 0 var(--internal-loading-spinner-circumference);
99
+ stroke-dashoffset: var(--internal-loading-spinner-negative-half-circumference);
97
100
  }
98
101
  50% {
99
- stroke-dasharray: var(--svelte-ui-loading-spinner-half-circumference)
100
- var(--svelte-ui-loading-spinner-circumference);
102
+ stroke-dasharray: var(--internal-loading-spinner-half-circumference)
103
+ var(--internal-loading-spinner-circumference);
101
104
  stroke-dashoffset: 0;
102
105
  }
103
106
  100% {
104
- stroke-dasharray: 0 var(--svelte-ui-loading-spinner-circumference);
105
- stroke-dashoffset: var(--svelte-ui-loading-spinner-negative-half-circumference);
107
+ stroke-dasharray: 0 var(--internal-loading-spinner-circumference);
108
+ stroke-dashoffset: var(--internal-loading-spinner-negative-half-circumference);
106
109
  }
107
110
  }
108
111
 
@@ -39,9 +39,6 @@
39
39
  // ARIA/アクセシビリティ
40
40
  reducedMotion?: boolean;
41
41
 
42
- // 入力イベント
43
- onchange?: BivariantValueHandler<OptionValue>;
44
-
45
42
  // フォーカスイベント
46
43
  onfocus?: FocusHandler;
47
44
  onblur?: FocusHandler;
@@ -75,6 +72,9 @@
75
72
  onpointermove?: PointerHandler;
76
73
  onpointercancel?: PointerHandler;
77
74
 
75
+ // 入力イベント
76
+ onchange?: BivariantValueHandler<OptionValue>;
77
+
78
78
  // その他
79
79
  [key: string]: any;
80
80
  };
@@ -102,9 +102,6 @@
102
102
  // ARIA/アクセシビリティ
103
103
  reducedMotion = false,
104
104
 
105
- // 入力イベント
106
- onchange = () => {}, // No params for type inference
107
-
108
105
  // フォーカスイベント
109
106
  onfocus = () => {}, // No params for type inference
110
107
  onblur = () => {}, // No params for type inference
@@ -138,6 +135,9 @@
138
135
  onpointermove = () => {}, // No params for type inference
139
136
  onpointercancel = () => {}, // No params for type inference
140
137
 
138
+ // 入力イベント
139
+ onchange = () => {}, // No params for type inference
140
+
141
141
  // その他
142
142
  ...restProps
143
143
  }: RadioProps = $props();
@@ -13,7 +13,6 @@ export type RadioProps = {
13
13
  disabled?: boolean;
14
14
  required?: boolean;
15
15
  reducedMotion?: boolean;
16
- onchange?: BivariantValueHandler<OptionValue>;
17
16
  onfocus?: FocusHandler;
18
17
  onblur?: FocusHandler;
19
18
  onkeydown?: KeyboardHandler;
@@ -37,6 +36,7 @@ export type RadioProps = {
37
36
  onpointerleave?: PointerHandler;
38
37
  onpointermove?: PointerHandler;
39
38
  onpointercancel?: PointerHandler;
39
+ onchange?: BivariantValueHandler<OptionValue>;
40
40
  [key: string]: any;
41
41
  };
42
42
  declare const Radio: import("svelte").Component<RadioProps, {}, "currentValue">;
@@ -73,11 +73,10 @@
73
73
 
74
74
  <ul
75
75
  class="radio-group"
76
- style="--svelte-ui-radio-group-flex-direction: {direction === 'vertical' ? 'column' : 'row'};
77
- {gapStyle ? `--svelte-ui-radio-group-gap: ${gapStyle};` : ''}
78
- --svelte-ui-radio-group-wrap: {wrap ? 'wrap' : 'none'};
79
- --svelte-ui-radio-group-min-option-width: {minOptionWidthStyle}
80
- "
76
+ style:--internal-radio-group-flex-direction={direction === 'vertical' ? 'column' : 'row'}
77
+ style:--internal-radio-group-gap={gapStyle}
78
+ style:--internal-radio-group-wrap={wrap ? 'wrap' : 'none'}
79
+ style:--internal-radio-group-min-option-width={minOptionWidthStyle}
81
80
  >
82
81
  {#each options as option (option.value)}
83
82
  <li class="radio-group__option">
@@ -100,12 +99,18 @@
100
99
  <style>
101
100
  .radio-group {
102
101
  display: flex;
103
- flex-direction: var(--svelte-ui-radio-group-flex-direction);
104
- gap: var(--svelte-ui-radio-group-gap);
105
- flex-wrap: var(--svelte-ui-radio-group-wrap);
102
+ flex-direction: var(
103
+ --internal-radio-group-flex-direction,
104
+ var(--svelte-ui-radio-group-flex-direction)
105
+ );
106
+ gap: var(--internal-radio-group-gap, var(--svelte-ui-radio-group-gap));
107
+ flex-wrap: var(--internal-radio-group-wrap, var(--svelte-ui-radio-group-wrap));
106
108
  }
107
109
 
108
110
  .radio-group__option {
109
- min-width: var(--svelte-ui-radio-group-min-option-width);
111
+ min-width: var(
112
+ --internal-radio-group-min-option-width,
113
+ var(--svelte-ui-radio-group-min-option-width)
114
+ );
110
115
  }
111
116
  </style>
@@ -399,7 +399,7 @@
399
399
  role="radiogroup"
400
400
  aria-label={ariaLabelledby ? undefined : ariaLabel}
401
401
  aria-labelledby={ariaLabelledby}
402
- style="--svelte-ui-segmented-control-selected-bg: {color || 'var(--svelte-ui-primary-color)'};"
402
+ style:--internal-segmented-control-selected-bg={color || 'var(--svelte-ui-primary-color)'}
403
403
  {id}
404
404
  data-testid="segmented-control"
405
405
  {...restProps}
@@ -605,7 +605,7 @@
605
605
 
606
606
  .segmented-control__input:checked + .segmented-control__label,
607
607
  .segmented-control__label--selected {
608
- background-color: var(--svelte-ui-segmented-control-selected-bg);
608
+ background-color: var(--internal-segmented-control-selected-bg, var(--svelte-ui-segmented-control-selected-bg));
609
609
  color: var(--svelte-ui-segmented-control-selected-text-color, white);
610
610
  }
611
611
 
@@ -378,6 +378,7 @@ select--focus-{focusStyle}"
378
378
  color: inherit;
379
379
  line-height: inherit;
380
380
  text-align: inherit;
381
+ cursor: pointer;
381
382
  -webkit-appearance: none;
382
383
  -moz-appearance: none;
383
384
  appearance: none;
@@ -284,28 +284,19 @@
284
284
  oninput?.(value);
285
285
  };
286
286
 
287
- // パーセンテージ計算
287
+ // パーセンテージ計算(将来の表示用に保持)
288
288
  const percentage = $derived(((value - min) / (max - min)) * 100);
289
289
 
290
290
  // スタイル計算
291
- const thumbColorStyle = $derived(
292
- thumbColor ? `--svelte-ui-slider-thumb-background: ${thumbColor};` : ''
291
+ const sliderWidthStyle = $derived(width ? getStyleFromNumber(width) : undefined);
292
+ const sliderHeightStyle = $derived(
293
+ thumbHeight ? getStyleFromNumber(thumbHeight) : 'var(--svelte-ui-slider-thumb-height)'
293
294
  );
294
-
295
295
  const thumbWidthStyle = $derived(
296
- thumbWidth ? `--svelte-ui-slider-thumb-width: ${getStyleFromNumber(thumbWidth)};` : ''
296
+ thumbWidth ? getStyleFromNumber(thumbWidth) : undefined
297
297
  );
298
-
299
298
  const thumbHeightStyle = $derived(
300
- thumbHeight ? `--svelte-ui-slider-thumb-height: ${getStyleFromNumber(thumbHeight)};` : ''
301
- );
302
-
303
- const sliderWidthStyle = $derived(width ? `width: ${getStyleFromNumber(width)};` : '');
304
-
305
- const sliderHeightStyle = $derived(
306
- thumbHeight
307
- ? `height: ${getStyleFromNumber(thumbHeight)};`
308
- : 'height: var(--svelte-ui-slider-thumb-height);'
299
+ thumbHeight ? getStyleFromNumber(thumbHeight) : undefined
309
300
  );
310
301
  </script>
311
302
 
@@ -315,7 +306,12 @@
315
306
  class:slider--disabled={disabled}
316
307
  class:slider--focused={isFocused}
317
308
  data-testid="slider"
318
- style="{sliderWidthStyle} {sliderHeightStyle} {thumbColorStyle} {thumbWidthStyle} {thumbHeightStyle} {customStyle}"
309
+ style:width={sliderWidthStyle}
310
+ style:height={sliderHeightStyle}
311
+ style:--internal-slider-thumb-background={thumbColor}
312
+ style:--internal-slider-thumb-width={thumbWidthStyle}
313
+ style:--internal-slider-thumb-height={thumbHeightStyle}
314
+ style={customStyle}
319
315
  >
320
316
  <input
321
317
  {id}
@@ -382,7 +378,10 @@
382
378
  * ============================================= */
383
379
  .slider__input {
384
380
  width: 100%;
385
- height: var(--svelte-ui-slider-track-height);
381
+ height: var(
382
+ --internal-slider-track-height,
383
+ var(--svelte-ui-slider-track-height)
384
+ );
386
385
  margin: 0;
387
386
  background: var(--svelte-ui-slider-track-background);
388
387
  border-radius: var(--svelte-ui-slider-track-border-radius);
@@ -395,17 +394,35 @@
395
394
  /* Track styles */
396
395
  .slider__input::-webkit-slider-track {
397
396
  width: 100%;
398
- height: var(--svelte-ui-slider-track-height);
399
- background: var(--svelte-ui-slider-track-background);
400
- border-radius: var(--svelte-ui-slider-track-border-radius);
397
+ height: var(
398
+ --internal-slider-track-height,
399
+ var(--svelte-ui-slider-track-height)
400
+ );
401
+ background: var(
402
+ --internal-slider-track-background,
403
+ var(--svelte-ui-slider-track-background)
404
+ );
405
+ border-radius: var(
406
+ --internal-slider-track-border-radius,
407
+ var(--svelte-ui-slider-track-border-radius)
408
+ );
401
409
  border: none;
402
410
  }
403
411
 
404
412
  .slider__input::-moz-range-track {
405
413
  width: 100%;
406
- height: var(--svelte-ui-slider-track-height);
407
- background: var(--svelte-ui-slider-track-background);
408
- border-radius: var(--svelte-ui-slider-track-border-radius);
414
+ height: var(
415
+ --internal-slider-track-height,
416
+ var(--svelte-ui-slider-track-height)
417
+ );
418
+ background: var(
419
+ --internal-slider-track-background,
420
+ var(--svelte-ui-slider-track-background)
421
+ );
422
+ border-radius: var(
423
+ --internal-slider-track-border-radius,
424
+ var(--svelte-ui-slider-track-border-radius)
425
+ );
409
426
  border: none;
410
427
  }
411
428
 
@@ -413,21 +430,51 @@
413
430
  .slider__input::-webkit-slider-thumb {
414
431
  -webkit-appearance: none;
415
432
  appearance: none;
416
- width: var(--svelte-ui-slider-thumb-width);
417
- height: var(--svelte-ui-slider-thumb-height);
418
- background: var(--svelte-ui-slider-thumb-background);
419
- border-radius: var(--svelte-ui-slider-thumb-border-radius);
420
- border: var(--svelte-ui-slider-thumb-border);
433
+ width: var(
434
+ --internal-slider-thumb-width,
435
+ var(--svelte-ui-slider-thumb-width)
436
+ );
437
+ height: var(
438
+ --internal-slider-thumb-height,
439
+ var(--svelte-ui-slider-thumb-height)
440
+ );
441
+ background: var(
442
+ --internal-slider-thumb-background,
443
+ var(--svelte-ui-slider-thumb-background)
444
+ );
445
+ border-radius: var(
446
+ --internal-slider-thumb-border-radius,
447
+ var(--svelte-ui-slider-thumb-border-radius)
448
+ );
449
+ border: var(
450
+ --internal-slider-thumb-border,
451
+ var(--svelte-ui-slider-thumb-border)
452
+ );
421
453
  cursor: pointer;
422
454
  box-shadow: var(--svelte-ui-slider-thumb-shadow);
423
455
  }
424
456
 
425
457
  .slider__input::-moz-range-thumb {
426
- width: var(--svelte-ui-slider-thumb-width);
427
- height: var(--svelte-ui-slider-thumb-height);
428
- background: var(--svelte-ui-slider-thumb-background);
429
- border-radius: var(--svelte-ui-slider-thumb-border-radius);
430
- border: var(--svelte-ui-slider-thumb-border);
458
+ width: var(
459
+ --internal-slider-thumb-width,
460
+ var(--svelte-ui-slider-thumb-width)
461
+ );
462
+ height: var(
463
+ --internal-slider-thumb-height,
464
+ var(--svelte-ui-slider-thumb-height)
465
+ );
466
+ background: var(
467
+ --internal-slider-thumb-background,
468
+ var(--svelte-ui-slider-thumb-background)
469
+ );
470
+ border-radius: var(
471
+ --internal-slider-thumb-border-radius,
472
+ var(--svelte-ui-slider-thumb-border-radius)
473
+ );
474
+ border: var(
475
+ --internal-slider-thumb-border,
476
+ var(--svelte-ui-slider-thumb-border)
477
+ );
431
478
  cursor: pointer;
432
479
  box-shadow: var(--svelte-ui-slider-thumb-shadow);
433
480
  }
@@ -146,22 +146,33 @@
146
146
 
147
147
  <div
148
148
  bind:this={snackbarRef}
149
- class="snackbar-item snackbar-item--{position} {visible ? '' : 'snackbar-item--hidden'}"
149
+ class="snackbar-item"
150
+ class:snackbar-item--top={position === 'top'}
151
+ class:snackbar-item--bottom={position === 'bottom'}
152
+ class:snackbar-item--hidden={!visible}
150
153
  data-testid="snackbar-item"
151
154
  >
152
155
  <div
153
- class="snackbar-item__content snackbar-item__content--{type} snackbar-item__content--{variant} snackbar-item__content--{position} {visible
154
- ? 'snackbar-item__content--visible'
155
- : ''}"
156
- style="--svelte-ui-snackbar-item-custom-color: {color ??
157
- 'unset'}; --svelte-ui-snackbar-item-custom-text-color: {textColor ?? 'unset'};"
156
+ class="snackbar-item__content"
157
+ class:snackbar-item__content--info={type === 'info'}
158
+ class:snackbar-item__content--success={type === 'success'}
159
+ class:snackbar-item__content--warning={type === 'warning'}
160
+ class:snackbar-item__content--error={type === 'error'}
161
+ class:snackbar-item__content--default={type === 'default'}
162
+ class:snackbar-item__content--filled={variant === 'filled'}
163
+ class:snackbar-item__content--outlined={variant === 'outlined'}
164
+ class:snackbar-item__content--top={position === 'top'}
165
+ class:snackbar-item__content--bottom={position === 'bottom'}
166
+ class:snackbar-item__content--visible={visible}
167
+ style:--internal-snackbar-item-custom-color={color ?? 'unset'}
168
+ style:--internal-snackbar-item-custom-text-color={textColor ?? 'unset'}
158
169
  role={type === 'error' || type === 'warning' ? 'alert' : 'status'}
159
170
  aria-live={type === 'error' || type === 'warning' ? 'assertive' : 'polite'}
160
171
  aria-atomic="true"
161
172
  aria-hidden={!visible}
162
173
  >
163
174
  {#if typeIcons[type]}
164
- <div class="snackbar__icon" aria-hidden="true">
175
+ <div class="snackbar-item__icon" aria-hidden="true">
165
176
  <Icon name={typeIcons[type]} size={32}>{typeIcons[type]}</Icon>
166
177
  </div>
167
178
  {/if}
@@ -332,90 +343,90 @@
332
343
  /* Type variants - filled */
333
344
  .snackbar-item__content--filled.snackbar-item__content--info {
334
345
  background-color: var(
335
- --svelte-ui-snackbar-item-custom-color,
346
+ --internal-snackbar-item-custom-color,
336
347
  var(--svelte-ui-snackbar-info-filled-bg)
337
348
  );
338
349
  color: var(
339
- --svelte-ui-snackbar-item-custom-text-color,
350
+ --internal-snackbar-item-custom-text-color,
340
351
  var(--svelte-ui-snackbar-info-filled-text-color)
341
352
  );
342
353
  }
343
354
 
344
355
  .snackbar-item__content--filled.snackbar-item__content--info .snackbar-item__icon {
345
356
  color: var(
346
- --svelte-ui-snackbar-item-custom-text-color,
357
+ --internal-snackbar-item-custom-text-color,
347
358
  var(--svelte-ui-snackbar-info-filled-text-color)
348
359
  );
349
360
  }
350
361
 
351
362
  .snackbar-item__content--filled.snackbar-item__content--success {
352
363
  background-color: var(
353
- --svelte-ui-snackbar-item-custom-color,
364
+ --internal-snackbar-item-custom-color,
354
365
  var(--svelte-ui-snackbar-success-filled-bg)
355
366
  );
356
367
  color: var(
357
- --svelte-ui-snackbar-item-custom-text-color,
368
+ --internal-snackbar-item-custom-text-color,
358
369
  var(--svelte-ui-snackbar-success-filled-text-color)
359
370
  );
360
371
  }
361
372
 
362
373
  .snackbar-item__content--filled.snackbar-item__content--success .snackbar-item__icon {
363
374
  color: var(
364
- --svelte-ui-snackbar-item-custom-text-color,
375
+ --internal-snackbar-item-custom-text-color,
365
376
  var(--svelte-ui-snackbar-success-filled-text-color)
366
377
  );
367
378
  }
368
379
 
369
380
  .snackbar-item__content--filled.snackbar-item__content--warning {
370
381
  background-color: var(
371
- --svelte-ui-snackbar-item-custom-color,
382
+ --internal-snackbar-item-custom-color,
372
383
  var(--svelte-ui-snackbar-warning-filled-bg)
373
384
  );
374
385
  color: var(
375
- --svelte-ui-snackbar-item-custom-text-color,
386
+ --internal-snackbar-item-custom-text-color,
376
387
  var(--svelte-ui-snackbar-warning-filled-text-color)
377
388
  );
378
389
  }
379
390
 
380
391
  .snackbar-item__content--filled.snackbar-item__content--warning .snackbar-item__icon {
381
392
  color: var(
382
- --svelte-ui-snackbar-item-custom-text-color,
393
+ --internal-snackbar-item-custom-text-color,
383
394
  var(--svelte-ui-snackbar-warning-filled-text-color)
384
395
  );
385
396
  }
386
397
 
387
398
  .snackbar-item__content--filled.snackbar-item__content--error {
388
399
  background-color: var(
389
- --svelte-ui-snackbar-item-custom-color,
400
+ --internal-snackbar-item-custom-color,
390
401
  var(--svelte-ui-snackbar-error-filled-bg)
391
402
  );
392
403
  color: var(
393
- --svelte-ui-snackbar-item-custom-text-color,
404
+ --internal-snackbar-item-custom-text-color,
394
405
  var(--svelte-ui-snackbar-error-filled-text-color)
395
406
  );
396
407
  }
397
408
 
398
409
  .snackbar-item__content--filled.snackbar-item__content--error .snackbar-item__icon {
399
410
  color: var(
400
- --svelte-ui-snackbar-item-custom-text-color,
411
+ --internal-snackbar-item-custom-text-color,
401
412
  var(--svelte-ui-snackbar-error-filled-text-color)
402
413
  );
403
414
  }
404
415
 
405
416
  .snackbar-item__content--filled.snackbar-item__content--default {
406
417
  background-color: var(
407
- --svelte-ui-snackbar-item-custom-color,
418
+ --internal-snackbar-item-custom-color,
408
419
  var(--svelte-ui-snackbar-default-filled-bg)
409
420
  );
410
421
  color: var(
411
- --svelte-ui-snackbar-item-custom-text-color,
422
+ --internal-snackbar-item-custom-text-color,
412
423
  var(--svelte-ui-snackbar-default-filled-text-color)
413
424
  );
414
425
  }
415
426
 
416
427
  .snackbar-item__content--filled.snackbar-item__content--default .snackbar-item__icon {
417
428
  color: var(
418
- --svelte-ui-snackbar-item-custom-text-color,
429
+ --internal-snackbar-item-custom-text-color,
419
430
  var(--svelte-ui-snackbar-default-filled-text-color)
420
431
  );
421
432
  }
@@ -423,115 +434,115 @@
423
434
  /* Type variants - outlined */
424
435
  .snackbar-item__content--outlined.snackbar-item__content--info {
425
436
  background-color: var(
426
- --svelte-ui-snackbar-item-custom-color,
437
+ --internal-snackbar-item-custom-color,
427
438
  var(--svelte-ui-snackbar-info-outlined-bg)
428
439
  );
429
440
  color: var(
430
- --svelte-ui-snackbar-item-custom-text-color,
441
+ --internal-snackbar-item-custom-text-color,
431
442
  var(--svelte-ui-snackbar-info-outlined-text-color)
432
443
  );
433
444
  box-shadow: inset 0 0 0 1px
434
445
  var(
435
- --svelte-ui-snackbar-item-custom-color,
446
+ --internal-snackbar-item-custom-color,
436
447
  var(--svelte-ui-snackbar-info-outlined-border-color)
437
448
  );
438
449
  }
439
450
 
440
451
  .snackbar-item__content--outlined.snackbar-item__content--info .snackbar-item__icon {
441
452
  color: var(
442
- --svelte-ui-snackbar-item-custom-text-color,
453
+ --internal-snackbar-item-custom-text-color,
443
454
  var(--svelte-ui-snackbar-info-outlined-text-color)
444
455
  );
445
456
  }
446
457
 
447
458
  .snackbar-item__content--outlined.snackbar-item__content--success {
448
459
  background-color: var(
449
- --svelte-ui-snackbar-item-custom-color,
460
+ --internal-snackbar-item-custom-color,
450
461
  var(--svelte-ui-snackbar-success-outlined-bg)
451
462
  );
452
463
  color: var(
453
- --svelte-ui-snackbar-item-custom-text-color,
464
+ --internal-snackbar-item-custom-text-color,
454
465
  var(--svelte-ui-snackbar-success-outlined-text-color)
455
466
  );
456
467
  box-shadow: inset 0 0 0 1px
457
468
  var(
458
- --svelte-ui-snackbar-item-custom-color,
469
+ --internal-snackbar-item-custom-color,
459
470
  var(--svelte-ui-snackbar-success-outlined-border-color)
460
471
  );
461
472
  }
462
473
 
463
474
  .snackbar-item__content--outlined.snackbar-item__content--success .snackbar-item__icon {
464
475
  color: var(
465
- --svelte-ui-snackbar-item-custom-text-color,
476
+ --internal-snackbar-item-custom-text-color,
466
477
  var(--svelte-ui-snackbar-success-outlined-text-color)
467
478
  );
468
479
  }
469
480
 
470
481
  .snackbar-item__content--outlined.snackbar-item__content--warning {
471
482
  background-color: var(
472
- --svelte-ui-snackbar-item-custom-color,
483
+ --internal-snackbar-item-custom-color,
473
484
  var(--svelte-ui-snackbar-warning-outlined-bg)
474
485
  );
475
486
  color: var(
476
- --svelte-ui-snackbar-item-custom-text-color,
487
+ --internal-snackbar-item-custom-text-color,
477
488
  var(--svelte-ui-snackbar-warning-outlined-text-color)
478
489
  );
479
490
  box-shadow: inset 0 0 0 1px
480
491
  var(
481
- --svelte-ui-snackbar-item-custom-color,
492
+ --internal-snackbar-item-custom-color,
482
493
  var(--svelte-ui-snackbar-warning-outlined-border-color)
483
494
  );
484
495
  }
485
496
 
486
497
  .snackbar-item__content--outlined.snackbar-item__content--warning .snackbar-item__icon {
487
498
  color: var(
488
- --svelte-ui-snackbar-item-custom-text-color,
499
+ --internal-snackbar-item-custom-text-color,
489
500
  var(--svelte-ui-snackbar-warning-outlined-text-color)
490
501
  );
491
502
  }
492
503
 
493
504
  .snackbar-item__content--outlined.snackbar-item__content--error {
494
505
  background-color: var(
495
- --svelte-ui-snackbar-item-custom-color,
506
+ --internal-snackbar-item-custom-color,
496
507
  var(--svelte-ui-snackbar-error-outlined-bg)
497
508
  );
498
509
  color: var(
499
- --svelte-ui-snackbar-item-custom-text-color,
510
+ --internal-snackbar-item-custom-text-color,
500
511
  var(--svelte-ui-snackbar-error-outlined-text-color)
501
512
  );
502
513
  box-shadow: inset 0 0 0 1px
503
514
  var(
504
- --svelte-ui-snackbar-item-custom-color,
515
+ --internal-snackbar-item-custom-color,
505
516
  var(--svelte-ui-snackbar-error-outlined-border-color)
506
517
  );
507
518
  }
508
519
 
509
520
  .snackbar-item__content--outlined.snackbar-item__content--error .snackbar-item__icon {
510
521
  color: var(
511
- --svelte-ui-snackbar-item-custom-text-color,
522
+ --internal-snackbar-item-custom-text-color,
512
523
  var(--svelte-ui-snackbar-error-outlined-text-color)
513
524
  );
514
525
  }
515
526
 
516
527
  .snackbar-item__content--outlined.snackbar-item__content--default {
517
528
  background-color: var(
518
- --svelte-ui-snackbar-item-custom-color,
529
+ --internal-snackbar-item-custom-color,
519
530
  var(--svelte-ui-snackbar-default-outlined-bg)
520
531
  );
521
532
  color: var(
522
- --svelte-ui-snackbar-item-custom-text-color,
533
+ --internal-snackbar-item-custom-text-color,
523
534
  var(--svelte-ui-snackbar-default-outlined-text-color)
524
535
  );
525
536
  box-shadow: inset 0 0 0 1px
526
537
  var(
527
- --svelte-ui-snackbar-item-custom-color,
538
+ --internal-snackbar-item-custom-color,
528
539
  var(--svelte-ui-snackbar-default-outlined-border-color)
529
540
  );
530
541
  }
531
542
 
532
543
  .snackbar-item__content--outlined.snackbar-item__content--default .snackbar-item__icon {
533
544
  color: var(
534
- --svelte-ui-snackbar-item-custom-text-color,
545
+ --internal-snackbar-item-custom-text-color,
535
546
  var(--svelte-ui-snackbar-default-outlined-text-color)
536
547
  );
537
548
  }
@@ -3,7 +3,7 @@
3
3
  <script lang="ts">
4
4
  import TabItem from './TabItem.svelte';
5
5
  import type { MenuItem } from '../types/menuItem';
6
- import { afterNavigate } from '$app/navigation';
6
+ import { subscribeUrlChange } from '../utils/urlChange';
7
7
 
8
8
  // =========================================================================
9
9
  // Props, States & Constants
@@ -44,6 +44,21 @@
44
44
 
45
45
  let resolvedCurrentPath = $state('');
46
46
 
47
+ // =========================================================================
48
+ // Effects
49
+ // =========================================================================
50
+ $effect(() => {
51
+ // props の currentPath が変更されたとき
52
+ resolvedCurrentPath = getCurrentPath();
53
+ });
54
+
55
+ $effect(() => {
56
+ // URL の変更を subscribe
57
+ return subscribeUrlChange(() => {
58
+ resolvedCurrentPath = getCurrentPath();
59
+ });
60
+ });
61
+
47
62
  // =========================================================================
48
63
  // Methods
49
64
  // =========================================================================
@@ -57,18 +72,10 @@
57
72
  if (typeof window !== 'undefined') {
58
73
  return window.location.pathname;
59
74
  }
75
+
60
76
  return '';
61
77
  };
62
78
 
63
- // currentPath が渡されたときやマウント時に選択状態を反映
64
- $effect(() => {
65
- resolvedCurrentPath = getCurrentPath();
66
- });
67
-
68
- afterNavigate(() => {
69
- resolvedCurrentPath = getCurrentPath();
70
- });
71
-
72
79
  // パスの正規化処理
73
80
  const normalizePath = (path: string): string => {
74
81
  if (!pathPrefix) return path;
@@ -109,11 +116,6 @@
109
116
  return normalizedCurrentPath !== '' && normalizedCurrentPath.startsWith(itemHref);
110
117
  };
111
118
 
112
- // 有効なタブのインデックス一覧(disabled を除く)
113
- const enabledIndices = $derived(
114
- tabItems.map((item, i) => (item.disabled ? -1 : i)).filter((i) => i >= 0)
115
- );
116
-
117
119
  // シンプルなキーボードナビゲーション(disabled タブはスキップ)
118
120
  const handleKeyDown = (event: KeyboardEvent) => {
119
121
  if (tabItems.length === 0 || enabledIndices.length === 0) return;
@@ -171,6 +173,11 @@
171
173
  }
172
174
  return -1;
173
175
  });
176
+
177
+ // 有効なタブのインデックス一覧(disabled を除く)
178
+ const enabledIndices = $derived(
179
+ tabItems.map((item, i) => (item.disabled ? -1 : i)).filter((i) => i >= 0)
180
+ );
174
181
  </script>
175
182
 
176
183
  <div
@@ -71,23 +71,19 @@
71
71
  return `${pathPrefix}${tabItem.href.startsWith('/') ? '' : '/'}${tabItem.href}`;
72
72
  });
73
73
 
74
- // 明示的に渡されたときだけ style で上書き。未渡しなら variables の tab 用変数をそのまま参照
75
- const tabItemStyle = $derived.by(() => {
76
- const parts: string[] = [];
77
- if (textColor !== undefined) parts.push(`--svelte-ui-tab-item-text-color: ${textColor}`);
78
- if (selectedTextColor !== undefined)
79
- parts.push(`--svelte-ui-tab-item-selected-text-color: ${selectedTextColor}`);
80
- if (selectedBarColor !== undefined)
81
- parts.push(`--svelte-ui-tab-item-selected-bar-color: ${selectedBarColor}`);
82
- return parts.length > 0 ? parts.join('; ') : undefined;
83
- });
74
+ // 明示的に渡されたときだけ内部CSS変数で上書き。未渡しなら variables の tab 用変数をそのまま参照
75
+ const internalTextColor = $derived(textColor);
76
+ const internalSelectedTextColor = $derived(selectedTextColor);
77
+ const internalSelectedBarColor = $derived(selectedBarColor);
84
78
  </script>
85
79
 
86
80
  {#if isDisabled}
87
81
  <span
88
82
  class="tab-item tab-item--disabled"
89
83
  class:tab-item--selected={isSelected}
90
- style={tabItemStyle}
84
+ style:--internal-tab-item-text-color={internalTextColor}
85
+ style:--internal-tab-item-selected-text-color={internalSelectedTextColor}
86
+ style:--internal-tab-item-selected-bar-color={internalSelectedBarColor}
91
87
  role="tab"
92
88
  aria-selected={isSelected}
93
89
  aria-disabled="true"
@@ -116,7 +112,9 @@
116
112
  href={hrefWithPrefix}
117
113
  class="tab-item"
118
114
  class:tab-item--selected={isSelected}
119
- style={tabItemStyle}
115
+ style:--internal-tab-item-text-color={internalTextColor}
116
+ style:--internal-tab-item-selected-text-color={internalSelectedTextColor}
117
+ style:--internal-tab-item-selected-bar-color={internalSelectedBarColor}
120
118
  role="tab"
121
119
  aria-selected={isSelected}
122
120
  tabindex={0}
@@ -149,7 +147,7 @@
149
147
  gap: var(--svelte-ui-tab-item-icon-gap);
150
148
  position: relative;
151
149
  padding: var(--svelte-ui-tab-item-padding);
152
- color: var(--svelte-ui-tab-item-text-color);
150
+ color: var(--internal-tab-item-text-color, var(--svelte-ui-tab-item-text-color));
153
151
  white-space: nowrap;
154
152
  text-decoration: none;
155
153
  transition-property: background-color, color, outline;
@@ -159,7 +157,7 @@
159
157
 
160
158
  @media (hover: hover) {
161
159
  .tab-item:hover:not(.tab-item--selected) {
162
- color: var(--svelte-ui-tab-item-selected-text-color);
160
+ color: var(--internal-tab-item-selected-text-color, var(--svelte-ui-tab-item-selected-text-color));
163
161
  }
164
162
  .tab-item:hover:not(.tab-item--selected)::before {
165
163
  opacity: 1;
@@ -178,7 +176,7 @@
178
176
  outline-offset: var(--svelte-ui-focus-outline-offset-inner);
179
177
  }
180
178
  .tab-item:focus:not(.tab-item--selected) {
181
- color: var(--svelte-ui-tab-item-selected-text-color);
179
+ color: var(--internal-tab-item-selected-text-color, var(--svelte-ui-tab-item-selected-text-color));
182
180
  }
183
181
  .tab-item:focus:not(.tab-item--selected)::before {
184
182
  opacity: 1;
@@ -193,7 +191,7 @@
193
191
  bottom: 0;
194
192
  width: calc(100% - 2 * var(--svelte-ui-tab-item-padding-x) + 2 * var(--svelte-ui-tab-item-selected-bar-offset));
195
193
  height: var(--svelte-ui-tab-item-selected-bar-height);
196
- background-color: var(--svelte-ui-tab-item-selected-bar-color);
194
+ background-color: var(--internal-tab-item-selected-bar-color, var(--svelte-ui-tab-item-selected-bar-color));
197
195
  border-radius: var(--svelte-ui-tab-item-selected-bar-radius);
198
196
  opacity: 0;
199
197
  transition-property: opacity;
@@ -201,7 +199,7 @@
201
199
  }
202
200
 
203
201
  .tab-item--selected {
204
- color: var(--svelte-ui-tab-item-selected-text-color);
202
+ color: var(--internal-tab-item-selected-text-color, var(--svelte-ui-tab-item-selected-text-color));
205
203
  background-color: transparent;
206
204
  }
207
205
 
@@ -524,13 +524,16 @@
524
524
  class:textarea--readonly={readonly}
525
525
  class:textarea--focused={isFocused}
526
526
  data-testid="textarea"
527
- style="width: {widthStyle}; {!inline ? `max-height: ${maxHeightStyle};` : ''}"
527
+ style:width={widthStyle}
528
+ style:max-height={!inline ? maxHeightStyle : undefined}
528
529
  >
529
530
  <div
530
531
  bind:this={displayTextRef}
531
532
  class="textarea__display-text"
532
533
  class:textarea__display-text--placeholder={!hasDisplayValue}
533
- style="min-height: {minHeightStyle}; max-height: {maxHeightStyle}; {customStyle}"
534
+ style:min-height={minHeightStyle}
535
+ style:max-height={maxHeightStyle}
536
+ style={customStyle}
534
537
  >
535
538
  {@html displayValue}
536
539
  </div>
@@ -552,7 +555,8 @@
552
555
  {spellcheck}
553
556
  {autocapitalize}
554
557
  class:resizable
555
- style="min-height: {minHeightStyle}; {customStyle}"
558
+ style:min-height={minHeightStyle}
559
+ style={customStyle}
556
560
  onchange={handleChange}
557
561
  oninput={handleInput}
558
562
  onfocus={handleFocus}
@@ -587,7 +591,9 @@
587
591
  <div
588
592
  bind:this={linkTextRef}
589
593
  class="textarea__link-text"
590
- style="min-height: {minHeightStyle}; max-height: {maxHeightStyle}; {customStyle}"
594
+ style:min-height={minHeightStyle}
595
+ style:max-height={maxHeightStyle}
596
+ style={customStyle}
591
597
  >
592
598
  {@html linkHtmlValue}
593
599
  </div>
@@ -0,0 +1 @@
1
+ export declare const subscribeUrlChange: (handler: () => void) => () => void;
@@ -0,0 +1,29 @@
1
+ const URL_CHANGE_EVENT = 'svelte-ui:urlchange';
2
+ let historyPatched = false;
3
+ const patchHistory = () => {
4
+ if (historyPatched || typeof window === 'undefined')
5
+ return;
6
+ historyPatched = true;
7
+ const originalPushState = history.pushState.bind(history);
8
+ const originalReplaceState = history.replaceState.bind(history);
9
+ history.pushState = (...args) => {
10
+ originalPushState(...args);
11
+ window.dispatchEvent(new Event(URL_CHANGE_EVENT));
12
+ };
13
+ history.replaceState = (...args) => {
14
+ originalReplaceState(...args);
15
+ window.dispatchEvent(new Event(URL_CHANGE_EVENT));
16
+ };
17
+ };
18
+ export const subscribeUrlChange = (handler) => {
19
+ if (typeof window === 'undefined') {
20
+ return () => { };
21
+ }
22
+ patchHistory();
23
+ window.addEventListener('popstate', handler);
24
+ window.addEventListener(URL_CHANGE_EVENT, handler);
25
+ return () => {
26
+ window.removeEventListener('popstate', handler);
27
+ window.removeEventListener(URL_CHANGE_EVENT, handler);
28
+ };
29
+ };
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.19",
5
+ "version": "0.0.21",
6
6
  "type": "module",
7
7
  "keywords": [
8
8
  "svelte",
@@ -106,7 +106,6 @@
106
106
  "sass": "^1.89.2"
107
107
  },
108
108
  "peerDependencies": {
109
- "@sveltejs/kit": "^2.0.0",
110
109
  "svelte": "^5.0.0"
111
110
  }
112
111
  }