diff --git a/cosmoz-data-nav-pure.js b/cosmoz-data-nav-pure.js new file mode 100644 index 0000000..dbbe746 --- /dev/null +++ b/cosmoz-data-nav-pure.js @@ -0,0 +1,40 @@ +import { + component, useState, useCallback +} from 'haunted'; + +import { useNotifyProperty } from '@neovici/cosmoz-utils/lib/hooks/use-notify-property'; +import { useMaintainSelection } from './lib/use-maintain-selection'; +import { useTriggerPreload } from './lib/use-trigger-preload'; + +const + useCosmozDataNav = host => { + const + { + items, + renderItem, + maintainSelection + } = host, + [selected, setSelected] = useState(0); + + useTriggerPreload(host, items, selected); + useMaintainSelection(items, selected, maintainSelection, setSelected); + useNotifyProperty('selected', selected); + + return { + items, + renderItem, + selected, + advance: useCallback(n => setSelected(selected => selected + n), []) + }; + }, + + renderCosmozDataNav = ({ + items, + renderItem, + selected, + advance + }) => items[selected] && renderItem(items[selected], selected, items, advance), + + CosmozDataNavPure = host => renderCosmozDataNav(useCosmozDataNav(host)); + +customElements.define('cosmoz-data-nav-pure', component(CosmozDataNavPure, { useShadowDOM: false })); diff --git a/lib/use-maintain-selection.js b/lib/use-maintain-selection.js new file mode 100644 index 0000000..6c2d845 --- /dev/null +++ b/lib/use-maintain-selection.js @@ -0,0 +1,31 @@ +import { + useState, useEffect +} from 'haunted'; + +export const useMaintainSelection = (items, selected, maintainSelection, setSelected) => { + const [selectedItem, setSelectedItem] = useState(items?.[selected]); + + useEffect(() => { + setSelectedItem(items?.[selected]); + }, [items, selected]); + + useEffect(() => { + if (maintainSelection === false) { + setSelected(0); + return; + } + + const index = items.findIndex(item => (item?.id || item) === (selectedItem?.id || selectedItem)); + + if (index === -1) { + setSelected(0); + return; + } + + if (index === selected) { + return; + } + + setSelected(index); + }, [items]); // We intentionally only run this code when `items` changes. +}; diff --git a/lib/use-trigger-preload.js b/lib/use-trigger-preload.js new file mode 100644 index 0000000..f44ac4c --- /dev/null +++ b/lib/use-trigger-preload.js @@ -0,0 +1,14 @@ +import { useEffect } from 'haunted'; + +const needData = (host, item) => item != null && typeof item !== 'object' && host.dispatchEvent(new CustomEvent('need-data', { detail: { id: item }})); + +export const useTriggerPreload = (host, items, selected) => + useEffect(() => { + if (items.length === 0) { + return; + } + + needData(host, items[selected - 1]); + needData(host, items[selected]); + needData(host, items[selected + 1]); + }, [items, selected]); diff --git a/package-lock.json b/package-lock.json index 0d894c8..658f976 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1276,9 +1276,9 @@ } }, "@neovici/cosmoz-utils": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@neovici/cosmoz-utils/-/cosmoz-utils-3.8.0.tgz", - "integrity": "sha512-VagVI8zRGh6bwGhLksrbSamgAHWKHIPhCOVMMn64hVKZvHZZl+tDxK/XskIkzNJXgvC1QCpqCkfed92mvKDN5A==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@neovici/cosmoz-utils/-/cosmoz-utils-3.13.0.tgz", + "integrity": "sha512-Ui/6/8PNFDlMl4BXjPMsi3ysU/+Ll7SGM+DFAdGZ2b6PsS6k7GUcdfmkW5D6zFcWws0e9aFBWlwgZlPzy/Dk9Q==", "requires": { "haunted": "^4.0.0" } @@ -9244,7 +9244,7 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true } @@ -9614,7 +9614,7 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true } diff --git a/package.json b/package.json index e71cbe0..dc60bdb 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@neovici/cosmoz-bottom-bar": "^3.0.10", "@neovici/cosmoz-i18next": "^3.2.2", "@neovici/cosmoz-page-router": "^6.0.5", - "@neovici/cosmoz-utils": "^3.8.0", + "@neovici/cosmoz-utils": "^3.13.0", "@polymer/iron-resizable-behavior": "^3.0.1", "@polymer/paper-icon-button": "^3.0.0", "@polymer/paper-spinner": "^3.0.0",