@14ch/svelte-ui 0.0.50 → 0.0.52
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.
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
// 基本プロパティ
|
|
17
17
|
/** `{ label, href, icon?, children?, disabled? }[]` */
|
|
18
18
|
navItems?: MenuItem[];
|
|
19
|
+
/** `navItems` のエイリアス。両方指定された場合は `navItems` が優先。 */
|
|
20
|
+
items?: MenuItem[];
|
|
19
21
|
/** Layout variant. @default 'horizontal' */
|
|
20
22
|
variant?: NavVariant;
|
|
21
23
|
/** Prepended to each item's href for active-state matching. */
|
|
@@ -65,7 +67,8 @@
|
|
|
65
67
|
|
|
66
68
|
let {
|
|
67
69
|
// 基本プロパティ
|
|
68
|
-
navItems
|
|
70
|
+
navItems: navItemsProp,
|
|
71
|
+
items: itemsAlias,
|
|
69
72
|
variant = 'horizontal',
|
|
70
73
|
pathPrefix = '',
|
|
71
74
|
customPathMatcher,
|
|
@@ -103,6 +106,9 @@
|
|
|
103
106
|
ariaLabelledby
|
|
104
107
|
}: NavProps = $props();
|
|
105
108
|
|
|
109
|
+
// navItems(正式名)を優先し、items(エイリアス)へフォールバック
|
|
110
|
+
const navItems = $derived<MenuItem[]>(navItemsProp ?? itemsAlias ?? []);
|
|
111
|
+
|
|
106
112
|
let resolvedCurrentPath = $state('');
|
|
107
113
|
let navEl: HTMLElement | undefined = $state();
|
|
108
114
|
let subBarEl: HTMLElement | undefined = $state();
|
|
@@ -5,6 +5,8 @@ import type { IconVariant, IconWeight, IconGrade, IconOpticalSize } from '../typ
|
|
|
5
5
|
export type NavProps = {
|
|
6
6
|
/** `{ label, href, icon?, children?, disabled? }[]` */
|
|
7
7
|
navItems?: MenuItem[];
|
|
8
|
+
/** `navItems` のエイリアス。両方指定された場合は `navItems` が優先。 */
|
|
9
|
+
items?: MenuItem[];
|
|
8
10
|
/** Layout variant. @default 'horizontal' */
|
|
9
11
|
variant?: NavVariant;
|
|
10
12
|
/** Prepended to each item's href for active-state matching. */
|
|
@@ -21,12 +21,17 @@
|
|
|
21
21
|
// =========================================================================
|
|
22
22
|
export type StepNavProps = {
|
|
23
23
|
// 基本プロパティ
|
|
24
|
-
/**
|
|
25
|
-
|
|
24
|
+
/** ステップ配列(正式名称)。`{ label, value?, href?, description?, icon?, error?, disabled? }[]` */
|
|
25
|
+
stepItems?: StepItem[];
|
|
26
|
+
/** `stepItems` のエイリアス。両方指定された場合は `stepItems` が優先。 */
|
|
27
|
+
items?: StepItem[];
|
|
26
28
|
/** 表示中ステップの値(インページ方式)。`bind:value` 対応。`item.value` 省略時は配列 index の文字列('0','1',...)が暗黙の値になる。 */
|
|
27
29
|
value?: string;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
+
/**
|
|
31
|
+
* 到達済みの最遠ステップ(進捗軸)。未指定時は表示中ステップ位置。
|
|
32
|
+
* 数値なら 0 始まりのインデックス、文字列ならアイテムのユニークキー(`value`。省略時は配列 index の文字列)で指定する。URL方式でも `value` をキーに使う。
|
|
33
|
+
*/
|
|
34
|
+
progress?: number | string;
|
|
30
35
|
|
|
31
36
|
// URL 方式(href 使用時)
|
|
32
37
|
/** 各 href のアクティブ判定に前置するパス。 */
|
|
@@ -58,7 +63,7 @@
|
|
|
58
63
|
iconOpticalSize?: IconOpticalSize;
|
|
59
64
|
|
|
60
65
|
// 状態/動作
|
|
61
|
-
/**
|
|
66
|
+
/** インページ方式でステップのクリック遷移を許可。到達済み(progress 以下)のステップのみクリック可能。 @default false */
|
|
62
67
|
clickable?: boolean;
|
|
63
68
|
/** コンポーネント全体を無効化。 @default false */
|
|
64
69
|
disabled?: boolean;
|
|
@@ -80,7 +85,8 @@
|
|
|
80
85
|
|
|
81
86
|
let {
|
|
82
87
|
// 基本プロパティ
|
|
83
|
-
|
|
88
|
+
stepItems,
|
|
89
|
+
items: itemsAlias,
|
|
84
90
|
value = $bindable(''),
|
|
85
91
|
progress,
|
|
86
92
|
|
|
@@ -141,6 +147,9 @@
|
|
|
141
147
|
// =========================================================================
|
|
142
148
|
// Derived state
|
|
143
149
|
// =========================================================================
|
|
150
|
+
// stepItems(正式名)を優先し、items(エイリアス)へフォールバック
|
|
151
|
+
const items = $derived<StepItem[]>(stepItems ?? itemsAlias ?? []);
|
|
152
|
+
|
|
144
153
|
const isLinkMode = $derived(items.some((item) => item.href != null));
|
|
145
154
|
|
|
146
155
|
const activeIndex = $derived.by(() => {
|
|
@@ -162,7 +171,12 @@
|
|
|
162
171
|
return items.findIndex((item, index) => (item.value ?? String(index)) === value);
|
|
163
172
|
});
|
|
164
173
|
|
|
165
|
-
|
|
174
|
+
// progress を数値インデックスへ解決する。文字列ならアイテムのユニークキー(value)で一致判定。未指定なら表示中位置。
|
|
175
|
+
const progressIndex = $derived.by(() => {
|
|
176
|
+
if (progress == null) return activeIndex;
|
|
177
|
+
if (typeof progress === 'number') return progress;
|
|
178
|
+
return items.findIndex((item, index) => (item.value ?? String(index)) === progress);
|
|
179
|
+
});
|
|
166
180
|
|
|
167
181
|
const resolvedIconSize = $derived(
|
|
168
182
|
iconOpticalSize || (size === 'small' ? 16 : size === 'large' ? 24 : 20)
|
|
@@ -204,12 +218,10 @@
|
|
|
204
218
|
|
|
205
219
|
const isStepDisabled = (item: StepItem): boolean => disabled || item.disabled === true;
|
|
206
220
|
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
// インページ方式でクリック遷移が有効なステップか(ボタン描画・クリック処理の判定)
|
|
212
|
-
const isStepButton = (item: StepItem): boolean => isStepInteractive(item) && !isLinkMode;
|
|
221
|
+
// 対話的なステップか。到達済み(index <= progressIndex)のステップのみ対話可能。
|
|
222
|
+
// URL方式はリンク、インページ方式は clickable のときボタン。未到達の先のステップへは飛べない。無効なら常に非対話。
|
|
223
|
+
const isStepInteractive = (item: StepItem, index: number): boolean =>
|
|
224
|
+
!isStepDisabled(item) && index <= progressIndex && (isLinkMode || clickable);
|
|
213
225
|
|
|
214
226
|
const stepClasses = (item: StepItem, status: StepStatus, isViewing: boolean): string =>
|
|
215
227
|
[
|
|
@@ -235,8 +247,8 @@
|
|
|
235
247
|
return `${step}: ${state}`;
|
|
236
248
|
};
|
|
237
249
|
|
|
250
|
+
// クリック可能なインページボタンからのみ呼ばれる(未到達/無効/URL/非clickable は非対話要素で描画される)
|
|
238
251
|
const handleStepClick = (item: StepItem, index: number, event: MouseEvent) => {
|
|
239
|
-
if (!isStepButton(item)) return;
|
|
240
252
|
const nextValue = item.value ?? String(index);
|
|
241
253
|
value = nextValue;
|
|
242
254
|
onchange(nextValue);
|
|
@@ -338,7 +350,7 @@
|
|
|
338
350
|
{@const status = getStatus(index)}
|
|
339
351
|
{@const isViewing = index === activeIndex}
|
|
340
352
|
<li class="step-nav__item" role="listitem">
|
|
341
|
-
{#if !isStepInteractive(item)}
|
|
353
|
+
{#if !isStepInteractive(item, index)}
|
|
342
354
|
<!-- 非対話(URL/インページを問わず共通): 表示のみ。無効ステップは aria-disabled を付与 -->
|
|
343
355
|
<span
|
|
344
356
|
class={stepClasses(item, status, isViewing)}
|
|
@@ -3,12 +3,17 @@ import type { ComponentSize, StepNavOrientation } from '../types/propOptions';
|
|
|
3
3
|
import type { IconVariant, IconWeight, IconGrade, IconOpticalSize } from '../types/icon';
|
|
4
4
|
import type { MouseHandler, FocusHandler, KeyboardHandler, BivariantValueHandler } from '../types/callbackHandlers';
|
|
5
5
|
export type StepNavProps = {
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/** ステップ配列(正式名称)。`{ label, value?, href?, description?, icon?, error?, disabled? }[]` */
|
|
7
|
+
stepItems?: StepItem[];
|
|
8
|
+
/** `stepItems` のエイリアス。両方指定された場合は `stepItems` が優先。 */
|
|
9
|
+
items?: StepItem[];
|
|
8
10
|
/** 表示中ステップの値(インページ方式)。`bind:value` 対応。`item.value` 省略時は配列 index の文字列('0','1',...)が暗黙の値になる。 */
|
|
9
11
|
value?: string;
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
+
/**
|
|
13
|
+
* 到達済みの最遠ステップ(進捗軸)。未指定時は表示中ステップ位置。
|
|
14
|
+
* 数値なら 0 始まりのインデックス、文字列ならアイテムのユニークキー(`value`。省略時は配列 index の文字列)で指定する。URL方式でも `value` をキーに使う。
|
|
15
|
+
*/
|
|
16
|
+
progress?: number | string;
|
|
12
17
|
/** 各 href のアクティブ判定に前置するパス。 */
|
|
13
18
|
pathPrefix?: string;
|
|
14
19
|
/** アクティブ判定をカスタムする関数。 */
|
|
@@ -30,7 +35,7 @@ export type StepNavProps = {
|
|
|
30
35
|
iconWeight?: IconWeight;
|
|
31
36
|
iconGrade?: IconGrade;
|
|
32
37
|
iconOpticalSize?: IconOpticalSize;
|
|
33
|
-
/**
|
|
38
|
+
/** インページ方式でステップのクリック遷移を許可。到達済み(progress 以下)のステップのみクリック可能。 @default false */
|
|
34
39
|
clickable?: boolean;
|
|
35
40
|
/** コンポーネント全体を無効化。 @default false */
|
|
36
41
|
disabled?: boolean;
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
// 基本プロパティ
|
|
13
13
|
/** `{ label, href, icon?, disabled? }[]` */
|
|
14
14
|
tabItems?: MenuItem[];
|
|
15
|
+
/** `tabItems` のエイリアス。両方指定された場合は `tabItems` が優先。 */
|
|
16
|
+
items?: MenuItem[];
|
|
15
17
|
/** Prepended to each item's href for active-state matching. */
|
|
16
18
|
pathPrefix?: string;
|
|
17
19
|
/** Custom function to determine if an item is active. */
|
|
@@ -52,7 +54,8 @@
|
|
|
52
54
|
|
|
53
55
|
let {
|
|
54
56
|
// 基本プロパティ
|
|
55
|
-
tabItems
|
|
57
|
+
tabItems: tabItemsProp,
|
|
58
|
+
items: itemsAlias,
|
|
56
59
|
pathPrefix = '',
|
|
57
60
|
customPathMatcher,
|
|
58
61
|
currentPath,
|
|
@@ -80,6 +83,9 @@
|
|
|
80
83
|
ariaLabel = 'Tabs',
|
|
81
84
|
ariaLabelledby
|
|
82
85
|
}: TabProps = $props();
|
|
86
|
+
|
|
87
|
+
// tabItems(正式名)を優先し、items(エイリアス)へフォールバック
|
|
88
|
+
const tabItems = $derived<MenuItem[]>(tabItemsProp ?? itemsAlias ?? []);
|
|
83
89
|
</script>
|
|
84
90
|
|
|
85
91
|
<div class="tab" data-testid="tab">
|
|
@@ -3,6 +3,8 @@ import type { IconVariant, IconWeight, IconGrade, IconOpticalSize } from '../typ
|
|
|
3
3
|
export type TabProps = {
|
|
4
4
|
/** `{ label, href, icon?, disabled? }[]` */
|
|
5
5
|
tabItems?: MenuItem[];
|
|
6
|
+
/** `tabItems` のエイリアス。両方指定された場合は `tabItems` が優先。 */
|
|
7
|
+
items?: MenuItem[];
|
|
6
8
|
/** Prepended to each item's href for active-state matching. */
|
|
7
9
|
pathPrefix?: string;
|
|
8
10
|
/** Custom function to determine if an item is active. */
|