diff --git a/plugins/woocommerce-admin/client/analytics/components/report-error/index.js b/plugins/woocommerce-admin/client/analytics/components/report-error/index.js
index c34ae921f0f..ea17d7438c2 100644
--- a/plugins/woocommerce-admin/client/analytics/components/report-error/index.js
+++ b/plugins/woocommerce-admin/client/analytics/components/report-error/index.js
@@ -7,10 +7,10 @@ import { Component } from '@wordpress/element';
import PropTypes from 'prop-types';
/**
- * Internal dependencies
+ * WooCommerce dependencies
*/
import { EmptyContent } from '@woocommerce/components';
-import { getAdminLink } from 'lib/nav-utils';
+import { getAdminLink } from '@woocommerce/navigation';
class ReportError extends Component {
render() {
diff --git a/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js b/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js
index 8a22c52fe1f..09c9aecc567 100644
--- a/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js
+++ b/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js
@@ -14,12 +14,12 @@ import PropTypes from 'prop-types';
*/
import { formatCurrency } from '@woocommerce/currency';
import { getDateParamsFromQuery } from '@woocommerce/date';
+import { getNewPath } from '@woocommerce/navigation';
import { SummaryList, SummaryListPlaceholder, SummaryNumber } from '@woocommerce/components';
/**
* Internal dependencies
*/
-import { getNewPath } from 'lib/nav-utils';
import { getSummaryNumbers } from 'store/reports/utils';
import { numberFormat } from 'lib/number';
import ReportError from 'analytics/components/report-error';
diff --git a/plugins/woocommerce-admin/client/analytics/report/orders/table.js b/plugins/woocommerce-admin/client/analytics/report/orders/table.js
index 913f90ed7af..f2158222fd3 100644
--- a/plugins/woocommerce-admin/client/analytics/report/orders/table.js
+++ b/plugins/woocommerce-admin/client/analytics/report/orders/table.js
@@ -12,19 +12,19 @@ import { get, map, orderBy } from 'lodash';
/**
* WooCommerce dependencies
*/
-import { Link, OrderStatus, TableCard, ViewMoreList } from '@woocommerce/components';
-import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
import {
appendTimestamp,
getCurrentDates,
getIntervalForQuery,
getDateFormatsForInterval,
} from '@woocommerce/date';
+import { Link, OrderStatus, TableCard, ViewMoreList } from '@woocommerce/components';
+import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
+import { getAdminLink, onQueryChange } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
-import { getAdminLink, onQueryChange } from 'lib/nav-utils';
import ReportError from 'analytics/components/report-error';
import { QUERY_DEFAULTS } from 'store/constants';
import { getReportChartData, getFilterQuery } from 'store/reports/utils';
diff --git a/plugins/woocommerce-admin/client/analytics/report/products/table.js b/plugins/woocommerce-admin/client/analytics/report/products/table.js
index 8d5f275b751..dde8eb607b0 100644
--- a/plugins/woocommerce-admin/client/analytics/report/products/table.js
+++ b/plugins/woocommerce-admin/client/analytics/report/products/table.js
@@ -11,14 +11,14 @@ import { get, map, orderBy } from 'lodash';
/**
* WooCommerce dependencies
*/
+import { appendTimestamp, getCurrentDates } from '@woocommerce/date';
import { Link, TableCard } from '@woocommerce/components';
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
-import { appendTimestamp, getCurrentDates } from '@woocommerce/date';
+import { getNewPath, getTimeRelatedQuery, onQueryChange } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
-import { getNewPath, getTimeRelatedQuery, onQueryChange } from 'lib/nav-utils';
import ReportError from 'analytics/components/report-error';
import { getFilterQuery, getReportChartData } from 'store/reports/utils';
import { QUERY_DEFAULTS } from 'store/constants';
diff --git a/plugins/woocommerce-admin/client/analytics/report/revenue/table.js b/plugins/woocommerce-admin/client/analytics/report/revenue/table.js
index bebd8aabcaa..7f913d23e3a 100644
--- a/plugins/woocommerce-admin/client/analytics/report/revenue/table.js
+++ b/plugins/woocommerce-admin/client/analytics/report/revenue/table.js
@@ -12,19 +12,19 @@ import { get, map } from 'lodash';
/**
* WooCommerce dependencies
*/
-import { Link, TableCard } from '@woocommerce/components';
-import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
import {
appendTimestamp,
getCurrentDates,
getDateFormatsForInterval,
getIntervalForQuery,
} from '@woocommerce/date';
+import { Link, TableCard } from '@woocommerce/components';
+import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
+import { onQueryChange } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
-import { onQueryChange } from 'lib/nav-utils';
import ReportError from 'analytics/components/report-error';
import { QUERY_DEFAULTS } from 'store/constants';
diff --git a/plugins/woocommerce-admin/client/components/chart/index.js b/plugins/woocommerce-admin/client/components/chart/index.js
index 4cf29bc12d0..e352f8ab4cf 100644
--- a/plugins/woocommerce-admin/client/components/chart/index.js
+++ b/plugins/woocommerce-admin/client/components/chart/index.js
@@ -2,7 +2,6 @@
/**
* External dependencies
*/
-
import { decodeEntities } from '@wordpress/html-entities';
import { __ } from '@wordpress/i18n';
import classNames from 'classnames';
@@ -14,15 +13,19 @@ import { interpolateViridis as d3InterpolateViridis } from 'd3-scale-chromatic';
import { formatDefaultLocale as d3FormatDefaultLocale } from 'd3-format';
import Gridicon from 'gridicons';
+/**
+ * WooCommerce dependencies
+ */
+import { updateQueryString } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import D3Chart from './charts';
+import { gap, gaplarge } from 'stylesheets/abstracts/_variables.scss';
+import { H, Section } from 'components/section';
import Legend from './legend';
import { WIDE_BREAKPOINT } from './utils';
-import { H, Section } from 'components/section';
-import { gap, gaplarge } from 'stylesheets/abstracts/_variables.scss';
-import { updateQueryString } from 'lib/nav-utils';
d3FormatDefaultLocale( {
decimal: '.',
diff --git a/plugins/woocommerce-admin/client/components/filters/advanced/index.js b/plugins/woocommerce-admin/client/components/filters/advanced/index.js
index 4f070b0308d..8885fab8d67 100644
--- a/plugins/woocommerce-admin/client/components/filters/advanced/index.js
+++ b/plugins/woocommerce-admin/client/components/filters/advanced/index.js
@@ -10,6 +10,11 @@ import PropTypes from 'prop-types';
import Gridicon from 'gridicons';
import interpolateComponents from 'interpolate-components';
+/**
+ * WooCommerce dependencies
+ */
+import { getNewPath } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
@@ -22,7 +27,6 @@ import {
getQueryFromActiveFilters,
getDefaultOptionValue,
} from './utils';
-import { getNewPath } from 'lib/nav-utils';
import './style.scss';
const matches = [
diff --git a/plugins/woocommerce-admin/client/components/filters/compare/index.js b/plugins/woocommerce-admin/client/components/filters/compare/index.js
index 68cb390aed7..1cd5edcbab2 100644
--- a/plugins/woocommerce-admin/client/components/filters/compare/index.js
+++ b/plugins/woocommerce-admin/client/components/filters/compare/index.js
@@ -8,12 +8,16 @@ import { Button } from '@wordpress/components';
import { isEqual } from 'lodash';
import PropTypes from 'prop-types';
+/**
+ * WooCommerce dependencies
+ */
+import { getIdsFromQuery, updateQueryString } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import Card from 'components/card';
import CompareButton from './button';
-import { getIdsFromQuery, updateQueryString } from 'lib/nav-utils';
import Search from 'components/search';
/**
diff --git a/plugins/woocommerce-admin/client/components/filters/date/index.js b/plugins/woocommerce-admin/client/components/filters/date/index.js
index 7b24f14c04e..dd773df83ac 100644
--- a/plugins/woocommerce-admin/client/components/filters/date/index.js
+++ b/plugins/woocommerce-admin/client/components/filters/date/index.js
@@ -11,13 +11,13 @@ import PropTypes from 'prop-types';
* WooCommerce dependencies
*/
import { getCurrentDates, getDateParamsFromQuery, isoDateFormat } from '@woocommerce/date';
+import { updateQueryString } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import DatePickerContent from './content';
import DropdownButton from 'components/dropdown-button';
-import { updateQueryString } from 'lib/nav-utils';
import './style.scss';
const shortDateFormat = __( 'MM/DD/YYYY', 'wc-admin' );
diff --git a/plugins/woocommerce-admin/client/components/filters/filter/index.js b/plugins/woocommerce-admin/client/components/filters/filter/index.js
index 442cd07ff55..767b422f8a6 100644
--- a/plugins/woocommerce-admin/client/components/filters/filter/index.js
+++ b/plugins/woocommerce-admin/client/components/filters/filter/index.js
@@ -9,13 +9,17 @@ import { Component } from '@wordpress/element';
import { find, partial, last, get, includes } from 'lodash';
import PropTypes from 'prop-types';
+/**
+ * WooCommerce dependencies
+ */
+import { getTimeRelatedQuery, updateQueryString } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import AnimationSlider from 'components/animation-slider';
import DropdownButton from 'components/dropdown-button';
import Search from 'components/search';
-import { getTimeRelatedQuery, updateQueryString } from 'lib/nav-utils';
import { flatenFilters } from './utils';
import './style.scss';
diff --git a/plugins/woocommerce-admin/client/components/link/index.js b/plugins/woocommerce-admin/client/components/link/index.js
index 7a4a0a4b397..463a0dcb861 100644
--- a/plugins/woocommerce-admin/client/components/link/index.js
+++ b/plugins/woocommerce-admin/client/components/link/index.js
@@ -3,13 +3,13 @@
* External dependencies
*/
import { Component } from '@wordpress/element';
-import PropTypes from 'prop-types';
import { Link as RouterLink } from 'react-router-dom';
+import PropTypes from 'prop-types';
/**
- * Internal dependencies
+ * WooCommerce dependencies
*/
-import { getAdminLink } from 'lib/nav-utils';
+import { getAdminLink } from '@woocommerce/navigation';
/**
* Use `Link` to create a link to another resource. It accepts a type to automatically
diff --git a/plugins/woocommerce-admin/client/components/search/autocompleters/coupons.js b/plugins/woocommerce-admin/client/components/search/autocompleters/coupons.js
index 53fd6f977c9..d0d4b3b9d4d 100644
--- a/plugins/woocommerce-admin/client/components/search/autocompleters/coupons.js
+++ b/plugins/woocommerce-admin/client/components/search/autocompleters/coupons.js
@@ -4,11 +4,15 @@
*/
import apiFetch from '@wordpress/api-fetch';
+/**
+ * WooCommerce dependencies
+ */
+import { stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import { computeSuggestionMatch } from './utils';
-import { stringifyQuery } from 'lib/nav-utils';
import { NAMESPACE } from 'store/constants';
/**
diff --git a/plugins/woocommerce-admin/client/components/search/autocompleters/product-cat.js b/plugins/woocommerce-admin/client/components/search/autocompleters/product-cat.js
index 939d3020e79..8819a2fd2bf 100644
--- a/plugins/woocommerce-admin/client/components/search/autocompleters/product-cat.js
+++ b/plugins/woocommerce-admin/client/components/search/autocompleters/product-cat.js
@@ -4,11 +4,15 @@
*/
import apiFetch from '@wordpress/api-fetch';
+/**
+ * WooCommerce dependencies
+ */
+import { stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import { computeSuggestionMatch } from './utils';
-import { stringifyQuery } from 'lib/nav-utils';
import { NAMESPACE } from 'store/constants';
/**
diff --git a/plugins/woocommerce-admin/client/components/search/autocompleters/product.js b/plugins/woocommerce-admin/client/components/search/autocompleters/product.js
index a4257b3e5d7..1f2c55655be 100644
--- a/plugins/woocommerce-admin/client/components/search/autocompleters/product.js
+++ b/plugins/woocommerce-admin/client/components/search/autocompleters/product.js
@@ -4,12 +4,16 @@
*/
import apiFetch from '@wordpress/api-fetch';
+/**
+ * WooCommerce dependencies
+ */
+import { stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import { computeSuggestionMatch } from './utils';
import ProductImage from 'components/product-image';
-import { stringifyQuery } from 'lib/nav-utils';
import { NAMESPACE } from 'store/constants';
/**
diff --git a/plugins/woocommerce-admin/client/components/table/index.js b/plugins/woocommerce-admin/client/components/table/index.js
index c7c9a273611..a24de7527cc 100644
--- a/plugins/woocommerce-admin/client/components/table/index.js
+++ b/plugins/woocommerce-admin/client/components/table/index.js
@@ -9,6 +9,11 @@ import { find, findIndex, first, isEqual, noop, partial, uniq } from 'lodash';
import { IconButton, ToggleControl } from '@wordpress/components';
import PropTypes from 'prop-types';
+/**
+ * WooCommerce dependencies
+ */
+import { getIdsFromQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
@@ -18,7 +23,6 @@ import CompareButton from 'components/filters/compare/button';
import DowloadIcon from './download-icon';
import EllipsisMenu from 'components/ellipsis-menu';
import { downloadCSVFile, generateCSVDataFromTable, generateCSVFileName } from 'lib/csv';
-import { getIdsFromQuery } from 'lib/nav-utils';
import MenuItem from 'components/ellipsis-menu/menu-item';
import MenuTitle from 'components/ellipsis-menu/menu-title';
import Pagination from 'components/pagination';
diff --git a/plugins/woocommerce-admin/client/dashboard/top-selling-products/index.js b/plugins/woocommerce-admin/client/dashboard/top-selling-products/index.js
index bf9b0e9754b..9704576ea71 100644
--- a/plugins/woocommerce-admin/client/dashboard/top-selling-products/index.js
+++ b/plugins/woocommerce-admin/client/dashboard/top-selling-products/index.js
@@ -13,11 +13,11 @@ import { withSelect } from '@wordpress/data';
*/
import { Card, EmptyTable, TableCard } from '@woocommerce/components';
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
+import { getAdminLink } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
-import { getAdminLink } from 'lib/nav-utils';
import { numberFormat } from 'lib/number';
import ReportError from 'analytics/components/report-error';
import { NAMESPACE } from 'store/constants';
diff --git a/plugins/woocommerce-admin/client/header/index.js b/plugins/woocommerce-admin/client/header/index.js
index 0de78215dbc..858f1c49250 100644
--- a/plugins/woocommerce-admin/client/header/index.js
+++ b/plugins/woocommerce-admin/client/header/index.js
@@ -9,13 +9,17 @@ import { decodeEntities } from '@wordpress/html-entities';
import { Fill } from 'react-slot-fill';
import PropTypes from 'prop-types';
+/**
+ * WooCommerce dependencies
+ */
+import { getNewPath, getTimeRelatedQuery } from '@woocommerce/navigation';
+import { Link } from '@woocommerce/components';
+
/**
* Internal dependencies
*/
import './style.scss';
import ActivityPanel from './activity-panel';
-import { Link } from '@woocommerce/components';
-import { getNewPath, getTimeRelatedQuery } from 'lib/nav-utils';
class Header extends Component {
constructor() {
diff --git a/plugins/woocommerce-admin/client/layout/controller.js b/plugins/woocommerce-admin/client/layout/controller.js
index 48bfdde3010..024ea1138ff 100644
--- a/plugins/woocommerce-admin/client/layout/controller.js
+++ b/plugins/woocommerce-admin/client/layout/controller.js
@@ -6,6 +6,11 @@ import { Component, createElement } from '@wordpress/element';
import { parse } from 'qs';
import { find, last } from 'lodash';
+/**
+ * WooCommerce dependencies
+ */
+import { getTimeRelatedQuery, stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
@@ -13,7 +18,6 @@ import Analytics from 'analytics';
import AnalyticsReport from 'analytics/report';
import Dashboard from 'dashboard';
import DevDocs from 'devdocs';
-import { getTimeRelatedQuery, stringifyQuery } from 'lib/nav-utils';
const getPages = () => {
const pages = [
diff --git a/plugins/woocommerce-admin/client/layout/index.js b/plugins/woocommerce-admin/client/layout/index.js
index 697c540d756..9862c2029b8 100644
--- a/plugins/woocommerce-admin/client/layout/index.js
+++ b/plugins/woocommerce-admin/client/layout/index.js
@@ -8,13 +8,17 @@ import { Slot } from 'react-slot-fill';
import PropTypes from 'prop-types';
import { get } from 'lodash';
+/**
+ * WooCommerce dependencies
+ */
+import { history } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
import './style.scss';
import { Controller, getPages } from './controller';
import Header from 'header';
-import history from 'lib/history';
import Notices from './notices';
import { recordPageView } from 'lib/tracks';
diff --git a/plugins/woocommerce-admin/client/lib/async-requests/index.js b/plugins/woocommerce-admin/client/lib/async-requests/index.js
index 8c417db50f4..476ea986cac 100644
--- a/plugins/woocommerce-admin/client/lib/async-requests/index.js
+++ b/plugins/woocommerce-admin/client/lib/async-requests/index.js
@@ -6,9 +6,9 @@ import apiFetch from '@wordpress/api-fetch';
import { identity } from 'lodash';
/**
- * Internal dependencies
+ * WooCommerce dependencies
*/
-import { getIdsFromQuery, stringifyQuery } from 'lib/nav-utils';
+import { getIdsFromQuery, stringifyQuery } from '@woocommerce/navigation';
/**
* Get a function that accepts ids as they are found in url parameter and
diff --git a/plugins/woocommerce-admin/client/lib/nav-utils/README.md b/plugins/woocommerce-admin/client/lib/nav-utils/README.md
deleted file mode 100644
index 035b18ed7ce..00000000000
--- a/plugins/woocommerce-admin/client/lib/nav-utils/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-Nav Utils
-=========
-
-This is a library of functions used in navigation.
-
-## `getPath()`
-
-Get the current path from history.
-
-## `getQuery()`
-
-Get the current query string, parsed into an object, from history.
-
-## `getAdminLink( string: path )`
-
-JS version of `admin_url`. Returns the full URL for a page in wp-admin.
-
-## `getNewPath( object: query, string: path, object: currentQuery )`
-
-Return a URL with set query parameters. Optional `path`, `currentQuery`, both will default to the current value fetched from `history` if not provided.
-
-## `updateQueryString( object: query )`
-
-Updates the query parameters of the current page.
diff --git a/plugins/woocommerce-admin/client/store/notes/resolvers.js b/plugins/woocommerce-admin/client/store/notes/resolvers.js
index 82a97f2b1b4..5e2ee4ca6c0 100644
--- a/plugins/woocommerce-admin/client/store/notes/resolvers.js
+++ b/plugins/woocommerce-admin/client/store/notes/resolvers.js
@@ -1,15 +1,18 @@
/** @format */
-
/**
* External dependencies
*/
import { dispatch } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';
+/**
+ * WooCommerce dependencies
+ */
+import { stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
-import { stringifyQuery } from 'lib/nav-utils';
import { NAMESPACE } from 'store/constants';
export default {
diff --git a/plugins/woocommerce-admin/client/store/orders/resolvers.js b/plugins/woocommerce-admin/client/store/orders/resolvers.js
index 5be6c64a206..12190394a5f 100644
--- a/plugins/woocommerce-admin/client/store/orders/resolvers.js
+++ b/plugins/woocommerce-admin/client/store/orders/resolvers.js
@@ -5,10 +5,14 @@
import { dispatch } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';
+/**
+ * WooCommerce dependencies
+ */
+import { stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
-import { stringifyQuery } from 'lib/nav-utils';
import { NAMESPACE } from 'store/constants';
export default {
diff --git a/plugins/woocommerce-admin/client/store/reports/stats/resolvers.js b/plugins/woocommerce-admin/client/store/reports/stats/resolvers.js
index d03cb2a3793..ef29b6ade32 100644
--- a/plugins/woocommerce-admin/client/store/reports/stats/resolvers.js
+++ b/plugins/woocommerce-admin/client/store/reports/stats/resolvers.js
@@ -6,10 +6,14 @@
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
+/**
+ * WooCommerce dependencies
+ */
+import { stringifyQuery } from '@woocommerce/navigation';
+
/**
* Internal dependencies
*/
-import { stringifyQuery } from 'lib/nav-utils';
import { NAMESPACE } from 'store/constants';
export default {
diff --git a/plugins/woocommerce-admin/lib/client-assets.php b/plugins/woocommerce-admin/lib/client-assets.php
index 49160134233..33c643d4b7f 100644
--- a/plugins/woocommerce-admin/lib/client-assets.php
+++ b/plugins/woocommerce-admin/lib/client-assets.php
@@ -26,6 +26,14 @@ function wc_admin_register_script() {
true
);
+ wp_register_script(
+ 'wc-navigation',
+ wc_admin_url( 'dist/navigation/index.js' ),
+ array(),
+ filemtime( wc_admin_dir_path( 'dist/navigation/index.js' ) ),
+ true
+ );
+
wp_register_script(
'wc-date',
wc_admin_url( 'dist/date/index.js' ),
@@ -46,6 +54,7 @@ function wc_admin_register_script() {
'wp-keycodes',
'wc-currency',
'wc-date',
+ 'wc-navigation',
),
filemtime( wc_admin_dir_path( 'dist/components/index.js' ) ),
true
@@ -54,7 +63,7 @@ function wc_admin_register_script() {
wp_register_script(
WC_ADMIN_APP,
wc_admin_url( "dist/{$entry}/index.js" ),
- array( 'wc-components', 'wp-date', 'wp-html-entities', 'wp-keycodes' ),
+ array( 'wc-components', 'wc-navigation', 'wp-date', 'wp-html-entities', 'wp-keycodes' ),
filemtime( wc_admin_dir_path( "dist/{$entry}/index.js" ) ),
true
);
diff --git a/plugins/woocommerce-admin/package.json b/plugins/woocommerce-admin/package.json
index bb605e915ac..de76844b4f1 100644
--- a/plugins/woocommerce-admin/package.json
+++ b/plugins/woocommerce-admin/package.json
@@ -130,6 +130,7 @@
"interpolate-components": "1.1.1",
"lodash": "^4.17.11",
"marked": "0.5.1",
+ "qs": "^6.5.2",
"react-click-outside": "3.0.1",
"react-dates": "^18.0.4",
"react-live": "1.12.0",
diff --git a/plugins/woocommerce-admin/packages/navigation/.npmrc b/plugins/woocommerce-admin/packages/navigation/.npmrc
new file mode 100644
index 00000000000..43c97e719a5
--- /dev/null
+++ b/plugins/woocommerce-admin/packages/navigation/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/plugins/woocommerce-admin/packages/navigation/README.md b/plugins/woocommerce-admin/packages/navigation/README.md
new file mode 100644
index 00000000000..3d9b95a3d81
--- /dev/null
+++ b/plugins/woocommerce-admin/packages/navigation/README.md
@@ -0,0 +1,106 @@
+# Navigation
+
+A collection of navigation-related functions for handling query parameter objects, serializing query parameters, updating query parameters, and triggering path changes.
+
+## Installation
+
+Install the module
+
+```bash
+npm install @woocommerce/navigation --save
+```
+
+## Usage
+
+### history
+
+A single history object used to perform path changes. This needs to be passed into ReactRouter to use the other path functions from this library.
+
+```jsx
+import { history } from '@woocommerce/navigation';
+
+render() {
+ return (
+
+ …
+
+ );
+}
+```
+
+### getAdminLink(path) ⇒ String
+Returns a string with the site's wp-admin URL appended. JS version of `admin_url`. This relies on a global object `wcSettings` with a property `adminUrl` set.
+
+**Returns**: String
- Full admin URL.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| path | String
| Relative path. |
+
+### getPath() ⇒ String
+Get the current path from history.
+
+**Returns**: String
- Current path.
+
+### stringifyQuery(query) ⇒ String
+Converts a query object to a query string.
+
+**Returns**: String
- Query string.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| query | Object
| parameters to be converted. |
+
+### getTimeRelatedQuery(query) ⇒ Object
+Gets time related parameters from a query.
+
+**Returns**: Object
- Object containing the time related queries.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| query | Object
| Query containing the parameters. |
+
+### getIdsFromQuery(queryString) ⇒ Array
+Get an array of IDs from a comma-separated query parameter.
+
+**Returns**: Array
- List of IDs converted to numbers.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| queryString | string
| string value extracted from URL. |
+
+### getNewPath(query, path, currentQuery) ⇒ String
+Return a URL with set query parameters.
+
+**Returns**: String
- Updated URL merging query params into existing params.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| query | Object
| object of params to be updated. |
+| path | String
| Relative path (defaults to current path). |
+| currentQuery | Object
| object of current query params (defaults to current querystring). |
+
+### getQuery() ⇒ Object
+Get the current query string, parsed into an object, from history.
+
+**Returns**: Object
- Current query object, defaults to empty object.
+
+### onQueryChange(param, path, query) ⇒ function
+This function returns an event handler for the given `param`
+
+**Returns**: function
- A callback which will update `param` to the passed value when called.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| param | string
| The parameter in the querystring which should be updated (ex `page`, `per_page`) |
+| path | string
| Relative path (defaults to current path). |
+| query | string
| object of current query params (defaults to current querystring). |
+
+### updateQueryString(query, path, currentQuery)
+Updates the query parameters of the current page.
+
+| Param | Type | Description |
+| --- | --- | --- |
+| query | Object
| object of params to be updated. |
+| path | String
| Relative path (defaults to current path). |
+| currentQuery | Object
| object of current query params (defaults to current querystring). |
diff --git a/plugins/woocommerce-admin/packages/navigation/package.json b/plugins/woocommerce-admin/packages/navigation/package.json
new file mode 100644
index 00000000000..d5f75553fce
--- /dev/null
+++ b/plugins/woocommerce-admin/packages/navigation/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "@woocommerce/navigation",
+ "version": "1.0.0-alpha.0",
+ "description": "WooCommerce navigation utilities.",
+ "author": "Automattic",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "wordpress",
+ "woocommerce",
+ "navigation"
+ ],
+ "homepage": "https://github.com/WooCommerce/wc-admin/tree/master/packages/navigation/README.md",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/WooCommerce/wc-admin.git"
+ },
+ "bugs": {
+ "url": "https://github.com/WooCommerce/wc-admin/issues"
+ },
+ "main": "build/index.js",
+ "module": "build-module/index.js",
+ "react-native": "src/index",
+ "dependencies": {
+ "@babel/runtime": "^7.0.0",
+ "history": "4.7.2",
+ "lodash": "^4.17.11",
+ "qs": "^6.5.2"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/plugins/woocommerce-admin/client/lib/history.js b/plugins/woocommerce-admin/packages/navigation/src/history.js
similarity index 99%
rename from plugins/woocommerce-admin/client/lib/history.js
rename to plugins/woocommerce-admin/packages/navigation/src/history.js
index 399846da1f2..6924d5233d8 100644
--- a/plugins/woocommerce-admin/client/lib/history.js
+++ b/plugins/woocommerce-admin/packages/navigation/src/history.js
@@ -1,5 +1,4 @@
/** @format */
-
/**
* External dependencies
*/
diff --git a/plugins/woocommerce-admin/client/lib/nav-utils/index.js b/plugins/woocommerce-admin/packages/navigation/src/index.js
similarity index 96%
rename from plugins/woocommerce-admin/client/lib/nav-utils/index.js
rename to plugins/woocommerce-admin/packages/navigation/src/index.js
index bf25d23696d..e2f4c0c36c4 100644
--- a/plugins/woocommerce-admin/client/lib/nav-utils/index.js
+++ b/plugins/woocommerce-admin/packages/navigation/src/index.js
@@ -2,9 +2,16 @@
/**
* External dependencies
*/
-import history from 'lib/history';
-import { parse, stringify } from 'qs';
import { isEmpty, pick, uniq } from 'lodash';
+import { parse, stringify } from 'qs';
+
+/**
+ * Internal dependencies
+ */
+import history from './history';
+
+// Expose history so all uses get the same history object.
+export { history };
/**
* Internal dependencies
diff --git a/plugins/woocommerce-admin/client/lib/nav-utils/test/index.js b/plugins/woocommerce-admin/packages/navigation/src/test/index.js
similarity index 100%
rename from plugins/woocommerce-admin/client/lib/nav-utils/test/index.js
rename to plugins/woocommerce-admin/packages/navigation/src/test/index.js
diff --git a/plugins/woocommerce-admin/tests/js/setup-globals.js b/plugins/woocommerce-admin/tests/js/setup-globals.js
index 894e58ccbe4..dbcfaa2f749 100644
--- a/plugins/woocommerce-admin/tests/js/setup-globals.js
+++ b/plugins/woocommerce-admin/tests/js/setup-globals.js
@@ -25,6 +25,7 @@ const wooCommercePackages = [
'components',
'currency',
'date',
+ 'navigation',
];
wordPressPackages.forEach( lib => {
diff --git a/plugins/woocommerce-admin/webpack.config.js b/plugins/woocommerce-admin/webpack.config.js
index 801e7e47014..c5636a4fc11 100644
--- a/plugins/woocommerce-admin/webpack.config.js
+++ b/plugins/woocommerce-admin/webpack.config.js
@@ -31,6 +31,7 @@ const wcAdminPackages = {
components: './client/components',
currency: './packages/currency',
date: './packages/date',
+ navigation: './packages/navigation',
};
Object.keys( wcAdminPackages ).forEach( ( name ) => {