@kawaiininja/layouts 3.0.1 → 3.1.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/README.md +30 -0
- package/dist/MobileLayout.js +3 -2
- package/dist/PcLayout.js +3 -2
- package/dist/hooks/useDrawerStack.d.ts +7 -3
- package/dist/hooks/useDrawerStack.js +7 -12
- package/dist/types/drawer.d.ts +1 -1
- package/dist/types/layout.d.ts +1 -7
- package/dist/types/navigation.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -184,6 +184,36 @@ const drawerItems = [
|
|
|
184
184
|
|
|
185
185
|
The framework will automatically calculate the correct path from your `TabConfig` and trigger `onNavigate`.
|
|
186
186
|
|
|
187
|
+
### 5. Triggering Drawers from Views
|
|
188
|
+
|
|
189
|
+
Every component rendered inside a sub-tab `view` automatically receives the `openDrawer` prop (and its alias `onOpenDrawer`). This allows you to trigger your registered drawers from any button or interaction within your content.
|
|
190
|
+
|
|
191
|
+
**New**: You can now pass a data object as the second argument. This data will be passed as props to the drawer component.
|
|
192
|
+
|
|
193
|
+
```jsx
|
|
194
|
+
// Inside a component used as a sub-tab 'view'
|
|
195
|
+
const MyFeedView = ({ openDrawer }) => {
|
|
196
|
+
return (
|
|
197
|
+
<div className="p-6">
|
|
198
|
+
<h1>Welcome to the Feed</h1>
|
|
199
|
+
{/* Pass custom data to the drawer */}
|
|
200
|
+
<button onClick={() => openDrawer("editor", { initialTitle: "Hello World" })}>
|
|
201
|
+
Compose New Post
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// The Drawer component then receives it as props
|
|
208
|
+
const MyEditorDrawer = ({ initialTitle, isOpen, onClose }) => {
|
|
209
|
+
return (
|
|
210
|
+
<AdaptiveDrawer isOpen={isOpen} onClose={onClose} title="New Post">
|
|
211
|
+
<input defaultValue={initialTitle} />
|
|
212
|
+
</AdaptiveDrawer>
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
```
|
|
216
|
+
|
|
187
217
|
---
|
|
188
218
|
|
|
189
219
|
## 🔄 Data Refresh & Safety
|
package/dist/MobileLayout.js
CHANGED
|
@@ -317,12 +317,13 @@ const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh,
|
|
|
317
317
|
.view, {
|
|
318
318
|
onOpenDrawer: handleOpenDrawer,
|
|
319
319
|
openDrawer: handleOpenDrawer,
|
|
320
|
-
}) }) }, `${activeTab}-${activeSubTab}`) })] })] }), _jsxs("nav", { className: "absolute right-0 top-0 bottom-0 w-12 bg-[rgb(var(--bg-tertiary))] border-l border-[rgb(var(--color-border-subtle))] flex flex-col z-50 pb-[env(safe-area-inset-bottom,0px)]", children: [_jsxs("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto no-scrollbar py-4 w-full relative", children: [_jsx(RailNavIndicator, { height: activeHeight, offset: activeOffset }), tabs.map((tab, idx) => (_jsx(RailNavButton, { title: tab.label, icon: tab.icon, active: activeTab === tab.id, onClick: () => handleNavTouchEnd(tab.id), onTouchStart: (e) => handleNavTouchStart(e, tab), onTouchMove: handleNavTouchMove, onTouchEnd: () => handleNavTouchEnd(tab.id), onRegisterRef: (el) => registerButtonRef(idx, el), isMobile: true }, tab.id)))] }), _jsx(RailNavThemeToggle, {})] })] }), _jsx(QuickMenu, { ...quickMenu, isMobile: true }), drawerStack.map((
|
|
320
|
+
}) }) }, `${activeTab}-${activeSubTab}`) })] })] }), _jsxs("nav", { className: "absolute right-0 top-0 bottom-0 w-12 bg-[rgb(var(--bg-tertiary))] border-l border-[rgb(var(--color-border-subtle))] flex flex-col z-50 pb-[env(safe-area-inset-bottom,0px)]", children: [_jsxs("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto no-scrollbar py-4 w-full relative", children: [_jsx(RailNavIndicator, { height: activeHeight, offset: activeOffset }), tabs.map((tab, idx) => (_jsx(RailNavButton, { title: tab.label, icon: tab.icon, active: activeTab === tab.id, onClick: () => handleNavTouchEnd(tab.id), onTouchStart: (e) => handleNavTouchStart(e, tab), onTouchMove: handleNavTouchMove, onTouchEnd: () => handleNavTouchEnd(tab.id), onRegisterRef: (el) => registerButtonRef(idx, el), isMobile: true }, tab.id)))] }), _jsx(RailNavThemeToggle, {})] })] }), _jsx(QuickMenu, { ...quickMenu, isMobile: true }), drawerStack.map((item, index) => {
|
|
321
|
+
const { id, data } = item;
|
|
321
322
|
const DrawerComp = drawers[id];
|
|
322
323
|
if (!DrawerComp)
|
|
323
324
|
return null;
|
|
324
325
|
const isTop = index === drawerStack.length - 1;
|
|
325
|
-
return (_jsx(DrawerComp, { isOpen: isTop, onClose: () => {
|
|
326
|
+
return (_jsx(DrawerComp, { isOpen: isTop, ...(data || {}), onClose: () => {
|
|
326
327
|
if (isTop) {
|
|
327
328
|
console.log("[OnyxMobileLayout] Drawer onClose Event:", id);
|
|
328
329
|
handleBackDrawer();
|
package/dist/PcLayout.js
CHANGED
|
@@ -106,12 +106,13 @@ const OnyxPcLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh, isRe
|
|
|
106
106
|
}) }) }, `${activeTab}-${activeSubTab}`) })] })] }), _jsxs("nav", { className: "w-16 bg-[rgb(var(--bg-surface))] border-l border-[rgb(var(--color-border-subtle))] flex flex-col z-50", children: [_jsxs("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto no-scrollbar py-4 w-full relative", children: [_jsx(RailNavIndicator, { height: activeHeight, offset: activeOffset }), tabs.map((tab, idx) => (_jsx(RailNavButton, { title: tab.label, icon: tab.icon, active: activeTab === tab.id, onClick: () => handleNavClick(tab.id), onMouseEnter: (e) => handleMouseEnter(tab, e), onMouseLeave: handleMouseLeave, onRegisterRef: (el) => registerButtonRef(idx, el) }, tab.id)))] }), _jsx(RailNavThemeToggle, {})] }), _jsx(QuickMenu, { ...quickMenu, onSelect: handleQuickAction, onMouseEnter: () => {
|
|
107
107
|
if (closeTimer.current)
|
|
108
108
|
clearTimeout(closeTimer.current);
|
|
109
|
-
}, onMouseLeave: handleMouseLeave }), drawerStack.map((
|
|
109
|
+
}, onMouseLeave: handleMouseLeave }), drawerStack.map((item, index) => {
|
|
110
|
+
const { id, data } = item;
|
|
110
111
|
const DrawerComp = drawers[id];
|
|
111
112
|
if (!DrawerComp)
|
|
112
113
|
return null;
|
|
113
114
|
const isTop = index === drawerStack.length - 1;
|
|
114
|
-
return (_jsx(DrawerComp, { isOpen: isTop, onClose: () => {
|
|
115
|
+
return (_jsx(DrawerComp, { isOpen: isTop, ...(data || {}), onClose: () => {
|
|
115
116
|
if (isTop)
|
|
116
117
|
handleBackDrawer();
|
|
117
118
|
}, onBack: () => {
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
export interface DrawerStackItem {
|
|
2
|
+
id: string;
|
|
3
|
+
data?: any;
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
6
|
* useDrawerStack
|
|
3
7
|
* Manages a stack of drawers for nested navigation.
|
|
4
8
|
*/
|
|
5
9
|
export declare function useDrawerStack(): {
|
|
6
|
-
drawerStack:
|
|
10
|
+
drawerStack: DrawerStackItem[];
|
|
7
11
|
activeDrawer: string | null;
|
|
8
|
-
handleOpenDrawer: (id: string) => void;
|
|
12
|
+
handleOpenDrawer: (id: string, data?: any) => void;
|
|
9
13
|
handleBackDrawer: () => void;
|
|
10
14
|
handleCloseDrawers: () => void;
|
|
11
|
-
setDrawerStack: import("react").Dispatch<import("react").SetStateAction<
|
|
15
|
+
setDrawerStack: import("react").Dispatch<import("react").SetStateAction<DrawerStackItem[]>>;
|
|
12
16
|
};
|
|
@@ -5,27 +5,22 @@ import { useCallback, useMemo, useState } from "react";
|
|
|
5
5
|
*/
|
|
6
6
|
export function useDrawerStack() {
|
|
7
7
|
const [drawerStack, setDrawerStack] = useState([]);
|
|
8
|
-
const activeDrawer = useMemo(() => drawerStack[drawerStack.length - 1] || null, [drawerStack]);
|
|
9
|
-
const handleOpenDrawer = useCallback((id) => {
|
|
10
|
-
console.log("[useDrawerStack] Opening Drawer:", id);
|
|
8
|
+
const activeDrawer = useMemo(() => drawerStack[drawerStack.length - 1]?.id || null, [drawerStack]);
|
|
9
|
+
const handleOpenDrawer = useCallback((id, data) => {
|
|
10
|
+
console.log("[useDrawerStack] Opening Drawer:", id, "with data:", data);
|
|
11
11
|
setDrawerStack((prev) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
console.log("[useDrawerStack] Drawer already at top, skipping push:", id);
|
|
12
|
+
// Don't push if it's already the top drawer with same data (optional check)
|
|
13
|
+
if (prev[prev.length - 1]?.id === id &&
|
|
14
|
+
prev[prev.length - 1]?.data === data) {
|
|
16
15
|
return prev;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
console.log("[useDrawerStack] New Stack after push:", next);
|
|
20
|
-
return next;
|
|
17
|
+
return [...prev, { id, data }];
|
|
21
18
|
});
|
|
22
19
|
}, []);
|
|
23
20
|
const handleBackDrawer = useCallback(() => {
|
|
24
|
-
console.log("[useDrawerStack] Popping Stack");
|
|
25
21
|
setDrawerStack((prev) => (prev.length > 0 ? prev.slice(0, -1) : prev));
|
|
26
22
|
}, []);
|
|
27
23
|
const handleCloseDrawers = useCallback(() => {
|
|
28
|
-
console.log("[useDrawerStack] Clearing Stack");
|
|
29
24
|
setDrawerStack([]);
|
|
30
25
|
}, []);
|
|
31
26
|
return {
|
package/dist/types/drawer.d.ts
CHANGED
package/dist/types/layout.d.ts
CHANGED
|
@@ -6,13 +6,7 @@ export interface OnyxMobileLayoutProps {
|
|
|
6
6
|
tabs: TabConfig[];
|
|
7
7
|
user: UserConfig;
|
|
8
8
|
drawers?: {
|
|
9
|
-
[key: string]: ComponentType<
|
|
10
|
-
isOpen: boolean;
|
|
11
|
-
onClose: () => void;
|
|
12
|
-
onBack?: () => void;
|
|
13
|
-
onOpenDrawer: (id: string) => void;
|
|
14
|
-
openDrawer?: (id: string) => void;
|
|
15
|
-
}>;
|
|
9
|
+
[key: string]: ComponentType<any>;
|
|
16
10
|
};
|
|
17
11
|
onSignOut?: () => void;
|
|
18
12
|
onRefresh?: () => void | Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kawaiininja/layouts",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"category": "UI Components",
|
|
5
5
|
"framework": "React / Framer Motion",
|
|
6
6
|
"description": "High-performance, premium mobile-first layouts for the Onyx Framework, featuring gesture-driven navigation, radial quick actions, and integrated theme support.",
|