@ahnseungchan/webviewkit 1.0.8 → 1.3.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/README.md +67 -107
- package/dist/bridge/WebViewBridgeProvider.d.ts +18 -0
- package/dist/bridge/WebViewBridgeProvider.d.ts.map +1 -0
- package/dist/bridge/WebViewBridgeProvider.js +26 -0
- package/dist/bridge/client.d.ts +20 -0
- package/dist/bridge/client.d.ts.map +1 -0
- package/dist/bridge/client.js +48 -0
- package/dist/bridge/detect-host.d.ts +4 -0
- package/dist/bridge/detect-host.d.ts.map +1 -0
- package/dist/bridge/detect-host.js +19 -0
- package/dist/bridge/host.d.ts +31 -0
- package/dist/bridge/host.d.ts.map +1 -0
- package/dist/bridge/host.js +77 -0
- package/dist/bridge/index.d.ts +10 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +33 -0
- package/dist/bridge/protocol.d.ts +51 -0
- package/dist/bridge/protocol.d.ts.map +1 -0
- package/dist/bridge/protocol.js +65 -0
- package/dist/bridge/stack-router-bridge.d.ts +17 -0
- package/dist/bridge/stack-router-bridge.d.ts.map +1 -0
- package/dist/bridge/stack-router-bridge.js +38 -0
- package/dist/bridge/transport.d.ts +11 -0
- package/dist/bridge/transport.d.ts.map +1 -0
- package/dist/bridge/transport.js +65 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +5 -0
- package/dist/{packages/core/src/history.d.ts → history.d.ts} +3 -2
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +91 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/stack-dev/stack-dev-roadmap.d.ts +15 -0
- package/dist/stack-dev/stack-dev-roadmap.d.ts.map +1 -0
- package/dist/stack-dev/stack-dev-roadmap.js +66 -0
- package/dist/stack-router/_components/back-router.d.ts +3 -0
- package/dist/stack-router/_components/back-router.d.ts.map +1 -0
- package/dist/stack-router/_components/back-router.js +39 -0
- package/dist/stack-router/_components/header.d.ts +3 -0
- package/dist/stack-router/_components/header.d.ts.map +1 -0
- package/dist/stack-router/_components/header.js +42 -0
- package/dist/{packages/core/src/stack-router → stack-router}/stack-router-provider.d.ts +4 -5
- package/dist/stack-router/stack-router-provider.d.ts.map +1 -0
- package/dist/stack-router/stack-router-provider.js +227 -0
- package/dist/{packages/core/src/type.d.ts → type.d.ts} +3 -5
- package/dist/type.d.ts.map +1 -0
- package/dist/type.js +14 -0
- package/package.json +22 -26
- package/dist/packages/core/src/__tests__/back-router.test.d.ts +0 -0
- package/dist/packages/core/src/__tests__/back-router.test.js +0 -62
- package/dist/packages/core/src/__tests__/history.test.d.ts +0 -1
- package/dist/packages/core/src/__tests__/history.test.js +0 -114
- package/dist/packages/core/src/__tests__/stack-router.test.d.ts +0 -0
- package/dist/packages/core/src/__tests__/stack-router.test.js +0 -185
- package/dist/packages/core/src/history.js +0 -82
- package/dist/packages/core/src/index.d.ts +0 -5
- package/dist/packages/core/src/index.js +0 -6
- package/dist/packages/core/src/stack-router/__tests__/stack-router.test.d.ts +0 -0
- package/dist/packages/core/src/stack-router/__tests__/stack-router.test.js +0 -153
- package/dist/packages/core/src/stack-router/_components/back-router.d.ts +0 -2
- package/dist/packages/core/src/stack-router/_components/back-router.js +0 -34
- package/dist/packages/core/src/stack-router/_components/header.d.ts +0 -2
- package/dist/packages/core/src/stack-router/_components/header.js +0 -36
- package/dist/packages/core/src/stack-router/stack-router-provider.js +0 -211
- package/dist/packages/core/src/type.js +0 -11
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StackRouterProvider = exports.useStackRouter = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const history_1 = require("../history");
|
|
10
|
+
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
11
|
+
const react_2 = require("@emotion/react");
|
|
12
|
+
const constants_1 = require("../constants");
|
|
13
|
+
const stack_dev_roadmap_1 = require("../stack-dev/stack-dev-roadmap");
|
|
14
|
+
const type_1 = require("../type");
|
|
15
|
+
const StackRouterContext = (0, react_1.createContext)(null);
|
|
16
|
+
const useStackRouter = () => {
|
|
17
|
+
const context = (0, react_1.useContext)(StackRouterContext);
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error("useStackRouter must be used within a StackRouterProvider");
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
};
|
|
23
|
+
exports.useStackRouter = useStackRouter;
|
|
24
|
+
const StackRouterProvider = ({ maxWidth = "600px", Activities = [], initialActivity, enableDevTools, }) => {
|
|
25
|
+
const showDevTools = (0, react_1.useMemo)(() => {
|
|
26
|
+
var _a;
|
|
27
|
+
if (enableDevTools !== undefined)
|
|
28
|
+
return enableDevTools;
|
|
29
|
+
return typeof process !== "undefined" && ((_a = process.env) === null || _a === void 0 ? void 0 : _a.NODE_ENV) === "development";
|
|
30
|
+
}, [enableDevTools]);
|
|
31
|
+
const [currentPath, setCurrentPath] = (0, react_1.useState)(history_1.history.getCurrentState().path);
|
|
32
|
+
const [currentState, setCurrentState] = (0, react_1.useState)(history_1.history.getCurrentState());
|
|
33
|
+
const [isTransitioning, setIsTransitioning] = (0, react_1.useState)(false);
|
|
34
|
+
const [direction, setDirection] = (0, react_1.useState)(type_1.Direction.FORWARD);
|
|
35
|
+
const [visiblePages, setVisiblePages] = (0, react_1.useState)([]);
|
|
36
|
+
// initialize visible pages
|
|
37
|
+
(0, react_1.useEffect)(() => {
|
|
38
|
+
setVisiblePages([
|
|
39
|
+
{
|
|
40
|
+
path: initialActivity.path,
|
|
41
|
+
element: initialActivity.element,
|
|
42
|
+
isEntering: true,
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
}, [initialActivity]);
|
|
46
|
+
// listen to history changes
|
|
47
|
+
(0, react_1.useEffect)(() => {
|
|
48
|
+
const removeListener = history_1.history.addListener((state) => {
|
|
49
|
+
if (!isTransitioning || direction !== type_1.Direction.BACKWARD) {
|
|
50
|
+
setCurrentPath(state === null || state === void 0 ? void 0 : state.path);
|
|
51
|
+
setCurrentState(state);
|
|
52
|
+
}
|
|
53
|
+
setIsTransitioning(true);
|
|
54
|
+
setDirection((state === null || state === void 0 ? void 0 : state.action) === type_1.HistoryAction.POP
|
|
55
|
+
? type_1.Direction.BACKWARD
|
|
56
|
+
: type_1.Direction.FORWARD);
|
|
57
|
+
});
|
|
58
|
+
return () => {
|
|
59
|
+
removeListener();
|
|
60
|
+
};
|
|
61
|
+
}, [isTransitioning, direction]);
|
|
62
|
+
// handle back
|
|
63
|
+
const handleBack = () => {
|
|
64
|
+
setIsTransitioning(true);
|
|
65
|
+
setDirection(type_1.Direction.BACKWARD);
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
setVisiblePages((prev) => prev.slice(0, -1));
|
|
68
|
+
}, constants_1.STACK_TRANSITION_MS);
|
|
69
|
+
history_1.history.back();
|
|
70
|
+
};
|
|
71
|
+
// update current path
|
|
72
|
+
(0, react_1.useEffect)(() => {
|
|
73
|
+
if (visiblePages.length > 0) {
|
|
74
|
+
setCurrentPath(visiblePages[visiblePages.length - 1].path);
|
|
75
|
+
}
|
|
76
|
+
}, [visiblePages]);
|
|
77
|
+
// handle push
|
|
78
|
+
const handlePush = (path, data) => {
|
|
79
|
+
setIsTransitioning(true);
|
|
80
|
+
setDirection(type_1.Direction.FORWARD);
|
|
81
|
+
const currentActivity = Activities.find((a) => a.path === path);
|
|
82
|
+
if (currentActivity) {
|
|
83
|
+
setVisiblePages((prev) => {
|
|
84
|
+
const existingIndex = prev.findIndex((a) => a.path === path);
|
|
85
|
+
if (existingIndex !== -1) {
|
|
86
|
+
const newActivities = [...prev];
|
|
87
|
+
const [removed] = newActivities.splice(existingIndex, 1);
|
|
88
|
+
return [...newActivities, { ...removed, isExiting: true }];
|
|
89
|
+
}
|
|
90
|
+
return [
|
|
91
|
+
...prev,
|
|
92
|
+
{ path, element: currentActivity.element, isExiting: true },
|
|
93
|
+
];
|
|
94
|
+
});
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
setCurrentPath(path);
|
|
97
|
+
}, constants_1.STACK_TRANSITION_MS);
|
|
98
|
+
}
|
|
99
|
+
history_1.history.push(path, data);
|
|
100
|
+
};
|
|
101
|
+
const value = {
|
|
102
|
+
currentPath,
|
|
103
|
+
currentState,
|
|
104
|
+
initialActivity,
|
|
105
|
+
Activities,
|
|
106
|
+
visiblePages,
|
|
107
|
+
push: handlePush,
|
|
108
|
+
replace: history_1.history.replace,
|
|
109
|
+
back: handleBack,
|
|
110
|
+
forward: history_1.history.forward,
|
|
111
|
+
};
|
|
112
|
+
return ((0, jsx_runtime_1.jsxs)(StackRouterContext.Provider, { value: value, children: [(0, jsx_runtime_1.jsx)(LayoutContainer, { children: (0, jsx_runtime_1.jsx)(Layout, { maxWidth: maxWidth, as: "div", "data-testid": "layout", children: (0, jsx_runtime_1.jsx)(PageContainer, { children: visiblePages.map((page, index) => ((0, jsx_runtime_1.jsx)(PageWrapper, { isTransitioning: isTransitioning, direction: direction, currentPage: index === visiblePages.length - 1, isEntering: page.isEntering, isExiting: page.isExiting, zIndex: index, children: page.element }, `${page.path}-${index}`))) }) }) }), (0, jsx_runtime_1.jsx)(stack_dev_roadmap_1.StackDevRoadmap, { visible: showDevTools, pages: visiblePages.map((p) => ({ path: p.path })), currentPath: currentPath })] }));
|
|
113
|
+
};
|
|
114
|
+
exports.StackRouterProvider = StackRouterProvider;
|
|
115
|
+
exports.default = StackRouterProvider;
|
|
116
|
+
/**styles */
|
|
117
|
+
const LayoutContainer = styled_1.default.div `
|
|
118
|
+
width: 100%;
|
|
119
|
+
height: 100vh;
|
|
120
|
+
display: flex;
|
|
121
|
+
justify-content: center;
|
|
122
|
+
background: white;
|
|
123
|
+
`;
|
|
124
|
+
const Layout = styled_1.default.div `
|
|
125
|
+
width: 100%;
|
|
126
|
+
max-width: ${({ maxWidth }) => maxWidth};
|
|
127
|
+
height: 100%;
|
|
128
|
+
position: relative;
|
|
129
|
+
overflow: hidden;
|
|
130
|
+
`;
|
|
131
|
+
const PageContainer = styled_1.default.div `
|
|
132
|
+
position: relative;
|
|
133
|
+
width: 100%;
|
|
134
|
+
height: 100%;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
background: white;
|
|
137
|
+
`;
|
|
138
|
+
const slideInRight = (0, react_2.keyframes) `
|
|
139
|
+
from {
|
|
140
|
+
transform: translateX(100%);
|
|
141
|
+
opacity: 0.2;
|
|
142
|
+
}
|
|
143
|
+
to {
|
|
144
|
+
transform: translateX(0);
|
|
145
|
+
opacity: 1;
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
const slideOutLeft = (0, react_2.keyframes) `
|
|
149
|
+
from {
|
|
150
|
+
transform: translateX(0);
|
|
151
|
+
opacity: 1;
|
|
152
|
+
}
|
|
153
|
+
to {
|
|
154
|
+
transform: translateX(-30%);
|
|
155
|
+
opacity: 0.2;
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
const slideInLeft = (0, react_2.keyframes) `
|
|
159
|
+
from {
|
|
160
|
+
transform: translateX(-30%);
|
|
161
|
+
opacity: 0.2;
|
|
162
|
+
}
|
|
163
|
+
to {
|
|
164
|
+
transform: translateX(0);
|
|
165
|
+
opacity: 1;
|
|
166
|
+
}
|
|
167
|
+
`;
|
|
168
|
+
const slideOutRight = (0, react_2.keyframes) `
|
|
169
|
+
from {
|
|
170
|
+
transform: translateX(0);
|
|
171
|
+
opacity: 1;
|
|
172
|
+
}
|
|
173
|
+
to {
|
|
174
|
+
transform: translateX(100%);
|
|
175
|
+
opacity: 0.2;
|
|
176
|
+
}
|
|
177
|
+
`;
|
|
178
|
+
const PageWrapper = styled_1.default.div `
|
|
179
|
+
position: absolute;
|
|
180
|
+
top: 0;
|
|
181
|
+
left: 0;
|
|
182
|
+
width: 100%;
|
|
183
|
+
height: 100%;
|
|
184
|
+
background: white;
|
|
185
|
+
cursor: grab;
|
|
186
|
+
user-select: none;
|
|
187
|
+
-webkit-user-select: none;
|
|
188
|
+
-webkit-touch-callout: none;
|
|
189
|
+
-webkit-tap-highlight-color: transparent;
|
|
190
|
+
z-index: ${({ zIndex }) => zIndex};
|
|
191
|
+
will-change: transform, opacity;
|
|
192
|
+
transform: translate3d(0, 0, 0);
|
|
193
|
+
animation: ${({ isTransitioning, direction, currentPage, isEntering, isExiting, }) => {
|
|
194
|
+
if (!isTransitioning)
|
|
195
|
+
return "none";
|
|
196
|
+
if (direction === "forward") {
|
|
197
|
+
if (isExiting) {
|
|
198
|
+
return (0, react_2.css) `
|
|
199
|
+
${slideInRight} ${constants_1.STACK_TRANSITION_MS}ms ease-in-out forwards
|
|
200
|
+
`;
|
|
201
|
+
}
|
|
202
|
+
if (isEntering) {
|
|
203
|
+
return (0, react_2.css) `
|
|
204
|
+
${slideOutLeft} ${constants_1.STACK_TRANSITION_MS}ms ease-in-out forwards
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
if (isExiting) {
|
|
210
|
+
return (0, react_2.css) `
|
|
211
|
+
${slideOutRight} ${constants_1.STACK_TRANSITION_MS}ms ease-in-out forwards
|
|
212
|
+
`;
|
|
213
|
+
}
|
|
214
|
+
if (isEntering) {
|
|
215
|
+
return (0, react_2.css) `
|
|
216
|
+
${slideInLeft} ${constants_1.STACK_TRANSITION_MS}ms ease-in-out forwards
|
|
217
|
+
`;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return "none";
|
|
221
|
+
}};
|
|
222
|
+
animation-fill-mode: forwards;
|
|
223
|
+
|
|
224
|
+
&:active {
|
|
225
|
+
cursor: grabbing;
|
|
226
|
+
}
|
|
227
|
+
`;
|
|
@@ -9,11 +9,8 @@ export interface StackRouterProviderProps {
|
|
|
9
9
|
path: string;
|
|
10
10
|
element: React.ReactNode;
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}>;
|
|
15
|
-
onNavigate?: (path: string) => void;
|
|
16
|
-
currentPath?: string;
|
|
12
|
+
/** 개발 시 스택 로드맵 오버레이 (기본: NODE_ENV === "development") */
|
|
13
|
+
enableDevTools?: boolean;
|
|
17
14
|
}
|
|
18
15
|
export interface VisiblePage {
|
|
19
16
|
path: string;
|
|
@@ -37,3 +34,4 @@ export interface HistoryState {
|
|
|
37
34
|
action?: HistoryAction.PUSH | HistoryAction.POP | HistoryAction.REPLACE;
|
|
38
35
|
}
|
|
39
36
|
export type HistoryListener = (state: HistoryState) => void;
|
|
37
|
+
//# sourceMappingURL=type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,EAAE,CAAC;IAC1D,eAAe,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,CAAC;IAC5D,wDAAwD;IACxD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,oBAAY,SAAS;IACnB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC;AAEnE,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,aAAa,CAAC,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC;CACzE;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC"}
|
package/dist/type.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HistoryAction = exports.Direction = void 0;
|
|
4
|
+
var Direction;
|
|
5
|
+
(function (Direction) {
|
|
6
|
+
Direction["FORWARD"] = "forward";
|
|
7
|
+
Direction["BACKWARD"] = "backward";
|
|
8
|
+
})(Direction || (exports.Direction = Direction = {}));
|
|
9
|
+
var HistoryAction;
|
|
10
|
+
(function (HistoryAction) {
|
|
11
|
+
HistoryAction["PUSH"] = "PUSH";
|
|
12
|
+
HistoryAction["POP"] = "POP";
|
|
13
|
+
HistoryAction["REPLACE"] = "REPLACE";
|
|
14
|
+
})(HistoryAction || (exports.HistoryAction = HistoryAction = {}));
|
package/package.json
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahnseungchan/webviewkit",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Stack navigation and native WebView bridge (RN/Flutter) for React hybrid apps",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.esm.js",
|
|
7
6
|
"types": "dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
|
|
10
|
-
],
|
|
11
|
-
"publishConfig": {
|
|
12
|
-
"access": "public"
|
|
13
|
-
},
|
|
7
|
+
"files": ["dist", "README.md"],
|
|
8
|
+
"sideEffects": false,
|
|
14
9
|
"scripts": {
|
|
15
|
-
"build": "tsc",
|
|
16
|
-
"test": "jest
|
|
10
|
+
"build": "tsc -p tsconfig.build.json",
|
|
11
|
+
"test": "jest --config jest.config.js",
|
|
17
12
|
"clean": "rimraf dist",
|
|
18
13
|
"lint": "eslint src --ext .ts,.tsx",
|
|
19
14
|
"prepublishOnly": "npm run clean && npm run build"
|
|
@@ -24,23 +19,27 @@
|
|
|
24
19
|
"stack-router",
|
|
25
20
|
"react",
|
|
26
21
|
"mobile",
|
|
27
|
-
"router"
|
|
22
|
+
"router",
|
|
23
|
+
"react-native-webview"
|
|
28
24
|
],
|
|
29
|
-
"author": "
|
|
25
|
+
"author": "Seungchan Ahn <omnipoo@naver.com>",
|
|
30
26
|
"license": "MIT",
|
|
31
27
|
"repository": {
|
|
32
28
|
"type": "git",
|
|
33
|
-
"url": "https://github.com/Ahnseungc/
|
|
29
|
+
"url": "https://github.com/Ahnseungc/WebViewKit.git"
|
|
34
30
|
},
|
|
35
31
|
"bugs": {
|
|
36
|
-
"url": "https://github.com/Ahnseungc/
|
|
32
|
+
"url": "https://github.com/Ahnseungc/WebViewKit/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/Ahnseungc/WebViewKit#readme",
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
37
|
},
|
|
38
|
-
"homepage": "https://github.com/Ahnseungc/webviewkit#readme",
|
|
39
38
|
"peerDependencies": {
|
|
40
|
-
"react": ">=16.8.0",
|
|
41
|
-
"react-dom": ">=16.8.0",
|
|
42
39
|
"@emotion/react": ">=11.0.0",
|
|
43
|
-
"@emotion/styled": ">=11.0.0"
|
|
40
|
+
"@emotion/styled": ">=11.0.0",
|
|
41
|
+
"react": ">=16.8.0",
|
|
42
|
+
"react-dom": ">=16.8.0"
|
|
44
43
|
},
|
|
45
44
|
"devDependencies": {
|
|
46
45
|
"@emotion/babel-plugin": "^11.11.0",
|
|
@@ -50,17 +49,14 @@
|
|
|
50
49
|
"@testing-library/react": "^14.2.1",
|
|
51
50
|
"@testing-library/user-event": "^14.5.2",
|
|
52
51
|
"@types/jest": "^29.5.12",
|
|
53
|
-
"@types/react": "^
|
|
54
|
-
"@types/react-dom": "^
|
|
52
|
+
"@types/react": "^18.3.21",
|
|
53
|
+
"@types/react-dom": "^18.3.7",
|
|
55
54
|
"jest": "^29.7.0",
|
|
56
55
|
"jest-environment-jsdom": "^29.7.0",
|
|
57
|
-
"react": "^
|
|
58
|
-
"react-dom": "^
|
|
56
|
+
"react": "^18.3.1",
|
|
57
|
+
"react-dom": "^18.3.1",
|
|
59
58
|
"rimraf": "^5.0.5",
|
|
60
59
|
"ts-jest": "^29.1.2",
|
|
61
60
|
"typescript": "^5.3.3"
|
|
62
|
-
},
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"gsap": "^3.13.0"
|
|
65
61
|
}
|
|
66
62
|
}
|
|
File without changes
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// import React from "react";
|
|
3
|
-
// import { render, screen, fireEvent } from "@testing-library/react";
|
|
4
|
-
// import BackRouter from "../stack-router/_components/back-router";
|
|
5
|
-
// import userEvent from "@testing-library/user-event";
|
|
6
|
-
// import { useStackRouter } from "../stack-router/stack-router-provider";
|
|
7
|
-
// jest.mock("../stack-router/stack-router-provider", () => ({
|
|
8
|
-
// useStackRouter: jest.fn(),
|
|
9
|
-
// }));
|
|
10
|
-
// describe("BackRouter", () => {
|
|
11
|
-
// const mockBack = jest.fn();
|
|
12
|
-
// const user = userEvent.setup();
|
|
13
|
-
// beforeEach(() => {
|
|
14
|
-
// // Reset all mocks before each test
|
|
15
|
-
// jest.clearAllMocks();
|
|
16
|
-
// // Setup default mock implementation
|
|
17
|
-
// (useStackRouter as jest.Mock).mockReturnValue({
|
|
18
|
-
// back: mockBack,
|
|
19
|
-
// });
|
|
20
|
-
// });
|
|
21
|
-
// it("renders back button with icon", () => {
|
|
22
|
-
// render(<BackRouter />);
|
|
23
|
-
// // Check if button exists
|
|
24
|
-
// const button = screen.getByRole("button");
|
|
25
|
-
// expect(button).toBeInTheDocument();
|
|
26
|
-
// // Check if SVG icon exists
|
|
27
|
-
// const svg = button.querySelector("svg");
|
|
28
|
-
// expect(svg).toBeInTheDocument();
|
|
29
|
-
// });
|
|
30
|
-
// it("calls back function when clicked", () => {
|
|
31
|
-
// render(<BackRouter />);
|
|
32
|
-
// const button = screen.getByRole("button");
|
|
33
|
-
// fireEvent.click(button);
|
|
34
|
-
// expect(mockBack).toHaveBeenCalledTimes(1);
|
|
35
|
-
// });
|
|
36
|
-
// it("applies correct styles", () => {
|
|
37
|
-
// render(<BackRouter />);
|
|
38
|
-
// const button = screen.getByRole("button");
|
|
39
|
-
// // Check initial styles
|
|
40
|
-
// expect(button).toHaveStyle({
|
|
41
|
-
// width: "40px",
|
|
42
|
-
// height: "40px",
|
|
43
|
-
// padding: "8px",
|
|
44
|
-
// borderRadius: "50%",
|
|
45
|
-
// });
|
|
46
|
-
// // Check if SVG has correct attributes
|
|
47
|
-
// const svg = button.querySelector("svg");
|
|
48
|
-
// expect(svg).toHaveAttribute("width", "32");
|
|
49
|
-
// expect(svg).toHaveAttribute("height", "32");
|
|
50
|
-
// expect(svg).toHaveAttribute("viewBox", "0 0 24 24");
|
|
51
|
-
// });
|
|
52
|
-
// it("handles hover and active states", async () => {
|
|
53
|
-
// render(<BackRouter />);
|
|
54
|
-
// const button = screen.getByRole("button");
|
|
55
|
-
// // expect hover
|
|
56
|
-
// await user.hover(button);
|
|
57
|
-
// expect(button).toHaveStyle({ color: "#666666" });
|
|
58
|
-
// // expect active
|
|
59
|
-
// await user.pointer({ keys: "[MouseLeft]", target: button });
|
|
60
|
-
// expect(button).toHaveStyle({ color: "#999999" });
|
|
61
|
-
// });
|
|
62
|
-
// });
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { history } from "../history";
|
|
2
|
-
// mocking window.history
|
|
3
|
-
const mockHistory = {
|
|
4
|
-
state: null,
|
|
5
|
-
pushState: jest.fn(),
|
|
6
|
-
replaceState: jest.fn(),
|
|
7
|
-
back: jest.fn(),
|
|
8
|
-
forward: jest.fn(),
|
|
9
|
-
go: jest.fn(),
|
|
10
|
-
};
|
|
11
|
-
// mocking window.location
|
|
12
|
-
const mockLocation = {
|
|
13
|
-
pathname: "/",
|
|
14
|
-
};
|
|
15
|
-
// mocking global window
|
|
16
|
-
Object.defineProperty(window, "history", {
|
|
17
|
-
value: mockHistory,
|
|
18
|
-
writable: true,
|
|
19
|
-
});
|
|
20
|
-
Object.defineProperty(window, "location", {
|
|
21
|
-
value: mockLocation,
|
|
22
|
-
writable: true,
|
|
23
|
-
});
|
|
24
|
-
describe("history", () => {
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
jest.clearAllMocks();
|
|
27
|
-
mockHistory.state = null;
|
|
28
|
-
mockLocation.pathname = "/";
|
|
29
|
-
});
|
|
30
|
-
describe("push", () => {
|
|
31
|
-
it("should push new history entry", () => {
|
|
32
|
-
const path = "/test";
|
|
33
|
-
const data = { title: "Test" };
|
|
34
|
-
history.push(path, data);
|
|
35
|
-
expect(mockHistory.pushState).toHaveBeenCalledWith({ path, data, action: "PUSH" }, "", path);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
describe("replace", () => {
|
|
39
|
-
it("should replace current history entry", () => {
|
|
40
|
-
const path = "/test";
|
|
41
|
-
const data = { title: "Test" };
|
|
42
|
-
history.replace(path, data);
|
|
43
|
-
expect(mockHistory.replaceState).toHaveBeenCalledWith({ path, data, action: "REPLACE" }, "", path);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe("navigation methods", () => {
|
|
47
|
-
it("should call history.back()", () => {
|
|
48
|
-
history.back();
|
|
49
|
-
expect(mockHistory.back).toHaveBeenCalled();
|
|
50
|
-
});
|
|
51
|
-
it("should call history.forward()", () => {
|
|
52
|
-
history.forward();
|
|
53
|
-
expect(mockHistory.forward).toHaveBeenCalled();
|
|
54
|
-
});
|
|
55
|
-
it("should call history.go()", () => {
|
|
56
|
-
const delta = 2;
|
|
57
|
-
history.go(delta);
|
|
58
|
-
expect(mockHistory.go).toHaveBeenCalledWith(delta);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
describe("getCurrentState", () => {
|
|
62
|
-
it("should return current state", () => {
|
|
63
|
-
const mockState = {
|
|
64
|
-
path: "/test",
|
|
65
|
-
data: { title: "Test" },
|
|
66
|
-
};
|
|
67
|
-
mockHistory.state = mockState;
|
|
68
|
-
const state = history.getCurrentState();
|
|
69
|
-
expect(state).toEqual(mockState);
|
|
70
|
-
});
|
|
71
|
-
it("should return default state when history.state is null", () => {
|
|
72
|
-
mockHistory.state = null;
|
|
73
|
-
mockLocation.pathname = "/default";
|
|
74
|
-
const state = history.getCurrentState();
|
|
75
|
-
expect(state).toEqual({ path: "/default" });
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
describe("addListener", () => {
|
|
79
|
-
it("should add and remove listener", () => {
|
|
80
|
-
const listener = jest.fn();
|
|
81
|
-
const removeListener = history.addListener(listener);
|
|
82
|
-
const testState = {
|
|
83
|
-
path: "/test",
|
|
84
|
-
};
|
|
85
|
-
const popStateEvent = new PopStateEvent("popstate", {
|
|
86
|
-
state: testState,
|
|
87
|
-
});
|
|
88
|
-
window.dispatchEvent(popStateEvent);
|
|
89
|
-
expect(listener).toHaveBeenCalledWith(testState);
|
|
90
|
-
// Delete listener
|
|
91
|
-
removeListener();
|
|
92
|
-
// change state and dispatch event
|
|
93
|
-
const newState = { path: "/new" };
|
|
94
|
-
const newPopStateEvent = new PopStateEvent("popstate", {
|
|
95
|
-
state: newState,
|
|
96
|
-
});
|
|
97
|
-
window.dispatchEvent(newPopStateEvent);
|
|
98
|
-
// listener should not be called anymore
|
|
99
|
-
expect(listener).toHaveBeenCalledTimes(1);
|
|
100
|
-
});
|
|
101
|
-
it("should not add duplicate listener", () => {
|
|
102
|
-
const listener = jest.fn();
|
|
103
|
-
// add listener twice
|
|
104
|
-
history.addListener(listener);
|
|
105
|
-
history.addListener(listener);
|
|
106
|
-
// change state and dispatch event
|
|
107
|
-
const testState = { path: "/test" };
|
|
108
|
-
const popStateEvent = new PopStateEvent("popstate", { state: testState });
|
|
109
|
-
window.dispatchEvent(popStateEvent);
|
|
110
|
-
// listener should be called only once
|
|
111
|
-
expect(listener).toHaveBeenCalledTimes(1);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
});
|
|
File without changes
|