@controleonline/ui-common 1.2.92 → 1.2.94
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/.release/rc-manifest.json +6 -12
- package/docs/homepage-1056.md +6 -0
- package/package.json +1 -1
- package/src/react/components/BottomNavigationBar.js +14 -4
- package/src/react/components/BottomNavigationBar.soft.styles.js +28 -0
- package/src/react/components/RuntimeBottomNavigationBar.js +2 -0
- package/src/react/components/RuntimeFooterMarqueeText.js +3 -0
- package/src/react/components/RuntimeInfoFooter.home.spacing.js +5 -0
- package/src/react/components/RuntimeInfoFooter.js +8 -2
- package/src/react/components/UserAvatar.js +3 -1
- package/src/tests/react/components/RuntimeFooterMarqueeText.test.js +2 -0
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.2.
|
|
2
|
+
"version": "1.2.93",
|
|
3
3
|
"rc": 1,
|
|
4
|
-
"branch": "rc/1.2.
|
|
5
|
-
"baseMaster": "
|
|
6
|
-
"tasks": [77
|
|
7
|
-
"repositories": {
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
"compositionNotes": [
|
|
11
|
-
"ui-common#77 (footer device info width 0 on Android) and app-community#1051 (zoom < 100 leaves screen detached from bottom).",
|
|
12
|
-
"Base is staging 03e8ae4 (= npm ui-common 1.2.91 consumed by app-community master); ui-common master is behind (1.2.87).",
|
|
13
|
-
"Individual task commits 19683a9 and 9e3a93b merged with --no-ff; no other dev content."
|
|
14
|
-
],
|
|
4
|
+
"branch": "rc/1.2.93-rc.1",
|
|
5
|
+
"baseMaster": "b4db94eb1ccd3bf878dc96e3d32c0249aad07402",
|
|
6
|
+
"tasks": [77],
|
|
7
|
+
"repositories": { "ControleOnline/ui-common": "4dfdb2d7ccb160f265115bdad3125d6ecd26bdfd" },
|
|
8
|
+
"compositionNotes": ["Verified on Android emulator: Text width was still 0 with flexBasis auto because Yoga prioritises flex over flexGrow/flexBasis. flex:0 fixes it."],
|
|
15
9
|
"frozen": true
|
|
16
10
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Homepage ADMIN/MANAGER — app-community#1056
|
|
2
|
+
|
|
3
|
+
Soft appearance is opt-in for HomePage only. Existing menu routes/parameters, permissions, stores and translations are preserved. App-provided homepage colors and components are used only in this appearance. Default consumers retain their current behavior.
|
|
4
|
+
|
|
5
|
+
Source: https://github.com/ControleOnline/app-community/issues/1056
|
|
6
|
+
Local evidence: 40 homepage tests and 34 runtime footer/zoom tests passed. No production authorization.
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import React, {useLayoutEffect, useMemo} from 'react';
|
|
2
2
|
import {Pressable, Text, View} from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import LegacyIcon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import HomeIcon from '@controleonline/../../src/components/HomeIcon';
|
|
4
5
|
import {useTheme} from './DefaultProvider';
|
|
5
6
|
import RuntimeInfoFooter from './RuntimeInfoFooter';
|
|
6
7
|
import {resolveMenuRouteParams} from '../utils/menuNavigation';
|
|
7
8
|
import createStyles from './BottomNavigationBar.styles';
|
|
9
|
+
import softenStyles from './BottomNavigationBar.soft.styles';
|
|
10
|
+
import {resolveHomepagePalette} from '@controleonline/../../src/styles/homepagePalette';
|
|
8
11
|
|
|
9
12
|
const BottomNavigationBar = ({
|
|
10
13
|
navigation,
|
|
@@ -14,7 +17,10 @@ const BottomNavigationBar = ({
|
|
|
14
17
|
colors = {},
|
|
15
18
|
testID = 'bottom-navigation',
|
|
16
19
|
useModernWebChromeProps = false,
|
|
20
|
+
appearance = 'legacy',
|
|
17
21
|
}) => {
|
|
22
|
+
const Icon = appearance === 'soft' ? HomeIcon : LegacyIcon;
|
|
23
|
+
colors = appearance === 'soft' ? resolveHomepagePalette(colors) : colors;
|
|
18
24
|
const theme = useTheme?.() || {};
|
|
19
25
|
const runtimeFooter = theme?.runtimeFooter || null;
|
|
20
26
|
const registerBottomNavigation =
|
|
@@ -31,14 +37,14 @@ const BottomNavigationBar = ({
|
|
|
31
37
|
|
|
32
38
|
const styles = useMemo(
|
|
33
39
|
() =>
|
|
34
|
-
createStyles({
|
|
40
|
+
softenStyles(createStyles({
|
|
35
41
|
activeBackground,
|
|
36
42
|
dockBackground,
|
|
37
43
|
dockBorder,
|
|
38
44
|
dockShadow,
|
|
39
45
|
activeBorder,
|
|
40
46
|
useModernWebChromeProps,
|
|
41
|
-
}),
|
|
47
|
+
}), colors, appearance),
|
|
42
48
|
[
|
|
43
49
|
activeBackground,
|
|
44
50
|
activeBorder,
|
|
@@ -46,6 +52,7 @@ const BottomNavigationBar = ({
|
|
|
46
52
|
dockBorder,
|
|
47
53
|
dockShadow,
|
|
48
54
|
useModernWebChromeProps,
|
|
55
|
+
appearance,
|
|
49
56
|
],
|
|
50
57
|
);
|
|
51
58
|
|
|
@@ -116,8 +123,11 @@ const BottomNavigationBar = ({
|
|
|
116
123
|
? [styles.host, styles.hostPointerEventsBoxNone]
|
|
117
124
|
: styles.host;
|
|
118
125
|
const footerProps = {
|
|
126
|
+
appearance,
|
|
119
127
|
appVersion: runtimeFooter?.appVersion,
|
|
120
|
-
colors:
|
|
128
|
+
colors: appearance === 'soft'
|
|
129
|
+
? {...runtimeFooter?.colors, footerBackground: colors.footerBackground, footerText: colors.footerText}
|
|
130
|
+
: runtimeFooter?.colors || {},
|
|
121
131
|
mainCompany: runtimeFooter?.mainCompany,
|
|
122
132
|
device: runtimeFooter?.device,
|
|
123
133
|
useModernWebChromeProps,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {Platform} from 'react-native';
|
|
2
|
+
|
|
3
|
+
// Only the homepage opts into this chrome; preserve all default navigation styles.
|
|
4
|
+
export default (styles, colors, appearance) => appearance !== 'soft' ? styles : {
|
|
5
|
+
...styles,
|
|
6
|
+
dock: [styles.dock, {
|
|
7
|
+
paddingHorizontal: 0,
|
|
8
|
+
paddingTop: 0,
|
|
9
|
+
paddingBottom: 0,
|
|
10
|
+
borderWidth: 0,
|
|
11
|
+
borderTopWidth: 1,
|
|
12
|
+
borderColor: colors.navigationBorder,
|
|
13
|
+
borderTopLeftRadius: 0,
|
|
14
|
+
borderTopRightRadius: 0,
|
|
15
|
+
elevation: 0,
|
|
16
|
+
shadowOpacity: 0,
|
|
17
|
+
...(Platform.OS === 'web' ? {boxShadow: 'none'} : {}),
|
|
18
|
+
}],
|
|
19
|
+
itemsRow: [styles.itemsRow, {minHeight: 64, paddingHorizontal: 12, paddingVertical: 5}],
|
|
20
|
+
item: [styles.item, {minHeight: 54, borderRadius: 12}],
|
|
21
|
+
itemLabel: [styles.itemLabel, {fontSize: 11, fontWeight: '400'}],
|
|
22
|
+
footerSlot: [styles.footerSlot, {
|
|
23
|
+
borderTopWidth: 1,
|
|
24
|
+
borderColor: colors.navigationBorder,
|
|
25
|
+
paddingHorizontal: 0,
|
|
26
|
+
minHeight: 28,
|
|
27
|
+
}],
|
|
28
|
+
};
|
|
@@ -19,6 +19,7 @@ const {
|
|
|
19
19
|
} = require('@controleonline/ui-common/src/react/utils/bottomNavigationToolbar');
|
|
20
20
|
|
|
21
21
|
const RuntimeBottomNavigationBar = ({
|
|
22
|
+
appearance = 'legacy',
|
|
22
23
|
activeRouteName: activeRouteNameProp,
|
|
23
24
|
colors: colorsOverride,
|
|
24
25
|
disabled: disabledOverride,
|
|
@@ -159,6 +160,7 @@ const RuntimeBottomNavigationBar = ({
|
|
|
159
160
|
|
|
160
161
|
return (
|
|
161
162
|
<BottomNavigationBar
|
|
163
|
+
appearance={appearance}
|
|
162
164
|
activeRouteName={effectiveActiveRoute}
|
|
163
165
|
colors={colors}
|
|
164
166
|
disabled={isDisabled}
|
|
@@ -107,6 +107,9 @@ const RuntimeFooterMarqueeText = props => {
|
|
|
107
107
|
flexGrow: 0,
|
|
108
108
|
// primaryText carries `flex: 1` (flexBasis 0 on native), which collapsed
|
|
109
109
|
// the Text to width 0 inside the row on Android. Force intrinsic sizing.
|
|
110
|
+
// Yoga gives `flex` precedence over flexGrow/flexBasis, so the inherited
|
|
111
|
+
// `flex: 1` must be overridden explicitly or the Text stays at width 0.
|
|
112
|
+
flex: 0,
|
|
110
113
|
flexBasis: 'auto',
|
|
111
114
|
minWidth: 0,
|
|
112
115
|
minHeight: 14,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from '@controleonline/ui-common/src/react/utils/runtimeFooter';
|
|
23
23
|
import styles from './RuntimeInfoFooter.styles';
|
|
24
24
|
import RuntimeFooterMarqueeText from './RuntimeFooterMarqueeText';
|
|
25
|
+
import resolveHomeFooterSpacing from './RuntimeInfoFooter.home.spacing';
|
|
25
26
|
|
|
26
27
|
const ROTATION_INTERVAL_MS = 4000;
|
|
27
28
|
const COMPACT_BREAKPOINT = 720;
|
|
@@ -66,6 +67,7 @@ const RuntimeInfoFooter = ({
|
|
|
66
67
|
device,
|
|
67
68
|
colors,
|
|
68
69
|
useModernWebChromeProps = false,
|
|
70
|
+
appearance = 'legacy',
|
|
69
71
|
}) => {
|
|
70
72
|
const {width} = useWindowDimensions();
|
|
71
73
|
const insets = useSafeAreaInsets();
|
|
@@ -258,6 +260,7 @@ const RuntimeInfoFooter = ({
|
|
|
258
260
|
: inlineText
|
|
259
261
|
) || primaryText || device?.id || '';
|
|
260
262
|
const backgroundColor = colors?.footerBackground;
|
|
263
|
+
const homeSpacing = resolveHomeFooterSpacing(appearance, Platform.OS, insets.bottom);
|
|
261
264
|
const borderColor = colors?.footerBorder;
|
|
262
265
|
const textColor = resolveVisibleFooterTextColor(colors);
|
|
263
266
|
const loadingColor = colors?.footerLink || colors?.primary || textColor;
|
|
@@ -267,7 +270,9 @@ const RuntimeInfoFooter = ({
|
|
|
267
270
|
: styles.shell;
|
|
268
271
|
|
|
269
272
|
return (
|
|
270
|
-
<View {...shellProps} style={shellStyle
|
|
273
|
+
<View {...shellProps} style={[shellStyle, homeSpacing && {
|
|
274
|
+
paddingBottom: homeSpacing.safeAreaBottom, backgroundColor,
|
|
275
|
+
}]}>
|
|
271
276
|
<View
|
|
272
277
|
testID="runtime-info-footer"
|
|
273
278
|
style={[
|
|
@@ -276,7 +281,8 @@ const RuntimeInfoFooter = ({
|
|
|
276
281
|
{
|
|
277
282
|
backgroundColor,
|
|
278
283
|
borderTopColor: borderColor,
|
|
279
|
-
paddingBottom: bottomInset,
|
|
284
|
+
paddingBottom: homeSpacing ? homeSpacing.contentPadding : bottomInset,
|
|
285
|
+
...(homeSpacing && !showDebugInfo ? {paddingTop: homeSpacing.contentPadding} : {}),
|
|
280
286
|
},
|
|
281
287
|
]}>
|
|
282
288
|
<View style={styles.primaryRow}>
|
|
@@ -156,6 +156,7 @@ const useDisplayUri = uri => {
|
|
|
156
156
|
|
|
157
157
|
const UserAvatar = ({
|
|
158
158
|
imageUrl,
|
|
159
|
+
imageHeaders,
|
|
159
160
|
email,
|
|
160
161
|
name,
|
|
161
162
|
size = 40,
|
|
@@ -215,7 +216,8 @@ const UserAvatar = ({
|
|
|
215
216
|
<View style={containerStyle}>
|
|
216
217
|
{displayUri ? (
|
|
217
218
|
<Image
|
|
218
|
-
source={
|
|
219
|
+
source={imageHeaders && Platform.OS !== 'web' && displayUri === imageUrl
|
|
220
|
+
? {uri: displayUri, headers: imageHeaders} : {uri: displayUri}}
|
|
219
221
|
style={styles.image}
|
|
220
222
|
onError={() => setSourceIndex(index => index + 1)}
|
|
221
223
|
/>
|
|
@@ -187,6 +187,8 @@ test('native text keeps intrinsic width even when style carries flex: 1 (android
|
|
|
187
187
|
|
|
188
188
|
const text = tree.root.findAllByType('Text')[0];
|
|
189
189
|
const flat = Object.assign({}, ...[].concat(text.props.style));
|
|
190
|
+
// Yoga gives `flex` precedence: it must not stay at the inherited 1 (width 0 on Android).
|
|
191
|
+
assert.equal(flat.flex, 0);
|
|
190
192
|
assert.equal(flat.flexBasis, 'auto');
|
|
191
193
|
assert.equal(flat.flexGrow, 0);
|
|
192
194
|
assert.equal(flat.flexShrink, 0);
|