@royaloperahouse/harmonic 0.6.0-a → 0.6.0-b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ISearchProps } from '../../../types/navigation';
3
- declare const Search: ({ selected, onClick, className }: ISearchProps) => React.JSX.Element;
3
+ declare const Search: React.ForwardRefExoticComponent<Pick<ISearchProps, "selected" | "onClick" | "className"> & React.RefAttributes<HTMLButtonElement>>;
4
4
  export default Search;
@@ -1,3 +1,3 @@
1
1
  import { ISearchProps } from '../../../types/navigation';
2
- export declare const SearchContainer: import("styled-components").StyledComponent<"div", any, ISearchProps, never>;
2
+ export declare const SearchContainer: import("styled-components").StyledComponent<"button", any, ISearchProps, never>;
3
3
  export declare const SvgContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { INavTopProps } from '../../../types/navigation';
3
- declare const NavTop: ({ accountText, accountLink, accountIcon, accountOptions, onLink, basketText, basketExpiryUnixTimestamp, basketLink, basketNumItems, basketNumVirtualItems, onClickSearch, isShowSearch, className, }: INavTopProps) => React.JSX.Element;
3
+ declare const NavTop: ({ accountText, accountLink, accountIcon, accountOptions, onLink, basketText, basketExpiryUnixTimestamp, basketLink, basketNumItems, basketNumVirtualItems, onClickSearch, isShowSearch, className, searchButtonRef, }: INavTopProps) => React.JSX.Element;
4
4
  export default NavTop;
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ISearchBarProps } from '../../../types/navigation';
3
- declare const SearchBar: ({ onClick, onClose, className }: ISearchBarProps) => React.JSX.Element;
3
+ declare const SearchBar: ({ onClick, onClose, className, inputRef }: ISearchBarProps) => React.JSX.Element;
4
4
  export default SearchBar;
