@reykjavik/hanna-react 0.10.126 → 0.10.128

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@
4
4
 
5
5
  - ... <!-- Add new lines here. -->
6
6
 
7
+ ## 0.10.128
8
+
9
+ _2024-07-01_
10
+
11
+ - feat: Add prop `renderItemSubContent` to all checkbox and radio group
12
+ compnents — to support more advanced UI patterns.
13
+ - feat: Add prop `allow` to `IframeBlock`
14
+
15
+ ## 0.10.127
16
+
17
+ _2024-06-27_
18
+
19
+ - fix: Ref error when `MainMenu2` unmounts
20
+
7
21
  ## 0.10.126
8
22
 
9
23
  _2024-06-05_
package/IframeBlock.d.ts CHANGED
@@ -9,6 +9,7 @@ export type IframeBlockProps = {
9
9
  framed?: boolean;
10
10
  compact?: boolean;
11
11
  align?: 'right';
12
+ allow?: JSX.IntrinsicElements['iframe']['allow'];
12
13
  } & EitherObj<{
13
14
  /** Fixed height, no auto-resizing of the iframe */
14
15
  height: number;
package/IframeBlock.js CHANGED
@@ -14,11 +14,11 @@ const iframe_resizer_react_1 = tslib_1.__importDefault(require("iframe-resizer-r
14
14
  * ```
15
15
  */
16
16
  const IframeBlock = (props) => {
17
- const { title, src, framed, compact, align } = props;
17
+ const { title, src, framed, compact, align, allow } = props;
18
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
- return (react_1.default.createElement("iframe", Object.assign({}, wrapperProps, { className: className, title: title, src: src,
21
+ return (react_1.default.createElement("iframe", Object.assign({}, wrapperProps, { className: className, title: title, src: src, allow: allow,
22
22
  // hidden tiger: pass negative height to disable iframe-resizer but not set height explicitly
23
23
  // (Silly hack, don't rely on this)
24
24
  height: height < 0 ? undefined : height,
package/MainMenu2.js CHANGED
@@ -126,12 +126,14 @@ const MainMenu2 = (props) => {
126
126
  document.addEventListener('keydown', escHandler);
127
127
  };
128
128
  const closeMenu = () => {
129
+ var _a;
129
130
  htmlCl.remove(globalClasses.menuIsOpen);
130
131
  htmlCl.add(globalClasses.menuIsClosed);
131
132
  setIsMenuOpen(false);
132
133
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
133
134
  setActiveSubmenu(defaultActive);
134
- wrapperRef.current.scrollTo(0, 0);
135
+ // closeMenu is called on umount, and then the ref might be null
136
+ (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo(0, 0);
135
137
  document.removeEventListener('keydown', escHandler);
136
138
  };
137
139
  (0, react_1.useEffect)(() => {
@@ -140,8 +142,8 @@ const MainMenu2 = (props) => {
140
142
  }
141
143
  htmlCl.add(globalClasses.menuIsClosed);
142
144
  return () => {
143
- closeMenu();
144
145
  htmlCl.remove(globalClasses.menuIsClosed);
146
+ closeMenu();
145
147
  };
146
148
  // eslint-disable-next-line react-hooks/exhaustive-deps
147
149
  }, [isBrowser]);
@@ -1,3 +1,4 @@
1
+ import { ReactNode } from 'react';
1
2
  import { FormFieldInputProps } from '../FormField.js';
2
3
  import { HTMLProps } from '../utils.js';
3
4
  import { TogglerInputProps } from './_TogglerInput.js';
@@ -25,6 +26,12 @@ export type TogglerGroupProps<T = 'default', Extras = {}> = {
25
26
  /** The updated value array */
26
27
  selectedValues: Array<string>;
27
28
  }) => void;
29
+ /**
30
+ * Render function that allows inserting content below each toggler
31
+ * (checkbox/radio) element, depending on the item's checked status
32
+ * (or other external state)
33
+ */
34
+ renderItemSubContent?: (option: TogglerGroupOption<T, Extras>, checked: boolean) => ReactNode;
28
35
  } & Omit<FormFieldInputProps, 'disabled'>;
29
36
  type _TogglerGroupProps = {
30
37
  bem: string;
@@ -9,7 +9,7 @@ const useDomid_js_1 = require("../utils/useDomid.js");
9
9
  const TogglerGroup = (props) => {
10
10
  const {
11
11
  // id,
12
- className, bem, disabled, readOnly, Toggler, onSelected, isRadio, inputProps = {}, } = props;
12
+ className, bem, disabled, readOnly, Toggler, onSelected, isRadio, renderItemSubContent, inputProps = {}, } = props;
13
13
  const [values, setValues] = (0, utils_js_1.useMixedControlState)(props, 'value', []);
14
14
  const name = (0, useDomid_js_1.useDomid)(props.name);
15
15
  const options = (0, react_1.useMemo)(() => {
@@ -25,7 +25,7 @@ const TogglerGroup = (props) => {
25
25
  ? disabled.includes(i)
26
26
  : disabled;
27
27
  const isChecked = values.includes(option.value);
28
- return (react_1.default.createElement(Toggler, Object.assign({ key: i }, inputProps, { className: `${bem}__item`, name: name, Wrapper: "li" }, option, { label: option.label || option.value, onChange: (e) => {
28
+ const togglerProps = Object.assign(Object.assign(Object.assign(Object.assign({}, inputProps), { name: name }), option), { label: option.label || option.value, onChange: (e) => {
29
29
  inputProps.onChange && inputProps.onChange(e);
30
30
  const { value } = option;
31
31
  const checked = e.currentTarget.checked;
@@ -35,7 +35,13 @@ const TogglerGroup = (props) => {
35
35
  }
36
36
  setValues(selectedValues);
37
37
  onSelected && onSelected({ value, checked, option, selectedValues });
38
- }, disabled: isDisabled, readOnly: readOnly, "aria-invalid": props['aria-invalid'], checked: isChecked })));
38
+ }, disabled: isDisabled, readOnly: readOnly, 'aria-invalid': props['aria-invalid'], checked: isChecked });
39
+ if (renderItemSubContent) {
40
+ return (react_1.default.createElement("li", { key: i, className: `${bem}__item` },
41
+ react_1.default.createElement(Toggler, Object.assign({}, togglerProps)),
42
+ renderItemSubContent(option, isChecked)));
43
+ }
44
+ return (react_1.default.createElement(Toggler, Object.assign({ key: i, className: `${bem}__item`, Wrapper: "li" }, togglerProps)));
39
45
  })));
40
46
  };
41
47
  exports.TogglerGroup = TogglerGroup;
@@ -9,6 +9,7 @@ export type IframeBlockProps = {
9
9
  framed?: boolean;
10
10
  compact?: boolean;
11
11
  align?: 'right';
12
+ allow?: JSX.IntrinsicElements['iframe']['allow'];
12
13
  } & EitherObj<{
13
14
  /** Fixed height, no auto-resizing of the iframe */
14
15
  height: number;
@@ -10,11 +10,11 @@ import IframeResizer from 'iframe-resizer-react';
10
10
  * ```
11
11
  */
12
12
  export const IframeBlock = (props) => {
13
- const { title, src, framed, compact, align } = props;
13
+ const { title, src, framed, compact, align, allow } = props;
14
14
  const className = modifiedClass('IframeBlock', [framed && 'framed', compact && 'compact', align === 'right' && `align--${align}`], (props.wrapperProps || {}).className);
15
15
  if (typeof props.height === 'number') {
16
16
  const { wrapperProps, scrolling, height } = props;
17
- return (React.createElement("iframe", Object.assign({}, wrapperProps, { className: className, title: title, src: src,
17
+ return (React.createElement("iframe", Object.assign({}, wrapperProps, { className: className, title: title, src: src, allow: allow,
18
18
  // hidden tiger: pass negative height to disable iframe-resizer but not set height explicitly
19
19
  // (Silly hack, don't rely on this)
20
20
  height: height < 0 ? undefined : height,
package/esm/MainMenu2.js CHANGED
@@ -122,12 +122,14 @@ export const MainMenu2 = (props) => {
122
122
  document.addEventListener('keydown', escHandler);
123
123
  };
124
124
  const closeMenu = () => {
125
+ var _a;
125
126
  htmlCl.remove(globalClasses.menuIsOpen);
126
127
  htmlCl.add(globalClasses.menuIsClosed);
127
128
  setIsMenuOpen(false);
128
129
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
129
130
  setActiveSubmenu(defaultActive);
130
- wrapperRef.current.scrollTo(0, 0);
131
+ // closeMenu is called on umount, and then the ref might be null
132
+ (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo(0, 0);
131
133
  document.removeEventListener('keydown', escHandler);
132
134
  };
133
135
  useEffect(() => {
@@ -136,8 +138,8 @@ export const MainMenu2 = (props) => {
136
138
  }
137
139
  htmlCl.add(globalClasses.menuIsClosed);
138
140
  return () => {
139
- closeMenu();
140
141
  htmlCl.remove(globalClasses.menuIsClosed);
142
+ closeMenu();
141
143
  };
142
144
  // eslint-disable-next-line react-hooks/exhaustive-deps
143
145
  }, [isBrowser]);
@@ -1,3 +1,4 @@
1
+ import { ReactNode } from 'react';
1
2
  import { FormFieldInputProps } from '../FormField.js';
2
3
  import { HTMLProps } from '../utils.js';
3
4
  import { TogglerInputProps } from './_TogglerInput.js';
@@ -25,6 +26,12 @@ export type TogglerGroupProps<T = 'default', Extras = {}> = {
25
26
  /** The updated value array */
26
27
  selectedValues: Array<string>;
27
28
  }) => void;
29
+ /**
30
+ * Render function that allows inserting content below each toggler
31
+ * (checkbox/radio) element, depending on the item's checked status
32
+ * (or other external state)
33
+ */
34
+ renderItemSubContent?: (option: TogglerGroupOption<T, Extras>, checked: boolean) => ReactNode;
28
35
  } & Omit<FormFieldInputProps, 'disabled'>;
29
36
  type _TogglerGroupProps = {
30
37
  bem: string;
@@ -5,7 +5,7 @@ import { useDomid } from '../utils/useDomid.js';
5
5
  export const TogglerGroup = (props) => {
6
6
  const {
7
7
  // id,
8
- className, bem, disabled, readOnly, Toggler, onSelected, isRadio, inputProps = {}, } = props;
8
+ className, bem, disabled, readOnly, Toggler, onSelected, isRadio, renderItemSubContent, inputProps = {}, } = props;
9
9
  const [values, setValues] = useMixedControlState(props, 'value', []);
10
10
  const name = useDomid(props.name);
11
11
  const options = useMemo(() => {
@@ -21,7 +21,7 @@ export const TogglerGroup = (props) => {
21
21
  ? disabled.includes(i)
22
22
  : disabled;
23
23
  const isChecked = values.includes(option.value);
24
- return (React.createElement(Toggler, Object.assign({ key: i }, inputProps, { className: `${bem}__item`, name: name, Wrapper: "li" }, option, { label: option.label || option.value, onChange: (e) => {
24
+ const togglerProps = Object.assign(Object.assign(Object.assign(Object.assign({}, inputProps), { name: name }), option), { label: option.label || option.value, onChange: (e) => {
25
25
  inputProps.onChange && inputProps.onChange(e);
26
26
  const { value } = option;
27
27
  const checked = e.currentTarget.checked;
@@ -31,6 +31,12 @@ export const TogglerGroup = (props) => {
31
31
  }
32
32
  setValues(selectedValues);
33
33
  onSelected && onSelected({ value, checked, option, selectedValues });
34
- }, disabled: isDisabled, readOnly: readOnly, "aria-invalid": props['aria-invalid'], checked: isChecked })));
34
+ }, disabled: isDisabled, readOnly: readOnly, 'aria-invalid': props['aria-invalid'], checked: isChecked });
35
+ if (renderItemSubContent) {
36
+ return (React.createElement("li", { key: i, className: `${bem}__item` },
37
+ React.createElement(Toggler, Object.assign({}, togglerProps)),
38
+ renderItemSubContent(option, isChecked)));
39
+ }
40
+ return (React.createElement(Toggler, Object.assign({ key: i, className: `${bem}__item`, Wrapper: "li" }, togglerProps)));
35
41
  })));
36
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reykjavik/hanna-react",
3
- "version": "0.10.126",
3
+ "version": "0.10.128",
4
4
  "author": "Reykjavík (http://www.reykjavik.is)",
5
5
  "contributors": [
6
6
  "Hugsmiðjan ehf (http://www.hugsmidjan.is)",