ferns-ui 0.36.5 → 0.37.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.
package/dist/Banner.d.ts CHANGED
@@ -1,27 +1,17 @@
1
1
  import React from "react";
2
- import { BoxColor, Rounding, TextColor } from "./Common";
2
+ import { BoxColor, IconName, Rounding, TextColor } from "./Common";
3
3
  export interface BannerProps {
4
4
  id: string;
5
+ dismissible?: boolean;
5
6
  text: string;
6
7
  subtext?: string;
8
+ iconName?: IconName;
7
9
  color?: BoxColor;
8
10
  textColor?: TextColor;
9
11
  negativeXMargin?: number;
10
- bold?: boolean;
11
12
  shape?: Rounding;
12
- type?: "dismiss" | "action";
13
+ type?: "dismiss" | "action" | "permanent";
13
14
  onClick?: () => void;
14
15
  }
15
- interface BannerState {
16
- show: boolean;
17
- }
18
- export declare const hideBanner: (id: string) => void;
19
- export declare class Banner extends React.Component<BannerProps, BannerState> {
20
- state: {
21
- show: boolean;
22
- };
23
- componentDidMount(): Promise<void>;
24
- dismiss: () => void;
25
- render(): React.JSX.Element | null;
26
- }
27
- export {};
16
+ export declare const hideBanner: (id: string) => Promise<void>;
17
+ export declare const Banner: ({ id, text, subtext, color, iconName, textColor, negativeXMargin, shape, type, onClick, }: BannerProps) => React.ReactElement | null;
package/dist/Banner.js CHANGED
@@ -1,56 +1,65 @@
1
- import React from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import { Box } from "./Box";
3
+ import { Icon } from "./Icon";
3
4
  import { IconButton } from "./IconButton";
4
5
  import { Text } from "./Text";
5
6
  import { Unifier } from "./Unifier";
6
7
  function getKey(id) {
7
- return `@ReactUnifier:${id}`;
8
+ return `@FernsUI:${id}`;
8
9
  }
9
10
  export const hideBanner = (id) => {
10
11
  console.debug(`[banner] Hiding ${getKey(id)} `);
11
- Unifier.storage.setItem(getKey(id), "true");
12
+ return Unifier.storage.setItem(getKey(id), "true");
12
13
  };
