tera-system-ui 0.1.71 → 0.1.73

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.
@@ -1,20 +1,55 @@
1
1
  import { type VariantProps } from "tailwind-variants";
2
2
  import type { Snippet } from "svelte";
3
3
  import type { HTMLAttributes } from "svelte/elements";
4
+ /**
5
+ * App-shell sidebar navigation. Use `SideNavigationLayout` as the outermost wrapper of a page: it renders the fixed sidebar plus a content region for your `Header`, the page body, and optional bottom controls. `SideNavigation` is the bar itself and is normally driven through the layout. Wrap the app in `TeraUiContext` so `sideNavHref` (active route) and `language` are supplied globally, or pass them as props directly.
6
+ *
7
+ * The `items` prop is a single flat array that may MIX two shapes in any order: (1) a link item `{ href, title, icon?, exactHref? }` — a single navigable entry, where `exactHref` (falling back to `href`) is compared to the active route to apply the `selected` highlight; and (2) a group `{ id, title, items, defaultExpanded? }` — a collapsible section whose `items` are link items. A group renders a compact, fixed-height header (title + chevron, no icon) that expands/collapses its children; in the compact icon-only rail the header collapses to a thin divider so groups stay separated without large gaps, while keeping a stable height so items don't shift. Group children render with their own icons.
8
+ *
9
+ * Group expand/collapse state is PERSISTED to localStorage under the key `side-nav-group-state` (a JSON map of `{ [groupId]: boolean }`), keyed by the group's `id` — so `id` must be stable and unique. `defaultExpanded` only sets the initial state the first time a group `id` is seen (before any saved value exists). A group that contains the active route is always force-expanded on mount, regardless of saved state.
10
+ *
11
+ * If `items` is omitted, a built-in default navigation (calculator / converter / docs) is rendered. The sidebar's own expand vs. compact (icon-only) state is toggled by calling the exported `toggleSideNavigation()` (e.g. from a hamburger button) and is persisted at the xl breakpoint under localStorage key `side-nav-xl-state`; on smaller widths the bar is icon-only and temporarily expands on hover.
12
+ *
13
+ * Example: `<SideNavigationLayout items={[{ href: '/home', title: 'Home', icon: IconHome }, { id: 'tools', title: 'Tools', defaultExpanded: true, items: [{ href: '/calc', exactHref: '/calc', title: 'Calculator', icon: IconCalc }] }]}> <Header onHamburgerClick={toggleSideNavigation}>...</Header> <div>Page content</div> </SideNavigationLayout>`
14
+ */
4
15
  export declare const styles: import("tailwind-variants").TVReturnType<{}, undefined, "", {}, undefined, import("tailwind-variants").TVReturnType<{}, undefined, "", unknown, unknown, undefined>>;
5
16
  type SideNavigationVariants = VariantProps<typeof styles>;
17
+ /** A single navigable link in the sidebar. */
6
18
  export type SideNavigationItem = {
19
+ /** Destination URL for the link. */
7
20
  href: string;
21
+ /** Route used for active-state matching; falls back to `href` when omitted. */
8
22
  exactHref?: string;
23
+ /** Icon component (e.g. a Tabler icon) rendered before the title. */
9
24
  icon?: any;
25
+ /** Visible label. */
10
26
  title: string;
11
27
  };
28
+ /** A collapsible section grouping several link items under a header. */
29
+ export type SideNavigationGroup = {
30
+ /** Stable, unique key — used to persist this group's expanded state in localStorage. */
31
+ id: string;
32
+ /** Header label (the group header shows title + chevron only, no icon). */
33
+ title: string;
34
+ /** Initial expanded state the first time the group is seen (before any saved value). */
35
+ defaultExpanded?: boolean;
36
+ /** Child links shown when the group is expanded. */
37
+ items: SideNavigationItem[];
38
+ };
39
+ /** An entry in the `items` array: either a flat link item or a collapsible group. */
40
+ export type SideNavigationEntry = SideNavigationItem | SideNavigationGroup;
41
+ /** Type guard: true when an entry is a {@link SideNavigationGroup} (has an `items` array). */
42
+ export declare function isSideNavigationGroup(entry: SideNavigationEntry): entry is SideNavigationGroup;
12
43
  export interface SideNavigationProps extends HTMLAttributes<HTMLElement>, SideNavigationVariants {
13
44
  children?: Snippet;
14
45
  class?: string;
46
+ /** Current active route, used to highlight the matching item. Usually supplied via TeraUiContext. */
15
47
  sideNavHref?: string;
48
+ /** Active language code; localizes the built-in default nav links. Usually supplied via TeraUiContext. */
16
49
  language?: string;
17
- items?: SideNavigationItem[];
50
+ /** Navigation entries: a flat array mixing link items ({ href, title, icon?, exactHref? }) and collapsible groups ({ id, title, items, defaultExpanded? }). Omit to render the built-in default nav. */
51
+ items?: SideNavigationEntry[];
52
+ /** Snippet rendered pinned at the bottom of the sidebar (e.g. a theme toggle). */
18
53
  bottomChildren?: Snippet;
19
54
  ref?: HTMLElement | null;
20
55
  }
