@12-apps/ui 6.74.1 → 6.74.2
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/NATIVE.md +1 -1
- package/dist/native/layout/Screen.js +4 -1
- package/dist/native/layout/Screen.js.map +1 -1
- package/dist/types-native/components/layout/Screen/Screen.native.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/layout/Screen/Screen.md +3 -1
- package/src/components/layout/Screen/Screen.native.tsx +11 -1
package/NATIVE.md
CHANGED
|
@@ -113,5 +113,5 @@ Ported: **28 of 149** public subpaths carry a `react-native` condition.
|
|
|
113
113
|
| `@12-apps/ui/typography/Heading` | 26 | 1 | `gradient` paints the gradient's first stop as a flat colour: React Native has no `background-clip: text` and no gradient fill in core. A host wanting the real thing adds a masked-gradient library. |
|
|
114
114
|
| `@12-apps/ui/typography/Paragraph` | 17 | 1 | — |
|
|
115
115
|
| `@12-apps/ui/typography/Text` | 26 | 3 | — |
|
|
116
|
-
| `@12-apps/ui/layout/Screen` |
|
|
116
|
+
| `@12-apps/ui/layout/Screen` | 11 | 0 | Keyboard geometry uses React Native KeyboardAvoidingView; react-native-web unit/story lanes verify its wiring, not a real Android/iOS keyboard. Device keyboard/rotation QA remains explicit.; Web safe-area values come from CSS environment variables; native values come from the existing navigator or an internal safe-area provider. Browser keyboard resizing remains browser-managed. |
|
|
117
117
|
<!-- native-parity:end -->
|
|
@@ -25,6 +25,9 @@ function keyboardBehavior(enabled) {
|
|
|
25
25
|
if (!enabled) return void 0;
|
|
26
26
|
return Platform.OS === "ios" ? "padding" : "height";
|
|
27
27
|
}
|
|
28
|
+
function keyboardDismissMode() {
|
|
29
|
+
return Platform.OS === "web" ? "none" : "on-drag";
|
|
30
|
+
}
|
|
28
31
|
function ScreenBoundary({ children }) {
|
|
29
32
|
const insets = React.useContext(SafeAreaInsetsContext);
|
|
30
33
|
return insets === null ? /* @__PURE__ */ jsx(SafeAreaProvider, { style: styles.fill, children }) : /* @__PURE__ */ jsx(Fragment, { children });
|
|
@@ -56,7 +59,7 @@ var Screen = React.forwardRef(({
|
|
|
56
59
|
ScrollView,
|
|
57
60
|
{
|
|
58
61
|
keyboardShouldPersistTaps: "handled",
|
|
59
|
-
keyboardDismissMode:
|
|
62
|
+
keyboardDismissMode: keyboardDismissMode(),
|
|
60
63
|
...scrollViewProps,
|
|
61
64
|
testID: scrollViewProps?.testID ?? (testID ? `${testID}-viewport` : void 0),
|
|
62
65
|
style: styles.fill,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/layout/Screen/Screen.native.tsx","../../../src/components/layout/Screen/Screen.base.ts"],"sourcesContent":["import * as React from 'react';\nimport { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, View } from 'react-native';\nimport { SafeAreaInsetsContext, SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';\n\nimport { SCREEN_EDGES } from './Screen.base';\nimport type { ScreenProps } from './Screen.types.native';\nimport { resolveBoxLayout, splitBoxProps } from '../Box/box-layout';\nimport { resolveTestId } from '../../../platform/test-id';\nimport { useUiTheme } from '../../../provider/use-ui-theme.native';\n\nconst styles = StyleSheet.create({ fill: { flex: 1 }, content: { flexGrow: 1 } });\n\nfunction keyboardBehavior(enabled: boolean): 'padding' | 'height' | undefined {\n if (!enabled) return undefined;\n return Platform.OS === 'ios' ? 'padding' : 'height';\n}\n\n/** Reuse a navigator's context, or own one outside the scrolling view. */\nfunction ScreenBoundary({ children }: { children: React.ReactNode }): React.JSX.Element {\n const insets = React.useContext(SafeAreaInsetsContext);\n return insets === null\n ? <SafeAreaProvider style={styles.fill}>{children}</SafeAreaProvider>\n : <>{children}</>;\n}\n\nexport const Screen = React.forwardRef<View, ScreenProps>(({\n children, scroll = true, safeAreaEdges = SCREEN_EDGES,\n keyboardAvoiding = true, keyboardVerticalOffset = 0, bg = 'default',\n style, contentContainerStyle, scrollViewProps, ...props\n}, ref) => {\n const theme = useUiTheme();\n const { layout, rest } = splitBoxProps(props);\n const testID = resolveTestId(layout);\n const contentStyle = [styles.content, resolveBoxLayout({ ...layout, direction: 'column' }, theme), contentContainerStyle];\n return (\n <ScreenBoundary>\n <View ref={ref} testID={testID} {...rest} style={[styles.fill, resolveBoxLayout({ bg }, theme), style]}>\n <SafeAreaView edges={safeAreaEdges} style={styles.fill}>\n <KeyboardAvoidingView style={styles.fill} enabled={keyboardAvoiding}\n behavior={keyboardBehavior(keyboardAvoiding)} keyboardVerticalOffset={keyboardVerticalOffset}>\n {scroll ? (\n <ScrollView keyboardShouldPersistTaps=\"handled\" keyboardDismissMode
|
|
1
|
+
{"version":3,"sources":["../../../src/components/layout/Screen/Screen.native.tsx","../../../src/components/layout/Screen/Screen.base.ts"],"sourcesContent":["import * as React from 'react';\nimport { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, View } from 'react-native';\nimport { SafeAreaInsetsContext, SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';\n\nimport { SCREEN_EDGES } from './Screen.base';\nimport type { ScreenProps } from './Screen.types.native';\nimport { resolveBoxLayout, splitBoxProps } from '../Box/box-layout';\nimport { resolveTestId } from '../../../platform/test-id';\nimport { useUiTheme } from '../../../provider/use-ui-theme.native';\n\nconst styles = StyleSheet.create({ fill: { flex: 1 }, content: { flexGrow: 1 } });\n\nfunction keyboardBehavior(enabled: boolean): 'padding' | 'height' | undefined {\n if (!enabled) return undefined;\n return Platform.OS === 'ios' ? 'padding' : 'height';\n}\n\n/**\n * Drag-to-dismiss on a device only. react-native-web runs `dismissKeyboard()`\n * on EVERY scroll event of an `on-drag` ScrollView, including the one the\n * browser fires to bring a just-focused field into view, so on the web the\n * field the user tapped lost focus as soon as the viewport moved.\n */\nfunction keyboardDismissMode(): 'on-drag' | 'none' {\n return Platform.OS === 'web' ? 'none' : 'on-drag';\n}\n\n/** Reuse a navigator's context, or own one outside the scrolling view. */\nfunction ScreenBoundary({ children }: { children: React.ReactNode }): React.JSX.Element {\n const insets = React.useContext(SafeAreaInsetsContext);\n return insets === null\n ? <SafeAreaProvider style={styles.fill}>{children}</SafeAreaProvider>\n : <>{children}</>;\n}\n\nexport const Screen = React.forwardRef<View, ScreenProps>(({\n children, scroll = true, safeAreaEdges = SCREEN_EDGES,\n keyboardAvoiding = true, keyboardVerticalOffset = 0, bg = 'default',\n style, contentContainerStyle, scrollViewProps, ...props\n}, ref) => {\n const theme = useUiTheme();\n const { layout, rest } = splitBoxProps(props);\n const testID = resolveTestId(layout);\n const contentStyle = [styles.content, resolveBoxLayout({ ...layout, direction: 'column' }, theme), contentContainerStyle];\n return (\n <ScreenBoundary>\n <View ref={ref} testID={testID} {...rest} style={[styles.fill, resolveBoxLayout({ bg }, theme), style]}>\n <SafeAreaView edges={safeAreaEdges} style={styles.fill}>\n <KeyboardAvoidingView style={styles.fill} enabled={keyboardAvoiding}\n behavior={keyboardBehavior(keyboardAvoiding)} keyboardVerticalOffset={keyboardVerticalOffset}>\n {scroll ? (\n <ScrollView keyboardShouldPersistTaps=\"handled\" keyboardDismissMode={keyboardDismissMode()} {...scrollViewProps}\n testID={scrollViewProps?.testID ?? (testID ? `${testID}-viewport` : undefined)}\n style={styles.fill} contentContainerStyle={contentStyle}\n horizontal={false} automaticallyAdjustKeyboardInsets={false}\n automaticallyAdjustContentInsets={false} contentInsetAdjustmentBehavior=\"never\">\n {children}\n </ScrollView>\n ) : <View style={[styles.fill, contentStyle]}>{children}</View>}\n </KeyboardAvoidingView>\n </SafeAreaView>\n </View>\n </ScreenBoundary>\n );\n});\nScreen.displayName = 'Screen';\n","import type { BoxBaseProps } from '../Box/Box.base';\n\n/** Physical screen edges, independent of a native dependency. */\nexport type ScreenEdge = 'top' | 'right' | 'bottom' | 'left';\nexport const SCREEN_EDGES: readonly ScreenEdge[] = ['top', 'right', 'bottom', 'left'];\n\n/** Padding and gap apply to the content, inside the selected safe-area edges. */\nexport interface ScreenBaseProps extends Pick<\n BoxBaseProps,\n 'children' | 'p' | 'px' | 'py' | 'pt' | 'pr' | 'pb' | 'pl' | 'gap' | 'bg' | 'testID' | 'dataTestId'\n> {\n /** Vertical scrolling; turn off when a child owns scrolling. Default true. */\n scroll?: boolean;\n /** Omit bottom when a navigator's tab bar already owns that inset. */\n safeAreaEdges?: readonly ScreenEdge[];\n /** Lift the native viewport above the soft keyboard. Default true. */\n keyboardAvoiding?: boolean;\n /** Native distance from the window top to the screen's parent, in dp. */\n keyboardVerticalOffset?: number;\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,YAAY,WAAW;AACvB,SAAS,sBAAsB,UAAU,YAAY,YAAY,YAAY;AAC7E,SAAS,uBAAuB,kBAAkB,oBAAoB;;;ACE/D,IAAM,eAAsC,CAAC,OAAO,SAAS,UAAU,MAAM;;;AD2B9E,SACA,UADA;AArBN,IAAM,SAAS,WAAW,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC;AAEhF,SAAS,iBAAiB,SAAoD;AAC5E,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,SAAS,OAAO,QAAQ,YAAY;AAC7C;AAQA,SAAS,sBAA0C;AACjD,SAAO,SAAS,OAAO,QAAQ,SAAS;AAC1C;AAGA,SAAS,eAAe,EAAE,SAAS,GAAqD;AACtF,QAAM,SAAe,iBAAW,qBAAqB;AACrD,SAAO,WAAW,OACd,oBAAC,oBAAiB,OAAO,OAAO,MAAO,UAAS,IAChD,gCAAG,UAAS;AAClB;AAEO,IAAM,SAAe,iBAA8B,CAAC;AAAA,EACzD;AAAA,EAAU,SAAS;AAAA,EAAM,gBAAgB;AAAA,EACzC,mBAAmB;AAAA,EAAM,yBAAyB;AAAA,EAAG,KAAK;AAAA,EAC1D;AAAA,EAAO;AAAA,EAAuB;AAAA,EAAiB,GAAG;AACpD,GAAG,QAAQ;AACT,QAAM,QAAQ,WAAW;AACzB,QAAM,EAAE,QAAQ,KAAK,IAAI,cAAc,KAAK;AAC5C,QAAM,SAAS,cAAc,MAAM;AACnC,QAAM,eAAe,CAAC,OAAO,SAAS,iBAAiB,EAAE,GAAG,QAAQ,WAAW,SAAS,GAAG,KAAK,GAAG,qBAAqB;AACxH,SACE,oBAAC,kBACC,8BAAC,QAAK,KAAU,QAAiB,GAAG,MAAM,OAAO,CAAC,OAAO,MAAM,iBAAiB,EAAE,GAAG,GAAG,KAAK,GAAG,KAAK,GACnG,8BAAC,gBAAa,OAAO,eAAe,OAAO,OAAO,MAChD;AAAA,IAAC;AAAA;AAAA,MAAqB,OAAO,OAAO;AAAA,MAAM,SAAS;AAAA,MACjD,UAAU,iBAAiB,gBAAgB;AAAA,MAAG;AAAA,MAC7C,mBACC;AAAA,QAAC;AAAA;AAAA,UAAW,2BAA0B;AAAA,UAAU,qBAAqB,oBAAoB;AAAA,UAAI,GAAG;AAAA,UAC9F,QAAQ,iBAAiB,WAAW,SAAS,GAAG,MAAM,cAAc;AAAA,UACpE,OAAO,OAAO;AAAA,UAAM,uBAAuB;AAAA,UAC3C,YAAY;AAAA,UAAO,mCAAmC;AAAA,UACtD,kCAAkC;AAAA,UAAO,gCAA+B;AAAA,UACvE;AAAA;AAAA,MACH,IACE,oBAAC,QAAK,OAAO,CAAC,OAAO,MAAM,YAAY,GAAI,UAAS;AAAA;AAAA,EAC1D,GACF,GACF,GACF;AAEJ,CAAC;AACD,OAAO,cAAc;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Screen.native.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/Screen/Screen.native.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA0D,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Screen.native.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/Screen/Screen.native.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA0D,IAAI,EAAE,MAAM,cAAc,CAAC;AAkC5F,eAAO,MAAM,MAAM;;;8BA6BjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -45,7 +45,9 @@ on iOS and height on Android. Its measured viewport already excludes the bottom
|
|
|
45
45
|
safe area, so the home-indicator inset is not added again above the keyboard.
|
|
46
46
|
ScrollView automatic keyboard and content insets are off so those owners do not
|
|
47
47
|
also apply the same lift/insets. Handled child taps remain usable with the
|
|
48
|
-
keyboard open; dragging dismisses it.
|
|
48
|
+
keyboard open; on a device, dragging dismisses it. On the web nothing is dismissed
|
|
49
|
+
on scroll: react-native-web would blur the focused field on every scroll event,
|
|
50
|
+
including the browser's own scroll to a just-focused field. `scrollViewProps` can change tap/dismiss
|
|
49
51
|
policy, but cannot override the viewport geometry or automatic inset ownership.
|
|
50
52
|
|
|
51
53
|
## Layout and accessibility
|
|
@@ -15,6 +15,16 @@ function keyboardBehavior(enabled: boolean): 'padding' | 'height' | undefined {
|
|
|
15
15
|
return Platform.OS === 'ios' ? 'padding' : 'height';
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Drag-to-dismiss on a device only. react-native-web runs `dismissKeyboard()`
|
|
20
|
+
* on EVERY scroll event of an `on-drag` ScrollView, including the one the
|
|
21
|
+
* browser fires to bring a just-focused field into view, so on the web the
|
|
22
|
+
* field the user tapped lost focus as soon as the viewport moved.
|
|
23
|
+
*/
|
|
24
|
+
function keyboardDismissMode(): 'on-drag' | 'none' {
|
|
25
|
+
return Platform.OS === 'web' ? 'none' : 'on-drag';
|
|
26
|
+
}
|
|
27
|
+
|
|
18
28
|
/** Reuse a navigator's context, or own one outside the scrolling view. */
|
|
19
29
|
function ScreenBoundary({ children }: { children: React.ReactNode }): React.JSX.Element {
|
|
20
30
|
const insets = React.useContext(SafeAreaInsetsContext);
|
|
@@ -39,7 +49,7 @@ export const Screen = React.forwardRef<View, ScreenProps>(({
|
|
|
39
49
|
<KeyboardAvoidingView style={styles.fill} enabled={keyboardAvoiding}
|
|
40
50
|
behavior={keyboardBehavior(keyboardAvoiding)} keyboardVerticalOffset={keyboardVerticalOffset}>
|
|
41
51
|
{scroll ? (
|
|
42
|
-
<ScrollView keyboardShouldPersistTaps="handled" keyboardDismissMode=
|
|
52
|
+
<ScrollView keyboardShouldPersistTaps="handled" keyboardDismissMode={keyboardDismissMode()} {...scrollViewProps}
|
|
43
53
|
testID={scrollViewProps?.testID ?? (testID ? `${testID}-viewport` : undefined)}
|
|
44
54
|
style={styles.fill} contentContainerStyle={contentStyle}
|
|
45
55
|
horizontal={false} automaticallyAdjustKeyboardInsets={false}
|