UNPKG

7.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var react_1 = tslib_1.__importStar(require("react"));
5var async_1 = require("@shopify/async");
6var react_intersection_observer_1 = require("@shopify/react-intersection-observer");
7var react_idle_1 = require("@shopify/react-idle");
8var react_hydrate_1 = require("@shopify/react-hydrate");
9var hooks_1 = require("./hooks");
10var types_1 = require("./types");
11function 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}
141exports.createAsyncComponent = createAsyncComponent;
142function noopUse() {
143 return function () { };
144}
145function noopRender() {
146 return null;
147}
148var DEFAULT_DISPLAY_NAME = 'Component';
149var FILENAME_REGEX = /([^/]*)\.\w+$/;
150function 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}
157function defaultRenderError(error) {
158 if (error) {
159 throw error;
160 }
161 return null;
162}
163function 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}