1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var tslib_1 = require("tslib");
|
4 | var react_1 = tslib_1.__importStar(require("react"));
|
5 | var async_1 = require("@shopify/async");
|
6 | var react_intersection_observer_1 = require("@shopify/react-intersection-observer");
|
7 | var react_idle_1 = require("@shopify/react-idle");
|
8 | var react_hydrate_1 = require("@shopify/react-hydrate");
|
9 | var hooks_1 = require("./hooks");
|
10 | var types_1 = require("./types");
|
11 | function createAsyncComponent(_a) {
|
12 | var id = _a.id, load = _a.load, defer = _a.defer, deferHydration = _a.deferHydration, displayName = _a.displayName, _b = _a.renderLoading, renderLoading = _b === void 0 ? noopRender : _b, _c = _a.renderError, renderError = _c === void 0 ? defaultRenderError : _c, _d = _a.usePreload, useCustomPreload = _d === void 0 ? noopUse : _d, _e = _a.usePrefetch, useCustomPrefetch = _e === void 0 ? noopUse : _e, _f = _a.useKeepFresh, useCustomKeepFresh = _f === void 0 ? noopUse : _f;
|
13 | var resolver = async_1.createResolver({ id: id, load: load });
|
14 | var componentName = displayName || displayNameFromId(resolver.id);
|
15 | var deferred = defer != null;
|
16 | var progressivelyHydrated = deferHydration != null;
|
17 | var scriptTiming = deferred || progressivelyHydrated
|
18 | ? types_1.AssetTiming.CurrentPage
|
19 | : types_1.AssetTiming.Immediate;
|
20 | var stylesTiming = deferred
|
21 | ? types_1.AssetTiming.CurrentPage
|
22 | : types_1.AssetTiming.Immediate;
|
23 | function Async(props) {
|
24 | var _a = hooks_1.useAsync(resolver, {
|
25 | scripts: scriptTiming,
|
26 | styles: stylesTiming,
|
27 | immediate: !deferred,
|
28 | }), Component = _a.resolved, load = _a.load, loading = _a.loading, error = _a.error;
|
29 | var startedHydrated = react_1.useRef(react_hydrate_1.useHydrationManager().hydrated).current;
|
30 | if (error) {
|
31 | return renderError(error);
|
32 | }
|
33 | var loadingMarkup = null;
|
34 | if (progressivelyHydrated && !startedHydrated) {
|
35 | loadingMarkup = (react_1.default.createElement(Loader, { defer: deferHydration, load: load, props: props }));
|
36 | }
|
37 | else if (loading) {
|
38 | loadingMarkup = react_1.default.createElement(Loader, { defer: defer, load: load, props: props });
|
39 | }
|
40 | var contentMarkup = null;
|
41 | var rendered = Component ? react_1.default.createElement(Component, tslib_1.__assign({}, props)) : null;
|
42 | if (progressivelyHydrated && !startedHydrated) {
|
43 | contentMarkup = rendered ? (react_1.default.createElement(react_hydrate_1.Hydrator, { id: resolver.id }, rendered)) : (react_1.default.createElement(react_hydrate_1.Hydrator, { id: resolver.id }));
|
44 | }
|
45 | else if (loading) {
|
46 | contentMarkup = renderLoading(props);
|
47 | }
|
48 | else {
|
49 | contentMarkup = rendered;
|
50 | }
|
51 | return (react_1.default.createElement(react_1.default.Fragment, null,
|
52 | contentMarkup,
|
53 | loadingMarkup));
|
54 | }
|
55 | Async.displayName = "Async(" + componentName + ")";
|
56 | function usePreload(props) {
|
57 | var load = hooks_1.useAsync(resolver, {
|
58 | assets: types_1.AssetTiming.NextPage,
|
59 | }).load;
|
60 | var customPreload = useCustomPreload(props);
|
61 | return react_1.useCallback(function () {
|
62 | load();
|
63 | if (customPreload) {
|
64 | customPreload();
|
65 | }
|
66 | }, [load, customPreload]);
|
67 | }
|
68 | function usePrefetch(props) {
|
69 | var load = hooks_1.useAsync(resolver, {
|
70 | assets: types_1.AssetTiming.NextPage,
|
71 | }).load;
|
72 | var customPrefetch = useCustomPrefetch(props);
|
73 | return react_1.useCallback(function () {
|
74 | load();
|
75 | if (customPrefetch) {
|
76 | customPrefetch();
|
77 | }
|
78 | }, [load, customPrefetch]);
|
79 | }
|
80 | function useKeepFresh(props) {
|
81 | var load = hooks_1.useAsync(resolver, {
|
82 | assets: types_1.AssetTiming.NextPage,
|
83 | }).load;
|
84 | var customKeepFresh = useCustomKeepFresh(props);
|
85 | return react_1.useCallback(function () {
|
86 | load();
|
87 | if (customKeepFresh) {
|
88 | customKeepFresh();
|
89 | }
|
90 | }, [load, customKeepFresh]);
|
91 | }
|
92 | function Preload(options) {
|
93 | react_idle_1.useIdleCallback(usePreload(options));
|
94 | return null;
|
95 | }
|
96 | Preload.displayName = "Async.Preload(" + displayName + ")";
|
97 | function Prefetch(options) {
|
98 | var prefetch = usePrefetch(options);
|
99 | react_1.useEffect(function () {
|
100 | prefetch();
|
101 | }, [prefetch]);
|
102 | return null;
|
103 | }
|
104 | Prefetch.displayName = "Async.Prefetch(" + displayName + ")";
|
105 | function KeepFresh(options) {
|
106 | react_idle_1.useIdleCallback(useKeepFresh(options));
|
107 | return null;
|
108 | }
|
109 | KeepFresh.displayName = "Async.KeepFresh(" + displayName + ")";
|
110 | var FinalComponent = Async;
|
111 | Reflect.defineProperty(FinalComponent, 'resolver', {
|
112 | value: resolver,
|
113 | writable: false,
|
114 | });
|
115 | Reflect.defineProperty(FinalComponent, 'Preload', {
|
116 | value: Preload,
|
117 | writable: false,
|
118 | });
|
119 | Reflect.defineProperty(FinalComponent, 'Prefetch', {
|
120 | value: Prefetch,
|
121 | writable: false,
|
122 | });
|
123 | Reflect.defineProperty(FinalComponent, 'KeepFresh', {
|
124 | value: KeepFresh,
|
125 | writable: false,
|
126 | });
|
127 | Reflect.defineProperty(FinalComponent, 'usePreload', {
|
128 | value: usePreload,
|
129 | writable: false,
|
130 | });
|
131 | Reflect.defineProperty(FinalComponent, 'usePrefetch', {
|
132 | value: usePrefetch,
|
133 | writable: false,
|
134 | });
|
135 | Reflect.defineProperty(FinalComponent, 'useKeepFresh', {
|
136 | value: useKeepFresh,
|
137 | writable: false,
|
138 | });
|
139 | return FinalComponent;
|
140 | }
|
141 | exports.createAsyncComponent = createAsyncComponent;
|
142 | function noopUse() {
|
143 | return function () { };
|
144 | }
|
145 | function noopRender() {
|
146 | return null;
|
147 | }
|
148 | var DEFAULT_DISPLAY_NAME = 'Component';
|
149 | var FILENAME_REGEX = /([^/]*)\.\w+$/;
|
150 | function displayNameFromId(id) {
|
151 | if (!id) {
|
152 | return DEFAULT_DISPLAY_NAME;
|
153 | }
|
154 | var match = FILENAME_REGEX.exec(id);
|
155 | return match ? match[1] : DEFAULT_DISPLAY_NAME;
|
156 | }
|
157 | function defaultRenderError(error) {
|
158 | if (error) {
|
159 | throw error;
|
160 | }
|
161 | return null;
|
162 | }
|
163 | function Loader(_a) {
|
164 | var defer = _a.defer, load = _a.load, props = _a.props;
|
165 | var handleIntersection = react_1.useCallback(function (_a) {
|
166 | var _b = _a.isIntersecting, isIntersecting = _b === void 0 ? true : _b;
|
167 | if (isIntersecting) {
|
168 | load();
|
169 | }
|
170 | }, [load]);
|
171 | react_1.useEffect(function () {
|
172 | if (defer == null || defer === async_1.DeferTiming.Mount) {
|
173 | load();
|
174 | }
|
175 | else if (typeof defer === 'function' && defer(props)) {
|
176 | load();
|
177 | }
|
178 | }, [defer, load, props]);
|
179 | if (typeof defer === 'function') {
|
180 | return null;
|
181 | }
|
182 | switch (defer) {
|
183 | case async_1.DeferTiming.Idle:
|
184 | return react_1.default.createElement(react_idle_1.OnIdle, { perform: load });
|
185 | case async_1.DeferTiming.InViewport:
|
186 | return (react_1.default.createElement(react_intersection_observer_1.IntersectionObserver, { threshold: 0, onIntersectionChange: handleIntersection }));
|
187 | default:
|
188 | return null;
|
189 | }
|
190 | }
|