Skip to content

Commit 14708ac

Browse files
committed
IE polyfills; sticky sidebar improvements
1 parent 39effc4 commit 14708ac

File tree

12 files changed

+206
-123
lines changed

12 files changed

+206
-123
lines changed

.env.development

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
PORT=3010
2+
REACT_APP_VERSION=$npm_package_version
23
REACT_APP_NEON_API_NAME="api"
34
REACT_APP_NEON_API_VERSION="v0"
45

.env.production

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
REACT_APP_VERSION=$npm_package_version
12
REACT_APP_NEON_API_NAME="api"
23
REACT_APP_NEON_API_VERSION="v0"
34

lib/components/NeonPage/NeonPage.js

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ var NeonPage = function NeonPage(props) {
296296
var headerRef = (0, _react.useRef)(null);
297297
var contentRef = (0, _react.useRef)(null);
298298
var sidebarRef = (0, _react.useRef)(null);
299+
var sidebarLinksContainerRef = (0, _react.useRef)(null);
299300
var belowMd = (0, _useMediaQuery.default)(_Theme.default.breakpoints.down('sm'));
300301
/**
301302
Sidebar Setup
@@ -312,9 +313,9 @@ var NeonPage = function NeonPage(props) {
312313
var sidebarHashMap = !hasSidebarLinks ? {} : Object.fromEntries(sidebarLinks.map(function (link, idx) {
313314
return [link.hash || '#', idx];
314315
}));
315-
var initialCurrectSidebarHash = hasSidebarLinks ? sidebarLinks[0].hash || '#' : '#';
316+
var initialCurrentSidebarHash = hasSidebarLinks ? sidebarLinks[0].hash || '#' : '#';
316317

317-
var _useState = (0, _react.useState)(initialCurrectSidebarHash),
318+
var _useState = (0, _react.useState)(initialCurrentSidebarHash),
318319
_useState2 = _slicedToArray(_useState, 2),
319320
currentSidebarHash = _useState2[0],
320321
setCurrentSidebarHash = _useState2[1];
@@ -345,12 +346,31 @@ var NeonPage = function NeonPage(props) {
345346

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

350354
(0, _react.useLayoutEffect)(function () {
351355
if (error || loading || !hasSidebarLinks) {
352356
return function () {};
353-
} // Handle URL-defined hash on initial load
357+
}
358+
359+
var handleHashChange = function handleHashChange() {
360+
var hash = document.location.hash;
361+
362+
if (currentSidebarHash === hash) {
363+
return;
364+
}
365+
366+
setCurrentSidebarHash(hash); // If standard sidebar mode (scroll to content) also perform the scroll offset here
367+
368+
if (!sidebarLinksAsStandaloneChildren) {
369+
window.setTimeout(function () {
370+
window.scrollTo(0, getSidebarLinkScrollPosition(hash));
371+
}, 0);
372+
}
373+
}; // Handle URL-defined hash on initial load
354374

355375

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

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

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

367-
if (!sidebarLinksAsStandaloneChildren) {
368-
window.setTimeout(function () {
369-
window.scrollTo(0, getSidebarLinkScrollPosition(hash));
370-
}, 0);
371-
}
372-
}
373-
374-
setHashInitialized(true);
375-
} // Set up event listener / handler for user-input scroll events for standard scrolling pages
388+
if (!sidebarUnsticky && hasSidebarLinks && sidebarLinksContainerRef.current) {
389+
var maxHeight = window.innerHeight - sidebarLinksContainerRef.current.offsetTop - 104;
390+
sidebarLinksContainerRef.current.style.maxHeight = "".concat(maxHeight, "px");
391+
} // For sidebarLinksAsStandaloneChildren listen for hash changes to trigger a "redirect".
376392

377393

378394
if (sidebarLinksAsStandaloneChildren) {
379-
return function () {};
380-
}
395+
window.addEventListener('hashchange', handleHashChange);
396+
return function () {
397+
window.removeEventListener('hashchange', handleHashChange);
398+
};
399+
} // Set up event listener / handler for user-input scroll events for standard scrolling pages
400+
381401

382402
var handleScroll = function handleScroll() {
383403
var scrollBreaks = sidebarLinks.map(function (link) {
@@ -403,9 +423,9 @@ var NeonPage = function NeonPage(props) {
403423
return function () {
404424
window.removeEventListener('scroll', handleScroll);
405425
};
406-
}, [error, loading, hasSidebarLinks, sidebarLinks, sidebarHashMap, hashInitialized, setHashInitialized, currentSidebarHash, setCurrentSidebarHash, getSidebarLinkScrollPosition, sidebarLinksAsStandaloneChildren]);
426+
}, [error, loading, sidebarUnsticky, hasSidebarLinks, sidebarLinks, sidebarHashMap, hashInitialized, setHashInitialized, currentSidebarHash, setCurrentSidebarHash, sidebarLinksContainerRef, getSidebarLinkScrollPosition, sidebarLinksAsStandaloneChildren]);
407427
/**
408-
Drupal CSS Loading
428+
Effect - Load Drupal CSS
409429
*/
410430

411431
var _useState7 = (0, _react.useState)(false),
@@ -501,6 +521,10 @@ var NeonPage = function NeonPage(props) {
501521
});
502522
}));
503523
};
524+
/**
525+
Effect - Fetch notifications
526+
*/
527+
504528