13
- export class Banner extends React.Component {
14
- constructor() {
15
- super(...arguments);
16
- this.state = { show: false };
17
- this.dismiss = () => {
18
- hideBanner(this.props.id);
19
- this.setState({ show: false });
20
- };
21
- }
22
- async componentDidMount() {
23
- const seen = await Unifier.storage.getItem(getKey(this.props.id));
24
- console.debug(`[banner] ${getKey(this.props.id)} seen? ${seen}`);
25
- this.setState({ show: !seen });
26
- }
27
- render() {
28
- if (!this.state.show) {
29
- return null;
14
+ export const Banner = ({ id, text, subtext, color = "secondaryDark", iconName, textColor = "white", negativeXMargin = 0, shape, type = "dismiss", onClick, }) => {
15
+ // If the banner is permanent, show it immediately.
16
+ const [show, setShow] = useState(type === "permanent");
17
+ // Load seen from async storage.
18
+ useEffect(() => {
19
+ // Always show permanent banners.
20
+ if (type === "permanent") {
21
+ return;
22
+ }
23
+ Unifier.storage.getItem(getKey(id)).then((isSeen) => {
24
+ console.debug(`[banner] ${getKey(id)} seen? ${isSeen}`);
25
+ setShow(!isSeen);
26
+ });
27
+ }, [id, type]);
28
+ const dismiss = () => {
29
+ if (type === "permanent") {
30
+ return;
30
31
  }
31
- const type = this.props.type || "dismiss";
32
- if (type === "action" && !this.props.onClick) {
33
- console.warn("Banners with type action require an onClick property.");
32
+ hideBanner(id);
33
+ setShow(false);
34
+ };
35
+ const renderButton = () => {
36
+ if (type === "permanent") {
37
+ return null;
34
38
  }
35
- const negativeMargin = (this.props.negativeXMargin || 0) * -4;
36
- return (React.createElement(Box, { color: this.props.color || "secondaryDark", dangerouslySetInlineStyle: {
37
- __style: {
38
- marginLeft: negativeMargin,
39
- marginRight: negativeMargin,
40
- },
41
- }, direction: "row", justifyContent: "between", marginBottom: 3, marginTop: 3, paddingX: 3, paddingY: 2, rounding: this.props.shape, shadow: true, width: Unifier.utils.dimensions().width || "100%", onClick: this.dismiss },
42
- React.createElement(Box, { alignItems: "center", direction: "column", flex: "shrink", justifyContent: "center" },
43
- React.createElement(Box, { paddingY: 1 },
44
- React.createElement(Text, { align: "center", color: this.props.textColor || "white", weight: "bold" }, this.props.text)),
45
- this.props.subtext && (React.createElement(Box, { paddingY: 1 },
46
- React.createElement(Text, { align: "center", color: this.props.textColor || "white" }, this.props.subtext)))),
47
- React.createElement(Box, { alignItems: "center", display: "block", justifyContent: "center", width: 40 },
48
- type === "dismiss" && (React.createElement(IconButton, { accessibilityLabel: "", icon: "times-circle",
49
- // size="lg"
50
- iconColor: (this.props.textColor || "white"), prefix: "fas", onClick: () => this.dismiss() })),
51
- type === "action" && (React.createElement(IconButton, { accessibilityLabel: "", icon: "arrow-right",
52
- // size="lg"
53
- iconColor: (this.props.textColor || "white"), prefix: "fas", onClick: () => this.props.onClick && this.props.onClick() })))));
39
+ return (React.createElement(Box, { alignItems: "center", display: "block", justifyContent: "center", width: 40 },
40
+ type === "dismiss" && (React.createElement(IconButton, { accessibilityLabel: "", icon: "times-circle", iconColor: textColor, prefix: "fas", onClick: dismiss })),
41
+ type === "action" && (React.createElement(IconButton, { accessibilityLabel: "", icon: "arrow-right", iconColor: textColor, prefix: "fas", onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick() }))));
42
+ };
43
+ if (!show) {
44
+ return null;
54
45
  }
55
- }
46
+ if (type === "action" && !onClick) {
47
+ console.warn("Banners with type action require an onClick property.");
48
+ }
49
+ const negativeMargin = negativeXMargin * -4;
50
+ return (React.createElement(Box, { color: color, dangerouslySetInlineStyle: {
51
+ __style: {
52
+ marginLeft: negativeMargin,
53
+ marginRight: negativeMargin,
54
+ },
55
+ }, direction: "row", justifyContent: "between", marginBottom: 3, marginTop: 3, paddingX: 3, paddingY: 2, rounding: shape, shadow: true, width: Unifier.utils.dimensions().width || "100%", onClick: type === "permanent" ? undefined : dismiss },
56
+ iconName && (React.createElement(Box, { justifyContent: "center", marginRight: 2, width: 32 },
57
+ React.createElement(Icon, { color: textColor, name: iconName, size: "lg" }))),
58
+ React.createElement(Box, { alignItems: "center", direction: "column", flex: "shrink", justifyContent: "center" },
59
+ React.createElement(Box, { paddingY: 1 },
60
+ React.createElement(Text, { align: "center", color: textColor, weight: "bold" }, text)),
61
+ subtext && (React.createElement(Box, { paddingY: 1 },
62
+ React.createElement(Text, { align: "center", color: textColor }, subtext)))),
63
+ renderButton()));
64
+ };
56
65
  //# sourceMappingURL=Banner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../src/Banner.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../src/Banner.tsx"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -57,6 +57,7 @@ export * from "./Table";
57
57
  export * from "./TableHeader";
58
58
  export * from "./TableHeaderCell";
59
59
  export * from "./TableRow";
60
+ export * from "./useStoredState";
60
61
  type ImageRequireSource = number;
61
62
  interface Insets {
62
63
  top?: number;
package/dist/index.js CHANGED
@@ -60,4 +60,5 @@ export * from "./Table";
60
60
  export * from "./TableHeader";
61
61
  export * from "./TableHeaderCell";
62
62
  export * from "./TableRow";
63
+ export * from "./useStoredState";
63
64
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,4BAA4B;AAC5B,4BAA4B;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AAExB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,2BAA2B;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,4BAA4B;AAC5B,4BAA4B;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AAExB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,2BAA2B;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const useStoredState: <T>(key: string, initialValue?: T | undefined) => [T | null | undefined, (value: T | null | undefined) => Promise<void>];
@@ -0,0 +1,33 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { Unifier } from "./Unifier";
3
+ export const useStoredState = (key, initialValue) => {
4
+ const [state, setState] = useState(initialValue);
5
+ // Function to fetch data from AsyncStorage
6
+ const fetchData = useCallback(async () => {
7
+ try {
8
+ return await Unifier.storage.getItem(key);
9
+ }
10
+ catch (error) {
11
+ console.error("Error reading data from AsyncStorage:", error);
12
+ return initialValue;
13
+ }
14
+ }, [initialValue, key]);
15
+ // Fetch data when the component mounts
16
+ useEffect(() => {
17
+ fetchData().then((value) => {
18
+ setState(value);
19
+ });
20
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21
+ }, []);
22
+ const setAsyncStorageState = async (newValue) => {
23
+ try {
24
+ await Unifier.storage.setItem(key, newValue);
25
+ setState(newValue);
26
+ }
27
+ catch (error) {
28
+ console.error("Error writing data to AsyncStorage:", error);
29
+ }
30
+ };
31
+ return [state, setAsyncStorageState];
32
+ };
33
+ //# sourceMappingURL=useStoredState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStoredState.js","sourceRoot":"","sources":["../src/useStoredState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,GAAW,EACX,YAAgB,EACwD,EAAE;IAC1E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAuB,YAAY,CAAC,CAAC;IAEvE,2CAA2C;IAC3C,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,IAA4B,EAAE;QAC/D,IAAI;YACF,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;SAC3C;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;YAC9D,OAAO,YAAY,CAAC;SACrB;IACH,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC;IAExB,uCAAuC;IACvC,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACzB,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QACH,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,oBAAoB,GAAG,KAAK,EAAE,QAA8B,EAAiB,EAAE;QACnF,IAAI;YACF,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC7C,QAAQ,CAAC,QAAQ,CAAC,CAAC;SACpB;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;SAC7D;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;AACvC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ferns-ui",
3
- "version": "0.36.5",
3
+ "version": "0.37.0",
4
4
  "main": "dist/index.js",
5
5
  "license": "Apache-2.0",
6
6
  "scripts": {
@@ -119,99 +119,99 @@
119
119
  "devDependencies": {
120
120
  "@expo/config-plugins": "~7.2.2",
121
121
  "@expo/vector-icons": "^13.0.0",
122
- "@react-native-async-storage/async-storage": "1.18.2",
122
+ "@react-native-async-storage/async-storage": "1.19.3",
123
123
  "@react-native-community/blur": "^4.3.0",
124
- "@react-native-community/datetimepicker": "7.2.0",
125
- "@react-native-picker/picker": "2.4.10",
126
- "@types/mdurl": "^1.0.2",
127
- "@types/react": "^18.2.21",
124
+ "@react-native-community/datetimepicker": "7.6.1",
125
+ "@react-native-picker/picker": "2.5.1",
126
+ "@types/mdurl": "^1.0.4",
127
+ "@types/react": "^18.2.31",
128
128
  "@types/react-datetime-picker": "^5.0.0",
129
129
  "@types/react-time-picker": "^6.0.0",
130
- "@typescript-eslint/eslint-plugin": "^6.7.0",
131
- "@typescript-eslint/parser": "^6.7.0",
132
- "dayjs": "^1.11.9",
133
- "eslint": "^8.49.0",
134
- "eslint-config-ferns": "^0.4.0",
130
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
131
+ "@typescript-eslint/parser": "^6.9.0",
132
+ "dayjs": "^1.11.10",
133
+ "eslint": "^8.52.0",
134
+ "eslint-config-ferns": "^0.4.4",
135
135
  "eslint-config-prettier": "^9.0.0",
136
- "eslint-plugin-import": "^2.28.1",
136
+ "eslint-plugin-import": "^2.29.0",
137
137
  "eslint-plugin-lodash": "^7.1.0",
138
- "eslint-plugin-prettier": "^5.0.0",
138
+ "eslint-plugin-prettier": "^5.0.1",
139
139
  "eslint-plugin-react": "^7.33.2",
140
140
  "eslint-plugin-react-hooks": "^4.5.0",
141
141
  "eslint-plugin-react-native": "^4.1.0",
142
142
  "eslint-plugin-simple-import-sort": "^10.0.0",
143
143
  "eslint-plugin-unused-imports": "3.0.0",
144
- "expo-clipboard": "~4.3.1",
145
- "expo-font": "~11.4.0",
146
- "expo-haptics": "~12.4.0",
147
- "expo-image-manipulator": "~11.3.0",
148
- "expo-image-picker": "~14.3.2",
149
- "libphonenumber-js": "^1.10.44",
144
+ "expo-clipboard": "~4.5.0",
145
+ "expo-font": "~11.6.0",
146
+ "expo-haptics": "~12.6.0",
147
+ "expo-image-manipulator": "~11.5.0",
148
+ "expo-image-picker": "~14.5.0",
149
+ "libphonenumber-js": "^1.10.48",
150
150
  "lodash": "^4.17.21",
151
151
  "mdurl": "^1.0.1",
152
152
  "prettier": "^3.0.3",
153
153
  "react": "18.2.0",
154
154
  "react-app-polyfill": "^3.0.0",
155
- "react-date-picker": "^10.0.3",
156
- "react-datetime-picker": "^5.0.3",
155
+ "react-date-picker": "^10.5.2",
156
+ "react-datetime-picker": "^5.5.3",
157
157
  "react-dev-utils": "^12.0.1",
158
158
  "react-dom": "18.2.0",
159
159
  "react-keyed-flatten-children": "^2.2.1",
160
- "react-native": "0.72.5",
161
- "react-native-actions-sheet": "^0.9.0-alpha.21",
160
+ "react-native": "0.72.6",
161
+ "react-native-actions-sheet": "^0.8.29",
162
162
  "react-native-calendars": "^1.1301.0",
163
163
  "react-native-drawer-layout": "^3.2.1",
164
- "react-native-gesture-handler": "~2.12.1",
164
+ "react-native-gesture-handler": "~2.13.4",
165
165
  "react-native-modalize": "^2.1.1",
166
- "react-native-permissions": "^3.9.1",
166
+ "react-native-permissions": "^3.10.0",
167
167
  "react-native-picker-select": "^8.1.0",
168
168
  "react-native-portalize": "^1.0.7",
169
- "react-native-reanimated": "~3.3.0",
170
- "react-native-svg": "13.9.0",
169
+ "react-native-reanimated": "~3.5.4",
170
+ "react-native-svg": "13.14.0",
171
171
  "react-native-swiper-flatlist": "^3.1.1",
172
172
  "react-native-toast-notifications": "^3.4.0",
173
- "react-router": "^6.15.0",
174
- "react-router-dom": "^6.15.0",
175
- "react-time-picker": "^6.0.4",
173
+ "react-router": "^6.17.0",
174
+ "react-router-dom": "^6.17.0",
175
+ "react-time-picker": "^6.5.2",
176
176
  "tsc-watch": "^6.0.4",
177
177
  "typescript": "^5.2.2"
178
178
  },
179
179
  "peerDependencies": {
180
180
  "@expo/vector-icons": "^13.0.0",
181
- "@react-native-async-storage/async-storage": "1.18.2",
181
+ "@react-native-async-storage/async-storage": "1.19.3",
182
182
  "@react-native-community/blur": "^4.3.0",
183
- "@react-native-community/datetimepicker": "7.2.0",
184
- "@react-native-picker/picker": "2.4.10",
185
- "@typescript-eslint/eslint-plugin": "^6.7.0",
186
- "@typescript-eslint/parser": "^6.7.0",
187
- "dayjs": "^1.11.9",
188
- "expo-clipboard": "~4.3.1",
189
- "expo-font": "~11.4.0",
190
- "expo-haptics": "~12.4.0",
191
- "expo-image-manipulator": "~11.3.0",
192
- "expo-image-picker": "~14.3.2",
193
- "libphonenumber-js": "^1.10.44",
183
+ "@react-native-community/datetimepicker": "7.6.1",
184
+ "@react-native-picker/picker": "2.5.1",
185
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
186
+ "@typescript-eslint/parser": "^6.9.0",
187
+ "dayjs": "^1.11.10",
188
+ "expo-clipboard": "~4.5.0",
189
+ "expo-font": "~11.6.0",
190
+ "expo-haptics": "~12.6.0",
191
+ "expo-image-manipulator": "~11.5.0",
192
+ "expo-image-picker": "~14.5.0",
193
+ "libphonenumber-js": "^1.10.48",
194
194
  "lodash": "^4.17.21",
195
195
  "react": "18.2.0",
196
196
  "react-app-polyfill": "^3.0.0",
197
- "react-date-picker": "^10.0.3",
198
- "react-datetime-picker": "^5.0.3",
197
+ "react-date-picker": "^10.5.2",
198
+ "react-datetime-picker": "^5.5.3",
199
199
  "react-dev-utils": "^12.0.1",
200
200
  "react-dom": "18.2.0",
201
- "react-native": "0.72.5",
202
- "react-native-actions-sheet": "^0.9.0-alpha.21",
201
+ "react-native": "0.72.6",
202
+ "react-native-actions-sheet": "^0.8.29",
203
203
  "react-native-calendars": "^1.1301.0",
204
204
  "react-native-drawer-layout": "^3.2.1",
205
- "react-native-gesture-handler": "~2.12.1",
205
+ "react-native-gesture-handler": "~2.13.4",
206
206
  "react-native-modalize": "^2.1.1",
207
- "react-native-permissions": "^3.9.1",
207
+ "react-native-permissions": "^3.10.0",
208
208
  "react-native-picker-select": "^8.1.0",
209
209
  "react-native-portalize": "^1.0.7",
210
- "react-native-reanimated": "~3.3.0",
211
- "react-native-svg": "13.9.0",
210
+ "react-native-reanimated": "~3.5.4",
211
+ "react-native-svg": "13.14.0",
212
212
  "react-native-toast-notifications": "^3.4.0",
213
- "react-router": "^6.15.0",
214
- "react-router-dom": "^6.15.0",
215
- "react-time-picker": "^6.0.4"
213
+ "react-router": "^6.17.0",
214
+ "react-router-dom": "^6.17.0",
215
+ "react-time-picker": "^6.5.2"
216
216
  }
217
217
  }
package/src/Banner.tsx CHANGED
@@ -1,124 +1,149 @@
1
- import React from "react";
1
+ import React, {useEffect, useState} from "react";
2
2
 
3
3
  import {Box} from "./Box";
4
- import {BoxColor, ButtonColor, Rounding, TextColor} from "./Common";
4
+ import {BoxColor, ButtonColor, IconName, Rounding, TextColor} from "./Common";
5
+ import {Icon} from "./Icon";
5
6
  import {IconButton} from "./IconButton";
6
7
  import {Text} from "./Text";
7
8
  import {Unifier} from "./Unifier";
8
9
 
9
- // import {faTimesCircle, faArrowRight} from "@fortawesome/free-solid-svg-icons";
10
-
11
10
  export interface BannerProps {
12
11
  id: string;
12
+ dismissible?: boolean;
13
13
  text: string;
14
14
  subtext?: string;
15
+ iconName?: IconName;
15
16
  color?: BoxColor;
16
17
  textColor?: TextColor;
17
18
  negativeXMargin?: number;
18
- bold?: boolean;
19
19
  shape?: Rounding;
20
- type?: "dismiss" | "action";
20
+ type?: "dismiss" | "action" | "permanent";
21
21
  onClick?: () => void;
22
22
  }
23
23
 
24
- // library.add(faTimesCircle);
25
- // library.add(faArrowRight);
26
-
27
- interface BannerState {
28
- show: boolean;
29
- }
30
-
31
- function getKey(id: string) {
32
- return `@ReactUnifier:${id}`;
24
+ function getKey(id: string): string {
25
+ return `@FernsUI:${id}`;
33
26
  }
34
27
 
35
- export const hideBanner = (id: string) => {
28
+ export const hideBanner = (id: string): Promise<void> => {
36
29
  console.debug(`[banner] Hiding ${getKey(id)} `);
37
- Unifier.storage.setItem(getKey(id), "true");
30
+ return Unifier.storage.setItem(getKey(id), "true");
38
31
  };
39
32
 
40
- export class Banner extends React.Component<BannerProps, BannerState> {
41
- state = {show: false};
33
+ export const Banner = ({
34
+ id,
35
+ text,
36
+ subtext,
37
+ color = "secondaryDark",
38
+ iconName,
39
+ textColor = "white",
40
+ negativeXMargin = 0,
41
+ shape,
42
+ type = "dismiss",
43
+ onClick,
44
+ }: BannerProps): React.ReactElement | null => {
45
+ // If the banner is permanent, show it immediately.
46
+ const [show, setShow] = useState(type === "permanent");
42
47
 
43
- async componentDidMount() {
44
- const seen = await Unifier.storage.getItem(getKey(this.props.id));
45
- console.debug(`[banner] ${getKey(this.props.id)} seen? ${seen}`);
46
- this.setState({show: !seen});
47
- }
48
+ // Load seen from async storage.
49
+ useEffect(() => {
50
+ // Always show permanent banners.
51
+ if (type === "permanent") {
52
+ return;
53
+ }
54
+
55
+ Unifier.storage.getItem(getKey(id)).then((isSeen) => {
56
+ console.debug(`[banner] ${getKey(id)} seen? ${isSeen}`);
57
+ setShow(!isSeen);
58
+ });
59
+ }, [id, type]);
48
60
 
49
- dismiss = () => {
50
- hideBanner(this.props.id);
51
- this.setState({show: false});
61
+ const dismiss = (): void => {
62
+ if (type === "permanent") {
63
+ return;
64
+ }
65
+ hideBanner(id);
66
+ setShow(false);
52
67
  };
53
68
 
54
- render() {
55
- if (!this.state.show) {
69
+ const renderButton = (): React.ReactElement | null => {
70
+ if (type === "permanent") {
56
71
  return null;
57
72
  }
58
- const type = this.props.type || "dismiss";
73
+ return (
74
+ <Box alignItems="center" display="block" justifyContent="center" width={40}>
75
+ {type === "dismiss" && (
76
+ <IconButton
77
+ accessibilityLabel=""
78
+ icon="times-circle"
79
+ iconColor={textColor as ButtonColor}
80
+ prefix="fas"
81
+ onClick={dismiss}
82
+ />
83
+ )}
84
+ {type === "action" && (
85
+ <IconButton
86
+ accessibilityLabel=""
87
+ icon="arrow-right"
88
+ iconColor={textColor as ButtonColor}
89
+ prefix="fas"
90
+ onClick={(): void => onClick?.()}
91
+ />
92
+ )}
93
+ </Box>
94
+ );
95
+ };
59
96
 
60
- if (type === "action" && !this.props.onClick) {
61
- console.warn("Banners with type action require an onClick property.");
62
- }
63
- const negativeMargin = (this.props.negativeXMargin || 0) * -4;
97
+ if (!show) {
98
+ return null;
99
+ }
64
100
 
65
- return (
66
- <Box
67
- color={this.props.color || "secondaryDark"}
68
- dangerouslySetInlineStyle={{
69
- __style: {
70
- marginLeft: negativeMargin,
71
- marginRight: negativeMargin,
72
- },
73
- }}
74
- direction="row"
75
- justifyContent="between"
76
- marginBottom={3}
77
- marginTop={3}
78
- paddingX={3}
79
- paddingY={2}
80
- rounding={this.props.shape}
81
- shadow
82
- width={Unifier.utils.dimensions().width || "100%"}
83
- onClick={this.dismiss}
84
- >
85
- <Box alignItems="center" direction="column" flex="shrink" justifyContent="center">
101
+ if (type === "action" && !onClick) {
102
+ console.warn("Banners with type action require an onClick property.");
103
+ }
104
+
105
+ const negativeMargin = negativeXMargin * -4;
106
+
107
+ return (
108
+ <Box
109
+ color={color}
110
+ dangerouslySetInlineStyle={{
111
+ __style: {
112
+ marginLeft: negativeMargin,
113
+ marginRight: negativeMargin,
114
+ },
115
+ }}
116
+ direction="row"
117
+ justifyContent="between"
118
+ marginBottom={3}
119
+ marginTop={3}
120
+ paddingX={3}
121
+ paddingY={2}
122
+ rounding={shape}
123
+ shadow
124
+ width={Unifier.utils.dimensions().width || "100%"}
125
+ onClick={type === "permanent" ? undefined : dismiss}
126
+ >
127
+ {iconName && (
128
+ <Box justifyContent="center" marginRight={2} width={32}>
129
+ <Icon color={textColor} name={iconName} size="lg" />
130
+ </Box>
131
+ )}
132
+ <Box alignItems="center" direction="column" flex="shrink" justifyContent="center">
133
+ <Box paddingY={1}>
134
+ <Text align="center" color={textColor} weight="bold">
135
+ {text}
136
+ </Text>
137
+ </Box>
138
+ {subtext && (
86
139
  <Box paddingY={1}>
87
- <Text align="center" color={this.props.textColor || "white"} weight="bold">
88
- {this.props.text}
140
+ <Text align="center" color={textColor}>
141
+ {subtext}
89
142
  </Text>
90
143
  </Box>
91
- {this.props.subtext && (
92
- <Box paddingY={1}>
93
- <Text align="center" color={this.props.textColor || "white"}>
94
- {this.props.subtext}
95
- </Text>
96
- </Box>
97
- )}
98
- </Box>
99
- <Box alignItems="center" display="block" justifyContent="center" width={40}>
100
- {type === "dismiss" && (
101
- <IconButton
102
- accessibilityLabel=""
103
- icon="times-circle"
104
- // size="lg"
105
- iconColor={(this.props.textColor || "white") as ButtonColor}
106
- prefix="fas"
107
- onClick={() => this.dismiss()}
108
- />
109
- )}
110
- {type === "action" && (
111
- <IconButton
112
- accessibilityLabel=""
113
- icon="arrow-right"
114
- // size="lg"
115
- iconColor={(this.props.textColor || "white") as ButtonColor}
116
- prefix="fas"
117
- onClick={() => this.props.onClick && this.props.onClick()}
118
- />
119
- )}
120
- </Box>
144
+ )}
121
145
  </Box>
122
- );
123
- }
124
- }
146
+ {renderButton()}
147
+ </Box>
148
+ );
149
+ };
package/src/index.tsx CHANGED
@@ -61,6 +61,7 @@ export * from "./Table";
61
61
  export * from "./TableHeader";
62
62
  export * from "./TableHeaderCell";
63
63
  export * from "./TableRow";
64
+ export * from "./useStoredState";
64
65
 
65
66
  // Lifted from react-native
66
67
  type ImageRequireSource = number;
@@ -0,0 +1,39 @@
1
+ import {useCallback, useEffect, useState} from "react";
2
+
3
+ import {Unifier} from "./Unifier";
4
+
5
+ export const useStoredState = <T>(
6
+ key: string,
7
+ initialValue?: T
8
+ ): [T | undefined | null, (value: T | undefined | null) => Promise<void>] => {
9
+ const [state, setState] = useState<T | undefined | null>(initialValue);
10
+
11
+ // Function to fetch data from AsyncStorage
12
+ const fetchData = useCallback(async (): Promise<T | undefined> => {
13
+ try {
14
+ return await Unifier.storage.getItem(key);
15
+ } catch (error) {
16
+ console.error("Error reading data from AsyncStorage:", error);
17
+ return initialValue;
18
+ }
19
+ }, [initialValue, key]);
20
+
21
+ // Fetch data when the component mounts
22
+ useEffect(() => {
23
+ fetchData().then((value) => {
24
+ setState(value);
25
+ });
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ }, []);
28
+
29
+ const setAsyncStorageState = async (newValue: T | undefined | null): Promise<void> => {
30
+ try {
31
+ await Unifier.storage.setItem(key, newValue);
32
+ setState(newValue);
33
+ } catch (error) {
34
+ console.error("Error writing data to AsyncStorage:", error);
35
+ }
36
+ };
37
+
38
+ return [state, setAsyncStorageState];
39
+ };