@reykjavik/hanna-react 0.10.133 → 0.10.135
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 +18 -0
- package/MainMenu.js +4 -1
- package/MainMenu2.d.ts +5 -2
- package/MainMenu2.js +22 -9
- package/esm/MainMenu.js +4 -1
- package/esm/MainMenu2.d.ts +5 -2
- package/esm/MainMenu2.js +22 -9
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
- ... <!-- Add new lines here. -->
|
|
6
6
|
|
|
7
|
+
## 0.10.135
|
|
8
|
+
|
|
9
|
+
_2024-09-03_
|
|
10
|
+
|
|
11
|
+
- feat: Add prop `variant="light"` to `MainMenu2`
|
|
12
|
+
|
|
13
|
+
## 0.10.134
|
|
14
|
+
|
|
15
|
+
_2024-08-19_
|
|
16
|
+
|
|
17
|
+
- `MainÞMenu2`:
|
|
18
|
+
- feat: Pass `openMenu()` prop to `MainMenu2CustomItem` callbacks
|
|
19
|
+
- feat: Allow rich-text (JSX) `label`s for menu items
|
|
20
|
+
- feat: Allow `icon` prop on related items
|
|
21
|
+
- fix: links with empty-string `href` not rendered server-side
|
|
22
|
+
- `MainMenu`:
|
|
23
|
+
- fix: Unnecessary scroll-reset when resizing window to enter hamburger-mode
|
|
24
|
+
|
|
7
25
|
## 0.10.133
|
|
8
26
|
|
|
9
27
|
_2024-08-08_
|
package/MainMenu.js
CHANGED
|
@@ -108,8 +108,11 @@ const _MainMenu = (props) => {
|
|
|
108
108
|
const htmlElmDataset = htmlElm.dataset;
|
|
109
109
|
// const menuElm = menuElmRef.current as HTMLElement;
|
|
110
110
|
_setActivePanel((activePanel) => {
|
|
111
|
+
if (!newActive && !activePanel) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
111
114
|
if (!newActive) {
|
|
112
|
-
|
|
115
|
+
setLaggyActivePanel(activePanel, 1000);
|
|
113
116
|
htmlElm.scrollTop = parseInt(htmlElmDataset.scrollTop || '') || 0;
|
|
114
117
|
delete htmlElmDataset.scrollTop;
|
|
115
118
|
delete htmlElmDataset.megaPanelActive;
|
package/MainMenu2.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type MainMenu2I18n = {
|
|
|
16
16
|
export declare const defaultMainMenu2Texts: DefaultTexts<MainMenu2I18n>;
|
|
17
17
|
export type MainMenu2Item = {
|
|
18
18
|
/** Visible label text */
|
|
19
|
-
label: string
|
|
19
|
+
label: string | NonNullable<ReactElement>;
|
|
20
20
|
/** Un-abbreviated label set as `title=""` and `aria-label=""` */
|
|
21
21
|
labelLong?: string;
|
|
22
22
|
/** Language of the link label */
|
|
@@ -57,6 +57,7 @@ export type MainMenu2ButtonItem = MainMenu2Item & {
|
|
|
57
57
|
};
|
|
58
58
|
export type MainMenu2CustomItem = (props: {
|
|
59
59
|
closeMenu: () => void;
|
|
60
|
+
openMenu: () => void;
|
|
60
61
|
}) => ReactElement;
|
|
61
62
|
export type MainMenu2SubMenuItem = MainMenu2Item & {
|
|
62
63
|
descr?: string;
|
|
@@ -98,8 +99,10 @@ export type MainMenu2Props = {
|
|
|
98
99
|
hot?: MainMenu2ButtonItemList;
|
|
99
100
|
extra?: MainMenu2ButtonItemList;
|
|
100
101
|
relatedTitle?: string;
|
|
101
|
-
related?:
|
|
102
|
+
related?: MainMenu2ButtonItemList;
|
|
102
103
|
};
|
|
104
|
+
/** Visual type */
|
|
105
|
+
variant?: 'default' | 'light';
|
|
103
106
|
/**
|
|
104
107
|
* NOTE: Clicking a MainMenu2 item will automatically close HannaUIState's
|
|
105
108
|
* "Hamburger menu" (a.k.a. "Mobile menu")
|
package/MainMenu2.js
CHANGED
|
@@ -62,13 +62,13 @@ const iconMap = {
|
|
|
62
62
|
* Whether we're rendering the menu on the server or in the browser, etc.
|
|
63
63
|
*/
|
|
64
64
|
const getRenderers = (props) => {
|
|
65
|
-
const { onItemClick, closeMenu, isBrowser } = props;
|
|
65
|
+
const { onItemClick, closeMenu, openMenu, isBrowser } = props;
|
|
66
66
|
const renderItem = (classPrefix, item, opts = {}) => {
|
|
67
67
|
const { key, Tag = 'li', button } = opts;
|
|
68
68
|
if (typeof item === 'function') {
|
|
69
69
|
const Item = item;
|
|
70
70
|
return (react_1.default.createElement("li", { key: key, className: `${classPrefix}item` },
|
|
71
|
-
react_1.default.createElement(Item, { closeMenu: closeMenu })));
|
|
71
|
+
react_1.default.createElement(Item, { closeMenu: closeMenu, openMenu: openMenu })));
|
|
72
72
|
}
|
|
73
73
|
const linkClassName = `${classPrefix}link`;
|
|
74
74
|
const { label, labelLong, href, target, lang, controlsId, onClick, descr, icon } = item;
|
|
@@ -77,23 +77,32 @@ const getRenderers = (props) => {
|
|
|
77
77
|
react_1.default.createElement("small", { className: `${linkClassName}__descr` }, descr)));
|
|
78
78
|
const ButtonTag = button ? ButtonSecondary_js_1.default : 'button';
|
|
79
79
|
const LinkTag = button ? ButtonSecondary_js_1.default : _Link_js_1.Link;
|
|
80
|
+
const commonProps = {
|
|
81
|
+
className: linkClassName,
|
|
82
|
+
'data-icon': icon ? iconMap[icon] : undefined,
|
|
83
|
+
'arial-label': labelLong,
|
|
84
|
+
title: labelLong,
|
|
85
|
+
lang,
|
|
86
|
+
};
|
|
80
87
|
const buttonCompProps = button
|
|
81
88
|
? {
|
|
82
89
|
size: 'small',
|
|
83
|
-
'data-icon': icon && iconMap[icon],
|
|
84
90
|
}
|
|
85
91
|
: undefined;
|
|
86
|
-
|
|
92
|
+
if (label === 'Græna planið') {
|
|
93
|
+
console.log('FOOBAR', icon, icon && iconMap[icon]);
|
|
94
|
+
}
|
|
95
|
+
return (react_1.default.createElement(Tag, { key: key, className: (0, classUtils_1.modifiedClass)(`${classPrefix}item`, item.modifier), "aria-current": item.current || undefined }, isBrowser && (onClick || href == null) ? (react_1.default.createElement(ButtonTag, Object.assign({}, commonProps, { type: "button", "aria-controls": controlsId, onClick: () => {
|
|
87
96
|
const keepOpen1 = onClick && onClick(item) === false;
|
|
88
97
|
const keepOpen2 = onItemClick && onItemClick(item) === false;
|
|
89
98
|
!(keepOpen1 || keepOpen2) && closeMenu();
|
|
90
|
-
}
|
|
99
|
+
} }, buttonCompProps),
|
|
91
100
|
label,
|
|
92
101
|
" ",
|
|
93
|
-
itemDescr)) : href ? (react_1.default.createElement(LinkTag, Object.assign({
|
|
102
|
+
itemDescr)) : href != null ? (react_1.default.createElement(LinkTag, Object.assign({}, commonProps, { href: href, hrefLang: item.hrefLang, target: target, onClick: () => {
|
|
94
103
|
const keepOpen = onItemClick && onItemClick(item) === false;
|
|
95
104
|
!keepOpen && closeMenu();
|
|
96
|
-
}
|
|
105
|
+
} }, buttonCompProps),
|
|
97
106
|
label,
|
|
98
107
|
" ",
|
|
99
108
|
itemDescr)) : null));
|
|
@@ -108,7 +117,7 @@ const getRenderers = (props) => {
|
|
|
108
117
|
};
|
|
109
118
|
// eslint-disable-next-line complexity
|
|
110
119
|
const MainMenu2 = (props) => {
|
|
111
|
-
const { homeLink = '/', items, onItemClick, illustration, imageUrl, wrapperProps = {}, } = props;
|
|
120
|
+
const { homeLink = '/', items, onItemClick, illustration, imageUrl, variant, wrapperProps = {}, } = props;
|
|
112
121
|
const domid = (0, utils_js_1.useDomid)(wrapperProps.id);
|
|
113
122
|
const isBrowser = (0, utils_js_1.useIsBrowserSide)(props.ssr);
|
|
114
123
|
const [isMenuOpen, setIsMenuOpen] = (0, react_1.useState)(false);
|
|
@@ -181,6 +190,7 @@ const MainMenu2 = (props) => {
|
|
|
181
190
|
const { renderItem, renderList } = getRenderers({
|
|
182
191
|
onItemClick,
|
|
183
192
|
closeMenu,
|
|
193
|
+
openMenu,
|
|
184
194
|
isBrowser,
|
|
185
195
|
});
|
|
186
196
|
const homeLinkItem = Object.assign(Object.assign({}, (typeof homeLink === 'string'
|
|
@@ -188,7 +198,10 @@ const MainMenu2 = (props) => {
|
|
|
188
198
|
: homeLink)), { modifier: 'home' });
|
|
189
199
|
const menuImageUrl = imageUrl || (illustration && (0, assets_1.getIllustrationUrl)(illustration));
|
|
190
200
|
const menuId = `${domid}-menu`;
|
|
191
|
-
return (react_1.default.createElement("nav", Object.assign({}, props.wrapperProps, { className: (0, classUtils_1.modifiedClass)('MainMenu2',
|
|
201
|
+
return (react_1.default.createElement("nav", Object.assign({}, props.wrapperProps, { className: (0, classUtils_1.modifiedClass)('MainMenu2', [
|
|
202
|
+
isBrowser && (isMenuOpen ? 'open' : 'closed'),
|
|
203
|
+
variant && variant !== 'default' ? `variant--${variant}` : undefined,
|
|
204
|
+
], wrapperProps.className), style: menuImageUrl
|
|
192
205
|
? Object.assign(Object.assign({}, wrapperProps.style), { '--menu-image': `url(${menuImageUrl})` })
|
|
193
206
|
: wrapperProps.style, ref: wrapperRef, "aria-label": txt.title, "data-sprinkled": isBrowser, id: menuId }),
|
|
194
207
|
isMenuOpen && react_1.default.createElement(FocusTrap_js_1.FocusTrap, { atTop: true }),
|
package/esm/MainMenu.js
CHANGED
|
@@ -104,8 +104,11 @@ export const _MainMenu = (props) => {
|
|
|
104
104
|
const htmlElmDataset = htmlElm.dataset;
|
|
105
105
|
// const menuElm = menuElmRef.current as HTMLElement;
|
|
106
106
|
_setActivePanel((activePanel) => {
|
|
107
|
+
if (!newActive && !activePanel) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
107
110
|
if (!newActive) {
|
|
108
|
-
|
|
111
|
+
setLaggyActivePanel(activePanel, 1000);
|
|
109
112
|
htmlElm.scrollTop = parseInt(htmlElmDataset.scrollTop || '') || 0;
|
|
110
113
|
delete htmlElmDataset.scrollTop;
|
|
111
114
|
delete htmlElmDataset.megaPanelActive;
|
package/esm/MainMenu2.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type MainMenu2I18n = {
|
|
|
16
16
|
export declare const defaultMainMenu2Texts: DefaultTexts<MainMenu2I18n>;
|
|
17
17
|
export type MainMenu2Item = {
|
|
18
18
|
/** Visible label text */
|
|
19
|
-
label: string
|
|
19
|
+
label: string | NonNullable<ReactElement>;
|
|
20
20
|
/** Un-abbreviated label set as `title=""` and `aria-label=""` */
|
|
21
21
|
labelLong?: string;
|
|
22
22
|
/** Language of the link label */
|
|
@@ -57,6 +57,7 @@ export type MainMenu2ButtonItem = MainMenu2Item & {
|
|
|
57
57
|
};
|
|
58
58
|
export type MainMenu2CustomItem = (props: {
|
|
59
59
|
closeMenu: () => void;
|
|
60
|
+
openMenu: () => void;
|
|
60
61
|
}) => ReactElement;
|
|
61
62
|
export type MainMenu2SubMenuItem = MainMenu2Item & {
|
|
62
63
|
descr?: string;
|
|
@@ -98,8 +99,10 @@ export type MainMenu2Props = {
|
|
|
98
99
|
hot?: MainMenu2ButtonItemList;
|
|
99
100
|
extra?: MainMenu2ButtonItemList;
|
|
100
101
|
relatedTitle?: string;
|
|
101
|
-
related?:
|
|
102
|
+
related?: MainMenu2ButtonItemList;
|
|
102
103
|
};
|
|
104
|
+
/** Visual type */
|
|
105
|
+
variant?: 'default' | 'light';
|
|
103
106
|
/**
|
|
104
107
|
* NOTE: Clicking a MainMenu2 item will automatically close HannaUIState's
|
|
105
108
|
* "Hamburger menu" (a.k.a. "Mobile menu")
|
package/esm/MainMenu2.js
CHANGED
|
@@ -58,13 +58,13 @@ const iconMap = {
|
|
|
58
58
|
* Whether we're rendering the menu on the server or in the browser, etc.
|
|
59
59
|
*/
|
|
60
60
|
const getRenderers = (props) => {
|
|
61
|
-
const { onItemClick, closeMenu, isBrowser } = props;
|
|
61
|
+
const { onItemClick, closeMenu, openMenu, isBrowser } = props;
|
|
62
62
|
const renderItem = (classPrefix, item, opts = {}) => {
|
|
63
63
|
const { key, Tag = 'li', button } = opts;
|
|
64
64
|
if (typeof item === 'function') {
|
|
65
65
|
const Item = item;
|
|
66
66
|
return (React.createElement("li", { key: key, className: `${classPrefix}item` },
|
|
67
|
-
React.createElement(Item, { closeMenu: closeMenu })));
|
|
67
|
+
React.createElement(Item, { closeMenu: closeMenu, openMenu: openMenu })));
|
|
68
68
|
}
|
|
69
69
|
const linkClassName = `${classPrefix}link`;
|
|
70
70
|
const { label, labelLong, href, target, lang, controlsId, onClick, descr, icon } = item;
|
|
@@ -73,23 +73,32 @@ const getRenderers = (props) => {
|
|
|
73
73
|
React.createElement("small", { className: `${linkClassName}__descr` }, descr)));
|
|
74
74
|
const ButtonTag = button ? ButtonSecondary : 'button';
|
|
75
75
|
const LinkTag = button ? ButtonSecondary : Link;
|
|
76
|
+
const commonProps = {
|
|
77
|
+
className: linkClassName,
|
|
78
|
+
'data-icon': icon ? iconMap[icon] : undefined,
|
|
79
|
+
'arial-label': labelLong,
|
|
80
|
+
title: labelLong,
|
|
81
|
+
lang,
|
|
82
|
+
};
|
|
76
83
|
const buttonCompProps = button
|
|
77
84
|
? {
|
|
78
85
|
size: 'small',
|
|
79
|
-
'data-icon': icon && iconMap[icon],
|
|
80
86
|
}
|
|
81
87
|
: undefined;
|
|
82
|
-
|
|
88
|
+
if (label === 'Græna planið') {
|
|
89
|
+
console.log('FOOBAR', icon, icon && iconMap[icon]);
|
|
90
|
+
}
|
|
91
|
+
return (React.createElement(Tag, { key: key, className: modifiedClass(`${classPrefix}item`, item.modifier), "aria-current": item.current || undefined }, isBrowser && (onClick || href == null) ? (React.createElement(ButtonTag, Object.assign({}, commonProps, { type: "button", "aria-controls": controlsId, onClick: () => {
|
|
83
92
|
const keepOpen1 = onClick && onClick(item) === false;
|
|
84
93
|
const keepOpen2 = onItemClick && onItemClick(item) === false;
|
|
85
94
|
!(keepOpen1 || keepOpen2) && closeMenu();
|
|
86
|
-
}
|
|
95
|
+
} }, buttonCompProps),
|
|
87
96
|
label,
|
|
88
97
|
" ",
|
|
89
|
-
itemDescr)) : href ? (React.createElement(LinkTag, Object.assign({
|
|
98
|
+
itemDescr)) : href != null ? (React.createElement(LinkTag, Object.assign({}, commonProps, { href: href, hrefLang: item.hrefLang, target: target, onClick: () => {
|
|
90
99
|
const keepOpen = onItemClick && onItemClick(item) === false;
|
|
91
100
|
!keepOpen && closeMenu();
|
|
92
|
-
}
|
|
101
|
+
} }, buttonCompProps),
|
|
93
102
|
label,
|
|
94
103
|
" ",
|
|
95
104
|
itemDescr)) : null));
|
|
@@ -104,7 +113,7 @@ const getRenderers = (props) => {
|
|
|
104
113
|
};
|
|
105
114
|
// eslint-disable-next-line complexity
|
|
106
115
|
export const MainMenu2 = (props) => {
|
|
107
|
-
const { homeLink = '/', items, onItemClick, illustration, imageUrl, wrapperProps = {}, } = props;
|
|
116
|
+
const { homeLink = '/', items, onItemClick, illustration, imageUrl, variant, wrapperProps = {}, } = props;
|
|
108
117
|
const domid = useDomid(wrapperProps.id);
|
|
109
118
|
const isBrowser = useIsBrowserSide(props.ssr);
|
|
110
119
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
@@ -177,6 +186,7 @@ export const MainMenu2 = (props) => {
|
|
|
177
186
|
const { renderItem, renderList } = getRenderers({
|
|
178
187
|
onItemClick,
|
|
179
188
|
closeMenu,
|
|
189
|
+
openMenu,
|
|
180
190
|
isBrowser,
|
|
181
191
|
});
|
|
182
192
|
const homeLinkItem = Object.assign(Object.assign({}, (typeof homeLink === 'string'
|
|
@@ -184,7 +194,10 @@ export const MainMenu2 = (props) => {
|
|
|
184
194
|
: homeLink)), { modifier: 'home' });
|
|
185
195
|
const menuImageUrl = imageUrl || (illustration && getIllustrationUrl(illustration));
|
|
186
196
|
const menuId = `${domid}-menu`;
|
|
187
|
-
return (React.createElement("nav", Object.assign({}, props.wrapperProps, { className: modifiedClass('MainMenu2',
|
|
197
|
+
return (React.createElement("nav", Object.assign({}, props.wrapperProps, { className: modifiedClass('MainMenu2', [
|
|
198
|
+
isBrowser && (isMenuOpen ? 'open' : 'closed'),
|
|
199
|
+
variant && variant !== 'default' ? `variant--${variant}` : undefined,
|
|
200
|
+
], wrapperProps.className), style: menuImageUrl
|
|
188
201
|
? Object.assign(Object.assign({}, wrapperProps.style), { '--menu-image': `url(${menuImageUrl})` })
|
|
189
202
|
: wrapperProps.style, ref: wrapperRef, "aria-label": txt.title, "data-sprinkled": isBrowser, id: menuId }),
|
|
190
203
|
isMenuOpen && React.createElement(FocusTrap, { atTop: true }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reykjavik/hanna-react",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.135",
|
|
4
4
|
"author": "Reykjavík (http://www.reykjavik.is)",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Hugsmiðjan ehf (http://www.hugsmidjan.is)",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@hugsmidjan/qj": "^4.22.1",
|
|
19
19
|
"@hugsmidjan/react": "^0.4.32",
|
|
20
20
|
"@reykjavik/hanna-css": "^0.4.14",
|
|
21
|
-
"@reykjavik/hanna-utils": "^0.2.
|
|
21
|
+
"@reykjavik/hanna-utils": "^0.2.16",
|
|
22
22
|
"@types/react-autosuggest": "^10.1.0",
|
|
23
23
|
"@types/react-datepicker": "^4.8.0",
|
|
24
24
|
"@types/react-transition-group": "^4.4.0",
|