@jobber/components-native 0.114.12 → 0.114.13-JOB-184129-cbbb878.3

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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components-native",
3
- "version": "0.114.12",
3
+ "version": "0.114.13-JOB-184129-cbbb878.3+cbbb8781",
4
4
  "license": "MIT",
5
5
  "description": "React Native implementation of Atlantis",
6
6
  "repository": {
@@ -123,5 +123,5 @@
123
123
  "react-native-screens": ">=4.18.0",
124
124
  "react-native-svg": ">=12.0.0"
125
125
  },
126
- "gitHead": "a9ac41dfb966649048fcaf7cce2db45f2569fc29"
126
+ "gitHead": "cbbb8781bf3153677263b60e5058734e6c0611b8"
127
127
  }
@@ -16,6 +16,13 @@ import { SelectFieldContext } from "./components/SelectFieldContext";
16
16
  import { FieldLabel } from "./components/SelectLabel";
17
17
  import { HelperText } from "../primitives/HelperText";
18
18
  import { SelectPrimitive } from "../primitives/Select";
19
+ // @rn-primitives/select treats `undefined` as uncontrolled. Keep an explicitly
20
+ // controlled empty value defined so clearing the prop cannot reveal stale
21
+ // internal state; its missing label makes Select.Value render the placeholder.
22
+ const EMPTY_CONTROLLED_VALUE = {
23
+ value: "",
24
+ label: undefined,
25
+ };
19
26
  /**
20
27
  * Composable `Select.Root` chrome: renders the optional `description` / `error`
21
28
  * below the field (via `HelperText`), owns the field-state context, and places the
@@ -28,6 +35,7 @@ import { SelectPrimitive } from "../primitives/Select";
28
35
  export function SelectRoot(_a) {
29
36
  var { labelPlacement = "inside", accessibilityLabel: accessibilityLabelProp, description, error, invalid, status, readOnly, children } = _a, rootProps = __rest(_a, ["labelPlacement", "accessibilityLabel", "description", "error", "invalid", "status", "readOnly", "children"]);
30
37
  const styles = useStyles();
38
+ const primitiveValue = getPrimitiveValue(rootProps);
31
39
  // An empty / whitespace-only string error counts as "no error".
32
40
  const hasError = typeof error === "string" ? error.trim().length > 0 : error != null;
33
41
  const isInvalid = invalid === true || status === "critical" || hasError;
@@ -69,11 +77,17 @@ export function SelectRoot(_a) {
69
77
  ]);
70
78
  return (React.createElement(View, { style: styles.container },
71
79
  React.createElement(SelectFieldContext.Provider, { value: fieldState },
72
- React.createElement(SelectPrimitive.Root, Object.assign({ style: styles.field }, rootProps),
80
+ React.createElement(SelectPrimitive.Root, Object.assign({ style: styles.field }, rootProps, { value: primitiveValue }),
73
81
  labelPlacement === "above" && React.createElement(FieldLabel, null),
74
82
  children)),
75
83
  renderBelowField(hasError ? error : undefined, description)));
76
84
  }
85
+ function getPrimitiveValue(props) {
86
+ const isControlled = Object.prototype.hasOwnProperty.call(props, "value");
87
+ return isControlled && props.value === undefined
88
+ ? EMPTY_CONTROLLED_VALUE
89
+ : props.value;
90
+ }
77
91
  function renderBelowField(error, description) {
78
92
  if (error != null) {
79
93
  return typeof error === "string" ? (React.createElement(HelperText, { message: error, status: "critical" })) : (error);
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
- import { render, screen, within } from "@testing-library/react-native";
2
+ import { fireEvent, render, screen, within, } from "@testing-library/react-native";
3
+ import { Pressable } from "react-native";
3
4
  import { SelectRoot } from "./SelectRoot";
4
5
  import { SelectTrigger } from "./components/SelectTrigger";
5
6
  import { SelectLabel } from "./components/SelectLabel";
@@ -12,6 +13,34 @@ function renderRoot(props = {}) {
12
13
  React.createElement(SelectPrimitive.Value, { placeholder: "Select an option" }))));
13
14
  }
14
15
  describe("SelectRoot chrome", () => {
16
+ it("shows the placeholder when a controlled value is cleared to undefined", () => {
17
+ function ControlledSelect() {
18
+ const [value, setValue] = React.useState();
19
+ return (React.createElement(React.Fragment, null,
20
+ React.createElement(SelectRoot, { value: value, onValueChange: setValue },
21
+ React.createElement(SelectTrigger, null,
22
+ React.createElement(SelectPrimitive.Value, { placeholder: "Select an option" })),
23
+ React.createElement(SelectPrimitive.Item, { testID: "toronto-option", value: "tor", label: "Toronto" })),
24
+ React.createElement(Pressable, { testID: "clear-value", onPress: () => setValue(undefined) })));
25
+ }
26
+ render(React.createElement(ControlledSelect, null));
27
+ fireEvent.press(screen.getByTestId("toronto-option"));
28
+ expect(screen.getByText("Toronto")).toBeDefined();
29
+ fireEvent.press(screen.getByTestId("clear-value"));
30
+ expect(screen.queryByText("Toronto")).toBeNull();
31
+ expect(screen.getByText("Select an option")).toHaveStyle({
32
+ color: tokens["color-text--secondary"],
33
+ });
34
+ });
35
+ it("preserves an uncontrolled default value across rerenders", () => {
36
+ const { rerender } = renderRoot({
37
+ defaultValue: { value: "tor", label: "Toronto" },
38
+ });
39
+ rerender(React.createElement(SelectRoot, { defaultValue: { value: "tor", label: "Toronto" } },
40
+ React.createElement(SelectTrigger, null,
41
+ React.createElement(SelectPrimitive.Value, { placeholder: "Select an option" }))));
42
+ expect(screen.getByText("Toronto")).toBeDefined();
43
+ });
15
44
  it("renders a composed label (visible, hidden from assistive tech)", () => {
16
45
  render(React.createElement(SelectRoot, null,
17
46
  React.createElement(SelectLabel, null, "City"),
@@ -49,7 +49,7 @@ function SelectPrimitiveValue(_a) {
49
49
  var { style } = _a, props = __rest(_a, ["style"]);
50
50
  const styles = useStyles();
51
51
  const { value, disabled } = Primitive.useRootContext();
52
- const isEmpty = (value === null || value === void 0 ? void 0 : value.value) === undefined;
52
+ const isEmpty = (value === null || value === void 0 ? void 0 : value.label) === undefined;
53
53
  return (React.createElement(Primitive.Value, Object.assign({ style: [
54
54
  styles.value,
55
55
  isEmpty && styles.valuePlaceholder,