@@ -24,6 +59,8 @@ export declare const SCREEN_BREAK_POINTS: {
24
59
  lg: number;
25
60
  xl: number;
26
61
  };
62
+ export declare function loadGroupStates(): Record<string, boolean>;
63
+ export declare function saveGroupStates(states: Record<string, boolean>): void;
27
64
  export declare function saveXlSideNavState(state: string | undefined): void;
28
65
  export declare function loadXlSideNavState(): string | undefined;
29
66
  export declare function restoreSideNavStateForXl(): void;
@@ -1,10 +1,25 @@
1
1
  import { tv } from "tailwind-variants";
2
+ /**
3
+ * App-shell sidebar navigation. Use `SideNavigationLayout` as the outermost wrapper of a page: it renders the fixed sidebar plus a content region for your `Header`, the page body, and optional bottom controls. `SideNavigation` is the bar itself and is normally driven through the layout. Wrap the app in `TeraUiContext` so `sideNavHref` (active route) and `language` are supplied globally, or pass them as props directly.
4
+ *
5
+ * The `items` prop is a single flat array that may MIX two shapes in any order: (1) a link item `{ href, title, icon?, exactHref? }` — a single navigable entry, where `exactHref` (falling back to `href`) is compared to the active route to apply the `selected` highlight; and (2) a group `{ id, title, items, defaultExpanded? }` — a collapsible section whose `items` are link items. A group renders a compact, fixed-height header (title + chevron, no icon) that expands/collapses its children; in the compact icon-only rail the header collapses to a thin divider so groups stay separated without large gaps, while keeping a stable height so items don't shift. Group children render with their own icons.
6
+ *
7
+ * Group expand/collapse state is PERSISTED to localStorage under the key `side-nav-group-state` (a JSON map of `{ [groupId]: boolean }`), keyed by the group's `id` — so `id` must be stable and unique. `defaultExpanded` only sets the initial state the first time a group `id` is seen (before any saved value exists). A group that contains the active route is always force-expanded on mount, regardless of saved state.
8
+ *
9
+ * If `items` is omitted, a built-in default navigation (calculator / converter / docs) is rendered. The sidebar's own expand vs. compact (icon-only) state is toggled by calling the exported `toggleSideNavigation()` (e.g. from a hamburger button) and is persisted at the xl breakpoint under localStorage key `side-nav-xl-state`; on smaller widths the bar is icon-only and temporarily expands on hover.
10
+ *
11
+ * Example: `<SideNavigationLayout items={[{ href: '/home', title: 'Home', icon: IconHome }, { id: 'tools', title: 'Tools', defaultExpanded: true, items: [{ href: '/calc', exactHref: '/calc', title: 'Calculator', icon: IconCalc }] }]}> <Header onHamburgerClick={toggleSideNavigation}>...</Header> <div>Page content</div> </SideNavigationLayout>`
12
+ */
2
13
  export const styles = tv({
3
14
  base: '',
4
15
  variants: {},
5
16
  compoundVariants: [],
6
17
  defaultVariants: {},
7
18
  });
