diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a708f..16d066b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.10.1] - 2023-01-10 +### Changed +- Added nextLocation and action to childData +- Added callbacks which will be called on become active: onShow() and onShowNative() +- Added method to navigate to another route during the prompt is active ## [1.9.6] - 2022-02-13 ### Fixed diff --git a/README.md b/README.md index 4ad73ea..5811cee 100644 --- a/README.md +++ b/README.md @@ -100,13 +100,17 @@ import Modal from "./your-own-code"; - `props` - afterCancel?: Function, - afterConfirm?: Function, - - allowGoBack: bool (use _goBack_ method instead of _push_ when navigating back -- !! NOTE WELL !! it will _always_ navigate back only 1 item, even when it should navigate back more items. read more: https://github.com/ZacharyRSmith/react-router-navigation-prompt/pull/30), + - afterSkip?: Function, + - allowGoBack?: bool (use _goBack_ method instead of _push_ when navigating back -- !! NOTE WELL !! it will _always_ navigate back only 1 item, even when it should navigate back more items. read more: https://github.com/ZacharyRSmith/react-router-navigation-prompt/pull/30), - beforeCancel?: Function, - beforeConfirm?: Function, - - children: (data: {isActive: bool, onCancel: Function, onConfirm: Function}) => React$Element<\*>, - - renderIfNotActive: bool, + - beforeSkip?: Function, + - onShow?: (data: {action: ?HistoryAction, nextLocation: ?Location, onCancel: Function, onConfirm: Function, onSkip: (nextLocation: Location | string, action?: HistoryAction) => void}) => void, + - onShowNative?: Function, + - children: (data: {isActive: bool, action: ?HistoryAction, nextLocation: ?Location, onCancel: Function, onConfirm: Function, onSkip: (nextLocation: Location | string, action?: HistoryAction) => void}) => React$Element<\*>, + - renderIfNotActive?: bool, - when: bool | (Location, ?Location, ?HistoryAction) => bool, - - disableNative: bool, + - disableNative?: bool, // Added by react-router: - match: Match, - history: RouterHistory, diff --git a/es/index.js b/es/index.js index ab4e64a..91d3950 100644 --- a/es/index.js +++ b/es/index.js @@ -1,315 +1 @@ -module.exports = -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _react = __webpack_require__(1); - -var _react2 = _interopRequireDefault(_react); - -var _reactRouterDom = __webpack_require__(2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var initState = { - action: null, - isActive: false, - nextLocation: null -}; - -/** - * A replacement component for the react-router `Prompt`. - * Allows for more flexible dialogs. - * - * @example - * - * {({isActive, onConfirm, onCancel}) => ( - * - * - * Do you really want to leave? - * Cancel - * Ok - * - * - * )} - * - */ - -var NavigationPrompt = function (_React$Component) { - _inherits(NavigationPrompt, _React$Component); - - /*:: _prevUserAction: string; */ - /*:: _isMounted: bool; */ - - function NavigationPrompt(props) { - _classCallCheck(this, NavigationPrompt); - - // `_prevUserAction` weirdness because setState()'s callback is not getting invoked. - // See: See https://github.com/ZacharyRSmith/react-router-navigation-prompt/pull/9 - // I don't like making this an instance var, - var _this = _possibleConstructorReturn(this, (NavigationPrompt.__proto__ || Object.getPrototypeOf(NavigationPrompt)).call(this, props)); - - _this._prevUserAction = ''; - - // This component could be used from inside a page, and therefore could be - // mounted/unmounted when the route changes. - _this._isMounted = true; - - _this.block = _this.block.bind(_this); - _this.onBeforeUnload = _this.onBeforeUnload.bind(_this); - _this.onCancel = _this.onCancel.bind(_this); - _this.onConfirm = _this.onConfirm.bind(_this); - _this.when = _this.when.bind(_this); - - _this.state = _extends({}, initState, { unblock: function unblock() {} /* unblock will be set in componentDidMount */ }); - return _this; - } - - _createClass(NavigationPrompt, [{ - key: 'componentDidMount', - value: function componentDidMount() { - if (!this.props.disableNative) { - window.addEventListener('beforeunload', this.onBeforeUnload); - } - - this.setState({ unblock: this.props.history.block(this.block) }); - } - }, { - key: 'componentDidUpdate', - value: function componentDidUpdate(prevProps, prevState) { - if (this._prevUserAction === 'CANCEL' && typeof this.props.afterCancel === 'function') { - this.props.afterCancel(); - } else if (this._prevUserAction === 'CONFIRM' && typeof this.props.afterConfirm === 'function') { - this.props.afterConfirm(); - } - this._prevUserAction = ''; - } - }, { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - this._isMounted = false; - if (this._prevUserAction === 'CONFIRM' && typeof this.props.afterConfirm === 'function') { - this._prevUserAction = ''; - this.props.afterConfirm(); - } - this.state.unblock(); - if (!this.props.disableNative) { - window.removeEventListener('beforeunload', this.onBeforeUnload); - } - } - }, { - key: 'block', - value: function block(nextLocation, action) { - var result = this.when(nextLocation, action); - if (result) { - this.setState({ - action: action, - nextLocation: nextLocation, - isActive: true - }); - } - return !result; - } - }, { - key: 'navigateToNextLocation', - value: function navigateToNextLocation(cb) { - var _this2 = this; - - var _state = this.state, - action = _state.action, - nextLocation = _state.nextLocation; - - action = { - 'POP': this.props.allowGoBack ? 'goBack' : 'push', - 'PUSH': 'push', - 'REPLACE': 'replace' - }[action || 'PUSH']; - if (!nextLocation) nextLocation = { pathname: '/' }; - var history = this.props.history; - - - this.state.unblock(); - this._prevUserAction = 'CONFIRM'; - if (action === 'goBack') { - // Because there is asynchronous time between calling history.goBack() - // and history actually changing, we need to set up this temporary callback - // -- if we tried to run this synchronously after calling history.goBack(), - // then navigateToNextLocation would be triggered again. - var unlisten = history.listen(function () { - unlisten(); - if (_this2._isMounted) { - // Just in case we unmounted on the route change - _this2.setState(_extends({}, initState, { - unblock: history.block(_this2.block) - })); - } - }); - history.goBack(); - } else { - // $FlowFixMe history.replace()'s type expects LocationShape even though it works with Location. - history[action](nextLocation); // could unmount at this point - if (this._isMounted) { - // Just in case we unmounted on the route change - this.setState(_extends({}, initState, { - unblock: this.props.history.block(this.block) - })); // FIXME? Does history.listen need to be used instead, for async? - } - } - } - }, { - key: 'onCancel', - value: function onCancel() { - var _this3 = this; - - (this.props.beforeCancel || function (cb) { - cb(); - })(function () { - _this3._prevUserAction = 'CANCEL'; - _this3.setState(_extends({}, initState)); - }); - } - }, { - key: 'onConfirm', - value: function onConfirm() { - var _this4 = this; - - (this.props.beforeConfirm || function (cb) { - cb(); - })(function () { - _this4.navigateToNextLocation(_this4.props.afterConfirm); - }); - } - }, { - key: 'onBeforeUnload', - value: function onBeforeUnload(e) { - if (!this.when()) return; - var msg = 'Do you want to leave this site?\n\nChanges you made may not be saved.'; - e.returnValue = msg; - return msg; - } - }, { - key: 'when', - value: function when(nextLocation, action) { - if (typeof this.props.when === 'function') { - return this.props.when(this.props.location, nextLocation, action); - } else { - return this.props.when; - } - } - }, { - key: 'render', - value: function render() { - if (!this.state.isActive && !this.props.renderIfNotActive) return null; - return _react2.default.createElement( - 'div', - null, - this.props.children({ - isActive: this.state.isActive, - onConfirm: this.onConfirm, - onCancel: this.onCancel - }) - ); - } - }]); - - return NavigationPrompt; -}(_react2.default.Component); - -exports.default = (0, _reactRouterDom.withRouter)(NavigationPrompt); - -/***/ }), -/* 1 */ -/***/ (function(module, exports) { - -module.exports = require("react"); - -/***/ }), -/* 2 */ -/***/ (function(module, exports) { - -module.exports = require("react-router-dom"); - -/***/ }) -/******/ ]); \ No newline at end of file +(()=>{"use strict";var t={689:t=>{t.exports=require("react")},661:t=>{t.exports=require("react-router-dom")}},e={};function o(n){var i=e[n];if(void 0!==i)return i.exports;var r=e[n]={exports:{}};return t[n](r,r.exports,o),r.exports}var n={};(()=>{var t=n;Object.defineProperty(t,"__esModule",{value:!0});var e,i=Object.assign||function(t){for(var e=1;e React$Element<*>, + beforeSkip?: Function, + afterSkip?: Function, + onShow?: (data: {action: ?HistoryAction, nextLocation: ?Location, onCancel: Function, onConfirm: Function, onSkip: (nextLocation: Location | string | URL, action?: HistoryAction) => void}) => void, + onShowNative?: Function, + children: (data: {isActive: bool, action: ?HistoryAction, nextLocation: ?Location, onCancel: Function, onConfirm: Function, onSkip: (nextLocation: Location | string | URL, action?: HistoryAction) => void}) => React$Element<*>, match: Match, history: RouterHistory, location: Location, renderIfNotActive?: bool, when: bool | (Location, ?Location, ?HistoryAction) => bool, disableNative?: bool, - allowGoBack?: bool, + allowGoBack?: bool }; declare type StateT = { action: ?HistoryAction, @@ -67,6 +71,7 @@ class NavigationPrompt extends React.Component { (this:Object).onBeforeUnload = this.onBeforeUnload.bind(this); (this:Object).onCancel = this.onCancel.bind(this); (this:Object).onConfirm = this.onConfirm.bind(this); + (this:Object).onSkip = this.onSkip.bind(this); (this:Object).when = this.when.bind(this); this.state = {...initState, unblock: () => {}/* unblock will be set in componentDidMount */}; @@ -85,6 +90,8 @@ class NavigationPrompt extends React.Component { this.props.afterCancel(); } else if (this._prevUserAction === 'CONFIRM' && typeof this.props.afterConfirm === 'function') { this.props.afterConfirm(); + } else if (this._prevUserAction === 'SKIP' && typeof this.props.afterSkip === 'function') { + this.props.afterSkip(); } this._prevUserAction = ''; } @@ -108,12 +115,20 @@ class NavigationPrompt extends React.Component { action, nextLocation, isActive: true - }); + }, () => this.props.onShow && + this.props.onShow({ + action: this.state.action, + nextLocation: this.state.nextLocation, + onConfirm: this.onConfirm, + onCancel: this.onCancel, + onSkip: this.onSkip + }) + ); } return !result; } - navigateToNextLocation(cb) { + navigateToNextLocation() { let {action, nextLocation} = this.state; action = { 'POP': this.props.allowGoBack ? 'goBack' : 'push', @@ -152,6 +167,57 @@ class NavigationPrompt extends React.Component { } } + navigateTo(nextLocation, action) { + const method = { + 'POP': '', + 'PUSH': 'push', + 'REPLACE': 'replace' + }[action || 'PUSH']; + if (!method) + throw new Error('Action is not supported!'); + + const {history} = this.props; + + this.state.unblock(); + this._prevUserAction = 'SKIP'; + // $FlowFixMe history.replace()'s type expects LocationShape even though it works with Location. + history[method](nextLocation); // could unmount at this point + if (this._isMounted) { // Just in case we unmounted on the route change + this.setState({ + ...initState, + unblock: this.props.history.block(this.block) + }); // FIXME? Does history.listen need to be used instead, for async? + } + } + + navigateToNative(nextLocation, action) { + if (!this.props.disableNative) { + window.removeEventListener('beforeunload', this.onBeforeUnload); + } + + if (action === 'PUSH') { + window.location.assign(nextLocation); + } else if (action === 'REPLACE') { + window.location.replace(nextLocation); + } else { + throw new Error('Action is not supported!'); + } + } + + onSkip(nextLocation, action) { + (this.props.beforeSkip || ((cb) => { + cb(); + }))(() => { + if (nextLocation instanceof URL) { + this.navigateToNative(nextLocation.toString(), action); + } else if (typeof nextLocation === 'string' && /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/.test(nextLocation)) { + this.navigateToNative(nextLocation, action); + } else { + this.navigateTo(nextLocation, action); + } + }); + } + onCancel() { (this.props.beforeCancel || ((cb) => { cb(); @@ -165,12 +231,13 @@ class NavigationPrompt extends React.Component { (this.props.beforeConfirm || ((cb) => { cb(); }))(() => { - this.navigateToNextLocation(this.props.afterConfirm); + this.navigateToNextLocation(); }); } onBeforeUnload(e) { if (!this.when()) return; + this.props.onShowNative && this.props.onShowNative(); const msg = 'Do you want to leave this site?\n\nChanges you made may not be saved.'; e.returnValue = msg; return msg; @@ -190,8 +257,11 @@ class NavigationPrompt extends React.Component { {this.props.children({ isActive: this.state.isActive, + action: this.state.action, + nextLocation: this.state.nextLocation, onConfirm: this.onConfirm, - onCancel: this.onCancel + onCancel: this.onCancel, + onSkip: this.onSkip })} ); diff --git a/package.json b/package.json index ea99378..aa8c0c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "react-router-navigation-prompt", - "version": "1.9.6", + "name": "react-router-navigation-prompt-flow", + "version": "1.10.3", "description": "A replacement component for the react-router ``. Allows for more flexible dialogs.", "scripts": { "build": "webpack", @@ -15,7 +15,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/ZacharyRSmith/react-router-navigation-prompt.git" + "url": "git+https://github.com/VOMATEC-Innovations/react-router-navigation-prompt.git" }, "keywords": [ "confirm", @@ -26,6 +26,7 @@ "user" ], "author": "@ZacharyRSmith", + "contributors": ["Fabian Wassenhoven "], "license": "MIT", "bugs": { "url": "https://github.com/ZacharyRSmith/react-router-navigation-prompt/issues" @@ -66,6 +67,7 @@ "testcafe": "^1.18.3", "typescript": "^3.1.1", "webpack": "^5.68.0", + "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.7.4" } } diff --git a/src/index.js b/src/index.js index a398203..adc0059 100644 --- a/src/index.js +++ b/src/index.js @@ -8,14 +8,18 @@ declare type PropsT = { afterConfirm?: Function, beforeCancel?: Function, beforeConfirm?: Function, - children: (data: {isActive: bool, onCancel: Function, onConfirm: Function}) => React$Element<*>, + beforeSkip?: Function, + afterSkip?: Function, + onShow?: (data: {action: ?HistoryAction, nextLocation: ?Location, onCancel: Function, onConfirm: Function, onSkip: (nextLocation: Location | string | URL, action?: HistoryAction) => void}) => void, + onShowNative?: Function, + children: (data: {isActive: bool, action: ?HistoryAction, nextLocation: ?Location, onCancel: Function, onConfirm: Function, onSkip: (nextLocation: Location | string | URL, action?: HistoryAction) => void}) => React$Element<*>, match: Match, history: RouterHistory, location: Location, renderIfNotActive?: bool, when: bool | (Location, ?Location, ?HistoryAction) => bool, disableNative?: bool, - allowGoBack?: bool, + allowGoBack?: bool }; declare type StateT = { action: ?HistoryAction, @@ -67,6 +71,7 @@ class NavigationPrompt extends React.Component { (this:Object).onBeforeUnload = this.onBeforeUnload.bind(this); (this:Object).onCancel = this.onCancel.bind(this); (this:Object).onConfirm = this.onConfirm.bind(this); + (this:Object).onSkip = this.onSkip.bind(this); (this:Object).when = this.when.bind(this); this.state = {...initState, unblock: () => {}/* unblock will be set in componentDidMount */}; @@ -85,6 +90,8 @@ class NavigationPrompt extends React.Component { this.props.afterCancel(); } else if (this._prevUserAction === 'CONFIRM' && typeof this.props.afterConfirm === 'function') { this.props.afterConfirm(); + } else if (this._prevUserAction === 'SKIP' && typeof this.props.afterSkip === 'function') { + this.props.afterSkip(); } this._prevUserAction = ''; } @@ -108,12 +115,20 @@ class NavigationPrompt extends React.Component { action, nextLocation, isActive: true - }); + }, () => this.props.onShow && + this.props.onShow({ + action: this.state.action, + nextLocation: this.state.nextLocation, + onConfirm: this.onConfirm, + onCancel: this.onCancel, + onSkip: this.onSkip + }) + ); } return !result; } - navigateToNextLocation(cb) { + navigateToNextLocation() { let {action, nextLocation} = this.state; action = { 'POP': this.props.allowGoBack ? 'goBack' : 'push', @@ -152,6 +167,57 @@ class NavigationPrompt extends React.Component { } } + navigateTo(nextLocation, action) { + const method = { + 'POP': '', + 'PUSH': 'push', + 'REPLACE': 'replace' + }[action || 'PUSH']; + if (!method) + throw new Error('Action is not supported!'); + + const {history} = this.props; + + this.state.unblock(); + this._prevUserAction = 'SKIP'; + // $FlowFixMe history.replace()'s type expects LocationShape even though it works with Location. + history[method](nextLocation); // could unmount at this point + if (this._isMounted) { // Just in case we unmounted on the route change + this.setState({ + ...initState, + unblock: this.props.history.block(this.block) + }); // FIXME? Does history.listen need to be used instead, for async? + } + } + + navigateToNative(nextLocation, action) { + if (!this.props.disableNative) { + window.removeEventListener('beforeunload', this.onBeforeUnload); + } + + if (action === 'PUSH') { + window.location.assign(nextLocation); + } else if (action === 'REPLACE') { + window.location.replace(nextLocation); + } else { + throw new Error('Action is not supported!'); + } + } + + onSkip(nextLocation, action) { + (this.props.beforeSkip || ((cb) => { + cb(); + }))(() => { + if (nextLocation instanceof URL) { + this.navigateToNative(nextLocation.toString(), action); + } else if (typeof nextLocation === 'string' && /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/.test(nextLocation)) { + this.navigateToNative(nextLocation, action); + } else { + this.navigateTo(nextLocation, action); + } + }); + } + onCancel() { (this.props.beforeCancel || ((cb) => { cb(); @@ -165,12 +231,13 @@ class NavigationPrompt extends React.Component { (this.props.beforeConfirm || ((cb) => { cb(); }))(() => { - this.navigateToNextLocation(this.props.afterConfirm); + this.navigateToNextLocation(); }); } onBeforeUnload(e) { if (!this.when()) return; + this.props.onShowNative && this.props.onShowNative(); const msg = 'Do you want to leave this site?\n\nChanges you made may not be saved.'; e.returnValue = msg; return msg; @@ -190,8 +257,11 @@ class NavigationPrompt extends React.Component { {this.props.children({ isActive: this.state.isActive, + action: this.state.action, + nextLocation: this.state.nextLocation, onConfirm: this.onConfirm, - onCancel: this.onCancel + onCancel: this.onCancel, + onSkip: this.onSkip })} ); diff --git a/types/index.d.ts b/types/index.d.ts index 3c26cff..c10e4c8 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -4,8 +4,11 @@ import { RouteComponentProps, Omit } from 'react-router'; export interface ChildData { isActive: boolean; + action: H.Action | undefined; + nextLocation: H.Location | undefined; onCancel: () => void; onConfirm: () => void; + onSkip: (nextLocation: H.Location | string | URL, action?: H.Action) => void; } export interface NavigationPromptProps extends RouteComponentProps { @@ -13,9 +16,13 @@ export interface NavigationPromptProps extends RouteComponentProps { when: boolean | ((currentLocation: H.Location, nextLocation?: H.Location, action?: H.Action) => boolean); afterCancel?: () => void; afterConfirm?: () => void; + afterSkip?: () => void; allowGoBack?: boolean; beforeCancel?: (callback: Function) => void; beforeConfirm?: (callback: Function) => void; + beforeSkip?: (callback: Function) => void; + onShow?: (data: {action: H.Action, nextLocation: H.Location, onCancel: () => void, onConfirm: () => void, onSkip: (nextLocation: H.Location | string | URL, action?: H.Action) => void}) => void; + onShowNative?: () => void; renderIfNotActive?: boolean; disableNative?: boolean; } @@ -32,9 +39,11 @@ interface NavigationPromptWithRouter extends React.Component void): void; + navigateToNextLocation(): void; + navigateTo(nextLocation: H.Location | string, action?: H.Action): void; onCancel(): void; onConfirm(): void; + onSkip(nextLocation: H.Location | string | URL, action?: H.Action): void; onBeforeUnload(e: any): string when(nextLocation?: H.Location, action?: H.Action): boolean; } diff --git a/webpack.config.js b/webpack.config.js index fa01ed0..aacc924 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,6 +2,7 @@ const path = require('path'); const CopyPlugin = require('copy-webpack-plugin'); module.exports = { + mode: 'production', entry: './src/index.js', output: { path: path.resolve(__dirname, 'es'), @@ -9,15 +10,17 @@ module.exports = { libraryTarget: 'commonjs2' // THIS IS THE MOST IMPORTANT LINE! :mindblow: I wasted more than 2 days until realize this was the line most important in all this guide. }, plugins: [ - new CopyPlugin([ - // copy the main source file to the `es/index.js.flow` to add - // a way to consume flow types for the end users - { - from: 'src/index.js', - to: 'index.js.flow', - toType: 'file' - } - ]), + new CopyPlugin({ + patterns: [ + // copy the main source file to the `es/index.js.flow` to add + // a way to consume flow types for the end users + { + from: 'src/index.js', + to: 'index.js.flow', + toType: 'file' + } + ] + }), ], module: { rules: [ diff --git a/yarn.lock b/yarn.lock index 44a62d4..6f2746c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -976,6 +976,11 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + "@eslint/eslintrc@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz" @@ -1486,6 +1491,23 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" @@ -2753,6 +2775,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + clone-response@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" @@ -2794,6 +2825,11 @@ colorette@^2.0.10: version "2.0.16" resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz" +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + colors@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -2814,6 +2850,11 @@ commander@^6.1.0: version "6.2.1" resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz" +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@^8.0.0: version "8.3.0" resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" @@ -3243,6 +3284,11 @@ enhanced-resolve@^5.8.3: graceful-fs "^4.2.4" tapable "^2.2.0" +envinfo@^7.7.3: + version "7.14.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" + integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== + error-stack-parser@^1.3.3, error-stack-parser@^1.3.6: version "1.3.6" resolved "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz" @@ -3630,6 +3676,11 @@ fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + fastq@^1.6.0: version "1.13.0" resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" @@ -3720,7 +3771,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.1.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" dependencies: @@ -3734,6 +3785,11 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^3.1.0: version "3.2.5" resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" @@ -3850,6 +3906,11 @@ function-bind@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" @@ -4130,6 +4191,13 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + highlight-es@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/highlight-es/-/highlight-es-1.0.1.tgz" @@ -4277,6 +4345,14 @@ import-lazy@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz" +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" @@ -4320,6 +4396,11 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz" +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + invariant@^2.1.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz" @@ -4397,6 +4478,13 @@ is-ci@^1.0.10: dependencies: ci-info "^1.0.0" +is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" @@ -5565,6 +5653,13 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" @@ -5837,6 +5932,13 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + regenerate-unicode-properties@^10.0.1: version "10.0.1" resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" @@ -5995,6 +6097,13 @@ resolve-cwd@^1.0.0: dependencies: resolve-from "^2.0.0" +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" @@ -6003,6 +6112,11 @@ resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-pathname@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz" @@ -6019,6 +6133,15 @@ resolve@^1.1.6, resolve@^1.13.1, resolve@^1.14.2: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.9.0: + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + dependencies: + is-core-module "^2.16.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.3: version "2.0.0-next.4" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" @@ -6215,6 +6338,13 @@ setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" @@ -7036,6 +7166,24 @@ webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" +webpack-cli@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + webpack-dev-middleware@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz" @@ -7081,6 +7229,15 @@ webpack-dev-server@^4.7.4: webpack-dev-middleware "^5.3.1" ws "^8.4.2" +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" @@ -7171,6 +7328,11 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz"
Do you really want to leave?