@inera/ids-react 9.0.4 → 9.1.1
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/components/alert/alert.js +1 -1
- package/components/breadcrumbs/breadcrumbs.js +1 -1
- package/components/card/card.d.ts +2 -2
- package/components/card/card.js +4 -15
- package/components/data-pagination/data-pagination.d.ts +6 -6
- package/components/data-pagination/data-pagination.js +1 -1
- package/components/dialog/dialog-base.js +1 -1
- package/components/dialog/dialog.js +12 -13
- package/components/dropdown/dropdown-base.js +2 -2
- package/components/dropdown/dropdown.js +1 -0
- package/components/footer-1177-pro/footer-1177-pro.d.ts +2 -1
- package/components/footer-1177-pro/footer-1177-pro.js +2 -2
- package/components/form/checkbox/checkbox-group-base.d.ts +2 -1
- package/components/form/checkbox/checkbox-group-base.js +4 -2
- package/components/form/checkbox/checkbox-group.d.ts +1 -0
- package/components/form/checkbox/checkbox-group.js +4 -3
- package/components/form/datepicker/datepicker.d.ts +2 -1
- package/components/form/datepicker/datepicker.js +60 -37
- package/components/form/input/input-base.d.ts +2 -1
- package/components/form/input/input-base.js +11 -10
- package/components/form/input/input.d.ts +1 -0
- package/components/form/radio/radio-group-base.d.ts +2 -1
- package/components/form/radio/radio-group-base.js +4 -2
- package/components/form/radio/radio-group.d.ts +1 -0
- package/components/form/radio-button/radio-button-group-base.js +1 -1
- package/components/form/select/select.d.ts +1 -1
- package/components/form/select/select.js +2 -2
- package/components/form/select-multiple/select-multiple-base.d.ts +3 -3
- package/components/form/select-multiple/select-multiple-base.js +5 -6
- package/components/form/select-multiple/select-multiple.d.ts +1 -1
- package/components/form/select-multiple/select-multiple.js +10 -23
- package/components/form/textarea/textarea.d.ts +1 -1
- package/components/form/textarea/textarea.js +2 -2
- package/components/form/time/time.d.ts +1 -1
- package/components/form/time/time.js +2 -2
- package/components/{alert → global-alert}/global-alert.d.ts +1 -1
- package/components/{alert → global-alert}/global-alert.js +2 -2
- package/components/header-1177/header-1177-avatar-base.d.ts +2 -1
- package/components/header-1177/header-1177-avatar-base.js +2 -2
- package/components/header-1177/header-1177-avatar.js +11 -24
- package/components/header-1177/header-1177-menu-mobile-base.d.ts +2 -1
- package/components/header-1177/header-1177-menu-mobile-base.js +2 -2
- package/components/header-1177/header-1177-menu-mobile.js +9 -14
- package/components/header-1177/header-1177-nav-item-base.d.ts +2 -1
- package/components/header-1177/header-1177-nav-item-base.js +2 -2
- package/components/header-1177/header-1177-nav-item.js +8 -14
- package/components/header-1177-admin/header-1177-admin-avatar-base.d.ts +2 -1
- package/components/header-1177-admin/header-1177-admin-avatar-base.js +2 -2
- package/components/header-1177-admin/header-1177-admin-avatar-mobile-base.d.ts +2 -1
- package/components/header-1177-admin/header-1177-admin-avatar-mobile-base.js +2 -2
- package/components/header-1177-admin/header-1177-admin-avatar-mobile.js +12 -24
- package/components/header-1177-admin/header-1177-admin-avatar.js +11 -14
- package/components/header-1177-admin/header-1177-admin-menu-mobile-base.d.ts +2 -1
- package/components/header-1177-admin/header-1177-admin-menu-mobile-base.js +2 -2
- package/components/header-1177-admin/header-1177-admin-menu-mobile.js +9 -14
- package/components/header-1177-admin/header-1177-admin-nav-item-base.d.ts +2 -1
- package/components/header-1177-admin/header-1177-admin-nav-item-base.js +2 -2
- package/components/header-1177-admin/header-1177-admin-nav-item.js +8 -14
- package/components/header-1177-pro/header-1177-pro-avatar-base.d.ts +2 -1
- package/components/header-1177-pro/header-1177-pro-avatar-base.js +2 -2
- package/components/header-1177-pro/header-1177-pro-avatar-mobile-base.d.ts +2 -1
- package/components/header-1177-pro/header-1177-pro-avatar-mobile-base.js +2 -2
- package/components/header-1177-pro/header-1177-pro-avatar-mobile.js +12 -24
- package/components/header-1177-pro/header-1177-pro-avatar.js +11 -14
- package/components/header-1177-pro/header-1177-pro-menu-mobile-base.d.ts +2 -1
- package/components/header-1177-pro/header-1177-pro-menu-mobile-base.js +2 -2
- package/components/header-1177-pro/header-1177-pro-menu-mobile.js +9 -14
- package/components/header-1177-pro/header-1177-pro-nav-item-base.d.ts +2 -1
- package/components/header-1177-pro/header-1177-pro-nav-item-base.js +2 -2
- package/components/header-1177-pro/header-1177-pro-nav-item.js +8 -14
- package/components/header-inera/header-inera-menu-mobile-base.d.ts +2 -1
- package/components/header-inera/header-inera-menu-mobile-base.js +2 -2
- package/components/header-inera/header-inera-menu-mobile.js +9 -14
- package/components/header-inera/header-inera-nav-item-base.d.ts +2 -1
- package/components/header-inera/header-inera-nav-item-base.js +2 -2
- package/components/header-inera/header-inera-nav-item.js +8 -14
- package/components/header-inera-admin/header-inera-admin-avatar-base.d.ts +2 -1
- package/components/header-inera-admin/header-inera-admin-avatar-base.js +2 -2
- package/components/header-inera-admin/header-inera-admin-avatar-mobile-base.d.ts +2 -1
- package/components/header-inera-admin/header-inera-admin-avatar-mobile-base.js +2 -2
- package/components/header-inera-admin/header-inera-admin-avatar-mobile.js +12 -24
- package/components/header-inera-admin/header-inera-admin-avatar.js +12 -16
- package/components/header-inera-admin/header-inera-admin-menu-mobile-base.d.ts +2 -1
- package/components/header-inera-admin/header-inera-admin-menu-mobile-base.js +2 -2
- package/components/header-inera-admin/header-inera-admin-menu-mobile.js +9 -14
- package/components/header-inera-admin/header-inera-admin-nav-item-base.d.ts +2 -1
- package/components/header-inera-admin/header-inera-admin-nav-item-base.js +2 -2
- package/components/header-inera-admin/header-inera-admin-nav-item.js +8 -14
- package/components/popover/popover-content.js +1 -1
- package/components/popover/popover.js +1 -1
- package/components/puff-list/puff-list-item-header.js +1 -1
- package/components/puff-list/puff-list-item.js +1 -1
- package/components/side-panel/side-panel-base.js +6 -2
- package/components/side-panel/side-panel.js +50 -41
- package/components/stepper/step-base.js +1 -1
- package/components/stepper/step.js +12 -10
- package/components/tabs/tab-panel.js +1 -1
- package/components/tabs/tab.js +1 -1
- package/components/tabs/tabs.d.ts +1 -1
- package/components/tabs/tabs.js +8 -4
- package/components/utils/hooks/useClickOutside.d.ts +10 -0
- package/components/utils/hooks/useClickOutside.js +31 -0
- package/components/utils/hooks/useEsc.d.ts +10 -0
- package/components/utils/hooks/useEsc.js +27 -0
- package/components/utils/hooks/useHasFocusableChildren.d.ts +2 -0
- package/components/utils/hooks/useHasFocusableChildren.js +25 -0
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/package.json +2 -2
- /package/components/{alert → global-alert}/global-alert-base.d.ts +0 -0
- /package/components/{alert → global-alert}/global-alert-base.js +0 -0
|
@@ -2,6 +2,7 @@ import { ChangeEvent, ReactNode, FieldsetHTMLAttributes } from "react";
|
|
|
2
2
|
interface IDSRadioGroupProps extends FieldsetHTMLAttributes<HTMLFieldSetElement> {
|
|
3
3
|
name?: string;
|
|
4
4
|
legend?: string;
|
|
5
|
+
hideLegend?: boolean;
|
|
5
6
|
errorMsg?: string | ReactNode;
|
|
6
7
|
compact?: boolean;
|
|
7
8
|
invalid?: boolean;
|
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
|
|
4
4
|
function IDSRadioButtonGroupBase({ legend, groupRef, tooltip, children, className, ...props }) {
|
|
5
|
-
return (jsxs("fieldset", { ref: groupRef, className: clsx("ids-form-group__fieldset", className), ...props, children: [legend ? (jsx("div", { className: "ids-label-wrapper", children: jsxs("legend", { children: [legend, tooltip && jsx("span", { className: "ids-legend__tooltip", children: tooltip })] }) })) : null, children] }));
|
|
5
|
+
return (jsxs("fieldset", { ref: groupRef, className: clsx("ids-form-group__fieldset", "ids-form-group__fieldset--compact", className), ...props, children: [legend ? (jsx("div", { className: "ids-label-wrapper", children: jsxs("legend", { children: [legend, tooltip && jsx("span", { className: "ids-legend__tooltip", children: tooltip })] }) })) : null, children] }));
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export { IDSRadioButtonGroupBase };
|
|
@@ -11,6 +11,6 @@ export interface IDSSelectProps extends SelectHTMLAttributes<HTMLSelectElement>
|
|
|
11
11
|
tooltip?: ReactNode;
|
|
12
12
|
dataTestId?: string;
|
|
13
13
|
noValidation?: boolean;
|
|
14
|
-
|
|
14
|
+
validationOnBlur?: boolean;
|
|
15
15
|
}
|
|
16
16
|
export declare const IDSSelect: import("react").ForwardRefExoticComponent<IDSSelectProps & import("react").RefAttributes<HTMLSelectElement>>;
|
|
@@ -4,10 +4,10 @@ import { forwardRef, useId, useRef, useImperativeHandle } from 'react';
|
|
|
4
4
|
import { useInputValidity } from '../form-hooks/useInputValidity.js';
|
|
5
5
|
import { IDSSelectBase } from './select-base.js';
|
|
6
6
|
|
|
7
|
-
const IDSSelect = forwardRef(({ id, label, errorMsg, disabled, required, light, focusAnchor, tooltip, dataTestId, invalid = false, noValidation = false,
|
|
7
|
+
const IDSSelect = forwardRef(({ id, label, errorMsg, disabled, required, light, focusAnchor, tooltip, dataTestId, invalid = false, noValidation = false, validationOnBlur = false, children, style, ...props }, ref) => {
|
|
8
8
|
const errorMsgId = `select-error-${useId()}`;
|
|
9
9
|
const selectRef = useRef(null);
|
|
10
|
-
const hasValidValue = useInputValidity(selectRef,
|
|
10
|
+
const hasValidValue = useInputValidity(selectRef, validationOnBlur);
|
|
11
11
|
const isInvalid = (invalid || !hasValidValue) && !noValidation;
|
|
12
12
|
useImperativeHandle(ref, () => selectRef.current);
|
|
13
13
|
return (jsx(IDSSelectBase, { ...props, style: style, id: id, label: label, errorMsg: errorMsg, disabled: disabled, required: required, light: light, focusAnchor: focusAnchor, tooltip: tooltip, dataTestId: dataTestId, selectRef: selectRef, errorMsgId: errorMsgId, invalid: isInvalid, children: children }));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CSSProperties, ReactNode } from "react";
|
|
2
2
|
export interface IDSSelectMultipleBaseProps {
|
|
3
|
-
labelId?: string;
|
|
4
3
|
id?: string;
|
|
4
|
+
labelId?: string;
|
|
5
5
|
label?: string;
|
|
6
6
|
expanded?: boolean;
|
|
7
7
|
placeholder?: string;
|
|
@@ -16,7 +16,7 @@ export interface IDSSelectMultipleBaseProps {
|
|
|
16
16
|
light?: boolean;
|
|
17
17
|
focusAnchor?: boolean;
|
|
18
18
|
tooltip?: ReactNode;
|
|
19
|
-
|
|
19
|
+
buttonRef?: React.Ref<HTMLButtonElement>;
|
|
20
20
|
componentRef?: React.Ref<HTMLDivElement>;
|
|
21
21
|
children?: ReactNode;
|
|
22
22
|
className?: string;
|
|
@@ -24,4 +24,4 @@ export interface IDSSelectMultipleBaseProps {
|
|
|
24
24
|
client?: boolean;
|
|
25
25
|
style?: CSSProperties;
|
|
26
26
|
}
|
|
27
|
-
export declare function IDSSelectMultipleBase({
|
|
27
|
+
export declare function IDSSelectMultipleBase({ id, labelId, label, placeholder, numbCheckedBoxes, selectedLabel, selectedLabelPlural, expanded, maxHeight, tooltip, componentRef, buttonRef, invalid, disabled, ariaDisabled, light, focusAnchor, className, children, style, onClick, client }: IDSSelectMultipleBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,10 +2,9 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
function IDSSelectMultipleBase({
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const inputLabelId = !!labelId ? labelId : `select-multiple-base-label-${reactId}`;
|
|
5
|
+
function IDSSelectMultipleBase({ id, labelId, label, placeholder, numbCheckedBoxes, selectedLabel = "vald", selectedLabelPlural = "valda", expanded, maxHeight = "", tooltip, componentRef, buttonRef, invalid, disabled, ariaDisabled, light, focusAnchor, className, children, style, onClick, client = false }) {
|
|
6
|
+
const defaultLabelId = !!labelId ? labelId : `select-multiple-base-label-${useId()}`;
|
|
7
|
+
const dropdownId = `select-multiple-dropdown-${useId()}`;
|
|
9
8
|
const displayedValue = numbCheckedBoxes === 0 || !numbCheckedBoxes
|
|
10
9
|
? placeholder
|
|
11
10
|
: numbCheckedBoxes === 1
|
|
@@ -16,10 +15,10 @@ function IDSSelectMultipleBase({ labelId, id, label, placeholder, numbCheckedBox
|
|
|
16
15
|
onClick
|
|
17
16
|
}
|
|
18
17
|
: {};
|
|
19
|
-
return (jsxs("div", { className: clsx("ids-select-multiple", className), ref: componentRef, style: style, children: [label && (jsxs("div", { className: "ids-label-wrapper ids-label-wrapper--margin-bottom", children: [jsx("label", { id:
|
|
18
|
+
return (jsxs("div", { className: clsx("ids-select-multiple", className), ref: componentRef, style: style, children: [label && (jsxs("div", { className: "ids-label-wrapper ids-label-wrapper--margin-bottom", children: [jsx("label", { id: defaultLabelId, className: clsx("ids-label", { "ids-label--disabled": disabled || ariaDisabled }), children: label }), tooltip && jsx("span", { className: "ids-label__tooltip", children: tooltip })] })), jsx("div", { className: "ids-select-multiple__select-wrapper", children: jsx("button", { ref: buttonRef, id: id, "aria-labelledby": defaultLabelId, type: "button", "aria-haspopup": "dialog", "aria-controls": dropdownId, className: clsx("ids-select-multiple__select", {
|
|
20
19
|
"ids-input--light": light,
|
|
21
20
|
"ids-focus-anchor": focusAnchor
|
|
22
|
-
}),
|
|
21
|
+
}), disabled: disabled, "aria-disabled": ariaDisabled, "aria-expanded": expanded, "aria-invalid": invalid, ...clickHandler, children: displayedValue }) }), jsx("div", { className: "ids-select-multiple__dropdown-wrapper", id: dropdownId, children: jsx("div", { className: clsx("ids-select-multiple__dropdown", {
|
|
23
22
|
"ids-select-multiple__dropdown--expanded": expanded
|
|
24
23
|
}), children: jsx("div", { className: "ids-select-multiple__dropdown-scroll-area", style: { maxHeight }, children: children }) }) })] }));
|
|
25
24
|
}
|
|
@@ -19,7 +19,7 @@ export interface IDSSelectMultipleProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
19
19
|
dataTestId?: string;
|
|
20
20
|
id?: string;
|
|
21
21
|
}
|
|
22
|
-
export declare function IDSSelectMultiple({ invalid, noValidation, expanded, errorMsg, ariaDisabled, style, children, ...props }: IDSSelectMultipleProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function IDSSelectMultiple({ label, id, invalid, noValidation, expanded, errorMsg, ariaDisabled, style, children, ...props }: IDSSelectMultipleProps): import("react/jsx-runtime").JSX.Element;
|
|
23
23
|
export declare namespace IDSSelectMultiple {
|
|
24
24
|
var displayName: string;
|
|
25
25
|
}
|
|
@@ -3,12 +3,18 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { IDSSelectMultipleBase } from './select-multiple-base.js';
|
|
5
5
|
import { IDSCheckboxGroup } from '../checkbox/checkbox-group.js';
|
|
6
|
+
import { useClickOutside } from '../../utils/hooks/useClickOutside.js';
|
|
7
|
+
import { useEsc } from '../../utils/hooks/useEsc.js';
|
|
6
8
|
|
|
7
|
-
function IDSSelectMultiple({ invalid = false, noValidation = false, expanded = false, errorMsg, ariaDisabled = false, style, children, ...props }) {
|
|
9
|
+
function IDSSelectMultiple({ label, id, invalid = false, noValidation = false, expanded = false, errorMsg, ariaDisabled = false, style, children, ...props }) {
|
|
8
10
|
const [isExpanded, setIsExpanded] = useState(expanded);
|
|
9
11
|
const [checkboxListInvalid, setCheckboxListInvalid] = useState(false);
|
|
10
|
-
const
|
|
12
|
+
const buttonRef = useRef(null);
|
|
11
13
|
const componentRef = useRef(null);
|
|
14
|
+
useClickOutside([componentRef, buttonRef], () => {
|
|
15
|
+
setIsExpanded(false);
|
|
16
|
+
});
|
|
17
|
+
useEsc(() => setIsExpanded(false), buttonRef, isExpanded);
|
|
12
18
|
useEffect(() => {
|
|
13
19
|
if (checkboxListInvalid && !noValidation)
|
|
14
20
|
setIsExpanded(true);
|
|
@@ -16,28 +22,9 @@ function IDSSelectMultiple({ invalid = false, noValidation = false, expanded = f
|
|
|
16
22
|
useEffect(() => {
|
|
17
23
|
setIsExpanded(expanded);
|
|
18
24
|
}, [expanded]);
|
|
19
|
-
|
|
20
|
-
const handleClickOutside = (event) => {
|
|
21
|
-
if (componentRef.current && !componentRef.current.contains(event.target)) {
|
|
22
|
-
setIsExpanded(false);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const handleKeyDown = (event) => {
|
|
26
|
-
if (event.key === "Escape")
|
|
27
|
-
setIsExpanded(false);
|
|
28
|
-
};
|
|
29
|
-
document.addEventListener("click", handleClickOutside);
|
|
30
|
-
document.addEventListener("focusin", handleClickOutside);
|
|
31
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
32
|
-
return () => {
|
|
33
|
-
document.removeEventListener("click", handleClickOutside);
|
|
34
|
-
document.removeEventListener("focusin", handleClickOutside);
|
|
35
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
36
|
-
};
|
|
37
|
-
}, []);
|
|
38
|
-
return (jsx(IDSSelectMultipleBase, { ...props, style: style, client: true, componentRef: componentRef, inputRef: inputRef, invalid: invalid || (!noValidation && checkboxListInvalid), expanded: isExpanded, ariaDisabled: ariaDisabled, onClick: () => {
|
|
25
|
+
return (jsx(IDSSelectMultipleBase, { ...props, style: style, client: true, label: label, id: id, componentRef: componentRef, buttonRef: buttonRef, invalid: invalid || (!noValidation && checkboxListInvalid), expanded: isExpanded, ariaDisabled: ariaDisabled, onClick: () => {
|
|
39
26
|
setIsExpanded(!isExpanded);
|
|
40
|
-
}, children: jsx(IDSCheckboxGroup, { block: true, noValidation: noValidation, errorMsg: errorMsg, onValidityChange: (isValid) => {
|
|
27
|
+
}, children: jsx(IDSCheckboxGroup, { block: true, legend: label, hideLegend: true, noValidation: noValidation, errorMsg: errorMsg, onValidityChange: (isValid) => {
|
|
41
28
|
if (!isValid && !noValidation) {
|
|
42
29
|
setIsExpanded(true);
|
|
43
30
|
setCheckboxListInvalid(!isValid);
|
|
@@ -6,7 +6,7 @@ export interface IDSTextareaProps extends React.TextareaHTMLAttributes<HTMLTextA
|
|
|
6
6
|
invalid?: boolean;
|
|
7
7
|
required?: boolean;
|
|
8
8
|
noValidation?: boolean;
|
|
9
|
-
|
|
9
|
+
validationOnBlur?: boolean;
|
|
10
10
|
autoSize?: boolean;
|
|
11
11
|
noResize?: boolean;
|
|
12
12
|
block?: boolean;
|
|
@@ -4,10 +4,10 @@ import { forwardRef, useRef, useImperativeHandle } from 'react';
|
|
|
4
4
|
import { useInputValidity } from '../form-hooks/useInputValidity.js';
|
|
5
5
|
import { IDSTextareaBase } from './textarea-base.js';
|
|
6
6
|
|
|
7
|
-
const IDSTextarea = forwardRef(({ id, label, hint, errorMsg, disabled = false, invalid = false, required = false, noValidation = false,
|
|
7
|
+
const IDSTextarea = forwardRef(({ id, label, hint, errorMsg, disabled = false, invalid = false, required = false, noValidation = false, validationOnBlur = false, autoSize = false, noResize = false, block = false, light = false, readOnly = false, focusAnchor = false, dataTestId = "", tooltip, className, children, style, ...props }, ref) => {
|
|
8
8
|
const textareaRef = useRef(null);
|
|
9
9
|
useImperativeHandle(ref, () => textareaRef.current);
|
|
10
|
-
const isValid = useInputValidity(textareaRef,
|
|
10
|
+
const isValid = useInputValidity(textareaRef, validationOnBlur);
|
|
11
11
|
const isInvalid = (invalid || !isValid) && !noValidation;
|
|
12
12
|
return (jsx(IDSTextareaBase, { id: id, label: label, hint: hint, errorMsg: errorMsg, invalid: isInvalid, required: required, disabled: disabled, readOnly: readOnly, light: light, autoSize: autoSize, noResize: noResize, block: block, focusAnchor: focusAnchor, tooltip: tooltip, className: className, textareaRef: textareaRef, dataTestId: dataTestId, style: style, ...props }));
|
|
13
13
|
});
|
|
@@ -11,6 +11,6 @@ export interface IDSTimeProps extends React.InputHTMLAttributes<HTMLInputElement
|
|
|
11
11
|
errorMsgId?: string;
|
|
12
12
|
dataTestId?: string;
|
|
13
13
|
noValidation?: boolean;
|
|
14
|
-
|
|
14
|
+
validationOnBlur?: boolean;
|
|
15
15
|
}
|
|
16
16
|
export declare const IDSTime: import("react").ForwardRefExoticComponent<IDSTimeProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -4,10 +4,10 @@ import { forwardRef, useRef, useImperativeHandle } from 'react';
|
|
|
4
4
|
import { useInputValidity } from '../form-hooks/useInputValidity.js';
|
|
5
5
|
import { IDSTimeBase } from './time-base.js';
|
|
6
6
|
|
|
7
|
-
const IDSTime = forwardRef(({ invalid = false, noValidation = false,
|
|
7
|
+
const IDSTime = forwardRef(({ invalid = false, noValidation = false, validationOnBlur = false, style, ...props }, ref) => {
|
|
8
8
|
const inputRef = useRef(null);
|
|
9
9
|
useImperativeHandle(ref, () => inputRef.current);
|
|
10
|
-
const hasValidValue = useInputValidity(inputRef,
|
|
10
|
+
const hasValidValue = useInputValidity(inputRef, validationOnBlur);
|
|
11
11
|
const isInvalid = (invalid || !hasValidValue) && !noValidation;
|
|
12
12
|
return jsx(IDSTimeBase, { invalid: isInvalid, inputRef: inputRef, ...props, style: style });
|
|
13
13
|
});
|
|
@@ -3,5 +3,5 @@ import { IDSGlobalAlertBase } from "./global-alert-base";
|
|
|
3
3
|
interface IDSGlobalAlertProps extends Omit<React.ComponentProps<typeof IDSGlobalAlertBase>, "onToggle" | "contentId"> {
|
|
4
4
|
onCollapsedChange?: (isCollapsed: boolean) => void;
|
|
5
5
|
}
|
|
6
|
-
export declare function IDSGlobalAlert({ collapsed, onCollapsedChange, ...props }: IDSGlobalAlertProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare function IDSGlobalAlert({ collapsed, onCollapsedChange, className, ...props }: IDSGlobalAlertProps): import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
export {};
|
|
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useEffect } from 'react';
|
|
4
4
|
import { IDSGlobalAlertBase } from './global-alert-base.js';
|
|
5
5
|
|
|
6
|
-
function IDSGlobalAlert({ collapsed = false, onCollapsedChange, ...props }) {
|
|
6
|
+
function IDSGlobalAlert({ collapsed = false, onCollapsedChange, className, ...props }) {
|
|
7
7
|
const [isCollapsed, setIsCollapsed] = useState(collapsed);
|
|
8
8
|
useEffect(() => {
|
|
9
9
|
setIsCollapsed(collapsed);
|
|
@@ -13,7 +13,7 @@ function IDSGlobalAlert({ collapsed = false, onCollapsedChange, ...props }) {
|
|
|
13
13
|
setIsCollapsed(newState);
|
|
14
14
|
onCollapsedChange?.(newState);
|
|
15
15
|
};
|
|
16
|
-
return jsx(IDSGlobalAlertBase, { ...props, client: true, collapsed: isCollapsed, onToggle: handleToggleCollapse });
|
|
16
|
+
return (jsx(IDSGlobalAlertBase, { ...props, client: true, collapsed: isCollapsed, onToggle: handleToggleCollapse, className: className }));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export { IDSGlobalAlert };
|
|
@@ -11,6 +11,7 @@ interface IDSHeader1177AvatarBaseProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
11
11
|
onToggle?: () => void;
|
|
12
12
|
componentRef?: React.RefObject<HTMLDivElement>;
|
|
13
13
|
menuRef?: React.RefObject<HTMLDivElement>;
|
|
14
|
+
buttonRef?: React.RefObject<HTMLButtonElement>;
|
|
14
15
|
}
|
|
15
|
-
export declare function IDSHeader1177AvatarBase({ username, agent, children, unresponsive, expanded, hide, noMobileMenu, client, onToggle, componentRef, menuRef, ...props }: IDSHeader1177AvatarBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function IDSHeader1177AvatarBase({ username, agent, children, unresponsive, expanded, hide, noMobileMenu, client, onToggle, componentRef, menuRef, buttonRef, ...props }: IDSHeader1177AvatarBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
16
17
|
export {};
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
function IDSHeader1177AvatarBase({ username, agent, children, unresponsive = false, expanded = false, hide = false, noMobileMenu = false, client = false, onToggle, componentRef, menuRef, ...props }) {
|
|
5
|
+
function IDSHeader1177AvatarBase({ username, agent, children, unresponsive = false, expanded = false, hide = false, noMobileMenu = false, client = false, onToggle, componentRef, menuRef, buttonRef, ...props }) {
|
|
6
6
|
if (hide)
|
|
7
7
|
return null;
|
|
8
8
|
const menuId = `header-1177-avatar-menu${useId()}`;
|
|
@@ -13,7 +13,7 @@ function IDSHeader1177AvatarBase({ username, agent, children, unresponsive = fal
|
|
|
13
13
|
: {};
|
|
14
14
|
return (jsx("div", { ref: componentRef, className: clsx("ids-header-1177-avatar", {
|
|
15
15
|
"ids-header-1177-avatar--unresponsive": unresponsive
|
|
16
|
-
}), style: { flexGrow: username ? "1" : "0" }, ...props, children: username && (jsx("div", { className: "ids-header-1177-avatar__avatar", children: jsxs("div", { className: "ids-header-1177-avatar__menu-wrapper", children: [jsx("button", { className: clsx("ids-header-1177-avatar__button", {
|
|
16
|
+
}), style: { flexGrow: username ? "1" : "0" }, ...props, children: username && (jsx("div", { className: "ids-header-1177-avatar__avatar", children: jsxs("div", { className: "ids-header-1177-avatar__menu-wrapper", children: [jsx("button", { ref: buttonRef, className: clsx("ids-header-1177-avatar__button", {
|
|
17
17
|
"ids-header-1177-avatar__button--expanded": expanded
|
|
18
18
|
}), ...toggleHandler, "aria-controls": menuId, "aria-expanded": expanded, children: jsx("div", { className: "ids-header-1177-avatar__name", title: username, children: username }) }), jsxs("div", { ref: menuRef, id: menuId, className: clsx("ids-header-1177-avatar__menu", {
|
|
19
19
|
"ids-header-1177-avatar__menu--expanded": expanded,
|
|
@@ -3,6 +3,9 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { useHeaderContext } from '../utils/contexts/HeaderContext.js';
|
|
5
5
|
import { IDSHeader1177AvatarBase } from './header-1177-avatar-base.js';
|
|
6
|
+
import { useFocusTrap } from '../utils/hooks/useFocusTrap.js';
|
|
7
|
+
import { useClickOutside } from '../utils/hooks/useClickOutside.js';
|
|
8
|
+
import { useEsc } from '../utils/hooks/useEsc.js';
|
|
6
9
|
|
|
7
10
|
function IDSHeader1177Avatar({ expanded = false, persistent = false, children, ...props }) {
|
|
8
11
|
const headerContext = useHeaderContext();
|
|
@@ -11,30 +14,14 @@ function IDSHeader1177Avatar({ expanded = false, persistent = false, children, .
|
|
|
11
14
|
const [isExpanded, setIsExpanded] = useState(expanded);
|
|
12
15
|
const componentRef = useRef(null);
|
|
13
16
|
const menuRef = useRef(null);
|
|
17
|
+
const buttonRef = useRef(null);
|
|
18
|
+
useFocusTrap(componentRef.current, isExpanded && !persistent);
|
|
19
|
+
useClickOutside([componentRef, buttonRef], () => {
|
|
20
|
+
if (!persistent)
|
|
21
|
+
setIsExpanded(false);
|
|
22
|
+
});
|
|
23
|
+
useEsc(() => setIsExpanded(false), buttonRef, isExpanded && !persistent);
|
|
14
24
|
const toggleAvatar = () => setIsExpanded(prev => !prev);
|
|
15
|
-
// Close when clicking outside
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
const handleClickOutside = (event) => {
|
|
18
|
-
if (!persistent && componentRef.current && !componentRef.current.contains(event.target)) {
|
|
19
|
-
setIsExpanded(false);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
23
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
24
|
-
}, [persistent]);
|
|
25
|
-
// Escape should also close
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
if (!isExpanded || persistent)
|
|
28
|
-
return;
|
|
29
|
-
const handleKeyDown = (event) => {
|
|
30
|
-
if (event.key === "Escape") {
|
|
31
|
-
event.preventDefault();
|
|
32
|
-
setIsExpanded(false);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
36
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
37
|
-
}, [isExpanded, persistent]);
|
|
38
25
|
// Clicking a link inside dropdown closes it
|
|
39
26
|
useEffect(() => {
|
|
40
27
|
if (!persistent && isExpanded) {
|
|
@@ -44,7 +31,7 @@ function IDSHeader1177Avatar({ expanded = false, persistent = false, children, .
|
|
|
44
31
|
}
|
|
45
32
|
}, [isExpanded, persistent]);
|
|
46
33
|
const closeOnClick = () => setIsExpanded(false);
|
|
47
|
-
return (jsx(IDSHeader1177AvatarBase, { ...props, client: true, expanded: isExpanded, onToggle: toggleAvatar, componentRef: componentRef, menuRef: menuRef, unresponsive: headerContext?.unresponsive ?? false, children: children }));
|
|
34
|
+
return (jsx(IDSHeader1177AvatarBase, { ...props, client: true, expanded: isExpanded, onToggle: toggleAvatar, componentRef: componentRef, menuRef: menuRef, buttonRef: buttonRef, unresponsive: headerContext?.unresponsive ?? false, children: children }));
|
|
48
35
|
}
|
|
49
36
|
|
|
50
37
|
export { IDSHeader1177Avatar };
|
|
@@ -6,7 +6,8 @@ interface IDSHeader1177MenuMobileBaseProps extends HTMLAttributes<HTMLDivElement
|
|
|
6
6
|
onToggleMenu?: () => void;
|
|
7
7
|
componentRef?: React.Ref<HTMLDivElement>;
|
|
8
8
|
menuRef?: React.Ref<HTMLDivElement>;
|
|
9
|
+
buttonRef?: React.Ref<HTMLButtonElement>;
|
|
9
10
|
client?: boolean;
|
|
10
11
|
}
|
|
11
|
-
export declare function IDSHeader1177MenuMobileBase({ srLabel, expanded, unresponsive, children, onToggleMenu, client, componentRef, menuRef, ...props }: IDSHeader1177MenuMobileBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function IDSHeader1177MenuMobileBase({ srLabel, expanded, unresponsive, children, onToggleMenu, client, componentRef, menuRef, buttonRef, ...props }: IDSHeader1177MenuMobileBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
12
13
|
export {};
|
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
function IDSHeader1177MenuMobileBase({ srLabel = "Meny", expanded = false, unresponsive, children, onToggleMenu, client = false, componentRef, menuRef, ...props }) {
|
|
5
|
+
function IDSHeader1177MenuMobileBase({ srLabel = "Meny", expanded = false, unresponsive, children, onToggleMenu, client = false, componentRef, menuRef, buttonRef, ...props }) {
|
|
6
6
|
const menuId = `header-1177-menu-${useId()}`;
|
|
7
7
|
const toggleHandler = client && onToggleMenu
|
|
8
8
|
? {
|
|
@@ -12,7 +12,7 @@ function IDSHeader1177MenuMobileBase({ srLabel = "Meny", expanded = false, unres
|
|
|
12
12
|
return (jsxs("div", { ...props, className: clsx("ids-header-1177-menu-mobile", {
|
|
13
13
|
"ids-header-1177-menu-mobile--expanded": expanded,
|
|
14
14
|
"ids-header-1177-menu-mobile--unresponsive": unresponsive
|
|
15
|
-
}), ref: componentRef, children: [jsx("button", { ...toggleHandler, "aria-expanded": expanded, "aria-label": srLabel, "aria-controls": menuId, className: "ids-header-1177-menu-mobile__button", children: jsx("div", { className: "ids-hamburger", children: jsx("span", { className: "ids-hamburger__lines" }) }) }), expanded && (jsx("div", { id: menuId, className: "ids-header-1177-menu-mobile__items", ref: menuRef, children: children }))] }));
|
|
15
|
+
}), ref: componentRef, children: [jsx("button", { ...toggleHandler, ref: buttonRef, "aria-expanded": expanded, "aria-label": srLabel, "aria-controls": menuId, className: "ids-header-1177-menu-mobile__button", children: jsx("div", { className: "ids-hamburger", children: jsx("span", { className: "ids-hamburger__lines" }) }) }), expanded && (jsx("div", { id: menuId, className: "ids-header-1177-menu-mobile__items", ref: menuRef, children: children }))] }));
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export { IDSHeader1177MenuMobileBase };
|
|
@@ -3,12 +3,20 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { IDSHeader1177MenuMobileBase } from './header-1177-menu-mobile-base.js';
|
|
5
5
|
import { useHeaderContext } from '../utils/contexts/HeaderContext.js';
|
|
6
|
+
import { useClickOutside } from '../utils/hooks/useClickOutside.js';
|
|
7
|
+
import { useEsc } from '../utils/hooks/useEsc.js';
|
|
6
8
|
|
|
7
9
|
function IDSHeader1177MenuMobile({ srLabel = "Meny", persistent = false, expanded = false, children, onExpanded, onClosed, ...props }) {
|
|
8
10
|
const [isExpanded, setIsExpanded] = useState(expanded);
|
|
9
11
|
const headerContext = useHeaderContext();
|
|
10
12
|
const componentRef = useRef(null);
|
|
11
13
|
const menuRef = useRef(null);
|
|
14
|
+
const buttonRef = useRef(null);
|
|
15
|
+
useClickOutside([componentRef, buttonRef], () => {
|
|
16
|
+
if (!persistent)
|
|
17
|
+
setIsExpanded(false);
|
|
18
|
+
});
|
|
19
|
+
useEsc(() => setIsExpanded(false), buttonRef, isExpanded && !persistent);
|
|
12
20
|
const handleLinkClick = () => {
|
|
13
21
|
setIsExpanded(false);
|
|
14
22
|
onClosed?.();
|
|
@@ -35,20 +43,7 @@ function IDSHeader1177MenuMobile({ srLabel = "Meny", persistent = false, expande
|
|
|
35
43
|
return () => links.forEach(link => link.removeEventListener("click", handleLinkClick));
|
|
36
44
|
}
|
|
37
45
|
}, [isExpanded, persistent]);
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (!isExpanded || persistent)
|
|
41
|
-
return;
|
|
42
|
-
const handleKeyDown = (event) => {
|
|
43
|
-
if (event.key === "Escape") {
|
|
44
|
-
event.preventDefault();
|
|
45
|
-
setIsExpanded(false);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
49
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
50
|
-
}, [isExpanded, persistent]);
|
|
51
|
-
return (jsx(IDSHeader1177MenuMobileBase, { ...props, client: true, srLabel: srLabel, expanded: isExpanded, unresponsive: headerContext?.unresponsive, onToggleMenu: toggleMenu, componentRef: componentRef, menuRef: menuRef, children: children }));
|
|
46
|
+
return (jsx(IDSHeader1177MenuMobileBase, { ...props, client: true, srLabel: srLabel, expanded: isExpanded, unresponsive: headerContext?.unresponsive, onToggleMenu: toggleMenu, componentRef: componentRef, menuRef: menuRef, buttonRef: buttonRef, children: children }));
|
|
52
47
|
}
|
|
53
48
|
|
|
54
49
|
export { IDSHeader1177MenuMobile };
|
|
@@ -11,8 +11,9 @@ export interface IDSHeader1177NavItemBaseProps extends HTMLAttributes<HTMLElemen
|
|
|
11
11
|
col4?: React.ReactNode;
|
|
12
12
|
componentRef?: React.Ref<HTMLDivElement>;
|
|
13
13
|
menuRef?: React.Ref<HTMLDivElement>;
|
|
14
|
+
buttonRef?: React.Ref<HTMLButtonElement>;
|
|
14
15
|
onToggleItem?: () => void;
|
|
15
16
|
unresponsive?: boolean;
|
|
16
17
|
client?: boolean;
|
|
17
18
|
}
|
|
18
|
-
export declare function IDSHeader1177NavItemBase({ label, active, expanded, children, col1, col2, col3, col4, componentRef, menuRef, onToggleItem, client, unresponsive, ...props }: IDSHeader1177NavItemBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function IDSHeader1177NavItemBase({ label, active, expanded, children, col1, col2, col3, col4, componentRef, menuRef, buttonRef, onToggleItem, client, unresponsive, ...props }: IDSHeader1177NavItemBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import React, { useId } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
function IDSHeader1177NavItemBase({ label, active, expanded, children, col1, col2, col3, col4, componentRef, menuRef, onToggleItem, client = false, unresponsive, ...props }) {
|
|
5
|
+
function IDSHeader1177NavItemBase({ label, active, expanded, children, col1, col2, col3, col4, componentRef, menuRef, buttonRef, onToggleItem, client = false, unresponsive, ...props }) {
|
|
6
6
|
const itemId = `header-1177-item-${useId()}`;
|
|
7
7
|
const toggleHandler = client && onToggleItem
|
|
8
8
|
? {
|
|
@@ -13,7 +13,7 @@ function IDSHeader1177NavItemBase({ label, active, expanded, children, col1, col
|
|
|
13
13
|
"ids-header-1177-nav-item--unresponsive": unresponsive,
|
|
14
14
|
"ids-header-1177-nav-item--expanded": expanded,
|
|
15
15
|
"ids-header-1177-nav-item--active": active
|
|
16
|
-
}), ...props, children: [!!label && (jsx("button", { "aria-controls": itemId, "aria-expanded": expanded, className: "ids-header-1177-nav-item__button", ...toggleHandler, children: label })), !label && (jsx("span", { className: "ids-header-1177-nav-item__link", children: React.Children.map(children, child => {
|
|
16
|
+
}), ...props, children: [!!label && (jsx("button", { "aria-controls": itemId, ref: buttonRef, "aria-expanded": expanded, className: "ids-header-1177-nav-item__button", ...toggleHandler, children: label })), !label && (jsx("span", { className: "ids-header-1177-nav-item__link", children: React.Children.map(children, child => {
|
|
17
17
|
if (!React.isValidElement(child))
|
|
18
18
|
return child;
|
|
19
19
|
const element = child;
|
|
@@ -3,12 +3,19 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { IDSHeader1177NavItemBase } from './header-1177-nav-item-base.js';
|
|
5
5
|
import { useHeaderContext } from '../utils/contexts/HeaderContext.js';
|
|
6
|
+
import { useClickOutside } from '../utils/hooks/useClickOutside.js';
|
|
7
|
+
import { useEsc } from '../utils/hooks/useEsc.js';
|
|
6
8
|
|
|
7
9
|
function IDSHeader1177NavItem({ expanded = false, ...props }) {
|
|
8
10
|
const headerContext = useHeaderContext();
|
|
9
11
|
const [isExpanded, setIsExpanded] = useState(expanded);
|
|
10
12
|
const componentRef = useRef(null);
|
|
11
13
|
const menuRef = useRef(null);
|
|
14
|
+
const buttonRef = useRef(null);
|
|
15
|
+
useClickOutside([componentRef, buttonRef], () => {
|
|
16
|
+
setIsExpanded(false);
|
|
17
|
+
});
|
|
18
|
+
useEsc(() => setIsExpanded(false), buttonRef);
|
|
12
19
|
useEffect(() => {
|
|
13
20
|
setIsExpanded(expanded);
|
|
14
21
|
}, [expanded]);
|
|
@@ -37,20 +44,7 @@ function IDSHeader1177NavItem({ expanded = false, ...props }) {
|
|
|
37
44
|
menuEl.addEventListener("click", onMenuClick);
|
|
38
45
|
return () => menuEl.removeEventListener("click", onMenuClick);
|
|
39
46
|
}, [menuRef]);
|
|
40
|
-
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (!isExpanded)
|
|
43
|
-
return;
|
|
44
|
-
const handleKeyDown = (event) => {
|
|
45
|
-
if (event.key === "Escape") {
|
|
46
|
-
event.preventDefault();
|
|
47
|
-
setIsExpanded(false);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
51
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
52
|
-
}, [isExpanded]);
|
|
53
|
-
return (jsx(IDSHeader1177NavItemBase, { ...props, client: true, expanded: isExpanded, unresponsive: headerContext?.unresponsive, componentRef: componentRef, menuRef: menuRef, onToggleItem: () => setIsExpanded((prev) => !prev) }));
|
|
47
|
+
return (jsx(IDSHeader1177NavItemBase, { ...props, client: true, expanded: isExpanded, unresponsive: headerContext?.unresponsive, componentRef: componentRef, menuRef: menuRef, buttonRef: buttonRef, onToggleItem: () => setIsExpanded((prev) => !prev) }));
|
|
54
48
|
}
|
|
55
49
|
|
|
56
50
|
export { IDSHeader1177NavItem };
|
|
@@ -8,7 +8,8 @@ interface IDSHeader1177AdminAvatarBaseProps extends HTMLAttributes<HTMLElement>
|
|
|
8
8
|
onToggleAvatar?: () => void;
|
|
9
9
|
componentRef?: React.RefObject<HTMLDivElement>;
|
|
10
10
|
menuRef?: React.RefObject<HTMLDivElement>;
|
|
11
|
+
buttonRef?: React.RefObject<HTMLButtonElement>;
|
|
11
12
|
client?: boolean;
|
|
12
13
|
}
|
|
13
|
-
export declare function IDSHeader1177AdminAvatarBase({ username, unit, expanded, unresponsive, hide, componentRef, menuRef, children, onToggleAvatar, client, ...props }: IDSHeader1177AdminAvatarBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export declare function IDSHeader1177AdminAvatarBase({ username, unit, expanded, unresponsive, hide, componentRef, menuRef, buttonRef, children, onToggleAvatar, client, ...props }: IDSHeader1177AdminAvatarBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
14
15
|
export {};
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
function IDSHeader1177AdminAvatarBase({ username, unit, expanded = false, unresponsive = false, hide = false, componentRef, menuRef, children, onToggleAvatar, client = false, ...props }) {
|
|
5
|
+
function IDSHeader1177AdminAvatarBase({ username, unit, expanded = false, unresponsive = false, hide = false, componentRef, menuRef, buttonRef, children, onToggleAvatar, client = false, ...props }) {
|
|
6
6
|
if (hide)
|
|
7
7
|
return null;
|
|
8
8
|
const menuId = `header-1177-admin-avatar-menu-${useId()}`;
|
|
@@ -13,7 +13,7 @@ function IDSHeader1177AdminAvatarBase({ username, unit, expanded = false, unresp
|
|
|
13
13
|
: {};
|
|
14
14
|
return (jsx("div", { ref: componentRef, className: clsx("ids-header-1177-admin-avatar", {
|
|
15
15
|
"ids-header-1177-admin-avatar--unresponsive": unresponsive
|
|
16
|
-
}), ...props, children: jsxs("div", { className: "ids-header-1177-admin-avatar__menu-wrapper", children: [jsxs("button", { className: clsx("ids-header-1177-admin-avatar__button", {
|
|
16
|
+
}), ...props, children: jsxs("div", { className: "ids-header-1177-admin-avatar__menu-wrapper", children: [jsxs("button", { ref: buttonRef, className: clsx("ids-header-1177-admin-avatar__button", {
|
|
17
17
|
"ids-header-1177-admin-avatar__button--expanded": expanded
|
|
18
18
|
}), ...toggleHandler, "aria-controls": menuId, "aria-expanded": expanded, children: [jsx("div", { className: "ids-header-1177-admin-avatar__name", title: username, children: username }), unit && (jsxs(Fragment, { children: [jsx("span", { className: "ids-header-1177-admin-avatar__unit-separator", children: "|" }), jsx("span", { className: "ids-header-1177-admin-avatar__unit", title: unit, children: unit })] }))] }), jsx("div", { ref: menuRef, id: menuId, className: clsx("ids-header-1177-admin-avatar__menu", {
|
|
19
19
|
"ids-header-1177-admin-avatar__menu--expanded": expanded
|
|
@@ -8,6 +8,7 @@ interface IDSHeader1177AdminAvatarMobileBaseProps extends HTMLAttributes<HTMLEle
|
|
|
8
8
|
client?: boolean;
|
|
9
9
|
onToggleAvatar?: () => void;
|
|
10
10
|
componentRef?: React.Ref<HTMLDivElement>;
|
|
11
|
+
buttonRef?: React.Ref<HTMLButtonElement>;
|
|
11
12
|
}
|
|
12
|
-
export declare function IDSHeader1177AdminAvatarMobileBase({ username, unit, children, unresponsive, expanded, hide, client, onToggleAvatar, componentRef, ...props }: IDSHeader1177AdminAvatarMobileBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare function IDSHeader1177AdminAvatarMobileBase({ username, unit, children, unresponsive, expanded, hide, client, onToggleAvatar, componentRef, buttonRef, ...props }: IDSHeader1177AdminAvatarMobileBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
13
14
|
export {};
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
|
-
function IDSHeader1177AdminAvatarMobileBase({ username, unit, children, unresponsive, expanded = false, hide = false, client = false, onToggleAvatar, componentRef, ...props }) {
|
|
5
|
+
function IDSHeader1177AdminAvatarMobileBase({ username, unit, children, unresponsive, expanded = false, hide = false, client = false, onToggleAvatar, componentRef, buttonRef, ...props }) {
|
|
6
6
|
if (hide)
|
|
7
7
|
return null;
|
|
8
8
|
const menuId = `header-1177-admin-avatar-mobile-menu-${useId()}`;
|
|
@@ -15,7 +15,7 @@ function IDSHeader1177AdminAvatarMobileBase({ username, unit, children, unrespon
|
|
|
15
15
|
"ids-header-1177-admin-avatar-mobile--unresponsive": unresponsive
|
|
16
16
|
}), ref: componentRef, ...props, children: jsxs("div", { className: "ids-header-1177-admin-avatar-mobile__menu-wrapper", children: [jsx("button", { className: clsx("ids-header-1177-admin-avatar-mobile__button", {
|
|
17
17
|
"ids-header-1177-admin-avatar-mobile__button--expanded": expanded
|
|
18
|
-
}), ...toggleHandler, "aria-controls": menuId, "aria-expanded": expanded, children: jsx("div", { className: "ids-header-1177-admin-avatar-mobile-content__name", title: username, children: username }) }), jsxs("div", { id: menuId, className: clsx("ids-header-1177-admin-avatar-mobile__menu", {
|
|
18
|
+
}), ...toggleHandler, ref: buttonRef, "aria-controls": menuId, "aria-expanded": expanded, children: jsx("div", { className: "ids-header-1177-admin-avatar-mobile-content__name", title: username, children: username }) }), jsxs("div", { id: menuId, className: clsx("ids-header-1177-admin-avatar-mobile__menu", {
|
|
19
19
|
"ids-header-1177-admin-avatar-mobile__menu--expanded": expanded
|
|
20
20
|
}), children: [unit && jsx("div", { className: "ids-header-1177-admin-avatar-mobile__unit", children: unit }), jsx("div", { className: "ids-header-1177-admin-avatar-mobile__menu-links", children: children })] })] }) }));
|
|
21
21
|
}
|
|
@@ -1,38 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useId, useState, useRef
|
|
3
|
+
import { useId, useState, useRef } from 'react';
|
|
4
4
|
import { useHeaderContext } from '../utils/contexts/HeaderContext.js';
|
|
5
5
|
import { IDSHeader1177AdminAvatarMobileBase } from './header-1177-admin-avatar-mobile-base.js';
|
|
6
|
+
import { useFocusTrap } from '../utils/hooks/useFocusTrap.js';
|
|
7
|
+
import { useClickOutside } from '../utils/hooks/useClickOutside.js';
|
|
8
|
+
import { useEsc } from '../utils/hooks/useEsc.js';
|
|
6
9
|
|
|
7
10
|
function IDSHeader1177AdminAvatarMobile({ username = "", unit = "", expanded = false, persistent = false, children, ...props }) {
|
|
8
11
|
useId();
|
|
9
12
|
const [isExpanded, setIsExpanded] = useState(expanded);
|
|
10
13
|
const headerContext = useHeaderContext();
|
|
11
14
|
const componentRef = useRef(null);
|
|
15
|
+
const buttonRef = useRef(null);
|
|
16
|
+
useFocusTrap(componentRef.current, isExpanded && !persistent);
|
|
17
|
+
useClickOutside([componentRef, buttonRef], () => {
|
|
18
|
+
if (!persistent)
|
|
19
|
+
setIsExpanded(false);
|
|
20
|
+
});
|
|
21
|
+
useEsc(() => setIsExpanded(false), buttonRef, isExpanded && !persistent);
|
|
12
22
|
const toggleAvatar = () => setIsExpanded(prev => !prev);
|
|
13
|
-
|
|
14
|
-
const handleClickOutside = (event) => {
|
|
15
|
-
if (!persistent && componentRef.current && !componentRef.current.contains(event.target)) {
|
|
16
|
-
setIsExpanded(false);
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
document.addEventListener("click", handleClickOutside);
|
|
20
|
-
return () => document.removeEventListener("click", handleClickOutside);
|
|
21
|
-
}, [persistent]);
|
|
22
|
-
// Escape should also close
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (!isExpanded || persistent)
|
|
25
|
-
return;
|
|
26
|
-
const handleKeyDown = (event) => {
|
|
27
|
-
if (event.key === "Escape") {
|
|
28
|
-
event.preventDefault();
|
|
29
|
-
setIsExpanded(false);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
33
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
34
|
-
}, [isExpanded, persistent]);
|
|
35
|
-
return (jsx(IDSHeader1177AdminAvatarMobileBase, { ...props, client: true, username: username, unit: unit, unresponsive: headerContext?.unresponsive ?? false, hide: headerContext?.hideAvatar, expanded: isExpanded, onToggleAvatar: toggleAvatar, componentRef: componentRef, children: children }));
|
|
23
|
+
return (jsx(IDSHeader1177AdminAvatarMobileBase, { ...props, client: true, username: username, unit: unit, unresponsive: headerContext?.unresponsive ?? false, hide: headerContext?.hideAvatar, expanded: isExpanded, onToggleAvatar: toggleAvatar, componentRef: componentRef, buttonRef: buttonRef, children: children }));
|
|
36
24
|
}
|
|
37
25
|
|
|
38
26
|
export { IDSHeader1177AdminAvatarMobile };
|