19
+ /** Type guard: true when an entry is a {@link SideNavigationGroup} (has an `items` array). */
20
+ export function isSideNavigationGroup(entry) {
21
+ return Array.isArray(entry.items);
22
+ }
8
23
  export const SCREEN_BREAK_POINTS = {
9
24
  sm: 640,
10
25
  md: 768,
@@ -12,6 +27,19 @@ export const SCREEN_BREAK_POINTS = {
12
27
  xl: 1280,
13
28
  };
14
29
  const SIDE_NAV_XL_STATE_KEY = 'side-nav-xl-state';
30
+ const SIDE_NAV_GROUP_STATE_KEY = 'side-nav-group-state';
31
+ export function loadGroupStates() {
32
+ try {
33
+ const raw = localStorage.getItem(SIDE_NAV_GROUP_STATE_KEY);
34
+ return raw ? JSON.parse(raw) : {};
35
+ }
36
+ catch {
37
+ return {};
38
+ }
39
+ }
40
+ export function saveGroupStates(states) {
41
+ localStorage.setItem(SIDE_NAV_GROUP_STATE_KEY, JSON.stringify(states));
42
+ }
15
43
  export function saveXlSideNavState(state) {
16
44
  if (state === undefined) {
17
45
  localStorage.removeItem(SIDE_NAV_XL_STATE_KEY);
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">import { onMount } from "svelte";
2
- import { mainLayout, SCREEN_BREAK_POINTS, setSideNavState, restoreSideNavStateForXl, toggleSideNavigation } from "./SideNavigation";
2
+ import { mainLayout, SCREEN_BREAK_POINTS, setSideNavState, restoreSideNavStateForXl, isSideNavigationGroup, loadGroupStates, saveGroupStates, toggleSideNavigation } from "./SideNavigation";
3
3
  import { clickOutside } from "../../actions/clickOutside";
4
4
  import { Button } from "../button";
5
5
  import { IconCoinConvert, IconHamburger } from "../icons";
6
6
  import { BrandLogo } from "../brand-logo";
7
7
  import SideNavItem from "./SideNavigationItem.svelte";
8
+ import SideNavGroup from "./SideNavigationGroup.svelte";
8
9
  import IconBook from "../icons/IconBook.svelte";
9
10
  import IconTransform from "../icons/IconTransform.svelte";
10
11
  import IconCalculator from "../icons/IconCalculator.svelte";
@@ -66,13 +67,32 @@ const NAV_ITEM = $derived(items ?? [
66
67
  title: m.text_calces_documentation(),
67
68
  },
68
69
  ]);
69
- let selectedIndex = (() => {
70
- return NAV_ITEM.findIndex((item) => {
71
- return (item.exactHref ?? item.href) === resolvedSideNavHref;
72
- });
73
- })();
70
+ function isSelected(item) {
71
+ return (item.exactHref ?? item.href) === resolvedSideNavHref;
72
+ }
73
+ let groupStates = $state({});
74
+ function toggleGroup(id) {
75
+ groupStates[id] = !groupStates[id];
76
+ saveGroupStates(groupStates);
77
+ }
74
78
  onMount(() => {
75
79
  restoreSideNavStateForXl();
80
+ const saved = loadGroupStates();
81
+ for (const entry of NAV_ITEM) {
82
+ if (!isSideNavigationGroup(entry))
83
+ continue;
84
+ const hasActiveChild = entry.items.some(isSelected);
85
+ if (entry.id in saved) {
86
+ groupStates[entry.id] = saved[entry.id];
87
+ }
88
+ else {
89
+ groupStates[entry.id] = entry.defaultExpanded ?? false;
90
+ }
91
+ // Force-expand the group containing the active route.
92
+ if (hasActiveChild) {
93
+ groupStates[entry.id] = true;
94
+ }
95
+ }
76
96
  });
77
97
  </script>
78
98
 
@@ -99,13 +119,24 @@ onMount(() => {
99
119
  handleHover(false)
100
120
  }}
101
121
  >
102
- {#each NAV_ITEM as item, index (item.href)}
103
- <SideNavItem href={item.href} class={selectedIndex === index ? 'selected' : ''}>
104
- {#snippet icon()}
105
- <item.icon/>
106
- {/snippet}
107
- {item.title}
108
- </SideNavItem>
122
+ {#each NAV_ITEM as entry (isSideNavigationGroup(entry) ? entry.id : entry.href)}
123
+ {#if isSideNavigationGroup(entry)}
124
+ <SideNavGroup
125
+ group={entry}
126
+ expanded={groupStates[entry.id]}
127
+ onToggle={() => toggleGroup(entry.id)}
128
+ {isSelected}
129
+ />
130
+ {:else}
131
+ <SideNavItem href={entry.href} class={isSelected(entry) ? 'selected' : ''}>
132
+ {#snippet icon()}
133
+ {#if entry.icon}
134
+ <entry.icon/>
135
+ {/if}
136
+ {/snippet}
137
+ {entry.title}
138
+ </SideNavItem>
139
+ {/if}
109
140
  {/each}
110
141
  </ul>
111
142
  {@render bottomChildren?.()}
@@ -0,0 +1,40 @@
1
+ <script lang="ts">import { slide } from "svelte/transition";
2
+ import { IconChevronDown } from "../icons";
3
+ import SideNavItem from "./SideNavigationItem.svelte";
4
+ let { group, expanded = false, onToggle, isSelected, } = $props();
5
+ </script>
6
+
7
+ <li class="side-nav_group">
8
+ <button
9
+ type="button"
10
+ class="side-nav_item side-nav_group-header"
11
+ aria-expanded={expanded}
12
+ onclick={onToggle}
13
+ >
14
+ <span class="side-nav_group-divider" aria-hidden="true"></span>
15
+ <div class="sm-hidden z-10 truncate side-nav_group-title">
16
+ {group.title}
17
+ </div>
18
+ <div class="sm-hidden z-10 side-nav_group-chevron" data-expanded={expanded}>
19
+ <IconChevronDown/>
20
+ </div>
21
+ </button>
22
+
23
+ {#if expanded}
24
+ <ul class="side-nav_group-items" transition:slide={{duration: 200}}>
25
+ {#each group.items as item (item.href)}
26
+ <SideNavItem
27
+ href={item.href}
28
+ class={`side-nav_group-item ${isSelected(item) ? 'selected' : ''}`}
29
+ >
30
+ {#snippet icon()}
31
+ {#if item.icon}
32
+ <item.icon/>
33
+ {/if}
34
+ {/snippet}
35
+ {item.title}
36
+ </SideNavItem>
37
+ {/each}
38
+ </ul>
39
+ {/if}
40
+ </li>
@@ -0,0 +1,10 @@
1
+ import type { SideNavigationGroup, SideNavigationItem } from "./SideNavigation";
2
+ type $$ComponentProps = {
3
+ group: SideNavigationGroup;
4
+ expanded?: boolean;
5
+ onToggle: () => void;
6
+ isSelected: (item: SideNavigationItem) => boolean;
7
+ };
8
+ declare const SideNavigationGroup: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type SideNavigationGroup = ReturnType<typeof SideNavigationGroup>;
10
+ export default SideNavigationGroup;
@@ -1,4 +1,5 @@
1
1
  export { default as SideNavigation } from './SideNavigation.svelte';
2
2
  export { default as SideNavigationLayout } from './SideNavigationLayout.svelte';
3
- export { toggleSideNavigation } from './SideNavigation';
4
- export type { SideNavigationItem, SideNavigationProps } from "./SideNavigation";
3
+ export { default as SideNavigationGroup } from './SideNavigationGroup.svelte';
4
+ export { toggleSideNavigation, isSideNavigationGroup } from './SideNavigation.js';
5
+ export type { SideNavigationItem, SideNavigationGroup as SideNavigationGroupItem, SideNavigationEntry, SideNavigationProps } from "./SideNavigation.js";
@@ -1,3 +1,4 @@
1
1
  export { default as SideNavigation } from './SideNavigation.svelte';
2
2
  export { default as SideNavigationLayout } from './SideNavigationLayout.svelte';
3
- export { toggleSideNavigation } from './SideNavigation';
3
+ export { default as SideNavigationGroup } from './SideNavigationGroup.svelte';
4
+ export { toggleSideNavigation, isSideNavigationGroup } from './SideNavigation.js';
@@ -163,3 +163,64 @@
163
163
  background-color: var(--color-surface-hover);
164
164
  }
165
165
  }
166
+
167
+ .side-nav_group {
168
+ .side-nav_group-header {
169
+ position: relative;
170
+ display: flex;
171
+ gap: 0.5rem;
172
+ align-items: center;
173
+ width: 100%;
174
+ /* Fixed compact height: keeps child items from shifting up/down when the
175
+ panel collapses/expands, and tightens the gap between groups in the rail. */
176
+ height: 2rem;
177
+ white-space: nowrap;
178
+ padding-block: 0;
179
+ padding-inline: --spacing(3);
180
+ font-weight: var(--font-weight-normal);
181
+ color: var(--color-text-secondary);
182
+ cursor: pointer;
183
+ background: transparent;
184
+ border: none;
185
+ text-align: start;
186
+
187
+ &:hover {
188
+ background-color: var(--color-surface-hover);
189
+ }
190
+ }
191
+
192
+ /* In the compact (icon-only) panel the title + chevron fade out and this line
193
+ fades in — so a group header reads as a thin divider between item clusters.
194
+ It is the exact inverse of `.sm-hidden`, sharing the same container-query
195
+ threshold so the two always cross-fade. */
196
+ .side-nav_group-divider {
197
+ position: absolute;
198
+ left: --spacing(2);
199
+ right: --spacing(2);
200
+ top: 50%;
201
+ transform: translateY(-50%);
202
+ height: 1px;
203
+ background: var(--color-border-default);
204
+ opacity: 1;
205
+ transition: opacity var(--sidebar-transition-duration);
206
+ pointer-events: none;
207
+
208
+ @container (min-width: 3rem) {
209
+ opacity: 0;
210
+ }
211
+ }
212
+
213
+ .side-nav_group-title {
214
+ flex: 1;
215
+ }
216
+
217
+ .side-nav_group-chevron {
218
+ display: flex;
219
+ align-items: center;
220
+ transition: rotate var(--sidebar-transition-duration) var(--ease-ui);
221
+
222
+ &[data-expanded="true"] {
223
+ rotate: 180deg;
224
+ }
225
+ }
226
+ }
package/dist/index.d.ts CHANGED
@@ -23,7 +23,7 @@ export { FeatureCard, StatBlock, PricingCard, TestimonialCard } from './componen
23
23
  export { Popover } from './components/popover/index.js';
24
24
  export { PopoverResponsive } from './components/popover-responsive/index.js';
25
25
  export { Select } from './components/select/index.js';
26
- export { SideNavigation, SideNavigationLayout, toggleSideNavigation } from './components/side-navigation/index.js';
26
+ export { SideNavigation, SideNavigationLayout, SideNavigationGroup } from './components/side-navigation/index.js';
27
27
  export { Skeleton } from './components/skeleton/index.js';
28
28
  export { Slider } from './components/slider/index.js';
29
29
  export { Spinner } from './components/spinner/index.js';
@@ -55,7 +55,7 @@ export type { LightDarkToggleProps } from './components/light-dark-toggle/index.
55
55
  export type { PopoverProps } from './components/popover/index.js';
56
56
  export type { PopoverResponsiveProps } from './components/popover-responsive/index.js';
57
57
  export type { SelectProps, SelectOption } from './components/select/index.js';
58
- export type { SideNavigationItem, SideNavigationProps } from './components/side-navigation/index.js';
58
+ export type { SideNavigationItem, SideNavigationGroupItem, SideNavigationEntry, SideNavigationProps } from './components/side-navigation/index.js';
59
59
  export type { SliderProps } from './components/slider/index.js';
60
60
  export type { StarRatingProps } from './components/star-rating/index.js';
61
61
  export type { SwitchProps } from './components/switch/index.js';
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ export { FeatureCard, StatBlock, PricingCard, TestimonialCard } from './componen
23
23
  export { Popover } from './components/popover/index.js';
24
24
  export { PopoverResponsive } from './components/popover-responsive/index.js';
25
25
  export { Select } from './components/select/index.js';
26
- export { SideNavigation, SideNavigationLayout, toggleSideNavigation } from './components/side-navigation/index.js';
26
+ export { SideNavigation, SideNavigationLayout, SideNavigationGroup } from './components/side-navigation/index.js';
27
27
  export { Skeleton } from './components/skeleton/index.js';
28
28
  export { Slider } from './components/slider/index.js';
29
29
  export { Spinner } from './components/spinner/index.js';
@@ -1,10 +1,12 @@
1
1
  # SideNavigation
2
2
 
3
- Sidebar navigation. Parts: SideNavigation, SideNavigationItem, SideNavigationLayout.
3
+ App-shell sidebar navigation with collapsible item groups (state persisted to localStorage). Parts: SideNavigationLayout (wrapper), SideNavigation (the bar), SideNavigationGroup, SideNavigationItem. Pass an `items` array mixing link items and groups.
4
+
5
+ App-shell sidebar navigation. Use `SideNavigationLayout` as the outermost wrapper of a page: it renders the fixed sidebar plus a content region for your `Header`, the page body, and optional bottom controls. `SideNavigation` is the bar itself and is normally driven through the layout. Wrap the app in `TeraUiContext` so `sideNavHref` (active route) and `language` are supplied globally, or pass them as props directly. The `items` prop is a single flat array that may MIX two shapes in any order: (1) a link item `{ href, title, icon?, exactHref? }` — a single navigable entry, where `exactHref` (falling back to `href`) is compared to the active route to apply the `selected` highlight; and (2) a group `{ id, title, items, defaultExpanded? }` — a collapsible section whose `items` are link items. A group renders a compact, fixed-height header (title + chevron, no icon) that expands/collapses its children; in the compact icon-only rail the header collapses to a thin divider so groups stay separated without large gaps, while keeping a stable height so items don't shift. Group children render with their own icons. Group expand/collapse state is PERSISTED to localStorage under the key `side-nav-group-state` (a JSON map of `{ [groupId]: boolean }`), keyed by the group's `id` — so `id` must be stable and unique. `defaultExpanded` only sets the initial state the first time a group `id` is seen (before any saved value exists). A group that contains the active route is always force-expanded on mount, regardless of saved state. If `items` is omitted, a built-in default navigation (calculator / converter / docs) is rendered. The sidebar's own expand vs. compact (icon-only) state is toggled by calling the exported `toggleSideNavigation()` (e.g. from a hamburger button) and is persisted at the xl breakpoint under localStorage key `side-nav-xl-state`; on smaller widths the bar is icon-only and temporarily expands on hover. Example: `<SideNavigationLayout items={[{ href: '/home', title: 'Home', icon: IconHome }, { id: 'tools', title: 'Tools', defaultExpanded: true, items: [{ href: '/calc', exactHref: '/calc', title: 'Calculator', icon: IconCalc }] }]}> <Header onHamburgerClick={toggleSideNavigation}>...</Header> <div>Page content</div> </SideNavigationLayout>`
4
6
 
5
7
  ## Import
6
8
 
7
- import { SideNavigation } from 'tera-system-ui';
9
+ import { SideNavigation, SideNavigationGroup } from 'tera-system-ui';
8
10
  import { SideNavigation } from 'tera-system-ui/side-navigation'; // subpath
9
11
 
10
12
  ## SideNavigation
@@ -15,10 +17,10 @@ Sidebar navigation. Parts: SideNavigation, SideNavigationItem, SideNavigationLay
15
17
  ──────────────────────────────────────────────────────────────────────────
16
18
  children Snippet optional
17
19
  class string optional
18
- sideNavHref string optional
19
- language string optional
20
- items SideNavigationItem[] optional
21
- bottomChildren Snippet optional
20
+ sideNavHref string optional Current active route, used to highlight the matching item. Usually supplied via TeraUiContext.
21
+ language string optional Active language code; localizes the built-in default nav links. Usually supplied via TeraUiContext.
22
+ items SideNavigationEntry[] optional Navigation entries: a flat array mixing link items ({ href, title, icon?, exactHref? }) and collapsible groups ({ id, title, items, defaultExpanded? }). Omit to render the built-in default nav.
23
+ bottomChildren Snippet optional Snippet rendered pinned at the bottom of the sidebar (e.g. a theme toggle).
22
24
  ref HTMLElement optional (bindable)
23
25
 
24
26
  ### Usage
@@ -28,3 +30,22 @@ Sidebar navigation. Parts: SideNavigation, SideNavigationItem, SideNavigationLay
28
30
  </script>
29
31
 
30
32
  <SideNavigation>Content</SideNavigation>
33
+
34
+ ## SideNavigationGroup
35
+
36
+ ### Props
37
+
38
+ Name Type Required
39
+ ──────────────────────────────────────────────────────────────────────────
40
+ group SideNavigationGroup required
41
+ expanded boolean optional
42
+ onToggle () => void required
43
+ isSelected (item: SideNavigationItem) => boolean required
44
+
45
+ ### Usage
46
+
47
+ <script>
48
+ import { SideNavigationGroup } from 'tera-system-ui';
49
+ </script>
50
+
51
+ <SideNavigationGroup />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tera-system-ui",
3
- "version": "0.1.71",
3
+ "version": "0.1.73",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "npm run customPrepublish && npm run generate-index && npm run generate-llms && vite build && npm run package && npm run copy-docs && npm run copy-llms && npm run postpublish",
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  import fs from "fs";
3
3
 
4
4
  import path from "path";
@@ -65,7 +65,10 @@ function extractExportNames(filePath) {
65
65
 
66
66
  // Find all matches for `export type { ... }`
67
67
  while ((match = typeExportRegex.exec(fileContent)) !== null) {
68
- const typeNames = match[1].split(',').map(t => t.trim().split(/\s+as\s+/)[0].trim()).filter(t => t);
68
+ const typeNames = match[1].split(',').map(t => {
69
+ const parts = t.trim().split(/\s+as\s+/);
70
+ return (parts[1] || parts[0]).trim();
71
+ }).filter(t => t);
69
72
  types.push(...typeNames);
70
73
  }
71
74