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 +6 -16
- package/dist/Banner.js +52 -43
- package/dist/Banner.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/useStoredState.d.ts +1 -0
- package/dist/useStoredState.js +33 -0
- package/dist/useStoredState.js.map +1 -0
- package/package.json +53 -53
- package/src/Banner.tsx +115 -90
- package/src/index.tsx +1 -0
- package/src/useStoredState.ts +39 -0
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
|
-
|
|
16
|
-
|
|
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 `@
|
|
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
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
return
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
hideBanner(id);
|
|
33
|
+
setShow(false);
|
|
34
|
+
};
|
|
35
|
+
const renderButton = () => {
|
|
36
|
+
if (type === "permanent") {
|
|
37
|
+
return null;
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
package/dist/Banner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Banner.js","sourceRoot":"","sources":["../src/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Banner.js","sourceRoot":"","sources":["../src/Banner.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
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.
|
|
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.
|
|
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.
|
|
125
|
-
"@react-native-picker/picker": "2.
|
|
126
|
-
"@types/mdurl": "^1.0.
|
|
127
|
-
"@types/react": "^18.2.
|
|
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.
|
|
131
|
-
"@typescript-eslint/parser": "^6.
|
|
132
|
-
"dayjs": "^1.11.
|
|
133
|
-
"eslint": "^8.
|
|
134
|
-
"eslint-config-ferns": "^0.4.
|
|
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.
|
|
136
|
+
"eslint-plugin-import": "^2.29.0",
|
|
137
137
|
"eslint-plugin-lodash": "^7.1.0",
|
|
138
|
-
"eslint-plugin-prettier": "^5.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.
|
|
145
|
-
"expo-font": "~11.
|
|
146
|
-
"expo-haptics": "~12.
|
|
147
|
-
"expo-image-manipulator": "~11.
|
|
148
|
-
"expo-image-picker": "~14.
|
|
149
|
-
"libphonenumber-js": "^1.10.
|
|
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.
|
|
156
|
-
"react-datetime-picker": "^5.
|
|
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.
|
|
161
|
-
"react-native-actions-sheet": "^0.
|
|
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.
|
|
164
|
+
"react-native-gesture-handler": "~2.13.4",
|
|
165
165
|
"react-native-modalize": "^2.1.1",
|
|
166
|
-
"react-native-permissions": "^3.
|
|
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.
|
|
170
|
-
"react-native-svg": "13.
|
|
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.
|
|
174
|
-
"react-router-dom": "^6.
|
|
175
|
-
"react-time-picker": "^6.
|
|
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.
|
|
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.
|
|
184
|
-
"@react-native-picker/picker": "2.
|
|
185
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
186
|
-
"@typescript-eslint/parser": "^6.
|
|
187
|
-
"dayjs": "^1.11.
|
|
188
|
-
"expo-clipboard": "~4.
|
|
189
|
-
"expo-font": "~11.
|
|
190
|
-
"expo-haptics": "~12.
|
|
191
|
-
"expo-image-manipulator": "~11.
|
|
192
|
-
"expo-image-picker": "~14.
|
|
193
|
-
"libphonenumber-js": "^1.10.
|
|
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.
|
|
198
|
-
"react-datetime-picker": "^5.
|
|
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.
|
|
202
|
-
"react-native-actions-sheet": "^0.
|
|
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.
|
|
205
|
+
"react-native-gesture-handler": "~2.13.4",
|
|
206
206
|
"react-native-modalize": "^2.1.1",
|
|
207
|
-
"react-native-permissions": "^3.
|
|
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.
|
|
211
|
-
"react-native-svg": "13.
|
|
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.
|
|
214
|
-
"react-router-dom": "^6.
|
|
215
|
-
"react-time-picker": "^6.
|
|
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
|
-
|
|
25
|
-
|
|
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
|
|
41
|
-
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
51
|
-
|
|
61
|
+
const dismiss = (): void => {
|
|
62
|
+
if (type === "permanent") {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
hideBanner(id);
|
|
66
|
+
setShow(false);
|
|
52
67
|
};
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
if (
|
|
69
|
+
const renderButton = (): React.ReactElement | null => {
|
|
70
|
+
if (type === "permanent") {
|
|
56
71
|
return null;
|
|
57
72
|
}
|
|
58
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const negativeMargin = (this.props.negativeXMargin || 0) * -4;
|
|
97
|
+
if (!show) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
64
100
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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={
|
|
88
|
-
{
|
|
140
|
+
<Text align="center" color={textColor}>
|
|
141
|
+
{subtext}
|
|
89
142
|
</Text>
|
|
90
143
|
</Box>
|
|
91
|
-
|
|
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
|
@@ -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
|
+
};
|