UNPKG

9.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 var key = {
10 router: null,
11 response: null,
12 navigation: null
13 };
14 var context = React.createContext(key);
15 var Provider = context.Provider, Curious = context.Consumer;
16
17 function curiProvider(router) {
18 function initialState() {
19 var _a = router.current(), response = _a.response, navigation = _a.navigation;
20 return {
21 router: router,
22 response: response,
23 navigation: navigation
24 };
25 }
26 return function Router(props) {
27 var _a = React.useState(initialState), state = _a[0], setState = _a[1];
28 React.useEffect(function () {
29 var removed = false;
30 var stopResponding = router.observe(function (emitted) {
31 if (!removed) {
32 setState(emitted);
33 }
34 }, { initial: false });
35 return function () {
36 removed = true;
37 stopResponding();
38 };
39 }, []);
40 return React.createElement(Provider, { value: state }, props.children);
41 };
42 }
43
44 function useCuri() {
45 return React.useContext(context);
46 }
47
48 function useActive(props) {
49 var _a = useCuri(), router = _a.router, response = _a.response;
50 if (process.env.NODE_ENV !== "production") {
51 if (!router.route.active) {
52 throw new Error("You are attempting to use the \"active\" route interaction, but have not included it in your Curi router.\n\nimport curi from \"@curi/router\";\nimport active from \"@curi/route-active\";\n\nconst router = curi(history, routes, {\n route: [active()]\n});");
53 }
54 }
55 var isActive = router.route.active(props.name, response, {
56 params: props.params,
57 partial: props.partial,
58 locationCheck: props.locationCheck
59 });
60 return isActive;
61 }
62
63 function useBlock(active, fn) {
64 var router = useCuri().router;
65 React.useEffect(function () {
66 if (active) {
67 router.history.confirmWith(fn);
68 return function () {
69 router.history.removeConfirmation();
70 };
71 }
72 }, [active, fn]);
73 }
74
75 function useLocation(props) {
76 var router = useCuri().router;
77 var pathname = React.useMemo(function () {
78 return props.name ? router.route.pathname(props.name, props.params) : "";
79 }, [
80 props.name
81 ].concat(Object.keys(props.params || {}).map(function (key) { return props.params[key]; })));
82 return {
83 pathname: pathname,
84 hash: props.hash,
85 query: props.query,
86 state: props.state
87 };
88 }
89
90 function useHref(props) {
91 var location = useLocation(props);
92 var router = useCuri().router;
93 return router.history.toHref(location);
94 }
95
96 function useNavigating() {
97 var router = useCuri().router;
98 var _a = React.useState(undefined), cancel = _a[0], setCancel = _a[1];
99 var _b = React.useState(false), removed = _b[0], setRemoved = _b[1];
100 React.useEffect(function () {
101 return function () {
102 setRemoved(true);
103 };
104 }, []);
105 React.useEffect(function () {
106 return router.cancel(function (cancelFn) {
107 if (!removed) {
108 setCancel(function () { return cancelFn; });
109 }
110 });
111 }, []);
112 return cancel;
113 }
114
115 function defaultCanNavigate() {
116 return true;
117 }
118 function useNavigationHandler(props, setNavigating, canNavigate) {
119 if (canNavigate === void 0) { canNavigate = defaultCanNavigate; }
120 var router = useCuri().router;
121 var cancel = React.useRef(undefined);
122 function handler(event) {
123 if (props.onNav) {
124 props.onNav(event);
125 }
126 if (canNavigate(event, props.forward)) {
127 event.preventDefault();
128 var cancelled = void 0, finished = void 0;
129 // only trigger re-renders when children uses state
130 if (typeof props.children === "function") {
131 cancelled = finished = function () {
132 cancel.current = undefined;
133 setNavigating(false);
134 };
135 setNavigating(true);
136 }
137 cancel.current = router.navigate({
138 method: props.method || "ANCHOR",
139 name: props.name,
140 params: props.params,
141 query: props.query,
142 state: props.state,
143 hash: props.hash,
144 cancelled: cancelled,
145 finished: finished
146 });
147 }
148 }
149 return { handler: handler, cancel: cancel };
150 }
151
152 function useNavigationFocus(ref, props) {
153 if (props === void 0) { props = {}; }
154 var response = useCuri().response;
155 React.useEffect(function () {
156 var ele = ref.current;
157 if (ele === null) {
158 if (process.env.NODE_ENV !== "production") {
159 console.warn("There is no element to focus. Did you forget to add the ref to an element?");
160 }
161 return;
162 }
163 if (props.preserve && ele.contains(document.activeElement)) {
164 return;
165 }
166 if (process.env.NODE_ENV !== "production") {
167 if (!ele.hasAttribute("tabIndex") && ele.tabIndex === -1) {
168 console.warn('The component that is passed the ref must have a "tabIndex" prop or be focusable by default in order to be focused. ' +
169 "Otherwise, the document's <body> will be focused instead.");
170 }
171 }
172 var _a = props.preventScroll, preventScroll = _a === void 0 ? false : _a;
173 var timeout = setTimeout(function () {
174 // @ts-ignore
175 ele.focus({ preventScroll: preventScroll });
176 });
177 return function () {
178 clearTimeout(timeout);
179 };
180 }, [response]);
181 }
182
183 /*! *****************************************************************************
184 Copyright (c) Microsoft Corporation. All rights reserved.
185 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
186 this file except in compliance with the License. You may obtain a copy of the
187 License at http://www.apache.org/licenses/LICENSE-2.0
188
189 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
190 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
191 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
192 MERCHANTABLITY OR NON-INFRINGEMENT.
193
194 See the Apache Version 2.0 License for specific language governing permissions
195 and limitations under the License.
196 ***************************************************************************** */
197
198 var __assign = function() {
199 __assign = Object.assign || function __assign(t) {
200 for (var s, i = 1, n = arguments.length; i < n; i++) {
201 s = arguments[i];
202 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
203 }
204 return t;
205 };
206 return __assign.apply(this, arguments);
207 };
208
209 function canNavigate(event, forward) {
210 return (!event.defaultPrevented &&
211 event.button === 0 &&
212 !(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) &&
213 (!forward || !forward.target));
214 }
215
216 var HookLink = React.forwardRef(function (props, ref) {
217 var _a = React.useState(false), navigating = _a[0], setNavigating = _a[1];
218 var href = useHref(props);
219 var _b = useNavigationHandler(props, setNavigating, canNavigate), handler = _b.handler, cancel = _b.cancel;
220 React.useEffect(function () {
221 return function () {
222 if (cancel.current) {
223 cancel.current();
224 }
225 };
226 }, []);
227 var _c = props.anchor, Anchor = _c === void 0 ? "a" : _c, children = props.children, forward = props.forward;
228 return (
229 // @ts-ignore
230 React.createElement(Anchor, __assign({ onClick: handler, href: href, ref: ref }, forward), typeof children === "function"
231 ? children(navigating)
232 : children));
233 });
234
235 exports.Link = HookLink;
236 exports.useNavigationFocus = useNavigationFocus;
237 exports.curiProvider = curiProvider;
238 exports.Curious = Curious;
239 exports.useCuri = useCuri;
240 exports.useActive = useActive;
241 exports.useBlock = useBlock;
242 exports.useLocation = useLocation;
243 exports.useHref = useHref;
244 exports.useNavigating = useNavigating;
245 exports.useNavigationHandler = useNavigationHandler;
246
247 Object.defineProperty(exports, '__esModule', { value: true });
248
249}));