"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useLinkProps = exports.shouldHandleLinkEvent = void 0; var _react = require("react"); var _queryString = require("query-string"); var _public = require("@kbn/kibana-utils-plugin/public"); var _public2 = require("@kbn/kibana-react-plugin/public"); var _use_prefix_path_with_basepath = require("./use_prefix_path_with_basepath"); var _navigation_warning_prompt = require("../components/navigation_warning_prompt"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const useLinkProps = ({ app, pathname, hash, search }, options = {}) => { var _useKibana$services$a; validateParams({ app, pathname, hash, search }); const { prompt } = (0, _navigation_warning_prompt.useNavigationWarningPrompt)(); const prefixer = (0, _use_prefix_path_with_basepath.usePrefixPathWithBasepath)(); const navigateToApp = (_useKibana$services$a = (0, _public2.useKibana)().services.application) === null || _useKibana$services$a === void 0 ? void 0 : _useKibana$services$a.navigateToApp; const { hrefOnly } = options; const encodedSearch = (0, _react.useMemo)(() => { return search ? encodeSearch(search) : undefined; }, [search]); const mergedHash = (0, _react.useMemo)(() => { // The URI spec defines that the query should appear before the fragment // https://tools.ietf.org/html/rfc3986#section-3 (e.g. url.format()). However, in Kibana, apps that use // hash based routing expect the query to be part of the hash. This will handle that. return hash && encodedSearch ? `${hash}?${encodedSearch}` : hash; }, [hash, encodedSearch]); const mergedPathname = (0, _react.useMemo)(() => { return pathname && encodedSearch ? `${pathname}?${encodedSearch}` : pathname; }, [pathname, encodedSearch]); const href = (0, _react.useMemo)(() => { const builtPathname = pathname !== null && pathname !== void 0 ? pathname : ''; const builtHash = mergedHash ? `#${mergedHash}` : ''; const builtSearch = !hash ? encodedSearch ? `?${encodedSearch}` : '' : ''; const link = `${builtPathname}${builtSearch}${builtHash}`; return prefixer(app, link); }, [mergedHash, hash, encodedSearch, pathname, prefixer, app]); const onClick = (0, _react.useMemo)(() => { return e => { if (!shouldHandleLinkEvent(e)) { return; } e.preventDefault(); const navigate = () => { if (navigateToApp) { const navigationPath = mergedHash ? `#${mergedHash}` : mergedPathname; navigateToApp(app, { path: navigationPath ? navigationPath : undefined }); } }; // A component somewhere within the app hierarchy is requesting that we // prompt the user before navigating. if (prompt) { const wantsToNavigate = window.confirm(prompt); if (wantsToNavigate) { navigate(); } else { return; } } else { navigate(); } }; }, [navigateToApp, mergedHash, mergedPathname, app, prompt]); return { href, // Sometimes it may not be desirable to have onClick call "navigateToApp". // E.g. the management section of Kibana cannot be successfully deeplinked to via // "navigateToApp". In those cases we can choose to defer to legacy behaviour. onClick: hrefOnly ? undefined : onClick }; }; exports.useLinkProps = useLinkProps; const encodeSearch = search => { return (0, _queryString.stringify)(_public.url.encodeQuery(search), { sort: false, encode: false }); }; const validateParams = ({ app, pathname, hash, search }) => { if (!app && hash) { throw new Error('The metrics and logs apps use browserHistory. Please provide a pathname rather than a hash.'); } }; const isModifiedEvent = event => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); const shouldHandleLinkEvent = e => !e.defaultPrevented && !isModifiedEvent(e); exports.shouldHandleLinkEvent = shouldHandleLinkEvent;