@reykjavik/hanna-react 0.10.113 → 0.10.115

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.
Files changed (125) hide show
  1. package/AccordionList.js +1 -1
  2. package/AutosuggestSearch.d.ts +6 -0
  3. package/AutosuggestSearch.js +19 -3
  4. package/BasicTable.js +4 -4
  5. package/BgBox.d.ts +5 -2
  6. package/BgBox.js +1 -1
  7. package/Bling.js +4 -4
  8. package/CHANGELOG.md +16 -0
  9. package/Carousel.d.ts +1 -1
  10. package/CarouselStepper.js +2 -2
  11. package/CheckboxButton.d.ts +1 -1
  12. package/CityBlock.js +1 -1
  13. package/ContactBubble.js +5 -3
  14. package/Datepicker.js +2 -1
  15. package/FileInput/_FileInput.utils.js +1 -1
  16. package/FileInput.js +6 -7
  17. package/Form.js +1 -1
  18. package/FormField.d.ts +2 -2
  19. package/FormField.js +1 -1
  20. package/Heading.js +1 -1
  21. package/IframeBlock.js +1 -1
  22. package/InfoHero.js +1 -1
  23. package/IslandBlock.js +1 -1
  24. package/IslandPageBlock.js +1 -1
  25. package/MainMenu.js +3 -1
  26. package/MainMenu2.js +3 -2
  27. package/MobileMenuToggler/_useMobileMenuToggling.js +1 -1
  28. package/Multiselect/_Multiselect.search.d.ts +5 -3
  29. package/Multiselect/_Multiselect.search.js +4 -5
  30. package/Multiselect.d.ts +5 -0
  31. package/Multiselect.js +1 -2
  32. package/NameCard.js +1 -1
  33. package/PageHeading.js +1 -1
  34. package/Pagination.js +2 -2
  35. package/Radio.d.ts +3 -0
  36. package/Radio.js +8 -0
  37. package/RadioGroup.d.ts +1 -7
  38. package/RadioGroup.js +2 -5
  39. package/SearchResults/_SearchResultsItem.js +5 -5
  40. package/SearchResults.js +1 -3
  41. package/ShareButtons.js +3 -3
  42. package/SiteSearchAutocomplete.js +6 -6
  43. package/Skeleton.js +1 -1
  44. package/SubHeading.js +1 -1
  45. package/TextInput.js +2 -1
  46. package/VSpacer.js +1 -1
  47. package/VerticalTabsTOC.js +1 -1
  48. package/_abstract/_AbstractCarousel.d.ts +2 -2
  49. package/_abstract/_AbstractCarousel.js +5 -5
  50. package/_abstract/_AbstractModal.js +1 -0
  51. package/_abstract/_Blings.js +1 -1
  52. package/_abstract/_CardList.js +5 -5
  53. package/_abstract/_Quote.js +2 -2
  54. package/_abstract/_Table.js +2 -2
  55. package/_abstract/_TogglerGroup.js +1 -1
  56. package/_abstract/_TogglerInput.d.ts +1 -0
  57. package/_abstract/_TogglerInput.js +10 -9
  58. package/esm/AccordionList.js +1 -1
  59. package/esm/AutosuggestSearch.d.ts +6 -0
  60. package/esm/AutosuggestSearch.js +19 -3
  61. package/esm/BasicTable.js +4 -4
  62. package/esm/BgBox.d.ts +5 -2
  63. package/esm/BgBox.js +1 -1
  64. package/esm/Bling.js +4 -4
  65. package/esm/Carousel.d.ts +1 -1
  66. package/esm/CarouselStepper.js +2 -2
  67. package/esm/CheckboxButton.d.ts +1 -1
  68. package/esm/CityBlock.js +1 -1
  69. package/esm/ContactBubble.js +5 -3
  70. package/esm/Datepicker.js +2 -1
  71. package/esm/FileInput/_FileInput.utils.js +1 -1
  72. package/esm/FileInput.js +6 -7
  73. package/esm/Form.js +1 -1
  74. package/esm/FormField.d.ts +2 -2
  75. package/esm/FormField.js +1 -1
  76. package/esm/Heading.js +1 -1
  77. package/esm/IframeBlock.js +1 -1
  78. package/esm/InfoHero.js +1 -1
  79. package/esm/IslandBlock.js +1 -1
  80. package/esm/IslandPageBlock.js +1 -1
  81. package/esm/MainMenu.js +3 -1
  82. package/esm/MainMenu2.js +3 -2
  83. package/esm/MobileMenuToggler/_useMobileMenuToggling.js +1 -1
  84. package/esm/Multiselect/_Multiselect.search.d.ts +5 -3
  85. package/esm/Multiselect/_Multiselect.search.js +4 -5
  86. package/esm/Multiselect.d.ts +5 -0
  87. package/esm/Multiselect.js +1 -2
  88. package/esm/NameCard.js +1 -1
  89. package/esm/PageHeading.js +1 -1
  90. package/esm/Pagination.js +2 -2
  91. package/esm/Radio.d.ts +3 -0
  92. package/esm/Radio.js +3 -0
  93. package/esm/RadioGroup.d.ts +1 -7
  94. package/esm/RadioGroup.js +1 -4
  95. package/esm/SearchResults/_SearchResultsItem.js +5 -5
  96. package/esm/SearchResults.js +1 -3
  97. package/esm/ShareButtons.js +3 -3
  98. package/esm/SiteSearchAutocomplete.js +6 -6
  99. package/esm/Skeleton.js +1 -1
  100. package/esm/SubHeading.js +1 -1
  101. package/esm/TextInput.js +2 -1
  102. package/esm/VSpacer.js +1 -1
  103. package/esm/VerticalTabsTOC.js +1 -1
  104. package/esm/_abstract/_AbstractCarousel.d.ts +2 -2
  105. package/esm/_abstract/_AbstractCarousel.js +5 -5
  106. package/esm/_abstract/_AbstractModal.js +1 -0
  107. package/esm/_abstract/_Blings.js +1 -1
  108. package/esm/_abstract/_CardList.js +5 -5
  109. package/esm/_abstract/_Quote.js +2 -2
  110. package/esm/_abstract/_Table.js +2 -2
  111. package/esm/_abstract/_TogglerGroup.js +1 -1
  112. package/esm/_abstract/_TogglerInput.d.ts +1 -0
  113. package/esm/_abstract/_TogglerInput.js +10 -9
  114. package/esm/index.d.ts +1 -0
  115. package/esm/utils/browserSide.js +2 -6
  116. package/esm/utils/seenEffect.js +2 -2
  117. package/esm/utils/useLaggedState.js +1 -1
  118. package/esm/utils/useMixedControlState.js +9 -15
  119. package/esm/utils/useShortState.js +4 -1
  120. package/index.d.ts +1 -0
  121. package/package.json +7 -3
  122. package/utils/browserSide.js +2 -6
  123. package/utils/seenEffect.js +2 -2
  124. package/utils/useMixedControlState.js +9 -15
  125. package/utils/useShortState.js +4 -1
