@exegia/corpora-ui 0.21.0 → 0.23.0
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-lib/components/blocks/auth/auth-flow-block.d.ts +123 -0
- package/dist-lib/components/blocks/layout.d.ts +4 -1
- package/dist-lib/components/blocks/profile/profile-card-block.d.ts +1 -1
- package/dist-lib/components/blocks/scaffold/__tests__/scaffold-atom.test.d.ts +1 -0
- package/dist-lib/components/blocks/scaffold/index.d.ts +2 -0
- package/dist-lib/components/blocks/scaffold/scaffold-atom.d.ts +97 -0
- package/dist-lib/components/blocks/scaffold/scaffold-context.d.ts +3 -1
- package/dist-lib/components/blocks/scaffold/scaffold-root.d.ts +12 -3
- package/dist-lib/components/blocks/scaffold/type.d.ts +58 -18
- package/dist-lib/components/blocks/scaffold/use-scaffold-state.d.ts +26 -0
- package/dist-lib/components/blocks/scaffold/use-scaffold.d.ts +7 -1
- package/dist-lib/components/blocks/scaffold/utils.d.ts +11 -1
- package/dist-lib/components/blocks/shell/index.d.ts +0 -12
- package/dist-lib/components/composed/__tests__/logo.test.d.ts +1 -0
- package/dist-lib/components/composed/logo.d.ts +34 -0
- package/dist-lib/components/ui/switch.d.ts +4 -0
- package/dist-lib/components/user-avatar/type.d.ts +10 -2
- package/dist-lib/components/user-avatar/use-user-avatar.d.ts +5 -0
- package/dist-lib/components/user-avatar/user-avatar-atom.d.ts +9 -0
- package/dist-lib/components/user-avatar/utils.d.ts +22 -0
- package/dist-lib/index.d.ts +2 -1
- package/dist-lib/index.js +3889 -3848
- package/dist-lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/beste/piece/browser-frame.tsx +1 -1
- package/src/components/beste/piece/utils.ts +4 -4
- package/src/components/blocks/auth/__tests__/auth-flow-block.test.tsx +183 -0
- package/src/components/blocks/auth/auth-flow-block.tsx +296 -0
- package/src/components/blocks/layout.ts +30 -2
- package/src/components/blocks/profile/profile-card-block.tsx +1 -1
- package/src/components/blocks/scaffold/__tests__/scaffold-atom.test.tsx +210 -0
- package/src/components/blocks/scaffold/index.ts +15 -0
- package/src/components/blocks/scaffold/scaffold-actions.tsx +5 -1
- package/src/components/blocks/scaffold/scaffold-atom.ts +383 -0
- package/src/components/blocks/scaffold/scaffold-canvas.tsx +12 -4
- package/src/components/blocks/scaffold/scaffold-context.ts +3 -1
- package/src/components/blocks/scaffold/scaffold-inspector.tsx +9 -2
- package/src/components/blocks/scaffold/scaffold-panel.tsx +9 -5
- package/src/components/blocks/scaffold/scaffold-root.tsx +64 -32
- package/src/components/blocks/scaffold/scaffold-tab.tsx +13 -9
- package/src/components/blocks/scaffold/type.ts +64 -18
- package/src/components/blocks/scaffold/use-scaffold-state.ts +58 -0
- package/src/components/blocks/scaffold/use-scaffold.ts +30 -19
- package/src/components/blocks/scaffold/utils.ts +45 -1
- package/src/components/blocks/shell/index.ts +0 -13
- package/src/components/composed/__tests__/logo.test.tsx +60 -0
- package/src/components/composed/logo.tsx +159 -0
- package/src/components/docs/component-preview.tsx +7 -2
- package/src/components/docs/demo-controls.tsx +32 -23
- package/src/components/ui/switch.tsx +30 -0
- package/src/components/user-avatar/__tests__/user-avatar.test.tsx +41 -0
- package/src/components/user-avatar/component.tsx +38 -8
- package/src/components/user-avatar/fallback.tsx +3 -1
- package/src/components/user-avatar/type.ts +10 -2
- package/src/components/user-avatar/use-user-avatar.ts +38 -2
- package/src/components/user-avatar/user-avatar-atom.ts +20 -0
- package/src/components/user-avatar/utils.ts +94 -0
- package/src/index.ts +2 -1
- package/dist-lib/components/blocks/nav/sidebar-block.d.ts +0 -14
- package/dist-lib/components/blocks/nav/sidebar-nav-row.d.ts +0 -3
- package/dist-lib/components/blocks/nav/types.d.ts +0 -60
- package/dist-lib/components/blocks/nav/utils.d.ts +0 -1
- package/dist-lib/components/blocks/scaffold/use-panel-visibility.d.ts +0 -19
- package/dist-lib/components/blocks/shell/animated-sidebar-content.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-footer.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-group-content.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-group-label.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-group.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-header.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-button.d.ts +0 -3
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-item.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-sub-button.d.ts +0 -3
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-sub-item.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-sub.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu.d.ts +0 -2
- package/src/components/blocks/nav/__tests__/sidebar-block.test.tsx +0 -125
- package/src/components/blocks/nav/sidebar-block.tsx +0 -142
- package/src/components/blocks/nav/sidebar-nav-row.tsx +0 -78
- package/src/components/blocks/nav/types.ts +0 -65
- package/src/components/blocks/nav/utils.ts +0 -4
- package/src/components/blocks/scaffold/use-panel-visibility.ts +0 -180
- package/src/components/blocks/shell/animated-sidebar-content.tsx +0 -19
- package/src/components/blocks/shell/animated-sidebar-footer.tsx +0 -19
- package/src/components/blocks/shell/animated-sidebar-group-content.tsx +0 -16
- package/src/components/blocks/shell/animated-sidebar-group-label.tsx +0 -29
- package/src/components/blocks/shell/animated-sidebar-group.tsx +0 -16
- package/src/components/blocks/shell/animated-sidebar-header.tsx +0 -16
- package/src/components/blocks/shell/animated-sidebar-menu-button.tsx +0 -151
- package/src/components/blocks/shell/animated-sidebar-menu-item.tsx +0 -20
- package/src/components/blocks/shell/animated-sidebar-menu-sub-button.tsx +0 -85
- package/src/components/blocks/shell/animated-sidebar-menu-sub-item.tsx +0 -19
- package/src/components/blocks/shell/animated-sidebar-menu-sub.tsx +0 -44
- package/src/components/blocks/shell/animated-sidebar-menu.tsx +0 -26
- /package/dist-lib/components/blocks/{nav/__tests__/sidebar-block.test.d.ts → auth/__tests__/auth-flow-block.test.d.ts} +0 -0
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/** A nested link, one level under a top-level entry. */
|
|
3
|
-
export interface ISidebarNavSubItem {
|
|
4
|
-
id: string
|
|
5
|
-
label: string
|
|
6
|
-
icon?: React.ReactNode
|
|
7
|
-
/** Renders an anchor. Without one the row is a button. */
|
|
8
|
-
href?: string
|
|
9
|
-
disabled?: boolean
|
|
10
|
-
target?: "_blank" | "_self" | "_parent" | "_top"
|
|
11
|
-
onSelect?: () => void
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** A top-level entry. With `items` it expands instead of navigating. */
|
|
15
|
-
export interface ISidebarNavItem extends ISidebarNavSubItem {
|
|
16
|
-
/** Trailing hint — a count, a "New" pill. Hidden while collapsed. */
|
|
17
|
-
badge?: React.ReactNode
|
|
18
|
-
items?: ISidebarNavSubItem[]
|
|
19
|
-
/** Start expanded. Defaults to expanded when one of its children is active. */
|
|
20
|
-
defaultOpen?: boolean
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** A titled run of entries. The title hides while the rail is collapsed. */
|
|
24
|
-
export interface ISidebarNavSection {
|
|
25
|
-
id: string
|
|
26
|
-
label?: string
|
|
27
|
-
items: ISidebarNavItem[]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface ISidebarBlockProps {
|
|
31
|
-
sections: ISidebarNavSection[]
|
|
32
|
-
/** `id` of the current entry — matches top-level and nested ids alike. */
|
|
33
|
-
activeId?: string
|
|
34
|
-
/** Fires for every selection, after the entry's own `onSelect`. */
|
|
35
|
-
onNavigate?: (item: ISidebarNavItem | ISidebarNavSubItem) => void
|
|
36
|
-
/** Brand row above the navigation. */
|
|
37
|
-
header?: React.ReactNode
|
|
38
|
-
/** Pinned below the navigation — an account card, a version note. */
|
|
39
|
-
footer?: React.ReactNode
|
|
40
|
-
/** Collapse toggle in the header row. */
|
|
41
|
-
showTrigger?: boolean
|
|
42
|
-
side?: "left" | "right"
|
|
43
|
-
variant?: "sidebar" | "floating" | "inset"
|
|
44
|
-
/** How the rail collapses: to icons, off-canvas, or not at all. */
|
|
45
|
-
collapsible?: "offcanvas" | "icon" | "none"
|
|
46
|
-
open?: boolean
|
|
47
|
-
defaultOpen?: boolean
|
|
48
|
-
onOpenChange?: (open: boolean) => void
|
|
49
|
-
/** Under 768px the panel is a drawer — drive it from your own header. */
|
|
50
|
-
openMobile?: boolean
|
|
51
|
-
defaultOpenMobile?: boolean
|
|
52
|
-
onOpenMobileChange?: (open: boolean) => void
|
|
53
|
-
/** Rail widths. CSS lengths, e.g. "16rem". */
|
|
54
|
-
width?: string
|
|
55
|
-
iconWidth?: string
|
|
56
|
-
mobileWidth?: string
|
|
57
|
-
ariaLabel?: string
|
|
58
|
-
className?: string
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface IRowProps {
|
|
62
|
-
item: ISidebarNavItem
|
|
63
|
-
activeId?: string
|
|
64
|
-
onNavigate?: (item: ISidebarNavItem | ISidebarNavSubItem) => void
|
|
65
|
-
}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
|
|
5
|
-
import { SCAFFOLD_PANEL_CAPACITY } from "./constants"
|
|
6
|
-
import { getPanelCapacity } from "./utils"
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Internal bookkeeping for responsive panel hiding.
|
|
10
|
-
*
|
|
11
|
-
* - `visibleOrder`: visible panel ids, least-recently-activated first — the
|
|
12
|
-
* front is what capacity pressure evicts next.
|
|
13
|
-
* - `autoHidden`: panels the scaffold hid because the canvas shrank, most
|
|
14
|
-
* recent last. They return on their own when room comes back.
|
|
15
|
-
* - `userHidden`: panels hidden by a tab press. They stay hidden until the
|
|
16
|
-
* tab is pressed again, however wide the canvas grows.
|
|
17
|
-
*/
|
|
18
|
-
interface PanelVisibilityState {
|
|
19
|
-
visibleOrder: string[]
|
|
20
|
-
autoHidden: string[]
|
|
21
|
-
userHidden: string[]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const EMPTY_STATE: PanelVisibilityState = {
|
|
25
|
-
visibleOrder: [],
|
|
26
|
-
autoHidden: [],
|
|
27
|
-
userHidden: [],
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Fold the registered ids and current capacity into a settled state:
|
|
31
|
-
* prune departed panels, admit new ones, evict the least-recently-activated
|
|
32
|
-
* visible panels past capacity, and restore auto-hidden ones when room
|
|
33
|
-
* returns. Returns `prev` untouched when nothing changes. */
|
|
34
|
-
function reconcile(
|
|
35
|
-
prev: PanelVisibilityState,
|
|
36
|
-
ids: readonly string[],
|
|
37
|
-
capacity: number
|
|
38
|
-
): PanelVisibilityState {
|
|
39
|
-
const known = new Set(ids)
|
|
40
|
-
const visibleOrder = prev.visibleOrder.filter((id) => known.has(id))
|
|
41
|
-
const autoHidden = prev.autoHidden.filter((id) => known.has(id))
|
|
42
|
-
const userHidden = prev.userHidden.filter((id) => known.has(id))
|
|
43
|
-
|
|
44
|
-
const tracked = new Set([...visibleOrder, ...autoHidden, ...userHidden])
|
|
45
|
-
for (const id of ids) if (!tracked.has(id)) visibleOrder.push(id)
|
|
46
|
-
|
|
47
|
-
while (visibleOrder.length > capacity && visibleOrder.length > 1) {
|
|
48
|
-
autoHidden.push(visibleOrder.shift() as string)
|
|
49
|
-
}
|
|
50
|
-
while (visibleOrder.length < capacity && autoHidden.length > 0) {
|
|
51
|
-
visibleOrder.push(autoHidden.pop() as string)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const unchanged =
|
|
55
|
-
visibleOrder.join(" ") === prev.visibleOrder.join(" ") &&
|
|
56
|
-
autoHidden.join(" ") === prev.autoHidden.join(" ") &&
|
|
57
|
-
userHidden.join(" ") === prev.userHidden.join(" ")
|
|
58
|
-
return unchanged ? prev : { visibleOrder, autoHidden, userHidden }
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface PanelVisibility {
|
|
62
|
-
/** How many panels currently fit side by side (1..capacity cap). */
|
|
63
|
-
panelCapacity: number
|
|
64
|
-
/** Ids of panels currently hidden (auto + user), for tabs to reflect. */
|
|
65
|
-
hiddenPanelIds: readonly string[]
|
|
66
|
-
isPanelHidden: (id: string) => boolean
|
|
67
|
-
togglePanelVisibility: (id: string) => void
|
|
68
|
-
/** Id of the panel whose tab is hovered — the canvas spotlights it. */
|
|
69
|
-
hoveredPanelId: string | null
|
|
70
|
-
/** @internal Tabs report pointer enter/leave on their label. */
|
|
71
|
-
setPanelHovered: (id: string, hovered: boolean) => void
|
|
72
|
-
/** @internal Canvas reports its ordered panel ids each render. */
|
|
73
|
-
registerPanelIds: (ids: readonly string[]) => void
|
|
74
|
-
/** @internal Canvas reports its measured width. */
|
|
75
|
-
setCanvasWidth: (width: number) => void
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Owns which panels are hidden as the canvas gains and loses room.
|
|
79
|
-
* Lives in `Scaffold.Root`; Canvas and Tab reach it through context. */
|
|
80
|
-
export function usePanelVisibility(): PanelVisibility {
|
|
81
|
-
const [panelIds, setPanelIds] = React.useState<readonly string[]>([])
|
|
82
|
-
const [measuredCapacity, setMeasuredCapacity] = React.useState<number | null>(
|
|
83
|
-
null
|
|
84
|
-
)
|
|
85
|
-
const [state, setState] = React.useState<PanelVisibilityState>(EMPTY_STATE)
|
|
86
|
-
const [hoveredPanelId, setHoveredPanelId] = React.useState<string | null>(
|
|
87
|
-
null
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
const panelCapacity = measuredCapacity ?? SCAFFOLD_PANEL_CAPACITY
|
|
91
|
-
|
|
92
|
-
const registerPanelIds = React.useCallback((ids: readonly string[]) => {
|
|
93
|
-
setPanelIds((prev) =>
|
|
94
|
-
prev.length === ids.length && prev.every((id, i) => id === ids[i])
|
|
95
|
-
? prev
|
|
96
|
-
: [...ids]
|
|
97
|
-
)
|
|
98
|
-
}, [])
|
|
99
|
-
|
|
100
|
-
// Store the derived capacity, not the raw width — resize storms only
|
|
101
|
-
// re-render the tree when a panel actually gains or loses room.
|
|
102
|
-
const setCanvasWidth = React.useCallback((width: number) => {
|
|
103
|
-
setMeasuredCapacity(getPanelCapacity(width))
|
|
104
|
-
}, [])
|
|
105
|
-
|
|
106
|
-
// Settle during render (the derive-state-while-rendering pattern): ids
|
|
107
|
-
// and capacity arrive as state, so an effect here would only add a
|
|
108
|
-
// cascading render after each change.
|
|
109
|
-
const settled = reconcile(state, panelIds, panelCapacity)
|
|
110
|
-
if (settled !== state) setState(settled)
|
|
111
|
-
|
|
112
|
-
const togglePanelVisibility = React.useCallback(
|
|
113
|
-
(id: string) => {
|
|
114
|
-
setState((prev) => {
|
|
115
|
-
if (!panelIds.includes(id)) return prev
|
|
116
|
-
const hidden =
|
|
117
|
-
prev.autoHidden.includes(id) || prev.userHidden.includes(id)
|
|
118
|
-
if (!hidden && prev.visibleOrder.length <= 1) return prev
|
|
119
|
-
|
|
120
|
-
const next: PanelVisibilityState = hidden
|
|
121
|
-
? {
|
|
122
|
-
// Showing: newest activation — reconcile evicts the oldest
|
|
123
|
-
// visible panel if the canvas can't fit one more.
|
|
124
|
-
visibleOrder: [...prev.visibleOrder, id],
|
|
125
|
-
autoHidden: prev.autoHidden.filter((other) => other !== id),
|
|
126
|
-
userHidden: prev.userHidden.filter((other) => other !== id),
|
|
127
|
-
}
|
|
128
|
-
: {
|
|
129
|
-
visibleOrder: prev.visibleOrder.filter((other) => other !== id),
|
|
130
|
-
autoHidden: prev.autoHidden,
|
|
131
|
-
userHidden: [...prev.userHidden, id],
|
|
132
|
-
}
|
|
133
|
-
return reconcile(next, panelIds, panelCapacity)
|
|
134
|
-
})
|
|
135
|
-
},
|
|
136
|
-
[panelIds, panelCapacity]
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
// Leaving clears only its own id — a tab that unmounts mid-hover must
|
|
140
|
-
// not wipe out a hover the pointer has already moved on to.
|
|
141
|
-
const setPanelHovered = React.useCallback((id: string, hovered: boolean) => {
|
|
142
|
-
setHoveredPanelId((prev) => {
|
|
143
|
-
if (hovered) return id
|
|
144
|
-
return prev === id ? null : prev
|
|
145
|
-
})
|
|
146
|
-
}, [])
|
|
147
|
-
|
|
148
|
-
const hiddenPanelIds = React.useMemo(
|
|
149
|
-
() => [...settled.autoHidden, ...settled.userHidden],
|
|
150
|
-
[settled]
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
const isPanelHidden = React.useCallback(
|
|
154
|
-
(id: string) => hiddenPanelIds.includes(id),
|
|
155
|
-
[hiddenPanelIds]
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
return React.useMemo(
|
|
159
|
-
() => ({
|
|
160
|
-
panelCapacity,
|
|
161
|
-
hiddenPanelIds,
|
|
162
|
-
isPanelHidden,
|
|
163
|
-
togglePanelVisibility,
|
|
164
|
-
hoveredPanelId,
|
|
165
|
-
setPanelHovered,
|
|
166
|
-
registerPanelIds,
|
|
167
|
-
setCanvasWidth,
|
|
168
|
-
}),
|
|
169
|
-
[
|
|
170
|
-
panelCapacity,
|
|
171
|
-
hiddenPanelIds,
|
|
172
|
-
isPanelHidden,
|
|
173
|
-
togglePanelVisibility,
|
|
174
|
-
hoveredPanelId,
|
|
175
|
-
setPanelHovered,
|
|
176
|
-
registerPanelIds,
|
|
177
|
-
setCanvasWidth,
|
|
178
|
-
]
|
|
179
|
-
)
|
|
180
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes } from "react"
|
|
2
|
-
import { cn } from "@/lib/utils"
|
|
3
|
-
|
|
4
|
-
export const AnimatedSidebarContent = forwardRef<
|
|
5
|
-
HTMLDivElement,
|
|
6
|
-
HTMLAttributes<HTMLDivElement>
|
|
7
|
-
>(function AnimatedSidebarContent({ className, ...props }, forwardedRef) {
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
{...props}
|
|
11
|
-
ref={forwardedRef}
|
|
12
|
-
data-slot="sidebar-content"
|
|
13
|
-
className={cn(
|
|
14
|
-
"flex min-h-0 flex-1 flex-col gap-2 overflow-x-hidden overflow-y-auto overscroll-contain px-2 py-2",
|
|
15
|
-
className
|
|
16
|
-
)}
|
|
17
|
-
/>
|
|
18
|
-
)
|
|
19
|
-
})
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes } from "react"
|
|
2
|
-
import { cn } from "@/lib/utils"
|
|
3
|
-
|
|
4
|
-
export const AnimatedSidebarFooter = forwardRef<
|
|
5
|
-
HTMLDivElement,
|
|
6
|
-
HTMLAttributes<HTMLDivElement>
|
|
7
|
-
>(function AnimatedSidebarFooter({ className, ...props }, forwardedRef) {
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
{...props}
|
|
11
|
-
ref={forwardedRef}
|
|
12
|
-
data-slot="sidebar-footer"
|
|
13
|
-
className={cn(
|
|
14
|
-
"flex shrink-0 flex-col gap-2 border-t border-border p-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]",
|
|
15
|
-
className
|
|
16
|
-
)}
|
|
17
|
-
/>
|
|
18
|
-
)
|
|
19
|
-
})
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes } from "react"
|
|
2
|
-
import { cn } from "@/lib/utils"
|
|
3
|
-
|
|
4
|
-
export const AnimatedSidebarGroupContent = forwardRef<
|
|
5
|
-
HTMLDivElement,
|
|
6
|
-
HTMLAttributes<HTMLDivElement>
|
|
7
|
-
>(function AnimatedSidebarGroupContent({ className, ...props }, forwardedRef) {
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
{...props}
|
|
11
|
-
ref={forwardedRef}
|
|
12
|
-
data-slot="sidebar-group-content"
|
|
13
|
-
className={cn("w-full min-w-0", className)}
|
|
14
|
-
/>
|
|
15
|
-
)
|
|
16
|
-
})
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes } from "react"
|
|
2
|
-
import { cn } from "@/lib/utils"
|
|
3
|
-
import { useAnimatedSidebarPanel } from "./utils"
|
|
4
|
-
|
|
5
|
-
export const AnimatedSidebarGroupLabel = forwardRef<
|
|
6
|
-
HTMLDivElement,
|
|
7
|
-
HTMLAttributes<HTMLDivElement>
|
|
8
|
-
>(function AnimatedSidebarGroupLabel(
|
|
9
|
-
{ children, className, ...props },
|
|
10
|
-
forwardedRef
|
|
11
|
-
) {
|
|
12
|
-
const { collapsed } = useAnimatedSidebarPanel()
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<div
|
|
16
|
-
{...props}
|
|
17
|
-
ref={forwardedRef}
|
|
18
|
-
aria-hidden={collapsed}
|
|
19
|
-
data-slot="sidebar-group-label"
|
|
20
|
-
className={cn(
|
|
21
|
-
"mb-1 h-7 overflow-hidden px-2 text-[10px] font-medium tracking-[0.14em] text-muted-foreground uppercase transition-opacity",
|
|
22
|
-
collapsed ? "opacity-0" : "opacity-100",
|
|
23
|
-
className
|
|
24
|
-
)}
|
|
25
|
-
>
|
|
26
|
-
{children}
|
|
27
|
-
</div>
|
|
28
|
-
)
|
|
29
|
-
})
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes } from "react"
|
|
2
|
-
import { cn } from "@/lib/utils"
|
|
3
|
-
|
|
4
|
-
export const AnimatedSidebarGroup = forwardRef<
|
|
5
|
-
HTMLDivElement,
|
|
6
|
-
HTMLAttributes<HTMLDivElement>
|
|
7
|
-
>(function AnimatedSidebarGroup({ className, ...props }, forwardedRef) {
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
{...props}
|
|
11
|
-
ref={forwardedRef}
|
|
12
|
-
data-slot="sidebar-group"
|
|
13
|
-
className={cn("flex w-full min-w-0 flex-col px-1 py-1.5", className)}
|
|
14
|
-
/>
|
|
15
|
-
)
|
|
16
|
-
})
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes } from "react"
|
|
2
|
-
import { cn } from "@/lib/utils"
|
|
3
|
-
|
|
4
|
-
export const AnimatedSidebarHeader = forwardRef<
|
|
5
|
-
HTMLDivElement,
|
|
6
|
-
HTMLAttributes<HTMLDivElement>
|
|
7
|
-
>(function AnimatedSidebarHeader({ className, ...props }, forwardedRef) {
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
{...props}
|
|
11
|
-
ref={forwardedRef}
|
|
12
|
-
data-slot="sidebar-header"
|
|
13
|
-
className={cn("flex shrink-0 flex-col gap-2 p-3", className)}
|
|
14
|
-
/>
|
|
15
|
-
)
|
|
16
|
-
})
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import type * as React from "react"
|
|
2
|
-
import { ChevronRight } from "lucide-react"
|
|
3
|
-
import { motion } from "motion/react"
|
|
4
|
-
import { SPRING_LAYOUT, SPRING_PRESS } from "@/lib/ease"
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
import type { AnimatedSidebarMenuButtonProps } from "./type"
|
|
7
|
-
import {
|
|
8
|
-
LABEL_ENTER_TRANSITION,
|
|
9
|
-
LABEL_EXIT_TRANSITION,
|
|
10
|
-
REDUCED_TRANSITION,
|
|
11
|
-
useAnimatedSidebar,
|
|
12
|
-
useAnimatedSidebarPanel,
|
|
13
|
-
} from "./utils"
|
|
14
|
-
|
|
15
|
-
export function AnimatedSidebarMenuButton({
|
|
16
|
-
children,
|
|
17
|
-
icon,
|
|
18
|
-
badge,
|
|
19
|
-
href,
|
|
20
|
-
isActive = false,
|
|
21
|
-
ariaExpanded,
|
|
22
|
-
disabled = false,
|
|
23
|
-
closeOnSelect,
|
|
24
|
-
target,
|
|
25
|
-
rel,
|
|
26
|
-
onSelect,
|
|
27
|
-
className,
|
|
28
|
-
}: AnimatedSidebarMenuButtonProps) {
|
|
29
|
-
const context = useAnimatedSidebar()
|
|
30
|
-
const panel = useAnimatedSidebarPanel()
|
|
31
|
-
const textLabel = typeof children === "string" ? children : undefined
|
|
32
|
-
|
|
33
|
-
const select = (
|
|
34
|
-
event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>
|
|
35
|
-
) => {
|
|
36
|
-
if (disabled) {
|
|
37
|
-
event.preventDefault()
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
onSelect?.()
|
|
41
|
-
const shouldCloseOnSelect = closeOnSelect ?? ariaExpanded === undefined
|
|
42
|
-
if (context.isMobile && shouldCloseOnSelect) {
|
|
43
|
-
context.setOpenMobile(false, panel.side)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const content = (
|
|
48
|
-
<>
|
|
49
|
-
{isActive ? (
|
|
50
|
-
<motion.span
|
|
51
|
-
layoutId={context.layoutId}
|
|
52
|
-
transition={context.reduce ? { duration: 0 } : SPRING_LAYOUT}
|
|
53
|
-
className="absolute inset-0 rounded-xl bg-muted"
|
|
54
|
-
/>
|
|
55
|
-
) : null}
|
|
56
|
-
{icon ? (
|
|
57
|
-
<span
|
|
58
|
-
aria-hidden="true"
|
|
59
|
-
className="relative z-10 grid size-5 shrink-0 place-items-center"
|
|
60
|
-
>
|
|
61
|
-
{icon}
|
|
62
|
-
</span>
|
|
63
|
-
) : null}
|
|
64
|
-
<motion.span
|
|
65
|
-
initial={false}
|
|
66
|
-
animate={{
|
|
67
|
-
opacity: panel.collapsed ? 0 : 1,
|
|
68
|
-
x: panel.collapsed ? -4 : 0,
|
|
69
|
-
}}
|
|
70
|
-
transition={
|
|
71
|
-
context.reduce
|
|
72
|
-
? REDUCED_TRANSITION
|
|
73
|
-
: panel.collapsed
|
|
74
|
-
? LABEL_EXIT_TRANSITION
|
|
75
|
-
: LABEL_ENTER_TRANSITION
|
|
76
|
-
}
|
|
77
|
-
aria-hidden={panel.collapsed}
|
|
78
|
-
className={cn(
|
|
79
|
-
"relative z-10 min-w-0 flex-1 truncate",
|
|
80
|
-
panel.collapsed && "pointer-events-none"
|
|
81
|
-
)}
|
|
82
|
-
>
|
|
83
|
-
{children}
|
|
84
|
-
</motion.span>
|
|
85
|
-
{badge && !panel.collapsed ? (
|
|
86
|
-
<span className="relative z-10 shrink-0 text-xs text-muted-foreground">
|
|
87
|
-
{badge}
|
|
88
|
-
</span>
|
|
89
|
-
) : null}
|
|
90
|
-
{ariaExpanded !== undefined ? (
|
|
91
|
-
<motion.span
|
|
92
|
-
aria-hidden="true"
|
|
93
|
-
initial={false}
|
|
94
|
-
animate={{
|
|
95
|
-
opacity: panel.collapsed ? 0 : 1,
|
|
96
|
-
rotate: ariaExpanded ? 90 : 0,
|
|
97
|
-
x: panel.collapsed ? 4 : 0,
|
|
98
|
-
}}
|
|
99
|
-
transition={context.reduce ? { duration: 0 } : SPRING_LAYOUT}
|
|
100
|
-
className="relative z-10 grid size-4 shrink-0 place-items-center text-muted-foreground"
|
|
101
|
-
>
|
|
102
|
-
<ChevronRight className="size-3.5" />
|
|
103
|
-
</motion.span>
|
|
104
|
-
) : null}
|
|
105
|
-
</>
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
const interactiveClassName = cn(
|
|
109
|
-
"relative flex min-h-9 w-full min-w-0 items-center gap-2.5 overflow-hidden rounded-xl px-3 text-left text-sm font-medium outline-none",
|
|
110
|
-
"text-muted-foreground transition-colors hover:text-foreground",
|
|
111
|
-
"focus-visible:bg-muted/70 focus-visible:ring-2 focus-visible:ring-ring",
|
|
112
|
-
isActive && "text-foreground",
|
|
113
|
-
disabled && "cursor-not-allowed opacity-40",
|
|
114
|
-
className
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
return href ? (
|
|
118
|
-
<motion.a
|
|
119
|
-
href={href}
|
|
120
|
-
target={target}
|
|
121
|
-
rel={rel ?? (target === "_blank" ? "noreferrer noopener" : undefined)}
|
|
122
|
-
aria-current={isActive ? "page" : undefined}
|
|
123
|
-
aria-expanded={ariaExpanded}
|
|
124
|
-
aria-disabled={disabled || undefined}
|
|
125
|
-
aria-label={panel.collapsed ? textLabel : undefined}
|
|
126
|
-
title={panel.collapsed ? textLabel : undefined}
|
|
127
|
-
tabIndex={disabled ? -1 : undefined}
|
|
128
|
-
onClick={select}
|
|
129
|
-
whileTap={context.reduce || disabled ? undefined : { scale: 0.98 }}
|
|
130
|
-
transition={SPRING_PRESS}
|
|
131
|
-
className={interactiveClassName}
|
|
132
|
-
>
|
|
133
|
-
{content}
|
|
134
|
-
</motion.a>
|
|
135
|
-
) : (
|
|
136
|
-
<motion.button
|
|
137
|
-
type="button"
|
|
138
|
-
disabled={disabled}
|
|
139
|
-
aria-current={isActive ? "page" : undefined}
|
|
140
|
-
aria-expanded={ariaExpanded}
|
|
141
|
-
aria-label={panel.collapsed ? textLabel : undefined}
|
|
142
|
-
title={panel.collapsed ? textLabel : undefined}
|
|
143
|
-
onClick={select}
|
|
144
|
-
whileTap={context.reduce || disabled ? undefined : { scale: 0.98 }}
|
|
145
|
-
transition={SPRING_PRESS}
|
|
146
|
-
className={interactiveClassName}
|
|
147
|
-
>
|
|
148
|
-
{content}
|
|
149
|
-
</motion.button>
|
|
150
|
-
)
|
|
151
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { forwardRef } from "react"
|
|
2
|
-
import { motion, type HTMLMotionProps } from "motion/react"
|
|
3
|
-
import { SPRING_LAYOUT } from "@/lib/ease"
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
5
|
-
|
|
6
|
-
export const AnimatedSidebarMenuItem = forwardRef<
|
|
7
|
-
HTMLLIElement,
|
|
8
|
-
HTMLMotionProps<"li">
|
|
9
|
-
>(function AnimatedSidebarMenuItem({ className, ...props }, forwardedRef) {
|
|
10
|
-
return (
|
|
11
|
-
<motion.li
|
|
12
|
-
{...props}
|
|
13
|
-
ref={forwardedRef}
|
|
14
|
-
layout="position"
|
|
15
|
-
transition={SPRING_LAYOUT}
|
|
16
|
-
data-slot="sidebar-menu-item"
|
|
17
|
-
className={cn("relative", className)}
|
|
18
|
-
/>
|
|
19
|
-
)
|
|
20
|
-
})
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type * as React from "react"
|
|
2
|
-
import { motion } from "motion/react"
|
|
3
|
-
import { SPRING_PRESS } from "@/lib/ease"
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
5
|
-
import type { AnimatedSidebarMenuSubButtonProps } from "./type"
|
|
6
|
-
import { useAnimatedSidebar, useAnimatedSidebarPanel } from "./utils"
|
|
7
|
-
|
|
8
|
-
export function AnimatedSidebarMenuSubButton({
|
|
9
|
-
children,
|
|
10
|
-
icon,
|
|
11
|
-
href,
|
|
12
|
-
isActive = false,
|
|
13
|
-
disabled = false,
|
|
14
|
-
closeOnSelect = true,
|
|
15
|
-
target,
|
|
16
|
-
rel,
|
|
17
|
-
onSelect,
|
|
18
|
-
className,
|
|
19
|
-
}: AnimatedSidebarMenuSubButtonProps) {
|
|
20
|
-
const context = useAnimatedSidebar()
|
|
21
|
-
const panel = useAnimatedSidebarPanel()
|
|
22
|
-
|
|
23
|
-
const select = (
|
|
24
|
-
event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>
|
|
25
|
-
) => {
|
|
26
|
-
if (disabled) {
|
|
27
|
-
event.preventDefault()
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
onSelect?.()
|
|
31
|
-
if (context.isMobile && closeOnSelect) {
|
|
32
|
-
context.setOpenMobile(false, panel.side)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const content = (
|
|
37
|
-
<>
|
|
38
|
-
<span
|
|
39
|
-
aria-hidden="true"
|
|
40
|
-
className="grid size-4 shrink-0 place-items-center"
|
|
41
|
-
>
|
|
42
|
-
{icon ?? <span className="size-1 rounded-full bg-current" />}
|
|
43
|
-
</span>
|
|
44
|
-
<span className="min-w-0 flex-1 truncate">{children}</span>
|
|
45
|
-
</>
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
const interactiveClassName = cn(
|
|
49
|
-
"flex min-h-8 w-full min-w-0 items-center gap-2 rounded-lg px-2 text-left text-xs outline-none",
|
|
50
|
-
"text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
|
|
51
|
-
"focus-visible:bg-muted/70 focus-visible:ring-2 focus-visible:ring-ring",
|
|
52
|
-
isActive && "bg-muted/70 text-foreground",
|
|
53
|
-
disabled && "cursor-not-allowed opacity-40",
|
|
54
|
-
className
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
return href ? (
|
|
58
|
-
<motion.a
|
|
59
|
-
href={href}
|
|
60
|
-
target={target}
|
|
61
|
-
rel={rel ?? (target === "_blank" ? "noreferrer noopener" : undefined)}
|
|
62
|
-
aria-current={isActive ? "page" : undefined}
|
|
63
|
-
aria-disabled={disabled || undefined}
|
|
64
|
-
tabIndex={disabled ? -1 : undefined}
|
|
65
|
-
onClick={select}
|
|
66
|
-
whileTap={context.reduce || disabled ? undefined : { scale: 0.98 }}
|
|
67
|
-
transition={SPRING_PRESS}
|
|
68
|
-
className={interactiveClassName}
|
|
69
|
-
>
|
|
70
|
-
{content}
|
|
71
|
-
</motion.a>
|
|
72
|
-
) : (
|
|
73
|
-
<motion.button
|
|
74
|
-
type="button"
|
|
75
|
-
disabled={disabled}
|
|
76
|
-
aria-current={isActive ? "page" : undefined}
|
|
77
|
-
onClick={select}
|
|
78
|
-
whileTap={context.reduce || disabled ? undefined : { scale: 0.98 }}
|
|
79
|
-
transition={SPRING_PRESS}
|
|
80
|
-
className={interactiveClassName}
|
|
81
|
-
>
|
|
82
|
-
{content}
|
|
83
|
-
</motion.button>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { forwardRef } from "react"
|
|
2
|
-
import { motion, type HTMLMotionProps } from "motion/react"
|
|
3
|
-
import { cn } from "@/lib/utils"
|
|
4
|
-
import { SUBMENU_ITEM_VARIANTS } from "./utils"
|
|
5
|
-
|
|
6
|
-
export const AnimatedSidebarMenuSubItem = forwardRef<
|
|
7
|
-
HTMLLIElement,
|
|
8
|
-
HTMLMotionProps<"li">
|
|
9
|
-
>(function AnimatedSidebarMenuSubItem({ className, ...props }, forwardedRef) {
|
|
10
|
-
return (
|
|
11
|
-
<motion.li
|
|
12
|
-
{...props}
|
|
13
|
-
ref={forwardedRef}
|
|
14
|
-
variants={SUBMENU_ITEM_VARIANTS}
|
|
15
|
-
data-slot="sidebar-menu-sub-item"
|
|
16
|
-
className={cn("relative min-w-0", className)}
|
|
17
|
-
/>
|
|
18
|
-
)
|
|
19
|
-
})
|