@tamer4lynx/tamer-app-shell 0.0.1 → 0.0.3
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/src/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import './app-shell.css';
|
|
2
|
-
import {
|
|
2
|
+
import type { IconSet } from '@tamer4lynx/tamer-icons';
|
|
3
|
+
import '@tamer4lynx/tamer-icons';
|
|
3
4
|
import type { ReactNode } from '@lynx-js/react';
|
|
4
5
|
import type { ViewProps } from '@lynx-js/types';
|
|
5
6
|
export { Screen, SafeArea, useSafeAreaContext } from '@tamer4lynx/tamer-screen';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,iBAAiB,CAAA;AAKxB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "@lynx-js/react/jsx-runtime";
|
|
2
1
|
/// <reference types="@lynx-js/react" />
|
|
3
2
|
import './app-shell.css';
|
|
4
3
|
import { createContext, useCallback, useContext, useState } from '@lynx-js/react';
|
|
5
4
|
import { useLocation } from 'react-router';
|
|
6
5
|
import { useInsets, useKeyboard } from '@tamer4lynx/tamer-insets';
|
|
7
6
|
import { useSafeAreaContext } from '@tamer4lynx/tamer-screen';
|
|
8
|
-
import
|
|
7
|
+
import '@tamer4lynx/tamer-icons';
|
|
9
8
|
export { Screen, SafeArea, useSafeAreaContext } from '@tamer4lynx/tamer-screen';
|
|
10
9
|
export const AppShellRouterContext = createContext(null);
|
|
11
10
|
export function useAppShellRouter() {
|
|
@@ -21,12 +20,15 @@ const ACTION_SIZE = 48;
|
|
|
21
20
|
const ACTION_ICON_SIZE = 32;
|
|
22
21
|
function ActionButton({ action, color = '#fff' }) {
|
|
23
22
|
const [pressed, setPressed] = useState(false);
|
|
24
|
-
return (
|
|
23
|
+
return (<view className={`AppShellActionButton${pressed ? ' AppShellActionButton--pressed' : ''}`} style={{
|
|
25
24
|
width: px(ACTION_SIZE),
|
|
26
25
|
height: px(ACTION_SIZE),
|
|
27
26
|
borderRadius: px(ACTION_SIZE / 2),
|
|
28
27
|
overflow: 'hidden',
|
|
29
|
-
}
|
|
28
|
+
}} bindtap={action.onTap} bindtouchstart={() => setPressed(true)} bindtouchend={() => setPressed(false)} bindtouchcancel={() => setPressed(false)}>
|
|
29
|
+
<icon icon={action.icon} set={action.set ?? 'material'} size={ACTION_ICON_SIZE} iconColor={color} style={{ width: px(ACTION_ICON_SIZE), height: px(ACTION_ICON_SIZE) }}/>
|
|
30
|
+
<view className="AppShellActionButton-ripple"/>
|
|
31
|
+
</view>);
|
|
30
32
|
}
|
|
31
33
|
export function AppBar({ title, barHeight = DEFAULT_BAR_HEIGHT, leftAction, rightActions = [], foregroundColor = '#fff', actionColor, style, children, ...rest }) {
|
|
32
34
|
const insets = useInsets();
|
|
@@ -38,10 +40,12 @@ export function AppBar({ title, barHeight = DEFAULT_BAR_HEIGHT, leftAction, righ
|
|
|
38
40
|
const resolvedTitleColor = foregroundColor;
|
|
39
41
|
const resolvedActionColor = actionColor ?? foregroundColor;
|
|
40
42
|
const showDefaultBack = leftAction === undefined && canGoBack();
|
|
41
|
-
const left = leftAction === false ? null : leftAction ? (
|
|
42
|
-
const right = rightActions.length > 0 ? (
|
|
43
|
+
const left = leftAction === false ? null : leftAction ? (<ActionButton action={leftAction} color={resolvedActionColor}/>) : showDefaultBack ? (<ActionButton action={{ icon: 'arrow_back', onTap: back }} color={resolvedActionColor}/>) : null;
|
|
44
|
+
const right = rightActions.length > 0 ? (<view style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
|
45
|
+
{rightActions.map((action, i) => (<ActionButton key={i} action={action} color={resolvedActionColor}/>))}
|
|
46
|
+
</view>) : null;
|
|
43
47
|
const effectiveBarHeight = isSafeAreaChild ? DEFAULT_BAR_HEIGHT + insets.top : barHeight;
|
|
44
|
-
return (
|
|
48
|
+
return (<view style={{
|
|
45
49
|
height: px(effectiveBarHeight),
|
|
46
50
|
...(isSafeAreaChild ? { marginTop: `-${Math.round(insets.top)}px`, paddingTop: px(insets.top) } : {}),
|
|
47
51
|
paddingLeft: '16px',
|
|
@@ -54,13 +58,24 @@ export function AppBar({ title, barHeight = DEFAULT_BAR_HEIGHT, leftAction, righ
|
|
|
54
58
|
borderBottomWidth: '1px',
|
|
55
59
|
borderBottomColor: '#e0e0e0',
|
|
56
60
|
...(style ?? {}),
|
|
57
|
-
}
|
|
61
|
+
}} {...rest}>
|
|
62
|
+
<view style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', minWidth: px(ACTION_SIZE) }}>
|
|
63
|
+
{left}
|
|
64
|
+
</view>
|
|
65
|
+
{children ?? (title ? <text style={{ display: 'block', width: '100%', fontWeight: 'bold', fontSize: px(18), textAlign: 'center', color: resolvedTitleColor }}>{title}</text> : <view style={{ flex: 1 }}/>)}
|
|
66
|
+
<view style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', minWidth: px(ACTION_SIZE), justifyContent: 'flex-end' }}>
|
|
67
|
+
{right}
|
|
68
|
+
</view>
|
|
69
|
+
</view>);
|
|
58
70
|
}
|
|
59
71
|
const DEFAULT_ICON_COLOR = { active: '#FFF', inactive: '#000' };
|
|
60
72
|
function TabBarItem({ item, isActive, onTap, iconColor = DEFAULT_ICON_COLOR, }) {
|
|
61
73
|
const [pressed, setPressed] = useState(false);
|
|
62
74
|
const iconC = isActive ? (iconColor.active ?? DEFAULT_ICON_COLOR.active) : (iconColor.inactive ?? DEFAULT_ICON_COLOR.inactive);
|
|
63
|
-
return (
|
|
75
|
+
return (<view className={`AppShellTabItem${pressed ? ' AppShellTabItem--pressed' : ''}`} style={{ opacity: isActive ? 1 : 0.6 }} bindtap={onTap} bindtouchstart={() => setPressed(true)} bindtouchend={() => setPressed(false)} bindtouchcancel={() => setPressed(false)}>
|
|
76
|
+
<icon icon={item.icon} set={item.set ?? 'material'} size={24} iconColor={iconC} style={{ width: px(24), height: px(24) }}/>
|
|
77
|
+
{item.label ? (<text style={{ marginTop: px(4), color: iconC }}>{item.label}</text>) : null}
|
|
78
|
+
</view>);
|
|
64
79
|
}
|
|
65
80
|
export function TabBar({ tabs, iconColor, style, ...rest }) {
|
|
66
81
|
const insets = useInsets();
|
|
@@ -87,7 +102,7 @@ export function TabBar({ tabs, iconColor, style, ...rest }) {
|
|
|
87
102
|
return;
|
|
88
103
|
replace(item.path, { tab: true });
|
|
89
104
|
}, [replace, tabs, location.pathname]);
|
|
90
|
-
return (
|
|
105
|
+
return (<view style={{
|
|
91
106
|
...(isSafeAreaChild ? { marginBottom: `-${Math.round(insets.bottom)}px` } : {}),
|
|
92
107
|
flexDirection: 'row',
|
|
93
108
|
paddingLeft: px(8),
|
|
@@ -98,14 +113,16 @@ export function TabBar({ tabs, iconColor, style, ...rest }) {
|
|
|
98
113
|
borderTopColor: '#e0e0e0',
|
|
99
114
|
...keyboard.visible ? { position: 'absolute', display: 'block', overflow: 'hidden', maxHeight: '0px', height: '0px', paddingBottom: '0px', paddingTop: '0px', bottom: '-50px' } : { display: 'flex', paddingBottom: px(insets.bottom), paddingTop: px(12) },
|
|
100
115
|
...(style ?? {}),
|
|
101
|
-
}
|
|
116
|
+
}} {...rest}>
|
|
117
|
+
{tabs.map((item, i) => {
|
|
102
118
|
const pathname = location.pathname || '/';
|
|
103
119
|
const p = item.path || '/';
|
|
104
120
|
const isActive = item.path
|
|
105
121
|
? p === '/' ? pathname === '/' || pathname === '' : pathname === p || pathname.startsWith(p + '/')
|
|
106
122
|
: false;
|
|
107
|
-
return (
|
|
108
|
-
})
|
|
123
|
+
return (<TabBarItem key={i} item={item} isActive={isActive} onTap={() => handleTap(item)} iconColor={iconColor}/>);
|
|
124
|
+
})}
|
|
125
|
+
</view>);
|
|
109
126
|
}
|
|
110
127
|
export function Content({ children, style, ...rest }) {
|
|
111
128
|
const scrollStyle = {
|
|
@@ -118,9 +135,13 @@ export function Content({ children, style, ...rest }) {
|
|
|
118
135
|
height: '100%',
|
|
119
136
|
...(style ?? {}),
|
|
120
137
|
};
|
|
121
|
-
return (
|
|
138
|
+
return (<view style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
|
|
139
|
+
<scroll-view scroll-y style={scrollStyle} {...rest}>
|
|
140
|
+
{children}
|
|
141
|
+
</scroll-view>
|
|
142
|
+
</view>);
|
|
122
143
|
}
|
|
123
144
|
export function AppShellProvider({ children, showAppBar = true, showTabBar = false, barHeight = DEFAULT_BAR_HEIGHT, }) {
|
|
124
145
|
const value = { showAppBar, showTabBar, barHeight };
|
|
125
|
-
return
|
|
146
|
+
return <AppShellContext.Provider value={value}>{children}</AppShellContext.Provider>;
|
|
126
147
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamer4lynx/tamer-app-shell",
|
|
3
3
|
"publishConfig": { "access": "public", "tag": "prerelease" },
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "App chrome: AppBar, TabBar, and Content layout for Lynx.",
|
|
7
|
-
"main": "dist/src/index.
|
|
7
|
+
"main": "dist/src/index.jsx",
|
|
8
8
|
"types": "dist/src/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/src/index.d.ts",
|
|
12
|
-
"import": "./dist/src/index.
|
|
13
|
-
"default": "./dist/src/index.
|
|
12
|
+
"import": "./dist/src/index.jsx",
|
|
13
|
+
"default": "./dist/src/index.jsx"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
@@ -22,16 +22,14 @@
|
|
|
22
22
|
"react-router": "^6.0.0"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
|
-
"build": "tsc && cp src/app-shell.css dist/src/app-shell.css"
|
|
25
|
+
"build": "rm -rf dist && tsc && cp src/app-shell.css dist/src/app-shell.css"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@tamer4lynx/tamer-icons": "^0.0.
|
|
28
|
+
"@tamer4lynx/tamer-icons": "^0.0.5",
|
|
29
29
|
"@tamer4lynx/tamer-insets": "^0.0.1",
|
|
30
|
-
"@tamer4lynx/tamer-screen": "^0.0.
|
|
30
|
+
"@tamer4lynx/tamer-screen": "^0.0.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@lynx-js/react": "^0.112.1",
|
|
34
|
-
"@lynx-js/types": "3.3.0",
|
|
35
33
|
"@types/react": "^17.0.0",
|
|
36
34
|
"react": "^17.0.2",
|
|
37
35
|
"react-router": "^6.28.0",
|