package/AccordionList.js CHANGED
@@ -18,7 +18,7 @@ const AccordionListItem = (props) => {
18
18
  };
19
19
  const AccordionList = (props) => {
20
20
  const { items, ssr, wide, defaultOpen, wrapperProps } = props;
21
- const [open, setOpenArray, mode] = (0, utils_js_1.useMixedControlState)(props, 'open', []);
21
+ const [open, setOpenArray /*, mode */] = (0, utils_js_1.useMixedControlState)(props, 'open', []);
22
22
  const onToggle = (index) => {
23
23
  setOpenArray((prevOpen) => {
24
24
  const opened = !prevOpen.includes(index);
@@ -18,8 +18,13 @@ export type AutosuggestSearchI18n = {
18
18
  lang?: string;
19
19
  };
20
20
  export declare const defaultAutosuggestSearchTexts: DefaultTexts<AutosuggestSearchI18n>;
21
+ type EmptyMessage = {
22
+ message: string | JSX.Element;
23
+ type: 'empty' | 'loading';
24
+ };
21
25
  export type AutosuggestSearchProps<T extends string | object> = {
22
26
  options: Array<T>;
27
+ emptyMessage?: EmptyMessage | EmptyMessage['message'];
23
28
  onInput: (value: string) => void;
24
29
  onSelected: (payload: {
25
30
  value: string;
@@ -38,3 +43,4 @@ export type AutosuggestSearchProps<T extends string | object> = {
38
43
  lang?: HannaLang;
39
44
  } & Pick<SearchInputProps, 'onSubmit' | 'onButtonClick' | 'button'> & WrapperElmProps;
40
45
  export declare const AutosuggestSearch: <T extends string | object>(props: AutosuggestSearchProps<T>) => JSX.Element;
46
+ export {};
@@ -31,7 +31,7 @@ exports.defaultAutosuggestSearchTexts = {
31
31
  },
32
32
  };
33
33
  const AutosuggestSearch = (props) => {
34
- const { options, itemActionIcon, onInput, onSelected, onClearOptions, onSubmit, onButtonClick = onSubmit, button, getOptionValue = (opt) => typeof opt !== 'object' || !('value' in opt)
34
+ const { options, emptyMessage, itemActionIcon, onInput, onSelected, onClearOptions, onSubmit, onButtonClick = onSubmit, button, getOptionValue = (opt) => typeof opt !== 'object' || !('value' in opt)
35
35
  ? opt.toString()
36
36
  : opt.value != null
37
37
  ? opt.value.toString()
@@ -41,6 +41,7 @@ const AutosuggestSearch = (props) => {
41
41
  const [value, setValue] = (0, react_1.useState)('');
42
42
  const inputRef = (0, react_1.useRef)(null);
43
43
  const txt = (0, i18n_1.getTexts)(props, exports.defaultAutosuggestSearchTexts);
44
+ const showEmptyMessage = !options.length && emptyMessage;
44
45
  return (react_1.default.createElement(react_autosuggest_1.default, { theme: {
45
46
  container: 'AutosuggestSearch',
46
47
  containerOpen: 'AutosuggestSearch--open',
@@ -49,11 +50,26 @@ const AutosuggestSearch = (props) => {
49
50
  suggestionsList: (0, classUtils_1.modifiedClass)('AutosuggestSearch__list', itemActionIcon && `action--${itemActionIcon}`),
50
51
  suggestion: 'AutosuggestSearch__item',
51
52
  suggestionHighlighted: 'AutosuggestSearch__item--highlighted',
52
- }, focusInputOnSuggestionClick: true, suggestions: options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ({ value }) => onInput(value), getSuggestionValue: getOptionValue, onSuggestionSelected: (_event, data) => {
53
+ }, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ({ value }) => onInput(value), getSuggestionValue: showEmptyMessage
54
+ ? () => value // Return the input value in case the user uses the up/down keys to select the hidden empty message
55
+ : getOptionValue, onSuggestionSelected: (event, data) => {
56
+ if (showEmptyMessage) {
57
+ event.preventDefault();
58
+ return;
59
+ }
53
60
  onSelected({ value: data.suggestionValue, option: data.suggestion });
54
61
  },
55
62
  // onSuggestionHighlighted={onSuggestionHighlighted}
56
- renderSuggestion: renderSuggestion, containerProps: Object.assign(Object.assign({}, wrapperProps), { 'aria-label': txt.label }), renderSuggestionsContainer: ({ containerProps, children }) => (react_1.default.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), children)), inputProps: {
63
+ renderSuggestion: showEmptyMessage ? () => '' : renderSuggestion, containerProps: Object.assign(Object.assign({}, wrapperProps), { 'aria-label': txt.label }), renderSuggestionsContainer: ({ containerProps, children }) => {
64
+ let contents = children;
65
+ if (showEmptyMessage) {
66
+ const { message, type } = typeof emptyMessage === 'string' || !('message' in emptyMessage)
67
+ ? { message: emptyMessage, type: 'empty' }
68
+ : emptyMessage;
69
+ contents = (react_1.default.createElement("div", { className: (0, classUtils_1.modifiedClass)('AutosuggestSearch__emptyMessage', type !== 'empty' && type) }, message));
70
+ }
71
+ return (react_1.default.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
72
+ }, inputProps: {
57
73
  ref: inputRef,
58
74
  value: value,
59
75
  onChange: (_, { newValue }) => {
package/BasicTable.js CHANGED
@@ -11,15 +11,15 @@ const tableTypes = {
11
11
  number: 'data--number',
12
12
  };
13
13
  const BasicTable = (props) => {
14
- // eslint-disable-next-line deprecation/deprecation
15
- const { align, fullWidth, type, tbody, tbodies, modifier, thead, tfoot, tableProps, caption, rowProps, compact, cols, wrapperProps, } = props;
14
+ const { align, fullWidth, type, tbody, tbodies, modifier, // eslint-disable-line deprecation/deprecation
15
+ thead, tfoot, tableProps, caption, rowProps, compact, cols, wrapperProps, } = props;
16
16
  return (react_1.default.createElement(_ScrollWrapper_js_1.ScrollWrapper, { bem: "TableWrapper", modifier: [
17
17
  'BasicTable',
18
- modifier && 'BasicTable--' + modifier,
18
+ modifier && `BasicTable--${modifier}`,
19
19
  fullWidth
20
20
  ? 'BasicTable--fullwidth'
21
21
  : align === 'right'
22
- ? 'BasicTable--align--' + align
22
+ ? `BasicTable--align--${align}`
23
23
  : undefined,
24
24
  ], wrapperProps: wrapperProps },
25
25
  react_1.default.createElement(_Table_js_1.Table, Object.assign({ className: (0, classUtils_1.modifiedClass)('BasicTable', [
package/BgBox.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { ReactNode } from 'react';
2
- import { DeprecatedSeenProp, EffectProp } from './utils/seenEffect.js';
2
+ import { DeprecatedSeenProp } from './utils/seenEffect.js';
3
3
  import { WrapperElmProps } from './utils.js';
4
4
  export type BgBoxProps = {
5
5
  className?: string;
6
6
  children: ReactNode;
7
- } & WrapperElmProps & DeprecatedSeenProp & EffectProp;
7
+ } & WrapperElmProps & DeprecatedSeenProp & {
8
+ /** @deprecated This prop does nothing nowadays (Will be removed in v0.11) */
9
+ effectType?: string;
10
+ };
8
11
  export declare const BgBox: (props: BgBoxProps) => JSX.Element;
9
12
  export default BgBox;
package/BgBox.js CHANGED
@@ -5,7 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const classUtils_1 = require("@hugsmidjan/qj/classUtils");
7
7
  const BgBox = (props) => {
8
- const { className, children, effectType, wrapperProps } = props;
8
+ const { className, children, wrapperProps } = props;
9
9
  return (react_1.default.createElement("div", Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('BgBox', undefined,
10
10
  // Prefer `className` over `wrapperProps.className`
11
11
  className || (wrapperProps || {}).className) }), children));
package/Bling.js CHANGED
@@ -38,10 +38,10 @@ const Bling = (props) => {
38
38
  const imageUrl = type ? (0, assets_1.getBlingUrl)(type) : blingUrl;
39
39
  const inlineSvg = (0, useGetSVGtext_js_1.useGetSVGtext)(imageUrl);
40
40
  return (react_1.default.createElement("div", Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('Bling', [
41
- 'align--' + (align && align in aligns ? align : 'left'),
42
- vertical && vertical in valigns && 'vertical--' + vertical,
43
- color && color in colors && 'color--' + color,
44
- parent && parent in parentOffset && 'parent--' + parent,
41
+ `align--${align && align in aligns ? align : 'left'}`,
42
+ vertical && vertical in valigns && `vertical--${vertical}`,
43
+ color && color in colors && `color--${color}`,
44
+ parent && parent in parentOffset && `parent--${parent}`,
45
45
  overlay && 'overlay',
46
46
  ],
47
47
  // Prefer `className` over `wrapperProps.className`
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@
4
4
 
5
5
  - ... <!-- Add new lines here. -->
6
6
 
7
+ ## 0.10.115
8
+
9
+ _2024-01-09_
10
+
11
+ - feat: Add `getSearchContent` prop to `Multiselect`
12
+ - feat: Change icon on `MainMenu2`'s toggler button when menu is open
13
+
14
+ ## 0.10.114
15
+
16
+ _2023-12-13_
17
+
18
+ - feat: Add prop `emptyMessage` to `AutosuggestSearch`
19
+ - feat: Add component `Radio` as a standalone atomic widget
20
+ - feat: Add prop `hideLabel` to `Checkbox` for minimal/atomic use
21
+ - fix: Regression in `Checkbox`- and `Radio`-related option typing
22
+
7
23
  ## 0.10.113
8
24
 
9
25
  _2023-12-08_
package/Carousel.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { CarouselProps } from './_abstract/_AbstractCarousel.js';
2
2
  export type { CarouselProps } from './_abstract/_AbstractCarousel.js';
3
- export declare const Carousel: <I extends Record<string, unknown> = {}, P extends Record<string, unknown> | undefined = {}>(props: CarouselProps<I, P>) => JSX.Element;
3
+ export declare const Carousel: <I extends Record<string, unknown> = Record<string, never>, P extends Record<string, unknown> | undefined = Record<string, never>>(props: CarouselProps<I, P>) => JSX.Element;
4
4
  export default Carousel;
@@ -10,11 +10,11 @@ const defaultTexts = {
10
10
  const array = new Array(50).join(' ').split('');
11
11
  const CarouselStepper = (props) => {
12
12
  const { current, itemCount, setCurrent, texts = defaultTexts, wrapperProps } = props;
13
- const labelPrefix = texts.prefix ? texts.prefix + ' ' : '';
13
+ const labelPrefix = texts.prefix ? `${texts.prefix} ` : '';
14
14
  return (react_1.default.createElement("div", Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('CarouselStepper', null, (wrapperProps || {}).className) }), array.slice(0, itemCount).map((_, i) => {
15
15
  const isCurrent = current === i || undefined;
16
16
  const label = labelPrefix + (i + 1);
17
- return (react_1.default.createElement("button", { key: i, className: 'CarouselStepper__button', type: "button", disabled: isCurrent, "aria-pressed": isCurrent, "aria-controls": props['aria-controls'], onClick: () => setCurrent(i), "aria-label": label, title: label }, label));
17
+ return (react_1.default.createElement("button", { key: i, className: "CarouselStepper__button", type: "button", disabled: isCurrent, "aria-pressed": isCurrent, "aria-controls": props['aria-controls'], onClick: () => setCurrent(i), "aria-label": label, title: label }, label));
18
18
  })));
19
19
  };
20
20
  exports.CarouselStepper = CarouselStepper;
@@ -1,6 +1,6 @@
1
1
  import { TogglerInputProps } from './_abstract/_TogglerInput.js';
2
2
  /** @deprecated Use `CheckboxButtonProps` instead (Will be removed in v0.11) */
3
3
  export type CheckboxProps = CheckboxButtonProps;
4
- export type CheckboxButtonProps = TogglerInputProps;
4
+ export type CheckboxButtonProps = Omit<TogglerInputProps, 'hideLabel'>;
5
5
  export declare const CheckboxButton: (props: CheckboxButtonProps) => JSX.Element;
6
6
  export default CheckboxButton;
package/CityBlock.js CHANGED
@@ -13,7 +13,7 @@ const types = {
13
13
  const CityBlock = (props) => {
14
14
  const align = props.align || 'right';
15
15
  const type = !props.illustration && props.type; // The presence of illustration prop suppresses type
16
- const modifier = [constants_js_1.aligns[align] && 'align--' + align, type && types[type] && type];
16
+ const modifier = [constants_js_1.aligns[align] && `align--${align}`, type && types[type] && type];
17
17
  const imageProps = props.illustration != null
18
18
  ? { src: (0, assets_1.getIllustrationUrl)(props.illustration) }
19
19
  : props.image;
package/ContactBubble.js CHANGED
@@ -103,7 +103,7 @@ const ContactBubble = (props) => {
103
103
  };
104
104
  },
105
105
  // eslint-disable-next-line react-hooks/exhaustive-deps
106
- [isBrowser, alwaysShow, closeBubble]);
106
+ [isBrowser, alwaysShow, closeBubble /* , wrapperRef */]);
107
107
  (0, react_1.useEffect)(() => {
108
108
  const escHandler = (e) => e.key === 'Escape' && closeBubble();
109
109
  const outsideClickHandler = (e) => {
@@ -126,7 +126,9 @@ const ContactBubble = (props) => {
126
126
  document.removeEventListener('keydown', escHandler);
127
127
  document.removeEventListener('click', outsideClickHandler, true);
128
128
  };
129
- }, [open, closeBubble]);
129
+ },
130
+ // eslint-disable-next-line react-hooks/exhaustive-deps
131
+ [open, closeBubble /* , wrapperRef */]);
130
132
  if (links.length === 0) {
131
133
  return null;
132
134
  }
@@ -135,7 +137,7 @@ const ContactBubble = (props) => {
135
137
  react_1.default.createElement("ul", { className: "ContactBubble__list" }, links.map((linkInfo, i) => {
136
138
  const { href, label, extraLabel, target, onClick } = linkInfo;
137
139
  const icon = (0, exports.ensureIcon)(linkInfo.icon);
138
- const itemClass = (0, classUtils_1.modifiedClass)('ContactBubble__item', icon && 'type--' + icon);
140
+ const itemClass = (0, classUtils_1.modifiedClass)('ContactBubble__item', icon && `type--${icon}`);
139
141
  const onClickHandler = (e) => {
140
142
  if (onClick) {
141
143
  const doPreventDefault = onClick() !== true;
package/Datepicker.js CHANGED
@@ -114,7 +114,8 @@ const defaultDatepickerTexts = {
114
114
  * Internally, this component uses the [`react-datepicker`](https://reactdatepicker.com/) component.
115
115
  */
116
116
  const Datepicker = (props) => {
117
- const { placeholder, dateFormat, name, startDate, endDate, minDate, maxDate, isStartDate = false, isEndDate = false, onChange, datepickerExtraProps, inputRef, isoMode, texts, lang = props.localeCode, fieldWrapperProps, } = (0, FormField_js_1.groupFormFieldWrapperProps)(props);
117
+ const { placeholder, dateFormat, name, startDate, endDate, minDate, maxDate, isStartDate = false, isEndDate = false, onChange, datepickerExtraProps, inputRef, isoMode, texts, lang = props.localeCode, // eslint-disable-line deprecation/deprecation
118
+ fieldWrapperProps, } = (0, FormField_js_1.groupFormFieldWrapperProps)(props);
118
119
  const [value, setValue] = utils_js_1.useMixedControlState.raw(props.value || props.initialDate, // eslint-disable-line deprecation/deprecation
119
120
  props.defaultValue, 'value');
120
121
  /*
@@ -36,7 +36,7 @@ const formatBytes = (bytes, lang = 'is', decimals = 2) => {
36
36
  }
37
37
  const i = Math.min(Math.floor(Math.log(Math.abs(bytes) / kThreshold) / Math.log(k)), units.length - 1);
38
38
  const scaled = bytes / Math.pow(k, i);
39
- const formatted = (parseFloat(scaled.toFixed(decimals)) + '').replace('.',
39
+ const formatted = `${parseFloat(scaled.toFixed(decimals))}`.replace('.',
40
40
  // NOTE: As of 2022-11 Chrome still doesn't support Icelandic
41
41
  decimalSymbols[lang] || (1.1).toLocaleString(lang)[1]);
42
42
  return `${formatted} ${units[i]}`;
package/FileInput.js CHANGED
@@ -16,12 +16,11 @@ const defaultRemoveFileText = {
16
16
  pl: 'Usuń',
17
17
  };
18
18
  const defaultOnFilesRejected = (rejectedFiles) => {
19
- window.alert('Error:\n' +
20
- rejectedFiles
21
- .map((elm) => {
22
- return elm.name;
23
- })
24
- .join(', '));
19
+ window.alert(`Error:\n${rejectedFiles
20
+ .map((elm) => {
21
+ return elm.name;
22
+ })
23
+ .join(', ')}`);
25
24
  };
26
25
  const arrayToFileList = (arr) => {
27
26
  const fileList = new DataTransfer();
@@ -109,7 +108,7 @@ const FileInput = (props) => {
109
108
  }
110
109
  onFilesUpdated(fileList, diff);
111
110
  };
112
- return (react_1.default.createElement(FormField_js_1.default, Object.assign({ extraClassName: (0, classUtils_1.modifiedClass)('FileInput', [multiple && 'multi']) }, fieldWrapperProps, { id: domid + '-fake', LabelTag: "h4", renderInput: (className, inputProps /* , addFocusProps */) => {
111
+ return (react_1.default.createElement(FormField_js_1.default, Object.assign({ extraClassName: (0, classUtils_1.modifiedClass)('FileInput', [multiple && 'multi']) }, fieldWrapperProps, { id: `${domid}-fake`, LabelTag: "h4", renderInput: (className, inputProps /* , addFocusProps */) => {
113
112
  return (react_1.default.createElement("div", { className: className.control, ref: fileInputWrapper },
114
113
  // Explicitly skip rendering of input element if no
115
114
  // name prop is provided. This is implicitly what the
package/Form.js CHANGED
@@ -8,7 +8,7 @@ const classUtils_1 = require("@hugsmidjan/qj/classUtils");
8
8
  // it makes little sense to add support for `wrapperProps` on top.
9
9
  const Form = (props) => {
10
10
  const { children, align, wide, className } = props, formProps = tslib_1.__rest(props, ["children", "align", "wide", "className"]);
11
- return (react_1.default.createElement("form", Object.assign({}, formProps, { className: (0, classUtils_1.modifiedClass)('Form', [align === 'right' && 'align--' + align, !align && wide && 'wide'], className) }), children));
11
+ return (react_1.default.createElement("form", Object.assign({}, formProps, { className: (0, classUtils_1.modifiedClass)('Form', [align === 'right' && `align--${align}`, !align && wide && 'wide'], className) }), children));
12
12
  };
13
13
  exports.Form = Form;
14
14
  exports.default = exports.Form;
package/FormField.d.ts CHANGED
@@ -86,8 +86,8 @@ export declare const getFormFieldWrapperProps: (props: (FormFieldGroupWrappingPr
86
86
  }) => RequireExplicitUndefined<FormFieldGroupWrappingProps> & {
87
87
  small: boolean | undefined;
88
88
  };
89
- export declare const groupFormFieldWrapperProps: <T extends (FormFieldGroupWrappingProps | Pick<TogglerGroupFieldProps<"default", {}>, "label" | "className" | "id" | "wrapperProps" | "disabled" | "ssr" | "invalid" | "readOnly" | "required" | "errorMessage" | "reqText" | "assistText" | "hideLabel" | "wrapperRef" | "LabelTag">) & {
89
+ export declare const groupFormFieldWrapperProps: <T extends (FormFieldGroupWrappingProps | Pick<TogglerGroupFieldProps<"default", {}>, "label" | "className" | "id" | "wrapperProps" | "disabled" | "ssr" | "invalid" | "readOnly" | "required" | "hideLabel" | "errorMessage" | "reqText" | "assistText" | "wrapperRef" | "LabelTag">) & {
90
90
  small?: boolean | undefined;
91
- }>(props: T) => Omit<T, "label" | "small" | "className" | "id" | "wrapperProps" | "disabled" | "ssr" | "invalid" | "readOnly" | "required" | "errorMessage" | "reqText" | "assistText" | "hideLabel" | "wrapperRef" | "LabelTag"> & {
91
+ }>(props: T) => Omit<T, "label" | "small" | "className" | "id" | "wrapperProps" | "disabled" | "ssr" | "invalid" | "readOnly" | "required" | "hideLabel" | "errorMessage" | "reqText" | "assistText" | "wrapperRef" | "LabelTag"> & {
92
92
  fieldWrapperProps: ReturnType<typeof getFormFieldWrapperProps>;
93
93
  };
package/FormField.js CHANGED
@@ -64,7 +64,7 @@ const FormField = (props) => {
64
64
  required: required,
65
65
  readOnly: readOnly,
66
66
  'aria-invalid': isInvalid,
67
- 'aria-describedby': assistTextId && errorId ? assistTextId + ' ' + errorId : assistTextId || errorId,
67
+ 'aria-describedby': assistTextId && errorId ? `${assistTextId} ${errorId}` : assistTextId || errorId,
68
68
  'aria-labelledby': labelId, // undefined if normalLabel
69
69
  };
70
70
  return (react_1.default.createElement("div", Object.assign({ ref: props.wrapperRef }, wrapperProps, { className: (0, classUtils_1.modifiedClass)('FormField', [
package/Heading.js CHANGED
@@ -16,7 +16,7 @@ const Heading = (props) => {
16
16
  const suppressWarning = process.env.NODE_ENV !== 'production' && Tag === 'h1' ? true : undefined;
17
17
  return (react_1.default.createElement(Tag, Object.assign({}, wrapperProps, { "data-dev-forcedh1": suppressWarning, className: (0, classUtils_1.modifiedClass)('Heading', [
18
18
  sizes[size],
19
- align === 'right' && 'align--' + align,
19
+ align === 'right' && `align--${align}`,
20
20
  !align && wide && 'wide',
21
21
  (wrapperProps || {}).className,
22
22
  ]) }), children));
package/IframeBlock.js CHANGED
@@ -15,7 +15,7 @@ const iframe_resizer_react_1 = tslib_1.__importDefault(require("iframe-resizer-r
15
15
  */
16
16
  const IframeBlock = (props) => {
17
17
  const { title, src, framed, compact, align } = props;
18
- const className = (0, classUtils_1.modifiedClass)('IframeBlock', [framed && 'framed', compact && 'compact', align === 'right' && 'align--' + align], (props.wrapperProps || {}).className);
18
+ const className = (0, classUtils_1.modifiedClass)('IframeBlock', [framed && 'framed', compact && 'compact', align === 'right' && `align--${align}`], (props.wrapperProps || {}).className);
19
19
  if (typeof props.height === 'number') {
20
20
  const { wrapperProps, scrolling, height } = props;
21
21
  return (react_1.default.createElement("iframe", Object.assign({}, wrapperProps, { className: className, title: title, src: src,
package/InfoHero.js CHANGED
@@ -74,7 +74,7 @@ const InfoHero = (props) => {
74
74
  const blings = typeof blingType === 'object'
75
75
  ? blingType
76
76
  : (blingType && blingOptions[blingType]) || blingOptions.waves; // default to `waves`
77
- return (react_1.default.createElement("div", Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('InfoHero', 'align--' + alignment, (wrapperProps || {}).className) }),
77
+ return (react_1.default.createElement("div", Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('InfoHero', `align--${alignment}`, (wrapperProps || {}).className) }),
78
78
  react_1.default.createElement("div", { className: "InfoHero__content" },
79
79
  react_1.default.createElement("h1", { className: "InfoHero__title" }, title),
80
80
  titleBlurb && react_1.default.createElement("div", { className: "InfoHero__titleblurb" }, titleBlurb),
package/IslandBlock.js CHANGED
@@ -15,7 +15,7 @@ const IslandBlock = (props) => {
15
15
  content,
16
16
  image: shapes ? { src: (0, assets_1.getFormheimurUrl)(shapes), inline: true } : image || {},
17
17
  };
18
- return (react_1.default.createElement(_Block_js_1.Block, Object.assign({ wrapperProps: wrapperProps, bem: "IslandBlock", modifier: 'align--' + alignment }, blockProps)));
18
+ return (react_1.default.createElement(_Block_js_1.Block, Object.assign({ wrapperProps: wrapperProps, bem: "IslandBlock", modifier: `align--${alignment}` }, blockProps)));
19
19
  };
20
20
  exports.IslandBlock = IslandBlock;
21
21
  exports.default = exports.IslandBlock;
@@ -15,7 +15,7 @@ const IslandPageBlock = (props) => {
15
15
  const { title, summary, buttons, illustration, image, align, background, wrapperProps, } = props;
16
16
  const alignment = align && constants_js_1.aligns[align] ? align : 'right';
17
17
  const bg = backgrounds[background || 'none'];
18
- return (react_1.default.createElement(_Block_js_1.Block, { wrapperProps: wrapperProps, bem: "IslandPageBlock", modifier: ['align--' + alignment, bg && 'background--' + bg], content: { title, summary, buttons }, image: illustration ? { src: (0, assets_1.getIllustrationUrl)(illustration) } : image || {} }));
18
+ return (react_1.default.createElement(_Block_js_1.Block, { wrapperProps: wrapperProps, bem: "IslandPageBlock", modifier: [`align--${alignment}`, bg && `background--${bg}`], content: { title, summary, buttons }, image: illustration ? { src: (0, assets_1.getIllustrationUrl)(illustration) } : image }));
19
19
  };
20
20
  exports.IslandPageBlock = IslandPageBlock;
21
21
  exports.default = exports.IslandPageBlock;
package/MainMenu.js CHANGED
@@ -173,7 +173,9 @@ const _MainMenu = (props) => {
173
173
  document.removeEventListener('keydown', escHandler);
174
174
  document.removeEventListener('click', clickHandler, true);
175
175
  };
176
- }, [hasActivePanel, setActivePanel, isBrowser]);
176
+ },
177
+ // eslint-disable-next-line react-hooks/exhaustive-deps
178
+ [hasActivePanel, setActivePanel, isBrowser /* , menuElmRef */]);
177
179
  if (menuItems.length === 0) {
178
180
  return null;
179
181
  }
package/MainMenu2.js CHANGED
@@ -71,7 +71,6 @@ const iconMap = {
71
71
  */
72
72
  const getRenderers = (props) => {
73
73
  const { onItemClick, closeMenu, isBrowser } = props;
74
- // eslint-disable-next-line complexity
75
74
  const renderItem = (classPrefix, item, opts = {}) => {
76
75
  const { key, Tag = 'li', button } = opts;
77
76
  if (typeof item === 'function') {
@@ -195,18 +194,20 @@ const MainMenu2 = (props) => {
195
194
  isMenuOpen && react_1.default.createElement(FocusTrap_js_1.FocusTrap, { atTop: true }),
196
195
  react_1.default.createElement("div", { className: "MainMenu2__content" },
197
196
  react_1.default.createElement("h2", { className: "MainMenu2__title" }, txt.title),
198
- isBrowser ? (react_1.default.createElement(ButtonPrimary_js_1.default, Object.assign({ className: "MainMenu2__toggler", size: "small", type: "button", "aria-pressed": isMenuOpen, "aria-controls": menuId, "data-icon": "text" }, (isMenuOpen
197
+ isBrowser ? (react_1.default.createElement(ButtonPrimary_js_1.default, Object.assign({ className: "MainMenu2__toggler", size: "small", type: "button", "aria-pressed": isMenuOpen, "aria-controls": menuId }, (isMenuOpen
199
198
  ? {
200
199
  onClick: closeMenu,
201
200
  'aria-label': txt.closeMenuLong,
202
201
  title: txt.closeMenuLong,
203
202
  children: txt.closeMenu,
203
+ 'data-icon': 'text',
204
204
  }
205
205
  : {
206
206
  onClick: openMenu,
207
207
  'aria-label': txt.openMenuLong,
208
208
  title: txt.openMenuLong,
209
209
  children: txt.openMenu,
210
+ 'data-icon': 'close',
210
211
  })))) : (react_1.default.createElement(ButtonPrimary_js_1.default, { className: "MainMenu2__toggler", size: "small", href: `#${menuId}`, onClick: a11yHelpers_js_1.handleAnchorLinkClick, "aria-hidden": "true", "data-icon": "text" }, txt.title)),
211
212
  mainItems && (react_1.default.createElement("div", { className: (0, classUtils_1.modifiedClass)('MainMenu2__main', activeSubmenu < 0 && 'noneActive') },
212
213
  renderItem('MainMenu2__main__', homeLinkItem, { Tag: 'div' }),
@@ -48,7 +48,7 @@ const useMobileMenuToggling = (opts) => {
48
48
  const toggler = typeof togglerElm === 'string' ? document.querySelector(togglerElm) : togglerElm;
49
49
  const menuElmId = toggler === null || toggler === void 0 ? void 0 : toggler.getAttribute('aria-controls');
50
50
  if (menuElmId) {
51
- (0, hanna_utils_1.focusElement)('#' + menuElmId);
51
+ (0, hanna_utils_1.focusElement)(`#${menuElmId}`);
52
52
  }
53
53
  }
54
54
  };
@@ -1,4 +1,4 @@
1
- import { TogglerGroupOptions } from '../_abstract/_TogglerGroup.js';
1
+ import { TogglerGroupOption, TogglerGroupOptions } from '../_abstract/_TogglerGroup.js';
2
2
  import { TogglerGroupFieldOption } from '../_abstract/_TogglerGroupField.js';
3
3
  export declare const _weights: {
4
4
  WHOLE_WORD: number;
@@ -13,7 +13,9 @@ item: TogglerGroupFieldOption<string>,
13
13
  /** Trimmed list of `toLowerCase`d query words */
14
14
  queryWords: Array<string>,
15
15
  /** The raw, untouched search query as typed by the user */
16
- rawQuery: string) => number;
16
+ rawQuery: string,
17
+ /** Function to extract the item's label */
18
+ itemContent: string | undefined) => number;
17
19
  export declare const defaultSearchScoring: SearchScoringfn;
18
20
  /** Returns a normalized, filtered list of options */
19
- export declare const filterItems: <Extras = {}>(options: TogglerGroupOptions<string, Extras>, searchQuery: string, searchScoringFn?: SearchScoringfn) => TogglerGroupOptions<string, Extras>;
21
+ export declare const filterItems: <Extras = Record<string, never>>(options: TogglerGroupOptions<string, Extras>, searchQuery: string, searchScoringFn?: SearchScoringfn, getLabel?: (item: TogglerGroupOption<string, Extras>) => string | undefined) => TogglerGroupOptions<string, Extras>;
@@ -47,13 +47,12 @@ const calcScore = (itemString, queryWords) => {
47
47
  });
48
48
  return score;
49
49
  };
50
- const defaultSearchScoring = (item, queryWords) => {
51
- var _a;
50
+ const defaultSearchScoring = (item, queryWords, _, itemContent) => {
52
51
  if (!item.value) {
53
52
  return 0;
54
53
  }
55
54
  const value = item.value.toLowerCase().trim();
56
- const label = ((_a = item.label) === null || _a === void 0 ? void 0 : _a.toLowerCase().trim()) || value;
55
+ const label = (itemContent === null || itemContent === void 0 ? void 0 : itemContent.toLowerCase().trim()) || value;
57
56
  let score = calcScore(label, queryWords);
58
57
  if (!score) {
59
58
  score = VALUE_WEIGHT * calcScore(value, queryWords);
@@ -65,7 +64,7 @@ exports.defaultSearchScoring = defaultSearchScoring;
65
64
  // banana emoji
66
65
  const SEP = '🍌';
67
66
  /** Returns a normalized, filtered list of options */
68
- const filterItems = (options, searchQuery, searchScoringFn = exports.defaultSearchScoring) => {
67
+ const filterItems = (options, searchQuery, searchScoringFn = exports.defaultSearchScoring, getLabel = (item) => item.label) => {
69
68
  if (!searchQuery.trim()) {
70
69
  return options;
71
70
  }
@@ -74,7 +73,7 @@ const filterItems = (options, searchQuery, searchScoringFn = exports.defaultSear
74
73
  return (options
75
74
  .map((item) => ({
76
75
  item,
77
- score: searchScoringFn(item, queryWords, searchQuery),
76
+ score: searchScoringFn(item, queryWords, searchQuery, getLabel(item)),
78
77
  }))
79
78
  .filter(({ score }) => score > 0)
80
79
  .sort((a, b) => (a.score === b.score ? 0 : a.score < b.score ? 1 : -1))
package/Multiselect.d.ts CHANGED
@@ -29,6 +29,11 @@ export type MultiselectProps = TogglerGroupFieldProps<string, {
29
29
  * A score of zero (or less) means the item is not a valid match.
30
30
  */
31
31
  searchScoring?: SearchScoringfn;
32
+ /**
33
+ * Custom function to extract the searchable content from a given option item.
34
+ * By default, the `label` property is used.
35
+ */
36
+ getSearchContent?: (item: MultiselectOption) => string;
32
37
  /**
33
38
  * Force display the current values at the top of the dropdown,
34
39
  * even when the total options are fewer than
package/Multiselect.js CHANGED
@@ -97,7 +97,7 @@ const Multiselect = (props) => {
97
97
  */
98
98
  const showCurrentValues = values.length > 0 &&
99
99
  (props.forceSummary || !isOpen || options.length >= summaryLimit);
100
- const filteredOptions = (0, react_1.useMemo)(() => (0, _Multiselect_search_js_1.filterItems)(options, searchQuery, props.searchScoring), [searchQuery, options, props.searchScoring]);
100
+ const filteredOptions = (0, react_1.useMemo)(() => (0, _Multiselect_search_js_1.filterItems)(options, searchQuery, props.searchScoring, props.getSearchContent), [searchQuery, options, props.searchScoring, props.getSearchContent]);
101
101
  const isFiltered = options !== filteredOptions;
102
102
  const handleCheckboxSelection = (0, react_1.useCallback)((selectedItem) => {
103
103
  const selValue = selectedItem.value;
@@ -224,7 +224,6 @@ const Multiselect = (props) => {
224
224
  removable: true,
225
225
  onRemove: () => {
226
226
  handleCheckboxSelection(item);
227
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
228
227
  inputWrapperRef
229
228
  .current.querySelector('.Multiselect__choices')
230
229
  .focus();
package/NameCard.js CHANGED
@@ -18,7 +18,7 @@ const _telToContactInfo = (tel) => {
18
18
  }
19
19
  tel = typeof tel === 'string' ? [tel] : tel;
20
20
  return tel.map((tel) => ({
21
- href: 'tel:' + tel,
21
+ href: `tel:${tel}`,
22
22
  value: tel,
23
23
  }));
24
24
  };
package/PageHeading.js CHANGED
@@ -6,7 +6,7 @@ const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const classUtils_1 = require("@hugsmidjan/qj/classUtils");
7
7
  const PageHeading = (props) => {
8
8
  const { Tag = 'h1', align, small, children, wrapperProps } = props;
9
- return (react_1.default.createElement(Tag, Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('PageHeading', [small && 'small', align === 'right' && 'align--' + align], (wrapperProps || {}).className) }), children));
9
+ return (react_1.default.createElement(Tag, Object.assign({}, wrapperProps, { className: (0, classUtils_1.modifiedClass)('PageHeading', [small && 'small', align === 'right' && `align--${align}`], (wrapperProps || {}).className) }), children));
10
10
  };
11
11
  exports.PageHeading = PageHeading;
12
12
  exports.default = exports.PageHeading;
package/Pagination.js CHANGED
@@ -10,8 +10,8 @@ const Pagination_privates_js_1 = require("./utils/Pagination.privates.js");
10
10
  const utils_js_1 = require("./utils.js");
11
11
  const PaginationButton = (props) => {
12
12
  const { page, label, modifier, disabled, onChange, href } = props;
13
- const labelLong = props.labelLong.replace(/\$\{page\}/, page + '');
14
- const labelShort = label ? label.replace(/\$\{page\}/, page + '') : page + '';
13
+ const labelLong = props.labelLong.replace(/\$\{page\}/, `${page}`);
14
+ const labelShort = label ? label.replace(/\$\{page\}/, `${page}`) : `${page}`;
15
15
  const btnProps = {
16
16
  key: props.key,
17
17
  className: (0, classUtils_1.modifiedClass)('Pagination__button', modifier),
package/Radio.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { TogglerInputProps } from './_abstract/_TogglerInput.js';
2
+ export type RadioProps = Omit<TogglerInputProps, 'reqText'>;
3
+ export declare const Radio: (props: RadioProps) => JSX.Element;
package/Radio.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Radio = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const _TogglerInput_js_1 = require("./_abstract/_TogglerInput.js");
7
+ const Radio = (props) => (react_1.default.createElement(_TogglerInput_js_1.TogglerInput, Object.assign({ bem: "Radio" }, props, { type: "radio", reqText: false })));
8
+ exports.Radio = Radio;
package/RadioGroup.d.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  import { TogglerGroupFieldOption, TogglerGroupFieldOptions, TogglerGroupFieldProps } from './_abstract/_TogglerGroupField.js';
2
- import { TogglerInputProps } from './_abstract/_TogglerInput.js';
3
- type RadioProps = Omit<TogglerInputProps, 'reqText'>;
4
2
  export type RadioGroupProps = TogglerGroupFieldProps & {
5
3
  layout?: 'inline';
6
4
  value?: string;
@@ -8,9 +6,5 @@ export type RadioGroupProps = TogglerGroupFieldProps & {
8
6
  };
9
7
  export type RadioGroupOption = TogglerGroupFieldOption;
10
8
  export type RadioGroupOptions = TogglerGroupFieldOptions;
11
- export declare const RadioGroup: {
12
- (props: RadioGroupProps): JSX.Element;
13
- /** @deprecated Exposed for testing purposes only. This may disappear at any time. */
14
- __Radio: (props: RadioProps) => JSX.Element;
15
- };
9
+ export declare const RadioGroup: (props: RadioGroupProps) => JSX.Element;
16
10
  export default RadioGroup;
package/RadioGroup.js CHANGED
@@ -4,10 +4,7 @@ exports.RadioGroup = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const _TogglerGroupField_js_1 = require("./_abstract/_TogglerGroupField.js");
7
- const _TogglerInput_js_1 = require("./_abstract/_TogglerInput.js");
8
- const Radio = (props) => react_1.default.createElement(_TogglerInput_js_1.TogglerInput, Object.assign({}, props, { bem: "Radio", type: "radio" }));
9
- const RadioGroup = (props) => (react_1.default.createElement(_TogglerGroupField_js_1.TogglerGroupField, Object.assign({}, props, { bem: "RadioGroup", modifier: props.layout, isRadio: true, Toggler: Radio })));
7
+ const Radio_js_1 = require("./Radio.js");
8
+ const RadioGroup = (props) => (react_1.default.createElement(_TogglerGroupField_js_1.TogglerGroupField, Object.assign({}, props, { bem: "RadioGroup", modifier: props.layout, isRadio: true, Toggler: Radio_js_1.Radio })));
10
9
  exports.RadioGroup = RadioGroup;
11
- /** @deprecated Exposed for testing purposes only. This may disappear at any time. */
12
- exports.RadioGroup.__Radio = Radio; // eslint-disable-line deprecation/deprecation
13
10
  exports.default = exports.RadioGroup;