@applicaster/zapp-react-native-ui-components 16.0.0-rc.65 → 16.0.0-rc.67

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.
@@ -18,8 +18,11 @@ export const Toggle = (props: Props) => {
18
18
 
19
19
  const { trackColor, trackColorActive, thumbColor, thumbColorActive } = style;
20
20
 
21
+ // `focused_selected` is the selected state with a finger on the row, so the
22
+ // switch has to read as on for both. Leaving it out reads a pressed selected
23
+ // row as off, which flips the thumb for the duration of the press.
21
24
  const isSelected = React.useMemo(
22
- () => cellState === "selected",
25
+ () => cellState === "selected" || cellState === "focused_selected",
23
26
  [item?.id, cellState]
24
27
  );
25
28
 
@@ -30,13 +33,16 @@ export const Toggle = (props: Props) => {
30
33
  // selection state and writes through the entry's tap actions, the same path a
31
34
  // tap on the row takes.
32
35
  //
33
- // The identifier alone cannot tell that case apart from a real action plugin.
34
- // The cell manifest declares an initial_value for `toggle_action_identifier`,
35
- // and `castOrDefault` substitutes that default whenever the configured value
36
- // is empty - and an empty string counts as empty. Clearing the field in the
37
- // app configuration therefore cannot produce an empty identifier here. What
38
- // does distinguish the two is whether the identifier resolves to an installed
39
- // action plugin, so that is what the route is decided on.
36
+ // An empty identifier is the way to ask for that, which is why the cell
37
+ // manifest declares no initial_value for `toggle_action_identifier`:
38
+ // `castOrDefault` substitutes the default whenever the configured value is
39
+ // empty - and an empty string counts as empty - so any default there would be
40
+ // uncleanable and would force every toggle onto that plugin.
41
+ //
42
+ // The route is still decided on whether the identifier resolves to an
43
+ // installed action plugin rather than on the string being non-empty. App
44
+ // configurations saved while the old default was in the manifest still carry
45
+ // it, and a mistyped plugin id has to fall back the same way.
40
46
  const hasActionPlugin = Boolean(
41
47
  action?.identifier && actionContext?.invokeAction
42
48
  );
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { fireEvent, render } from "@testing-library/react-native";
3
+ import { Switch } from "react-native";
3
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
4
5
 
5
6
  import { Toggle } from "../Toggle";
@@ -24,7 +25,6 @@ const style = {
24
25
  trackColorActive: "rgba(4,207,153,1)",
25
26
  thumbColor: "rgba(255,255,255,1)",
26
27
  thumbColorActive: "rgba(255,255,255,1)",
27
- iosBackgroundColor: "rgba(0,0,0,1)",
28
28
  } as any;
29
29
 
30
30
  const item = { id: "true", title: "I agree" } as any;
@@ -56,6 +56,21 @@ describe("Toggle with an empty action identifier", () => {
56
56
  expect(getByRole("switch").props.value).toBe(false);
57
57
  });
58
58
 
59
+ // A finger on a selected row resolves the cell to focused_selected. Reading
60
+ // that as unselected flipped the thumb for the duration of the press and let
61
+ // it jump back on release, which reads as a second tap.
62
+ it("stays on while a selected cell is pressed", () => {
63
+ const { getByRole } = renderToggle("", "focused_selected");
64
+
65
+ expect(getByRole("switch").props.value).toBe(true);
66
+ });
67
+
68
+ it("is off while an unselected cell is pressed", () => {
69
+ const { getByRole } = renderToggle("", "focused");
70
+
71
+ expect(getByRole("switch").props.value).toBe(false);
72
+ });
73
+
59
74
  it("routes a change through the cell click path", () => {
60
75
  const { getByRole } = renderToggle("", "default");
61
76
 
@@ -70,6 +85,28 @@ describe("Toggle with an empty action identifier", () => {
70
85
 
71
86
  expect(mockInitialEntryState).not.toHaveBeenCalled();
72
87
  });
88
+
89
+ // Asserted on the Switch element rather than the rendered host component:
90
+ // what Toggle owns is the props it hands to Switch, and React Native rewrites
91
+ // them into platform-specific ones (tintColor, a style entry) underneath.
92
+ it("forwards every configured color to the switch", () => {
93
+ const { UNSAFE_getByType } = renderToggle("", "default");
94
+
95
+ expect(UNSAFE_getByType(Switch).props).toMatchObject({
96
+ trackColor: { false: style.trackColor, true: style.trackColorActive },
97
+ thumbColor: style.thumbColor,
98
+ });
99
+ });
100
+
101
+ // ios_backgroundColor paints an opaque layer behind the track that the track
102
+ // color cannot cover, which on iOS reads as a halo around the switch. The
103
+ // switch is left on its platform default instead, so the prop must stay
104
+ // unset even if a style happens to carry a color for it.
105
+ it("does not set an iOS background color on the switch", () => {
106
+ const { UNSAFE_getByType } = renderToggle("", "default");
107
+
108
+ expect(UNSAFE_getByType(Switch).props.ios_backgroundColor).toBeUndefined();
109
+ });
73
110
  });
74
111
 
75
112
  describe("Toggle with an action plugin identifier", () => {
@@ -92,11 +129,11 @@ describe("Toggle with an action plugin identifier", () => {
92
129
  });
93
130
 
94
131
  describe("Toggle with an identifier whose action plugin is not installed", () => {
95
- // The cell manifest declares initial_value "firebase-push-topic-action" for
96
- // toggle_action_identifier, and castOrDefault replaces an empty configured
97
- // value with that default. A form toggle therefore always arrives with a
98
- // non-empty identifier it never asked for - the presence of a real action
99
- // context, not the identifier string, is what decides the route.
132
+ // The cell manifest no longer defaults toggle_action_identifier, but app
133
+ // configurations saved while it did still carry "firebase-push-topic-action",
134
+ // and a mistyped id is always possible. A toggle can therefore still arrive
135
+ // with a non-empty identifier it never asked for - the presence of a real
136
+ // action context, not the identifier string, is what decides the route.
100
137
  beforeEach(() => {
101
138
  jest.clearAllMocks();
102
139
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "16.0.0-rc.65",
3
+ "version": "16.0.0-rc.67",
4
4
  "description": "Applicaster Zapp React Native ui components for the Quick Brick App",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "16.0.0-rc.65",
32
- "@applicaster/zapp-react-native-bridge": "16.0.0-rc.65",
33
- "@applicaster/zapp-react-native-redux": "16.0.0-rc.65",
34
- "@applicaster/zapp-react-native-utils": "16.0.0-rc.65",
31
+ "@applicaster/applicaster-types": "16.0.0-rc.67",
32
+ "@applicaster/zapp-react-native-bridge": "16.0.0-rc.67",
33
+ "@applicaster/zapp-react-native-redux": "16.0.0-rc.67",
34
+ "@applicaster/zapp-react-native-utils": "16.0.0-rc.67",
35
35
  "fast-json-stable-stringify": "^2.1.0",
36
36
  "promise": "^8.3.0",
37
37
  "react-native-sortables": "1.7.1",