@thoughtbot/superglue 1.0.3 → 2.0.0-alpha.10
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/.tool-versions +1 -2
- package/dist/action_creators.d.mts +1 -1
- package/dist/action_creators.mjs +1 -1
- package/dist/{chunk-ENOVWJUC.mjs → chunk-J2XH5QTK.mjs} +565 -68
- package/dist/chunk-J2XH5QTK.mjs.map +1 -0
- package/dist/cjs/action_creators.cjs +535 -66
- package/dist/cjs/action_creators.cjs.map +1 -1
- package/dist/cjs/superglue.cjs +780 -112
- package/dist/cjs/superglue.cjs.map +1 -1
- package/dist/{index-BYr1PoYr.d.mts → index-j0c-9ZLt.d.mts} +69 -18
- package/dist/superglue.d.mts +46 -14
- package/dist/superglue.mjs +267 -54
- package/dist/superglue.mjs.map +1 -1
- package/package.json +16 -8
- package/thoughtbot-superglue-2.0.0-alpha.10.tgz +0 -0
- package/typedoc.json +1 -0
- package/dist/chunk-ENOVWJUC.mjs.map +0 -1
package/dist/cjs/superglue.cjs
CHANGED
|
@@ -42,19 +42,22 @@ __export(lib_exports, {
|
|
|
42
42
|
getIn: () => getIn,
|
|
43
43
|
pageReducer: () => pageReducer,
|
|
44
44
|
prepareStore: () => prepareStore,
|
|
45
|
+
receiveResponse: () => receiveResponse,
|
|
45
46
|
removePage: () => removePage,
|
|
46
47
|
rootReducer: () => rootReducer,
|
|
47
48
|
saveAndProcessPage: () => saveAndProcessPage,
|
|
48
49
|
saveResponse: () => saveResponse,
|
|
49
50
|
setup: () => setup,
|
|
50
51
|
superglueReducer: () => superglueReducer,
|
|
51
|
-
|
|
52
|
+
unproxy: () => unproxy2,
|
|
52
53
|
urlToPageKey: () => urlToPageKey,
|
|
53
54
|
useContent: () => useContent,
|
|
55
|
+
useSetFragment: () => useSetFragment,
|
|
56
|
+
useStreamSource: () => useStreamSource,
|
|
54
57
|
useSuperglue: () => useSuperglue
|
|
55
58
|
});
|
|
56
59
|
module.exports = __toCommonJS(lib_exports);
|
|
57
|
-
var
|
|
60
|
+
var import_react4 = __toESM(require("react"));
|
|
58
61
|
|
|
59
62
|
// lib/config.ts
|
|
60
63
|
var config = {
|
|
@@ -228,7 +231,26 @@ function setIn(object, path, value) {
|
|
|
228
231
|
return results[0];
|
|
229
232
|
}
|
|
230
233
|
|
|
234
|
+
// lib/utils/limited_set.ts
|
|
235
|
+
var LimitedSet = class extends Set {
|
|
236
|
+
constructor(maxSize) {
|
|
237
|
+
super();
|
|
238
|
+
this.maxSize = maxSize;
|
|
239
|
+
}
|
|
240
|
+
add(value) {
|
|
241
|
+
if (this.size >= this.maxSize) {
|
|
242
|
+
const iterator = this.values();
|
|
243
|
+
const oldestValue = iterator.next().value;
|
|
244
|
+
this.delete(oldestValue);
|
|
245
|
+
}
|
|
246
|
+
super.add(value);
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
231
251
|
// lib/utils/request.ts
|
|
252
|
+
var import_uuid = require("uuid");
|
|
253
|
+
var lastRequestIds = new LimitedSet(20);
|
|
232
254
|
function isValidResponse(xhr) {
|
|
233
255
|
return isValidContent(xhr) && !downloadingFile(xhr);
|
|
234
256
|
}
|
|
@@ -284,6 +306,9 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
284
306
|
nextHeaders["x-requested-with"] = "XMLHttpRequest";
|
|
285
307
|
nextHeaders["accept"] = "application/json";
|
|
286
308
|
nextHeaders["x-superglue-request"] = "true";
|
|
309
|
+
const requestId = (0, import_uuid.v4)();
|
|
310
|
+
lastRequestIds.add(requestId);
|
|
311
|
+
nextHeaders["X-Superglue-Request-Id"] = requestId;
|
|
287
312
|
if (method != "GET" && method != "HEAD") {
|
|
288
313
|
nextHeaders["content-type"] = "application/json";
|
|
289
314
|
}
|
|
@@ -323,7 +348,7 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
323
348
|
return [fetchPath.toString(), { ...options, ...rest }];
|
|
324
349
|
}
|
|
325
350
|
function extractJSON(rsp) {
|
|
326
|
-
return rsp.
|
|
351
|
+
return rsp.json().then((json) => {
|
|
327
352
|
return { rsp, json };
|
|
328
353
|
}).catch((e) => {
|
|
329
354
|
e.response = rsp;
|
|
@@ -477,7 +502,6 @@ var handleGraft = (0, import_toolkit.createAction)(
|
|
|
477
502
|
var superglueError = (0, import_toolkit.createAction)(
|
|
478
503
|
"@@superglue/ERROR"
|
|
479
504
|
);
|
|
480
|
-
var updateFragments = (0, import_toolkit.createAction)("@@superglue/UPDATE_FRAGMENTS");
|
|
481
505
|
var copyPage = (0, import_toolkit.createAction)(
|
|
482
506
|
"@@superglue/COPY_PAGE"
|
|
483
507
|
);
|
|
@@ -492,24 +516,291 @@ var beforeRemote = (0, import_toolkit.createAction)("@@superglue/BEFORE_REMOTE")
|
|
|
492
516
|
var setCSRFToken = (0, import_toolkit.createAction)("@@superglue/SET_CSRF_TOKEN");
|
|
493
517
|
var historyChange = (0, import_toolkit.createAction)("@@superglue/HISTORY_CHANGE");
|
|
494
518
|
var setActivePage = (0, import_toolkit.createAction)("@@superglue/SET_ACTIVE_PAGE");
|
|
519
|
+
var handleFragmentGraft = (0, import_toolkit.createAction)(
|
|
520
|
+
"@@superglue/HANDLE_FRAGMENT_GRAFT",
|
|
521
|
+
({
|
|
522
|
+
fragmentId,
|
|
523
|
+
response
|
|
524
|
+
}) => {
|
|
525
|
+
return {
|
|
526
|
+
payload: {
|
|
527
|
+
response,
|
|
528
|
+
fragmentId
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
);
|
|
533
|
+
var saveFragment = (0, import_toolkit.createAction)(
|
|
534
|
+
"@@superglue/SAVE_FRAGMENT",
|
|
535
|
+
({ fragmentId, data }) => {
|
|
536
|
+
return {
|
|
537
|
+
payload: {
|
|
538
|
+
fragmentId,
|
|
539
|
+
data
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
var receiveResponse = (0, import_toolkit.createAction)(
|
|
545
|
+
"@@superglue/RECEIVE_RESPONSE",
|
|
546
|
+
({ pageKey, response }) => {
|
|
547
|
+
pageKey = urlToPageKey(pageKey);
|
|
548
|
+
return {
|
|
549
|
+
payload: {
|
|
550
|
+
pageKey,
|
|
551
|
+
response
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
var appendToFragment = (0, import_toolkit.createAction)(
|
|
557
|
+
"@@superglue/APPEND_TO_FRAGMENT",
|
|
558
|
+
({ data, fragmentId }) => {
|
|
559
|
+
return {
|
|
560
|
+
payload: {
|
|
561
|
+
data,
|
|
562
|
+
fragmentId
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
var prependToFragment = (0, import_toolkit.createAction)(
|
|
568
|
+
"@@superglue/PREPEND_TO_FRAGMENT",
|
|
569
|
+
({ data, fragmentId }) => {
|
|
570
|
+
return {
|
|
571
|
+
payload: {
|
|
572
|
+
data,
|
|
573
|
+
fragmentId
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
|
|
579
|
+
// lib/utils/proxy.ts
|
|
580
|
+
var ORIGINAL_TARGET = Symbol("@@originalTarget");
|
|
581
|
+
var ARRAY_GETTER_METHODS = /* @__PURE__ */ new Set([
|
|
582
|
+
Symbol.iterator,
|
|
583
|
+
"at",
|
|
584
|
+
"concat",
|
|
585
|
+
"entries",
|
|
586
|
+
"every",
|
|
587
|
+
"filter",
|
|
588
|
+
"find",
|
|
589
|
+
"findIndex",
|
|
590
|
+
"flat",
|
|
591
|
+
"flatMap",
|
|
592
|
+
"forEach",
|
|
593
|
+
"includes",
|
|
594
|
+
"indexOf",
|
|
595
|
+
"join",
|
|
596
|
+
"keys",
|
|
597
|
+
"lastIndexOf",
|
|
598
|
+
"map",
|
|
599
|
+
"reduce",
|
|
600
|
+
"reduceRight",
|
|
601
|
+
"slice",
|
|
602
|
+
"some",
|
|
603
|
+
"toString",
|
|
604
|
+
"values"
|
|
605
|
+
]);
|
|
606
|
+
var ARRAY_SETTER_METHODS = /* @__PURE__ */ new Set([
|
|
607
|
+
"copyWithin",
|
|
608
|
+
"fill",
|
|
609
|
+
"pop",
|
|
610
|
+
"push",
|
|
611
|
+
"reverse",
|
|
612
|
+
"shift",
|
|
613
|
+
"sort",
|
|
614
|
+
"splice",
|
|
615
|
+
"unshift"
|
|
616
|
+
]);
|
|
617
|
+
function isArraySetter(prop) {
|
|
618
|
+
return ARRAY_SETTER_METHODS.has(prop);
|
|
619
|
+
}
|
|
620
|
+
function isArrayGetter(prop) {
|
|
621
|
+
return ARRAY_GETTER_METHODS.has(prop);
|
|
622
|
+
}
|
|
623
|
+
function convertToInt(prop) {
|
|
624
|
+
if (typeof prop === "symbol") return null;
|
|
625
|
+
const num = Number(prop);
|
|
626
|
+
return Number.isInteger(num) ? num : null;
|
|
627
|
+
}
|
|
628
|
+
function isFragmentReference(value) {
|
|
629
|
+
return !!value && typeof value === "object" && "__id" in value && typeof value.__id === "string";
|
|
630
|
+
}
|
|
631
|
+
function createArrayProxy(arrayData, fragments, dependencies, proxyCache) {
|
|
632
|
+
if (proxyCache && proxyCache.has(arrayData)) {
|
|
633
|
+
return proxyCache.get(arrayData);
|
|
634
|
+
}
|
|
635
|
+
const proxy = new Proxy(arrayData, {
|
|
636
|
+
get(target, prop) {
|
|
637
|
+
if (prop === ORIGINAL_TARGET) {
|
|
638
|
+
return target;
|
|
639
|
+
}
|
|
640
|
+
if (isArrayGetter(prop)) {
|
|
641
|
+
const method = target[prop];
|
|
642
|
+
if (typeof method === "function") {
|
|
643
|
+
return function(...args) {
|
|
644
|
+
return Reflect.apply(method, proxy, args);
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
return method;
|
|
648
|
+
}
|
|
649
|
+
if (isArraySetter(prop)) {
|
|
650
|
+
throw new Error(
|
|
651
|
+
`Cannot mutate proxy array. Use useSetFragment to update state.`
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
const index = convertToInt(prop);
|
|
655
|
+
if (index !== null && index >= 0 && index < target.length) {
|
|
656
|
+
const item = target[index];
|
|
657
|
+
if (isFragmentReference(item)) {
|
|
658
|
+
dependencies.add(item.__id);
|
|
659
|
+
const fragmentData = fragments.current[item.__id];
|
|
660
|
+
if (!fragmentData) {
|
|
661
|
+
return void 0;
|
|
662
|
+
}
|
|
663
|
+
return createProxy(fragmentData, fragments, dependencies, proxyCache);
|
|
664
|
+
}
|
|
665
|
+
if (typeof item === "object" && item !== null) {
|
|
666
|
+
if ("$$typeof" in item) {
|
|
667
|
+
return item;
|
|
668
|
+
} else {
|
|
669
|
+
return createProxy(
|
|
670
|
+
item,
|
|
671
|
+
fragments,
|
|
672
|
+
dependencies,
|
|
673
|
+
proxyCache
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return item;
|
|
678
|
+
}
|
|
679
|
+
return Reflect.get(target, prop);
|
|
680
|
+
},
|
|
681
|
+
has(target, prop) {
|
|
682
|
+
if (prop === ORIGINAL_TARGET) {
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
return Reflect.has(target, prop);
|
|
686
|
+
},
|
|
687
|
+
set() {
|
|
688
|
+
throw new Error(
|
|
689
|
+
"Cannot mutate proxy array. Use useSetFragment to update state."
|
|
690
|
+
);
|
|
691
|
+
},
|
|
692
|
+
deleteProperty() {
|
|
693
|
+
throw new Error(
|
|
694
|
+
"Cannot delete properties on proxy array. Use useSetFragment to update state."
|
|
695
|
+
);
|
|
696
|
+
},
|
|
697
|
+
defineProperty() {
|
|
698
|
+
throw new Error(
|
|
699
|
+
"Cannot define properties on proxy array. Use useSetFragment to update state."
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
if (proxyCache) {
|
|
704
|
+
proxyCache.set(arrayData, proxy);
|
|
705
|
+
}
|
|
706
|
+
return proxy;
|
|
707
|
+
}
|
|
708
|
+
function createObjectProxy(objectData, fragments, dependencies, proxyCache) {
|
|
709
|
+
if (proxyCache && proxyCache.has(objectData)) {
|
|
710
|
+
return proxyCache.get(objectData);
|
|
711
|
+
}
|
|
712
|
+
const proxy = new Proxy(objectData, {
|
|
713
|
+
get(target, prop) {
|
|
714
|
+
if (prop === ORIGINAL_TARGET) {
|
|
715
|
+
return target;
|
|
716
|
+
}
|
|
717
|
+
const value = target[prop];
|
|
718
|
+
if (isFragmentReference(value)) {
|
|
719
|
+
dependencies.add(value.__id);
|
|
720
|
+
const fragmentData = fragments.current[value.__id];
|
|
721
|
+
if (!fragmentData) {
|
|
722
|
+
return void 0;
|
|
723
|
+
}
|
|
724
|
+
return createProxy(fragmentData, fragments, dependencies, proxyCache);
|
|
725
|
+
}
|
|
726
|
+
if (typeof value === "object" && value !== null) {
|
|
727
|
+
if ("$$typeof" in value) {
|
|
728
|
+
return value;
|
|
729
|
+
} else if (Array.isArray(value)) {
|
|
730
|
+
return createArrayProxy(value, fragments, dependencies, proxyCache);
|
|
731
|
+
} else {
|
|
732
|
+
return createObjectProxy(value, fragments, dependencies, proxyCache);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return value;
|
|
736
|
+
},
|
|
737
|
+
has(target, prop) {
|
|
738
|
+
if (prop === ORIGINAL_TARGET) {
|
|
739
|
+
return true;
|
|
740
|
+
}
|
|
741
|
+
return Reflect.has(target, prop);
|
|
742
|
+
},
|
|
743
|
+
set() {
|
|
744
|
+
throw new Error(
|
|
745
|
+
"Cannot mutate proxy object. Use useSetFragment to update state."
|
|
746
|
+
);
|
|
747
|
+
},
|
|
748
|
+
deleteProperty() {
|
|
749
|
+
throw new Error(
|
|
750
|
+
"Cannot delete properties on proxy object. Use useSetFragment to update state."
|
|
751
|
+
);
|
|
752
|
+
},
|
|
753
|
+
defineProperty() {
|
|
754
|
+
throw new Error(
|
|
755
|
+
"Cannot define properties on proxy object. Use useSetFragment to update state."
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
if (proxyCache) {
|
|
760
|
+
proxyCache.set(objectData, proxy);
|
|
761
|
+
}
|
|
762
|
+
return proxy;
|
|
763
|
+
}
|
|
764
|
+
function createProxy(content, fragments, dependencies, proxyCache) {
|
|
765
|
+
if (!content || typeof content !== "object") {
|
|
766
|
+
return content;
|
|
767
|
+
}
|
|
768
|
+
if ("$$typeof" in content) {
|
|
769
|
+
return content;
|
|
770
|
+
}
|
|
771
|
+
if (Array.isArray(content)) {
|
|
772
|
+
return createArrayProxy(content, fragments, dependencies, proxyCache);
|
|
773
|
+
}
|
|
774
|
+
return createObjectProxy(content, fragments, dependencies, proxyCache);
|
|
775
|
+
}
|
|
776
|
+
function unproxy(proxy) {
|
|
777
|
+
if (proxy && typeof proxy === "object" && ORIGINAL_TARGET in proxy) {
|
|
778
|
+
return proxy[ORIGINAL_TARGET];
|
|
779
|
+
}
|
|
780
|
+
return proxy;
|
|
781
|
+
}
|
|
495
782
|
|
|
496
783
|
// lib/action_creators/requests.ts
|
|
497
784
|
function handleFetchErr(err, fetchArgs, dispatch) {
|
|
498
785
|
dispatch(superglueError({ message: err.message }));
|
|
786
|
+
console.error(err);
|
|
499
787
|
throw err;
|
|
500
788
|
}
|
|
501
789
|
function buildMeta(pageKey, page, state, rsp, fetchArgs) {
|
|
502
790
|
const { assets: prevAssets } = state;
|
|
503
791
|
const { assets: nextAssets } = page;
|
|
504
|
-
|
|
792
|
+
const meta = {
|
|
505
793
|
pageKey,
|
|
506
794
|
page,
|
|
507
795
|
redirected: rsp.redirected,
|
|
508
796
|
rsp,
|
|
509
797
|
fetchArgs,
|
|
510
|
-
componentIdentifier: page.componentIdentifier,
|
|
511
798
|
needsRefresh: needsRefresh(prevAssets, nextAssets)
|
|
512
799
|
};
|
|
800
|
+
if (page.action !== "handleStreamResponse") {
|
|
801
|
+
meta.componentIdentifier = page.componentIdentifier;
|
|
802
|
+
}
|
|
803
|
+
return meta;
|
|
513
804
|
}
|
|
514
805
|
var MismatchedComponentError = class extends Error {
|
|
515
806
|
constructor(message) {
|
|
@@ -517,10 +808,11 @@ var MismatchedComponentError = class extends Error {
|
|
|
517
808
|
this.name = "MismatchedComponentError";
|
|
518
809
|
}
|
|
519
810
|
};
|
|
811
|
+
var defaultBeforeSave = (prevPage, receivedPage) => receivedPage;
|
|
520
812
|
var remote = (path, {
|
|
521
813
|
pageKey: targetPageKey,
|
|
522
814
|
force = false,
|
|
523
|
-
beforeSave =
|
|
815
|
+
beforeSave = defaultBeforeSave,
|
|
524
816
|
...rest
|
|
525
817
|
} = {}) => {
|
|
526
818
|
targetPageKey = targetPageKey && urlToPageKey(targetPageKey);
|
|
@@ -530,7 +822,7 @@ var remote = (path, {
|
|
|
530
822
|
dispatch(beforeRemote({ currentPageKey, fetchArgs }));
|
|
531
823
|
dispatch(beforeFetch({ fetchArgs }));
|
|
532
824
|
return fetch(...fetchArgs).then(parseResponse).then(({ rsp, json }) => {
|
|
533
|
-
const { superglue, pages = {} } = getState();
|
|
825
|
+
const { superglue, pages = {}, fragments } = getState();
|
|
534
826
|
let pageKey;
|
|
535
827
|
if (targetPageKey === void 0) {
|
|
536
828
|
const isGet = fetchArgs[1].method === "GET";
|
|
@@ -539,10 +831,11 @@ var remote = (path, {
|
|
|
539
831
|
pageKey = targetPageKey;
|
|
540
832
|
}
|
|
541
833
|
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
834
|
+
if (json.action !== "handleStreamResponse") {
|
|
835
|
+
const existingId = pages[pageKey]?.componentIdentifier;
|
|
836
|
+
const receivedId = json.componentIdentifier;
|
|
837
|
+
if (!!existingId && existingId != receivedId && !force) {
|
|
838
|
+
const message = `You cannot replace or update an existing page
|
|
546
839
|
located at pages["${currentPageKey}"] that has a componentIdentifier
|
|
547
840
|
of "${existingId}" with the contents of a page response that has a
|
|
548
841
|
componentIdentifier of "${receivedId}".
|
|
@@ -558,9 +851,27 @@ compatible with the page component associated with "${existingId}".
|
|
|
558
851
|
Consider using data-sg-visit, the visit function, or redirect_back to
|
|
559
852
|
the same page. Or if you're sure you want to proceed, use force: true.
|
|
560
853
|
`;
|
|
561
|
-
|
|
854
|
+
throw new MismatchedComponentError(message);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
dispatch(
|
|
858
|
+
receiveResponse({
|
|
859
|
+
pageKey,
|
|
860
|
+
response: JSON.parse(JSON.stringify(json))
|
|
861
|
+
})
|
|
862
|
+
);
|
|
863
|
+
const existingPage = createProxy(
|
|
864
|
+
pages[pageKey],
|
|
865
|
+
{ current: fragments },
|
|
866
|
+
/* @__PURE__ */ new Set(),
|
|
867
|
+
/* @__PURE__ */ new WeakMap()
|
|
868
|
+
);
|
|
869
|
+
let page = json;
|
|
870
|
+
if (json.action === "savePage" || json.action === "graft") {
|
|
871
|
+
page = JSON.parse(
|
|
872
|
+
JSON.stringify(beforeSave(existingPage, json))
|
|
873
|
+
);
|
|
562
874
|
}
|
|
563
|
-
const page = beforeSave(pages[pageKey], json);
|
|
564
875
|
return dispatch(saveAndProcessPage(pageKey, page)).then(() => meta);
|
|
565
876
|
}).catch((e) => handleFetchErr(e, fetchArgs, dispatch));
|
|
566
877
|
};
|
|
@@ -577,6 +888,155 @@ function calculatePageKey(rsp, isGet, currentPageKey) {
|
|
|
577
888
|
return pageKey;
|
|
578
889
|
}
|
|
579
890
|
|
|
891
|
+
// lib/action_creators/stream.ts
|
|
892
|
+
var streamPrepend = (fragments, data, options = {}) => {
|
|
893
|
+
return (dispatch) => {
|
|
894
|
+
if (options.saveAs) {
|
|
895
|
+
const { saveAs } = options;
|
|
896
|
+
dispatch(
|
|
897
|
+
saveFragment({
|
|
898
|
+
fragmentId: saveAs,
|
|
899
|
+
data
|
|
900
|
+
})
|
|
901
|
+
);
|
|
902
|
+
fragments.forEach((fragmentId) => {
|
|
903
|
+
dispatch(
|
|
904
|
+
prependToFragment({
|
|
905
|
+
fragmentId,
|
|
906
|
+
data: {
|
|
907
|
+
__id: saveAs
|
|
908
|
+
}
|
|
909
|
+
})
|
|
910
|
+
);
|
|
911
|
+
});
|
|
912
|
+
} else {
|
|
913
|
+
fragments.forEach((fragmentId) => {
|
|
914
|
+
dispatch(
|
|
915
|
+
prependToFragment({
|
|
916
|
+
fragmentId,
|
|
917
|
+
data
|
|
918
|
+
})
|
|
919
|
+
);
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
};
|
|
924
|
+
var streamAppend = (fragments, data, options = {}) => {
|
|
925
|
+
return (dispatch) => {
|
|
926
|
+
if (options.saveAs) {
|
|
927
|
+
const { saveAs } = options;
|
|
928
|
+
dispatch(
|
|
929
|
+
saveFragment({
|
|
930
|
+
fragmentId: saveAs,
|
|
931
|
+
data
|
|
932
|
+
})
|
|
933
|
+
);
|
|
934
|
+
fragments.forEach((fragmentId) => {
|
|
935
|
+
dispatch(
|
|
936
|
+
appendToFragment({
|
|
937
|
+
fragmentId,
|
|
938
|
+
data: {
|
|
939
|
+
__id: saveAs
|
|
940
|
+
}
|
|
941
|
+
})
|
|
942
|
+
);
|
|
943
|
+
});
|
|
944
|
+
} else {
|
|
945
|
+
fragments.forEach((fragmentId) => {
|
|
946
|
+
dispatch(
|
|
947
|
+
appendToFragment({
|
|
948
|
+
fragmentId,
|
|
949
|
+
data
|
|
950
|
+
})
|
|
951
|
+
);
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
};
|
|
956
|
+
var streamSave = (fragment, data) => {
|
|
957
|
+
return (dispatch) => {
|
|
958
|
+
dispatch(
|
|
959
|
+
saveFragment({
|
|
960
|
+
fragmentId: fragment,
|
|
961
|
+
data
|
|
962
|
+
})
|
|
963
|
+
);
|
|
964
|
+
};
|
|
965
|
+
};
|
|
966
|
+
var handleStreamMessage = (rawMessage) => {
|
|
967
|
+
return (dispatch) => {
|
|
968
|
+
const message = JSON.parse(rawMessage);
|
|
969
|
+
let nextMessage = message;
|
|
970
|
+
if (message.handler !== "refresh") {
|
|
971
|
+
message.fragments.reverse().forEach((fragment) => {
|
|
972
|
+
const { id, path } = fragment;
|
|
973
|
+
const node = getIn(nextMessage, path);
|
|
974
|
+
nextMessage = setIn(nextMessage, path, { __id: id });
|
|
975
|
+
dispatch(
|
|
976
|
+
saveFragment({
|
|
977
|
+
fragmentId: id,
|
|
978
|
+
data: node
|
|
979
|
+
})
|
|
980
|
+
);
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
if (nextMessage.action === "handleStreamMessage") {
|
|
984
|
+
if (nextMessage.handler === "append") {
|
|
985
|
+
dispatch(
|
|
986
|
+
streamAppend(
|
|
987
|
+
nextMessage.fragmentIds,
|
|
988
|
+
nextMessage.data,
|
|
989
|
+
nextMessage.options
|
|
990
|
+
)
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
if (nextMessage.handler === "prepend") {
|
|
994
|
+
dispatch(
|
|
995
|
+
streamPrepend(
|
|
996
|
+
nextMessage.fragmentIds,
|
|
997
|
+
nextMessage.data,
|
|
998
|
+
nextMessage.options
|
|
999
|
+
)
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
if (nextMessage.handler === "save") {
|
|
1003
|
+
dispatch(streamSave(nextMessage.fragmentIds[0], nextMessage.data));
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
};
|
|
1008
|
+
var handleStreamResponse = (response) => {
|
|
1009
|
+
return (dispatch) => {
|
|
1010
|
+
let nextResponse = response;
|
|
1011
|
+
nextResponse.fragments.reverse().forEach((fragment) => {
|
|
1012
|
+
const { id, path } = fragment;
|
|
1013
|
+
const node = getIn(nextResponse, path);
|
|
1014
|
+
nextResponse = setIn(nextResponse, path, { __id: id });
|
|
1015
|
+
dispatch(
|
|
1016
|
+
saveFragment({
|
|
1017
|
+
fragmentId: id,
|
|
1018
|
+
data: node
|
|
1019
|
+
})
|
|
1020
|
+
);
|
|
1021
|
+
});
|
|
1022
|
+
nextResponse.data.forEach((message) => {
|
|
1023
|
+
if (message.handler === "append") {
|
|
1024
|
+
dispatch(
|
|
1025
|
+
streamAppend(message.fragmentIds, message.data, message.options)
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
if (message.handler === "prepend") {
|
|
1029
|
+
dispatch(
|
|
1030
|
+
streamPrepend(message.fragmentIds, message.data, message.options)
|
|
1031
|
+
);
|
|
1032
|
+
}
|
|
1033
|
+
if (message.handler === "save") {
|
|
1034
|
+
dispatch(streamSave(message.fragmentIds[0], message.data));
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
};
|
|
1038
|
+
};
|
|
1039
|
+
|
|
580
1040
|
// lib/action_creators/index.ts
|
|
581
1041
|
function fetchDeferments(pageKey, defers = []) {
|
|
582
1042
|
pageKey = urlToPageKey(pageKey);
|
|
@@ -610,58 +1070,64 @@ function fetchDeferments(pageKey, defers = []) {
|
|
|
610
1070
|
return Promise.all(fetches);
|
|
611
1071
|
};
|
|
612
1072
|
}
|
|
1073
|
+
function addPlaceholdersToDeferredNodes(existingPage, page) {
|
|
1074
|
+
const { defers = [] } = existingPage;
|
|
1075
|
+
const prevDefers = defers.map(({ path }) => {
|
|
1076
|
+
const node = getIn(existingPage, path);
|
|
1077
|
+
const copy = JSON.stringify(node);
|
|
1078
|
+
return [path, JSON.parse(copy)];
|
|
1079
|
+
});
|
|
1080
|
+
return prevDefers.reduce((memo, [path, node]) => {
|
|
1081
|
+
return setIn(page, path, node);
|
|
1082
|
+
}, page);
|
|
1083
|
+
}
|
|
613
1084
|
function saveAndProcessPage(pageKey, page) {
|
|
614
1085
|
return (dispatch, getState) => {
|
|
615
1086
|
pageKey = urlToPageKey(pageKey);
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
})
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
});
|
|
646
|
-
} else {
|
|
647
|
-
dispatch(saveResponse({ pageKey, page }));
|
|
648
|
-
const currentPage = getState().pages[pageKey];
|
|
649
|
-
currentPage.fragments.forEach((fragment) => {
|
|
650
|
-
const { type, path } = fragment;
|
|
651
|
-
const currentFragment = getIn(currentPage, path);
|
|
1087
|
+
let nextPage = page;
|
|
1088
|
+
const state = getState();
|
|
1089
|
+
if (page.action === "savePage" && state.pages[pageKey]) {
|
|
1090
|
+
const existingPage = createProxy(
|
|
1091
|
+
state.pages[pageKey],
|
|
1092
|
+
{ current: state.fragments },
|
|
1093
|
+
/* @__PURE__ */ new Set(),
|
|
1094
|
+
/* @__PURE__ */ new WeakMap()
|
|
1095
|
+
);
|
|
1096
|
+
nextPage = JSON.parse(
|
|
1097
|
+
JSON.stringify(addPlaceholdersToDeferredNodes(existingPage, nextPage))
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
page.fragments.slice().reverse().forEach((fragment) => {
|
|
1101
|
+
const { id, path } = fragment;
|
|
1102
|
+
const node = getIn(nextPage, path);
|
|
1103
|
+
nextPage = setIn(nextPage, path, { __id: id });
|
|
1104
|
+
dispatch(
|
|
1105
|
+
saveFragment({
|
|
1106
|
+
fragmentId: id,
|
|
1107
|
+
data: node
|
|
1108
|
+
})
|
|
1109
|
+
);
|
|
1110
|
+
});
|
|
1111
|
+
if (nextPage.action === "graft") {
|
|
1112
|
+
if (typeof nextPage.fragmentContext === "string") {
|
|
652
1113
|
dispatch(
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
value: currentFragment,
|
|
657
|
-
path
|
|
1114
|
+
handleFragmentGraft({
|
|
1115
|
+
fragmentId: nextPage.fragmentContext,
|
|
1116
|
+
response: nextPage
|
|
658
1117
|
})
|
|
659
1118
|
);
|
|
660
|
-
}
|
|
1119
|
+
} else {
|
|
1120
|
+
dispatch(handleGraft({ pageKey, page: nextPage }));
|
|
1121
|
+
}
|
|
1122
|
+
} else if (nextPage.action === "handleStreamResponse") {
|
|
1123
|
+
dispatch(handleStreamResponse(nextPage));
|
|
1124
|
+
return Promise.resolve();
|
|
1125
|
+
} else {
|
|
1126
|
+
dispatch(saveResponse({ pageKey, page: nextPage }));
|
|
661
1127
|
}
|
|
662
1128
|
const hasFetch = typeof fetch != "undefined";
|
|
663
1129
|
if (hasFetch) {
|
|
664
|
-
return dispatch(fetchDeferments(pageKey, defers)).then(
|
|
1130
|
+
return dispatch(fetchDeferments(pageKey, nextPage.defers)).then(
|
|
665
1131
|
() => Promise.resolve()
|
|
666
1132
|
);
|
|
667
1133
|
} else {
|
|
@@ -671,13 +1137,170 @@ function saveAndProcessPage(pageKey, page) {
|
|
|
671
1137
|
}
|
|
672
1138
|
|
|
673
1139
|
// lib/index.tsx
|
|
1140
|
+
var import_react_redux5 = require("react-redux");
|
|
1141
|
+
|
|
1142
|
+
// lib/hooks/useStreamSource.tsx
|
|
1143
|
+
var import_react2 = require("react");
|
|
1144
|
+
|
|
1145
|
+
// lib/hooks/index.ts
|
|
674
1146
|
var import_react_redux3 = require("react-redux");
|
|
1147
|
+
|
|
1148
|
+
// lib/hooks/useContent.tsx
|
|
1149
|
+
var import_react_redux = require("react-redux");
|
|
1150
|
+
var import_react = require("react");
|
|
1151
|
+
function useContent(fragmentRef) {
|
|
1152
|
+
const superglueState = useSuperglue();
|
|
1153
|
+
const currentPageKey = superglueState.currentPageKey;
|
|
1154
|
+
const dependencies = (0, import_react.useRef)(/* @__PURE__ */ new Set());
|
|
1155
|
+
const fragmentId = typeof fragmentRef === "string" ? fragmentRef : fragmentRef?.__id;
|
|
1156
|
+
const sourceData = (0, import_react_redux.useSelector)((state) => {
|
|
1157
|
+
if (fragmentId) {
|
|
1158
|
+
return state.fragments[fragmentId];
|
|
1159
|
+
} else {
|
|
1160
|
+
return state.pages[currentPageKey].data;
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
const trackedFragments = (0, import_react_redux.useSelector)(
|
|
1164
|
+
(state) => state.fragments,
|
|
1165
|
+
(oldFragments, newFragments) => {
|
|
1166
|
+
if (oldFragments === newFragments) {
|
|
1167
|
+
return true;
|
|
1168
|
+
}
|
|
1169
|
+
return Array.from(dependencies.current).every((id) => {
|
|
1170
|
+
const prevVal = oldFragments[id];
|
|
1171
|
+
const nextVal = newFragments[id];
|
|
1172
|
+
return prevVal === nextVal;
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
);
|
|
1176
|
+
const store = (0, import_react_redux.useStore)();
|
|
1177
|
+
const proxy = (0, import_react.useMemo)(() => {
|
|
1178
|
+
const proxyCache = /* @__PURE__ */ new WeakMap();
|
|
1179
|
+
if (fragmentId && !sourceData) {
|
|
1180
|
+
return void 0;
|
|
1181
|
+
}
|
|
1182
|
+
return createProxy(
|
|
1183
|
+
sourceData,
|
|
1184
|
+
{ current: store.getState().fragments },
|
|
1185
|
+
dependencies.current,
|
|
1186
|
+
proxyCache
|
|
1187
|
+
);
|
|
1188
|
+
}, [sourceData, trackedFragments]);
|
|
1189
|
+
return proxy;
|
|
1190
|
+
}
|
|
1191
|
+
function unproxy2(proxy) {
|
|
1192
|
+
return unproxy(proxy);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// lib/hooks/useSetFragment.tsx
|
|
1196
|
+
var import_react_redux2 = require("react-redux");
|
|
1197
|
+
var import_immer = require("immer");
|
|
1198
|
+
var immer = new import_immer.Immer();
|
|
1199
|
+
immer.setAutoFreeze(false);
|
|
1200
|
+
function useSetFragment() {
|
|
1201
|
+
const dispatch = (0, import_react_redux2.useDispatch)();
|
|
1202
|
+
const fragments = (0, import_react_redux2.useSelector)((state) => state.fragments);
|
|
1203
|
+
function setter(fragmentRefOrId, updater) {
|
|
1204
|
+
const fragmentId = typeof fragmentRefOrId === "string" ? fragmentRefOrId : fragmentRefOrId.__id;
|
|
1205
|
+
const currentFragment = fragments[fragmentId];
|
|
1206
|
+
if (currentFragment === void 0) {
|
|
1207
|
+
throw new Error(`Fragment with id "${fragmentId}" not found`);
|
|
1208
|
+
}
|
|
1209
|
+
const updatedFragment = immer.produce(currentFragment, updater);
|
|
1210
|
+
dispatch(
|
|
1211
|
+
saveFragment({
|
|
1212
|
+
fragmentId,
|
|
1213
|
+
data: updatedFragment
|
|
1214
|
+
})
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
return setter;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
// lib/hooks/index.ts
|
|
1221
|
+
function useSuperglue() {
|
|
1222
|
+
return (0, import_react_redux3.useSelector)((state) => state.superglue);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// lib/hooks/useStreamSource.tsx
|
|
1226
|
+
var import_lodash = __toESM(require("lodash.debounce"));
|
|
1227
|
+
var StreamActions = class {
|
|
1228
|
+
constructor({
|
|
1229
|
+
remote: remote2,
|
|
1230
|
+
store
|
|
1231
|
+
}) {
|
|
1232
|
+
this.store = store;
|
|
1233
|
+
this.remote = (0, import_lodash.default)(remote2, 300);
|
|
1234
|
+
}
|
|
1235
|
+
refresh(pageKey) {
|
|
1236
|
+
this.remote(pageKey);
|
|
1237
|
+
}
|
|
1238
|
+
prepend(fragments, data, options = {}) {
|
|
1239
|
+
this.store.dispatch(streamPrepend(fragments, data, options));
|
|
1240
|
+
}
|
|
1241
|
+
save(fragment, data) {
|
|
1242
|
+
this.store.dispatch(streamSave(fragment, data));
|
|
1243
|
+
}
|
|
1244
|
+
append(fragments, data, options = {}) {
|
|
1245
|
+
this.store.dispatch(streamAppend(fragments, data, options));
|
|
1246
|
+
}
|
|
1247
|
+
handle(rawMessage, currentPageKey) {
|
|
1248
|
+
const message = JSON.parse(rawMessage);
|
|
1249
|
+
const { superglue } = this.store.getState();
|
|
1250
|
+
const nextPageKey = superglue.currentPageKey;
|
|
1251
|
+
if (message.action === "handleStreamMessage") {
|
|
1252
|
+
if (message.handler === "refresh" && currentPageKey === nextPageKey && !lastRequestIds.has(message.requestId)) {
|
|
1253
|
+
this.refresh(currentPageKey);
|
|
1254
|
+
}
|
|
1255
|
+
if (message.handler !== "refresh") {
|
|
1256
|
+
this.store.dispatch(handleStreamMessage(rawMessage));
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
var CableContext = (0, import_react2.createContext)({
|
|
1262
|
+
cable: null,
|
|
1263
|
+
streamActions: null
|
|
1264
|
+
});
|
|
1265
|
+
function useStreamSource(channel) {
|
|
1266
|
+
const { cable: cable2, streamActions } = (0, import_react2.useContext)(CableContext);
|
|
1267
|
+
const [connected, setConnected] = (0, import_react2.useState)(false);
|
|
1268
|
+
const { currentPageKey } = useSuperglue();
|
|
1269
|
+
const subscriptionRef = (0, import_react2.useRef)(null);
|
|
1270
|
+
(0, import_react2.useEffect)(() => {
|
|
1271
|
+
if (cable2) {
|
|
1272
|
+
const subscription = cable2.subscriptions.create(channel, {
|
|
1273
|
+
received: (message) => {
|
|
1274
|
+
streamActions?.handle(message, currentPageKey);
|
|
1275
|
+
},
|
|
1276
|
+
connected: () => {
|
|
1277
|
+
setConnected(true);
|
|
1278
|
+
},
|
|
1279
|
+
disconnected: () => setConnected(false)
|
|
1280
|
+
});
|
|
1281
|
+
subscriptionRef.current = subscription;
|
|
1282
|
+
return () => subscription.unsubscribe();
|
|
1283
|
+
} else {
|
|
1284
|
+
subscriptionRef.current = null;
|
|
1285
|
+
setConnected(false);
|
|
1286
|
+
return () => {
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
}, [cable2, JSON.stringify(channel), currentPageKey]);
|
|
1290
|
+
return {
|
|
1291
|
+
connected,
|
|
1292
|
+
subscription: subscriptionRef.current
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// lib/index.tsx
|
|
1297
|
+
var import_actioncable = require("@rails/actioncable");
|
|
675
1298
|
var import_history = require("history");
|
|
676
1299
|
|
|
677
1300
|
// lib/components/Navigation.tsx
|
|
678
|
-
var
|
|
679
|
-
var
|
|
680
|
-
var NavigationContext = (0,
|
|
1301
|
+
var import_react3 = __toESM(require("react"));
|
|
1302
|
+
var import_react_redux4 = require("react-redux");
|
|
1303
|
+
var NavigationContext = (0, import_react3.createContext)(
|
|
681
1304
|
{}
|
|
682
1305
|
);
|
|
683
1306
|
var hasWindow = typeof window !== "undefined";
|
|
@@ -694,27 +1317,27 @@ var notFound = (identifier) => {
|
|
|
694
1317
|
);
|
|
695
1318
|
throw error;
|
|
696
1319
|
};
|
|
697
|
-
var NavigationProvider = (0,
|
|
698
|
-
const dispatch = (0,
|
|
699
|
-
const pages = (0,
|
|
700
|
-
const superglue = (0,
|
|
1320
|
+
var NavigationProvider = (0, import_react3.forwardRef)(function NavigationProvider2({ history, visit, remote: remote2, mapping }, ref) {
|
|
1321
|
+
const dispatch = (0, import_react_redux4.useDispatch)();
|
|
1322
|
+
const pages = (0, import_react_redux4.useSelector)((state) => state.pages);
|
|
1323
|
+
const superglue = (0, import_react_redux4.useSelector)(
|
|
701
1324
|
(state) => state.superglue
|
|
702
1325
|
);
|
|
703
|
-
const currentPageKey = (0,
|
|
1326
|
+
const currentPageKey = (0, import_react_redux4.useSelector)(
|
|
704
1327
|
(state) => state.superglue.currentPageKey
|
|
705
1328
|
);
|
|
706
|
-
const store = (0,
|
|
707
|
-
(0,
|
|
1329
|
+
const store = (0, import_react_redux4.useStore)();
|
|
1330
|
+
(0, import_react3.useEffect)(() => {
|
|
708
1331
|
return history.listen(onHistoryChange);
|
|
709
1332
|
}, []);
|
|
710
|
-
(0,
|
|
1333
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
711
1334
|
const state = history.location.state;
|
|
712
1335
|
if (state && "superglue" in state) {
|
|
713
1336
|
const { posX, posY } = state;
|
|
714
1337
|
setWindowScroll(posX, posY);
|
|
715
1338
|
}
|
|
716
1339
|
}, [currentPageKey]);
|
|
717
|
-
(0,
|
|
1340
|
+
(0, import_react3.useImperativeHandle)(
|
|
718
1341
|
ref,
|
|
719
1342
|
() => {
|
|
720
1343
|
return {
|
|
@@ -739,7 +1362,6 @@ var NavigationProvider = (0, import_react.forwardRef)(function NavigationProvide
|
|
|
739
1362
|
hash: location.hash
|
|
740
1363
|
},
|
|
741
1364
|
{
|
|
742
|
-
pageKey: nextPageKey,
|
|
743
1365
|
superglue: true,
|
|
744
1366
|
posY: window.pageYOffset,
|
|
745
1367
|
posX: window.pageXOffset
|
|
@@ -748,7 +1370,7 @@ var NavigationProvider = (0, import_react.forwardRef)(function NavigationProvide
|
|
|
748
1370
|
}
|
|
749
1371
|
}
|
|
750
1372
|
if (state && "superglue" in state) {
|
|
751
|
-
const
|
|
1373
|
+
const pageKey = urlToPageKey(location.pathname + location.search);
|
|
752
1374
|
const prevPageKey = store.getState().superglue.currentPageKey;
|
|
753
1375
|
const containsKey = !!pages[pageKey];
|
|
754
1376
|
if (containsKey) {
|
|
@@ -797,7 +1419,6 @@ var NavigationProvider = (0, import_react.forwardRef)(function NavigationProvide
|
|
|
797
1419
|
const historyArgs = [
|
|
798
1420
|
path,
|
|
799
1421
|
{
|
|
800
|
-
pageKey: nextPageKey,
|
|
801
1422
|
superglue: true,
|
|
802
1423
|
posY: 0,
|
|
803
1424
|
posX: 0
|
|
@@ -843,12 +1464,12 @@ var NavigationProvider = (0, import_react.forwardRef)(function NavigationProvide
|
|
|
843
1464
|
const { componentIdentifier } = pages[currentPageKey];
|
|
844
1465
|
const Component = mapping[componentIdentifier];
|
|
845
1466
|
if (Component) {
|
|
846
|
-
return /* @__PURE__ */
|
|
1467
|
+
return /* @__PURE__ */ import_react3.default.createElement(
|
|
847
1468
|
NavigationContext.Provider,
|
|
848
1469
|
{
|
|
849
1470
|
value: { pageKey: currentPageKey, search, navigateTo, visit, remote: remote2 }
|
|
850
1471
|
},
|
|
851
|
-
/* @__PURE__ */
|
|
1472
|
+
/* @__PURE__ */ import_react3.default.createElement(Component, null)
|
|
852
1473
|
);
|
|
853
1474
|
} else {
|
|
854
1475
|
notFound(componentIdentifier);
|
|
@@ -856,17 +1477,6 @@ var NavigationProvider = (0, import_react.forwardRef)(function NavigationProvide
|
|
|
856
1477
|
});
|
|
857
1478
|
|
|
858
1479
|
// lib/reducers/index.ts
|
|
859
|
-
function addPlaceholdersToDeferredNodes(existingPage, page) {
|
|
860
|
-
const { defers = [] } = existingPage;
|
|
861
|
-
const prevDefers = defers.map(({ path }) => {
|
|
862
|
-
const node = getIn(existingPage, path);
|
|
863
|
-
const copy = JSON.stringify(node);
|
|
864
|
-
return [path, JSON.parse(copy)];
|
|
865
|
-
});
|
|
866
|
-
return prevDefers.reduce((memo, [path, node]) => {
|
|
867
|
-
return setIn(page, path, node);
|
|
868
|
-
}, page);
|
|
869
|
-
}
|
|
870
1480
|
function constrainPagesSize(state) {
|
|
871
1481
|
const { maxPages } = config;
|
|
872
1482
|
const allPageKeys = Object.keys(state);
|
|
@@ -879,14 +1489,10 @@ function constrainPagesSize(state) {
|
|
|
879
1489
|
}
|
|
880
1490
|
function handleSaveResponse(state, pageKey, page) {
|
|
881
1491
|
state = { ...state };
|
|
882
|
-
|
|
1492
|
+
const nextPage = {
|
|
883
1493
|
...page,
|
|
884
1494
|
savedAt: Date.now()
|
|
885
1495
|
};
|
|
886
|
-
const existingPage = state[pageKey];
|
|
887
|
-
if (existingPage) {
|
|
888
|
-
nextPage = addPlaceholdersToDeferredNodes(existingPage, nextPage);
|
|
889
|
-
}
|
|
890
1496
|
constrainPagesSize(state);
|
|
891
1497
|
state[pageKey] = nextPage;
|
|
892
1498
|
return state;
|
|
@@ -916,7 +1522,7 @@ function appendReceivedFragmentsOntoPage(state, pageKey, receivedFragments) {
|
|
|
916
1522
|
nextState[pageKey] = nextPage;
|
|
917
1523
|
return nextState;
|
|
918
1524
|
}
|
|
919
|
-
function
|
|
1525
|
+
function graftNodeOntoTarget(state, pageKey, node, pathToNode) {
|
|
920
1526
|
if (!node) {
|
|
921
1527
|
console.warn(
|
|
922
1528
|
"There was no node returned in the response. Do you have the correct key path in your props_at?"
|
|
@@ -929,6 +1535,17 @@ function graftNodeOntoPage(state, pageKey, node, pathToNode) {
|
|
|
929
1535
|
const fullPathToNode = [pageKey, pathToNode].join(".");
|
|
930
1536
|
return setIn(state, fullPathToNode, node);
|
|
931
1537
|
}
|
|
1538
|
+
function handleFragmentGraftResponse(state, key, response) {
|
|
1539
|
+
const target = state[key];
|
|
1540
|
+
if (!target) {
|
|
1541
|
+
const error = new Error(
|
|
1542
|
+
`Superglue was looking for ${key} in your fragments, but could not find it.`
|
|
1543
|
+
);
|
|
1544
|
+
throw error;
|
|
1545
|
+
}
|
|
1546
|
+
const { data: receivedNode, path: pathToNode } = response;
|
|
1547
|
+
return graftNodeOntoTarget(state, key, receivedNode, pathToNode);
|
|
1548
|
+
}
|
|
932
1549
|
function handleGraftResponse(state, pageKey, page) {
|
|
933
1550
|
const currentPage = state[pageKey];
|
|
934
1551
|
if (!currentPage) {
|
|
@@ -943,7 +1560,7 @@ function handleGraftResponse(state, pageKey, page) {
|
|
|
943
1560
|
fragments: receivedFragments = []
|
|
944
1561
|
} = page;
|
|
945
1562
|
return [
|
|
946
|
-
(nextState) =>
|
|
1563
|
+
(nextState) => graftNodeOntoTarget(nextState, pageKey, receivedNode, pathToNode),
|
|
947
1564
|
(nextState) => appendReceivedFragmentsOntoPage(nextState, pageKey, receivedFragments)
|
|
948
1565
|
].reduce((memo, fn) => fn(memo), state);
|
|
949
1566
|
}
|
|
@@ -1006,25 +1623,68 @@ function superglueReducer(state = {
|
|
|
1006
1623
|
}
|
|
1007
1624
|
return state;
|
|
1008
1625
|
}
|
|
1626
|
+
function fragmentReducer(state = {}, action) {
|
|
1627
|
+
if (handleFragmentGraft.match(action)) {
|
|
1628
|
+
const { fragmentId, response } = action.payload;
|
|
1629
|
+
return handleFragmentGraftResponse(state, fragmentId, response);
|
|
1630
|
+
}
|
|
1631
|
+
if (saveFragment.match(action)) {
|
|
1632
|
+
const { fragmentId, data } = action.payload;
|
|
1633
|
+
return {
|
|
1634
|
+
...state,
|
|
1635
|
+
[fragmentId]: data
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
if (appendToFragment.match(action)) {
|
|
1639
|
+
const { data, fragmentId } = action.payload;
|
|
1640
|
+
let targetFragment = state[fragmentId];
|
|
1641
|
+
if (Array.isArray(targetFragment)) {
|
|
1642
|
+
targetFragment = [...targetFragment, data];
|
|
1643
|
+
return {
|
|
1644
|
+
...state,
|
|
1645
|
+
[fragmentId]: targetFragment
|
|
1646
|
+
};
|
|
1647
|
+
} else {
|
|
1648
|
+
return state;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
if (prependToFragment.match(action)) {
|
|
1652
|
+
const { data, fragmentId } = action.payload;
|
|
1653
|
+
let targetFragment = state[fragmentId];
|
|
1654
|
+
if (Array.isArray(targetFragment)) {
|
|
1655
|
+
targetFragment = [data, ...targetFragment];
|
|
1656
|
+
return {
|
|
1657
|
+
...state,
|
|
1658
|
+
[fragmentId]: targetFragment
|
|
1659
|
+
};
|
|
1660
|
+
} else {
|
|
1661
|
+
return state;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return state;
|
|
1665
|
+
}
|
|
1009
1666
|
var rootReducer = {
|
|
1010
1667
|
superglue: superglueReducer,
|
|
1011
|
-
pages: pageReducer
|
|
1668
|
+
pages: pageReducer,
|
|
1669
|
+
fragments: fragmentReducer
|
|
1012
1670
|
};
|
|
1013
1671
|
|
|
1014
|
-
// lib/hooks/index.ts
|
|
1015
|
-
var import_react_redux2 = require("react-redux");
|
|
1016
|
-
function useSuperglue() {
|
|
1017
|
-
return (0, import_react_redux2.useSelector)((state) => state.superglue);
|
|
1018
|
-
}
|
|
1019
|
-
function useContent() {
|
|
1020
|
-
const superglueState = useSuperglue();
|
|
1021
|
-
const currentPageKey = superglueState.currentPageKey;
|
|
1022
|
-
return (0, import_react_redux2.useSelector)(
|
|
1023
|
-
(state) => state.pages[currentPageKey]
|
|
1024
|
-
).data;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
1672
|
// lib/index.tsx
|
|
1673
|
+
function getConfig(name) {
|
|
1674
|
+
if (typeof document !== "undefined") {
|
|
1675
|
+
const element = document.head.querySelector(
|
|
1676
|
+
`meta[name='action-cable-${name}']`
|
|
1677
|
+
);
|
|
1678
|
+
if (element) {
|
|
1679
|
+
return element.getAttribute("content") || "/cable";
|
|
1680
|
+
} else {
|
|
1681
|
+
return "/cable";
|
|
1682
|
+
}
|
|
1683
|
+
} else {
|
|
1684
|
+
return "/cable";
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
var cable = (0, import_actioncable.createConsumer)(getConfig("url"));
|
|
1028
1688
|
var hasWindow2 = typeof window !== "undefined";
|
|
1029
1689
|
var createHistory = () => {
|
|
1030
1690
|
if (hasWindow2) {
|
|
@@ -1041,6 +1701,9 @@ var prepareStore = (store, initialPage, path) => {
|
|
|
1041
1701
|
pageKey: initialPageKey
|
|
1042
1702
|
})
|
|
1043
1703
|
);
|
|
1704
|
+
store.dispatch(
|
|
1705
|
+
receiveResponse({ pageKey: initialPageKey, response: initialPage })
|
|
1706
|
+
);
|
|
1044
1707
|
store.dispatch(saveAndProcessPage(initialPageKey, initialPage));
|
|
1045
1708
|
store.dispatch(setCSRFToken({ csrfToken }));
|
|
1046
1709
|
};
|
|
@@ -1065,12 +1728,14 @@ var setup = ({
|
|
|
1065
1728
|
ujsAttributePrefix: "data-sg",
|
|
1066
1729
|
store
|
|
1067
1730
|
});
|
|
1731
|
+
const streamActions = new StreamActions({ remote: remote2, store });
|
|
1068
1732
|
return {
|
|
1069
1733
|
visit,
|
|
1070
1734
|
remote: remote2,
|
|
1071
1735
|
nextHistory,
|
|
1072
1736
|
initialPageKey,
|
|
1073
|
-
ujs: handlers
|
|
1737
|
+
ujs: handlers,
|
|
1738
|
+
streamActions
|
|
1074
1739
|
};
|
|
1075
1740
|
};
|
|
1076
1741
|
function Application({
|
|
@@ -1083,8 +1748,8 @@ function Application({
|
|
|
1083
1748
|
mapping,
|
|
1084
1749
|
...rest
|
|
1085
1750
|
}) {
|
|
1086
|
-
const navigatorRef = (0,
|
|
1087
|
-
const { visit, remote: remote2, nextHistory, initialPageKey, ujs } = (0,
|
|
1751
|
+
const navigatorRef = (0, import_react4.useRef)(null);
|
|
1752
|
+
const { visit, remote: remote2, nextHistory, initialPageKey, ujs, streamActions } = (0, import_react4.useMemo)(() => {
|
|
1088
1753
|
return setup({
|
|
1089
1754
|
initialPage,
|
|
1090
1755
|
baseUrl,
|
|
@@ -1095,7 +1760,7 @@ function Application({
|
|
|
1095
1760
|
navigatorRef
|
|
1096
1761
|
});
|
|
1097
1762
|
}, []);
|
|
1098
|
-
return /* @__PURE__ */
|
|
1763
|
+
return /* @__PURE__ */ import_react4.default.createElement("div", { onClick: ujs.onClick, onSubmit: ujs.onSubmit, ...rest }, /* @__PURE__ */ import_react4.default.createElement(import_react_redux5.Provider, { store }, /* @__PURE__ */ import_react4.default.createElement(CableContext.Provider, { value: { streamActions, cable } }, /* @__PURE__ */ import_react4.default.createElement(
|
|
1099
1764
|
NavigationProvider,
|
|
1100
1765
|
{
|
|
1101
1766
|
ref: navigatorRef,
|
|
@@ -1105,7 +1770,7 @@ function Application({
|
|
|
1105
1770
|
history: nextHistory,
|
|
1106
1771
|
initialPageKey
|
|
1107
1772
|
}
|
|
1108
|
-
)));
|
|
1773
|
+
))));
|
|
1109
1774
|
}
|
|
1110
1775
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1111
1776
|
0 && (module.exports = {
|
|
@@ -1121,15 +1786,18 @@ function Application({
|
|
|
1121
1786
|
getIn,
|
|
1122
1787
|
pageReducer,
|
|
1123
1788
|
prepareStore,
|
|
1789
|
+
receiveResponse,
|
|
1124
1790
|
removePage,
|
|
1125
1791
|
rootReducer,
|
|
1126
1792
|
saveAndProcessPage,
|
|
1127
1793
|
saveResponse,
|
|
1128
1794
|
setup,
|
|
1129
1795
|
superglueReducer,
|
|
1130
|
-
|
|
1796
|
+
unproxy,
|
|
1131
1797
|
urlToPageKey,
|
|
1132
1798
|
useContent,
|
|
1799
|
+
useSetFragment,
|
|
1800
|
+
useStreamSource,
|
|
1133
1801
|
useSuperglue
|
|
1134
1802
|
});
|
|
1135
1803
|
//# sourceMappingURL=superglue.cjs.map
|