@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.
@@ -1,16 +1,10 @@
1
1
  {
2
- "version": "1.2.92",
2
+ "version": "1.2.93",
3
3
  "rc": 1,
4
- "branch": "rc/1.2.92-rc.1",
5
- "baseMaster": "03e8ae44638497cb992d2c6e6d00c898abb24cde",
6
- "tasks": [77, 1051],
7
- "repositories": {
8
- "ControleOnline/ui-common": "e500e5f96b022f7a626824683ae1f2bd3bd63471"
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@controleonline/ui-common",
3
- "version": "1.2.92",
3
+ "version": "1.2.94",
4
4
  "author": "ControleOnline",
5
5
  "description": "ControleOnline Common Quasar UI Component",
6
6
  "license": "MIT",
@@ -1,10 +1,13 @@
1
1
  import React, {useLayoutEffect, useMemo} from 'react';
2
2
  import {Pressable, Text, View} from 'react-native';
3
- import Icon from 'react-native-vector-icons/Feather';
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: runtimeFooter?.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,
@@ -0,0 +1,5 @@
1
+ // Keep the native safe area outside the centered content row.
2
+ export default (appearance, platform, bottomInset) => appearance === 'soft' ? {
3
+ contentPadding: 4,
4
+ safeAreaBottom: platform === 'web' ? 0 : Math.max(Number(bottomInset) || 0, 0),
5
+ } : null;
@@ -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={{uri: displayUri}}
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);