@kawaiininja/layouts 1.0.4 → 1.0.5
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 +2 -2
- package/dist/MobileLayout.js +37 -14
- package/dist/types.d.ts +5 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ High-performance, premium mobile-first layouts for the Onyx Framework. Designed
|
|
|
36
36
|
## 🚀 Installation
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npm install @
|
|
39
|
+
npm install @kawaiininja/layouts
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Note: This package requires `framer-motion`, `lucide-react`, and `react` >= 18.0.0.
|
|
@@ -48,7 +48,7 @@ Note: This package requires `framer-motion`, `lucide-react`, and `react` >= 18.0
|
|
|
48
48
|
### Basic Example
|
|
49
49
|
|
|
50
50
|
```jsx
|
|
51
|
-
import { OnyxMobileLayout } from "@
|
|
51
|
+
import { OnyxMobileLayout } from "@kawaiininja/layouts";
|
|
52
52
|
import { Home, Search, Bell, User, PenTool, Grid } from "lucide-react";
|
|
53
53
|
|
|
54
54
|
const MyApp = () => {
|
package/dist/MobileLayout.js
CHANGED
|
@@ -103,17 +103,43 @@ function useRailNavScroll(active, navKeys) {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
// --- Main Layout Component ---
|
|
106
|
-
const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh, isRefreshing: externalRefreshing, rightAction, initialTab = "home", drawerItems = [], }) => {
|
|
107
|
-
const [
|
|
106
|
+
const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh, isRefreshing: externalRefreshing, rightAction, initialTab = "home", activeTab: externalActiveTab, activeSubTab: externalActiveSubTab, onNavigate, drawerItems = [], }) => {
|
|
107
|
+
const [internalActiveTab, setInternalActiveTab] = useState(initialTab);
|
|
108
|
+
const activeTab = externalActiveTab || internalActiveTab;
|
|
108
109
|
const [isOpen, setIsOpen] = useState(false);
|
|
109
110
|
const [isDragging, setIsDragging] = useState(false);
|
|
110
111
|
const [activeDrawer, setActiveDrawer] = useState(null);
|
|
111
112
|
const [pullY, setPullY] = useState(0);
|
|
112
113
|
const [internalRefreshing, setInternalRefreshing] = useState(false);
|
|
113
114
|
const currentTabConfig = tabs.find((t) => t.id === activeTab);
|
|
114
|
-
const isRefreshing = currentTabConfig?.isRefreshing ?? externalRefreshing ?? internalRefreshing;
|
|
115
115
|
const subTabs = currentTabConfig?.subTabs || [];
|
|
116
|
-
const [
|
|
116
|
+
const [internalSubTab, setInternalSubTab] = useState(subTabs[0]?.label || "");
|
|
117
|
+
const subTab = externalActiveSubTab || internalSubTab;
|
|
118
|
+
const navigateTo = (tabId, subTabLabel) => {
|
|
119
|
+
if (tabId)
|
|
120
|
+
setInternalActiveTab(tabId);
|
|
121
|
+
if (subTabLabel)
|
|
122
|
+
setInternalSubTab(subTabLabel);
|
|
123
|
+
if (onNavigate) {
|
|
124
|
+
const targetTab = tabs.find((t) => t.id === (tabId || activeTab));
|
|
125
|
+
let path = targetTab?.path || "";
|
|
126
|
+
if (subTabLabel) {
|
|
127
|
+
const st = targetTab?.subTabs.find((s) => s.label === subTabLabel);
|
|
128
|
+
if (st?.path) {
|
|
129
|
+
if (st.path.startsWith("/")) {
|
|
130
|
+
path = st.path;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const base = path.endsWith("/") ? path : path + "/";
|
|
134
|
+
path = base + st.path;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (path)
|
|
139
|
+
onNavigate(path);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const isRefreshing = currentTabConfig?.isRefreshing ?? externalRefreshing ?? internalRefreshing;
|
|
117
143
|
const navKeys = useMemo(() => tabs.map((t) => t.id), [tabs]);
|
|
118
144
|
const { scrollContainerRef, activeHeight, activeOffset, registerButtonRef } = useRailNavScroll(activeTab, navKeys);
|
|
119
145
|
const DRAWER_WIDTH = 220;
|
|
@@ -165,8 +191,8 @@ const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh,
|
|
|
165
191
|
useEffect(() => {
|
|
166
192
|
if (currentTabConfig && currentTabConfig.subTabs.length > 0) {
|
|
167
193
|
const isValid = currentTabConfig.subTabs.some((st) => st.label === subTab);
|
|
168
|
-
if (!isValid)
|
|
169
|
-
|
|
194
|
+
if (!isValid && currentTabConfig.subTabs.length > 0)
|
|
195
|
+
navigateTo(undefined, currentTabConfig.subTabs[0].label);
|
|
170
196
|
}
|
|
171
197
|
}, [activeTab, tabs, subTab, currentTabConfig]);
|
|
172
198
|
const [[prevActive, direction], setDir] = useState([activeTab, 0]);
|
|
@@ -210,10 +236,7 @@ const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh,
|
|
|
210
236
|
targetTab: tabs[0].id,
|
|
211
237
|
targetSubTab: st.label,
|
|
212
238
|
}))).map((item) => (_jsxs("button", { onClick: () => {
|
|
213
|
-
|
|
214
|
-
setActiveTab(item.targetTab);
|
|
215
|
-
if (item.targetSubTab)
|
|
216
|
-
setSubTab(item.targetSubTab);
|
|
239
|
+
navigateTo(item.targetTab, item.targetSubTab);
|
|
217
240
|
if (item.onClick)
|
|
218
241
|
item.onClick({
|
|
219
242
|
openDrawer: (id) => setActiveDrawer(id),
|
|
@@ -280,9 +303,9 @@ const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh,
|
|
|
280
303
|
if (Math.abs(lastDxRef.current) > 50) {
|
|
281
304
|
const idx = subTabs.findIndex((t) => t.label === subTab);
|
|
282
305
|
if (lastDxRef.current < 0 && idx < subTabs.length - 1)
|
|
283
|
-
|
|
306
|
+
navigateTo(undefined, subTabs[idx + 1].label);
|
|
284
307
|
else if (lastDxRef.current > 0 && idx > 0)
|
|
285
|
-
|
|
308
|
+
navigateTo(undefined, subTabs[idx - 1].label);
|
|
286
309
|
}
|
|
287
310
|
}
|
|
288
311
|
if (isVerticalPull.current) {
|
|
@@ -365,7 +388,7 @@ const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh,
|
|
|
365
388
|
setQuickMenu((prev) => ({ ...prev, visible: false, selectedIndex: -1 }));
|
|
366
389
|
}
|
|
367
390
|
else {
|
|
368
|
-
|
|
391
|
+
navigateTo(tabId);
|
|
369
392
|
}
|
|
370
393
|
};
|
|
371
394
|
const currentTranslate = isDragging ? renderDragX : isOpen ? DRAWER_WIDTH : 0;
|
|
@@ -377,7 +400,7 @@ const OnyxMobileLayoutBase = ({ tabs, user, drawers = {}, onSignOut, onRefresh,
|
|
|
377
400
|
? "none"
|
|
378
401
|
: "transform 0.3s cubic-bezier(0.32, 0.72, 0, 1), border-radius 0.3s",
|
|
379
402
|
overflow: "hidden",
|
|
380
|
-
}, children: [isOpen && !isDragging && (_jsx("div", { className: "absolute inset-0 z-50 bg-black/20", onClick: () => setIsOpen(false) })), _jsxs("div", { className: "flex-1 flex flex-col h-full mr-12 relative bg-[rgb(var(--bg-main))]", children: [_jsx(Header, { title: currentTabConfig?.navTitle || currentTabConfig?.label || "App", onMenuClick: () => setIsOpen(!isOpen), rightAction: currentTabConfig?.rightAction || rightAction }), _jsx(HorizontalTabs, { tabs: subTabs, active: subTab, onChange:
|
|
403
|
+
}, children: [isOpen && !isDragging && (_jsx("div", { className: "absolute inset-0 z-50 bg-black/20", onClick: () => setIsOpen(false) })), _jsxs("div", { className: "flex-1 flex flex-col h-full mr-12 relative bg-[rgb(var(--bg-main))]", children: [_jsx(Header, { title: currentTabConfig?.navTitle || currentTabConfig?.label || "App", onMenuClick: () => setIsOpen(!isOpen), rightAction: currentTabConfig?.rightAction || rightAction }), _jsx(HorizontalTabs, { tabs: subTabs, active: subTab, onChange: (label) => navigateTo(undefined, label) }), _jsxs("main", { ref: mainScrollRef, className: "flex-1 overflow-y-auto no-scrollbar overscroll-contain relative mr-4", children: [_jsx("div", { className: "absolute top-0 left-0 right-0 flex justify-center items-center pointer-events-none z-0", style: {
|
|
381
404
|
height: `${pullY}px`,
|
|
382
405
|
opacity: Math.min(pullY / 40, 1),
|
|
383
406
|
}, children: _jsx("div", { className: `p-2 bg-[rgb(var(--bg-surface))] rounded-full shadow-md border border-[rgb(var(--color-border-subtle))] ${isRefreshing
|
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export interface SubTabConfig {
|
|
|
3
3
|
label: string;
|
|
4
4
|
icon: ComponentType<any>;
|
|
5
5
|
view: ComponentType<any>;
|
|
6
|
+
path?: string;
|
|
6
7
|
}
|
|
7
8
|
export interface QuickActionConfig {
|
|
8
9
|
label: string;
|
|
@@ -16,6 +17,7 @@ export interface TabConfig {
|
|
|
16
17
|
label: string;
|
|
17
18
|
icon: ComponentType<any>;
|
|
18
19
|
navTitle?: string;
|
|
20
|
+
path?: string;
|
|
19
21
|
subTabs: SubTabConfig[];
|
|
20
22
|
quickActions: QuickActionConfig[];
|
|
21
23
|
rightAction?: ReactNode;
|
|
@@ -50,5 +52,8 @@ export interface OnyxMobileLayoutProps {
|
|
|
50
52
|
isRefreshing?: boolean;
|
|
51
53
|
rightAction?: ReactNode;
|
|
52
54
|
initialTab?: string;
|
|
55
|
+
activeTab?: string;
|
|
56
|
+
activeSubTab?: string;
|
|
57
|
+
onNavigate?: (path: string) => void;
|
|
53
58
|
drawerItems?: DrawerItemConfig[];
|
|
54
59
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kawaiininja/layouts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "High-performance, premium mobile-first layouts for the Onyx Framework, featuring gesture-driven navigation, radial quick actions, and integrated theme support.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/
|
|
29
|
+
"url": "https://github.com/4kawaiininja/onyx-framework.git",
|
|
30
30
|
"directory": "layouts"
|
|
31
31
|
},
|
|
32
32
|
"bugs": {
|
|
33
|
-
"url": "https://github.com/
|
|
33
|
+
"url": "https://github.com/4kawaiininja/onyx-framework/issues"
|
|
34
34
|
},
|
|
35
|
-
"homepage": "https://github.com/
|
|
35
|
+
"homepage": "https://github.com/4kawaiininja/onyx-framework/blob/main/layouts/README.md",
|
|
36
36
|
"exports": {
|
|
37
37
|
".": {
|
|
38
38
|
"types": "./dist/index.d.ts",
|