From 8fb85a253e2dcbd165940f85fbfa5e4ec11b53f6 Mon Sep 17 00:00:00 2001 From: OlimpiaZurek Date: Tue, 11 Apr 2023 16:01:17 +0200 Subject: [PATCH] feat: preserve white spaces on Web --- README.md | 9 +++++++++ example/src/PickerExample.tsx | 23 +++++++++++++++++++++++ js/Picker.web.js | 14 ++++++++++++-- js/PickerItem.js | 12 ++++++++++-- js/types.js | 6 ++++++ typings/Picker.d.ts | 13 +++++++++++++ 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 16311cb857..93683d5cc3 100644 --- a/README.md +++ b/README.md @@ -327,6 +327,15 @@ such that the total number of lines does not exceed this number. Default is '1' | ------- | -------- | -------- | | ColorValue | no | iOS | +### `preserveSpacesInLabel` + +If set to true, the items label will be displayed with spaces preserved. + +@default false +| Type | Required | Platform | +| ------- | -------- | -------- | +| boolean | no | Web | + ## Methods ### `blur` (Android only, lib version 1.16.0+) diff --git a/example/src/PickerExample.tsx b/example/src/PickerExample.tsx index ec897a3d4f..dc217e1207 100644 --- a/example/src/PickerExample.tsx +++ b/example/src/PickerExample.tsx @@ -104,6 +104,25 @@ function DropdownMultilinePickerExample() { ); } +function DropdownPreserveWhiteSpacesPickerExample() { + const [value, setValue] = React.useState('key1'); + + return ( + setValue(v)} + mode="dropdown" + preserveSpacesInLabel> + + + + ); +} + function PromptPickerExample() { const [value, setValue] = React.useState('key1'); return ( @@ -294,6 +313,10 @@ export const examples = [ title: 'Multiline Dropdown Picker', render: DropdownMultilinePickerExample, }, + { + title: 'Preserve White Space Dropdown Picker', + render: DropdownPreserveWhiteSpacesPickerExample, + }, { title: 'Picker with prompt message', render: PromptPickerExample, diff --git a/js/Picker.web.js b/js/Picker.web.js index 54b3774685..a9b44a2454 100644 --- a/js/Picker.web.js +++ b/js/Picker.web.js @@ -28,6 +28,7 @@ type PickerProps = { itemStyle?: GenericStyleProp, mode?: string, prompt?: string, + preserveSpacesInLabel?: boolean, }; const Select = forwardRef((props: any, forwardedRef) => @@ -69,8 +70,17 @@ const Picker: React$AbstractComponent = forwardRef< onChange={handleChange} ref={forwardedRef} value={selectedValue} - {...other} - /> + {...other}> + {React.Children.map(other.children, (child) => { + if (React.isValidElement(child)) { + let cloneElement = React.cloneElement(child, { + preserveSpacesInLabel: other.preserveSpacesInLabel || false, + }); + + return cloneElement; + } + })} + ); }); diff --git a/js/PickerItem.js b/js/PickerItem.js index 3f2cbe08e6..ef2b36f3d7 100644 --- a/js/PickerItem.js +++ b/js/PickerItem.js @@ -10,12 +10,17 @@ import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; import * as React from 'react'; import * as ReactNativeWeb from 'react-native-web'; +const preserveSpaces = (label: string) => { + return label.replace(/ /g, '\u00a0'); +}; + type Props = { color?: ColorValue, label: string, testID?: string, enabled?: boolean, value?: number | string, + preserveSpacesInLabel?: boolean, }; const Option = (props: any) => @@ -31,15 +36,18 @@ export default function PickerItem({ testID, value, enabled = true, + preserveSpacesInLabel = false, }: Props): React.Node { + const pickerLabel = preserveSpacesInLabel ? preserveSpaces(label) : label; + return ( ); } diff --git a/js/types.js b/js/types.js index a7b1114483..6b43023ed6 100644 --- a/js/types.js +++ b/js/types.js @@ -39,4 +39,10 @@ export type PickerItem = $ReadOnly<{| * @platform android */ enabled?: ?boolean, + /** + * If set to true, the specific item will be displayed with spaces preserved. + * default false + * @platform web + */ + preserveSpacesInLabel?: ?boolean, |}>; diff --git a/typings/Picker.d.ts b/typings/Picker.d.ts index 5ebb2d36a6..42a888bced 100644 --- a/typings/Picker.d.ts +++ b/typings/Picker.d.ts @@ -35,6 +35,12 @@ export interface PickerItemProps { * @platform android | web */ enabled?: boolean; + /** + * If set to true, the specific item will be displayed with spaces preserved. + * default false + * @platform web + */ + preserveSpacesInLabel?: ?boolean, } export interface PickerProps extends ViewProps { @@ -118,8 +124,15 @@ export interface PickerProps extends ViewProps { * @platform android */ onBlur?: (e: NativeSyntheticEvent) => void; + /** + * If set to true, the items label will be displayed with spaces preserved. + * default false + * @platform web + */ + preserveSpacesInLabel?: ?boolean, } + declare class Picker extends React.Component, {}> { /** * On Android, display the options in a dialog (this is the default).