diff --git a/packages/pluggableWidgets/switch-native/package.json b/packages/pluggableWidgets/switch-native/package.json index 0e0a2e361..f26e99a7f 100644 --- a/packages/pluggableWidgets/switch-native/package.json +++ b/packages/pluggableWidgets/switch-native/package.json @@ -1,7 +1,7 @@ { "name": "switch-native", "widgetName": "Switch", - "version": "1.1.0", + "version": "1.1.1", "license": "Apache-2.0", "repository": { "type": "git", diff --git a/packages/pluggableWidgets/switch-native/src/Switch.tsx b/packages/pluggableWidgets/switch-native/src/Switch.tsx index 3a8e4bc97..3b5618717 100644 --- a/packages/pluggableWidgets/switch-native/src/Switch.tsx +++ b/packages/pluggableWidgets/switch-native/src/Switch.tsx @@ -1,5 +1,5 @@ import { flattenStyles } from "@mendix/piw-native-utils-internal"; -import { ReactElement, useCallback } from "react"; +import React, { ReactElement, useCallback } from "react"; import { View, Text, Switch as SwitchComponent, Platform } from "react-native"; import { executeAction } from "@mendix/piw-utils-internal"; import { extractStyles } from "@mendix/pluggable-widgets-tools"; @@ -10,7 +10,7 @@ import { SwitchStyle, defaultSwitchStyle, CheckBoxInputType } from "./ui/Styles" export type Props = SwitchProps; export function Switch(props: Props): ReactElement { - const { label, labelOrientation, showLabel, name, onChange, booleanAttribute } = props; + const { label, labelOrientation, showLabel, name, onChange, booleanAttribute, labelPosition } = props; const combinedStyles = flattenStyles(defaultSwitchStyle, props.style); const styles = processStyles(combinedStyles); const horizontalOrientation = showLabel && labelOrientation === "horizontal"; @@ -39,36 +39,73 @@ export function Switch(props: Props): ReactElement { const labelValue = label?.status === "available" ? label.value : ""; + const switchElement = ( + + ); + + const labelElement = showLabel ? ( + + {labelValue} + + ) : null; + + const validationMessage = hasValidationMessage ? ( + + {booleanAttribute.validation} + + ) : null; + return ( - {showLabel ? ( - - {labelValue} - - ) : null} - - - {hasValidationMessage ? ( - - {booleanAttribute.validation} - - ) : null} - + {horizontalOrientation ? ( + // Horizontal layout: label and switch in a row, validation message below + <> + + {labelPosition === "right" ? ( + <> + {React.cloneElement(switchElement, { key: "switch" })} + {labelElement && React.cloneElement(labelElement, { key: "label" })} + + ) : ( + <> + {labelElement && React.cloneElement(labelElement, { key: "label" })} + {React.cloneElement(switchElement, { key: "switch" })} + + )} + + {validationMessage} + + ) : ( + // Vertical layout: label, switch, and validation message all in a column + <> + {labelElement && React.cloneElement(labelElement, { key: "label" })} + {React.cloneElement(switchElement, { key: "switch" })} + {validationMessage} + + )} ); } diff --git a/packages/pluggableWidgets/switch-native/src/Switch.xml b/packages/pluggableWidgets/switch-native/src/Switch.xml index 1bffec638..ae69d2e2f 100644 --- a/packages/pluggableWidgets/switch-native/src/Switch.xml +++ b/packages/pluggableWidgets/switch-native/src/Switch.xml @@ -1,7 +1,5 @@ - - + + Switch Toggle a boolean attribute. Display @@ -11,44 +9,52 @@ Attribute - + - + On change - + Show label - + Label - + Label orientation - + Horizontal Vertical + + Label position + The position of the label relative to the switch + + Left + Right + + - + - + - + diff --git a/packages/pluggableWidgets/switch-native/src/__tests__/Switch.spec.tsx b/packages/pluggableWidgets/switch-native/src/__tests__/Switch.spec.tsx index b48a70aa4..cd4e36259 100644 --- a/packages/pluggableWidgets/switch-native/src/__tests__/Switch.spec.tsx +++ b/packages/pluggableWidgets/switch-native/src/__tests__/Switch.spec.tsx @@ -13,7 +13,8 @@ const createProps = (props?: Partial): Props => { showLabel: false, booleanAttribute: new EditableValueBuilder().withValue(false).build(), onChange: undefined, - style: [{ ...defaultSwitchStyle, ...style }] + style: [{ ...defaultSwitchStyle, ...style }], + labelPosition: "left" }; return { ...defaultProps, ...props }; @@ -55,14 +56,23 @@ describe("Switch", () => { expect(screen.getByTestId(`${name}$label`)).toBeTruthy(); }); - it("with showLabel true renders label horizontally", () => { + it("with showLabel true and horizontal orientation, renders label and switch in a row", () => { const props = createProps({ - showLabel: true + showLabel: true, + labelOrientation: "horizontal", + label: dynamicValue("Test Label", false) }); render(); - const wrapper = screen.getByTestId(`${name}$wrapper`); - expect(wrapper.props.style).toEqual(expect.arrayContaining([{ flexDirection: "row", alignItems: "center" }])); + + const horizontalContainer = screen.getByTestId(`${name}$horizontalContainer`); + + expect(horizontalContainer.props.style).toEqual( + expect.objectContaining({ flexDirection: "row", alignItems: "center" }) + ); + + expect(horizontalContainer).toContainElement(screen.getByTestId(`${name}$label`)); + expect(horizontalContainer).toContainElement(screen.getByTestId(name)); }); it("with showLabel true and labelOrientation vertical, renders vertical", () => { @@ -74,8 +84,9 @@ describe("Switch", () => { render(); const wrapper = screen.getByTestId(`${name}$wrapper`); expect(wrapper.props.style).toEqual( - expect.not.arrayContaining([{ flexDirection: "row", alignItems: "center" }]) + expect.arrayContaining([{ flexDirection: "column", alignItems: "flex-start" }]) ); + expect(screen.queryByTestId(`${name}$horizontalContainer`)).toBeNull(); }); it("with error renders validation message", () => { diff --git a/packages/pluggableWidgets/switch-native/src/assets/checked-dark.svg b/packages/pluggableWidgets/switch-native/src/assets/checked-dark.svg index bd5e31bb6..d80ba755e 100644 --- a/packages/pluggableWidgets/switch-native/src/assets/checked-dark.svg +++ b/packages/pluggableWidgets/switch-native/src/assets/checked-dark.svg @@ -1,4 +1,4 @@ - + diff --git a/packages/pluggableWidgets/switch-native/src/assets/checked.svg b/packages/pluggableWidgets/switch-native/src/assets/checked.svg index 15afc0cea..6a828d278 100644 --- a/packages/pluggableWidgets/switch-native/src/assets/checked.svg +++ b/packages/pluggableWidgets/switch-native/src/assets/checked.svg @@ -1,4 +1,4 @@ - + diff --git a/packages/pluggableWidgets/switch-native/src/package.xml b/packages/pluggableWidgets/switch-native/src/package.xml index b7e7c6f86..36e64d933 100644 --- a/packages/pluggableWidgets/switch-native/src/package.xml +++ b/packages/pluggableWidgets/switch-native/src/package.xml @@ -1,6 +1,6 @@ - + diff --git a/packages/pluggableWidgets/switch-native/src/ui/Styles.ts b/packages/pluggableWidgets/switch-native/src/ui/Styles.ts index f97731217..c4af5569e 100644 --- a/packages/pluggableWidgets/switch-native/src/ui/Styles.ts +++ b/packages/pluggableWidgets/switch-native/src/ui/Styles.ts @@ -25,7 +25,6 @@ export interface SwitchStyle extends Style { export const defaultSwitchStyle: SwitchStyle = { container: { // All ViewStyle properties are allowed - paddingVertical: 4, justifyContent: "center" }, containerDisabled: { @@ -50,6 +49,5 @@ export const defaultSwitchStyle: SwitchStyle = { }, validationMessage: { // All TextStyle properties are allowed - alignSelf: "stretch" } }; diff --git a/packages/pluggableWidgets/switch-native/typings/SwitchProps.d.ts b/packages/pluggableWidgets/switch-native/typings/SwitchProps.d.ts index c14598ddd..88130d80c 100644 --- a/packages/pluggableWidgets/switch-native/typings/SwitchProps.d.ts +++ b/packages/pluggableWidgets/switch-native/typings/SwitchProps.d.ts @@ -8,6 +8,8 @@ import { ActionValue, DynamicValue, EditableValue } from "mendix"; export type LabelOrientationEnum = "horizontal" | "vertical"; +export type LabelPositionEnum = "left" | "right"; + export interface SwitchProps