@14ch/svelte-ui 0.0.30 → 0.0.31
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.
|
@@ -275,7 +275,7 @@
|
|
|
275
275
|
{chevron}
|
|
276
276
|
{resolvedCurrentPath}
|
|
277
277
|
{customPathMatcher}
|
|
278
|
-
|
|
278
|
+
isChildrenVisible={(childrenVariant === 'bar' || childrenVariant === 'accordion') && expandedParent === item}
|
|
279
279
|
onChildrenToggle={handleToggle}
|
|
280
280
|
onChildrenClose={() => { expandedParent = null; }}
|
|
281
281
|
/>
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
isDisabled?: boolean;
|
|
47
47
|
/** When true, this item does not render its own children (prevents infinite recursion). */
|
|
48
48
|
isChild?: boolean;
|
|
49
|
-
/**
|
|
50
|
-
|
|
49
|
+
/** Whether this item's children are currently visible. */
|
|
50
|
+
isChildrenVisible?: boolean;
|
|
51
51
|
|
|
52
52
|
// イベントハンドラ
|
|
53
53
|
/** For bar/accordion mode: called when this parent is clicked. */
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
isSelected = false,
|
|
81
81
|
isDisabled = false,
|
|
82
82
|
isChild = false,
|
|
83
|
-
|
|
83
|
+
isChildrenVisible = $bindable(false),
|
|
84
84
|
|
|
85
85
|
// イベントハンドラ
|
|
86
86
|
onChildrenToggle,
|
|
@@ -121,36 +121,22 @@
|
|
|
121
121
|
// =========================================================================
|
|
122
122
|
// States
|
|
123
123
|
// =========================================================================
|
|
124
|
-
let isChildrenOpen = $state(false);
|
|
125
124
|
let anchorEl: HTMLElement | undefined = $state();
|
|
126
125
|
let popupMenuRef: PopupMenu | undefined = $state();
|
|
127
|
-
let isPopupOpen = $state(false);
|
|
128
126
|
let bottomSheetEl: HTMLElement | undefined = $state();
|
|
129
127
|
|
|
130
128
|
const focusFirstChild = (container: HTMLElement | undefined) =>
|
|
131
129
|
container?.querySelector<HTMLElement>('[data-nav-item-child]:not([tabindex="-1"])')?.focus();
|
|
132
130
|
|
|
133
131
|
$effect(() => {
|
|
134
|
-
if (
|
|
132
|
+
if (isChildrenVisible && childrenVariant === 'bottom-sheet') tick().then(() => focusFirstChild(bottomSheetEl));
|
|
135
133
|
});
|
|
136
134
|
|
|
137
135
|
const popupPosition = $derived<PopupPosition>(
|
|
138
136
|
variant === 'vertical' ? 'right-top' : variant === 'mobile' ? 'top-center' : 'bottom-left'
|
|
139
137
|
);
|
|
140
138
|
|
|
141
|
-
const
|
|
142
|
-
!hasChildren
|
|
143
|
-
? false
|
|
144
|
-
: childrenVariant === 'expanded'
|
|
145
|
-
? true
|
|
146
|
-
: childrenVariant === 'bottom-sheet'
|
|
147
|
-
? isChildrenOpen
|
|
148
|
-
: childrenVariant === 'popup'
|
|
149
|
-
? isPopupOpen
|
|
150
|
-
: isChildrenExpanded
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const showChevron = $derived(hasChildren && chevron && variant !== 'mobile');
|
|
139
|
+
const showChevron = $derived(hasChildren && chevron && variant !== 'mobile' && childrenVariant !== 'expanded');
|
|
154
140
|
|
|
155
141
|
// popup の方向に合わせたアイコン。それ以外は expand_more
|
|
156
142
|
const chevronIcon = $derived(
|
|
@@ -168,16 +154,16 @@
|
|
|
168
154
|
// Methods
|
|
169
155
|
// =========================================================================
|
|
170
156
|
const toggleOpen = () => {
|
|
171
|
-
|
|
157
|
+
isChildrenVisible = !isChildrenVisible;
|
|
172
158
|
};
|
|
173
159
|
|
|
174
160
|
const closeOpen = () => {
|
|
175
|
-
|
|
161
|
+
isChildrenVisible = false;
|
|
176
162
|
};
|
|
177
163
|
|
|
178
164
|
// popup の ArrowRight(vertical) / ArrowDown(horizontal) でサブメニューを開く
|
|
179
165
|
const handleTriggerKeyDown = (event: KeyboardEvent) => {
|
|
180
|
-
if (!hasChildren || childrenVariant !== 'popup' ||
|
|
166
|
+
if (!hasChildren || childrenVariant !== 'popup' || isChildrenVisible) return;
|
|
181
167
|
const openKey = variant === 'vertical' ? 'ArrowRight' : 'ArrowDown';
|
|
182
168
|
if (event.key !== openKey) return;
|
|
183
169
|
event.preventDefault();
|
|
@@ -227,7 +213,7 @@
|
|
|
227
213
|
popupMenuRef?.toggle();
|
|
228
214
|
} else if (childrenVariant === 'bottom-sheet') {
|
|
229
215
|
toggleOpen();
|
|
230
|
-
} else {
|
|
216
|
+
} else if (childrenVariant !== 'expanded') {
|
|
231
217
|
onChildrenToggle?.(item);
|
|
232
218
|
}
|
|
233
219
|
};
|
|
@@ -273,7 +259,7 @@
|
|
|
273
259
|
=================================================================== -->
|
|
274
260
|
<div
|
|
275
261
|
class="nav-item__group nav-item__group--{variant}"
|
|
276
|
-
class:nav-item__group--open={isChildrenVisible}
|
|
262
|
+
class:nav-item__group--open={childrenVariant === 'expanded' || isChildrenVisible}
|
|
277
263
|
>
|
|
278
264
|
<a
|
|
279
265
|
href={resolvedParentHref}
|
|
@@ -285,7 +271,7 @@
|
|
|
285
271
|
class:nav-item--style-tonal={isSelected && resolvedSelectedStyle === 'tonal'}
|
|
286
272
|
class:nav-item--style-underline={resolvedSelectedStyle === 'underline'}
|
|
287
273
|
aria-current={isSelected ? 'page' : undefined}
|
|
288
|
-
aria-expanded={childrenVariant === '
|
|
274
|
+
aria-expanded={childrenVariant === 'expanded' || isChildrenVisible}
|
|
289
275
|
tabindex={0}
|
|
290
276
|
data-nav-item
|
|
291
277
|
data-testid="nav-item"
|
|
@@ -325,7 +311,7 @@
|
|
|
325
311
|
{#if childrenVariant === 'popup'}
|
|
326
312
|
<PopupMenu
|
|
327
313
|
bind:this={popupMenuRef}
|
|
328
|
-
bind:isOpen={
|
|
314
|
+
bind:isOpen={isChildrenVisible}
|
|
329
315
|
anchorElement={anchorEl}
|
|
330
316
|
position={popupPosition}
|
|
331
317
|
menuItems={item.children!}
|
|
@@ -339,7 +325,7 @@
|
|
|
339
325
|
{/if}
|
|
340
326
|
|
|
341
327
|
<!-- accordion / expanded サブメニュー -->
|
|
342
|
-
{#if
|
|
328
|
+
{#if childrenVariant === 'expanded' || (childrenVariant === 'accordion' && isChildrenVisible)}
|
|
343
329
|
<div class="nav-item__children" role="presentation" transition:slide={{ duration: 200 }}>
|
|
344
330
|
{#each item.children! as child}
|
|
345
331
|
<NavItem
|
|
@@ -363,7 +349,7 @@
|
|
|
363
349
|
{/if}
|
|
364
350
|
|
|
365
351
|
<!-- bottom-sheet オーバーレイ -->
|
|
366
|
-
{#if childrenVariant === 'bottom-sheet' &&
|
|
352
|
+
{#if childrenVariant === 'bottom-sheet' && isChildrenVisible}
|
|
367
353
|
<div
|
|
368
354
|
class="nav-item__bottom-sheet-backdrop"
|
|
369
355
|
role="presentation"
|
|
@@ -25,13 +25,13 @@ export type NavItemProps = {
|
|
|
25
25
|
isDisabled?: boolean;
|
|
26
26
|
/** When true, this item does not render its own children (prevents infinite recursion). */
|
|
27
27
|
isChild?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/** Whether this item's children are currently visible. */
|
|
29
|
+
isChildrenVisible?: boolean;
|
|
30
30
|
/** For bar/accordion mode: called when this parent is clicked. */
|
|
31
31
|
onChildrenToggle?: (item: MenuItem) => void;
|
|
32
32
|
/** Called when a leaf item (no children) is clicked — used to close any open sub-menu. */
|
|
33
33
|
onChildrenClose?: () => void;
|
|
34
34
|
};
|
|
35
|
-
declare const NavItem: import("svelte").Component<NavItemProps, {}, "">;
|
|
35
|
+
declare const NavItem: import("svelte").Component<NavItemProps, {}, "isChildrenVisible">;
|
|
36
36
|
type NavItem = ReturnType<typeof NavItem>;
|
|
37
37
|
export default NavItem;
|