@thoughtbot/superglue 0.54.0 → 1.0.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/.prettierrc +3 -1
- package/dist/action_creators.d.mts +1 -23
- package/dist/action_creators.mjs +3 -7
- package/dist/{chunk-MNVGYKSD.mjs → chunk-LGUVOEZ3.mjs} +253 -242
- package/dist/chunk-LGUVOEZ3.mjs.map +1 -0
- package/dist/cjs/action_creators.cjs +215 -172
- package/dist/cjs/action_creators.cjs.map +1 -1
- package/dist/cjs/superglue.cjs +668 -771
- package/dist/cjs/superglue.cjs.map +1 -1
- package/dist/index-BYr1PoYr.d.mts +232 -0
- package/dist/superglue.d.mts +53 -54
- package/dist/superglue.mjs +366 -482
- package/dist/superglue.mjs.map +1 -1
- package/package.json +9 -10
- package/thoughtbot-superglue-1.0.0.tgz +0 -0
- package/thoughtbot-superglue-1.0.0a.tgz +0 -0
- package/thoughtbot-superglue-1.0.0b.tgz +0 -0
- package/thoughtbot-superglue-1.0.0d.tgz +0 -0
- package/thoughtbot-superglue-1.0.1.tgz +0 -0
- package/typedoc.json +3 -1
- package/dist/chunk-MNVGYKSD.mjs.map +0 -1
- package/dist/index-DfWsUSqv.d.mts +0 -246
package/dist/superglue.mjs
CHANGED
|
@@ -1,33 +1,221 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BEFORE_FETCH,
|
|
3
|
-
BEFORE_REMOTE,
|
|
4
|
-
BEFORE_VISIT,
|
|
5
|
-
COPY_PAGE,
|
|
6
2
|
GRAFTING_ERROR,
|
|
7
3
|
GRAFTING_SUCCESS,
|
|
8
|
-
HANDLE_GRAFT,
|
|
9
|
-
HISTORY_CHANGE,
|
|
10
|
-
KeyPathError,
|
|
11
|
-
REMOVE_PAGE,
|
|
12
|
-
SAVE_RESPONSE,
|
|
13
|
-
SET_CSRF_TOKEN,
|
|
14
|
-
UPDATE_FRAGMENTS,
|
|
15
|
-
actions_exports,
|
|
16
4
|
argsForHistory,
|
|
5
|
+
beforeFetch,
|
|
6
|
+
beforeRemote,
|
|
7
|
+
beforeVisit,
|
|
17
8
|
config,
|
|
9
|
+
copyPage,
|
|
18
10
|
getIn,
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
handleGraft,
|
|
12
|
+
historyChange,
|
|
13
|
+
parsePageKey,
|
|
21
14
|
pathWithoutBZParams,
|
|
15
|
+
removePage,
|
|
22
16
|
saveAndProcessPage,
|
|
17
|
+
saveResponse,
|
|
18
|
+
setActivePage,
|
|
19
|
+
setCSRFToken,
|
|
23
20
|
setIn,
|
|
24
21
|
ujsHandlers,
|
|
22
|
+
updateFragments,
|
|
25
23
|
urlToPageKey
|
|
26
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-LGUVOEZ3.mjs";
|
|
27
25
|
|
|
28
26
|
// lib/index.tsx
|
|
29
|
-
import React2 from "react";
|
|
27
|
+
import React2, { useRef, useMemo } from "react";
|
|
30
28
|
import parse from "url-parse";
|
|
29
|
+
import { Provider } from "react-redux";
|
|
30
|
+
import { createBrowserHistory, createMemoryHistory } from "history";
|
|
31
|
+
|
|
32
|
+
// lib/components/Navigation.tsx
|
|
33
|
+
import React, {
|
|
34
|
+
createContext,
|
|
35
|
+
useEffect,
|
|
36
|
+
useLayoutEffect,
|
|
37
|
+
forwardRef,
|
|
38
|
+
useImperativeHandle
|
|
39
|
+
} from "react";
|
|
40
|
+
import { useDispatch, useSelector, useStore } from "react-redux";
|
|
41
|
+
var NavigationContext = createContext(
|
|
42
|
+
{}
|
|
43
|
+
);
|
|
44
|
+
var hasWindow = typeof window !== "undefined";
|
|
45
|
+
var setWindowScroll = (posX, posY) => {
|
|
46
|
+
hasWindow && window.scrollTo(posX, posY);
|
|
47
|
+
};
|
|
48
|
+
var notFound = (identifier) => {
|
|
49
|
+
let reminder = "";
|
|
50
|
+
if (!identifier) {
|
|
51
|
+
reminder = "Did you forget to add `json.componentIdentifier` in your application.json.props layout?";
|
|
52
|
+
}
|
|
53
|
+
const error = new Error(
|
|
54
|
+
`Superglue Nav component was looking for ${identifier} but could not find it in your mapping. ${reminder}`
|
|
55
|
+
);
|
|
56
|
+
throw error;
|
|
57
|
+
};
|
|
58
|
+
var NavigationProvider = forwardRef(function NavigationProvider2({ history, visit, remote, mapping }, ref) {
|
|
59
|
+
const dispatch = useDispatch();
|
|
60
|
+
const pages = useSelector((state) => state.pages);
|
|
61
|
+
const superglue = useSelector(
|
|
62
|
+
(state) => state.superglue
|
|
63
|
+
);
|
|
64
|
+
const currentPageKey = useSelector(
|
|
65
|
+
(state) => state.superglue.currentPageKey
|
|
66
|
+
);
|
|
67
|
+
const store = useStore();
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
return history.listen(onHistoryChange);
|
|
70
|
+
}, []);
|
|
71
|
+
useLayoutEffect(() => {
|
|
72
|
+
const state = history.location.state;
|
|
73
|
+
if (state && "superglue" in state) {
|
|
74
|
+
const { posX, posY } = state;
|
|
75
|
+
setWindowScroll(posX, posY);
|
|
76
|
+
}
|
|
77
|
+
}, [currentPageKey]);
|
|
78
|
+
useImperativeHandle(
|
|
79
|
+
ref,
|
|
80
|
+
() => {
|
|
81
|
+
return {
|
|
82
|
+
navigateTo
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
[]
|
|
86
|
+
);
|
|
87
|
+
const onHistoryChange = ({ location, action }) => {
|
|
88
|
+
const state = location.state;
|
|
89
|
+
if (action !== "POP") {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!state && location.hash !== "") {
|
|
93
|
+
const nextPageKey = urlToPageKey(location.pathname + location.search);
|
|
94
|
+
const containsKey = !!pages[nextPageKey];
|
|
95
|
+
if (containsKey) {
|
|
96
|
+
history.replace(
|
|
97
|
+
{
|
|
98
|
+
pathname: location.pathname,
|
|
99
|
+
search: location.search,
|
|
100
|
+
hash: location.hash
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
pageKey: nextPageKey,
|
|
104
|
+
superglue: true,
|
|
105
|
+
posY: window.pageYOffset,
|
|
106
|
+
posX: window.pageXOffset
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (state && "superglue" in state) {
|
|
112
|
+
const { pageKey } = state;
|
|
113
|
+
const prevPageKey = store.getState().superglue.currentPageKey;
|
|
114
|
+
const containsKey = !!pages[pageKey];
|
|
115
|
+
if (containsKey) {
|
|
116
|
+
const { restoreStrategy } = pages[pageKey];
|
|
117
|
+
switch (restoreStrategy) {
|
|
118
|
+
case "fromCacheOnly":
|
|
119
|
+
dispatch(setActivePage({ pageKey }));
|
|
120
|
+
break;
|
|
121
|
+
case "fromCacheAndRevisitInBackground":
|
|
122
|
+
dispatch(setActivePage({ pageKey }));
|
|
123
|
+
visit(pageKey, { revisit: true });
|
|
124
|
+
break;
|
|
125
|
+
case "revisitOnly":
|
|
126
|
+
default:
|
|
127
|
+
visit(pageKey, { revisit: true }).then(() => {
|
|
128
|
+
const noNav = prevPageKey === store.getState().superglue.currentPageKey;
|
|
129
|
+
if (noNav) {
|
|
130
|
+
dispatch(setActivePage({ pageKey }));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
visit(pageKey, { revisit: true }).then(() => {
|
|
136
|
+
const noNav = prevPageKey === store.getState().superglue.currentPageKey;
|
|
137
|
+
if (noNav) {
|
|
138
|
+
dispatch(setActivePage({ pageKey }));
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const navigateTo = (path, { action } = {
|
|
145
|
+
action: "push"
|
|
146
|
+
}) => {
|
|
147
|
+
if (action === "none") {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
path = pathWithoutBZParams(path);
|
|
151
|
+
const nextPageKey = urlToPageKey(path);
|
|
152
|
+
const hasPage = Object.prototype.hasOwnProperty.call(
|
|
153
|
+
store.getState().pages,
|
|
154
|
+
nextPageKey
|
|
155
|
+
);
|
|
156
|
+
if (hasPage) {
|
|
157
|
+
const location = history.location;
|
|
158
|
+
const state = location.state;
|
|
159
|
+
const historyArgs = [
|
|
160
|
+
path,
|
|
161
|
+
{
|
|
162
|
+
pageKey: nextPageKey,
|
|
163
|
+
superglue: true,
|
|
164
|
+
posY: 0,
|
|
165
|
+
posX: 0
|
|
166
|
+
}
|
|
167
|
+
];
|
|
168
|
+
if (action === "push") {
|
|
169
|
+
if (hasWindow) {
|
|
170
|
+
history.replace(
|
|
171
|
+
{
|
|
172
|
+
pathname: location.pathname,
|
|
173
|
+
search: location.search,
|
|
174
|
+
hash: location.hash
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
...state,
|
|
178
|
+
posY: window.scrollY,
|
|
179
|
+
posX: window.scrollX
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
history.push(...historyArgs);
|
|
184
|
+
dispatch(setActivePage({ pageKey: nextPageKey }));
|
|
185
|
+
}
|
|
186
|
+
if (action === "replace") {
|
|
187
|
+
history.replace(...historyArgs);
|
|
188
|
+
if (currentPageKey !== nextPageKey) {
|
|
189
|
+
dispatch(setActivePage({ pageKey: nextPageKey }));
|
|
190
|
+
dispatch(removePage({ pageKey: currentPageKey }));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
} else {
|
|
195
|
+
console.warn(
|
|
196
|
+
`\`navigateTo\` was called , but could not find
|
|
197
|
+
the pageKey in the store. This may happen when the wrong
|
|
198
|
+
content_location was set in your non-get controller action.
|
|
199
|
+
No navigation will take place`
|
|
200
|
+
);
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const { search } = superglue;
|
|
205
|
+
const { componentIdentifier } = pages[currentPageKey];
|
|
206
|
+
const Component = mapping[componentIdentifier];
|
|
207
|
+
if (Component) {
|
|
208
|
+
return /* @__PURE__ */ React.createElement(
|
|
209
|
+
NavigationContext.Provider,
|
|
210
|
+
{
|
|
211
|
+
value: { pageKey: currentPageKey, search, navigateTo, visit, remote }
|
|
212
|
+
},
|
|
213
|
+
/* @__PURE__ */ React.createElement(Component, null)
|
|
214
|
+
);
|
|
215
|
+
} else {
|
|
216
|
+
notFound(componentIdentifier);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
31
219
|
|
|
32
220
|
// lib/reducers/index.ts
|
|
33
221
|
function addPlaceholdersToDeferredNodes(existingPage, page) {
|
|
@@ -51,10 +239,9 @@ function constrainPagesSize(state) {
|
|
|
51
239
|
}
|
|
52
240
|
}
|
|
53
241
|
}
|
|
54
|
-
function
|
|
242
|
+
function handleSaveResponse(state, pageKey, page) {
|
|
55
243
|
state = { ...state };
|
|
56
244
|
let nextPage = {
|
|
57
|
-
pageKey,
|
|
58
245
|
...page,
|
|
59
246
|
savedAt: Date.now()
|
|
60
247
|
};
|
|
@@ -104,7 +291,7 @@ function graftNodeOntoPage(state, pageKey, node, pathToNode) {
|
|
|
104
291
|
const fullPathToNode = [pageKey, pathToNode].join(".");
|
|
105
292
|
return setIn(state, fullPathToNode, node);
|
|
106
293
|
}
|
|
107
|
-
function
|
|
294
|
+
function handleGraftResponse(state, pageKey, page) {
|
|
108
295
|
const currentPage = state[pageKey];
|
|
109
296
|
if (!currentPage) {
|
|
110
297
|
const error = new Error(
|
|
@@ -123,491 +310,188 @@ function handleGraft(state, pageKey, page) {
|
|
|
123
310
|
].reduce((memo, fn) => fn(memo), state);
|
|
124
311
|
}
|
|
125
312
|
function pageReducer(state = {}, action) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
let nextState = state;
|
|
138
|
-
Object.entries(state).forEach(([pageKey, page]) => {
|
|
139
|
-
page.fragments.forEach((fragment) => {
|
|
140
|
-
const { type, path } = fragment;
|
|
141
|
-
const changedNode = changedFragments[type];
|
|
142
|
-
const currentNode = getIn(nextState, `${pageKey}.${path}`);
|
|
143
|
-
if (type in changedFragments && changedNode !== currentNode) {
|
|
144
|
-
const nextNode = JSON.parse(JSON.stringify(changedNode));
|
|
145
|
-
nextState = setIn(nextState, `${pageKey}.${path}`, nextNode);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
return nextState;
|
|
150
|
-
}
|
|
151
|
-
case COPY_PAGE: {
|
|
152
|
-
const nextState = { ...state };
|
|
153
|
-
const { from, to } = action.payload;
|
|
154
|
-
nextState[urlToPageKey(to)] = JSON.parse(JSON.stringify(nextState[from]));
|
|
155
|
-
return nextState;
|
|
156
|
-
}
|
|
157
|
-
case REMOVE_PAGE: {
|
|
158
|
-
const { pageKey } = action.payload;
|
|
159
|
-
const nextState = { ...state };
|
|
160
|
-
delete nextState[pageKey];
|
|
161
|
-
return nextState;
|
|
162
|
-
}
|
|
163
|
-
default:
|
|
164
|
-
return state;
|
|
313
|
+
if (removePage.match(action)) {
|
|
314
|
+
const { pageKey } = action.payload;
|
|
315
|
+
const nextState = { ...state };
|
|
316
|
+
delete nextState[pageKey];
|
|
317
|
+
return nextState;
|
|
318
|
+
}
|
|
319
|
+
if (copyPage.match(action)) {
|
|
320
|
+
const nextState = { ...state };
|
|
321
|
+
const { from, to } = action.payload;
|
|
322
|
+
nextState[urlToPageKey(to)] = JSON.parse(JSON.stringify(nextState[from]));
|
|
323
|
+
return nextState;
|
|
165
324
|
}
|
|
325
|
+
if (handleGraft.match(action)) {
|
|
326
|
+
const { pageKey, page } = action.payload;
|
|
327
|
+
return handleGraftResponse(state, pageKey, page);
|
|
328
|
+
}
|
|
329
|
+
if (saveResponse.match(action)) {
|
|
330
|
+
const { pageKey, page } = action.payload;
|
|
331
|
+
const nextState = handleSaveResponse(state, pageKey, page);
|
|
332
|
+
return nextState;
|
|
333
|
+
}
|
|
334
|
+
return state;
|
|
166
335
|
}
|
|
167
|
-
function superglueReducer(state = {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return { ...state, csrfToken, assets };
|
|
185
|
-
}
|
|
186
|
-
case SET_CSRF_TOKEN: {
|
|
187
|
-
const { csrfToken } = action.payload;
|
|
188
|
-
return { ...state, csrfToken };
|
|
189
|
-
}
|
|
190
|
-
default:
|
|
191
|
-
return state;
|
|
336
|
+
function superglueReducer(state = {
|
|
337
|
+
currentPageKey: "",
|
|
338
|
+
search: {},
|
|
339
|
+
assets: []
|
|
340
|
+
}, action) {
|
|
341
|
+
if (setCSRFToken.match(action)) {
|
|
342
|
+
const { csrfToken } = action.payload;
|
|
343
|
+
return { ...state, csrfToken };
|
|
344
|
+
}
|
|
345
|
+
if (setActivePage.match(action)) {
|
|
346
|
+
const { pageKey } = action.payload;
|
|
347
|
+
const { search } = parsePageKey(pageKey);
|
|
348
|
+
return {
|
|
349
|
+
...state,
|
|
350
|
+
search,
|
|
351
|
+
currentPageKey: pageKey
|
|
352
|
+
};
|
|
192
353
|
}
|
|
354
|
+
if (historyChange.match(action)) {
|
|
355
|
+
const { pageKey } = action.payload;
|
|
356
|
+
const { search } = parsePageKey(pageKey);
|
|
357
|
+
return {
|
|
358
|
+
...state,
|
|
359
|
+
currentPageKey: pageKey,
|
|
360
|
+
search
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
if (saveResponse.match(action)) {
|
|
364
|
+
const {
|
|
365
|
+
page: { csrfToken, assets }
|
|
366
|
+
} = action.payload;
|
|
367
|
+
return { ...state, csrfToken, assets };
|
|
368
|
+
}
|
|
369
|
+
return state;
|
|
193
370
|
}
|
|
194
371
|
var rootReducer = {
|
|
195
372
|
superglue: superglueReducer,
|
|
196
373
|
pages: pageReducer
|
|
197
374
|
};
|
|
198
375
|
|
|
199
|
-
// lib/index.
|
|
200
|
-
import {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
376
|
+
// lib/hooks/index.ts
|
|
377
|
+
import { useSelector as useSelector2 } from "react-redux";
|
|
378
|
+
function useSuperglue() {
|
|
379
|
+
return useSelector2((state) => state.superglue);
|
|
380
|
+
}
|
|
381
|
+
function useContent() {
|
|
382
|
+
const superglueState = useSuperglue();
|
|
383
|
+
const currentPageKey = superglueState.currentPageKey;
|
|
384
|
+
return useSelector2(
|
|
385
|
+
(state) => state.pages[currentPageKey]
|
|
386
|
+
).data;
|
|
387
|
+
}
|
|
205
388
|
|
|
206
|
-
// lib/
|
|
207
|
-
|
|
208
|
-
var
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
super(props);
|
|
214
|
-
const { history, initialPageKey } = this.props;
|
|
215
|
-
this.history = history;
|
|
216
|
-
this.navigateTo = this.navigateTo.bind(this);
|
|
217
|
-
this.scrollTo = this.scrollTo.bind(this);
|
|
218
|
-
this.onHistoryChange = this.onHistoryChange.bind(this);
|
|
219
|
-
this.state = {
|
|
220
|
-
pageKey: initialPageKey,
|
|
221
|
-
ownProps: {}
|
|
222
|
-
};
|
|
223
|
-
this.hasWindow = typeof window !== "undefined";
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* @ignore
|
|
227
|
-
*/
|
|
228
|
-
componentDidMount() {
|
|
229
|
-
this.unsubscribeHistory = this.history.listen(this.onHistoryChange);
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* @ignore
|
|
233
|
-
*/
|
|
234
|
-
componentWillUnmount() {
|
|
235
|
-
this.unsubscribeHistory();
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Passed to every page component. Manually navigate using pages that exists
|
|
239
|
-
* in the store and restores scroll position. This is what {@link Visit} in
|
|
240
|
-
* your `application_visit.js` ultimately calls.
|
|
241
|
-
*
|
|
242
|
-
* If there is an existing page in your store `navigateTo` will restore the props,
|
|
243
|
-
* render the correct component, and return `true`. Otherwise, it will return
|
|
244
|
-
* `false`. This is useful if you want to restore an existing page before making a
|
|
245
|
-
* call to `visit` or `remote`.
|
|
246
|
-
*
|
|
247
|
-
* @param path
|
|
248
|
-
* @param options when `none`, immediately returns `false`
|
|
249
|
-
* @returns `true` if the navigation was a success, `false` if the page was not found in the
|
|
250
|
-
* store.
|
|
251
|
-
*/
|
|
252
|
-
navigateTo(path, {
|
|
253
|
-
action,
|
|
254
|
-
ownProps
|
|
255
|
-
} = {
|
|
256
|
-
action: "push",
|
|
257
|
-
ownProps: {}
|
|
258
|
-
}) {
|
|
259
|
-
if (action === "none") {
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
path = pathWithoutBZParams(path);
|
|
263
|
-
const nextPageKey = urlToPageKey(path);
|
|
264
|
-
const { store } = this.props;
|
|
265
|
-
const hasPage = !!store.getState().pages[nextPageKey];
|
|
266
|
-
if (hasPage) {
|
|
267
|
-
const location = this.history.location;
|
|
268
|
-
const state = location.state;
|
|
269
|
-
const prevPageKey = state.pageKey;
|
|
270
|
-
const historyArgs = [
|
|
271
|
-
path,
|
|
272
|
-
{
|
|
273
|
-
pageKey: nextPageKey,
|
|
274
|
-
superglue: true,
|
|
275
|
-
posY: 0,
|
|
276
|
-
posX: 0
|
|
277
|
-
}
|
|
278
|
-
];
|
|
279
|
-
if (action === "push") {
|
|
280
|
-
if (this.hasWindow) {
|
|
281
|
-
this.history.replace(
|
|
282
|
-
{
|
|
283
|
-
pathname: location.pathname,
|
|
284
|
-
search: location.search,
|
|
285
|
-
hash: location.hash
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
...state,
|
|
289
|
-
posY: window.pageYOffset,
|
|
290
|
-
posX: window.pageXOffset
|
|
291
|
-
}
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
this.history.push(...historyArgs);
|
|
295
|
-
}
|
|
296
|
-
if (action === "replace") {
|
|
297
|
-
this.history.replace(...historyArgs);
|
|
298
|
-
}
|
|
299
|
-
this.setState({ pageKey: nextPageKey, ownProps });
|
|
300
|
-
this.scrollTo(0, 0);
|
|
301
|
-
if (action === "replace" && prevPageKey && prevPageKey !== nextPageKey) {
|
|
302
|
-
store.dispatch({
|
|
303
|
-
type: REMOVE_PAGE,
|
|
304
|
-
payload: {
|
|
305
|
-
pageKey: prevPageKey
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
return true;
|
|
310
|
-
} else {
|
|
311
|
-
console.warn(
|
|
312
|
-
`\`navigateTo\` was called , but could not find.
|
|
313
|
-
the pageKey in the store. This may happen when the wrong
|
|
314
|
-
content_location was set in your non-get controller action.
|
|
315
|
-
No navigation will take place`
|
|
316
|
-
);
|
|
317
|
-
return false;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* @ignore
|
|
322
|
-
*/
|
|
323
|
-
scrollTo(posX, posY) {
|
|
324
|
-
this.hasWindow && window.scrollTo(posX, posY);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* @ignore
|
|
328
|
-
*/
|
|
329
|
-
onHistoryChange({ location, action }) {
|
|
330
|
-
const { store, visit } = this.props;
|
|
331
|
-
const { pathname, search, hash } = location;
|
|
332
|
-
const state = location.state;
|
|
333
|
-
if (state && "superglue" in state) {
|
|
334
|
-
store.dispatch({
|
|
335
|
-
type: HISTORY_CHANGE,
|
|
336
|
-
payload: { pathname, search, hash }
|
|
337
|
-
});
|
|
338
|
-
if (action !== "POP") {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
const { pageKey, posX, posY } = state;
|
|
342
|
-
const containsKey = !!store.getState().pages[pageKey];
|
|
343
|
-
if (containsKey) {
|
|
344
|
-
const { restoreStrategy } = store.getState().pages[pageKey];
|
|
345
|
-
switch (restoreStrategy) {
|
|
346
|
-
case "fromCacheOnly":
|
|
347
|
-
this.setState({ pageKey });
|
|
348
|
-
this.scrollTo(posX, posY);
|
|
349
|
-
break;
|
|
350
|
-
case "fromCacheAndRevisitInBackground":
|
|
351
|
-
this.setState({ pageKey });
|
|
352
|
-
this.scrollTo(posX, posY);
|
|
353
|
-
visit(pageKey, { revisit: true });
|
|
354
|
-
break;
|
|
355
|
-
case "revisitOnly":
|
|
356
|
-
default:
|
|
357
|
-
visit(pageKey, { revisit: true }).then((meta) => {
|
|
358
|
-
if (meta === void 0) {
|
|
359
|
-
console.warn(
|
|
360
|
-
`scoll restoration was skipped. Your visit's then funtion
|
|
361
|
-
should return the meta object it recieved if you want your
|
|
362
|
-
application to restore the page's previous scroll.`
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
if (!!meta && meta.suggestedAction === "none") {
|
|
366
|
-
this.setState({ pageKey });
|
|
367
|
-
this.scrollTo(posX, posY);
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
} else {
|
|
372
|
-
visit(pageKey, { revisit: true }).then((meta) => {
|
|
373
|
-
if (meta === void 0) {
|
|
374
|
-
console.warn(
|
|
375
|
-
`scoll restoration was skipped. Your visit's then funtion
|
|
376
|
-
should return the meta object it recieved if you want your
|
|
377
|
-
application to restore the page's previous scroll.`
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
if (!!meta && meta.suggestedAction === "none") {
|
|
381
|
-
this.setState({ pageKey });
|
|
382
|
-
this.scrollTo(posX, posY);
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* @ignore
|
|
390
|
-
*/
|
|
391
|
-
notFound(identifier) {
|
|
392
|
-
let reminder = "";
|
|
393
|
-
if (!identifier) {
|
|
394
|
-
reminder = "Did you forget to add `json.componentIdentifier` in your application.json.props layout?";
|
|
395
|
-
}
|
|
396
|
-
const error = new Error(
|
|
397
|
-
`Superglue Nav component was looking for ${identifier} but could not find it in your mapping. ${reminder}`
|
|
398
|
-
);
|
|
399
|
-
throw error;
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* @ignore
|
|
403
|
-
*/
|
|
404
|
-
render() {
|
|
405
|
-
const { store, visit, remote } = this.props;
|
|
406
|
-
const { pageKey, ownProps } = this.state;
|
|
407
|
-
const { componentIdentifier } = store.getState().pages[pageKey];
|
|
408
|
-
const Component = this.props.mapping[componentIdentifier];
|
|
409
|
-
if (Component) {
|
|
410
|
-
return /* @__PURE__ */ React.createElement(
|
|
411
|
-
Component,
|
|
412
|
-
{
|
|
413
|
-
pageKey,
|
|
414
|
-
navigateTo: this.navigateTo,
|
|
415
|
-
visit,
|
|
416
|
-
remote,
|
|
417
|
-
...ownProps
|
|
418
|
-
}
|
|
419
|
-
);
|
|
420
|
-
} else {
|
|
421
|
-
this.notFound(componentIdentifier);
|
|
422
|
-
}
|
|
389
|
+
// lib/index.tsx
|
|
390
|
+
var hasWindow2 = typeof window !== "undefined";
|
|
391
|
+
var createHistory = () => {
|
|
392
|
+
if (hasWindow2) {
|
|
393
|
+
return createBrowserHistory({});
|
|
394
|
+
} else {
|
|
395
|
+
return createMemoryHistory({});
|
|
423
396
|
}
|
|
424
397
|
};
|
|
425
|
-
var
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
const type = action.type;
|
|
437
|
-
if (actionValues.includes(type)) {
|
|
438
|
-
return nextAction;
|
|
439
|
-
}
|
|
440
|
-
if (prevState.pages === nextState.pages) {
|
|
441
|
-
return nextAction;
|
|
442
|
-
}
|
|
443
|
-
const changedFragments = {};
|
|
444
|
-
const changedKeys = Object.keys(nextState.pages).filter((key) => {
|
|
445
|
-
return prevState.pages[key] !== nextState.pages[key];
|
|
446
|
-
});
|
|
447
|
-
if (changedKeys.length === 0) {
|
|
448
|
-
return nextAction;
|
|
449
|
-
}
|
|
450
|
-
changedKeys.forEach((key) => {
|
|
451
|
-
nextState.pages[key].fragments.forEach((fragment) => {
|
|
452
|
-
const { type: type2, path } = fragment;
|
|
453
|
-
const nextPage = nextState.pages[key];
|
|
454
|
-
const prevPage = prevState.pages[key];
|
|
455
|
-
let nextFragment, prevFragment;
|
|
456
|
-
try {
|
|
457
|
-
prevFragment = getIn(prevPage, path);
|
|
458
|
-
nextFragment = getIn(nextPage, path);
|
|
459
|
-
} catch (err) {
|
|
460
|
-
if (err instanceof KeyPathError) {
|
|
461
|
-
console.warn(err.message);
|
|
462
|
-
} else {
|
|
463
|
-
throw err;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
if (nextFragment !== void 0 && prevFragment !== void 0 && nextFragment !== prevFragment && nextFragment) {
|
|
467
|
-
changedFragments[type2] = nextFragment;
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
});
|
|
471
|
-
if (Object.keys(changedFragments).length === 0) {
|
|
472
|
-
return nextAction;
|
|
473
|
-
}
|
|
474
|
-
store.dispatch({
|
|
475
|
-
type: UPDATE_FRAGMENTS,
|
|
476
|
-
payload: {
|
|
477
|
-
changedFragments
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
return nextAction;
|
|
398
|
+
var prepareStore = (store, initialPage, path) => {
|
|
399
|
+
const location = parse(path);
|
|
400
|
+
const initialPageKey = urlToPageKey(location.href);
|
|
401
|
+
const { csrfToken } = initialPage;
|
|
402
|
+
store.dispatch(
|
|
403
|
+
historyChange({
|
|
404
|
+
pageKey: initialPageKey
|
|
405
|
+
})
|
|
406
|
+
);
|
|
407
|
+
store.dispatch(saveAndProcessPage(initialPageKey, initialPage));
|
|
408
|
+
store.dispatch(setCSRFToken({ csrfToken }));
|
|
481
409
|
};
|
|
482
|
-
|
|
483
|
-
// lib/index.tsx
|
|
484
|
-
function pageToInitialState(key, page) {
|
|
485
|
-
const slices = page.slices || {};
|
|
486
|
-
const nextPage = {
|
|
487
|
-
...page,
|
|
488
|
-
pageKey: key,
|
|
489
|
-
//TODO remove this
|
|
490
|
-
savedAt: Date.now()
|
|
491
|
-
};
|
|
492
|
-
return {
|
|
493
|
-
pages: { [key]: nextPage },
|
|
494
|
-
...slices
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
function start({
|
|
410
|
+
var setup = ({
|
|
498
411
|
initialPage,
|
|
499
|
-
baseUrl
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
412
|
+
baseUrl,
|
|
413
|
+
path,
|
|
414
|
+
store,
|
|
415
|
+
buildVisitAndRemote,
|
|
416
|
+
history,
|
|
417
|
+
navigatorRef
|
|
418
|
+
}) => {
|
|
506
419
|
config.baseUrl = baseUrl;
|
|
507
|
-
|
|
420
|
+
const { visit, remote } = buildVisitAndRemote(navigatorRef, store);
|
|
421
|
+
const initialPageKey = urlToPageKey(parse(path).href);
|
|
422
|
+
const nextHistory = history || createHistory();
|
|
423
|
+
nextHistory.replace(...argsForHistory(path));
|
|
424
|
+
prepareStore(store, initialPage, path);
|
|
425
|
+
const handlers = ujsHandlers({
|
|
426
|
+
visit,
|
|
427
|
+
remote,
|
|
428
|
+
ujsAttributePrefix: "data-sg",
|
|
429
|
+
store
|
|
430
|
+
});
|
|
508
431
|
return {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
pathname: location.pathname,
|
|
515
|
-
search: location.query,
|
|
516
|
-
hash: location.hash
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
store.dispatch(saveAndProcessPage(initialPageKey, initialPage));
|
|
520
|
-
store.dispatch({ type: SET_CSRF_TOKEN, payload: { csrfToken } });
|
|
521
|
-
},
|
|
522
|
-
initialState: pageToInitialState(initialPageKey, initialPage),
|
|
523
|
-
initialPageKey
|
|
432
|
+
visit,
|
|
433
|
+
remote,
|
|
434
|
+
nextHistory,
|
|
435
|
+
initialPageKey,
|
|
436
|
+
ujs: handlers
|
|
524
437
|
};
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
this.history.replace(...argsForHistory(this.props.path));
|
|
547
|
-
const unconnectedMapping = this.mapping();
|
|
548
|
-
const nextMapping = {};
|
|
549
|
-
for (const key in unconnectedMapping) {
|
|
550
|
-
const component = unconnectedMapping[key];
|
|
551
|
-
nextMapping[key] = connect(mapStateToProps, mapDispatchToProps)(component);
|
|
552
|
-
}
|
|
553
|
-
this.connectedMapping = nextMapping;
|
|
554
|
-
const { visit, remote } = this.visitAndRemote(this.navigatorRef, this.store);
|
|
555
|
-
this.visit = visit;
|
|
556
|
-
this.remote = remote;
|
|
557
|
-
}
|
|
558
|
-
componentDidMount() {
|
|
559
|
-
const { appEl } = this.props;
|
|
560
|
-
this.ujsHandlers = ujsHandlers({
|
|
561
|
-
visit: this.visit,
|
|
562
|
-
remote: this.remote,
|
|
563
|
-
ujsAttributePrefix: "data-sg"
|
|
438
|
+
};
|
|
439
|
+
function Application({
|
|
440
|
+
initialPage,
|
|
441
|
+
baseUrl,
|
|
442
|
+
path,
|
|
443
|
+
store,
|
|
444
|
+
buildVisitAndRemote,
|
|
445
|
+
history,
|
|
446
|
+
mapping,
|
|
447
|
+
...rest
|
|
448
|
+
}) {
|
|
449
|
+
const navigatorRef = useRef(null);
|
|
450
|
+
const { visit, remote, nextHistory, initialPageKey, ujs } = useMemo(() => {
|
|
451
|
+
return setup({
|
|
452
|
+
initialPage,
|
|
453
|
+
baseUrl,
|
|
454
|
+
path,
|
|
455
|
+
store,
|
|
456
|
+
buildVisitAndRemote,
|
|
457
|
+
history,
|
|
458
|
+
navigatorRef
|
|
564
459
|
});
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
createHistory() {
|
|
576
|
-
if (this.hasWindow) {
|
|
577
|
-
return createBrowserHistory({});
|
|
578
|
-
} else {
|
|
579
|
-
return createMemoryHistory({});
|
|
460
|
+
}, []);
|
|
461
|
+
return /* @__PURE__ */ React2.createElement("div", { onClick: ujs.onClick, onSubmit: ujs.onSubmit, ...rest }, /* @__PURE__ */ React2.createElement(Provider, { store }, /* @__PURE__ */ React2.createElement(
|
|
462
|
+
NavigationProvider,
|
|
463
|
+
{
|
|
464
|
+
ref: navigatorRef,
|
|
465
|
+
visit,
|
|
466
|
+
remote,
|
|
467
|
+
mapping,
|
|
468
|
+
history: nextHistory,
|
|
469
|
+
initialPageKey
|
|
580
470
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
return /* @__PURE__ */ React2.createElement(Provider, { store: this.store }, /* @__PURE__ */ React2.createElement(
|
|
584
|
-
Nav_default,
|
|
585
|
-
{
|
|
586
|
-
store: this.store,
|
|
587
|
-
ref: this.navigatorRef,
|
|
588
|
-
visit: this.visit,
|
|
589
|
-
remote: this.remote,
|
|
590
|
-
mapping: this.connectedMapping,
|
|
591
|
-
history: this.history,
|
|
592
|
-
initialPageKey: this.initialPageKey
|
|
593
|
-
}
|
|
594
|
-
));
|
|
595
|
-
}
|
|
596
|
-
};
|
|
471
|
+
)));
|
|
472
|
+
}
|
|
597
473
|
export {
|
|
598
|
-
|
|
599
|
-
BEFORE_FETCH,
|
|
600
|
-
BEFORE_REMOTE,
|
|
601
|
-
BEFORE_VISIT,
|
|
602
|
-
COPY_PAGE,
|
|
474
|
+
Application,
|
|
603
475
|
GRAFTING_ERROR,
|
|
604
476
|
GRAFTING_SUCCESS,
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
477
|
+
NavigationContext,
|
|
478
|
+
NavigationProvider,
|
|
479
|
+
beforeFetch,
|
|
480
|
+
beforeRemote,
|
|
481
|
+
beforeVisit,
|
|
482
|
+
copyPage,
|
|
610
483
|
getIn,
|
|
611
|
-
|
|
484
|
+
pageReducer,
|
|
485
|
+
prepareStore,
|
|
486
|
+
removePage,
|
|
487
|
+
rootReducer,
|
|
488
|
+
saveAndProcessPage,
|
|
489
|
+
saveResponse,
|
|
490
|
+
setup,
|
|
491
|
+
superglueReducer,
|
|
492
|
+
updateFragments,
|
|
493
|
+
urlToPageKey,
|
|
494
|
+
useContent,
|
|
495
|
+
useSuperglue
|
|
612
496
|
};
|
|
613
497
|
//# sourceMappingURL=superglue.mjs.map
|