UNPKG

12.9 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
3 typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
4 (global = global || self, factory(global.CuriReactDOM = {}, global.React));
5}(this, function (exports, React) { 'use strict';
6
7 React = React && React.hasOwnProperty('default') ? React['default'] : React;
8
9 function find(name, children) {
10 return children.some(function (node) {
11 if (node.name === name) {
12 return true;
13 }
14 else if (node.children) {
15 return find(name, node.children);
16 }
17 return false;
18 });
19 }
20 function active(route, response, options) {
21 if (options === void 0) { options = {}; }
22 if (response.name !== route.name &&
23 (!options.partial || !find(response.name, route.children))) {
24 return false;
25 }
26 var keys = route.keys;
27 if (keys.length) {
28 if (!options.params) {
29 return false;
30 }
31 for (var r = 0, length = keys.length; r < length; r++) {
32 var key = keys[r];
33 var param = options.params[key];
34 if (!param || param !== response.params[key]) {
35 return false;
36 }
37 }
38 }
39 if (options.components) {
40 return options.components(response.location);
41 }
42 return true;
43 }
44
45 var key = {
46 response: null,
47 navigation: null
48 };
49 var responseContext = React.createContext(key);
50 var ResponseProvider = responseContext.Provider, ResponseConsumer = responseContext.Consumer;
51 var routerContext = React.createContext(null);
52 var RouterProvider = routerContext.Provider, RouterConsumer = routerContext.Consumer;
53
54 function createRouterComponent(router) {
55 function initialState() {
56 return router.current();
57 }
58 return function Router(props) {
59 var _a = React.useState(initialState), response = _a[0], setResponse = _a[1];
60 React.useEffect(function () {
61 var removed = false;
62 var stop = router.observe(function (_a) {
63 var response = _a.response, navigation = _a.navigation;
64 if (!removed) {
65 setResponse({ response: response, navigation: navigation });
66 }
67 }, { initial: false });
68 return function () {
69 removed = true;
70 stop();
71 };
72 }, []);
73 return (React.createElement(RouterProvider, { value: router },
74 React.createElement(ResponseProvider, { value: response }, props.children)));
75 };
76 }
77
78 function useRouter() {
79 return React.useContext(routerContext);
80 }
81
82 function useResponse() {
83 return React.useContext(responseContext);
84 }
85
86 function useActive(props) {
87 var router = useRouter();
88 var response = useResponse().response;
89 var route = router.route(props.name);
90 if (!route) {
91 return false;
92 }
93 return active(route, response, {
94 params: props.params,
95 partial: props.partial,
96 components: props.components
97 });
98 }
99
100 function useURL(props) {
101 var router = useRouter();
102 return router.url(props);
103 }
104
105 function useNavigating() {
106 var router = useRouter();
107 var _a = React.useState(undefined), cancel = _a[0], setCancel = _a[1];
108 React.useEffect(function () {
109 var removed = false;
110 var stop = router.cancel(function (callback) {
111 if (!removed) {
112 setCancel(function () { return callback; });
113 }
114 });
115 return function () {
116 removed = true;
117 stop();
118 };
119 }, []);
120 return cancel;
121 }
122
123 function defaultCanNavigate() {
124 return true;
125 }
126 function useNavigationHandler(props) {
127 var url = props.url, onNav = props.onNav, method = props.method, target = props.target, state = props.state, _a = props.canNavigate, canNavigate = _a === void 0 ? defaultCanNavigate : _a;
128 var router = useRouter();
129 var eventHandler = React.useCallback(function eventHandler(event) {
130 if (onNav) {
131 onNav(event);
132 }
133 if (canNavigate(event, target)) {
134 event.preventDefault();
135 router.navigate({ url: url, state: state, method: method });
136 }
137 }, [url, method, state, onNav, target]);
138 return {
139 url: url,
140 eventHandler: eventHandler
141 };
142 }
143 function useStatefulNavigationHandler(props) {
144 var url = props.url, onNav = props.onNav, method = props.method, target = props.target, state = props.state, _a = props.canNavigate, canNavigate = _a === void 0 ? defaultCanNavigate : _a;
145 var router = useRouter();
146 var removeCallbacks = React.useRef(undefined);
147 var _b = React.useState(false), navigating = _b[0], setNavigating = _b[1];
148 React.useEffect(function () {
149 return function () {
150 if (removeCallbacks.current) {
151 removeCallbacks.current();
152 }
153 };
154 }, []);
155 var eventHandler = React.useCallback(function eventHandler(event) {
156 if (onNav) {
157 onNav(event);
158 }
159 if (canNavigate(event, target)) {
160 event.preventDefault();
161 var done = function () {
162 removeCallbacks.current = undefined;
163 setNavigating(false);
164 };
165 setNavigating(true);
166 removeCallbacks.current = router.navigate({
167 url: url,
168 state: state,
169 method: method,
170 cancelled: done,
171 finished: done
172 });
173 }
174 }, [url, method, state, onNav, target]);
175 return {
176 url: url,
177 eventHandler: eventHandler,
178 navigating: navigating
179 };
180 }
181
182 function useConfirm(fn) {
183 var router = useRouter();
184 React.useEffect(function () {
185 router.history.confirm(fn);
186 return function () {
187 router.history.confirm();
188 };
189 }, [fn]);
190 }
191
192 function useNavigationFocus(ref, props) {
193 if (props === void 0) { props = {}; }
194 // The response isn't actually used, but the app should only
195 // re-focus when the response changes. The preserve and preventScroll
196 // values are used, but not used in the comparison array because
197 // changing these values would steal the app's focus even though
198 // the location hasn't changed.
199 var response = useResponse().response;
200 var preserve = props.preserve, _a = props.preventScroll, preventScroll = _a === void 0 ? false : _a;
201 React.useEffect(function () {
202 var ele = ref.current;
203 if (ele === null) {
204 {
205 console.warn("There is no element to focus. Did you forget to add the ref to an element?");
206 }
207 return;
208 }
209 if (preserve && ele.contains(document.activeElement)) {
210 return;
211 }
212 {
213 if (!ele.hasAttribute("tabIndex") && ele.tabIndex === -1) {
214 console.warn('The component that is passed the ref must have a "tabIndex" prop or be focusable by default in order to be focused. ' +
215 "Otherwise, the document's <body> will be focused instead.");
216 }
217 }
218 // @ts-ignore
219 ele.focus({ preventScroll: preventScroll });
220 }, [response]);
221 }
222
223 /*! *****************************************************************************
224 Copyright (c) Microsoft Corporation. All rights reserved.
225 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
226 this file except in compliance with the License. You may obtain a copy of the
227 License at http://www.apache.org/licenses/LICENSE-2.0
228
229 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
230 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
231 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
232 MERCHANTABLITY OR NON-INFRINGEMENT.
233
234 See the Apache Version 2.0 License for specific language governing permissions
235 and limitations under the License.
236 ***************************************************************************** */
237
238 var __assign = function() {
239 __assign = Object.assign || function __assign(t) {
240 for (var s, i = 1, n = arguments.length; i < n; i++) {
241 s = arguments[i];
242 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
243 }
244 return t;
245 };
246 return __assign.apply(this, arguments);
247 };
248
249 function __rest(s, e) {
250 var t = {};
251 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
252 t[p] = s[p];
253 if (s != null && typeof Object.getOwnPropertySymbols === "function")
254 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
255 t[p[i]] = s[p[i]];
256 return t;
257 }
258
259 function canNavigate(event, target) {
260 return (!event.defaultPrevented &&
261 !target &&
262 event.button === 0 &&
263 !(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey));
264 }
265
266 var Link = React.forwardRef(function (props, ref) {
267 var _a;
268 var
269 // url
270 name = props.name, params = props.params, query = props.query, hash = props.hash,
271 // navigation
272 state = props.state, onNav = props.onNav, method = props.method,
273 // props
274 children = props.children, Anchor = (_a = props.anchor, _a === void 0 ? "a" : _a), rest = __rest(props, ["name", "params", "query", "hash", "state", "onNav", "method", "children", "anchor"]);
275 var url = useURL({ name: name, params: params, query: query, hash: hash });
276 var eventHandler = useNavigationHandler({
277 url: url,
278 state: state,
279 onNav: onNav,
280 method: method,
281 canNavigate: canNavigate,
282 target: rest.target
283 }).eventHandler;
284 return (React.createElement(Anchor, __assign({}, rest, { onClick: eventHandler, href: url, ref: ref }), children));
285 });
286 var AsyncLink = React.forwardRef(function (props, ref) {
287 var _a, _b;
288 var
289 // url
290 name = props.name, params = props.params, query = props.query, hash = props.hash,
291 // navigation
292 state = props.state, onNav = props.onNav, method = props.method,
293 // props
294 children = props.children, Anchor = (_a = props.anchor, _a === void 0 ? "a" : _a), rest = __rest(props, ["name", "params", "query", "hash", "state", "onNav", "method", "children", "anchor"]);
295 var url = useURL({ name: name, params: params, query: query, hash: hash });
296 var eventHandler = (_b = useStatefulNavigationHandler({ url: url, state: state, onNav: onNav, method: method, canNavigate: canNavigate, target: rest.target }), _b.eventHandler), navigating = _b.navigating;
297 return (React.createElement(Anchor, __assign({}, rest, { onClick: eventHandler, href: url, ref: ref }), children(navigating)));
298 });
299
300 exports.AsyncLink = AsyncLink;
301 exports.Link = Link;
302 exports.ResponseConsumer = ResponseConsumer;
303 exports.RouterConsumer = RouterConsumer;
304 exports.createRouterComponent = createRouterComponent;
305 exports.useActive = useActive;
306 exports.useConfirm = useConfirm;
307 exports.useNavigating = useNavigating;
308 exports.useNavigationFocus = useNavigationFocus;
309 exports.useNavigationHandler = useNavigationHandler;
310 exports.useResponse = useResponse;
311 exports.useRouter = useRouter;
312 exports.useStatefulNavigationHandler = useStatefulNavigationHandler;
313 exports.useURL = useURL;
314
315 Object.defineProperty(exports, '__esModule', { value: true });
316
317}));