@14ch/svelte-ui 0.0.32 → 0.0.33

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.
@@ -395,6 +395,8 @@
395
395
  --svelte-ui-nav-vertical-item-gap: 8px;
396
396
  /* Nav: horizontal */
397
397
  --svelte-ui-nav-horizontal-item-gap: 8px;
398
+ /* Nav: children spacing (parent item → children list) */
399
+ --svelte-ui-nav-children-offset: 8px;
398
400
  /* Nav: sub-menu */
399
401
  --svelte-ui-nav-sub-popup-min-width: 160px;
400
402
  --svelte-ui-nav-sub-popup-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
@@ -78,7 +78,11 @@
78
78
  // スタイル/レイアウト
79
79
  selectedVariant,
80
80
  gap,
81
- childrenVariant = variant === 'mobile' ? 'bottom-sheet' : variant === 'vertical' ? 'accordion' : 'bar',
81
+ childrenVariant = variant === 'mobile'
82
+ ? 'bottom-sheet'
83
+ : variant === 'vertical'
84
+ ? 'accordion'
85
+ : 'bar',
82
86
  chevron,
83
87
  customContainerStyle,
84
88
  customItemStyle,
@@ -111,15 +115,19 @@
111
115
  });
112
116
  });
113
117
 
114
- // accordion モード: アクティブな子を持つ親を自動展開
118
+ // accordion / bar モード: アクティブな親を自動展開
115
119
  $effect(() => {
116
- if (childrenVariant !== 'accordion' || !resolvedCurrentPath) return;
117
- const activeParent = navItems.find((item) =>
118
- item.children?.some(
119
- (child) =>
120
- child.href &&
121
- matchPath(resolvedCurrentPath, child.href, child, pathPrefix, customPathMatcher)
122
- )
120
+ if ((childrenVariant !== 'accordion' && childrenVariant !== 'bar') || !resolvedCurrentPath)
121
+ return;
122
+ const selected = navItems[selectedIndex];
123
+ const activeParent = navItems.find(
124
+ (item) =>
125
+ (item === selected && !!item.children?.length) ||
126
+ item.children?.some(
127
+ (child) =>
128
+ child.href &&
129
+ matchPath(resolvedCurrentPath, child.href, child, pathPrefix, customPathMatcher)
130
+ )
123
131
  );
124
132
  if (activeParent) expandedParent = activeParent;
125
133
  });
@@ -140,7 +148,7 @@
140
148
  const selector = includeChildren ? '[data-nav-item], [data-nav-item-child]' : '[data-nav-item]';
141
149
  const navItemEls = Array.from(
142
150
  (event.currentTarget as HTMLElement).querySelectorAll<HTMLElement>(selector)
143
- ).filter(el => el.tabIndex !== -1);
151
+ ).filter((el) => el.tabIndex !== -1);
144
152
 
145
153
  if (navItemEls.length === 0) return;
146
154
 
