Skip to content

Commit

Permalink
IE polyfills; sticky sidebar improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Frencil committed Sep 24, 2020
1 parent 39effc4 commit 14708ac
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 123 deletions.
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
PORT=3010
REACT_APP_VERSION=$npm_package_version
REACT_APP_NEON_API_NAME="api"
REACT_APP_NEON_API_VERSION="v0"

Expand Down
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
REACT_APP_VERSION=$npm_package_version
REACT_APP_NEON_API_NAME="api"
REACT_APP_NEON_API_VERSION="v0"

Expand Down
65 changes: 45 additions & 20 deletions lib/components/NeonPage/NeonPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ var NeonPage = function NeonPage(props) {
var headerRef = (0, _react.useRef)(null);
var contentRef = (0, _react.useRef)(null);
var sidebarRef = (0, _react.useRef)(null);
var sidebarLinksContainerRef = (0, _react.useRef)(null);
var belowMd = (0, _useMediaQuery.default)(_Theme.default.breakpoints.down('sm'));
/**
Sidebar Setup
Expand All @@ -312,9 +313,9 @@ var NeonPage = function NeonPage(props) {
var sidebarHashMap = !hasSidebarLinks ? {} : Object.fromEntries(sidebarLinks.map(function (link, idx) {
return [link.hash || '#', idx];
}));
var initialCurrectSidebarHash = hasSidebarLinks ? sidebarLinks[0].hash || '#' : '#';
var initialCurrentSidebarHash = hasSidebarLinks ? sidebarLinks[0].hash || '#' : '#';

var _useState = (0, _react.useState)(initialCurrectSidebarHash),
var _useState = (0, _react.useState)(initialCurrentSidebarHash),
_useState2 = _slicedToArray(_useState, 2),
currentSidebarHash = _useState2[0],
setCurrentSidebarHash = _useState2[1];
Expand Down Expand Up @@ -345,12 +346,31 @@ var NeonPage = function NeonPage(props) {

var anchor = contentRef.current.querySelector(hash);
return !anchor ? -1 : anchor.offsetTop + headerOffset - stickyOffset - _Theme.default.spacing(5);
}, [hasSidebarLinks, sidebarLinksAsStandaloneChildren, belowMd]); // For sidebarLinks pages, on successful load, if hash is present then update the current
}, [hasSidebarLinks, sidebarLinksAsStandaloneChildren, belowMd]);
/**
Effect - For sidebarLinks pages, on successful load, if hash is present then update the current
*/

(0, _react.useLayoutEffect)(function () {
if (error || loading || !hasSidebarLinks) {
return function () {};
} // Handle URL-defined hash on initial load
}

var handleHashChange = function handleHashChange() {
var hash = document.location.hash;

if (currentSidebarHash === hash) {
return;
}

setCurrentSidebarHash(hash); // If standard sidebar mode (scroll to content) also perform the scroll offset here

if (!sidebarLinksAsStandaloneChildren) {
window.setTimeout(function () {
window.scrollTo(0, getSidebarLinkScrollPosition(hash));
}, 0);
}
}; // Handle URL-defined hash on initial load


if (document.location.hash && !hashInitialized) {
Expand All @@ -359,25 +379,25 @@ var NeonPage = function NeonPage(props) {
document.location.hash = '#';
}

var hash = document.location.hash;
handleHashChange();
setHashInitialized(true);
} // Set max-height on sidebar links container when the sidebar is sticky so the links get
// a dedicated scrollbar instead of clipping

if (currentSidebarHash !== hash) {
setCurrentSidebarHash(hash); // If standard sidebar mode (scroll to content) also perform the scroll offset here

if (!sidebarLinksAsStandaloneChildren) {
window.setTimeout(function () {
window.scrollTo(0, getSidebarLinkScrollPosition(hash));
}, 0);
}
}

setHashInitialized(true);
} // Set up event listener / handler for user-input scroll events for standard scrolling pages
if (!sidebarUnsticky && hasSidebarLinks && sidebarLinksContainerRef.current) {
var maxHeight = window.innerHeight - sidebarLinksContainerRef.current.offsetTop - 104;
sidebarLinksContainerRef.current.style.maxHeight = "".concat(maxHeight, "px");
} // For sidebarLinksAsStandaloneChildren listen for hash changes to trigger a "redirect".


if (sidebarLinksAsStandaloneChildren) {
return function () {};
}
window.addEventListener('hashchange', handleHashChange);
return function () {
window.removeEventListener('hashchange', handleHashChange);
};
} // Set up event listener / handler for user-input scroll events for standard scrolling pages


