@jobber/components-native 0.35.0 → 0.36.0

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.
@@ -0,0 +1,66 @@
1
+ import React from "react";
2
+ import { Pressable, View } from "react-native";
3
+ import { tokens } from "@jobber/design/foundation";
4
+ import { styles } from "./Checkbox.style";
5
+ import { Text } from "../Text";
6
+ import { Icon } from "../Icon";
7
+ import { FormField } from "../FormField";
8
+ export function Checkbox(props) {
9
+ if (props.checked !== undefined && props.onChange !== undefined) {
10
+ return React.createElement(CheckboxInternal, Object.assign({}, props));
11
+ }
12
+ else if (props.name) {
13
+ return (React.createElement(FormField, { name: props.name, defaultValue: props.defaultChecked }, field => {
14
+ return (React.createElement(CheckboxInternal, Object.assign({}, props, { checked: field.value, onChange: newValue => {
15
+ var _a;
16
+ (_a = props === null || props === void 0 ? void 0 : props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newValue);
17
+ field.onChange(newValue);
18
+ } })));
19
+ }));
20
+ }
21
+ else {
22
+ throw new Error("Checkbox was given invalid props");
23
+ }
24
+ }
25
+ function CheckboxInternal({ label, checked, defaultChecked, indeterminate = false, disabled = false, assistiveText, onChange, accessibilityLabel, }) {
26
+ const internalValue = checked !== null && checked !== void 0 ? checked : !!defaultChecked;
27
+ const iconName = indeterminate ? "minus2" : "checkmark";
28
+ const textVariation = disabled ? "disabled" : "subdued";
29
+ const a11yStateChecked = indeterminate ? "mixed" : internalValue;
30
+ const backgroundColor = getBackgroundColor(internalValue, disabled, indeterminate);
31
+ return (React.createElement(Pressable, { accessibilityRole: "checkbox", accessibilityLabel: accessibilityLabel || label, accessibilityState: {
32
+ disabled: disabled,
33
+ checked: a11yStateChecked,
34
+ }, disabled: disabled, style: ({ pressed }) => [
35
+ {
36
+ opacity: pressed ? 0.2 : 1,
37
+ },
38
+ styles.container,
39
+ ], onPress: () => {
40
+ onChange === null || onChange === void 0 ? void 0 : onChange(!internalValue);
41
+ } },
42
+ React.createElement(View, { style: styles.checkBoxContainer },
43
+ label && (React.createElement(View, { style: styles.label },
44
+ React.createElement(Text, { variation: textVariation, align: "start" }, label))),
45
+ React.createElement(View, { style: [
46
+ styles.checkbox,
47
+ disabled && styles.disabledCheckbox,
48
+ {
49
+ backgroundColor,
50
+ },
51
+ ] }, (internalValue || indeterminate) && (React.createElement(Icon, { name: iconName, color: "white" })))),
52
+ assistiveText && (React.createElement(Text, { level: "textSupporting", align: "start", variation: textVariation }, assistiveText))));
53
+ }
54
+ function getBackgroundColor(checked, disabled, indeterminate) {
55
+ if (checked || indeterminate) {
56
+ if (disabled) {
57
+ return tokens["color-disabled"];
58
+ }
59
+ else {
60
+ return tokens["color-interactive"];
61
+ }
62
+ }
63
+ else {
64
+ return tokens["color-overlay--dimmed"];
65
+ }
66
+ }
@@ -0,0 +1,30 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ const checkboxDimensions = tokens["space-large"] + tokens["space-smaller"];
4
+ export const styles = StyleSheet.create({
5
+ container: {
6
+ width: "100%",
7
+ },
8
+ checkBoxContainer: {
9
+ width: "100%",
10
+ justifyContent: "space-between",
11
+ flexDirection: "row",
12
+ alignItems: "center",
13
+ paddingVertical: tokens["space-small"],
14
+ },
15
+ label: {
16
+ flex: 1,
17
+ },
18
+ checkbox: {
19
+ borderRadius: tokens["radius-base"],
20
+ borderWidth: tokens["border-thick"],
21
+ justifyContent: "flex-end",
22
+ width: checkboxDimensions,
23
+ height: checkboxDimensions,
24
+ marginLeft: tokens["space-smaller"],
25
+ borderColor: tokens["color-interactive"],
26
+ },
27
+ disabledCheckbox: {
28
+ borderColor: tokens["color-disabled"],
29
+ },
30
+ });
@@ -0,0 +1,115 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React, { Fragment, useReducer } from "react";
13
+ import { View } from "react-native";
14
+ import isEmpty from "lodash/isEmpty";
15
+ import reduce from "lodash/reduce";
16
+ import { styles } from "./CheckboxGroup.style";
17
+ import { Checkbox } from "./Checkbox";
18
+ import { checkboxGroupReducer, initCheckboxGroupState, } from "./CheckboxGroupReducer";
19
+ import { FormField } from "../FormField";
20
+ import { Divider } from "../Divider";
21
+ export function CheckboxGroup(_a) {
22
+ var { children, state, onChange, name } = _a, rest = __rest(_a, ["children", "state", "onChange", "name"]);
23
+ if (state !== undefined && onChange !== undefined) {
24
+ return (React.createElement(CheckboxGroupInternal, Object.assign({ state: state, onChange: onChange, name: name }, rest), children));
25
+ }
26
+ if (name) {
27
+ return (React.createElement(FormField, { name: name }, field => {
28
+ return (React.createElement(CheckboxGroupInternal, Object.assign({ name: field.name, state: field.value, onChange: newValue => {
29
+ onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
30
+ field.onChange(newValue);
31
+ } }, rest), children));
32
+ }));
33
+ }
34
+ throw new Error("CheckboxGroup passed invalid props");
35
+ }
36
+ function CheckboxGroupInternal({ label, disabled, children, state, accessibilityLabel, onChange, name: parentName, }) {
37
+ const childrenNames = React.Children.map(children, child => {
38
+ const name = throwErrorIfItHasNoName(child.props.name);
39
+ return name;
40
+ });
41
+ const isNested = !!label;
42
+ const [internalCheckedValues, dispatch] = useReducer(checkboxGroupReducer, childrenNames, initCheckboxGroupState);
43
+ const actualCheckedValues = !isEmpty(state) ? state : internalCheckedValues;
44
+ const handleChange = (data) => {
45
+ dispatch({ type: "Update", data });
46
+ onChange === null || onChange === void 0 ? void 0 : onChange(data);
47
+ };
48
+ const indeterminate = checkIndeterminateStatus(actualCheckedValues);
49
+ function cloneChildCheckbox(checkbox) {
50
+ const name = throwErrorIfItHasNoName(checkbox.props.name);
51
+ const childDisabled = disabled || checkbox.props.disabled;
52
+ const childrenHandleChange = (checked) => {
53
+ var _a, _b;
54
+ const childrenNextValue = Object.assign(Object.assign({}, actualCheckedValues.childrenChecked), { [name]: checked });
55
+ const parentNextValue = reduce(childrenNextValue, getParentChecked, true);
56
+ (_b = (_a = checkbox.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, checked);
57
+ handleChange({
58
+ childrenChecked: childrenNextValue,
59
+ parentChecked: parentNextValue,
60
+ });
61
+ };
62
+ return React.cloneElement(checkbox, {
63
+ onChange: childrenHandleChange,
64
+ checked: actualCheckedValues.childrenChecked[name],
65
+ disabled: childDisabled,
66
+ });
67
+ }
68
+ const checkboxObject = React.Children.toArray(children).reduce((childCheckboxObject, child) => {
69
+ if (!React.isValidElement(child)) {
70
+ return childCheckboxObject;
71
+ }
72
+ const name = throwErrorIfItHasNoName(child.props.name);
73
+ return Object.assign(Object.assign({}, childCheckboxObject), { [name]: cloneChildCheckbox(child) });
74
+ }, {});
75
+ function getParentChecked(acc, value, childName) {
76
+ var _a;
77
+ const currentCheckbox = checkboxObject[childName];
78
+ if ((_a = currentCheckbox === null || currentCheckbox === void 0 ? void 0 : currentCheckbox.props) === null || _a === void 0 ? void 0 : _a.disabled) {
79
+ return acc;
80
+ }
81
+ return acc && value;
82
+ }
83
+ return (React.createElement(View, null,
84
+ isNested ? (React.createElement(React.Fragment, null,
85
+ React.createElement(Checkbox, { name: parentName, label: label, accessibilityLabel: accessibilityLabel || label, indeterminate: indeterminate, checked: actualCheckedValues.parentChecked || false, onChange: value => {
86
+ const newValues = reduce(actualCheckedValues.childrenChecked, (acc, currentCheckboxValue, childName) => {
87
+ var _a;
88
+ const currentCheckbox = checkboxObject[childName];
89
+ return ((_a = currentCheckbox === null || currentCheckbox === void 0 ? void 0 : currentCheckbox.props) === null || _a === void 0 ? void 0 : _a.disabled)
90
+ ? Object.assign(Object.assign({}, acc), { [childName]: currentCheckboxValue }) : Object.assign(Object.assign({}, acc), { [childName]: value });
91
+ }, {});
92
+ const parentChecked = reduce(newValues, getParentChecked, value);
93
+ onChange({ childrenChecked: newValues, parentChecked });
94
+ }, disabled: disabled }),
95
+ React.createElement(Divider, null))) : undefined,
96
+ React.createElement(View, null),
97
+ React.createElement(View, { style: isNested ? styles.nestedCheckboxes : {} }, Object.values(checkboxObject).map((checkbox, index) => {
98
+ return (React.createElement(Fragment, { key: index },
99
+ checkbox,
100
+ index !== children.length - 1 && React.createElement(Divider, null)));
101
+ }))));
102
+ }
103
+ function throwErrorIfItHasNoName(name) {
104
+ if (!name) {
105
+ throw new Error("You must provide a name to checkboxes in a checkbox group");
106
+ }
107
+ return name;
108
+ }
109
+ function checkIndeterminateStatus(checkedValues) {
110
+ const checkedValuesAsArray = Object.values(checkedValues.childrenChecked);
111
+ if (checkedValuesAsArray.length === 1) {
112
+ return false;
113
+ }
114
+ return !checkedValuesAsArray.every((value, i, arr) => value === arr[0]);
115
+ }
@@ -0,0 +1,14 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ container: {
5
+ width: "100%",
6
+ justifyContent: "center",
7
+ alignItems: "center",
8
+ paddingHorizontal: tokens["space-base"],
9
+ paddingVertical: tokens["space-small"],
10
+ },
11
+ nestedCheckboxes: {
12
+ marginLeft: tokens["space-large"],
13
+ },
14
+ });
@@ -0,0 +1,17 @@
1
+ import deepmerge from "deepmerge";
2
+ export function initCheckboxGroupState(childNames) {
3
+ return {
4
+ parentChecked: false,
5
+ childrenChecked: childNames.reduce((acc, name) => {
6
+ return Object.assign(Object.assign({}, acc), { [name]: false });
7
+ }, {}),
8
+ };
9
+ }
10
+ export function checkboxGroupReducer(state, action) {
11
+ switch (action.type) {
12
+ case "Update":
13
+ return deepmerge(state, action.data);
14
+ default:
15
+ return state;
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ export { Checkbox } from "./Checkbox";
2
+ export { CheckboxGroup } from "./CheckboxGroup";
@@ -0,0 +1 @@
1
+ export {};
package/dist/src/index.js CHANGED
@@ -7,6 +7,7 @@ export * from "./BottomSheet";
7
7
  export * from "./Button";
8
8
  export * from "./ButtonGroup";
9
9
  export * from "./Card";
10
+ export * from "./Checkbox";
10
11
  export * from "./Chip";
11
12
  export * from "./Content";
12
13
  export * from "./Divider";