@@ -2939,7 +2939,7 @@ var OptionsContainer = /*#__PURE__*/styled__default.div(_templateObject3 || (_te
2939
2939
 
2940
2940
  var _templateObject$7, _templateObject2$5, _templateObject3$1, _templateObject4;
2941
2941
  var ControlledDropdownWrapper = /*#__PURE__*/styled__default.div(_templateObject$7 || (_templateObject$7 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n position: relative;\n width: fit-content;\n"])));
2942
- var ControlledDropdownHeaderContainer = /*#__PURE__*/styled__default.button(_templateObject2$5 || (_templateObject2$5 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n all: unset;\n\n display: flex;\n gap: 6px;\n border-bottom: 1px solid transparent;\n height: 24px;\n line-height: 24px;\n font-size: var(--harmonic-font-size-navigation);\n font-family: var(--font-family-sans);\n font-weight: var(--font-weight-navigation);\n letter-spacing: var(--harmonic-letter-spacing-navigation);\n color: var(--color-primary-black);\n text-decoration: none;\n cursor: pointer;\n width: max-content;\n\n &:focus {\n outline: 2px solid var(--color-primary-black);\n outline-offset: 2px;\n }\n\n ", "\n"])), function (_ref) {
2942
+ var ControlledDropdownHeaderContainer = /*#__PURE__*/styled__default.button(_templateObject2$5 || (_templateObject2$5 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n all: unset;\n display: flex;\n gap: 6px;\n border-bottom: 1px solid transparent;\n height: 24px;\n line-height: 24px;\n font-size: var(--harmonic-font-size-navigation);\n font-family: var(--font-family-sans);\n font-weight: var(--font-weight-navigation);\n letter-spacing: var(--harmonic-letter-spacing-navigation);\n color: var(--color-primary-black);\n text-decoration: none;\n cursor: pointer;\n width: max-content;\n\n &:focus {\n outline: 2px solid var(--color-primary-black);\n outline-offset: 2px;\n }\n\n ", "\n"])), function (_ref) {
2943
2943
  var active = _ref.active;
2944
2944
  if (active) {
2945
2945
  return "\n & {\n color: var(--color-primary-red);\n }\n && svg path {\n fill: var(--color-primary-red);\n } \n ";
@@ -5312,7 +5312,7 @@ var Basket$1 = function Basket(_ref) {
5312
5312
  };
5313
5313
 
5314
5314
  var _templateObject$A, _templateObject2$q;
5315
- var SearchContainer = /*#__PURE__*/styled__default.div(_templateObject$A || (_templateObject$A = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n display: inline-flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n cursor: pointer;\n border-bottom: 1px solid transparent;\n padding-top: 3px;\n padding-bottom: 3px;\n\n svg path {\n fill: var(--color-primary-black);\n }\n\n ", "\n\n :hover {\n border-bottom: 1px solid var(--color-primary-red);\n && svg path {\n fill: var(--color-primary-red);\n }\n }\n"])), function (_ref) {
5315
+ var SearchContainer = /*#__PURE__*/styled__default.button(_templateObject$A || (_templateObject$A = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n all: unset;\n display: inline-flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n cursor: pointer;\n border-bottom: 1px solid transparent;\n padding-top: 3px;\n padding-bottom: 3px;\n\n svg path {\n fill: var(--color-primary-black);\n }\n\n ", "\n\n :hover {\n border-bottom: 1px solid var(--color-primary-red);\n && svg path {\n fill: var(--color-primary-red);\n }\n }\n\n &:focus {\n outline: 2px solid var(--color-primary-black);\n outline-offset: 2px;\n }\n"])), function (_ref) {
5316
5316
  var selected = _ref.selected;
5317
5317
  if (selected) {
5318
5318
  return "\n border-bottom: 1px solid var(--color-primary-red);\n && svg path {\n fill: var(--color-primary-red);\n }\n ";
@@ -5321,31 +5321,26 @@ var SearchContainer = /*#__PURE__*/styled__default.div(_templateObject$A || (_te
5321
5321
  });
5322
5322
  var SvgContainer$1 = /*#__PURE__*/styled__default.div(_templateObject2$q || (_templateObject2$q = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n svg {\n width: var(--navigation-large-gap);\n height: var(--navigation-large-gap);\n }\n"])));
5323
5323
 
5324
- var Search$1 = function Search(_ref) {
5324
+ var Search$1 = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
5325
5325
  var _ref$selected = _ref.selected,
5326
5326
  selected = _ref$selected === void 0 ? false : _ref$selected,
5327
5327
  onClick = _ref.onClick,
5328
5328
  className = _ref.className;
5329
- var onKeyDownHandler = function onKeyDownHandler(e) {
5330
- if (e.key === 'Enter') {
5331
- onClick == null || onClick();
5332
- }
5333
- };
5329
+ Search$1.displayName = 'Search';
5334
5330
  return /*#__PURE__*/React__default.createElement(SearchContainer, {
5335
- role: "button",
5336
5331
  "aria-label": "Search",
5337
5332
  selected: selected,
5338
5333
  onClick: onClick,
5339
- onKeyDown: onKeyDownHandler,
5340
5334
  "data-testid": "search-icon",
5341
5335
  tabIndex: 0,
5342
- className: className
5336
+ className: className,
5337
+ ref: ref
5343
5338
  }, /*#__PURE__*/React__default.createElement(SvgContainer$1, {
5344
5339
  "aria-hidden": "true"
5345
5340
  }, /*#__PURE__*/React__default.createElement(Icon, {
5346
5341
  iconName: "Search"
5347
5342
  })));
5348
- };
5343
+ });
5349
5344
 
5350
5345
  /* eslint-disable react/jsx-no-useless-fragment */
5351
5346
  var Dropdown = function Dropdown(_ref) {
@@ -5563,12 +5558,14 @@ var NavTop = function NavTop(_ref) {
5563
5558
  onClickSearch = _ref.onClickSearch,
5564
5559
  _ref$isShowSearch = _ref.isShowSearch,
5565
5560
  isShowSearch = _ref$isShowSearch === void 0 ? false : _ref$isShowSearch,
5566
- className = _ref.className;
5561
+ className = _ref.className,
5562
+ searchButtonRef = _ref.searchButtonRef;
5567
5563
  return /*#__PURE__*/React__default.createElement(NavTopContainer$1, {
5568
5564
  className: className
5569
5565
  }, /*#__PURE__*/React__default.createElement(Search$1, {
5570
5566
  onClick: onClickSearch,
5571
- selected: isShowSearch
5567
+ selected: isShowSearch,
5568
+ ref: searchButtonRef
5572
5569
  }), /*#__PURE__*/React__default.createElement(Basket$1, {
5573
5570
  link: basketLink,
5574
5571
  text: basketText,
@@ -5717,30 +5714,56 @@ var Tabs = function Tabs(_ref) {
5717
5714
  var _templateObject$C, _templateObject2$s, _templateObject3$i, _templateObject5$a, _templateObject6$7, _templateObject7$4;
5718
5715
  var SearchBarContainer = /*#__PURE__*/styled__default.div(_templateObject$C || (_templateObject$C = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n display: flex;\n flex-direction: row;\n column-gap: 64px;\n justify-content: space-between;\n align-items: center;\n height: 100%;\n background-color: transparent;\n\n @media ", " {\n column-gap: 12px;\n }\n"])), devices.mobile);
5719
5716
  var SvgContainerSearch = /*#__PURE__*/styled__default.div(_templateObject2$s || (_templateObject2$s = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n svg {\n width: var(--navigation-xlarge-gap);\n height: var(--navigation-xlarge-gap);\n }\n"])));
5720
- var SvgContainerClose = /*#__PURE__*/styled__default.div(_templateObject3$i || (_templateObject3$i = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n svg {\n width: var(--navigation-large-gap);\n height: var(--navigation-large-gap);\n }\n\n :hover {\n cursor: pointer;\n && svg path {\n fill: var(--color-primary-red);\n }\n }\n"])));
5717
+ var SvgContainerClose = /*#__PURE__*/styled__default.div(_templateObject3$i || (_templateObject3$i = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n as: button;\n all: unset;\n\n svg {\n width: var(--navigation-large-gap);\n height: var(--navigation-large-gap);\n }\n\n :hover {\n cursor: pointer;\n && svg path {\n fill: var(--color-primary-red);\n }\n }\n\n &:focus {\n outline: 2px solid var(--color-primary-black);\n outline-offset: 2px;\n }\n"])));
5721
5718
  var InputContainer = /*#__PURE__*/styled__default.div(_templateObject5$a || (_templateObject5$a = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n background-color: blue;\n width: 100%;\n\n input {\n font-size: var(--font-size-search);\n font-family: var(--font-family-serif);\n border: none;\n border-radius: 0;\n outline: none;\n outline-color: var(--color-base-white);\n height: 48px;\n box-sizing: border-box;\n width: 100%;\n -webkit-appearance: none;\n\n &.search-input {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n @media ", " {\n column-gap: 24px;\n }\n }\n"])), devices.mobile);
5722
5719
  var TextLinkWrapper$1 = /*#__PURE__*/styled__default(TextLink)(_templateObject6$7 || (_templateObject6$7 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n color: var(--color-primary-red);\n"])));
5723
5720
  var SearchArrowContainer = /*#__PURE__*/styled__default.a(_templateObject7$4 || (_templateObject7$4 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n padding-right: 8px;\n\n svg {\n width: var(--navigation-large-gap);\n height: var(--navigation-large-gap);\n }\n"])));
5724
5721
 
5722
+ function useFocusTrap(containerRef, onEscape) {
5723
+ React.useEffect(function () {
5724
+ var container = containerRef.current;
5725
+ if (!container) return undefined;
5726
+ var focusableSelectors = 'input, button, select, textarea, a[href], [tabindex]:not([tabindex="-1"])';
5727
+ var focusableEls = container.querySelectorAll(focusableSelectors);
5728
+ var firstEl = focusableEls[0];
5729
+ var lastEl = focusableEls[focusableEls.length - 1];
5730
+ var handleKeyDown = function handleKeyDown(e) {
5731
+ if (e.key === 'Tab') {
5732
+ if (focusableEls.length === 0) return;
5733
+ if (e.shiftKey && document.activeElement === firstEl) {
5734
+ e.preventDefault();
5735
+ lastEl == null || lastEl.focus();
5736
+ } else if (!e.shiftKey && document.activeElement === lastEl) {
5737
+ e.preventDefault();
5738
+ firstEl == null || firstEl.focus();
5739
+ }
5740
+ }
5741
+ if (e.key === 'Escape') {
5742
+ onEscape == null || onEscape();
5743
+ }
5744
+ };
5745
+ document.addEventListener('keydown', handleKeyDown);
5746
+ return function () {
5747
+ return document.removeEventListener('keydown', handleKeyDown);
5748
+ };
5749
+ }, [containerRef, onEscape]);
5750
+ }
5751
+
5725
5752
  var SearchBar = function SearchBar(_ref) {
5726
5753
  var onClick = _ref.onClick,
5727
5754
  onClose = _ref.onClose,
5728
- className = _ref.className;
5755
+ className = _ref.className,
5756
+ inputRef = _ref.inputRef;
5729
5757
  var _useState = React.useState(false),
5730
5758
  showSearchLink = _useState[0],
5731
5759
  setShowSearchLink = _useState[1];
5732
5760
  var _useState2 = React.useState(''),
5733
5761
  searchValue = _useState2[0],
5734
5762
  setSearchValue = _useState2[1];
5735
- var inputRef = React.useRef(null);
5736
- React.useEffect(function () {
5737
- var _inputRef$current;
5738
- inputRef == null || (_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
5739
- return function () {
5740
- var _inputRef$current2;
5741
- return inputRef == null || (_inputRef$current2 = inputRef.current) == null ? void 0 : _inputRef$current2.blur();
5742
- };
5743
- }, [inputRef]);
5763
+ var internalRef = React.useRef(null);
5764
+ var finalInputRef = inputRef != null ? inputRef : internalRef;
5765
+ var containerRef = React.useRef(null);
5766
+ useFocusTrap(containerRef, onClose);
5744
5767
  var onSearchHandler = function onSearchHandler(value) {
5745
5768
  onClick(value);
5746
5769
  setSearchValue('');
@@ -5776,12 +5799,13 @@ var SearchBar = function SearchBar(_ref) {
5776
5799
  var _useViewport = useViewport(),
5777
5800
  isDesktop = _useViewport.isDesktop;
5778
5801
  return /*#__PURE__*/React__default.createElement(SearchBarContainer, {
5779
- className: className
5802
+ className: className,
5803
+ ref: containerRef
5780
5804
  }, /*#__PURE__*/React__default.createElement(SvgContainerSearch, null, /*#__PURE__*/React__default.createElement(Icon, {
5781
5805
  iconName: "Search"
5782
5806
  })), /*#__PURE__*/React__default.createElement(InputContainer, null, /*#__PURE__*/React__default.createElement("input", {
5783
5807
  "data-testid": "input-html",
5784
- ref: inputRef,
5808
+ ref: finalInputRef,
5785
5809
  className: "search-input",
5786
5810
  placeholder: "Search the website...",
5787
5811
  type: "text",
@@ -5814,7 +5838,8 @@ var SearchBar = function SearchBar(_ref) {
5814
5838
  tabIndex: 0,
5815
5839
  onClick: onCloseHandler,
5816
5840
  onKeyDown: onKeyboardCloseHandler,
5817
- "data-testid": "close-icon"
5841
+ "data-testid": "close-icon",
5842
+ "aria-label": "Close search bar"
5818
5843
  }, /*#__PURE__*/React__default.createElement(Icon, {
5819
5844
  iconName: "Close"
5820
5845
  })));
@@ -5831,6 +5856,8 @@ var Navigation = function Navigation(_ref) {
5831
5856
  crest = _ref$crest === void 0 ? false : _ref$crest,
5832
5857
  className = _ref.className,
5833
5858
  logoLink = _ref.logoLink;
5859
+ var searchInputRef = React.useRef(null);
5860
+ var searchButtonRef = React.useRef(null);
5834
5861
  var _useState = React.useState(dataNavTop),
5835
5862
  navTopData = _useState[0],
5836
5863
  setNavTopData = _useState[1];
@@ -5863,9 +5890,7 @@ var Navigation = function Navigation(_ref) {
5863
5890
  setNavTopData(dataNavTop);
5864
5891
  }, [dataNavTop]);
5865
5892
  var onClickSearchHandler = function onClickSearchHandler() {
5866
- setshowSearch(function (prev) {
5867
- return !prev;
5868
- });
5893
+ setshowSearch(true);
5869
5894
  };
5870
5895
  var onLinkHandler = function onLinkHandler(link) {
5871
5896
  onLink(link);
@@ -5882,7 +5907,23 @@ var Navigation = function Navigation(_ref) {
5882
5907
  };
5883
5908
  var onCloseSearchHandler = function onCloseSearchHandler() {
5884
5909
  setshowSearch(false);
5910
+ setTimeout(function () {
5911
+ var _searchButtonRef$curr;
5912
+ (_searchButtonRef$curr = searchButtonRef.current) == null || _searchButtonRef$curr.focus();
5913
+ }, 0);
5885
5914
  };
5915
+ React.useEffect(function () {
5916
+ if (showSearch) {
5917
+ var timer = setTimeout(function () {
5918
+ var _searchInputRef$curre;
5919
+ (_searchInputRef$curre = searchInputRef.current) == null || _searchInputRef$curre.focus();
5920
+ }, 50);
5921
+ return function () {
5922
+ return clearTimeout(timer);
5923
+ };
5924
+ }
5925
+ return undefined;
5926
+ }, [showSearch]);
5886
5927
  var _useViewport = useViewport(),
5887
5928
  isMobile = _useViewport.isMobile;
5888
5929
  return /*#__PURE__*/React__default.createElement(NavigationWrapper, {
@@ -5924,7 +5965,8 @@ var Navigation = function Navigation(_ref) {
5924
5965
  basketNumVirtualItems: navTopData.basketNumVirtualItems,
5925
5966
  onClickSearch: onClickSearchHandler,
5926
5967
  onLink: onLinkHandler,
5927
- isShowSearch: showSearch
5968
+ isShowSearch: showSearch,
5969
+ searchButtonRef: searchButtonRef
5928
5970
  }))))), /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(SearchBackground, {
5929
5971
  visible: showSearch
5930
5972
  }), /*#__PURE__*/React__default.createElement(GridItemSearch, {
@@ -5935,6 +5977,7 @@ var Navigation = function Navigation(_ref) {
5935
5977
  columnStartDevice: 2,
5936
5978
  columnSpanDevice: 12
5937
5979
  }, /*#__PURE__*/React__default.createElement(SearchBar, {
5980
+ inputRef: searchInputRef,
5938
5981
  onClick: onSearchHandler,
5939
5982
  onClose: onCloseSearchHandler
5940
5983
  })))), showMenu && (/*#__PURE__*/React__default.createElement(NavigationGridMobile, {