@@ -239,13 +247,21 @@
239
247
  const selectedIndex = $derived.by(() => {
240
248
  for (let i = 0; i < navItems.length; i++) {
241
249
  const item = navItems[i];
242
- if (item.href && matchPath(resolvedCurrentPath, item.href, item, pathPrefix, customPathMatcher)) {
250
+ if (
251
+ item.href &&
252
+ matchPath(resolvedCurrentPath, item.href, item, pathPrefix, customPathMatcher)
253
+ ) {
243
254
  return i;
244
255
  }
245
256
  // bar モード: 子が選択されていれば親も選択とみなす
246
- if (childrenVariant === 'bar' && item.children?.some(
247
- (child) => child.href && matchPath(resolvedCurrentPath, child.href, child, pathPrefix, customPathMatcher)
248
- )) {
257
+ if (
258
+ childrenVariant === 'bar' &&
259
+ item.children?.some(
260
+ (child) =>
261
+ child.href &&
262
+ matchPath(resolvedCurrentPath, child.href, child, pathPrefix, customPathMatcher)
263
+ )
264
+ ) {
249
265
  return i;
250
266
  }
251
267
  }
@@ -257,7 +273,8 @@
257
273
  );
258
274
 
259
275
  const isChildSelected = (child: MenuItem) =>
260
- !!child.href && matchPath(resolvedCurrentPath, child.href, child, pathPrefix, customPathMatcher);
276
+ !!child.href &&
277
+ matchPath(resolvedCurrentPath, child.href, child, pathPrefix, customPathMatcher);
261
278
  </script>
262
279
 
263
280
  <nav
@@ -271,37 +288,47 @@
271
288
  bind:this={navEl}
272
289
  >
273
290
  <div style="display: contents" role="presentation" onkeydown={handleKeyDown}>
274
- {#each navItems as item, index}
275
- <NavItem
276
- {item}
277
- {variant}
278
- {pathPrefix}
279
- isSelected={index === selectedIndex}
280
- isDisabled={item.disabled ?? false}
281
- {iconFilled}
282
- {iconWeight}
283
- {iconGrade}
284
- {iconOpticalSize}
285
- {iconVariant}
286
- {selectedVariant}
287
- {childrenVariant}
288
- {chevron}
289
- customStyle={customItemStyle}
290
- customChildrenStyle={customChildrenItemStyle}
291
- {customChildrenContainerStyle}
292
- {resolvedCurrentPath}
293
- {customPathMatcher}
294
- isChildrenVisible={(childrenVariant === 'bar' || childrenVariant === 'accordion') && expandedParent === item}
295
- onChildrenToggle={handleToggle}
296
- onChildrenClose={() => { expandedParent = null; }}
297
- />
298
- {/each}
291
+ {#each navItems as item, index}
292
+ <NavItem
293
+ {item}
294
+ {variant}
295
+ {pathPrefix}
296
+ isSelected={index === selectedIndex}
297
+ isDisabled={item.disabled ?? false}
298
+ {iconFilled}
299
+ {iconWeight}
300
+ {iconGrade}
301
+ {iconOpticalSize}
302
+ {iconVariant}
303
+ {selectedVariant}
304
+ {childrenVariant}
305
+ {chevron}
306
+ customStyle={customItemStyle}
307
+ customChildrenStyle={customChildrenItemStyle}
308
+ {customChildrenContainerStyle}
309
+ {resolvedCurrentPath}
310
+ {customPathMatcher}
311
+ isChildrenVisible={(childrenVariant === 'bar' || childrenVariant === 'accordion') &&
312
+ expandedParent === item}
313
+ onChildrenToggle={handleToggle}
314
+ onChildrenClose={() => {
315
+ expandedParent = null;
316
+ }}
317
+ />
318
+ {/each}
299
319
  </div>
300
320
  </nav>
301
321
 
302
322
  <!-- bar モード: 選択中の親の子アイテムを横バーとして表示 -->
303
323
  {#if showSubBar && expandedParent?.children}
304
- <div class="nav__children-bar" role="menu" tabindex="-1" style={customChildrenContainerStyle} onkeydown={handleSubBarKeyDown} bind:this={subBarEl}>
324
+ <div
325
+ class="nav__children-bar"
326
+ role="menu"
327
+ tabindex="-1"
328
+ style={customChildrenContainerStyle}
329
+ onkeydown={handleSubBarKeyDown}
330
+ bind:this={subBarEl}
331
+ >
305
332
  {#each expandedParent.children as child}
306
333
  <NavItem
307
334
  item={child}
@@ -362,4 +389,5 @@
362
389
  flex-direction: row;
363
390
  gap: var(--internal-nav-gap, var(--svelte-ui-nav-horizontal-item-gap));
364
391
  align-items: center;
392
+ padding-top: var(--svelte-ui-nav-children-offset);
365
393
  }</style>
@@ -623,7 +623,7 @@
623
623
  .nav-item__children {
624
624
  display: flex;
625
625
  flex-direction: column;
626
- padding-top: var(--internal-nav-gap, var(--svelte-ui-nav-vertical-item-gap));
626
+ padding-top: var(--svelte-ui-nav-children-offset);
627
627
  gap: var(--internal-nav-gap, var(--svelte-ui-nav-vertical-item-gap));
628
628
  overflow: hidden;
629
629
  }
@@ -36,6 +36,14 @@
36
36
  selectedTextColor?: string;
37
37
  /** Custom CSS color for the active tab indicator bar. */
38
38
  selectedBarColor?: string;
39
+ /** Inline style applied to the tab container element. */
40
+ customContainerStyle?: string;
41
+ /** Inline style applied to each tab item element. */
42
+ customItemStyle?: string;
43
+ /** Inline style applied to the children container. */
44
+ customChildrenContainerStyle?: string;
45
+ /** Inline style applied to each child item element. */
46
+ customChildrenItemStyle?: string;
39
47
 
40
48
  // ARIA/アクセシビリティ
41
49
  ariaLabel?: string;
@@ -63,6 +71,10 @@
63
71
  textColor,
64
72
  selectedTextColor,
65
73
  selectedBarColor,
74
+ customContainerStyle,
75
+ customItemStyle,
76
+ customChildrenContainerStyle,
77
+ customChildrenItemStyle,
66
78
 
67
79
  // ARIA/アクセシビリティ
68
80
  ariaLabel = 'Tabs',
@@ -90,6 +102,10 @@
90
102
  {iconGrade}
91
103
  {iconOpticalSize}
92
104
  {iconVariant}
105
+ {customContainerStyle}
106
+ {customItemStyle}
107
+ {customChildrenContainerStyle}
108
+ {customChildrenItemStyle}
93
109
  {ariaLabel}
94
110
  {ariaLabelledby}
95
111
  />
@@ -21,6 +21,14 @@ export type TabProps = {
21
21
  selectedTextColor?: string;
22
22
  /** Custom CSS color for the active tab indicator bar. */
23
23
  selectedBarColor?: string;
24
+ /** Inline style applied to the tab container element. */
25
+ customContainerStyle?: string;
26
+ /** Inline style applied to each tab item element. */
27
+ customItemStyle?: string;
28
+ /** Inline style applied to the children container. */
29
+ customChildrenContainerStyle?: string;
30
+ /** Inline style applied to each child item element. */
31
+ customChildrenItemStyle?: string;
24
32
  ariaLabel?: string;
25
33
  ariaLabelledby?: string;
26
34
  };
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.32",
5
+ "version": "0.0.33",
6
6
  "type": "module",
7
7
  "keywords": [
8
8
  "svelte",