@artsy/dismissible 0.2.0 → 0.3.1
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/CHANGELOG.md +12 -0
- package/README.md +90 -4
- package/dist/DismissibleContext.d.ts +4 -6
- package/dist/DismissibleContext.js +9 -10
- package/dist/DismissibleContext.js.map +1 -1
- package/package.json +1 -1
- package/src/DismissibleContext.tsx +9 -13
- package/src/__tests__/DismissibleContext.jest.tsx +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# v0.3.1 (Fri Dec 22 2023)
|
|
2
|
+
|
|
3
|
+
#### ⚠️ Pushed to `main`
|
|
4
|
+
|
|
5
|
+
- docs(readme): Update ([@damassi](https://github.com/damassi))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- Christopher Pappas ([@damassi](https://github.com/damassi))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# v0.2.0 (Wed Dec 20 2023)
|
|
2
14
|
|
|
3
15
|
#### 🚀 Enhancement
|
package/README.md
CHANGED
|
@@ -1,12 +1,81 @@
|
|
|
1
1
|
# @artsy/dismissible
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Store dismissible key/value entries in localStorage, which can be used for things like onboarding, notifications and more.
|
|
4
4
|
|
|
5
|
-
## Use
|
|
5
|
+
## Setup and Use
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
yarn install @artsy/dismissible
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Once the package is installed, add the `DismissibleProvider` context to your app, pass in localStorage `keys` to be dismissed later, and (optionally) add a `userID` to attach the key identifiers to:
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
const Root = () => {
|
|
15
|
+
return (
|
|
16
|
+
<DismissibleProvider
|
|
17
|
+
keys={["newFeature", "newFeature2"]}
|
|
18
|
+
userID="some-user-id"
|
|
19
|
+
>
|
|
20
|
+
<NewFeatureAlert>
|
|
21
|
+
<NewFeature />
|
|
22
|
+
</NewFeatureAlert>
|
|
23
|
+
|
|
24
|
+
<NewFeature2Alert>
|
|
25
|
+
<NewFeature2>
|
|
26
|
+
</NewFeature2Alert>
|
|
27
|
+
</DismissibleProvider>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then from `<NewFeatureAlert />`, can manage dismissible keys like so:
|
|
33
|
+
|
|
34
|
+
```jsx
|
|
35
|
+
const NewFeatureAlert = () => {
|
|
36
|
+
const { dismiss, isDismissed } = useDismissibleContext()
|
|
37
|
+
|
|
38
|
+
const isDisplayable = !isDismissed("newFeature").status
|
|
39
|
+
|
|
40
|
+
const handleClose = () => {
|
|
41
|
+
dismiss(ALERT_ID)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!isDisplayable) {
|
|
45
|
+
return <>{children}</>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return <Popover message="Check out this new feature!">{children}</Popover>
|
|
49
|
+
}
|
|
50
|
+
```
|
|
8
51
|
|
|
9
|
-
##
|
|
52
|
+
## API
|
|
53
|
+
|
|
54
|
+
The `useDismissibleContext` hook returns a few useful things for managing dismissibles:
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
const App = () => {
|
|
58
|
+
const { dismiss, dismissed, isDismissed, keys, syncFromLoggedOutUser } =
|
|
59
|
+
useDismissibleContext()
|
|
60
|
+
|
|
61
|
+
// Dismisses a key
|
|
62
|
+
dismiss("id")
|
|
63
|
+
|
|
64
|
+
// All dismissed keys
|
|
65
|
+
dismissed()
|
|
66
|
+
|
|
67
|
+
// Status of the thing dismissed, including timestamp
|
|
68
|
+
isDismissied("id")
|
|
69
|
+
|
|
70
|
+
// If a logged-out user logs in, resync so that dismissed keys don't reappear
|
|
71
|
+
syncFromLoggedOutUser()
|
|
72
|
+
|
|
73
|
+
// All dismissible keys
|
|
74
|
+
console.log(keys)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Development
|
|
10
79
|
|
|
11
80
|
```bash
|
|
12
81
|
yarn test
|
|
@@ -15,3 +84,20 @@ yarn lint
|
|
|
15
84
|
yarn compile
|
|
16
85
|
yarn watch
|
|
17
86
|
```
|
|
87
|
+
|
|
88
|
+
This project uses [auto-release](https://github.com/intuit/auto-release#readme)
|
|
89
|
+
to automatically release on every PR. Every PR should have a label that matches
|
|
90
|
+
one of the following
|
|
91
|
+
|
|
92
|
+
- Version: Trivial
|
|
93
|
+
- Version: Patch
|
|
94
|
+
- Version: Minor
|
|
95
|
+
- Version: Major
|
|
96
|
+
|
|
97
|
+
Major, minor, and patch will cause a new release to be generated. Use major for
|
|
98
|
+
breaking changes, minor for new non-breaking features, and patch for bug fixes.
|
|
99
|
+
Trivial will not cause a release and should be used when updating documentation
|
|
100
|
+
or non-project code.
|
|
101
|
+
|
|
102
|
+
If you don't want to release on a particular PR but the changes aren't trivial
|
|
103
|
+
then use the `Skip Release` tag along side the appropriate version tag.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Yup from "yup";
|
|
2
2
|
import React from "react";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
declare type DismissibleKey = DismissibleContextProps["keys"][number];
|
|
4
|
+
declare type DismissibleKeys = DismissibleKey[];
|
|
5
5
|
interface DismissedKey {
|
|
6
6
|
key: DismissibleKey;
|
|
7
7
|
timestamp: number;
|
|
@@ -10,7 +10,7 @@ interface DismissedKeyStatus {
|
|
|
10
10
|
status: boolean;
|
|
11
11
|
timestamp: number;
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
interface DismissibleContextProps {
|
|
14
14
|
dismissed: DismissedKey[];
|
|
15
15
|
dismiss: (key: DismissibleKey | readonly DismissibleKey[]) => void;
|
|
16
16
|
isDismissed: (key: DismissibleKey) => DismissedKeyStatus;
|
|
@@ -18,16 +18,14 @@ export interface DismissibleContextProps {
|
|
|
18
18
|
syncFromLoggedOutUser: () => void;
|
|
19
19
|
/** An optional userID to track against */
|
|
20
20
|
userID?: string | null;
|
|
21
|
-
__internal__: ReturnType<typeof useLocalStorageUtils>;
|
|
22
21
|
}
|
|
23
|
-
export declare const DismissibleContext: React.Context<DismissibleContextProps>;
|
|
24
22
|
export declare const DismissibleProvider: React.FC<{
|
|
25
23
|
children: React.ReactNode;
|
|
26
24
|
keys: DismissibleKeys;
|
|
27
25
|
userID?: DismissibleContextProps["userID"];
|
|
28
26
|
}>;
|
|
29
27
|
export declare const useDismissibleContext: () => DismissibleContextProps;
|
|
30
|
-
export declare const
|
|
28
|
+
export declare const DISMISSIBLE_LOGGED_OUT_USER_ID: "user";
|
|
31
29
|
export declare const localStorageKey: (id: string) => string;
|
|
32
30
|
interface UseLocalStorageUtilsProps {
|
|
33
31
|
keys: DismissibleContextProps["keys"];
|
|
@@ -26,18 +26,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.useLocalStorageUtils = exports.localStorageKey = exports.
|
|
29
|
+
exports.useLocalStorageUtils = exports.localStorageKey = exports.DISMISSIBLE_LOGGED_OUT_USER_ID = exports.useDismissibleContext = exports.DismissibleProvider = void 0;
|
|
30
30
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
31
31
|
const Yup = __importStar(require("yup"));
|
|
32
32
|
const react_1 = require("react");
|
|
33
33
|
const lodash_uniqby_1 = __importDefault(require("lodash.uniqby"));
|
|
34
|
-
|
|
34
|
+
const DismissibleContext = (0, react_1.createContext)({
|
|
35
35
|
dismissed: [],
|
|
36
36
|
keys: [],
|
|
37
37
|
isDismissed: () => ({ status: false, timestamp: 0 }),
|
|
38
38
|
});
|
|
39
39
|
const DismissibleProvider = ({ children, keys = [], userID }) => {
|
|
40
|
-
const id = userID !== null && userID !== void 0 ? userID : exports.
|
|
40
|
+
const id = userID !== null && userID !== void 0 ? userID : exports.DISMISSIBLE_LOGGED_OUT_USER_ID;
|
|
41
41
|
const [dismissed, setDismissed] = (0, react_1.useState)([]);
|
|
42
42
|
const localStorageUtils = (0, exports.useLocalStorageUtils)({ keys });
|
|
43
43
|
const { __dismiss__, get } = localStorageUtils;
|
|
@@ -70,15 +70,15 @@ const DismissibleProvider = ({ children, keys = [], userID }) => {
|
|
|
70
70
|
* to login, we need to sync up the dismissed state from the logged out user
|
|
71
71
|
*/
|
|
72
72
|
const syncFromLoggedOutUser = (0, react_1.useCallback)(() => {
|
|
73
|
-
if (id === exports.
|
|
73
|
+
if (id === exports.DISMISSIBLE_LOGGED_OUT_USER_ID) {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
const loggedOutDismissals = get(exports.
|
|
76
|
+
const loggedOutDismissals = get(exports.DISMISSIBLE_LOGGED_OUT_USER_ID);
|
|
77
77
|
const loggedInDismissals = get(id);
|
|
78
78
|
const dismissals = (0, lodash_uniqby_1.default)([...loggedOutDismissals, ...loggedInDismissals], (d) => d.key);
|
|
79
79
|
setDismissed(dismissals);
|
|
80
80
|
localStorage.setItem((0, exports.localStorageKey)(id), JSON.stringify(dismissals));
|
|
81
|
-
localStorage.removeItem((0, exports.localStorageKey)(exports.
|
|
81
|
+
localStorage.removeItem((0, exports.localStorageKey)(exports.DISMISSIBLE_LOGGED_OUT_USER_ID));
|
|
82
82
|
}, [id]);
|
|
83
83
|
// Ensure that the dismissed state stays in sync incase the user
|
|
84
84
|
// has multiple tabs open.
|
|
@@ -94,21 +94,20 @@ const DismissibleProvider = ({ children, keys = [], userID }) => {
|
|
|
94
94
|
window.removeEventListener("focus", handleFocus);
|
|
95
95
|
};
|
|
96
96
|
}, [id]);
|
|
97
|
-
return ((0, jsx_runtime_1.jsx)(
|
|
97
|
+
return ((0, jsx_runtime_1.jsx)(DismissibleContext.Provider, Object.assign({ value: {
|
|
98
98
|
dismissed,
|
|
99
99
|
dismiss,
|
|
100
100
|
isDismissed,
|
|
101
101
|
keys,
|
|
102
102
|
syncFromLoggedOutUser,
|
|
103
|
-
__internal__: localStorageUtils,
|
|
104
103
|
} }, { children: children })));
|
|
105
104
|
};
|
|
106
105
|
exports.DismissibleProvider = DismissibleProvider;
|
|
107
106
|
const useDismissibleContext = () => {
|
|
108
|
-
return (0, react_1.useContext)(
|
|
107
|
+
return (0, react_1.useContext)(DismissibleContext);
|
|
109
108
|
};
|
|
110
109
|
exports.useDismissibleContext = useDismissibleContext;
|
|
111
|
-
exports.
|
|
110
|
+
exports.DISMISSIBLE_LOGGED_OUT_USER_ID = "user";
|
|
112
111
|
const localStorageKey = (id) => {
|
|
113
112
|
return `progressive-onboarding.dismissed.${id}`;
|
|
114
113
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DismissibleContext.js","sourceRoot":"","sources":["../src/DismissibleContext.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAA0B;AAC1B,iCAMc;AACd,kEAAkC;
|
|
1
|
+
{"version":3,"file":"DismissibleContext.js","sourceRoot":"","sources":["../src/DismissibleContext.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -8,8 +8,8 @@ import React, {
|
|
|
8
8
|
} from "react"
|
|
9
9
|
import uniqBy from "lodash.uniqby"
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
type DismissibleKey = DismissibleContextProps["keys"][number]
|
|
12
|
+
type DismissibleKeys = DismissibleKey[]
|
|
13
13
|
|
|
14
14
|
interface DismissedKey {
|
|
15
15
|
key: DismissibleKey
|
|
@@ -21,7 +21,7 @@ interface DismissedKeyStatus {
|
|
|
21
21
|
timestamp: number
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
interface DismissibleContextProps {
|
|
25
25
|
dismissed: DismissedKey[]
|
|
26
26
|
dismiss: (key: DismissibleKey | readonly DismissibleKey[]) => void
|
|
27
27
|
isDismissed: (key: DismissibleKey) => DismissedKeyStatus
|
|
@@ -29,10 +29,9 @@ export interface DismissibleContextProps {
|
|
|
29
29
|
syncFromLoggedOutUser: () => void
|
|
30
30
|
/** An optional userID to track against */
|
|
31
31
|
userID?: string | null
|
|
32
|
-
__internal__: ReturnType<typeof useLocalStorageUtils>
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
const DismissibleContext = createContext<DismissibleContextProps>({
|
|
36
35
|
dismissed: [],
|
|
37
36
|
keys: [],
|
|
38
37
|
isDismissed: () => ({ status: false, timestamp: 0 }),
|
|
@@ -43,7 +42,7 @@ export const DismissibleProvider: React.FC<{
|
|
|
43
42
|
keys: DismissibleKeys
|
|
44
43
|
userID?: DismissibleContextProps["userID"]
|
|
45
44
|
}> = ({ children, keys = [], userID }) => {
|
|
46
|
-
const id = userID ??
|
|
45
|
+
const id = userID ?? DISMISSIBLE_LOGGED_OUT_USER_ID
|
|
47
46
|
|
|
48
47
|
const [dismissed, setDismissed] = useState<DismissedKey[]>([])
|
|
49
48
|
|
|
@@ -96,11 +95,11 @@ export const DismissibleProvider: React.FC<{
|
|
|
96
95
|
* to login, we need to sync up the dismissed state from the logged out user
|
|
97
96
|
*/
|
|
98
97
|
const syncFromLoggedOutUser = useCallback(() => {
|
|
99
|
-
if (id ===
|
|
98
|
+
if (id === DISMISSIBLE_LOGGED_OUT_USER_ID) {
|
|
100
99
|
return
|
|
101
100
|
}
|
|
102
101
|
|
|
103
|
-
const loggedOutDismissals = get(
|
|
102
|
+
const loggedOutDismissals = get(DISMISSIBLE_LOGGED_OUT_USER_ID)
|
|
104
103
|
const loggedInDismissals = get(id)
|
|
105
104
|
|
|
106
105
|
const dismissals = uniqBy(
|
|
@@ -111,9 +110,7 @@ export const DismissibleProvider: React.FC<{
|
|
|
111
110
|
setDismissed(dismissals)
|
|
112
111
|
|
|
113
112
|
localStorage.setItem(localStorageKey(id), JSON.stringify(dismissals))
|
|
114
|
-
localStorage.removeItem(
|
|
115
|
-
localStorageKey(PROGRESSIVE_ONBOARDING_LOGGED_OUT_USER_ID)
|
|
116
|
-
)
|
|
113
|
+
localStorage.removeItem(localStorageKey(DISMISSIBLE_LOGGED_OUT_USER_ID))
|
|
117
114
|
}, [id])
|
|
118
115
|
|
|
119
116
|
// Ensure that the dismissed state stays in sync incase the user
|
|
@@ -142,7 +139,6 @@ export const DismissibleProvider: React.FC<{
|
|
|
142
139
|
isDismissed,
|
|
143
140
|
keys,
|
|
144
141
|
syncFromLoggedOutUser,
|
|
145
|
-
__internal__: localStorageUtils,
|
|
146
142
|
}}
|
|
147
143
|
>
|
|
148
144
|
{children}
|
|
@@ -154,7 +150,7 @@ export const useDismissibleContext = () => {
|
|
|
154
150
|
return useContext(DismissibleContext)
|
|
155
151
|
}
|
|
156
152
|
|
|
157
|
-
export const
|
|
153
|
+
export const DISMISSIBLE_LOGGED_OUT_USER_ID = "user" as const
|
|
158
154
|
|
|
159
155
|
export const localStorageKey = (id: string) => {
|
|
160
156
|
return `progressive-onboarding.dismissed.${id}`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import { renderHook } from "@testing-library/react-hooks"
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
DISMISSIBLE_LOGGED_OUT_USER_ID,
|
|
5
5
|
DismissibleProvider,
|
|
6
6
|
useLocalStorageUtils,
|
|
7
7
|
useDismissibleContext,
|
|
@@ -230,7 +230,7 @@ describe("DismissibleContext", () => {
|
|
|
230
230
|
|
|
231
231
|
describe("logged in", () => {
|
|
232
232
|
it("syncs the dismissed state from the logged out user", () => {
|
|
233
|
-
const loggedOutUserId =
|
|
233
|
+
const loggedOutUserId = DISMISSIBLE_LOGGED_OUT_USER_ID
|
|
234
234
|
|
|
235
235
|
const loggedOutDismissals = [
|
|
236
236
|
{ key: "follow-artist", timestamp: 555 },
|