@liberfi.io/ui-scaffold 0.1.35 → 0.1.36
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/README.md +350 -0
- package/dist/index.d.mts +190 -21
- package/dist/index.d.ts +190 -21
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
package/README.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# @liberfi.io/ui-scaffold
|
|
2
|
+
|
|
3
|
+
Page layout and scaffold components for the Liberfi React SDK. Provides a responsive layout shell with configurable header/footer, auto-active navigation, and IoC-friendly design.
|
|
4
|
+
|
|
5
|
+
## Design Philosophy
|
|
6
|
+
|
|
7
|
+
- **IoC (Inversion of Control)**: The scaffold does not hardcode routing or side effects. Consumers inject `pathname` and `onNavigate` via props, keeping the library framework-agnostic.
|
|
8
|
+
- **Breakpoint-array visibility**: Header and footer visibility is described as an explicit list of breakpoints (e.g. `["desktop", "tablet"]`), making the API symmetric and self-documenting.
|
|
9
|
+
- **Slot-based composition**: Header and footer accept either pre-built components (`ScaffoldHeader`, `ScaffoldFooter`) or arbitrary `ReactNode` for full customisation.
|
|
10
|
+
- **CSS-variable height system**: Fixed header/footer heights are exposed as CSS custom properties (`--scaffold-header-height`, `--scaffold-footer-height`) so children can compute their own height via `calc()`.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @liberfi.io/ui-scaffold
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Peer dependencies
|
|
19
|
+
|
|
20
|
+
The consumer must provide:
|
|
21
|
+
|
|
22
|
+
- `react` >= 18
|
|
23
|
+
- `react-dom` >= 18
|
|
24
|
+
- `jotai` >= 2.15.1 (used by the draggable sub-module)
|
|
25
|
+
- `@liberfi.io/ui` (workspace)
|
|
26
|
+
- `@liberfi.io/i18n` (workspace)
|
|
27
|
+
|
|
28
|
+
## API Reference
|
|
29
|
+
|
|
30
|
+
### Components
|
|
31
|
+
|
|
32
|
+
#### `Scaffold`
|
|
33
|
+
|
|
34
|
+
Main layout container. Manages header/footer areas, CSS variables, responsive visibility, and provides `ScaffoldContext`.
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Default | Description |
|
|
37
|
+
| --------------- | ------------------------------------------ | ------------------------------- | ----------------------------------------------- |
|
|
38
|
+
| `pathname` | `string` | `""` | Current route pathname for nav active detection |
|
|
39
|
+
| `onNavigate` | `(href: string) => void` | no-op | Navigation callback (IoC) |
|
|
40
|
+
| `header` | `ReactNode` | — | Header slot |
|
|
41
|
+
| `footer` | `ReactNode` | — | Footer slot |
|
|
42
|
+
| `headerHeight` | `number` | `60` | Header height in px |
|
|
43
|
+
| `footerHeight` | `number` | `56` | Footer height in px |
|
|
44
|
+
| `headerVisible` | `LayoutBreakpoint[]` | `["desktop","tablet","mobile"]` | Breakpoints where header is visible |
|
|
45
|
+
| `footerVisible` | `LayoutBreakpoint[]` | `[]` | Breakpoints where footer is visible |
|
|
46
|
+
| `className` | `string` | — | Wrapper class |
|
|
47
|
+
| `classNames` | `{ wrapper?, header?, content?, footer? }` | — | Per-section classes |
|
|
48
|
+
|
|
49
|
+
#### `ScaffoldHeader`
|
|
50
|
+
|
|
51
|
+
Pre-built desktop header with left/nav/right slots.
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Description |
|
|
54
|
+
| ---------- | ----------- | -------------------------------------------------- |
|
|
55
|
+
| `left` | `ReactNode` | Left slot (e.g. Logo) |
|
|
56
|
+
| `right` | `ReactNode` | Right slot (e.g. account menu) |
|
|
57
|
+
| `navItems` | `NavItem[]` | Navigation items with auto-active detection |
|
|
58
|
+
| `children` | `ReactNode` | Full custom override (ignores left/right/navItems) |
|
|
59
|
+
|
|
60
|
+
#### `ScaffoldFooter`
|
|
61
|
+
|
|
62
|
+
Pre-built mobile footer with tab-style navigation.
|
|
63
|
+
|
|
64
|
+
| Prop | Type | Description |
|
|
65
|
+
| ---------- | ----------- | ------------------------------------------- |
|
|
66
|
+
| `navItems` | `NavItem[]` | Navigation items rendered as icon+text tabs |
|
|
67
|
+
| `children` | `ReactNode` | Full custom override (ignores navItems) |
|
|
68
|
+
|
|
69
|
+
#### `NavLink`
|
|
70
|
+
|
|
71
|
+
Single navigation link with auto-active detection. Reads `pathname` and `onNavigate` from `ScaffoldContext`.
|
|
72
|
+
|
|
73
|
+
| Prop | Type | Default | Description |
|
|
74
|
+
| --------- | ---------------------- | ---------- | ------------------------- |
|
|
75
|
+
| `item` | `NavItem` | — | Navigation item to render |
|
|
76
|
+
| `variant` | `"header" \| "footer"` | `"header"` | Visual variant |
|
|
77
|
+
|
|
78
|
+
#### `Logo`
|
|
79
|
+
|
|
80
|
+
Logo link component with desktop/mobile icon variants.
|
|
81
|
+
|
|
82
|
+
| Prop | Type | Default | Description |
|
|
83
|
+
| ---------- | ----------- | ------- | ------------------------------------------- |
|
|
84
|
+
| `icon` | `ReactNode` | — | Icon for desktop |
|
|
85
|
+
| `miniIcon` | `ReactNode` | — | Icon for mobile (and desktop when below xl) |
|
|
86
|
+
| `href` | `string` | `"/"` | URL when clicking the logo |
|
|
87
|
+
|
|
88
|
+
### Hooks
|
|
89
|
+
|
|
90
|
+
#### `useScaffold()`
|
|
91
|
+
|
|
92
|
+
Returns the full `ScaffoldContextValue`. Must be used within a `<Scaffold>`.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
const {
|
|
96
|
+
pathname,
|
|
97
|
+
onNavigate,
|
|
98
|
+
headerHeight,
|
|
99
|
+
footerHeight,
|
|
100
|
+
headerVisible,
|
|
101
|
+
footerVisible,
|
|
102
|
+
activeNavKey,
|
|
103
|
+
} = useScaffold();
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### `useScaffoldLayout(config)`
|
|
107
|
+
|
|
108
|
+
Declaratively set the layout for the current page. Overrides on mount, resets to Scaffold defaults on unmount.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
useScaffoldLayout({
|
|
112
|
+
headerVisible?: LayoutBreakpoint[];
|
|
113
|
+
footerVisible?: LayoutBreakpoint[];
|
|
114
|
+
activeNavKey?: string;
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Types
|
|
119
|
+
|
|
120
|
+
#### `LayoutBreakpoint`
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
type LayoutBreakpoint = "desktop" | "tablet" | "mobile";
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Breakpoint mapping: desktop >= 1024px (lg), tablet 640–1023px (sm–lg), mobile < 640px.
|
|
127
|
+
|
|
128
|
+
#### `NavItem`
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
type NavItem = {
|
|
132
|
+
key: string;
|
|
133
|
+
label: string;
|
|
134
|
+
href: string;
|
|
135
|
+
icon?: ReactNode;
|
|
136
|
+
match?: string | RegExp | ((pathname: string) => boolean);
|
|
137
|
+
};
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### `ScaffoldContextValue`
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
type ScaffoldContextValue = {
|
|
144
|
+
pathname: string;
|
|
145
|
+
onNavigate: (href: string) => void;
|
|
146
|
+
headerHeight: number;
|
|
147
|
+
footerHeight: number;
|
|
148
|
+
headerVisible: LayoutBreakpoint[];
|
|
149
|
+
footerVisible: LayoutBreakpoint[];
|
|
150
|
+
activeNavKey: string | undefined;
|
|
151
|
+
setHeaderVisible: (breakpoints: LayoutBreakpoint[]) => void;
|
|
152
|
+
setFooterVisible: (breakpoints: LayoutBreakpoint[]) => void;
|
|
153
|
+
setActiveNavKey: (key: string | undefined) => void;
|
|
154
|
+
defaultHeaderVisible: LayoutBreakpoint[];
|
|
155
|
+
defaultFooterVisible: LayoutBreakpoint[];
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Utilities
|
|
160
|
+
|
|
161
|
+
#### `isNavItemActive(item, pathname)`
|
|
162
|
+
|
|
163
|
+
Check whether a `NavItem` is active for the given pathname.
|
|
164
|
+
|
|
165
|
+
#### `getVisibilityClass(breakpoints)`
|
|
166
|
+
|
|
167
|
+
Map a `LayoutBreakpoint[]` to Tailwind visibility class names.
|
|
168
|
+
|
|
169
|
+
#### `ALL_BREAKPOINTS`
|
|
170
|
+
|
|
171
|
+
Constant: `["desktop", "tablet", "mobile"]`.
|
|
172
|
+
|
|
173
|
+
## Usage Examples
|
|
174
|
+
|
|
175
|
+
### Basic usage with custom header/footer
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { Scaffold } from "@liberfi.io/ui-scaffold";
|
|
179
|
+
|
|
180
|
+
function App() {
|
|
181
|
+
const pathname = usePathname(); // from your router
|
|
182
|
+
const navigate = useNavigate();
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<Scaffold
|
|
186
|
+
pathname={pathname}
|
|
187
|
+
onNavigate={navigate}
|
|
188
|
+
header={<MyCustomHeader />}
|
|
189
|
+
footer={<MyCustomFooter />}
|
|
190
|
+
headerVisible={["desktop", "tablet"]}
|
|
191
|
+
footerVisible={["mobile"]}
|
|
192
|
+
>
|
|
193
|
+
<MyPageContent />
|
|
194
|
+
</Scaffold>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Using built-in navigation
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import {
|
|
203
|
+
Scaffold,
|
|
204
|
+
ScaffoldHeader,
|
|
205
|
+
ScaffoldFooter,
|
|
206
|
+
Logo,
|
|
207
|
+
type NavItem,
|
|
208
|
+
} from "@liberfi.io/ui-scaffold";
|
|
209
|
+
|
|
210
|
+
const navItems: NavItem[] = [
|
|
211
|
+
{ key: "home", label: "Home", href: "/", icon: <HomeIcon /> },
|
|
212
|
+
{ key: "trade", label: "Trade", href: "/trade", icon: <TradeIcon /> },
|
|
213
|
+
{ key: "account", label: "Account", href: "/account", icon: <AccountIcon /> },
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
function App() {
|
|
217
|
+
return (
|
|
218
|
+
<Scaffold
|
|
219
|
+
pathname={pathname}
|
|
220
|
+
onNavigate={navigate}
|
|
221
|
+
headerVisible={["desktop", "tablet"]}
|
|
222
|
+
footerVisible={["tablet", "mobile"]}
|
|
223
|
+
header={
|
|
224
|
+
<ScaffoldHeader
|
|
225
|
+
left={<Logo icon={<LogoSvg />} />}
|
|
226
|
+
navItems={navItems}
|
|
227
|
+
right={<AccountMenu />}
|
|
228
|
+
/>
|
|
229
|
+
}
|
|
230
|
+
footer={<ScaffoldFooter navItems={navItems} />}
|
|
231
|
+
>
|
|
232
|
+
{children}
|
|
233
|
+
</Scaffold>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Per-page layout overrides
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
import { useScaffoldLayout } from "@liberfi.io/ui-scaffold";
|
|
242
|
+
|
|
243
|
+
function HomePage() {
|
|
244
|
+
useScaffoldLayout({
|
|
245
|
+
headerVisible: ["desktop", "tablet"],
|
|
246
|
+
footerVisible: ["tablet", "mobile"],
|
|
247
|
+
activeNavKey: "home",
|
|
248
|
+
});
|
|
249
|
+
return <HomeContent />;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function TradePage() {
|
|
253
|
+
useScaffoldLayout({
|
|
254
|
+
headerVisible: ["desktop", "tablet", "mobile"],
|
|
255
|
+
footerVisible: [],
|
|
256
|
+
});
|
|
257
|
+
return <TradeContent />;
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Using CSS variables for height calculation
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
function PageContent() {
|
|
265
|
+
return (
|
|
266
|
+
<div
|
|
267
|
+
style={{
|
|
268
|
+
height:
|
|
269
|
+
"calc(100vh - var(--scaffold-header-height) - var(--scaffold-footer-height))",
|
|
270
|
+
}}
|
|
271
|
+
>
|
|
272
|
+
{/* content with precise height */}
|
|
273
|
+
</div>
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Split View
|
|
279
|
+
|
|
280
|
+
#### `SplitView`
|
|
281
|
+
|
|
282
|
+
Resizable split-view container with a draggable handle between two panes. Supports horizontal (left | right) and vertical (top | bottom) splitting, and can be nested for complex layouts.
|
|
283
|
+
|
|
284
|
+
| Prop | Type | Default | Description |
|
|
285
|
+
| -------------- | ----------------------------------- | -------------- | -------------------------------------------------------- |
|
|
286
|
+
| `direction` | `"horizontal" \| "vertical"` | `"horizontal"` | Split direction |
|
|
287
|
+
| `primary` | `ReactNode` | — | Content for the primary (first) pane |
|
|
288
|
+
| `secondary` | `ReactNode` | — | Content for the secondary (second) pane |
|
|
289
|
+
| `defaultSize` | `number` | `400` | Initial size of the primary pane in px |
|
|
290
|
+
| `minSize` | `number` | `100` | Minimum size of the primary pane in px |
|
|
291
|
+
| `maxSize` | `number` | `Infinity` | Maximum size of the primary pane in px |
|
|
292
|
+
| `onSizeChange` | `(size: number) => void` | — | Callback when size changes |
|
|
293
|
+
| `persistId` | `string` | — | Unique id for localStorage persistence (omit to disable) |
|
|
294
|
+
| `className` | `string` | — | Wrapper class |
|
|
295
|
+
| `classNames` | `{ primary?, secondary?, handle? }` | — | Per-section classes |
|
|
296
|
+
|
|
297
|
+
#### `SplitHandle`
|
|
298
|
+
|
|
299
|
+
Resize handle rendered between panes. Used internally by `SplitView`, but exported for custom layouts.
|
|
300
|
+
|
|
301
|
+
| Prop | Type | Description |
|
|
302
|
+
| --------------- | ------------------------------- | ------------------------------------ |
|
|
303
|
+
| `direction` | `"horizontal" \| "vertical"` | Direction of the split |
|
|
304
|
+
| `isResizing` | `boolean` | Whether a resize is in progress |
|
|
305
|
+
| `onResizeStart` | `(e: React.MouseEvent) => void` | Mouse-down handler to begin resizing |
|
|
306
|
+
|
|
307
|
+
### Split View Usage
|
|
308
|
+
|
|
309
|
+
#### Horizontal split (left | right)
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
import { SplitView } from "@liberfi.io/ui-scaffold";
|
|
313
|
+
|
|
314
|
+
<SplitView
|
|
315
|
+
direction="horizontal"
|
|
316
|
+
defaultSize={500}
|
|
317
|
+
minSize={200}
|
|
318
|
+
maxSize={800}
|
|
319
|
+
primary={<ChartPanel />}
|
|
320
|
+
secondary={<OrderFormPanel />}
|
|
321
|
+
/>;
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### Nested trading dashboard layout
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
<SplitView
|
|
328
|
+
direction="horizontal"
|
|
329
|
+
defaultSize={700}
|
|
330
|
+
minSize={400}
|
|
331
|
+
maxSize={1200}
|
|
332
|
+
primary={
|
|
333
|
+
<SplitView
|
|
334
|
+
direction="vertical"
|
|
335
|
+
defaultSize={450}
|
|
336
|
+
minSize={200}
|
|
337
|
+
primary={<ChartPanel />}
|
|
338
|
+
secondary={<PositionsPanel />}
|
|
339
|
+
/>
|
|
340
|
+
}
|
|
341
|
+
secondary={<OrderFormPanel />}
|
|
342
|
+
/>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Future Improvements
|
|
346
|
+
|
|
347
|
+
- Animation support for header/footer show/hide transitions
|
|
348
|
+
- `DraggablePanelProvider` integration as an optional Scaffold feature
|
|
349
|
+
- Keyboard navigation and focus management for nav items
|
|
350
|
+
- Touch/pointer event support for SplitView resize on mobile
|
package/dist/index.d.mts
CHANGED
|
@@ -145,30 +145,166 @@ type UseDraggablePanelDisclosureReturnType = {
|
|
|
145
145
|
};
|
|
146
146
|
declare function useDraggablePanelDisclosure(id: string): UseDraggablePanelDisclosureReturnType;
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
/** Responsive breakpoints: desktop (>=1024px), tablet (640–1023px), mobile (<640px) */
|
|
149
|
+
type LayoutBreakpoint = "desktop" | "tablet" | "mobile";
|
|
150
|
+
declare const ALL_BREAKPOINTS: LayoutBreakpoint[];
|
|
151
|
+
/** Navigation item for header links and footer tabs */
|
|
152
|
+
type NavItem = {
|
|
153
|
+
key: string;
|
|
154
|
+
label: string;
|
|
155
|
+
href: string;
|
|
156
|
+
icon?: ReactNode;
|
|
157
|
+
/**
|
|
158
|
+
* Custom active-matching rule.
|
|
159
|
+
* - function: called with pathname, return true if active
|
|
160
|
+
* - RegExp: tested against pathname
|
|
161
|
+
* - string: pathname.startsWith(match)
|
|
162
|
+
* - undefined: exact match for "/", startsWith for others
|
|
163
|
+
*/
|
|
164
|
+
match?: string | RegExp | ((pathname: string) => boolean);
|
|
165
|
+
};
|
|
166
|
+
/** Check whether a NavItem is active for the given pathname */
|
|
167
|
+
declare function isNavItemActive(item: NavItem, pathname: string): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Map a LayoutBreakpoint[] to Tailwind visibility class names.
|
|
170
|
+
*
|
|
171
|
+
* desktop = lg+ (>=1024), tablet = sm..lg (640–1023), mobile = <sm (<640)
|
|
172
|
+
*
|
|
173
|
+
* Returns a class string that hides the element on breakpoints NOT in the array.
|
|
174
|
+
*/
|
|
175
|
+
declare function getVisibilityClass(breakpoints: LayoutBreakpoint[]): string;
|
|
176
|
+
|
|
177
|
+
type ScaffoldContextValue = {
|
|
178
|
+
/** Current route pathname for nav active detection (IoC) */
|
|
179
|
+
pathname: string;
|
|
180
|
+
/** Navigation callback (IoC — no router dependency) */
|
|
181
|
+
onNavigate: (href: string) => void;
|
|
182
|
+
/** Header height in px */
|
|
183
|
+
headerHeight: number;
|
|
184
|
+
/** Footer height in px */
|
|
185
|
+
footerHeight: number;
|
|
186
|
+
/** Toolbar height in px */
|
|
187
|
+
toolbarHeight: number;
|
|
188
|
+
/** Breakpoints where the header is visible */
|
|
189
|
+
headerVisible: LayoutBreakpoint[];
|
|
190
|
+
/** Breakpoints where the footer is visible */
|
|
191
|
+
footerVisible: LayoutBreakpoint[];
|
|
192
|
+
/** Breakpoints where the toolbar is visible */
|
|
193
|
+
toolbarVisible: LayoutBreakpoint[];
|
|
194
|
+
/** Override header visibility (used by useScaffoldLayout) */
|
|
195
|
+
setHeaderVisible: (breakpoints: LayoutBreakpoint[]) => void;
|
|
196
|
+
/** Override footer visibility (used by useScaffoldLayout) */
|
|
197
|
+
setFooterVisible: (breakpoints: LayoutBreakpoint[]) => void;
|
|
198
|
+
/** Override toolbar visibility (used by useScaffoldLayout) */
|
|
199
|
+
setToolbarVisible: (breakpoints: LayoutBreakpoint[]) => void;
|
|
200
|
+
/** Default headerVisible from Scaffold props (for reset on unmount) */
|
|
201
|
+
defaultHeaderVisible: LayoutBreakpoint[];
|
|
202
|
+
/** Default footerVisible from Scaffold props (for reset on unmount) */
|
|
203
|
+
defaultFooterVisible: LayoutBreakpoint[];
|
|
204
|
+
/** Default toolbarVisible from Scaffold props (for reset on unmount) */
|
|
205
|
+
defaultToolbarVisible: LayoutBreakpoint[];
|
|
206
|
+
};
|
|
207
|
+
declare const ScaffoldContext: react.Context<ScaffoldContextValue | null>;
|
|
208
|
+
/** Read the Scaffold context. Throws if used outside a Scaffold. */
|
|
209
|
+
declare function useScaffold(): ScaffoldContextValue;
|
|
210
|
+
/**
|
|
211
|
+
* Declaratively set the layout for the current page.
|
|
212
|
+
* Overrides on mount, resets to Scaffold defaults on unmount.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* useScaffoldLayout({
|
|
216
|
+
* headerVisible: ["desktop", "tablet"],
|
|
217
|
+
* footerVisible: ["tablet", "mobile"],
|
|
218
|
+
* toolbarVisible: ["desktop"],
|
|
219
|
+
* });
|
|
220
|
+
*/
|
|
221
|
+
declare function useScaffoldLayout(config: {
|
|
222
|
+
headerVisible?: LayoutBreakpoint[];
|
|
223
|
+
footerVisible?: LayoutBreakpoint[];
|
|
224
|
+
toolbarVisible?: LayoutBreakpoint[];
|
|
225
|
+
}): void;
|
|
226
|
+
|
|
227
|
+
type ScaffoldProps = PropsWithChildren<{
|
|
228
|
+
/** Current route pathname for nav active detection */
|
|
229
|
+
pathname?: string;
|
|
230
|
+
/** Navigation callback (IoC — decoupled from router) */
|
|
231
|
+
onNavigate?: (href: string) => void;
|
|
232
|
+
/** Header slot */
|
|
233
|
+
header?: ReactNode;
|
|
234
|
+
/** Footer slot (typically mobile tab navigation) */
|
|
235
|
+
footer?: ReactNode;
|
|
236
|
+
/** Toolbar slot (typically desktop bottom status bar) */
|
|
237
|
+
toolbar?: ReactNode;
|
|
238
|
+
/** Header height in px (default 60) */
|
|
239
|
+
headerHeight?: number;
|
|
240
|
+
/** Footer height in px (default 56) */
|
|
241
|
+
footerHeight?: number;
|
|
242
|
+
/** Toolbar height in px (default 36) */
|
|
243
|
+
toolbarHeight?: number;
|
|
244
|
+
/** Breakpoints where the header is visible (default all) */
|
|
245
|
+
headerVisible?: LayoutBreakpoint[];
|
|
246
|
+
/** Breakpoints where the footer is visible (default none) */
|
|
247
|
+
footerVisible?: LayoutBreakpoint[];
|
|
248
|
+
/** Breakpoints where the toolbar is visible (default none) */
|
|
249
|
+
toolbarVisible?: LayoutBreakpoint[];
|
|
149
250
|
className?: string;
|
|
251
|
+
classNames?: {
|
|
252
|
+
wrapper?: string;
|
|
253
|
+
header?: string;
|
|
254
|
+
content?: string;
|
|
255
|
+
footer?: string;
|
|
256
|
+
toolbar?: string;
|
|
257
|
+
};
|
|
150
258
|
}>;
|
|
151
|
-
declare function
|
|
259
|
+
declare function Scaffold({ children, pathname, onNavigate, header, footer, toolbar, headerHeight, footerHeight, toolbarHeight, headerVisible: defaultHeaderVisible, footerVisible: defaultFooterVisible, toolbarVisible: defaultToolbarVisible, className, classNames, }: ScaffoldProps): react_jsx_runtime.JSX.Element;
|
|
152
260
|
|
|
153
|
-
type
|
|
261
|
+
type ScaffoldHeaderProps = PropsWithChildren<{
|
|
262
|
+
/** Left slot (e.g. Logo) */
|
|
263
|
+
left?: ReactNode;
|
|
264
|
+
/** Right slot (e.g. account menu, settings) */
|
|
265
|
+
right?: ReactNode;
|
|
266
|
+
/** Navigation items rendered as horizontal links with auto-active detection */
|
|
267
|
+
navItems?: NavItem[];
|
|
154
268
|
className?: string;
|
|
155
269
|
}>;
|
|
156
|
-
|
|
270
|
+
/**
|
|
271
|
+
* Pre-built header layout with left / nav / right slots.
|
|
272
|
+
* Pass `children` for full custom control (left/right/navItems will be ignored).
|
|
273
|
+
*/
|
|
274
|
+
declare function ScaffoldHeader({ children, left, right, navItems, className, }: ScaffoldHeaderProps): react_jsx_runtime.JSX.Element;
|
|
157
275
|
|
|
158
|
-
type
|
|
276
|
+
type ScaffoldFooterProps = PropsWithChildren<{
|
|
277
|
+
/** Navigation items rendered as vertical icon+text tabs */
|
|
278
|
+
navItems?: NavItem[];
|
|
159
279
|
className?: string;
|
|
160
280
|
}>;
|
|
161
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Pre-built footer layout with tab-style navigation.
|
|
283
|
+
* Pass `children` for full custom control (navItems will be ignored).
|
|
284
|
+
*/
|
|
285
|
+
declare function ScaffoldFooter({ children, navItems, className, }: ScaffoldFooterProps): react_jsx_runtime.JSX.Element;
|
|
162
286
|
|
|
163
|
-
type
|
|
287
|
+
type ScaffoldToolbarProps = PropsWithChildren<{
|
|
288
|
+
/** Left-aligned content */
|
|
289
|
+
left?: ReactNode;
|
|
290
|
+
/** Right-aligned content */
|
|
291
|
+
right?: ReactNode;
|
|
164
292
|
className?: string;
|
|
165
293
|
}>;
|
|
166
|
-
|
|
294
|
+
/**
|
|
295
|
+
* Pre-built bottom toolbar layout with left / right slots.
|
|
296
|
+
* Typically shown on desktop while ScaffoldFooter is shown on mobile.
|
|
297
|
+
* Pass `children` for full custom control (left/right will be ignored).
|
|
298
|
+
*/
|
|
299
|
+
declare function ScaffoldToolbar({ children, left, right, className, }: ScaffoldToolbarProps): react_jsx_runtime.JSX.Element;
|
|
167
300
|
|
|
168
|
-
type
|
|
301
|
+
type NavLinkProps = {
|
|
302
|
+
item: NavItem;
|
|
303
|
+
/** "header" = horizontal text link, "footer" = vertical icon+text tab */
|
|
304
|
+
variant?: "header" | "footer";
|
|
169
305
|
className?: string;
|
|
170
|
-
}
|
|
171
|
-
declare function
|
|
306
|
+
};
|
|
307
|
+
declare function NavLink({ item, variant, className }: NavLinkProps): react_jsx_runtime.JSX.Element;
|
|
172
308
|
|
|
173
309
|
type LogoProps = {
|
|
174
310
|
/** icon for desktop */
|
|
@@ -182,14 +318,6 @@ type LogoProps = {
|
|
|
182
318
|
};
|
|
183
319
|
declare function Logo({ href, icon, miniIcon, className }: LogoProps): react_jsx_runtime.JSX.Element;
|
|
184
320
|
|
|
185
|
-
type HeaderNavigationProps = PropsWithChildren<{
|
|
186
|
-
href: string;
|
|
187
|
-
title: string;
|
|
188
|
-
active?: boolean;
|
|
189
|
-
className?: string;
|
|
190
|
-
}>;
|
|
191
|
-
declare function HeaderNavigation({ href, title, active, className, }: HeaderNavigationProps): react_jsx_runtime.JSX.Element;
|
|
192
|
-
|
|
193
321
|
type RenderAsyncModalProps<P = any, R = any> = {
|
|
194
322
|
/** custom parameters for the modal */
|
|
195
323
|
params?: P;
|
|
@@ -222,6 +350,47 @@ type UseAsyncModalReturnType<P = any, R = any> = {
|
|
|
222
350
|
};
|
|
223
351
|
declare function useAsyncModal<P = any, R = any>(id: string): UseAsyncModalReturnType<P, R>;
|
|
224
352
|
|
|
353
|
+
type SplitViewProps = {
|
|
354
|
+
/** Split direction */
|
|
355
|
+
direction?: "horizontal" | "vertical";
|
|
356
|
+
/** Content for the primary (first) pane */
|
|
357
|
+
primary: ReactNode;
|
|
358
|
+
/** Content for the secondary (second) pane */
|
|
359
|
+
secondary: ReactNode;
|
|
360
|
+
/** Initial size of the primary pane in px */
|
|
361
|
+
defaultSize?: number;
|
|
362
|
+
/** Minimum size of the primary pane in px */
|
|
363
|
+
minSize?: number;
|
|
364
|
+
/** Maximum size of the primary pane in px */
|
|
365
|
+
maxSize?: number;
|
|
366
|
+
/** Minimum size of the secondary pane in px */
|
|
367
|
+
secondaryMinSize?: number;
|
|
368
|
+
/** Callback when size changes */
|
|
369
|
+
onSizeChange?: (size: number) => void;
|
|
370
|
+
/** Unique id for localStorage persistence (omit to disable) */
|
|
371
|
+
persistId?: string;
|
|
372
|
+
className?: string;
|
|
373
|
+
classNames?: {
|
|
374
|
+
primary?: string;
|
|
375
|
+
secondary?: string;
|
|
376
|
+
handle?: string;
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
/**
|
|
380
|
+
* Resizable split-view container with a draggable handle between two panes.
|
|
381
|
+
* Supports horizontal (left | right) and vertical (top | bottom) splitting.
|
|
382
|
+
* Composable: nest SplitViews for complex layouts (e.g. trading dashboards).
|
|
383
|
+
*/
|
|
384
|
+
declare function SplitView({ direction, primary, secondary, defaultSize, minSize, maxSize, secondaryMinSize, onSizeChange, persistId, className, classNames, }: SplitViewProps): react_jsx_runtime.JSX.Element;
|
|
385
|
+
|
|
386
|
+
type SplitHandleProps = {
|
|
387
|
+
direction: "horizontal" | "vertical";
|
|
388
|
+
isResizing: boolean;
|
|
389
|
+
onResizeStart: (e: React.MouseEvent) => void;
|
|
390
|
+
className?: string;
|
|
391
|
+
};
|
|
392
|
+
declare function SplitHandle({ direction, isResizing, onResizeStart, className, }: SplitHandleProps): react_jsx_runtime.JSX.Element;
|
|
393
|
+
|
|
225
394
|
declare global {
|
|
226
395
|
interface Window {
|
|
227
396
|
__LIBERFI_VERSION__?: {
|
|
@@ -229,6 +398,6 @@ declare global {
|
|
|
229
398
|
};
|
|
230
399
|
}
|
|
231
400
|
}
|
|
232
|
-
declare const _default: "0.1.
|
|
401
|
+
declare const _default: "0.1.36";
|
|
233
402
|
|
|
234
|
-
export { AsyncModal, type AsyncModalProps, type DraggableContentProps, DraggableModal, type DraggableModalProps, DraggablePanel, type DraggablePanelProps, DraggablePanelProvider, type DraggablePanelProviderProps,
|
|
403
|
+
export { ALL_BREAKPOINTS, AsyncModal, type AsyncModalProps, type DraggableContentProps, DraggableModal, type DraggableModalProps, DraggablePanel, type DraggablePanelProps, DraggablePanelProvider, type DraggablePanelProviderProps, type LayoutBreakpoint, Logo, type LogoProps, type NavItem, NavLink, type NavLinkProps, type OpenAsyncModalOptions, type OpenDraggableModalOptions, type OpenDraggablePanelOptions, type RenderAsyncModalProps, Scaffold, ScaffoldContext, type ScaffoldContextValue, ScaffoldFooter, type ScaffoldFooterProps, ScaffoldHeader, type ScaffoldHeaderProps, type ScaffoldProps, ScaffoldToolbar, type ScaffoldToolbarProps, SplitHandle, type SplitHandleProps, SplitView, type SplitViewProps, type UseAsyncModalReturnType, type UseDraggableDisclosureReturnType, type UseDraggableModalDisclosureReturnType, type UseDraggablePanelDisclosureReturnType, getVisibilityClass, isNavItemActive, useAsyncModal, useDraggableDisclosure, useDraggableModalDisclosure, useDraggablePanelDisclosure, useScaffold, useScaffoldLayout, _default as version };
|