505529
(0, _react.useEffect)(function () {
506530
if (fetchNotificationsStatus !== null) {
@@ -706,6 +730,7 @@ var NeonPage = function NeonPage(props) {
706730
};
707731

708732
var fullLinks = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
733+
ref: sidebarLinksContainerRef,
709734
className: classes.sidebarLinksContainer
710735
}, sidebarLinks.map(function (link) {
711736
return renderLink(link);

lib/components/SiteMap/SiteMapContext.js

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,12 +1103,14 @@ var Provider = function Provider(props) {
11031103
*/
11041104

11051105
(0, _react.useEffect)(function () {
1106+
var noop = function noop() {};
1107+
11061108
var _state$focusLocation = state.focusLocation,
11071109
current = _state$focusLocation.current,
11081110
currentStatus = _state$focusLocation.fetch.status;
11091111

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

11141116

@@ -1122,7 +1124,7 @@ var Provider = function Provider(props) {
11221124
var _statesData$current$c = statesData[current].center,
11231125
latitude = _statesData$current$c[0],
11241126
longitude = _statesData$current$c[1];
1125-
window.setTimeout(function () {
1127+
var timeout = window.setTimeout(function () {
11261128
dispatch({
11271129
type: 'setFocusLocationFetchSucceeded',
11281130
data: {
@@ -1132,14 +1134,17 @@ var Provider = function Provider(props) {
11321134
}
11331135
});
11341136
}, 0);
1135-
return;
1137+
return function () {
1138+
return window.clearTimeout(timeout);
1139+
};
11361140
}
11371141

11381142
if (Object.keys(domainsData).includes(current)) {
11391143
var _domainsData$current$ = domainsData[current].center,
11401144
_latitude = _domainsData$current$[0],
11411145
_longitude = _domainsData$current$[1];
1142-
window.setTimeout(function () {
1146+
1147+
var _timeout = window.setTimeout(function () {
11431148
dispatch({
11441149
type: 'setFocusLocationFetchSucceeded',
11451150
data: {
@@ -1149,14 +1154,18 @@ var Provider = function Provider(props) {
11491154
}
11501155
});
11511156
}, 0);
1152-
return;
1157+
1158+
return function () {
1159+
return window.clearTimeout(_timeout);
1160+
};
11531161
}
11541162

11551163
if (Object.keys(state.sites).includes(current)) {
11561164
var _state$sites$current = state.sites[current],
11571165
_latitude2 = _state$sites$current.latitude,
11581166
_longitude2 = _state$sites$current.longitude;
1159-
window.setTimeout(function () {
1167+
1168+
var _timeout2 = window.setTimeout(function () {
11601169
dispatch({
11611170
type: 'setFocusLocationFetchSucceeded',
11621171
data: {
@@ -1166,7 +1175,10 @@ var Provider = function Provider(props) {
11661175
}
11671176
});
11681177
}, 0);
1169-
return;
1178+
1179+
return function () {
1180+
return window.clearTimeout(_timeout2);
1181+
};
11701182
} // Trigger focus location fetch
11711183

11721184

@@ -1184,6 +1196,7 @@ var Provider = function Provider(props) {
11841196
error: error
11851197
});
11861198
});
1199+
return noop;
11871200
}, [state.sites, state.focusLocation, state.focusLocation.fetch.status, state.neonContextHydrated, state.featureData]);
11881201
/**
11891202
Effect - trigger all data fetches and imports

lib/components/SiteMap/SiteMapLeaflet.js

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -244,45 +244,45 @@ var SiteMapLeaflet = function SiteMapLeaflet() {
244244
/**
245245
Effect
246246
Visually distinguish unselectable markers in the marker pane while also changing the draw order
247-
of marker icons to put unselectable ones behind selectable ones.
247+
of marker icons to put unselectable ones behind selectable ones. Use a 0-length setTimeout to
248+
allow the map to complete one render cycle first.
248249
*/
249250

250-
var ghostUnselectables = (0, _react.useCallback)(function () {
251-
if (!mapRef.current || !mapRef.current.leafletElement || !mapRef.current.leafletElement._panes || !mapRef.current.leafletElement._layers || !state.selection.active || !state.selection.validSet) {
252-
return;
253-
}
251+
(0, _react.useLayoutEffect)(function () {
252+
var timeout = window.setTimeout(function () {
253+
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) {
254+
return;
255+
}
254256

255-
var markerPane = mapRef.current.leafletElement._panes.markerPane;
257+
var markerPane = mapRef.current.leafletElement._panes.markerPane;
256258

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

266268

267-
state.selection.validSet.forEach(function (item) {
268-
var layerIdx = Object.keys(mapRef.current.leafletElement._layers).find(function (k) {
269-
return mapRef.current.leafletElement._layers[k].options && mapRef.current.leafletElement._layers[k].options.title === item;
270-
});
269+
state.selection.validSet.forEach(function (item) {
270+
var layerIdx = Object.keys(mapRef.current.leafletElement._layers).find(function (k) {
271+
return mapRef.current.leafletElement._layers[k].options && mapRef.current.leafletElement._layers[k].options.title === item;
272+
});
271273

272-
if (layerIdx !== -1) {
273-
var zIndex = (mapRef.current.leafletElement._layers[layerIdx] || {})._zIndex || 0;
274+
if (layerIdx !== -1) {
275+
var zIndex = (mapRef.current.leafletElement._layers[layerIdx] || {})._zIndex || 0;
274276

275-
mapRef.current.leafletElement._layers[layerIdx].setZIndexOffset(zIndex + 1000);
276-
}
277-
});
278-
}
279-
});
280-
(0, _react.useLayoutEffect)(ghostUnselectables, [mapRef, state.selection.hideUnselectable]); // Fire ghostUnselectables with a 0-length setTimeout when changing the view to allow the newly
281-
// rendered map to complete one render cycle first.
282-
283-
(0, _react.useLayoutEffect)(function () {
284-
window.setTimeout(ghostUnselectables, 0);
285-
}, [state.map.bounds, state.view.current]);
277+
mapRef.current.leafletElement._layers[layerIdx].setZIndexOffset(zIndex + 1000);
278+
}
279+
});
280+
}
281+
}, 0);
282+
return function () {
283+
return window.clearTimeout(timeout);
284+
};
285+
}, [state.selection.active, state.selection.validSet, state.selection.hideUnselectable, state.map.bounds, state.view]);
286286
/**
287287
Effect
288288
Force a redraw when switching to the map for the first time from another view

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "portal-core-components",
3-
"version": "1.5.3",
3+
"version": "1.5.4",
44
"main": "./lib/index.js",
55
"private": true,
66
"homepage": "http://localhost:3010/core-components",
@@ -53,7 +53,8 @@
5353
"sockjs-client": "^1.4.0",
5454
"tinycolor2": "^1.4.1",
5555
"typeface-inter": "^3.12.0",
56-
"universal-cookie": "^4.0.2"
56+
"universal-cookie": "^4.0.2",
57+
"whatwg-fetch": "^3.4.1"
5758
},
5859
"devDependencies": {
5960
"@babel/cli": "^7.8.3",

src/App.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,15 @@ const sidebarLinks = [
133133
];
134134

135135
export default function App() {
136+
let sidebarSubtitle = null;
137+
if (process.env.REACT_APP_VERSION) {
138+
sidebarSubtitle = `version ${process.env.REACT_APP_VERSION}`;
139+
}
136140
return (
137141
<NeonRouter>
138142
<NeonPage
139-
title="Portal Core Components"
143+
title="NEON Data Portal Core Components"
144+
sidebarSubtitle={sidebarSubtitle}
140145
sidebarLinks={sidebarLinks}
141146
sidebarLinksAsStandaloneChildren
142147
useCoreAuth

src/index.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import 'core-js/es/array';
55
import 'core-js/es/symbol';
66
import 'core-js/es/promise';
77
import 'core-js/es/number/is-integer';
8+
import 'core-js/es/number/is-nan';
9+
import 'core-js/es/number/is-finite';
810
import 'core-js/es/object/assign';
11+
import 'core-js/es/object/entries';
12+
import 'core-js/es/object/from-entries';
913
import 'core-js/es/object/values';
14+
import 'core-js/es/string/includes';
1015
import 'core-js/es/string/pad-start';
1116
import 'core-js/es/string/starts-with';
17+
import 'whatwg-fetch';
1218

1319
import React from 'react';
1420
import ReactDOM from 'react-dom';

0 commit comments

Comments
 (0)