var handleScroll = function handleScroll() {
var scrollBreaks = sidebarLinks.map(function (link) {
Expand All @@ -403,9 +423,9 @@ var NeonPage = function NeonPage(props) {
return function () {
window.removeEventListener('scroll', handleScroll);
};
}, [error, loading, hasSidebarLinks, sidebarLinks, sidebarHashMap, hashInitialized, setHashInitialized, currentSidebarHash, setCurrentSidebarHash, getSidebarLinkScrollPosition, sidebarLinksAsStandaloneChildren]);
}, [error, loading, sidebarUnsticky, hasSidebarLinks, sidebarLinks, sidebarHashMap, hashInitialized, setHashInitialized, currentSidebarHash, setCurrentSidebarHash, sidebarLinksContainerRef, getSidebarLinkScrollPosition, sidebarLinksAsStandaloneChildren]);
/**
Drupal CSS Loading
Effect - Load Drupal CSS
*/

var _useState7 = (0, _react.useState)(false),
Expand Down Expand Up @@ -501,6 +521,10 @@ var NeonPage = function NeonPage(props) {
});
}));
};
/**
Effect - Fetch notifications
*/


(0, _react.useEffect)(function () {
if (fetchNotificationsStatus !== null) {
Expand Down Expand Up @@ -706,6 +730,7 @@ var NeonPage = function NeonPage(props) {
};

var fullLinks = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
ref: sidebarLinksContainerRef,
className: classes.sidebarLinksContainer
}, sidebarLinks.map(function (link) {
return renderLink(link);
Expand Down
27 changes: 20 additions & 7 deletions lib/components/SiteMap/SiteMapContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -1103,12 +1103,14 @@ var Provider = function Provider(props) {
*/

(0, _react.useEffect)(function () {
var noop = function noop() {};

var _state$focusLocation = state.focusLocation,
current = _state$focusLocation.current,
currentStatus = _state$focusLocation.fetch.status;

if (!current || currentStatus !== _SiteMapUtils.FETCH_STATUS.AWAITING_CALL || !state.neonContextHydrated) {
return;
return noop;
} // If the location is a known Domain, State, or Site then pull from NeonContext


Expand All @@ -1122,7 +1124,7 @@ var Provider = function Provider(props) {
var _statesData$current$c = statesData[current].center,
latitude = _statesData$current$c[0],
longitude = _statesData$current$c[1];
window.setTimeout(function () {
var timeout = window.setTimeout(function () {
dispatch({
type: 'setFocusLocationFetchSucceeded',
data: {
Expand All @@ -1132,14 +1134,17 @@ var Provider = function Provider(props) {
}
});
}, 0);
return;
return function () {
return window.clearTimeout(timeout);
};
}

if (Object.keys(domainsData).includes(current)) {
var _domainsData$current$ = domainsData[current].center,
_latitude = _domainsData$current$[0],
_longitude = _domainsData$current$[1];
window.setTimeout(function () {

var _timeout = window.setTimeout(function () {
dispatch({
type: 'setFocusLocationFetchSucceeded',
data: {
Expand All @@ -1149,14 +1154,18 @@ var Provider = function Provider(props) {
}
});
}, 0);
return;

return function () {
return window.clearTimeout(_timeout);
};
}

if (Object.keys(state.sites).includes(current)) {
var _state$sites$current = state.sites[current],
_latitude2 = _state$sites$current.latitude,
_longitude2 = _state$sites$current.longitude;
window.setTimeout(function () {

var _timeout2 = window.setTimeout(function () {
dispatch({
type: 'setFocusLocationFetchSucceeded',
data: {
Expand All @@ -1166,7 +1175,10 @@ var Provider = function Provider(props) {
}
});
}, 0);
return;

return function () {
return window.clearTimeout(_timeout2);
};
} // Trigger focus location fetch


Expand All @@ -1184,6 +1196,7 @@ var Provider = function Provider(props) {
error: error
});
});
return noop;
}, [state.sites, state.focusLocation, state.focusLocation.fetch.status, state.neonContextHydrated, state.featureData]);
/**
Effect - trigger all data fetches and imports
Expand Down
62 changes: 31 additions & 31 deletions lib/components/SiteMap/SiteMapLeaflet.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,45 +244,45 @@ var SiteMapLeaflet = function SiteMapLeaflet() {
/**
Effect
Visually distinguish unselectable markers in the marker pane while also changing the draw order
of marker icons to put unselectable ones behind selectable ones.
of marker icons to put unselectable ones behind selectable ones. Use a 0-length setTimeout to
allow the map to complete one render cycle first.
*/

var ghostUnselectables = (0, _react.useCallback)(function () {
if (!mapRef.current || !mapRef.current.leafletElement || !mapRef.current.leafletElement._panes || !mapRef.current.leafletElement._layers || !state.selection.active || !state.selection.validSet) {
return;
}
(0, _react.useLayoutEffect)(function () {
var timeout = window.setTimeout(function () {
if (!mapRef.current || !mapRef.current.leafletElement || !mapRef.current.leafletElement._panes || !mapRef.current.leafletElement._layers || !state.selection.active || !state.selection.validSet || state.view.current !== _SiteMapUtils.VIEWS.MAP) {
return;
}

var markerPane = mapRef.current.leafletElement._panes.markerPane;
var markerPane = mapRef.current.leafletElement._panes.markerPane;

if (markerPane && markerPane.children && markerPane.children.length) {
// Unselectables: apply CSS filters to appear ghosted
_toConsumableArray(markerPane.children).filter(function (marker) {
return !state.selection.validSet.has(marker.title);
}).forEach(function (marker) {
// eslint-disable-next-line no-param-reassign
marker.style.filter = _SiteMapUtils.UNSELECTABLE_MARKER_FILTER;
}); // Selecatbles: Uniformly bump the zIndexOffset to put them all on top
if (markerPane && markerPane.children && markerPane.children.length) {
// Unselectables: apply CSS filters to appear ghosted
_toConsumableArray(markerPane.children).filter(function (marker) {
return !state.selection.validSet.has(marker.title);
}).forEach(function (marker) {
// eslint-disable-next-line no-param-reassign
marker.style.filter = _SiteMapUtils.UNSELECTABLE_MARKER_FILTER;
}); // Selecatbles: Uniformly bump the zIndexOffset to put them all on top


state.selection.validSet.forEach(function (item) {
var layerIdx = Object.keys(mapRef.current.leafletElement._layers).find(function (k) {
return mapRef.current.leafletElement._layers[k].options && mapRef.current.leafletElement._layers[k].options.title === item;
});
state.selection.validSet.forEach(function (item) {
var layerIdx = Object.keys(mapRef.current.leafletElement._layers).find(function (k) {
return mapRef.current.leafletElement._layers[k].options && mapRef.current.leafletElement._layers[k].options.title === item;
});

if (layerIdx !== -1) {
var zIndex = (mapRef.current.leafletElement._layers[layerIdx] || {})._zIndex || 0;
if (layerIdx !== -1) {
var zIndex = (mapRef.current.leafletElement._layers[layerIdx] || {})._zIndex || 0;

mapRef.current.leafletElement._layers[layerIdx].setZIndexOffset(zIndex + 1000);
}
});
}
});
(0, _react.useLayoutEffect)(ghostUnselectables, [mapRef, state.selection.hideUnselectable]); // Fire ghostUnselectables with a 0-length setTimeout when changing the view to allow the newly
// rendered map to complete one render cycle first.

(0, _react.useLayoutEffect)(function () {
window.setTimeout(ghostUnselectables, 0);
}, [state.map.bounds, state.view.current]);
mapRef.current.leafletElement._layers[layerIdx].setZIndexOffset(zIndex + 1000);
}
});
}
}, 0);
return function () {
return window.clearTimeout(timeout);
};
}, [state.selection.active, state.selection.validSet, state.selection.hideUnselectable, state.map.bounds, state.view]);
/**
Effect
Force a redraw when switching to the map for the first time from another view
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "portal-core-components",
"version": "1.5.3",
"version": "1.5.4",
"main": "./lib/index.js",
"private": true,
"homepage": "http://localhost:3010/core-components",
Expand Down Expand Up @@ -53,7 +53,8 @@
"sockjs-client": "^1.4.0",
"tinycolor2": "^1.4.1",
"typeface-inter": "^3.12.0",
"universal-cookie": "^4.0.2"
"universal-cookie": "^4.0.2",
"whatwg-fetch": "^3.4.1"
},
"devDependencies": {
"@babel/cli": "^7.8.3",
Expand Down
7 changes: 6 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,15 @@ const sidebarLinks = [
];

export default function App() {
let sidebarSubtitle = null;
if (process.env.REACT_APP_VERSION) {
sidebarSubtitle = `version ${process.env.REACT_APP_VERSION}`;
}
return (
<NeonRouter>
<NeonPage
title="Portal Core Components"
title="NEON Data Portal Core Components"
sidebarSubtitle={sidebarSubtitle}
sidebarLinks={sidebarLinks}
sidebarLinksAsStandaloneChildren
useCoreAuth
Expand Down
6 changes: 6 additions & 0 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import 'core-js/es/array';
import 'core-js/es/symbol';
import 'core-js/es/promise';
import 'core-js/es/number/is-integer';
import 'core-js/es/number/is-nan';
import 'core-js/es/number/is-finite';
import 'core-js/es/object/assign';
import 'core-js/es/object/entries';
import 'core-js/es/object/from-entries';
import 'core-js/es/object/values';
import 'core-js/es/string/includes';
import 'core-js/es/string/pad-start';
import 'core-js/es/string/starts-with';
import 'whatwg-fetch';

import React from 'react';
import ReactDOM from 'react-dom';
Expand Down
Loading

0 comments on commit 14708ac

Please sign in to comment.