@thoughtbot/superglue 0.53.3 → 0.54.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.
@@ -0,0 +1,613 @@
1
+ import {
2
+ BEFORE_FETCH,
3
+ BEFORE_REMOTE,
4
+ BEFORE_VISIT,
5
+ COPY_PAGE,
6
+ GRAFTING_ERROR,
7
+ 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
+ argsForHistory,
17
+ config,
18
+ getIn,
19
+ mapDispatchToProps,
20
+ mapStateToProps,
21
+ pathWithoutBZParams,
22
+ saveAndProcessPage,
23
+ setIn,
24
+ ujsHandlers,
25
+ urlToPageKey
26
+ } from "./chunk-MNVGYKSD.mjs";
27
+
28
+ // lib/index.tsx
29
+ import React2 from "react";
30
+ import parse from "url-parse";
31
+
32
+ // lib/reducers/index.ts
33
+ function addPlaceholdersToDeferredNodes(existingPage, page) {
34
+ const { defers = [] } = existingPage;
35
+ const prevDefers = defers.map(({ path }) => {
36
+ const node = getIn(existingPage, path);
37
+ const copy = JSON.stringify(node);
38
+ return [path, JSON.parse(copy)];
39
+ });
40
+ return prevDefers.reduce((memo, [path, node]) => {
41
+ return setIn(page, path, node);
42
+ }, page);
43
+ }
44
+ function constrainPagesSize(state) {
45
+ const { maxPages } = config;
46
+ const allPageKeys = Object.keys(state);
47
+ const cacheTimesRecentFirst = allPageKeys.map((key) => state[key].savedAt).sort((a, b) => b - a);
48
+ for (const key of Array.from(allPageKeys)) {
49
+ if (state[key].savedAt <= cacheTimesRecentFirst[maxPages - 1]) {
50
+ delete state[key];
51
+ }
52
+ }
53
+ }
54
+ function saveResponse(state, pageKey, page) {
55
+ state = { ...state };
56
+ let nextPage = {
57
+ pageKey,
58
+ ...page,
59
+ savedAt: Date.now()
60
+ };
61
+ const existingPage = state[pageKey];
62
+ if (existingPage) {
63
+ nextPage = addPlaceholdersToDeferredNodes(existingPage, nextPage);
64
+ }
65
+ constrainPagesSize(state);
66
+ state[pageKey] = nextPage;
67
+ return state;
68
+ }
69
+ function appendReceivedFragmentsOntoPage(state, pageKey, receivedFragments) {
70
+ if (!pageKey) {
71
+ return state;
72
+ }
73
+ if (receivedFragments.length === 0) {
74
+ return state;
75
+ }
76
+ const currentPage = state[pageKey];
77
+ const { fragments: prevFragments = [] } = currentPage;
78
+ const nextFragments = [...prevFragments];
79
+ const existingKeys = {};
80
+ prevFragments.forEach((frag) => existingKeys[frag.path] = true);
81
+ receivedFragments.forEach((frag) => {
82
+ if (!existingKeys[frag.path]) {
83
+ nextFragments.push(frag);
84
+ }
85
+ });
86
+ const nextPage = {
87
+ ...currentPage,
88
+ fragments: nextFragments
89
+ };
90
+ const nextState = { ...state };
91
+ nextState[pageKey] = nextPage;
92
+ return nextState;
93
+ }
94
+ function graftNodeOntoPage(state, pageKey, node, pathToNode) {
95
+ if (!node) {
96
+ console.warn(
97
+ "There was no node returned in the response. Do you have the correct key path in your props_at?"
98
+ );
99
+ return state;
100
+ }
101
+ if (!pathToNode || !pageKey) {
102
+ return state;
103
+ }
104
+ const fullPathToNode = [pageKey, pathToNode].join(".");
105
+ return setIn(state, fullPathToNode, node);
106
+ }
107
+ function handleGraft(state, pageKey, page) {
108
+ const currentPage = state[pageKey];
109
+ if (!currentPage) {
110
+ const error = new Error(
111
+ `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?`
112
+ );
113
+ throw error;
114
+ }
115
+ const {
116
+ data: receivedNode,
117
+ path: pathToNode,
118
+ fragments: receivedFragments = []
119
+ } = page;
120
+ return [
121
+ (nextState) => graftNodeOntoPage(nextState, pageKey, receivedNode, pathToNode),
122
+ (nextState) => appendReceivedFragmentsOntoPage(nextState, pageKey, receivedFragments)
123
+ ].reduce((memo, fn) => fn(memo), state);
124
+ }
125
+ function pageReducer(state = {}, action) {
126
+ switch (action.type) {
127
+ case SAVE_RESPONSE: {
128
+ const { pageKey, page } = action.payload;
129
+ return saveResponse(state, pageKey, page);
130
+ }
131
+ case HANDLE_GRAFT: {
132
+ const { pageKey, page } = action.payload;
133
+ return handleGraft(state, pageKey, page);
134
+ }
135
+ case UPDATE_FRAGMENTS: {
136
+ const { changedFragments } = action.payload;
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;
165
+ }
166
+ }
167
+ function superglueReducer(state = {}, action) {
168
+ switch (action.type) {
169
+ case HISTORY_CHANGE: {
170
+ const { pathname, search, hash } = action.payload;
171
+ const currentPageKey = urlToPageKey(pathname + search);
172
+ return {
173
+ ...state,
174
+ currentPageKey,
175
+ pathname,
176
+ search,
177
+ hash
178
+ };
179
+ }
180
+ case SAVE_RESPONSE: {
181
+ const {
182
+ page: { csrfToken, assets }
183
+ } = action.payload;
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;
192
+ }
193
+ }
194
+ var rootReducer = {
195
+ superglue: superglueReducer,
196
+ pages: pageReducer
197
+ };
198
+
199
+ // lib/index.tsx
200
+ import { Provider, connect } from "react-redux";
201
+ import {
202
+ createBrowserHistory,
203
+ createMemoryHistory
204
+ } from "history";
205
+
206
+ // lib/components/Nav.tsx
207
+ import React from "react";
208
+ var Nav = class extends React.Component {
209
+ /**
210
+ * @ignore
211
+ */
212
+ constructor(props) {
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
+ }
423
+ }
424
+ };
425
+ var Nav_default = Nav;
426
+
427
+ // lib/middleware.ts
428
+ var actionValues = Object.values(actions_exports).map((action) => action.toString());
429
+ var fragmentMiddleware = (store) => (next) => (action) => {
430
+ const prevState = store.getState();
431
+ const nextAction = next(action);
432
+ const nextState = store.getState();
433
+ if (!(action instanceof Object && "type" in action && typeof action.type === "string")) {
434
+ return nextAction;
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;
481
+ };
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({
498
+ initialPage,
499
+ baseUrl = config.baseUrl,
500
+ maxPages = config.maxPages,
501
+ path
502
+ }) {
503
+ const initialPageKey = urlToPageKey(parse(path).href);
504
+ const { csrfToken } = initialPage;
505
+ const location = parse(path);
506
+ config.baseUrl = baseUrl;
507
+ config.maxPages = maxPages;
508
+ return {
509
+ reducer: rootReducer,
510
+ prepareStore: function(store) {
511
+ store.dispatch({
512
+ type: HISTORY_CHANGE,
513
+ payload: {
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
524
+ };
525
+ }
526
+ var ApplicationBase = class extends React2.Component {
527
+ /**
528
+ * The constructor of the `ApplicationBase` class.
529
+ * @param props
530
+ */
531
+ constructor(props) {
532
+ super(props);
533
+ this.hasWindow = typeof window !== "undefined";
534
+ this.navigatorRef = React2.createRef();
535
+ const { prepareStore, initialState, initialPageKey, reducer } = start({
536
+ initialPage: this.props.initialPage,
537
+ baseUrl: this.props.baseUrl,
538
+ path: this.props.path
539
+ // The max number of pages to keep in the store. Default is 20
540
+ // maxPages: 20
541
+ });
542
+ this.initialPageKey = initialPageKey;
543
+ this.store = this.buildStore(initialState, reducer);
544
+ prepareStore(this.store);
545
+ this.history = this.createHistory();
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"
564
+ });
565
+ const { onClick, onSubmit } = this.ujsHandlers;
566
+ appEl.addEventListener("click", onClick);
567
+ appEl.addEventListener("submit", onSubmit);
568
+ }
569
+ componentWillUnmount() {
570
+ const { appEl } = this.props;
571
+ const { onClick, onSubmit } = this.ujsHandlers;
572
+ appEl.removeEventListener("click", onClick);
573
+ appEl.removeEventListener("submit", onSubmit);
574
+ }
575
+ createHistory() {
576
+ if (this.hasWindow) {
577
+ return createBrowserHistory({});
578
+ } else {
579
+ return createMemoryHistory({});
580
+ }
581
+ }
582
+ render() {
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
+ };
597
+ export {
598
+ ApplicationBase,
599
+ BEFORE_FETCH,
600
+ BEFORE_REMOTE,
601
+ BEFORE_VISIT,
602
+ COPY_PAGE,
603
+ GRAFTING_ERROR,
604
+ GRAFTING_SUCCESS,
605
+ HISTORY_CHANGE,
606
+ REMOVE_PAGE,
607
+ SAVE_RESPONSE,
608
+ UPDATE_FRAGMENTS,
609
+ fragmentMiddleware,
610
+ getIn,
611
+ urlToPageKey
612
+ };
613
+ //# sourceMappingURL=superglue.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/index.tsx","../lib/reducers/index.ts","../lib/components/Nav.tsx","../lib/middleware.ts"],"sourcesContent":["import React from 'react'\nimport parse from 'url-parse'\nimport { rootReducer } from './reducers'\nimport { config } from './config'\nimport { urlToPageKey, ujsHandlers, argsForHistory } from './utils'\nimport { saveAndProcessPage } from './action_creators'\nimport { HISTORY_CHANGE, SET_CSRF_TOKEN } from './actions'\nimport { ConnectedComponent, Provider, connect } from 'react-redux'\n\nimport {\n BrowserHistory,\n History,\n createBrowserHistory,\n createMemoryHistory,\n} from 'history'\n\nimport Nav from './components/Nav'\n\nexport {\n BEFORE_FETCH,\n BEFORE_VISIT,\n BEFORE_REMOTE,\n SAVE_RESPONSE,\n UPDATE_FRAGMENTS,\n COPY_PAGE,\n REMOVE_PAGE,\n GRAFTING_ERROR,\n GRAFTING_SUCCESS,\n HISTORY_CHANGE,\n} from './actions'\n\nimport { mapStateToProps, mapDispatchToProps } from './utils/react'\nimport {\n Remote,\n SuperglueStore,\n Handlers,\n Visit,\n VisitResponse,\n PageOwnProps,\n AllPages,\n Page,\n JSONValue,\n} from './types'\n// export { superglueReducer, pageReducer, rootReducer } from './reducers'\nexport { fragmentMiddleware } from './middleware'\nexport { getIn } from './utils/immutability'\nexport { urlToPageKey }\n\nfunction pageToInitialState(key: string, page: VisitResponse) {\n const slices = page.slices || {}\n const nextPage: Page = {\n ...page,\n pageKey: key, //TODO remove this\n savedAt: Date.now(),\n }\n\n return {\n pages: { [key]: nextPage },\n ...slices,\n }\n}\n\nfunction start({\n initialPage,\n baseUrl = config.baseUrl,\n maxPages = config.maxPages,\n path,\n}: {\n initialPage: VisitResponse\n baseUrl: string\n maxPages?: number\n path: string\n}) {\n const initialPageKey = urlToPageKey(parse(path).href)\n const { csrfToken } = initialPage\n const location = parse(path)\n\n config.baseUrl = baseUrl\n config.maxPages = maxPages\n\n return {\n reducer: rootReducer,\n prepareStore: function (store: SuperglueStore) {\n store.dispatch({\n type: HISTORY_CHANGE,\n payload: {\n pathname: location.pathname,\n search: location.query,\n hash: location.hash,\n },\n })\n store.dispatch(saveAndProcessPage(initialPageKey, initialPage))\n store.dispatch({ type: SET_CSRF_TOKEN, payload: { csrfToken } })\n },\n initialState: pageToInitialState(initialPageKey, initialPage),\n initialPageKey,\n }\n}\n/**\n * Props for the `ApplicationBase` component\n */\ninterface ApplicationProps {\n /**\n * The global var SUPERGLUE_INITIAL_PAGE_STATE is set by your erb\n * template, e.g., index.html.erb\n */\n initialPage: VisitResponse\n /**\n * The base url prefixed to all calls made by `visit` and\n * `remote`.\n */\n baseUrl: string\n /**\n * The path of the current page. It should equal to the `location.pathname` +\n * `location.search` + `location.hash`\n */\n path: string\n /**\n * The app element that was passed to React's `createRoot`. This will be used\n * to setup UJS helpers.\n */\n appEl: HTMLElement\n /**\n * A store to perform setup on. If none is provided, it will build a basic\n * store.\n */\n store?: SuperglueStore\n}\n\ntype ConnectedMapping = Record<\n string,\n ConnectedComponent<React.ComponentType, PageOwnProps>\n>\n/**\n * The entry point to your superglue application. You should create a class\n * (Application) that inherit from the ApplicationBase component and override\n * the {@link buildStore}, {@link mapping}, and {@link visitAndRemote} methods.\n *\n * This would be setup for you when installing Superglue at `application.js`.\n */\nexport abstract class ApplicationBase extends React.Component<ApplicationProps> {\n private hasWindow: boolean\n private navigatorRef: React.RefObject<Nav>\n private initialPageKey: string\n private store: SuperglueStore\n private history: History\n private connectedMapping: ConnectedMapping\n private ujsHandlers: Handlers\n private visit: Visit\n private remote: Remote\n\n /**\n * The constructor of the `ApplicationBase` class.\n * @param props\n */\n constructor(props: ApplicationProps) {\n super(props)\n this.hasWindow = typeof window !== 'undefined'\n\n // Create a navigator Ref for UJS attributes and to enhance the base `visit`\n // and `visit` thunks\n this.navigatorRef = React.createRef()\n\n // Retrieve initial values and methods to prepare the store.\n const { prepareStore, initialState, initialPageKey, reducer } = start({\n initialPage: this.props.initialPage,\n baseUrl: this.props.baseUrl,\n path: this.props.path,\n // The max number of pages to keep in the store. Default is 20\n // maxPages: 20\n })\n this.initialPageKey = initialPageKey\n\n // Build the store and pass Superglue's provided reducer to be combined with\n // your reducers located at `application_reducer.js`\n this.store = this.buildStore(initialState, reducer)\n\n // Fire initial events and populate the store\n prepareStore(this.store)\n\n // Build history\n this.history = this.createHistory()\n this.history.replace(...argsForHistory(this.props.path))\n\n const unconnectedMapping = this.mapping()\n const nextMapping: ConnectedMapping = {}\n for (const key in unconnectedMapping) {\n const component = unconnectedMapping[key]\n nextMapping[key] = connect(mapStateToProps, mapDispatchToProps)(component)\n }\n\n this.connectedMapping = nextMapping\n\n // Build visit and remote thunks\n // Your modified `visit` and `remote` will get passed below to the\n // Nav component then to your components\n //\n // You can access them via `this.props.visit` or `this.props.remote`. In\n // your page components\n const { visit, remote } = this.visitAndRemote(this.navigatorRef, this.store)\n this.visit = visit\n this.remote = remote\n }\n\n /**\n * Override this method to return a visit and remote function. These functions\n * will be used by Superglue to power its UJS attributes and passed to your\n * page components. You may customize this functionality to your liking, e.g,\n * adding a progress bar.\n *\n * @param navigatorRef\n * @param store\n *\n * @returns\n */\n abstract visitAndRemote(\n // eslint-disable-next-line\n navigatorRef: React.RefObject<Nav>,\n store: SuperglueStore\n ): { visit: Visit; remote: Remote }\n\n componentDidMount(): void {\n const { appEl } = this.props\n // Create the ujs event handlers. You can change the ujsAttributePrefix\n // in the event the data attribute conflicts with another.\n this.ujsHandlers = ujsHandlers({\n visit: this.visit,\n remote: this.remote,\n ujsAttributePrefix: 'data-sg',\n })\n const { onClick, onSubmit } = this.ujsHandlers\n\n appEl.addEventListener('click', onClick)\n appEl.addEventListener('submit', onSubmit)\n }\n\n componentWillUnmount(): void {\n const { appEl } = this.props\n const { onClick, onSubmit } = this.ujsHandlers\n\n appEl.removeEventListener('click', onClick)\n appEl.removeEventListener('submit', onSubmit)\n }\n\n /**\n * Override this method and return a Redux store for Superglue to use. This\n * would be setup and generated for you in `store.js`. We recommend using\n * using Redux toolkit's `configureStore` to build the store.\n *\n * @param initialState - A preconfigured intial state to pass to your store.\n * @param reducer - A preconfigured reducer\n */\n abstract buildStore(\n initialState: { pages: AllPages; [key: string]: JSONValue },\n reducer: typeof rootReducer\n ): SuperglueStore\n\n createHistory(): BrowserHistory {\n if (this.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\n /**\n * Override this method and return a mapping between a componentIdentifier and\n * a PageComponent. This will be passed to Superglue to determine which Page component\n * to render with which payload.\n *\n * @returns\n */\n abstract mapping(): Record<string, React.ComponentType>\n\n render(): JSX.Element {\n // The Nav component is pretty bare and can be inherited from for custom\n // behavior or replaced with your own.\n return (\n <Provider store={this.store}>\n <Nav\n store={this.store}\n ref={this.navigatorRef}\n visit={this.visit}\n remote={this.remote}\n mapping={this.connectedMapping}\n history={this.history}\n initialPageKey={this.initialPageKey}\n />\n </Provider>\n )\n }\n}\n","import { setIn, getIn, urlToPageKey } from '../utils'\nimport {\n REMOVE_PAGE,\n SAVE_RESPONSE,\n HANDLE_GRAFT,\n HISTORY_CHANGE,\n SET_CSRF_TOKEN,\n COPY_PAGE,\n UPDATE_FRAGMENTS,\n} from '../actions'\nimport { config } from '../config'\nimport {\n AllPages,\n Page,\n PageReducerAction,\n VisitResponse,\n Fragment,\n GraftResponse,\n SuperglueState,\n SuperglueReducerAction,\n HistoryChange,\n SaveResponseAction,\n SetCSRFToken,\n HandleGraftAction,\n UpdateFragmentsAction,\n CopyAction,\n RemovePageAction,\n JSONMappable,\n} from '../types'\nimport { UnknownAction } from 'redux'\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 saveResponse(\n state: AllPages,\n pageKey: string,\n page: VisitResponse\n): AllPages {\n state = { ...state }\n\n let nextPage: Page = {\n pageKey,\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\nexport function handleGraft(\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(\n state: AllPages = {},\n action: PageReducerAction | UnknownAction\n): AllPages {\n switch (action.type) {\n case SAVE_RESPONSE: {\n const { pageKey, page } = action.payload as SaveResponseAction['payload']\n return saveResponse(state, pageKey, page)\n }\n case HANDLE_GRAFT: {\n const { pageKey, page } = action.payload as HandleGraftAction['payload']\n\n return handleGraft(state, pageKey, page)\n }\n case UPDATE_FRAGMENTS: {\n const { changedFragments } =\n action.payload as UpdateFragmentsAction['payload']\n let nextState = state\n\n Object.entries(state).forEach(([pageKey, page]) => {\n page.fragments.forEach((fragment) => {\n const { type, path } = fragment\n const changedNode = changedFragments[type]\n const currentNode = getIn(nextState, `${pageKey}.${path}`)\n\n if (type in changedFragments && changedNode !== currentNode) {\n const nextNode = JSON.parse(JSON.stringify(changedNode))\n nextState = setIn(nextState, `${pageKey}.${path}`, nextNode)\n }\n })\n })\n\n return nextState\n }\n case COPY_PAGE: {\n const nextState = { ...state }\n const { from, to } = action.payload as CopyAction['payload']\n\n nextState[urlToPageKey(to)] = JSON.parse(JSON.stringify(nextState[from]))\n\n return nextState\n }\n case REMOVE_PAGE: {\n const { pageKey } = action.payload as RemovePageAction['payload']\n const nextState = { ...state }\n delete nextState[pageKey]\n\n return nextState\n }\n default:\n return state\n }\n}\n\nexport function superglueReducer(\n state: Partial<SuperglueState> = {},\n action: SuperglueReducerAction | UnknownAction\n): Partial<SuperglueState> {\n switch (action.type) {\n case HISTORY_CHANGE: {\n const { pathname, search, hash } =\n action.payload as HistoryChange['payload']\n const currentPageKey = urlToPageKey(pathname + search)\n\n return {\n ...state,\n currentPageKey,\n pathname,\n search,\n hash,\n }\n }\n case SAVE_RESPONSE: {\n const {\n page: { csrfToken, assets },\n } = action.payload as SaveResponseAction['payload']\n\n return { ...state, csrfToken, assets }\n }\n case SET_CSRF_TOKEN: {\n const { csrfToken } = action.payload as SetCSRFToken['payload']\n return { ...state, csrfToken: csrfToken }\n }\n default:\n return state\n }\n}\n\nexport const rootReducer = {\n superglue: superglueReducer,\n pages: pageReducer,\n}\n","import React from 'react'\nimport { urlToPageKey, pathWithoutBZParams } from '../utils'\nimport { REMOVE_PAGE, HISTORY_CHANGE } from '../actions'\nimport {\n HistoryState,\n Keypath,\n NavigationAction,\n PageOwnProps,\n Remote,\n SuperglueStore,\n Visit,\n} from '../types'\nimport { ConnectedComponent } from 'react-redux'\nimport { History, Update } from 'history'\n\ninterface Props {\n store: SuperglueStore\n history: History\n mapping: Record<string, ConnectedComponent<React.ComponentType, PageOwnProps>>\n visit: Visit\n remote: Remote\n initialPageKey: string\n}\n\ninterface State {\n pageKey: string\n ownProps: Record<string, unknown>\n}\n\n/**\n * A Nav component for browsers. It handles changine the browser history,\n * deciding which page component to render based on a passed mapping, and\n * passes a `navigateTo` to all page components.\n */\nclass Nav extends React.Component<Props, State> {\n private history: History\n private hasWindow: boolean\n private unsubscribeHistory: () => void\n\n /**\n * @ignore\n */\n constructor(props: Props) {\n super(props)\n const { history, initialPageKey } = this.props\n this.history = history\n this.navigateTo = this.navigateTo.bind(this)\n this.scrollTo = this.scrollTo.bind(this)\n this.onHistoryChange = this.onHistoryChange.bind(this)\n this.state = {\n pageKey: initialPageKey,\n ownProps: {},\n }\n this.hasWindow = typeof window !== 'undefined'\n }\n /**\n * @ignore\n */\n componentDidMount(): void {\n this.unsubscribeHistory = this.history.listen(this.onHistoryChange)\n }\n\n /**\n * @ignore\n */\n componentWillUnmount(): void {\n this.unsubscribeHistory()\n }\n\n /**\n * Passed to every page component. Manually navigate using pages that exists\n * in the store and restores scroll position. This is what {@link Visit} in\n * your `application_visit.js` ultimately calls.\n *\n * If there is an existing page in your store `navigateTo` will restore the props,\n * render the correct component, and return `true`. Otherwise, it will return\n * `false`. This is useful if you want to restore an existing page before making a\n * call to `visit` or `remote`.\n *\n * @param path\n * @param options when `none`, immediately returns `false`\n * @returns `true` if the navigation was a success, `false` if the page was not found in the\n * store.\n */\n navigateTo(\n path: Keypath,\n {\n action,\n ownProps,\n }: { action: NavigationAction; ownProps: Record<string, unknown> } = {\n action: 'push',\n ownProps: {},\n }\n ): boolean {\n if (action === 'none') {\n return false\n }\n\n path = pathWithoutBZParams(path)\n const nextPageKey = urlToPageKey(path)\n const { store } = this.props\n const hasPage = !!store.getState().pages[nextPageKey]\n\n if (hasPage) {\n const location = this.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 (this.hasWindow) {\n this.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 this.history.push(...historyArgs)\n }\n\n if (action === 'replace') {\n this.history.replace(...historyArgs)\n }\n\n this.setState({ pageKey: nextPageKey, ownProps })\n this.scrollTo(0, 0)\n\n if (action === 'replace' && prevPageKey && prevPageKey !== nextPageKey) {\n store.dispatch({\n type: REMOVE_PAGE,\n payload: {\n pageKey: prevPageKey,\n },\n })\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 /**\n * @ignore\n */\n scrollTo(posX: number, posY: number): void {\n this.hasWindow && window.scrollTo(posX, posY)\n }\n\n /**\n * @ignore\n */\n onHistoryChange({ location, action }: Update): void {\n const { store, visit } = this.props\n const { pathname, search, hash } = location\n const state = location.state as HistoryState\n\n if (state && 'superglue' in state) {\n store.dispatch({\n type: HISTORY_CHANGE,\n payload: { pathname, search, hash },\n })\n\n if (action !== 'POP') {\n return\n }\n\n const { pageKey, posX, posY } = state\n const containsKey = !!store.getState().pages[pageKey]\n\n if (containsKey) {\n const { restoreStrategy } = store.getState().pages[pageKey]\n\n switch (restoreStrategy) {\n case 'fromCacheOnly':\n this.setState({ pageKey })\n this.scrollTo(posX, posY)\n break\n case 'fromCacheAndRevisitInBackground':\n this.setState({ pageKey })\n this.scrollTo(posX, posY)\n visit(pageKey, { revisit: true })\n break\n case 'revisitOnly':\n default:\n visit(pageKey, { revisit: true }).then((meta) => {\n if (meta === undefined) {\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 if (!!meta && meta.suggestedAction === 'none') {\n this.setState({ pageKey })\n this.scrollTo(posX, posY)\n }\n })\n }\n } else {\n visit(pageKey, { revisit: true }).then((meta) => {\n if (meta === undefined) {\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 if (!!meta && meta.suggestedAction === 'none') {\n this.setState({ pageKey })\n this.scrollTo(posX, posY)\n }\n })\n }\n }\n }\n\n /**\n * @ignore\n */\n 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\n /**\n * @ignore\n */\n render(): JSX.Element {\n const { store, visit, remote } = this.props\n const { pageKey, ownProps } = this.state\n const { componentIdentifier } = store.getState().pages[pageKey]\n const Component = this.props.mapping[componentIdentifier]\n\n if (Component) {\n return (\n <Component\n pageKey={pageKey}\n navigateTo={this.navigateTo}\n visit={visit}\n remote={remote}\n {...ownProps}\n />\n )\n } else {\n this.notFound(componentIdentifier)\n }\n }\n}\n\nexport default Nav\n","import * as actions from './actions'\nimport { Dispatch, JSONValue, RootState } from './types'\nimport { getIn } from './utils/immutability'\nimport { Middleware } from 'redux'\nimport { KeyPathError } from './utils/immutability'\n\nconst actionValues = Object.values(actions).map((action) => action.toString())\n\n/**\n * A middleware that will update all {@link Fragment} across the {@link\n * AllPages} slice, if a fragment on any page was mutated.\n *\n * @experimental\n */\nconst fragmentMiddleware: Middleware<unknown, RootState, Dispatch> =\n (store) => (next) => (action) => {\n const prevState = store.getState()\n const nextAction = next(action)\n const nextState = store.getState()\n if (\n !(\n action instanceof Object &&\n 'type' in action &&\n typeof action.type === 'string'\n )\n ) {\n return nextAction\n }\n\n const type = action.type\n\n if (actionValues.includes(type)) {\n return nextAction\n }\n\n if (prevState.pages === nextState.pages) {\n return nextAction\n }\n\n const changedFragments: Record<string, JSONValue> = {}\n const changedKeys = Object.keys(nextState.pages).filter((key) => {\n return prevState.pages[key] !== nextState.pages[key]\n })\n\n if (changedKeys.length === 0) {\n return nextAction\n }\n\n changedKeys.forEach((key) => {\n nextState.pages[key].fragments.forEach((fragment) => {\n const { type, path } = fragment\n const nextPage = nextState.pages[key]\n const prevPage = prevState.pages[key]\n let nextFragment, prevFragment\n\n try {\n prevFragment = getIn(prevPage, path)\n nextFragment = getIn(nextPage, path)\n } catch (err) {\n if (err instanceof KeyPathError) {\n console.warn(err.message)\n } else {\n throw err\n }\n }\n\n if (\n nextFragment !== undefined &&\n prevFragment !== undefined &&\n nextFragment !== prevFragment &&\n nextFragment\n ) {\n changedFragments[type] = nextFragment\n }\n })\n })\n\n if (Object.keys(changedFragments).length === 0) {\n return nextAction\n }\n\n store.dispatch({\n type: actions.UPDATE_FRAGMENTS,\n payload: {\n changedFragments,\n },\n })\n\n return nextAction\n }\n\nexport { fragmentMiddleware }\n"],"mappings":"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","names":["React","type","React"]}