@thoughtbot/superglue 0.53.4 → 1.0.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/.babelrc.js +15 -0
- package/.prettierignore +6 -0
- package/.prettierrc +7 -0
- package/.tool-versions +1 -0
- package/LICENSE +21 -0
- package/dist/action_creators.d.mts +3 -0
- package/dist/action_creators.mjs +13 -0
- package/dist/action_creators.mjs.map +1 -0
- package/dist/chunk-LGUVOEZ3.mjs +790 -0
- package/dist/chunk-LGUVOEZ3.mjs.map +1 -0
- package/dist/cjs/action_creators.cjs +640 -0
- package/dist/cjs/action_creators.cjs.map +1 -0
- package/dist/cjs/superglue.cjs +1178 -0
- package/dist/cjs/superglue.cjs.map +1 -0
- package/dist/index-BYr1PoYr.d.mts +232 -0
- package/dist/superglue.d.mts +64 -0
- package/dist/superglue.mjs +499 -0
- package/dist/superglue.mjs.map +1 -0
- package/package.json +64 -30
- package/tsconfig.json +15 -0
- package/tsup.config.ts +29 -0
- package/typedoc.json +32 -0
- package/README.md +0 -126
- package/action_creators/index.js +0 -144
- package/action_creators/requests.js +0 -207
- package/actions.js +0 -17
- package/components/Nav.js +0 -211
- package/config.js +0 -8
- package/index.js +0 -215
- package/middleware.js +0 -63
- package/reducers/index.js +0 -225
- package/utils/helpers.js +0 -33
- package/utils/immutability.js +0 -128
- package/utils/index.js +0 -45
- package/utils/react.js +0 -40
- package/utils/request.js +0 -120
- package/utils/ujs.js +0 -110
- package/utils/url.js +0 -79
- package/utils/window.js +0 -14
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GRAFTING_ERROR,
|
|
3
|
+
GRAFTING_SUCCESS,
|
|
4
|
+
argsForHistory,
|
|
5
|
+
beforeFetch,
|
|
6
|
+
beforeRemote,
|
|
7
|
+
beforeVisit,
|
|
8
|
+
config,
|
|
9
|
+
copyPage,
|
|
10
|
+
getIn,
|
|
11
|
+
handleGraft,
|
|
12
|
+
historyChange,
|
|
13
|
+
parsePageKey,
|
|
14
|
+
pathWithoutBZParams,
|
|
15
|
+
removePage,
|
|
16
|
+
saveAndProcessPage,
|
|
17
|
+
saveResponse,
|
|
18
|
+
setActivePage,
|
|
19
|
+
setCSRFToken,
|
|
20
|
+
setIn,
|
|
21
|
+
ujsHandlers,
|
|
22
|
+
updateFragments,
|
|
23
|
+
urlToPageKey
|
|
24
|
+
} from "./chunk-LGUVOEZ3.mjs";
|
|
25
|
+
|
|
26
|
+
// lib/index.tsx
|
|
27
|
+
import React2, { useRef, useMemo } from "react";
|
|
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
|
+
forwardRef,
|
|
37
|
+
useImperativeHandle
|
|
38
|
+
} from "react";
|
|
39
|
+
import { useDispatch, useSelector, useStore } from "react-redux";
|
|
40
|
+
var NavigationContext = createContext(
|
|
41
|
+
{}
|
|
42
|
+
);
|
|
43
|
+
var hasWindow = typeof window !== "undefined";
|
|
44
|
+
var setWindowScroll = (posX, posY) => {
|
|
45
|
+
hasWindow && window.scrollTo(posX, posY);
|
|
46
|
+
};
|
|
47
|
+
var notFound = (identifier) => {
|
|
48
|
+
let reminder = "";
|
|
49
|
+
if (!identifier) {
|
|
50
|
+
reminder = "Did you forget to add `json.componentIdentifier` in your application.json.props layout?";
|
|
51
|
+
}
|
|
52
|
+
const error = new Error(
|
|
53
|
+
`Superglue Nav component was looking for ${identifier} but could not find it in your mapping. ${reminder}`
|
|
54
|
+
);
|
|
55
|
+
throw error;
|
|
56
|
+
};
|
|
57
|
+
var NavigationProvider = forwardRef(function NavigationProvider2({ history, visit, remote, mapping }, ref) {
|
|
58
|
+
const dispatch = useDispatch();
|
|
59
|
+
const pages = useSelector((state) => state.pages);
|
|
60
|
+
const superglue = useSelector(
|
|
61
|
+
(state) => state.superglue
|
|
62
|
+
);
|
|
63
|
+
const store = useStore();
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
return history.listen(onHistoryChange);
|
|
66
|
+
}, []);
|
|
67
|
+
useImperativeHandle(
|
|
68
|
+
ref,
|
|
69
|
+
() => {
|
|
70
|
+
return {
|
|
71
|
+
navigateTo
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
[]
|
|
75
|
+
);
|
|
76
|
+
const visitAndRestore = (pageKey, posX, posY) => {
|
|
77
|
+
return visit(pageKey, { revisit: true }).then((meta) => {
|
|
78
|
+
if (meta) {
|
|
79
|
+
if (meta.navigationAction === "none") {
|
|
80
|
+
dispatch(setActivePage({ pageKey }));
|
|
81
|
+
setWindowScroll(posX, posY);
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
console.warn(
|
|
85
|
+
`scoll restoration was skipped. Your visit's then funtion
|
|
86
|
+
should return the meta object it recieved if you want your
|
|
87
|
+
application to restore the page's previous scroll.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const onHistoryChange = ({ location, action }) => {
|
|
93
|
+
const state = location.state;
|
|
94
|
+
if (!state && location.hash !== "" && action === "POP") {
|
|
95
|
+
const nextPageKey = urlToPageKey(location.pathname + location.search);
|
|
96
|
+
const containsKey = !!pages[nextPageKey];
|
|
97
|
+
if (containsKey) {
|
|
98
|
+
history.replace(
|
|
99
|
+
{
|
|
100
|
+
pathname: location.pathname,
|
|
101
|
+
search: location.search,
|
|
102
|
+
hash: location.hash
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
pageKey: nextPageKey,
|
|
106
|
+
superglue: true,
|
|
107
|
+
posY: window.pageYOffset,
|
|
108
|
+
posX: window.pageXOffset
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (state && "superglue" in state) {
|
|
114
|
+
dispatch(
|
|
115
|
+
historyChange({
|
|
116
|
+
pageKey: state.pageKey
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
if (action !== "POP") {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const { pageKey, posX, posY } = state;
|
|
123
|
+
const containsKey = !!pages[pageKey];
|
|
124
|
+
if (containsKey) {
|
|
125
|
+
const { restoreStrategy } = pages[pageKey];
|
|
126
|
+
switch (restoreStrategy) {
|
|
127
|
+
case "fromCacheOnly":
|
|
128
|
+
dispatch(setActivePage({ pageKey }));
|
|
129
|
+
setWindowScroll(posX, posY);
|
|
130
|
+
break;
|
|
131
|
+
case "fromCacheAndRevisitInBackground":
|
|
132
|
+
dispatch(setActivePage({ pageKey }));
|
|
133
|
+
setWindowScroll(posX, posY);
|
|
134
|
+
visit(pageKey, { revisit: true });
|
|
135
|
+
break;
|
|
136
|
+
case "revisitOnly":
|
|
137
|
+
default:
|
|
138
|
+
visitAndRestore(pageKey, posX, posY);
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
visitAndRestore(pageKey, posX, posY);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const navigateTo = (path, { action } = {
|
|
146
|
+
action: "push"
|
|
147
|
+
}) => {
|
|
148
|
+
if (action === "none") {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
path = pathWithoutBZParams(path);
|
|
152
|
+
const nextPageKey = urlToPageKey(path);
|
|
153
|
+
const hasPage = Object.prototype.hasOwnProperty.call(
|
|
154
|
+
store.getState().pages,
|
|
155
|
+
nextPageKey
|
|
156
|
+
);
|
|
157
|
+
if (hasPage) {
|
|
158
|
+
const location = history.location;
|
|
159
|
+
const state = location.state;
|
|
160
|
+
const prevPageKey = state.pageKey;
|
|
161
|
+
const historyArgs = [
|
|
162
|
+
path,
|
|
163
|
+
{
|
|
164
|
+
pageKey: nextPageKey,
|
|
165
|
+
superglue: true,
|
|
166
|
+
posY: 0,
|
|
167
|
+
posX: 0
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
if (action === "push") {
|
|
171
|
+
if (hasWindow) {
|
|
172
|
+
history.replace(
|
|
173
|
+
{
|
|
174
|
+
pathname: location.pathname,
|
|
175
|
+
search: location.search,
|
|
176
|
+
hash: location.hash
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
...state,
|
|
180
|
+
posY: window.pageYOffset,
|
|
181
|
+
posX: window.pageXOffset
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
history.push(...historyArgs);
|
|
186
|
+
}
|
|
187
|
+
if (action === "replace") {
|
|
188
|
+
history.replace(...historyArgs);
|
|
189
|
+
}
|
|
190
|
+
setActivePage({ pageKey: nextPageKey });
|
|
191
|
+
setWindowScroll(0, 0);
|
|
192
|
+
if (action === "replace" && prevPageKey && prevPageKey !== nextPageKey) {
|
|
193
|
+
dispatch(removePage({ pageKey: prevPageKey }));
|
|
194
|
+
}
|
|
195
|
+
return true;
|
|
196
|
+
} else {
|
|
197
|
+
console.warn(
|
|
198
|
+
`\`navigateTo\` was called , but could not find
|
|
199
|
+
the pageKey in the store. This may happen when the wrong
|
|
200
|
+
content_location was set in your non-get controller action.
|
|
201
|
+
No navigation will take place`
|
|
202
|
+
);
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const { currentPageKey, search } = superglue;
|
|
207
|
+
const { componentIdentifier } = pages[currentPageKey];
|
|
208
|
+
const Component = mapping[componentIdentifier];
|
|
209
|
+
if (Component) {
|
|
210
|
+
return /* @__PURE__ */ React.createElement(
|
|
211
|
+
NavigationContext.Provider,
|
|
212
|
+
{
|
|
213
|
+
value: { pageKey: currentPageKey, search, navigateTo, visit, remote }
|
|
214
|
+
},
|
|
215
|
+
/* @__PURE__ */ React.createElement(Component, null)
|
|
216
|
+
);
|
|
217
|
+
} else {
|
|
218
|
+
notFound(componentIdentifier);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// lib/reducers/index.ts
|
|
223
|
+
function addPlaceholdersToDeferredNodes(existingPage, page) {
|
|
224
|
+
const { defers = [] } = existingPage;
|
|
225
|
+
const prevDefers = defers.map(({ path }) => {
|
|
226
|
+
const node = getIn(existingPage, path);
|
|
227
|
+
const copy = JSON.stringify(node);
|
|
228
|
+
return [path, JSON.parse(copy)];
|
|
229
|
+
});
|
|
230
|
+
return prevDefers.reduce((memo, [path, node]) => {
|
|
231
|
+
return setIn(page, path, node);
|
|
232
|
+
}, page);
|
|
233
|
+
}
|
|
234
|
+
function constrainPagesSize(state) {
|
|
235
|
+
const { maxPages } = config;
|
|
236
|
+
const allPageKeys = Object.keys(state);
|
|
237
|
+
const cacheTimesRecentFirst = allPageKeys.map((key) => state[key].savedAt).sort((a, b) => b - a);
|
|
238
|
+
for (const key of Array.from(allPageKeys)) {
|
|
239
|
+
if (state[key].savedAt <= cacheTimesRecentFirst[maxPages - 1]) {
|
|
240
|
+
delete state[key];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function handleSaveResponse(state, pageKey, page) {
|
|
245
|
+
state = { ...state };
|
|
246
|
+
let nextPage = {
|
|
247
|
+
...page,
|
|
248
|
+
savedAt: Date.now()
|
|
249
|
+
};
|
|
250
|
+
const existingPage = state[pageKey];
|
|
251
|
+
if (existingPage) {
|
|
252
|
+
nextPage = addPlaceholdersToDeferredNodes(existingPage, nextPage);
|
|
253
|
+
}
|
|
254
|
+
constrainPagesSize(state);
|
|
255
|
+
state[pageKey] = nextPage;
|
|
256
|
+
return state;
|
|
257
|
+
}
|
|
258
|
+
function appendReceivedFragmentsOntoPage(state, pageKey, receivedFragments) {
|
|
259
|
+
if (!pageKey) {
|
|
260
|
+
return state;
|
|
261
|
+
}
|
|
262
|
+
if (receivedFragments.length === 0) {
|
|
263
|
+
return state;
|
|
264
|
+
}
|
|
265
|
+
const currentPage = state[pageKey];
|
|
266
|
+
const { fragments: prevFragments = [] } = currentPage;
|
|
267
|
+
const nextFragments = [...prevFragments];
|
|
268
|
+
const existingKeys = {};
|
|
269
|
+
prevFragments.forEach((frag) => existingKeys[frag.path] = true);
|
|
270
|
+
receivedFragments.forEach((frag) => {
|
|
271
|
+
if (!existingKeys[frag.path]) {
|
|
272
|
+
nextFragments.push(frag);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
const nextPage = {
|
|
276
|
+
...currentPage,
|
|
277
|
+
fragments: nextFragments
|
|
278
|
+
};
|
|
279
|
+
const nextState = { ...state };
|
|
280
|
+
nextState[pageKey] = nextPage;
|
|
281
|
+
return nextState;
|
|
282
|
+
}
|
|
283
|
+
function graftNodeOntoPage(state, pageKey, node, pathToNode) {
|
|
284
|
+
if (!node) {
|
|
285
|
+
console.warn(
|
|
286
|
+
"There was no node returned in the response. Do you have the correct key path in your props_at?"
|
|
287
|
+
);
|
|
288
|
+
return state;
|
|
289
|
+
}
|
|
290
|
+
if (!pathToNode || !pageKey) {
|
|
291
|
+
return state;
|
|
292
|
+
}
|
|
293
|
+
const fullPathToNode = [pageKey, pathToNode].join(".");
|
|
294
|
+
return setIn(state, fullPathToNode, node);
|
|
295
|
+
}
|
|
296
|
+
function handleGraftResponse(state, pageKey, page) {
|
|
297
|
+
const currentPage = state[pageKey];
|
|
298
|
+
if (!currentPage) {
|
|
299
|
+
const error = new Error(
|
|
300
|
+
`Superglue was looking for ${pageKey} in your state, but could not find it in your mapping. Did you forget to pass in a valid pageKey to this.props.remote or this.props.visit?`
|
|
301
|
+
);
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
const {
|
|
305
|
+
data: receivedNode,
|
|
306
|
+
path: pathToNode,
|
|
307
|
+
fragments: receivedFragments = []
|
|
308
|
+
} = page;
|
|
309
|
+
return [
|
|
310
|
+
(nextState) => graftNodeOntoPage(nextState, pageKey, receivedNode, pathToNode),
|
|
311
|
+
(nextState) => appendReceivedFragmentsOntoPage(nextState, pageKey, receivedFragments)
|
|
312
|
+
].reduce((memo, fn) => fn(memo), state);
|
|
313
|
+
}
|
|
314
|
+
function pageReducer(state = {}, action) {
|
|
315
|
+
if (removePage.match(action)) {
|
|
316
|
+
const { pageKey } = action.payload;
|
|
317
|
+
const nextState = { ...state };
|
|
318
|
+
delete nextState[pageKey];
|
|
319
|
+
return nextState;
|
|
320
|
+
}
|
|
321
|
+
if (copyPage.match(action)) {
|
|
322
|
+
const nextState = { ...state };
|
|
323
|
+
const { from, to } = action.payload;
|
|
324
|
+
nextState[urlToPageKey(to)] = JSON.parse(JSON.stringify(nextState[from]));
|
|
325
|
+
return nextState;
|
|
326
|
+
}
|
|
327
|
+
if (handleGraft.match(action)) {
|
|
328
|
+
const { pageKey, page } = action.payload;
|
|
329
|
+
return handleGraftResponse(state, pageKey, page);
|
|
330
|
+
}
|
|
331
|
+
if (saveResponse.match(action)) {
|
|
332
|
+
const { pageKey, page } = action.payload;
|
|
333
|
+
const nextState = handleSaveResponse(state, pageKey, page);
|
|
334
|
+
return nextState;
|
|
335
|
+
}
|
|
336
|
+
return state;
|
|
337
|
+
}
|
|
338
|
+
function superglueReducer(state = {
|
|
339
|
+
currentPageKey: "",
|
|
340
|
+
search: {},
|
|
341
|
+
assets: []
|
|
342
|
+
}, action) {
|
|
343
|
+
if (setCSRFToken.match(action)) {
|
|
344
|
+
const { csrfToken } = action.payload;
|
|
345
|
+
return { ...state, csrfToken };
|
|
346
|
+
}
|
|
347
|
+
if (setActivePage.match(action)) {
|
|
348
|
+
const { pageKey } = action.payload;
|
|
349
|
+
const { search } = parsePageKey(pageKey);
|
|
350
|
+
return {
|
|
351
|
+
...state,
|
|
352
|
+
search,
|
|
353
|
+
currentPageKey: pageKey
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
if (historyChange.match(action)) {
|
|
357
|
+
const { pageKey } = action.payload;
|
|
358
|
+
const { search } = parsePageKey(pageKey);
|
|
359
|
+
return {
|
|
360
|
+
...state,
|
|
361
|
+
currentPageKey: pageKey,
|
|
362
|
+
search
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
if (saveResponse.match(action)) {
|
|
366
|
+
const {
|
|
367
|
+
page: { csrfToken, assets }
|
|
368
|
+
} = action.payload;
|
|
369
|
+
return { ...state, csrfToken, assets };
|
|
370
|
+
}
|
|
371
|
+
return state;
|
|
372
|
+
}
|
|
373
|
+
var rootReducer = {
|
|
374
|
+
superglue: superglueReducer,
|
|
375
|
+
pages: pageReducer
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// lib/hooks/index.ts
|
|
379
|
+
import { useSelector as useSelector2 } from "react-redux";
|
|
380
|
+
function useSuperglue() {
|
|
381
|
+
return useSelector2((state) => state.superglue);
|
|
382
|
+
}
|
|
383
|
+
function useContent() {
|
|
384
|
+
const superglueState = useSuperglue();
|
|
385
|
+
const currentPageKey = superglueState.currentPageKey;
|
|
386
|
+
return useSelector2(
|
|
387
|
+
(state) => state.pages[currentPageKey]
|
|
388
|
+
).data;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// lib/index.tsx
|
|
392
|
+
var hasWindow2 = typeof window !== "undefined";
|
|
393
|
+
var createHistory = () => {
|
|
394
|
+
if (hasWindow2) {
|
|
395
|
+
return createBrowserHistory({});
|
|
396
|
+
} else {
|
|
397
|
+
return createMemoryHistory({});
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
var prepareStore = (store, initialPage, path) => {
|
|
401
|
+
const location = parse(path);
|
|
402
|
+
const initialPageKey = urlToPageKey(location.href);
|
|
403
|
+
const { csrfToken } = initialPage;
|
|
404
|
+
store.dispatch(
|
|
405
|
+
historyChange({
|
|
406
|
+
pageKey: initialPageKey
|
|
407
|
+
})
|
|
408
|
+
);
|
|
409
|
+
store.dispatch(saveAndProcessPage(initialPageKey, initialPage));
|
|
410
|
+
store.dispatch(setCSRFToken({ csrfToken }));
|
|
411
|
+
};
|
|
412
|
+
var setup = ({
|
|
413
|
+
initialPage,
|
|
414
|
+
baseUrl,
|
|
415
|
+
path,
|
|
416
|
+
store,
|
|
417
|
+
buildVisitAndRemote,
|
|
418
|
+
history,
|
|
419
|
+
navigatorRef
|
|
420
|
+
}) => {
|
|
421
|
+
config.baseUrl = baseUrl;
|
|
422
|
+
const { visit, remote } = buildVisitAndRemote(navigatorRef, store);
|
|
423
|
+
const initialPageKey = urlToPageKey(parse(path).href);
|
|
424
|
+
const nextHistory = history || createHistory();
|
|
425
|
+
nextHistory.replace(...argsForHistory(path));
|
|
426
|
+
prepareStore(store, initialPage, path);
|
|
427
|
+
const handlers = ujsHandlers({
|
|
428
|
+
visit,
|
|
429
|
+
remote,
|
|
430
|
+
ujsAttributePrefix: "data-sg",
|
|
431
|
+
store
|
|
432
|
+
});
|
|
433
|
+
return {
|
|
434
|
+
visit,
|
|
435
|
+
remote,
|
|
436
|
+
nextHistory,
|
|
437
|
+
initialPageKey,
|
|
438
|
+
ujs: handlers
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
function Application({
|
|
442
|
+
initialPage,
|
|
443
|
+
baseUrl,
|
|
444
|
+
path,
|
|
445
|
+
store,
|
|
446
|
+
buildVisitAndRemote,
|
|
447
|
+
history,
|
|
448
|
+
mapping,
|
|
449
|
+
...rest
|
|
450
|
+
}) {
|
|
451
|
+
const navigatorRef = useRef(null);
|
|
452
|
+
const { visit, remote, nextHistory, initialPageKey, ujs } = useMemo(() => {
|
|
453
|
+
return setup({
|
|
454
|
+
initialPage,
|
|
455
|
+
baseUrl,
|
|
456
|
+
path,
|
|
457
|
+
store,
|
|
458
|
+
buildVisitAndRemote,
|
|
459
|
+
history,
|
|
460
|
+
navigatorRef
|
|
461
|
+
});
|
|
462
|
+
}, []);
|
|
463
|
+
return /* @__PURE__ */ React2.createElement("div", { onClick: ujs.onClick, onSubmit: ujs.onSubmit, ...rest }, /* @__PURE__ */ React2.createElement(Provider, { store }, /* @__PURE__ */ React2.createElement(
|
|
464
|
+
NavigationProvider,
|
|
465
|
+
{
|
|
466
|
+
ref: navigatorRef,
|
|
467
|
+
visit,
|
|
468
|
+
remote,
|
|
469
|
+
mapping,
|
|
470
|
+
history: nextHistory,
|
|
471
|
+
initialPageKey
|
|
472
|
+
}
|
|
473
|
+
)));
|
|
474
|
+
}
|
|
475
|
+
export {
|
|
476
|
+
Application,
|
|
477
|
+
GRAFTING_ERROR,
|
|
478
|
+
GRAFTING_SUCCESS,
|
|
479
|
+
NavigationContext,
|
|
480
|
+
NavigationProvider,
|
|
481
|
+
beforeFetch,
|
|
482
|
+
beforeRemote,
|
|
483
|
+
beforeVisit,
|
|
484
|
+
copyPage,
|
|
485
|
+
getIn,
|
|
486
|
+
pageReducer,
|
|
487
|
+
prepareStore,
|
|
488
|
+
removePage,
|
|
489
|
+
rootReducer,
|
|
490
|
+
saveAndProcessPage,
|
|
491
|
+
saveResponse,
|
|
492
|
+
setup,
|
|
493
|
+
superglueReducer,
|
|
494
|
+
updateFragments,
|
|
495
|
+
urlToPageKey,
|
|
496
|
+
useContent,
|
|
497
|
+
useSuperglue
|
|
498
|
+
};
|
|
499
|
+
//# sourceMappingURL=superglue.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../lib/index.tsx","../lib/components/Navigation.tsx","../lib/reducers/index.ts","../lib/hooks/index.ts"],"sourcesContent":["import React, { useRef, useMemo } from 'react'\nimport parse from 'url-parse'\nimport { config } from './config'\nimport { urlToPageKey, ujsHandlers, argsForHistory } from './utils'\nimport { saveAndProcessPage } from './action_creators'\nimport { historyChange, setCSRFToken } from './actions'\nimport { Provider } from 'react-redux'\n\nimport { createBrowserHistory, createMemoryHistory } from 'history'\n\nimport { NavigationProvider } from './components/Navigation'\nexport { NavigationProvider, NavigationContext } from './components/Navigation'\nexport { saveAndProcessPage } from './action_creators'\nexport {\n beforeFetch,\n beforeVisit,\n beforeRemote,\n updateFragments,\n copyPage,\n removePage,\n saveResponse,\n GRAFTING_ERROR,\n GRAFTING_SUCCESS,\n} from './actions'\nexport * from './types'\n\nimport {\n VisitResponse,\n ApplicationProps,\n NavigateTo,\n SuperglueStore,\n SetupProps,\n} from './types'\nexport { superglueReducer, pageReducer, rootReducer } from './reducers'\nexport { getIn } from './utils/immutability'\nexport { urlToPageKey }\nexport * from './hooks'\n\nconst hasWindow = typeof window !== 'undefined'\n\nconst createHistory = () => {\n if (hasWindow) {\n // This is used for client side rendering\n return createBrowserHistory({})\n } else {\n // This is used for server side rendering\n return createMemoryHistory({})\n }\n}\n\nexport const prepareStore = (\n store: SuperglueStore,\n initialPage: VisitResponse,\n path: string\n) => {\n const location = parse(path)\n const initialPageKey = urlToPageKey(location.href)\n const { csrfToken } = initialPage\n\n store.dispatch(\n historyChange({\n pageKey: initialPageKey,\n })\n )\n store.dispatch(saveAndProcessPage(initialPageKey, initialPage))\n store.dispatch(setCSRFToken({ csrfToken }))\n}\n\n/**\n * This is the setup function that the Application calls. Use this function if\n * you like to build your own Application component.\n */\nexport const setup = ({\n initialPage,\n baseUrl,\n path,\n store,\n buildVisitAndRemote,\n history,\n navigatorRef,\n}: SetupProps) => {\n config.baseUrl = baseUrl\n\n const { visit, remote } = buildVisitAndRemote(navigatorRef, store)\n\n const initialPageKey = urlToPageKey(parse(path).href)\n const nextHistory = history || createHistory()\n nextHistory.replace(...argsForHistory(path))\n prepareStore(store, initialPage, path)\n\n const handlers = ujsHandlers({\n visit,\n remote,\n ujsAttributePrefix: 'data-sg',\n store,\n })\n\n return {\n visit,\n remote,\n nextHistory,\n initialPageKey,\n ujs: handlers,\n }\n}\n\n/**\n * The entry point to your superglue application. It sets up the redux Provider,\n * redux state and the Navigation component.\n *\n * This is a simple component, you can override this by copying the source code and\n * use the exported methods used by this component (`start` and `ujsHandler`).\n */\nfunction Application({\n initialPage,\n baseUrl,\n path,\n store,\n buildVisitAndRemote,\n history,\n mapping,\n ...rest\n}: ApplicationProps) {\n const navigatorRef = useRef<{ navigateTo: NavigateTo } | null>(null)\n\n const { visit, remote, nextHistory, initialPageKey, ujs } = useMemo(() => {\n return setup({\n initialPage,\n baseUrl,\n path,\n store,\n buildVisitAndRemote,\n history,\n navigatorRef,\n })\n }, [])\n\n // The Nav component is pretty bare and can be inherited from for custom\n // behavior or replaced with your own.\n return (\n <div onClick={ujs.onClick} onSubmit={ujs.onSubmit} {...rest}>\n <Provider store={store}>\n <NavigationProvider\n ref={navigatorRef}\n visit={visit}\n remote={remote}\n mapping={mapping}\n history={nextHistory}\n initialPageKey={initialPageKey}\n />\n </Provider>\n </div>\n )\n}\n\nexport { Application }\n","import React, {\n createContext,\n useEffect,\n forwardRef,\n useImperativeHandle,\n ForwardedRef,\n} from 'react'\nimport { urlToPageKey, pathWithoutBZParams } from '../utils'\nimport { removePage, historyChange, setActivePage } from '../actions'\nimport {\n HistoryState,\n RootState,\n NavigateTo,\n NavigationContextProps,\n NavigationProviderProps,\n AllPages,\n SuperglueState,\n PageKey,\n} from '../types'\nimport { Update } from 'history'\nimport { useDispatch, useSelector, useStore } from 'react-redux'\n\nconst NavigationContext = createContext<NavigationContextProps>(\n {} as NavigationContextProps\n)\n\nconst hasWindow = typeof window !== 'undefined'\n\nconst setWindowScroll = (posX: number, posY: number): void => {\n hasWindow && window.scrollTo(posX, posY)\n}\n\nconst notFound = (identifier: string | undefined): never => {\n let reminder = ''\n if (!identifier) {\n reminder =\n 'Did you forget to add `json.componentIdentifier` in your application.json.props layout?'\n }\n\n const error = new Error(\n `Superglue Nav component was looking for ${identifier} but could not find it in your mapping. ${reminder}`\n )\n\n throw error\n}\n\nconst NavigationProvider = forwardRef(function NavigationProvider(\n { history, visit, remote, mapping }: NavigationProviderProps,\n ref: ForwardedRef<{ navigateTo: NavigateTo | null }>\n) {\n const dispatch = useDispatch()\n const pages = useSelector<RootState, AllPages>((state) => state.pages)\n const superglue = useSelector<RootState, SuperglueState>(\n (state) => state.superglue\n )\n const store = useStore()\n\n useEffect(() => {\n return history.listen(onHistoryChange)\n }, [])\n\n useImperativeHandle(\n ref,\n () => {\n return {\n navigateTo,\n }\n },\n []\n )\n\n const visitAndRestore = (pageKey: PageKey, posX: number, posY: number) => {\n // When the application visit gets called with revisit: true\n // - In cases where the response was not redirected, the calculated\n // navigationAction is set to 'none' (meaning `navigateTo` immediately returned `false`)\n // and so we have restore scroll and the set the active page\n // - In cases where the response was redirected, the calculated\n // navigationAction is set to 'replace', and is handled gracefully by navigateTo,\n // before this method gets called.\n // That's why we're only concerned with the first case, but we gracefully warn\n // if the application visit did not return the meta object like the dev was supposed to.\n return visit(pageKey, { revisit: true }).then((meta) => {\n if (meta) {\n if (meta.navigationAction === 'none') {\n dispatch(setActivePage({ pageKey }))\n setWindowScroll(posX, posY)\n }\n } else {\n console.warn(\n `scoll restoration was skipped. Your visit's then funtion\n should return the meta object it recieved if you want your\n application to restore the page's previous scroll.`\n )\n }\n })\n }\n\n const onHistoryChange = ({ location, action }: Update): void => {\n const state = location.state as HistoryState\n\n if (!state && location.hash !== '' && action === 'POP') {\n const nextPageKey = urlToPageKey(location.pathname + location.search)\n const containsKey = !!pages[nextPageKey]\n if (containsKey) {\n history.replace(\n {\n pathname: location.pathname,\n search: location.search,\n hash: location.hash,\n },\n {\n pageKey: nextPageKey,\n superglue: true,\n posY: window.pageYOffset,\n posX: window.pageXOffset,\n }\n )\n }\n }\n\n if (state && 'superglue' in state) {\n dispatch(\n historyChange({\n pageKey: state.pageKey,\n })\n )\n\n if (action !== 'POP') {\n return\n }\n\n const { pageKey, posX, posY } = state\n const containsKey = !!pages[pageKey]\n\n if (containsKey) {\n const { restoreStrategy } = pages[pageKey]\n\n switch (restoreStrategy) {\n case 'fromCacheOnly':\n dispatch(setActivePage({ pageKey }))\n setWindowScroll(posX, posY)\n break\n case 'fromCacheAndRevisitInBackground':\n dispatch(setActivePage({ pageKey }))\n setWindowScroll(posX, posY)\n visit(pageKey, { revisit: true })\n break\n case 'revisitOnly':\n default:\n visitAndRestore(pageKey, posX, posY)\n }\n } else {\n visitAndRestore(pageKey, posX, posY)\n }\n }\n }\n\n const navigateTo: NavigateTo = (\n path,\n { action } = {\n action: 'push',\n }\n ) => {\n if (action === 'none') {\n return false\n }\n\n path = pathWithoutBZParams(path)\n const nextPageKey = urlToPageKey(path)\n const hasPage = Object.prototype.hasOwnProperty.call(\n store.getState().pages,\n nextPageKey\n )\n\n if (hasPage) {\n const location = history.location\n const state = location.state as HistoryState\n const prevPageKey = state.pageKey\n const historyArgs = [\n path,\n {\n pageKey: nextPageKey,\n superglue: true,\n posY: 0,\n posX: 0,\n },\n ] as const\n\n if (action === 'push') {\n if (hasWindow) {\n history.replace(\n {\n pathname: location.pathname,\n search: location.search,\n hash: location.hash,\n },\n {\n ...state,\n posY: window.pageYOffset,\n posX: window.pageXOffset,\n }\n )\n }\n\n history.push(...historyArgs)\n }\n\n if (action === 'replace') {\n history.replace(...historyArgs)\n }\n\n setActivePage({ pageKey: nextPageKey })\n setWindowScroll(0, 0)\n\n if (action === 'replace' && prevPageKey && prevPageKey !== nextPageKey) {\n dispatch(removePage({ pageKey: prevPageKey }))\n }\n\n return true\n } else {\n console.warn(\n `\\`navigateTo\\` was called , but could not find\n the pageKey in the store. This may happen when the wrong\n content_location was set in your non-get controller action.\n No navigation will take place`\n )\n return false\n }\n }\n\n const { currentPageKey, search } = superglue\n const { componentIdentifier } = pages[currentPageKey]\n const Component = mapping[componentIdentifier]\n\n if (Component) {\n return (\n <NavigationContext.Provider\n value={{ pageKey: currentPageKey, search, navigateTo, visit, remote }}\n >\n <Component />\n </NavigationContext.Provider>\n )\n } else {\n notFound(componentIdentifier)\n }\n})\n\nexport { NavigationContext, NavigationProvider }\n","import { setIn, getIn, urlToPageKey, parsePageKey } from '../utils'\nimport type { Action } from '@reduxjs/toolkit'\nimport {\n saveResponse,\n handleGraft,\n historyChange,\n copyPage,\n setCSRFToken,\n setActivePage,\n removePage,\n} from '../actions'\nimport { config } from '../config'\nimport {\n AllPages,\n Page,\n VisitResponse,\n Fragment,\n GraftResponse,\n SuperglueState,\n JSONMappable,\n} from '../types'\n\nfunction addPlaceholdersToDeferredNodes(existingPage: Page, page: Page): Page {\n const { defers = [] } = existingPage\n\n const prevDefers = defers.map(({ path }) => {\n const node = getIn(existingPage, path)\n const copy = JSON.stringify(node)\n return [path, JSON.parse(copy)]\n })\n\n return prevDefers.reduce((memo, [path, node]) => {\n return setIn(page, path, node)\n }, page)\n}\n\nfunction constrainPagesSize(state: AllPages) {\n const { maxPages } = config\n const allPageKeys = Object.keys(state)\n const cacheTimesRecentFirst = allPageKeys\n .map((key) => state[key].savedAt)\n .sort((a, b) => b - a)\n\n for (const key of Array.from(allPageKeys)) {\n if (state[key].savedAt <= cacheTimesRecentFirst[maxPages - 1]) {\n delete state[key]\n }\n }\n}\n\nfunction handleSaveResponse(\n state: AllPages,\n pageKey: string,\n page: VisitResponse\n): AllPages {\n state = { ...state }\n\n let nextPage: Page = {\n ...page,\n savedAt: Date.now(),\n }\n\n const existingPage = state[pageKey]\n\n if (existingPage) {\n nextPage = addPlaceholdersToDeferredNodes(existingPage, nextPage)\n }\n constrainPagesSize(state)\n state[pageKey] = nextPage\n\n return state\n}\n\nexport function appendReceivedFragmentsOntoPage(\n state: AllPages,\n pageKey: string,\n receivedFragments: Fragment[]\n): AllPages {\n if (!pageKey) {\n return state\n }\n\n if (receivedFragments.length === 0) {\n return state\n }\n\n const currentPage = state[pageKey]\n const { fragments: prevFragments = [] } = currentPage\n const nextFragments = [...prevFragments]\n const existingKeys: Record<string, boolean> = {}\n prevFragments.forEach((frag) => (existingKeys[frag.path] = true))\n\n receivedFragments.forEach((frag) => {\n if (!existingKeys[frag.path]) {\n nextFragments.push(frag)\n }\n })\n\n const nextPage = {\n ...currentPage,\n fragments: nextFragments,\n }\n\n const nextState = { ...state }\n nextState[pageKey] = nextPage\n\n return nextState\n}\n\nexport function graftNodeOntoPage(\n state: AllPages,\n pageKey: string,\n node: JSONMappable,\n pathToNode: string\n): AllPages {\n if (!node) {\n console.warn(\n 'There was no node returned in the response. Do you have the correct key path in your props_at?'\n )\n return state\n }\n\n if (!pathToNode || !pageKey) {\n return state\n }\n const fullPathToNode = [pageKey, pathToNode].join('.')\n return setIn(state, fullPathToNode, node)\n}\n\nfunction handleGraftResponse(\n state: AllPages,\n pageKey: string,\n page: GraftResponse\n): AllPages {\n const currentPage = state[pageKey]\n if (!currentPage) {\n const error = new Error(\n `Superglue was looking for ${pageKey} in your state, but could not find it in your mapping. Did you forget to pass in a valid pageKey to this.props.remote or this.props.visit?`\n )\n throw error\n }\n const {\n data: receivedNode,\n path: pathToNode,\n fragments: receivedFragments = [],\n } = page\n\n return [\n (nextState: AllPages) =>\n graftNodeOntoPage(nextState, pageKey, receivedNode, pathToNode),\n (nextState: AllPages) =>\n appendReceivedFragmentsOntoPage(nextState, pageKey, receivedFragments),\n ].reduce((memo, fn) => fn(memo), state)\n}\n\nexport function pageReducer(state: AllPages = {}, action: Action): AllPages {\n if (removePage.match(action)) {\n const { pageKey } = action.payload\n const nextState = { ...state }\n delete nextState[pageKey]\n\n return nextState\n }\n\n if (copyPage.match(action)) {\n const nextState = { ...state }\n const { from, to } = action.payload\n\n nextState[urlToPageKey(to)] = JSON.parse(JSON.stringify(nextState[from]))\n\n return nextState\n }\n\n if (handleGraft.match(action)) {\n const { pageKey, page } = action.payload\n\n return handleGraftResponse(state, pageKey, page)\n }\n\n if (saveResponse.match(action)) {\n const { pageKey, page } = action.payload\n const nextState = handleSaveResponse(state, pageKey, page)\n return nextState\n }\n\n return state\n}\n\nexport function superglueReducer(\n state: SuperglueState = {\n currentPageKey: '',\n search: {},\n assets: [],\n },\n action: Action\n): SuperglueState {\n if (setCSRFToken.match(action)) {\n const { csrfToken } = action.payload\n return { ...state, csrfToken: csrfToken }\n }\n\n if (setActivePage.match(action)) {\n const { pageKey } = action.payload\n const { search } = parsePageKey(pageKey)\n\n return {\n ...state,\n search,\n currentPageKey: pageKey,\n }\n }\n\n if (historyChange.match(action)) {\n const { pageKey } = action.payload\n const { search } = parsePageKey(pageKey)\n\n return {\n ...state,\n currentPageKey: pageKey,\n search,\n }\n }\n\n if (saveResponse.match(action)) {\n const {\n page: { csrfToken, assets },\n } = action.payload\n\n return { ...state, csrfToken, assets }\n }\n\n return state\n}\n\nexport const rootReducer = {\n superglue: superglueReducer,\n pages: pageReducer,\n}\n","import { useSelector } from 'react-redux'\nimport { JSONMappable, Page, RootState, SuperglueState } from '../types'\n\n/**\n * A lightweight hook that grabs the superglue state from the store.\n */\nexport function useSuperglue() {\n return useSelector<RootState, SuperglueState>((state) => state.superglue)\n}\n\n/**\n * A lightweight hook that grabs the current page's content from the store.\n */\nexport function useContent<T = JSONMappable>() {\n const superglueState = useSuperglue()\n const currentPageKey = superglueState.currentPageKey\n\n return useSelector<RootState<T>, Page<T>>(\n (state) => state.pages[currentPageKey]\n ).data\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAOA,UAAS,QAAQ,eAAe;AACvC,OAAO,WAAW;AAKlB,SAAS,gBAAgB;AAEzB,SAAS,sBAAsB,2BAA2B;;;ACR1D,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAcP,SAAS,aAAa,aAAa,gBAAgB;AAEnD,IAAM,oBAAoB;AAAA,EACxB,CAAC;AACH;AAEA,IAAM,YAAY,OAAO,WAAW;AAEpC,IAAM,kBAAkB,CAAC,MAAc,SAAuB;AAC5D,eAAa,OAAO,SAAS,MAAM,IAAI;AACzC;AAEA,IAAM,WAAW,CAAC,eAA0C;AAC1D,MAAI,WAAW;AACf,MAAI,CAAC,YAAY;AACf,eACE;AAAA,EACJ;AAEA,QAAM,QAAQ,IAAI;AAAA,IAChB,2CAA2C,UAAU,2CAA2C,QAAQ;AAAA,EAC1G;AAEA,QAAM;AACR;AAEA,IAAM,qBAAqB,WAAW,SAASC,oBAC7C,EAAE,SAAS,OAAO,QAAQ,QAAQ,GAClC,KACA;AACA,QAAM,WAAW,YAAY;AAC7B,QAAM,QAAQ,YAAiC,CAAC,UAAU,MAAM,KAAK;AACrE,QAAM,YAAY;AAAA,IAChB,CAAC,UAAU,MAAM;AAAA,EACnB;AACA,QAAM,QAAQ,SAAS;AAEvB,YAAU,MAAM;AACd,WAAO,QAAQ,OAAO,eAAe;AAAA,EACvC,GAAG,CAAC,CAAC;AAEL;AAAA,IACE;AAAA,IACA,MAAM;AACJ,aAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkB,CAAC,SAAkB,MAAc,SAAiB;AAUxE,WAAO,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS;AACtD,UAAI,MAAM;AACR,YAAI,KAAK,qBAAqB,QAAQ;AACpC,mBAAS,cAAc,EAAE,QAAQ,CAAC,CAAC;AACnC,0BAAgB,MAAM,IAAI;AAAA,QAC5B;AAAA,MACF,OAAO;AACL,gBAAQ;AAAA,UACN;AAAA;AAAA;AAAA,QAGF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkB,CAAC,EAAE,UAAU,OAAO,MAAoB;AAC9D,UAAM,QAAQ,SAAS;AAEvB,QAAI,CAAC,SAAS,SAAS,SAAS,MAAM,WAAW,OAAO;AACtD,YAAM,cAAc,aAAa,SAAS,WAAW,SAAS,MAAM;AACpE,YAAM,cAAc,CAAC,CAAC,MAAM,WAAW;AACvC,UAAI,aAAa;AACf,gBAAQ;AAAA,UACN;AAAA,YACE,UAAU,SAAS;AAAA,YACnB,QAAQ,SAAS;AAAA,YACjB,MAAM,SAAS;AAAA,UACjB;AAAA,UACA;AAAA,YACE,SAAS;AAAA,YACT,WAAW;AAAA,YACX,MAAM,OAAO;AAAA,YACb,MAAM,OAAO;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,eAAe,OAAO;AACjC;AAAA,QACE,cAAc;AAAA,UACZ,SAAS,MAAM;AAAA,QACjB,CAAC;AAAA,MACH;AAEA,UAAI,WAAW,OAAO;AACpB;AAAA,MACF;AAEA,YAAM,EAAE,SAAS,MAAM,KAAK,IAAI;AAChC,YAAM,cAAc,CAAC,CAAC,MAAM,OAAO;AAEnC,UAAI,aAAa;AACf,cAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO;AAEzC,gBAAQ,iBAAiB;AAAA,UACvB,KAAK;AACH,qBAAS,cAAc,EAAE,QAAQ,CAAC,CAAC;AACnC,4BAAgB,MAAM,IAAI;AAC1B;AAAA,UACF,KAAK;AACH,qBAAS,cAAc,EAAE,QAAQ,CAAC,CAAC;AACnC,4BAAgB,MAAM,IAAI;AAC1B,kBAAM,SAAS,EAAE,SAAS,KAAK,CAAC;AAChC;AAAA,UACF,KAAK;AAAA,UACL;AACE,4BAAgB,SAAS,MAAM,IAAI;AAAA,QACvC;AAAA,MACF,OAAO;AACL,wBAAgB,SAAS,MAAM,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAyB,CAC7B,MACA,EAAE,OAAO,IAAI;AAAA,IACX,QAAQ;AAAA,EACV,MACG;AACH,QAAI,WAAW,QAAQ;AACrB,aAAO;AAAA,IACT;AAEA,WAAO,oBAAoB,IAAI;AAC/B,UAAM,cAAc,aAAa,IAAI;AACrC,UAAM,UAAU,OAAO,UAAU,eAAe;AAAA,MAC9C,MAAM,SAAS,EAAE;AAAA,MACjB;AAAA,IACF;AAEA,QAAI,SAAS;AACX,YAAM,WAAW,QAAQ;AACzB,YAAM,QAAQ,SAAS;AACvB,YAAM,cAAc,MAAM;AAC1B,YAAM,cAAc;AAAA,QAClB;AAAA,QACA;AAAA,UACE,SAAS;AAAA,UACT,WAAW;AAAA,UACX,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AAEA,UAAI,WAAW,QAAQ;AACrB,YAAI,WAAW;AACb,kBAAQ;AAAA,YACN;AAAA,cACE,UAAU,SAAS;AAAA,cACnB,QAAQ,SAAS;AAAA,cACjB,MAAM,SAAS;AAAA,YACjB;AAAA,YACA;AAAA,cACE,GAAG;AAAA,cACH,MAAM,OAAO;AAAA,cACb,MAAM,OAAO;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAEA,gBAAQ,KAAK,GAAG,WAAW;AAAA,MAC7B;AAEA,UAAI,WAAW,WAAW;AACxB,gBAAQ,QAAQ,GAAG,WAAW;AAAA,MAChC;AAEA,oBAAc,EAAE,SAAS,YAAY,CAAC;AACtC,sBAAgB,GAAG,CAAC;AAEpB,UAAI,WAAW,aAAa,eAAe,gBAAgB,aAAa;AACtE,iBAAS,WAAW,EAAE,SAAS,YAAY,CAAC,CAAC;AAAA,MAC/C;AAEA,aAAO;AAAA,IACT,OAAO;AACL,cAAQ;AAAA,QACN;AAAA;AAAA;AAAA;AAAA,MAIF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,EAAE,gBAAgB,OAAO,IAAI;AACnC,QAAM,EAAE,oBAAoB,IAAI,MAAM,cAAc;AACpD,QAAM,YAAY,QAAQ,mBAAmB;AAE7C,MAAI,WAAW;AACb,WACE;AAAA,MAAC,kBAAkB;AAAA,MAAlB;AAAA,QACC,OAAO,EAAE,SAAS,gBAAgB,QAAQ,YAAY,OAAO,OAAO;AAAA;AAAA,MAEpE,oCAAC,eAAU;AAAA,IACb;AAAA,EAEJ,OAAO;AACL,aAAS,mBAAmB;AAAA,EAC9B;AACF,CAAC;;;AC/ND,SAAS,+BAA+B,cAAoB,MAAkB;AAC5E,QAAM,EAAE,SAAS,CAAC,EAAE,IAAI;AAExB,QAAM,aAAa,OAAO,IAAI,CAAC,EAAE,KAAK,MAAM;AAC1C,UAAM,OAAO,MAAM,cAAc,IAAI;AACrC,UAAM,OAAO,KAAK,UAAU,IAAI;AAChC,WAAO,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC;AAAA,EAChC,CAAC;AAED,SAAO,WAAW,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM;AAC/C,WAAO,MAAM,MAAM,MAAM,IAAI;AAAA,EAC/B,GAAG,IAAI;AACT;AAEA,SAAS,mBAAmB,OAAiB;AAC3C,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,cAAc,OAAO,KAAK,KAAK;AACrC,QAAM,wBAAwB,YAC3B,IAAI,CAAC,QAAQ,MAAM,GAAG,EAAE,OAAO,EAC/B,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAEvB,aAAW,OAAO,MAAM,KAAK,WAAW,GAAG;AACzC,QAAI,MAAM,GAAG,EAAE,WAAW,sBAAsB,WAAW,CAAC,GAAG;AAC7D,aAAO,MAAM,GAAG;AAAA,IAClB;AAAA,EACF;AACF;AAEA,SAAS,mBACP,OACA,SACA,MACU;AACV,UAAQ,EAAE,GAAG,MAAM;AAEnB,MAAI,WAAiB;AAAA,IACnB,GAAG;AAAA,IACH,SAAS,KAAK,IAAI;AAAA,EACpB;AAEA,QAAM,eAAe,MAAM,OAAO;AAElC,MAAI,cAAc;AAChB,eAAW,+BAA+B,cAAc,QAAQ;AAAA,EAClE;AACA,qBAAmB,KAAK;AACxB,QAAM,OAAO,IAAI;AAEjB,SAAO;AACT;AAEO,SAAS,gCACd,OACA,SACA,mBACU;AACV,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,MAAI,kBAAkB,WAAW,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,MAAM,OAAO;AACjC,QAAM,EAAE,WAAW,gBAAgB,CAAC,EAAE,IAAI;AAC1C,QAAM,gBAAgB,CAAC,GAAG,aAAa;AACvC,QAAM,eAAwC,CAAC;AAC/C,gBAAc,QAAQ,CAAC,SAAU,aAAa,KAAK,IAAI,IAAI,IAAK;AAEhE,oBAAkB,QAAQ,CAAC,SAAS;AAClC,QAAI,CAAC,aAAa,KAAK,IAAI,GAAG;AAC5B,oBAAc,KAAK,IAAI;AAAA,IACzB;AAAA,EACF,CAAC;AAED,QAAM,WAAW;AAAA,IACf,GAAG;AAAA,IACH,WAAW;AAAA,EACb;AAEA,QAAM,YAAY,EAAE,GAAG,MAAM;AAC7B,YAAU,OAAO,IAAI;AAErB,SAAO;AACT;AAEO,SAAS,kBACd,OACA,SACA,MACA,YACU;AACV,MAAI,CAAC,MAAM;AACT,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,cAAc,CAAC,SAAS;AAC3B,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,CAAC,SAAS,UAAU,EAAE,KAAK,GAAG;AACrD,SAAO,MAAM,OAAO,gBAAgB,IAAI;AAC1C;AAEA,SAAS,oBACP,OACA,SACA,MACU;AACV,QAAM,cAAc,MAAM,OAAO;AACjC,MAAI,CAAC,aAAa;AAChB,UAAM,QAAQ,IAAI;AAAA,MAChB,6BAA6B,OAAO;AAAA,IACtC;AACA,UAAM;AAAA,EACR;AACA,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW,oBAAoB,CAAC;AAAA,EAClC,IAAI;AAEJ,SAAO;AAAA,IACL,CAAC,cACC,kBAAkB,WAAW,SAAS,cAAc,UAAU;AAAA,IAChE,CAAC,cACC,gCAAgC,WAAW,SAAS,iBAAiB;AAAA,EACzE,EAAE,OAAO,CAAC,MAAM,OAAO,GAAG,IAAI,GAAG,KAAK;AACxC;AAEO,SAAS,YAAY,QAAkB,CAAC,GAAG,QAA0B;AAC1E,MAAI,WAAW,MAAM,MAAM,GAAG;AAC5B,UAAM,EAAE,QAAQ,IAAI,OAAO;AAC3B,UAAM,YAAY,EAAE,GAAG,MAAM;AAC7B,WAAO,UAAU,OAAO;AAExB,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,MAAM,MAAM,GAAG;AAC1B,UAAM,YAAY,EAAE,GAAG,MAAM;AAC7B,UAAM,EAAE,MAAM,GAAG,IAAI,OAAO;AAE5B,cAAU,aAAa,EAAE,CAAC,IAAI,KAAK,MAAM,KAAK,UAAU,UAAU,IAAI,CAAC,CAAC;AAExE,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,MAAM,MAAM,GAAG;AAC7B,UAAM,EAAE,SAAS,KAAK,IAAI,OAAO;AAEjC,WAAO,oBAAoB,OAAO,SAAS,IAAI;AAAA,EACjD;AAEA,MAAI,aAAa,MAAM,MAAM,GAAG;AAC9B,UAAM,EAAE,SAAS,KAAK,IAAI,OAAO;AACjC,UAAM,YAAY,mBAAmB,OAAO,SAAS,IAAI;AACzD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,iBACd,QAAwB;AAAA,EACtB,gBAAgB;AAAA,EAChB,QAAQ,CAAC;AAAA,EACT,QAAQ,CAAC;AACX,GACA,QACgB;AAChB,MAAI,aAAa,MAAM,MAAM,GAAG;AAC9B,UAAM,EAAE,UAAU,IAAI,OAAO;AAC7B,WAAO,EAAE,GAAG,OAAO,UAAqB;AAAA,EAC1C;AAEA,MAAI,cAAc,MAAM,MAAM,GAAG;AAC/B,UAAM,EAAE,QAAQ,IAAI,OAAO;AAC3B,UAAM,EAAE,OAAO,IAAI,aAAa,OAAO;AAEvC,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,gBAAgB;AAAA,IAClB;AAAA,EACF;AAEA,MAAI,cAAc,MAAM,MAAM,GAAG;AAC/B,UAAM,EAAE,QAAQ,IAAI,OAAO;AAC3B,UAAM,EAAE,OAAO,IAAI,aAAa,OAAO;AAEvC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,gBAAgB;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa,MAAM,MAAM,GAAG;AAC9B,UAAM;AAAA,MACJ,MAAM,EAAE,WAAW,OAAO;AAAA,IAC5B,IAAI,OAAO;AAEX,WAAO,EAAE,GAAG,OAAO,WAAW,OAAO;AAAA,EACvC;AAEA,SAAO;AACT;AAEO,IAAM,cAAc;AAAA,EACzB,WAAW;AAAA,EACX,OAAO;AACT;;;AC7OA,SAAS,eAAAC,oBAAmB;AAMrB,SAAS,eAAe;AAC7B,SAAOA,aAAuC,CAAC,UAAU,MAAM,SAAS;AAC1E;AAKO,SAAS,aAA+B;AAC7C,QAAM,iBAAiB,aAAa;AACpC,QAAM,iBAAiB,eAAe;AAEtC,SAAOA;AAAA,IACL,CAAC,UAAU,MAAM,MAAM,cAAc;AAAA,EACvC,EAAE;AACJ;;;AHkBA,IAAMC,aAAY,OAAO,WAAW;AAEpC,IAAM,gBAAgB,MAAM;AAC1B,MAAIA,YAAW;AAEb,WAAO,qBAAqB,CAAC,CAAC;AAAA,EAChC,OAAO;AAEL,WAAO,oBAAoB,CAAC,CAAC;AAAA,EAC/B;AACF;AAEO,IAAM,eAAe,CAC1B,OACA,aACA,SACG;AACH,QAAM,WAAW,MAAM,IAAI;AAC3B,QAAM,iBAAiB,aAAa,SAAS,IAAI;AACjD,QAAM,EAAE,UAAU,IAAI;AAEtB,QAAM;AAAA,IACJ,cAAc;AAAA,MACZ,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,QAAM,SAAS,mBAAmB,gBAAgB,WAAW,CAAC;AAC9D,QAAM,SAAS,aAAa,EAAE,UAAU,CAAC,CAAC;AAC5C;AAMO,IAAM,QAAQ,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAkB;AAChB,SAAO,UAAU;AAEjB,QAAM,EAAE,OAAO,OAAO,IAAI,oBAAoB,cAAc,KAAK;AAEjE,QAAM,iBAAiB,aAAa,MAAM,IAAI,EAAE,IAAI;AACpD,QAAM,cAAc,WAAW,cAAc;AAC7C,cAAY,QAAQ,GAAG,eAAe,IAAI,CAAC;AAC3C,eAAa,OAAO,aAAa,IAAI;AAErC,QAAM,WAAW,YAAY;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK;AAAA,EACP;AACF;AASA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,QAAM,eAAe,OAA0C,IAAI;AAEnE,QAAM,EAAE,OAAO,QAAQ,aAAa,gBAAgB,IAAI,IAAI,QAAQ,MAAM;AACxE,WAAO,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAIL,SACE,gBAAAC,OAAA,cAAC,SAAI,SAAS,IAAI,SAAS,UAAU,IAAI,UAAW,GAAG,QACrD,gBAAAA,OAAA,cAAC,YAAS,SACR,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA;AAAA,EACF,CACF,CACF;AAEJ;","names":["React","NavigationProvider","useSelector","hasWindow","React"]}
|
package/package.json
CHANGED
|
@@ -1,56 +1,90 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thoughtbot/superglue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Use a vanilla Rails with React and Redux",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsup",
|
|
7
|
+
"dev": "tsup --watch",
|
|
8
|
+
"clean": "rm -rf dist",
|
|
9
|
+
"lint": "run-p lint:eslint lint:types lint:prettier",
|
|
10
|
+
"lint:eslint": "eslint --max-warnings=0 --ext js,jsx,ts,tsx ./lib",
|
|
11
|
+
"lint:prettier": "prettier --check '**/*' --ignore-unknown",
|
|
12
|
+
"lint:types": "tsc",
|
|
13
|
+
"fix:prettier": "prettier --write '**/*' --ignore-unknown",
|
|
14
|
+
"test": "vitest",
|
|
15
|
+
"test:run": "vitest run",
|
|
16
|
+
"test:cov": "vitest --coverage",
|
|
17
|
+
"test:all": "npm lint && npm test:run",
|
|
18
|
+
"pub:beta": "npm build && npm publish --tag beta",
|
|
19
|
+
"pub:release": "npm build && npm publish"
|
|
20
|
+
},
|
|
5
21
|
"repository": {
|
|
6
22
|
"type": "git",
|
|
7
23
|
"url": "git+https://github.com/thoughtbot/superglue.git"
|
|
8
24
|
},
|
|
9
25
|
"author": "Johny Ho",
|
|
26
|
+
"main": "dist/cjs/superglue.cjs",
|
|
27
|
+
"module": "dist/superglue.mjs",
|
|
28
|
+
"types": "dist/superglue.d.mts",
|
|
29
|
+
"exports": {
|
|
30
|
+
"./package.json": "./package.json",
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/superglue.d.mts",
|
|
33
|
+
"import": "./dist/superglue.mjs",
|
|
34
|
+
"default": "./dist/cjs/superglue.cjs"
|
|
35
|
+
},
|
|
36
|
+
"./action_creators": {
|
|
37
|
+
"types": "./dist/action_creators.d.mts",
|
|
38
|
+
"import": "./dist/action_creators.mjs",
|
|
39
|
+
"default": "./dist/cjs/action_creators.cjs"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
10
42
|
"license": "MIT",
|
|
11
43
|
"bugs": {
|
|
12
44
|
"url": "https://github.com/thoughtbot/superglue/issues"
|
|
13
45
|
},
|
|
14
46
|
"homepage": "https://github.com/thoughtbot/superglue#readme",
|
|
15
47
|
"devDependencies": {
|
|
16
|
-
"@
|
|
17
|
-
"@
|
|
18
|
-
"@
|
|
19
|
-
"@
|
|
20
|
-
"@
|
|
21
|
-
"@
|
|
22
|
-
"@typescript-eslint/
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"eslint
|
|
28
|
-
"eslint-plugin-
|
|
29
|
-
"eslint-plugin-react": "^7.24.0",
|
|
48
|
+
"@testing-library/dom": "^10.4.0",
|
|
49
|
+
"@testing-library/jest-dom": "^6.5.0",
|
|
50
|
+
"@testing-library/react": "^16.0.1",
|
|
51
|
+
"@testing-library/user-event": "^14.5.2",
|
|
52
|
+
"@types/node": "^22.10.1",
|
|
53
|
+
"@types/url-parse": "^1.4.11",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
|
55
|
+
"@typescript-eslint/parser": "^7.15.0",
|
|
56
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
57
|
+
"@vitest/coverage-v8": "^2.0.2",
|
|
58
|
+
"abortcontroller-polyfill": "^1.7.3",
|
|
59
|
+
"eslint": "^8.57.0",
|
|
60
|
+
"eslint-plugin-react": "^7.34.3",
|
|
30
61
|
"fetch-headers": "^2.0.0",
|
|
31
62
|
"fetch-mock": "^9.11.0",
|
|
32
|
-
"
|
|
33
|
-
"jest": "^27.0.4",
|
|
63
|
+
"jsdom": "^24.1.0",
|
|
34
64
|
"node-fetch": "^2.6.1",
|
|
65
|
+
"npm-run-all": "^4.1.5",
|
|
35
66
|
"prettier": "^2.3.1",
|
|
36
|
-
"
|
|
37
|
-
"react": "^
|
|
38
|
-
"react-dom": "^
|
|
39
|
-
"react-redux": "^7.2.
|
|
40
|
-
"redux": "^
|
|
67
|
+
"prettier-eslint": "^16.3.0",
|
|
68
|
+
"react": "^18.3.1",
|
|
69
|
+
"react-dom": "^18.3.1",
|
|
70
|
+
"react-redux": "^7.2.9",
|
|
71
|
+
"redux": "^5.0.1",
|
|
41
72
|
"redux-mock-store": "^1.5.4",
|
|
42
|
-
"redux-thunk": "^
|
|
73
|
+
"redux-thunk": "^3.1.0",
|
|
74
|
+
"tsup": "^8.1.0",
|
|
75
|
+
"typedoc": "~0.26.5",
|
|
76
|
+
"typedoc-plugin-markdown": "~4.2.3",
|
|
77
|
+
"typedoc-plugin-missing-exports": "~3.0.0",
|
|
78
|
+
"typescript": "^5.5.3",
|
|
79
|
+
"vitest": "^2.0.2"
|
|
43
80
|
},
|
|
44
81
|
"peerDependencies": {
|
|
45
|
-
"
|
|
46
|
-
"react": "
|
|
47
|
-
"
|
|
48
|
-
"redux": ">=4.1",
|
|
49
|
-
"redux-thunk": ">=2.3"
|
|
82
|
+
"react": "^18 || ^19",
|
|
83
|
+
"react-redux": "^9 || ^8",
|
|
84
|
+
"@reduxjs/toolkit": "^2.2.8"
|
|
50
85
|
},
|
|
51
86
|
"dependencies": {
|
|
52
|
-
"
|
|
53
|
-
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
|
87
|
+
"history": "^5.3.0",
|
|
54
88
|
"url-parse": "^1.5.1"
|
|
55
89
|
}
|
|
56
90
|
}
|