@14ch/svelte-ui 0.0.68 → 0.0.70
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/import.css +22 -5
- package/dist/assets/styles/variables.scss +22 -5
- package/dist/components/ColorPicker.svelte +1 -1
- package/dist/components/Input.svelte +56 -94
- package/dist/components/MultiSelect.svelte +40 -36
- package/dist/components/MultiSelect.svelte.d.ts +2 -2
- package/dist/components/Select.svelte +492 -318
- package/dist/components/Select.svelte.d.ts +10 -9
- package/dist/components/StepNav.svelte +20 -6
- package/dist/components/StepNav.svelte.d.ts +4 -0
- package/dist/components/Textarea.svelte +64 -54
- package/package.json +1 -1
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import type { FocusHandler, KeyboardHandler, MouseHandler, TouchHandler, PointerHandler, BivariantValueHandler } from '../types/callbackHandlers';
|
|
2
|
-
import type { Option } from '../types/options';
|
|
3
|
-
import type {
|
|
4
|
-
export type SelectProps =
|
|
2
|
+
import type { Option, OptionValue } from '../types/options';
|
|
3
|
+
import type { PopupPosition } from '../types/propOptions';
|
|
4
|
+
export type SelectProps = {
|
|
5
5
|
name?: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/** Supports `bind:value`. */
|
|
7
|
+
value: OptionValue;
|
|
8
|
+
/** `{ label, value, disabled? }[]` or `'separator'` for dividers. */
|
|
9
|
+
options: (Option | 'separator')[];
|
|
9
10
|
id?: string | null;
|
|
10
11
|
ariaLabel?: string;
|
|
11
12
|
tabindex?: number | null;
|
|
12
13
|
placeholder?: string;
|
|
13
|
-
/** Number of visible rows (multi-line mode). @default null */
|
|
14
|
-
size?: number | null;
|
|
15
14
|
/** Renders inline. @default false */
|
|
16
15
|
inline?: boolean;
|
|
17
16
|
/** @default 'outline' */
|
|
@@ -21,6 +20,8 @@ export type SelectProps = Omit<HTMLSelectAttributes, 'value' | 'id' | 'tabindex'
|
|
|
21
20
|
customStyle?: string;
|
|
22
21
|
disabled?: boolean;
|
|
23
22
|
required?: boolean;
|
|
23
|
+
/** @default 'bottom-left' */
|
|
24
|
+
position?: PopupPosition;
|
|
24
25
|
onfocus?: FocusHandler;
|
|
25
26
|
onblur?: FocusHandler;
|
|
26
27
|
onkeydown?: KeyboardHandler;
|
|
@@ -44,7 +45,7 @@ export type SelectProps = Omit<HTMLSelectAttributes, 'value' | 'id' | 'tabindex'
|
|
|
44
45
|
onpointerleave?: PointerHandler;
|
|
45
46
|
onpointermove?: PointerHandler;
|
|
46
47
|
onpointercancel?: PointerHandler;
|
|
47
|
-
onchange?: BivariantValueHandler<
|
|
48
|
+
onchange?: BivariantValueHandler<OptionValue>;
|
|
48
49
|
};
|
|
49
50
|
declare const Select: import("svelte").Component<SelectProps, {}, "value">;
|
|
50
51
|
type Select = ReturnType<typeof Select>;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
KeyboardHandler,
|
|
13
13
|
BivariantValueHandler
|
|
14
14
|
} from '../types/callbackHandlers';
|
|
15
|
+
import { getStyleFromNumber } from '../utils/style';
|
|
15
16
|
import { getCurrentPath, matchPath } from '../utils/navPath';
|
|
16
17
|
import { subscribeUrlChange } from '../utils/urlChange';
|
|
17
18
|
import { t } from '../i18n';
|
|
@@ -52,6 +53,10 @@
|
|
|
52
53
|
size?: ComponentSize;
|
|
53
54
|
/** 現在/完了ステップの強調色。テーマ色より優先。 */
|
|
54
55
|
color?: string;
|
|
56
|
+
/** 幅。数値は px として扱う。 */
|
|
57
|
+
width?: string | number | null;
|
|
58
|
+
minWidth?: string | number | null;
|
|
59
|
+
maxWidth?: string | number | null;
|
|
55
60
|
/** 番号の代わりに各ステップの icon を表示。 @default false */
|
|
56
61
|
showIcon?: boolean;
|
|
57
62
|
/** 追加インラインスタイル。 */
|
|
@@ -103,6 +108,9 @@
|
|
|
103
108
|
orientation = 'horizontal',
|
|
104
109
|
size = 'medium',
|
|
105
110
|
color,
|
|
111
|
+
width = null,
|
|
112
|
+
minWidth = null,
|
|
113
|
+
maxWidth = null,
|
|
106
114
|
showIcon = false,
|
|
107
115
|
customStyle = '',
|
|
108
116
|
|
|
@@ -204,12 +212,19 @@
|
|
|
204
212
|
.join(' ')
|
|
205
213
|
);
|
|
206
214
|
|
|
215
|
+
const widthStyle = $derived(getStyleFromNumber(width));
|
|
216
|
+
const minWidthStyle = $derived(getStyleFromNumber(minWidth));
|
|
217
|
+
const maxWidthStyle = $derived(getStyleFromNumber(maxWidth));
|
|
218
|
+
|
|
207
219
|
const rootStyle = $derived(
|
|
208
220
|
[
|
|
209
221
|
// color 指定時は強調色を上書き。リングは半透明の色なので同率で合成した値も注入する。
|
|
210
222
|
color ? `--internal-step-nav-accent:${color}` : '',
|
|
211
223
|
color ? `--internal-step-nav-ring-color:color-mix(in srgb, ${color} 40%, transparent)` : '',
|
|
212
|
-
customStyle
|
|
224
|
+
customStyle,
|
|
225
|
+
widthStyle ? `width: ${widthStyle}` : '',
|
|
226
|
+
minWidthStyle ? `min-width: ${minWidthStyle}` : '',
|
|
227
|
+
maxWidthStyle ? `max-width: ${maxWidthStyle}` : ''
|
|
213
228
|
]
|
|
214
229
|
.filter(Boolean)
|
|
215
230
|
.join('; ')
|
|
@@ -504,14 +519,12 @@ button.step-nav__step {
|
|
|
504
519
|
|
|
505
520
|
/* upcoming: 淡いアウトライン + 番号 */
|
|
506
521
|
.step-nav__step--upcoming .step-nav__marker {
|
|
507
|
-
background: var(--svelte-ui-surface-color);
|
|
508
522
|
color: var(--svelte-ui-step-nav-upcoming-text-color);
|
|
509
523
|
border: var(--svelte-ui-step-nav-marker-border-width) solid var(--svelte-ui-step-nav-upcoming-marker-color);
|
|
510
524
|
}
|
|
511
525
|
|
|
512
526
|
/* in-progress: primary アウトライン + 番号 */
|
|
513
527
|
.step-nav__step--in-progress .step-nav__marker {
|
|
514
|
-
background: var(--svelte-ui-surface-color);
|
|
515
528
|
color: var(--internal-step-nav-accent, var(--svelte-ui-step-nav-accent-color));
|
|
516
529
|
border: var(--svelte-ui-step-nav-marker-border-width) solid var(--internal-step-nav-accent, var(--svelte-ui-step-nav-accent-color));
|
|
517
530
|
}
|
|
@@ -525,14 +538,15 @@ button.step-nav__step {
|
|
|
525
538
|
|
|
526
539
|
/* error: error 色 + error アイコン(進捗軸を上書き) */
|
|
527
540
|
.step-nav__step--error .step-nav__marker {
|
|
528
|
-
background: var(--svelte-ui-surface-color);
|
|
529
541
|
color: var(--svelte-ui-step-nav-error-color);
|
|
530
542
|
border: var(--svelte-ui-step-nav-marker-border-width) solid var(--svelte-ui-step-nav-error-color);
|
|
531
543
|
}
|
|
532
544
|
|
|
533
|
-
/* 表示中:
|
|
545
|
+
/* 表示中: 外周リング(フォーカス表示とは別レイヤー・別色)。
|
|
546
|
+
リングとマーカーの隙間に背景が透けるよう、box-shadow ではなく outline で描く */
|
|
534
547
|
.step-nav__step--viewing .step-nav__marker {
|
|
535
|
-
|
|
548
|
+
outline: var(--svelte-ui-step-nav-ring-width) solid var(--internal-step-nav-ring-color, var(--svelte-ui-step-nav-ring-color));
|
|
549
|
+
outline-offset: var(--svelte-ui-step-nav-ring-offset);
|
|
536
550
|
}
|
|
537
551
|
|
|
538
552
|
/* ---- ラベル/説明 ---- */
|
|
@@ -31,6 +31,10 @@ export type StepNavProps = {
|
|
|
31
31
|
size?: ComponentSize;
|
|
32
32
|
/** 現在/完了ステップの強調色。テーマ色より優先。 */
|
|
33
33
|
color?: string;
|
|
34
|
+
/** 幅。数値は px として扱う。 */
|
|
35
|
+
width?: string | number | null;
|
|
36
|
+
minWidth?: string | number | null;
|
|
37
|
+
maxWidth?: string | number | null;
|
|
34
38
|
/** 番号の代わりに各ステップの icon を表示。 @default false */
|
|
35
39
|
showIcon?: boolean;
|
|
36
40
|
/** 追加インラインスタイル。 */
|
|
@@ -469,13 +469,18 @@
|
|
|
469
469
|
const width = rect.width;
|
|
470
470
|
if (!height || !width) return;
|
|
471
471
|
|
|
472
|
+
// 箱(ルート)は padding を持つため、textarea の実寸に padding 分を足す
|
|
473
|
+
const rootStyle = getComputedStyle(containerRef);
|
|
474
|
+
const paddingY = parseFloat(rootStyle.paddingTop) + parseFloat(rootStyle.paddingBottom);
|
|
475
|
+
const paddingX = parseFloat(rootStyle.paddingLeft) + parseFloat(rootStyle.paddingRight);
|
|
476
|
+
|
|
472
477
|
// コンポーネント全体の高さは textarea に合わせる
|
|
473
|
-
containerRef.style.height = `${height}px`;
|
|
478
|
+
containerRef.style.height = `${height + paddingY}px`;
|
|
474
479
|
|
|
475
480
|
// 幅は、初期状態では width プロップを優先し、
|
|
476
481
|
// ユーザーがリサイズ(ResizeObserver 経由)したあとは textarea の幅で上書きする
|
|
477
482
|
if (forceWidth || !widthStyle) {
|
|
478
|
-
containerRef.style.width = `${width}px`;
|
|
483
|
+
containerRef.style.width = `${width + paddingX}px`;
|
|
479
484
|
}
|
|
480
485
|
|
|
481
486
|
// display-text / link-text はコンテナにフィットさせる
|
|
@@ -549,6 +554,27 @@
|
|
|
549
554
|
);
|
|
550
555
|
const maxHeightStyle = $derived(getStyleFromNumber(maxHeight));
|
|
551
556
|
const widthStyle = $derived(getStyleFromNumber(width));
|
|
557
|
+
// 箱(ルート)は border-box、内側のテキスト層は padding を持たないので縦 padding を差し引く
|
|
558
|
+
const innerMinHeightStyle = $derived(
|
|
559
|
+
`calc(${minHeightStyle} - var(--internal-textarea-vertical-padding))`
|
|
560
|
+
);
|
|
561
|
+
const innerMaxHeightStyle = $derived(
|
|
562
|
+
maxHeightStyle
|
|
563
|
+
? `calc(${maxHeightStyle} - var(--internal-textarea-vertical-padding))`
|
|
564
|
+
: undefined
|
|
565
|
+
);
|
|
566
|
+
// アイコンの領域は customStyle で消されないよう、customStyle より後ろに指定する。
|
|
567
|
+
// style: ディレクティブは style 属性に勝つため、幅・最大高さも同じ文字列に混ぜる
|
|
568
|
+
const boxStyle = $derived(
|
|
569
|
+
[
|
|
570
|
+
customStyle,
|
|
571
|
+
clearable ? 'padding-right: var(--svelte-ui-textarea-icon-space)' : '',
|
|
572
|
+
widthStyle ? `width: ${widthStyle}` : '',
|
|
573
|
+
!inline && maxHeightStyle ? `max-height: ${maxHeightStyle}` : ''
|
|
574
|
+
]
|
|
575
|
+
.filter(Boolean)
|
|
576
|
+
.join('; ')
|
|
577
|
+
);
|
|
552
578
|
</script>
|
|
553
579
|
|
|
554
580
|
<div
|
|
@@ -567,16 +593,14 @@
|
|
|
567
593
|
class:textarea--readonly={readonly}
|
|
568
594
|
class:textarea--focused={isFocused}
|
|
569
595
|
data-testid="textarea"
|
|
570
|
-
style
|
|
571
|
-
style:max-height={!inline ? maxHeightStyle : undefined}
|
|
596
|
+
style={boxStyle}
|
|
572
597
|
>
|
|
573
598
|
<div
|
|
574
599
|
bind:this={displayTextRef}
|
|
575
600
|
class="textarea__display-text"
|
|
576
601
|
class:textarea__display-text--placeholder={!hasDisplayValue}
|
|
577
|
-
style:min-height={
|
|
578
|
-
style:max-height={
|
|
579
|
-
style={customStyle}
|
|
602
|
+
style:min-height={innerMinHeightStyle}
|
|
603
|
+
style:max-height={innerMaxHeightStyle}
|
|
580
604
|
>
|
|
581
605
|
{@html displayValue}
|
|
582
606
|
</div>
|
|
@@ -599,8 +623,7 @@
|
|
|
599
623
|
{spellcheck}
|
|
600
624
|
{autocapitalize}
|
|
601
625
|
class:resizable
|
|
602
|
-
style:min-height={
|
|
603
|
-
style={customStyle}
|
|
626
|
+
style:min-height={innerMinHeightStyle}
|
|
604
627
|
onchange={handleChange}
|
|
605
628
|
oninput={handleInput}
|
|
606
629
|
onfocus={handleFocus}
|
|
@@ -634,9 +657,8 @@
|
|
|
634
657
|
<div
|
|
635
658
|
bind:this={linkTextRef}
|
|
636
659
|
class="textarea__link-text"
|
|
637
|
-
style:min-height={
|
|
638
|
-
style:max-height={
|
|
639
|
-
style={customStyle}
|
|
660
|
+
style:min-height={innerMinHeightStyle}
|
|
661
|
+
style:max-height={innerMaxHeightStyle}
|
|
640
662
|
>
|
|
641
663
|
{@html linkHtmlValue}
|
|
642
664
|
</div>
|
|
@@ -670,6 +692,13 @@
|
|
|
670
692
|
width: auto;
|
|
671
693
|
max-width: 100%;
|
|
672
694
|
overflow: hidden;
|
|
695
|
+
--internal-textarea-vertical-padding: calc(
|
|
696
|
+
var(--svelte-ui-textarea-min-height) - var(--svelte-ui-textarea-line-height)
|
|
697
|
+
);
|
|
698
|
+
padding: var(--svelte-ui-textarea-padding);
|
|
699
|
+
background-color: var(--svelte-ui-textarea-bg);
|
|
700
|
+
box-shadow: 0 0 0 var(--svelte-ui-border-width) inset var(--svelte-ui-textarea-border-color);
|
|
701
|
+
border-radius: var(--svelte-ui-textarea-border-radius);
|
|
673
702
|
|
|
674
703
|
&.textarea--full-height {
|
|
675
704
|
height: 100%;
|
|
@@ -684,9 +713,8 @@
|
|
|
684
713
|
height: 100%;
|
|
685
714
|
padding: inherit;
|
|
686
715
|
border: none;
|
|
687
|
-
border-radius:
|
|
688
|
-
background-color:
|
|
689
|
-
box-shadow: 0 0 0 var(--svelte-ui-border-width) inset var(--svelte-ui-textarea-border-color);
|
|
716
|
+
border-radius: inherit;
|
|
717
|
+
background-color: transparent;
|
|
690
718
|
font-size: inherit;
|
|
691
719
|
font-weight: inherit;
|
|
692
720
|
color: inherit;
|
|
@@ -700,11 +728,11 @@
|
|
|
700
728
|
textarea {
|
|
701
729
|
width: 100%;
|
|
702
730
|
height: auto;
|
|
703
|
-
min-height: var(--svelte-ui-textarea-
|
|
704
|
-
padding:
|
|
731
|
+
min-height: var(--svelte-ui-textarea-line-height);
|
|
732
|
+
padding: 0;
|
|
705
733
|
background-color: transparent;
|
|
706
734
|
border: none;
|
|
707
|
-
border-radius:
|
|
735
|
+
border-radius: inherit;
|
|
708
736
|
font-family: inherit;
|
|
709
737
|
font-size: inherit;
|
|
710
738
|
font-weight: inherit;
|
|
@@ -724,10 +752,10 @@
|
|
|
724
752
|
.textarea__link-text {
|
|
725
753
|
display: block;
|
|
726
754
|
width: 100%;
|
|
727
|
-
min-height: var(--svelte-ui-textarea-
|
|
728
|
-
padding:
|
|
729
|
-
background:
|
|
730
|
-
border:
|
|
755
|
+
min-height: var(--svelte-ui-textarea-line-height);
|
|
756
|
+
padding: 0;
|
|
757
|
+
background: transparent;
|
|
758
|
+
border: none;
|
|
731
759
|
font-size: inherit;
|
|
732
760
|
font-weight: inherit;
|
|
733
761
|
color: inherit;
|
|
@@ -774,6 +802,7 @@
|
|
|
774
802
|
left: 0;
|
|
775
803
|
width: 100%;
|
|
776
804
|
height: 100%;
|
|
805
|
+
padding: inherit;
|
|
777
806
|
pointer-events: none;
|
|
778
807
|
z-index: 1;
|
|
779
808
|
}
|
|
@@ -818,7 +847,11 @@
|
|
|
818
847
|
/* =============================================
|
|
819
848
|
* フォーカス効果バリエーション
|
|
820
849
|
* ============================================= */
|
|
821
|
-
|
|
850
|
+
textarea:focus {
|
|
851
|
+
outline: none;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.textarea--focus-outline.textarea--focused .textarea__wrapper {
|
|
822
855
|
outline: var(--svelte-ui-focus-outline-inner);
|
|
823
856
|
outline-offset: var(--svelte-ui-focus-outline-offset-inner);
|
|
824
857
|
}
|
|
@@ -827,14 +860,6 @@
|
|
|
827
860
|
background: var(--svelte-ui-hover-overlay);
|
|
828
861
|
}
|
|
829
862
|
|
|
830
|
-
.textarea--focus-background textarea:focus {
|
|
831
|
-
outline: none;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
.textarea--focus-none textarea:focus {
|
|
835
|
-
outline: none;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
863
|
/* =============================================
|
|
839
864
|
* 状態管理(disabled, readonly等)
|
|
840
865
|
* ============================================= */
|
|
@@ -853,7 +878,7 @@
|
|
|
853
878
|
/* =============================================
|
|
854
879
|
* 表示切り替え
|
|
855
880
|
* ============================================= */
|
|
856
|
-
/* 非フォーカス時: textarea
|
|
881
|
+
/* 非フォーカス時: textarea要素自体を不可視化(枠線・背景はルートにあるため display-text のみ表示) */
|
|
857
882
|
.textarea:not(.textarea--focused) textarea {
|
|
858
883
|
opacity: 0;
|
|
859
884
|
}
|
|
@@ -868,14 +893,6 @@
|
|
|
868
893
|
* 機能バリエーション
|
|
869
894
|
* ============================================= */
|
|
870
895
|
/* clearable */
|
|
871
|
-
.textarea--clearable {
|
|
872
|
-
textarea,
|
|
873
|
-
.textarea__display-text,
|
|
874
|
-
.textarea__link-text {
|
|
875
|
-
padding-right: var(--svelte-ui-textarea-icon-space);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
|
|
879
896
|
@media (hover: hover) {
|
|
880
897
|
.textarea--clearable:hover .textarea__clear-button {
|
|
881
898
|
opacity: 1;
|
|
@@ -913,29 +930,22 @@
|
|
|
913
930
|
* デザインバリエーション
|
|
914
931
|
* ============================================= */
|
|
915
932
|
/* rounded */
|
|
916
|
-
.textarea--rounded:not(.textarea--inline)
|
|
917
|
-
.textarea--rounded:not(.textarea--inline) textarea {
|
|
933
|
+
.textarea--rounded:not(.textarea--inline) {
|
|
918
934
|
border-radius: var(--svelte-ui-textarea-border-radius-rounded);
|
|
919
935
|
}
|
|
920
936
|
|
|
921
937
|
/* inline */
|
|
922
938
|
.textarea--inline {
|
|
939
|
+
--internal-textarea-vertical-padding: 0px;
|
|
940
|
+
padding: 0;
|
|
941
|
+
background-color: transparent;
|
|
942
|
+
box-shadow: none;
|
|
943
|
+
border-radius: 0;
|
|
944
|
+
|
|
923
945
|
.textarea__display-text,
|
|
924
946
|
.textarea__link-text,
|
|
925
947
|
textarea {
|
|
926
948
|
min-height: auto;
|
|
927
|
-
padding-top: inherit;
|
|
928
|
-
padding-bottom: inherit;
|
|
929
|
-
padding-left: inherit;
|
|
930
|
-
padding-right: inherit;
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
.textarea__wrapper,
|
|
934
|
-
textarea {
|
|
935
|
-
padding: inherit;
|
|
936
|
-
background: transparent;
|
|
937
|
-
box-shadow: none;
|
|
938
|
-
border-radius: 0;
|
|
939
949
|
}
|
|
940
950
|
|
|
941
951
|
textarea {
|