@inera/ids-react 9.0.4 → 9.1.0

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 (111) hide show
  1. package/components/alert/alert.js +1 -1
  2. package/components/breadcrumbs/breadcrumbs.js +1 -1
  3. package/components/card/card.d.ts +2 -2
  4. package/components/card/card.js +4 -15
  5. package/components/data-pagination/data-pagination.d.ts +6 -6
  6. package/components/data-pagination/data-pagination.js +1 -1
  7. package/components/dialog/dialog-base.js +1 -1
  8. package/components/dialog/dialog.js +12 -13
  9. package/components/dropdown/dropdown-base.js +2 -2
  10. package/components/dropdown/dropdown.js +1 -0
  11. package/components/footer-1177-pro/footer-1177-pro.d.ts +2 -1
  12. package/components/footer-1177-pro/footer-1177-pro.js +2 -2
  13. package/components/form/checkbox/checkbox-group-base.d.ts +2 -1
  14. package/components/form/checkbox/checkbox-group-base.js +4 -2
  15. package/components/form/checkbox/checkbox-group.d.ts +1 -0
  16. package/components/form/checkbox/checkbox-group.js +4 -3
  17. package/components/form/datepicker/datepicker.d.ts +2 -1
  18. package/components/form/datepicker/datepicker.js +60 -37
  19. package/components/form/input/input-base.d.ts +2 -1
  20. package/components/form/input/input-base.js +10 -10
  21. package/components/form/input/input.d.ts +1 -0
  22. package/components/form/radio/radio-group-base.d.ts +2 -1
  23. package/components/form/radio/radio-group-base.js +4 -2
  24. package/components/form/radio/radio-group.d.ts +1 -0
  25. package/components/form/radio-button/radio-button-group-base.js +1 -1
  26. package/components/form/select/select.d.ts +1 -1
  27. package/components/form/select/select.js +2 -2
  28. package/components/form/select-multiple/select-multiple-base.d.ts +3 -3
  29. package/components/form/select-multiple/select-multiple-base.js +5 -6
  30. package/components/form/select-multiple/select-multiple.d.ts +1 -1
  31. package/components/form/select-multiple/select-multiple.js +10 -23
  32. package/components/form/textarea/textarea.d.ts +1 -1
  33. package/components/form/textarea/textarea.js +2 -2
  34. package/components/form/time/time.d.ts +1 -1
  35. package/components/form/time/time.js +2 -2
  36. package/components/{alert → global-alert}/global-alert.d.ts +1 -1
  37. package/components/{alert → global-alert}/global-alert.js +2 -2
  38. package/components/header-1177/header-1177-avatar-base.d.ts +2 -1
  39. package/components/header-1177/header-1177-avatar-base.js +2 -2
  40. package/components/header-1177/header-1177-avatar.js +11 -24
  41. package/components/header-1177/header-1177-menu-mobile-base.d.ts +2 -1
  42. package/components/header-1177/header-1177-menu-mobile-base.js +2 -2
  43. package/components/header-1177/header-1177-menu-mobile.js +9 -14
  44. package/components/header-1177/header-1177-nav-item-base.d.ts +2 -1
  45. package/components/header-1177/header-1177-nav-item-base.js +2 -2
  46. package/components/header-1177/header-1177-nav-item.js +8 -14
  47. package/components/header-1177-admin/header-1177-admin-avatar-base.d.ts +2 -1
  48. package/components/header-1177-admin/header-1177-admin-avatar-base.js +2 -2
  49. package/components/header-1177-admin/header-1177-admin-avatar-mobile-base.d.ts +2 -1
  50. package/components/header-1177-admin/header-1177-admin-avatar-mobile-base.js +2 -2
  51. package/components/header-1177-admin/header-1177-admin-avatar-mobile.js +12 -24
  52. package/components/header-1177-admin/header-1177-admin-avatar.js +11 -14
  53. package/components/header-1177-admin/header-1177-admin-menu-mobile-base.d.ts +2 -1
  54. package/components/header-1177-admin/header-1177-admin-menu-mobile-base.js +2 -2
  55. package/components/header-1177-admin/header-1177-admin-menu-mobile.js +9 -14
  56. package/components/header-1177-admin/header-1177-admin-nav-item-base.d.ts +2 -1
  57. package/components/header-1177-admin/header-1177-admin-nav-item-base.js +2 -2
  58. package/components/header-1177-admin/header-1177-admin-nav-item.js +8 -14
  59. package/components/header-1177-pro/header-1177-pro-avatar-base.d.ts +2 -1
  60. package/components/header-1177-pro/header-1177-pro-avatar-base.js +2 -2
  61. package/components/header-1177-pro/header-1177-pro-avatar-mobile-base.d.ts +2 -1
  62. package/components/header-1177-pro/header-1177-pro-avatar-mobile-base.js +2 -2
  63. package/components/header-1177-pro/header-1177-pro-avatar-mobile.js +12 -24
  64. package/components/header-1177-pro/header-1177-pro-avatar.js +11 -14
  65. package/components/header-1177-pro/header-1177-pro-menu-mobile-base.d.ts +2 -1
  66. package/components/header-1177-pro/header-1177-pro-menu-mobile-base.js +2 -2
  67. package/components/header-1177-pro/header-1177-pro-menu-mobile.js +9 -14
  68. package/components/header-1177-pro/header-1177-pro-nav-item-base.d.ts +2 -1
  69. package/components/header-1177-pro/header-1177-pro-nav-item-base.js +2 -2
  70. package/components/header-1177-pro/header-1177-pro-nav-item.js +8 -14
  71. package/components/header-inera/header-inera-menu-mobile-base.d.ts +2 -1
  72. package/components/header-inera/header-inera-menu-mobile-base.js +2 -2
  73. package/components/header-inera/header-inera-menu-mobile.js +9 -14
  74. package/components/header-inera/header-inera-nav-item-base.d.ts +2 -1
  75. package/components/header-inera/header-inera-nav-item-base.js +2 -2
  76. package/components/header-inera/header-inera-nav-item.js +8 -14
  77. package/components/header-inera-admin/header-inera-admin-avatar-base.d.ts +2 -1
  78. package/components/header-inera-admin/header-inera-admin-avatar-base.js +2 -2
  79. package/components/header-inera-admin/header-inera-admin-avatar-mobile-base.d.ts +2 -1
  80. package/components/header-inera-admin/header-inera-admin-avatar-mobile-base.js +2 -2
  81. package/components/header-inera-admin/header-inera-admin-avatar-mobile.js +12 -24
  82. package/components/header-inera-admin/header-inera-admin-avatar.js +12 -16
  83. package/components/header-inera-admin/header-inera-admin-menu-mobile-base.d.ts +2 -1
  84. package/components/header-inera-admin/header-inera-admin-menu-mobile-base.js +2 -2
  85. package/components/header-inera-admin/header-inera-admin-menu-mobile.js +9 -14
  86. package/components/header-inera-admin/header-inera-admin-nav-item-base.d.ts +2 -1
  87. package/components/header-inera-admin/header-inera-admin-nav-item-base.js +2 -2
  88. package/components/header-inera-admin/header-inera-admin-nav-item.js +8 -14
  89. package/components/popover/popover-content.js +1 -1
  90. package/components/popover/popover.js +1 -1
  91. package/components/puff-list/puff-list-item-header.js +1 -1
  92. package/components/puff-list/puff-list-item.js +1 -1
  93. package/components/side-panel/side-panel-base.js +6 -2
  94. package/components/side-panel/side-panel.js +50 -41
  95. package/components/stepper/step-base.js +1 -1
  96. package/components/stepper/step.js +12 -10
  97. package/components/tabs/tab-panel.js +1 -1
  98. package/components/tabs/tab.js +1 -1
  99. package/components/tabs/tabs.d.ts +1 -1
  100. package/components/tabs/tabs.js +8 -4
  101. package/components/utils/hooks/useClickOutside.d.ts +10 -0
  102. package/components/utils/hooks/useClickOutside.js +31 -0
  103. package/components/utils/hooks/useEsc.d.ts +10 -0
  104. package/components/utils/hooks/useEsc.js +27 -0
  105. package/components/utils/hooks/useHasFocusableChildren.d.ts +2 -0
  106. package/components/utils/hooks/useHasFocusableChildren.js +25 -0
  107. package/index.d.ts +2 -2
  108. package/index.js +2 -2
  109. package/package.json +2 -2
  110. /package/components/{alert → global-alert}/global-alert-base.d.ts +0 -0
  111. /package/components/{alert → global-alert}/global-alert-base.js +0 -0
@@ -16,7 +16,7 @@ function IDSAlert({ collapsed = false, onCollapsedChange, onClose, children, cla
16
16
  const handleClose = () => {
17
17
  onClose?.();
18
18
  };
19
- return (jsx(IDSAlertBase, { ...props, client: true, collapsed: isCollapsed, onToggleCollapse: handleToggleCollapse, onClose: handleClose, children: children }));
19
+ return (jsx(IDSAlertBase, { ...props, client: true, collapsed: isCollapsed, className: className, onToggleCollapse: handleToggleCollapse, onClose: handleClose, children: children }));
20
20
  }
21
21
 
22
22
  export { IDSAlert };
@@ -24,7 +24,7 @@ function IDSBreadcrumbs({ lead = "Du är här", mobileLink, children, className,
24
24
  }
25
25
  });
26
26
  };
27
- return (jsxs("nav", { ...props, className: clsx("ids-breadcrumbs", className), "aria-label": lead, children: [jsxs("ol", { className: "ids-breadcrumbs__desktop", children: [jsx("li", { className: "ids-breadcrumbs__lead", children: lead }), getLinks()] }), jsx("ol", { className: "ids-breadcrumbs__mobile", children: jsxs("li", { className: "ids-breadcrumbs__mobile-links", children: [jsx("span", { className: "ids-breadcrumbs__icon" }), getMobileLink()] }) })] }));
27
+ return (jsxs("nav", { ...props, className: clsx("ids-breadcrumbs", className), "aria-label": lead, children: [jsxs("ol", { className: "ids-breadcrumbs__desktop", children: [jsx("li", { className: "ids-breadcrumbs__lead", children: lead }), getLinks()] }), mobileLink && (jsx("ol", { className: "ids-breadcrumbs__mobile", children: jsxs("li", { className: "ids-breadcrumbs__mobile-links", children: [jsx("span", { className: "ids-breadcrumbs__icon" }), getMobileLink()] }) }))] }));
28
28
  }
29
29
 
30
30
  export { IDSBreadcrumbs };
@@ -2,12 +2,12 @@ import React from "react";
2
2
  import "@inera/ids-design/components/card/card.css";
3
3
  interface IDSCardProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  borderTop?: boolean;
5
- cardLink?: React.ReactElement | React.AnchorHTMLAttributes<HTMLAnchorElement> | React.ReactNode;
6
5
  fill?: boolean;
7
6
  focusCard?: boolean;
8
7
  hideOnM?: boolean;
9
8
  hideOnS?: boolean;
10
9
  lean?: boolean;
10
+ interactive?: boolean;
11
11
  }
12
- export declare function IDSCard({ focusCard, fill, borderTop, lean, hideOnM, hideOnS, cardLink, children, className, ...props }: IDSCardProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function IDSCard({ focusCard, fill, borderTop, lean, hideOnM, hideOnS, interactive, children, className, ...props }: IDSCardProps): import("react/jsx-runtime").JSX.Element;
13
13
  export {};
@@ -1,19 +1,8 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { isValidElement, cloneElement } from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
2
  import clsx from 'clsx';
4
3
  import '@inera/ids-design/components/card/card.css';
5
4
 
6
- function IDSCard({ focusCard = false, fill = false, borderTop = false, lean = false, hideOnM = false, hideOnS = false, cardLink, children, className, ...props }) {
7
- let enhancedCardLink = null;
8
- if (isValidElement(cardLink)) {
9
- enhancedCardLink = cloneElement(cardLink, {
10
- className: clsx(cardLink.props.className, "ids-card--interactive-link")
11
- });
12
- }
13
- else if (cardLink) {
14
- const anchorProps = cardLink;
15
- enhancedCardLink = jsx("a", { ...anchorProps, className: clsx(anchorProps.className, "ids-card--interactive-link") });
16
- }
5
+ function IDSCard({ focusCard = false, fill = false, borderTop = false, lean = false, hideOnM = false, hideOnS = false, interactive = false, children, className, ...props }) {
17
6
  return (jsxs("div", { ...props, className: clsx("ids-card", {
18
7
  "ids-card--fill": fill,
19
8
  "ids-card--border-top": !!borderTop && !focusCard,
@@ -21,8 +10,8 @@ function IDSCard({ focusCard = false, fill = false, borderTop = false, lean = fa
21
10
  "ids-card--hide-on-m": hideOnM,
22
11
  "ids-card--hide-on-s": hideOnS,
23
12
  "ids-card--lean": lean,
24
- "ids-card--interactive": !!cardLink
25
- }, className), children: [!!borderTop && !focusCard && jsx("div", { className: "ids-card__border-top" }), jsx("div", { className: "ids-card__content", children: children }), enhancedCardLink] }));
13
+ "ids-card--interactive": !!interactive && !hideOnM && !hideOnS && !borderTop
14
+ }, className), children: [!!borderTop && !focusCard && !interactive && jsx("div", { className: "ids-card__border-top" }), jsx("div", { className: "ids-card__content", children: children })] }));
26
15
  }
27
16
 
28
17
  export { IDSCard };
@@ -1,4 +1,4 @@
1
- import React, { ReactNode } from "react";
1
+ import React from "react";
2
2
  import "@inera/ids-design/components/data-pagination/data-pagination.css";
3
3
  export interface IDSDataPaginationProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  from: number;
@@ -7,9 +7,9 @@ export interface IDSDataPaginationProps extends React.HTMLAttributes<HTMLDivElem
7
7
  total: number | string;
8
8
  defaultValue?: string;
9
9
  light?: boolean;
10
- firstPageButton?: ReactNode;
11
- previousButton?: ReactNode;
12
- nextButton?: ReactNode;
13
- lastPageButton?: ReactNode;
10
+ firstPageButton?: React.ReactElement;
11
+ previousButton?: React.ReactElement;
12
+ nextButton?: React.ReactElement;
13
+ lastPageButton?: React.ReactElement;
14
14
  }
15
- export declare const IDSDataPagination: React.ForwardRefExoticComponent<IDSDataPaginationProps & React.RefAttributes<HTMLSelectElement>>;
15
+ export declare const IDSDataPagination: React.ForwardRefExoticComponent<IDSDataPaginationProps & React.RefAttributes<HTMLDivElement>>;
@@ -5,7 +5,7 @@ import '@inera/ids-design/components/data-pagination/data-pagination.css';
5
5
 
6
6
  const IDSDataPagination = forwardRef(({ from, to, of = "av", total, defaultValue = "", firstPageButton, previousButton, nextButton, lastPageButton, light = false, className, children, ...props }, ref) => {
7
7
  const summaryText = `${from} - ${to} ${of} ${total}`;
8
- return (jsxs("div", { className: clsx("ids-data-pagination", { "ids-data-pagination--light": light }, className), ...props, children: [!!children && jsx("div", { className: "ids-data-pagination__select", children: children }), jsx("div", { className: "ids-data-pagination__summary", children: summaryText }), jsxs("div", { className: "ids-data-pagination__buttons", children: [firstPageButton && jsx("div", { className: "ids-data-pagination__first-page-button", children: firstPageButton }), previousButton && jsx("div", { className: "ids-data-pagination__prev-button", children: previousButton }), nextButton && jsx("div", { className: "ids-data-pagination__next-button", children: nextButton }), lastPageButton && jsx("div", { className: "ids-data-pagination__last-page-button", children: lastPageButton })] })] }));
8
+ return (jsxs("div", { className: clsx("ids-data-pagination", { "ids-data-pagination--light": light }, className), ...props, ref: ref, children: [!!children && jsx("div", { className: "ids-data-pagination__select", children: children }), jsx("div", { className: "ids-data-pagination__summary", children: summaryText }), jsxs("div", { className: "ids-data-pagination__buttons", children: [firstPageButton && jsx("div", { className: "ids-data-pagination__first-page-button", children: firstPageButton }), previousButton && jsx("div", { className: "ids-data-pagination__prev-button", children: previousButton }), nextButton && jsx("div", { className: "ids-data-pagination__next-button", children: nextButton }), lastPageButton && jsx("div", { className: "ids-data-pagination__last-page-button", children: lastPageButton })] })] }));
9
9
  });
10
10
  IDSDataPagination.displayName = "IDSDataPagination";
11
11
 
@@ -20,7 +20,7 @@ const IDSDialogBase = forwardRef(({ show = false, width, maxWidth, height, headl
20
20
  "ids-dialog--hidden": !show,
21
21
  "ids-focus-trap": !noFocusTrap,
22
22
  "ids-dialog--dismissible": !!dismissible
23
- }), ref: dialogRef, role: "dialog", "aria-modal": "true", "aria-labelledby": headline ? headlineId : undefined, style: { width, maxWidth, height, maxHeight: height || undefined }, children: [dismissible && (jsx("div", { className: "ids-dialog__dismissible", children: jsx("button", { "aria-label": srClose, ...closeHandler, className: "ids-dialog__close-button" }) })), jsxs("div", { ref: scrollAreaRef, className: clsx("ids-dialog__body", {
23
+ }, className), ref: dialogRef, role: "dialog", "aria-modal": "true", "aria-labelledby": headline ? headlineId : undefined, style: { width, maxWidth, height, maxHeight: height || undefined }, children: [dismissible && (jsx("div", { className: "ids-dialog__dismissible", children: jsx("button", { "aria-label": srClose, ...closeHandler, className: "ids-dialog__close-button" }) })), jsxs("div", { ref: scrollAreaRef, className: clsx("ids-dialog__body", {
24
24
  "ids-dialog__body--scroll-area-focus": !noScrollAreaFocus
25
25
  }), tabIndex: noScrollAreaFocus ? -1 : 0, children: [jsx("div", { className: "ids-dialog__body-headline", id: headlineId, children: headline }), jsx("div", { className: "ids-dialog__body-content", children: children }), actions && jsx("div", { className: "ids-dialog__footer", children: actions })] })] })] }));
26
26
  });
@@ -3,6 +3,7 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { useState, useRef, useEffect, useCallback } from 'react';
4
4
  import { IDSDialogBase } from './dialog-base.js';
5
5
  import { useFocusTrap } from '../utils/hooks/useFocusTrap.js';
6
+ import { useEsc } from '../utils/hooks/useEsc.js';
6
7
 
7
8
  function IDSDialog({ show = false, srClose = "Stäng", headline, width, maxWidth, height, trigger, actions, noOverlay = false, dismissible = false, autoFocus = true, noFocusTrap = false, persistent = false, keepScrollbar = false, noScrollAreaFocus = false, onVisibilityChange, children, className, ...props }) {
8
9
  const [isVisible, setIsVisible] = useState(show);
@@ -10,6 +11,7 @@ function IDSDialog({ show = false, srClose = "Stäng", headline, width, maxWidth
10
11
  const dialogRef = useRef(null);
11
12
  const scrollAreaRef = useRef(null);
12
13
  useFocusTrap(dialogRef.current, isVisible && !noFocusTrap);
14
+ useEsc(() => setIsVisible(false), triggerRef, isVisible && !persistent);
13
15
  // Sync prop show
14
16
  useEffect(() => {
15
17
  setIsVisible(show);
@@ -30,16 +32,6 @@ function IDSDialog({ show = false, srClose = "Stäng", headline, width, maxWidth
30
32
  document.body.classList.remove("ids-hide-overflow");
31
33
  };
32
34
  }, [isVisible, keepScrollbar]);
33
- // Escape key
34
- useEffect(() => {
35
- const handleKeyDown = (e) => {
36
- if (e.key === "Escape" && isVisible && !persistent) {
37
- setIsVisible(false);
38
- }
39
- };
40
- document.addEventListener("keydown", handleKeyDown);
41
- return () => document.removeEventListener("keydown", handleKeyDown);
42
- }, [isVisible, persistent]);
43
35
  // Auto focus
44
36
  useEffect(() => {
45
37
  if (isVisible && autoFocus) {
@@ -61,16 +53,23 @@ function IDSDialog({ show = false, srClose = "Stäng", headline, width, maxWidth
61
53
  }
62
54
  }
63
55
  }, [isVisible, autoFocus]);
56
+ const focusTrigger = () => {
57
+ const container = triggerRef.current;
58
+ if (!container)
59
+ return;
60
+ const focusable = container.querySelector('button, [href], input, [tabindex]:not([tabindex="-1"])');
61
+ focusable?.focus();
62
+ };
64
63
  const overlayClick = useCallback(() => {
65
64
  if (!persistent)
66
65
  setIsVisible(false);
67
- triggerRef.current?.focus();
66
+ focusTrigger();
68
67
  }, []);
69
68
  const closeDialog = useCallback(() => {
70
69
  setIsVisible(false);
71
- triggerRef.current?.focus();
70
+ focusTrigger();
72
71
  }, []);
73
- return (jsxs(Fragment, { children: [jsx("div", { className: "ids-dialog__trigger", "aria-haspopup": "dialog", ref: triggerRef, children: trigger }), jsx(IDSDialogBase, { ...props, client: true, show: isVisible, noOverlay: noOverlay, headline: headline, dismissible: dismissible, width: width, maxWidth: maxWidth, height: height, dialogRef: dialogRef, scrollAreaRef: scrollAreaRef, actions: actions, noFocusTrap: noFocusTrap, noScrollAreaFocus: noScrollAreaFocus, onCloseDialog: closeDialog, onOverlayClick: overlayClick, children: children })] }));
72
+ return (jsxs(Fragment, { children: [jsx("div", { className: "ids-dialog__trigger", "aria-haspopup": "dialog", ref: triggerRef, children: trigger }), jsx(IDSDialogBase, { ...props, client: true, className: className, show: isVisible, noOverlay: noOverlay, headline: headline, dismissible: dismissible, width: width, maxWidth: maxWidth, height: height, dialogRef: dialogRef, scrollAreaRef: scrollAreaRef, actions: actions, noFocusTrap: noFocusTrap, noScrollAreaFocus: noScrollAreaFocus, onCloseDialog: closeDialog, onOverlayClick: overlayClick, children: children })] }));
74
73
  }
75
74
 
76
75
  export { IDSDialog };
@@ -27,11 +27,11 @@ function IDSDropdownBase({ expanded, trigger, triggerRef, onTriggerClick, positi
27
27
  ...trigger.props
28
28
  })
29
29
  : trigger;
30
- return (jsxs("span", { ...props, className: clsx(`ids-dropdown`, className, {
30
+ return (jsxs("span", { ...props, className: clsx(`ids-dropdown`, {
31
31
  "ids-dropdown--m-block": mBlock,
32
32
  "ids-dropdown--s-block": sBlock,
33
33
  "ids-dropdown--expanded": expanded
34
- }), children: [enhancedTrigger, jsx("div", { ...props, ref: contentRef, "aria-labelledby": triggerId, "aria-hidden": !expanded, className: clsx(`ids-dropdown-content ids-dropdown-content--position-${position}`, {
34
+ }, className), children: [enhancedTrigger, jsx("div", { ...props, ref: contentRef, "aria-labelledby": triggerId, "aria-hidden": !expanded, className: clsx(`ids-dropdown-content ids-dropdown-content--position-${position}`, {
35
35
  "ids-dropdown-content--show": expanded,
36
36
  "ids-dropdown-content--mblock": mBlock,
37
37
  "ids-dropdown-content--sblock": sBlock,
@@ -35,6 +35,7 @@ function IDSDropdown({ button, position, maxHeight, minWidth, sBlock, mBlock, ex
35
35
  event.preventDefault();
36
36
  setIsExpanded(false);
37
37
  onClosed?.();
38
+ triggerRef.current?.focus();
38
39
  }
39
40
  };
40
41
  document.addEventListener("keydown", handleKeyDown);
@@ -3,6 +3,7 @@ import "@inera/ids-design/components/footer-1177-pro/footer-1177-pro.css";
3
3
  interface Footer1177ProProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  headline?: string;
5
5
  srHeadline?: string;
6
+ mobileHeadline?: string;
6
7
  toggle?: ReactNode;
7
8
  col1Headline?: ReactNode;
8
9
  col2Headline?: ReactNode;
@@ -17,5 +18,5 @@ interface Footer1177ProProps extends React.HTMLAttributes<HTMLDivElement> {
17
18
  subFooterMobile?: ReactNode;
18
19
  children?: ReactNode;
19
20
  }
20
- export declare function IDSFooter1177Pro({ headline, srHeadline, col1, col2, col3, toggle, col1Headline, col2Headline, col3Headline, subFooterLeft, subFooterRight, mobileMenu, mobileLinks, subFooterMobile, children, className, ...props }: Footer1177ProProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare function IDSFooter1177Pro({ headline, srHeadline, mobileHeadline, col1, col2, col3, toggle, col1Headline, col2Headline, col3Headline, subFooterLeft, subFooterRight, mobileMenu, mobileLinks, subFooterMobile, children, className, ...props }: Footer1177ProProps): import("react/jsx-runtime").JSX.Element;
21
22
  export {};
@@ -2,7 +2,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import clsx from 'clsx';
3
3
  import '@inera/ids-design/components/footer-1177-pro/footer-1177-pro.css';
4
4
 
5
- function IDSFooter1177Pro({ headline = "", srHeadline = "", col1, col2, col3, toggle, col1Headline, col2Headline, col3Headline, subFooterLeft, subFooterRight, mobileMenu, mobileLinks, subFooterMobile, children, className, ...props }) {
5
+ function IDSFooter1177Pro({ headline = "", srHeadline = "", mobileHeadline = "", col1, col2, col3, toggle, col1Headline, col2Headline, col3Headline, subFooterLeft, subFooterRight, mobileMenu, mobileLinks, subFooterMobile, children, className, ...props }) {
6
6
  const renderHeadline = () => {
7
7
  if (srHeadline) {
8
8
  return (jsxs(Fragment, { children: [jsx("h2", { className: "ids-footer-1177-pro__headline--sr", children: srHeadline }), jsx("h2", { "aria-hidden": "true", className: "ids-footer-1177-pro__headline", children: headline })] }));
@@ -21,7 +21,7 @@ function IDSFooter1177Pro({ headline = "", srHeadline = "", col1, col2, col3, to
21
21
  }
22
22
  return null;
23
23
  };
24
- return (jsxs("footer", { className: clsx("ids-footer-1177-pro", className), ...props, children: [jsx("div", { className: "ids-footer-1177-pro__inner-wrapper", children: jsxs("div", { className: "ids-footer-1177-pro__inner", children: [jsx("div", { className: "ids-footer-1177-pro__headline-wrapper", children: renderHeadline() }), jsxs("div", { className: "ids-footer-1177-pro__content", children: [jsxs("div", { className: "ids-footer-1177-pro__text", children: [children, toggle && jsx("div", { className: "ids-footer-1177-pro__darkmode-toggle", children: toggle })] }), jsx("div", { className: "ids-footer-1177-pro__cols", children: renderCols() })] })] }) }), jsx("div", { className: "ids-footer-1177-pro__mobile-menu", children: mobileMenu }), jsxs("div", { className: "ids-footer-1177-pro__sub-footer", children: [jsx("div", { className: "ids-footer-1177-pro__sub-footer-container", children: jsxs("div", { className: "ids-footer-1177-pro__sub-footer-inner", children: [jsx("div", { className: "ids-footer-1177-pro__sub-footer-left", children: subFooterLeft }), jsx("div", { className: "ids-footer-1177-pro__sub-footer-right", children: subFooterRight }), jsx("div", { className: "ids-footer-1177-pro__mobile-links", children: mobileLinks })] }) }), jsxs("div", { className: "ids-footer-1177-pro__sub-footer-mobile", children: [jsxs("div", { className: "ids-footer-1177-pro__sub-footer-mobile-headline-wrapper", children: [jsx("div", { className: "ids-footer-1177-pro__sub-footer-mobile-logo" }), jsx("div", { className: "ids-footer-1177-pro__sub-footer-mobile-headline", children: headline })] }), jsx("div", { className: "ids-footer-1177-pro__sub-footer-mobile-text", children: subFooterMobile })] })] })] }));
24
+ return (jsxs("footer", { className: clsx("ids-footer-1177-pro", className), ...props, children: [jsx("div", { className: "ids-footer-1177-pro__inner-wrapper", children: jsxs("div", { className: "ids-footer-1177-pro__inner", children: [jsx("div", { className: "ids-footer-1177-pro__headline-wrapper", children: renderHeadline() }), jsxs("div", { className: "ids-footer-1177-pro__content", children: [jsxs("div", { className: "ids-footer-1177-pro__text", children: [children, toggle && jsx("div", { className: "ids-footer-1177-pro__darkmode-toggle", children: toggle })] }), jsx("div", { className: "ids-footer-1177-pro__cols", children: renderCols() })] })] }) }), jsx("div", { className: "ids-footer-1177-pro__mobile-menu", children: mobileMenu }), jsxs("div", { className: "ids-footer-1177-pro__sub-footer", children: [jsx("div", { className: "ids-footer-1177-pro__sub-footer-container", children: jsxs("div", { className: "ids-footer-1177-pro__sub-footer-inner", children: [jsx("div", { className: "ids-footer-1177-pro__sub-footer-left", children: subFooterLeft }), jsx("div", { className: "ids-footer-1177-pro__sub-footer-right", children: subFooterRight }), jsx("div", { className: "ids-footer-1177-pro__mobile-links", children: mobileLinks })] }) }), jsxs("div", { className: "ids-footer-1177-pro__sub-footer-mobile", children: [jsxs("div", { className: "ids-footer-1177-pro__sub-footer-mobile-headline-wrapper", children: [jsx("div", { className: "ids-footer-1177-pro__sub-footer-mobile-logo" }), jsx("div", { className: "ids-footer-1177-pro__sub-footer-mobile-headline", children: mobileHeadline })] }), jsx("div", { className: "ids-footer-1177-pro__sub-footer-mobile-text", children: subFooterMobile })] })] })] }));
25
25
  }
26
26
 
27
27
  export { IDSFooter1177Pro };
@@ -1,6 +1,7 @@
1
1
  import React, { ReactNode, InputHTMLAttributes } from "react";
2
2
  export interface IDSCheckboxGroupBaseProps extends InputHTMLAttributes<HTMLFieldSetElement> {
3
3
  legend?: string;
4
+ hideLegend?: boolean;
4
5
  errorMsg?: string | ReactNode;
5
6
  compact?: boolean;
6
7
  tooltip?: ReactNode;
@@ -9,4 +10,4 @@ export interface IDSCheckboxGroupBaseProps extends InputHTMLAttributes<HTMLField
9
10
  errorMsgId?: string;
10
11
  groupRef?: React.Ref<HTMLFieldSetElement>;
11
12
  }
12
- export declare function IDSCheckboxGroupBase({ legend, errorMsg, compact, tooltip, children, className, invalid, errorMsgId, groupRef, ...props }: IDSCheckboxGroupBaseProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function IDSCheckboxGroupBase({ legend, errorMsg, compact, hideLegend, tooltip, children, className, invalid, errorMsgId, groupRef, ...props }: IDSCheckboxGroupBaseProps): import("react/jsx-runtime").JSX.Element;
@@ -3,11 +3,13 @@ import { useId } from 'react';
3
3
  import clsx from 'clsx';
4
4
  import { IDSErrorMessage } from '../error-message/error-message.js';
5
5
 
6
- function IDSCheckboxGroupBase({ legend = "", errorMsg = "", compact = false, tooltip, children, className, invalid = false, errorMsgId, groupRef, ...props }) {
6
+ function IDSCheckboxGroupBase({ legend, errorMsg = "", compact = false, hideLegend, tooltip, children, className, invalid = false, errorMsgId, groupRef, ...props }) {
7
7
  const baseErrorMsgId = !!errorMsgId ? errorMsgId : `checkbox-group-base-error-${useId()}`;
8
8
  return (jsxs("fieldset", { ref: groupRef, className: clsx("ids-form-group__fieldset", {
9
9
  "ids-form-group__fieldset--compact": compact
10
- }, className), ...props, children: [legend && (jsx("div", { className: "ids-label-wrapper", children: jsxs("legend", { children: [legend, tooltip && jsx("span", { className: "ids-legend__tooltip", children: tooltip })] }) })), children, invalid && !!errorMsg && (jsx(IDSErrorMessage, { id: baseErrorMsgId, show: true, compact: true, style: { marginTop: compact ? "0.75rem" : "auto" }, children: errorMsg }))] }));
10
+ }, className), ...props, children: [legend && (jsx("div", { className: clsx("ids-label-wrapper", {
11
+ "ids-label-wrapper--sr-only": hideLegend
12
+ }, className), children: jsxs("legend", { children: [legend, tooltip && jsx("span", { className: "ids-legend__tooltip", children: tooltip })] }) })), children, invalid && !!errorMsg && (jsx(IDSErrorMessage, { id: baseErrorMsgId, show: true, compact: true, style: { marginTop: compact ? "0.75rem" : "auto" }, children: errorMsg }))] }));
11
13
  }
12
14
 
13
15
  export { IDSCheckboxGroupBase };
@@ -3,6 +3,7 @@ export interface IDSCheckboxGroupProps extends InputHTMLAttributes<HTMLFieldSetE
3
3
  legend?: string;
4
4
  errorMsg?: string | ReactNode;
5
5
  compact?: boolean;
6
+ hideLegend?: boolean;
6
7
  invalid?: boolean;
7
8
  tooltip?: ReactNode;
8
9
  block?: boolean;
@@ -13,6 +13,7 @@ function IDSCheckboxGroup({ errorMsg = "", block, invalid, noValidation = false,
13
13
  onValidityChange?.(false);
14
14
  }
15
15
  });
16
+ const groupInvalid = !noValidation && hasInteracted && !isValid;
16
17
  useEffect(() => {
17
18
  if (hasInteracted) {
18
19
  onValidityChange?.(isValid);
@@ -23,9 +24,9 @@ function IDSCheckboxGroup({ errorMsg = "", block, invalid, noValidation = false,
23
24
  return child;
24
25
  if (child.type === IDSCheckbox) {
25
26
  const cloneProps = {
26
- key: child.props.id,
27
+ key: child.key,
27
28
  id: child.props.id,
28
- groupErrorMsgId: !!errorMsg && !noValidation ? errorMsgId : undefined,
29
+ groupErrorMsgId: groupInvalid && !!errorMsg ? errorMsgId : undefined,
29
30
  block,
30
31
  noValidation
31
32
  };
@@ -33,7 +34,7 @@ function IDSCheckboxGroup({ errorMsg = "", block, invalid, noValidation = false,
33
34
  }
34
35
  return child;
35
36
  });
36
- return (jsx(IDSCheckboxGroupBase, { ...props, groupRef: groupRef, invalid: !isValid && hasInteracted || invalid, errorMsgId: errorMsgId, errorMsg: !noValidation && errorMsg, children: clonedChildren }));
37
+ return (jsx(IDSCheckboxGroupBase, { ...props, groupRef: groupRef, invalid: groupInvalid || invalid, errorMsgId: errorMsgId, errorMsg: !noValidation && errorMsg, children: clonedChildren }));
37
38
  }
38
39
 
39
40
  export { IDSCheckboxGroup };
@@ -24,6 +24,7 @@ export interface IDSDatePickerProps extends Omit<React.HTMLAttributes<HTMLElemen
24
24
  errorMsg?: string;
25
25
  missingDateErrorMsg?: string;
26
26
  invalidDateErrorMsg?: string;
27
+ validationOnBlur?: boolean;
27
28
  invalid?: boolean;
28
29
  disableNavigation?: boolean;
29
30
  tooltip?: ReactNode;
@@ -33,4 +34,4 @@ export interface IDSDatePickerProps extends Omit<React.HTMLAttributes<HTMLElemen
33
34
  onClose?: () => void;
34
35
  onDayClick?: (date: Date, modifiers: Modifiers, e: React.MouseEvent) => void;
35
36
  }
36
- export declare function IDSDatePicker({ label, value, light, placeholder, errorMsg, missingDateErrorMsg, invalidDateErrorMsg, calendarHeader, srOpenText, srCloseText, defaultMonth, startMonth, endMonth, noValidation, disabled, required, invalid, tooltip, disableNavigation, modifiers, focusedDay, onChange, onFocus, onBlur, onOpen, onClose, onDayClick, className, ...props }: IDSDatePickerProps): import("react/jsx-runtime").JSX.Element;
37
+ export declare function IDSDatePicker({ label, value, light, placeholder, errorMsg, missingDateErrorMsg, invalidDateErrorMsg, calendarHeader, srOpenText, srCloseText, validationOnBlur, defaultMonth, startMonth, endMonth, noValidation, disabled, required, invalid, tooltip, disableNavigation, modifiers, focusedDay, onChange, onFocus, onBlur, onOpen, onClose, onDayClick, className, ...props }: IDSDatePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -24,7 +24,7 @@ const getPrevMonthYear = (date) => {
24
24
  const getNextMonthYear = (date) => {
25
25
  return `${getSweMonth(addMonths(date, 1))} ${getSweYear(addMonths(date, 1))}`;
26
26
  };
27
- function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm/dd", errorMsg = "", missingDateErrorMsg = "Datum saknas", invalidDateErrorMsg = "Ogiltigt datum", calendarHeader = "Välj datum", srOpenText = "Öppna kalendern", srCloseText = "Stäng kalendern", defaultMonth, startMonth = new Date(1900, 0, 1), endMonth = new Date(2050, 0, 1), noValidation = false, disabled = false, required = false, invalid = false, tooltip, disableNavigation = false, modifiers, focusedDay, onChange, onFocus, onBlur, onOpen, onClose, onDayClick, className, ...props }) {
27
+ function IDSDatePicker({ label, value, light = false, placeholder = "åååå-mm-dd", errorMsg = "", missingDateErrorMsg = "Datum saknas", invalidDateErrorMsg = "Ogiltigt datum", calendarHeader = "Välj datum", srOpenText = "Öppna kalendern", srCloseText = "Stäng kalendern", validationOnBlur = false, defaultMonth, startMonth = new Date(1900, 0, 1), endMonth = new Date(2050, 0, 1), noValidation = false, disabled = false, required = false, invalid = false, tooltip, disableNavigation = false, modifiers, focusedDay, onChange, onFocus, onBlur, onOpen, onClose, onDayClick, className, ...props }) {
28
28
  const shortWeek = "v.";
29
29
  const inputRef = useRef(null);
30
30
  const triggerRef = useRef(null);
@@ -34,7 +34,7 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
34
34
  const nextMonthButtonRef = useRef(null);
35
35
  const dialogId = `datepicker-dialog-${useId()}`;
36
36
  const headerId = `datepicker-header-${useId()}`;
37
- const inputId = `datepicker-input-${useId()}`;
37
+ const inputId = props.id || `datepicker-input-${useId()}`;
38
38
  const errorMsgId = `datepicker-error-${useId()}`;
39
39
  const [isDialogOpen, setIsDialogOpen] = useState(false);
40
40
  const [inputValue, setInputValue] = useState(value);
@@ -43,11 +43,12 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
43
43
  const [month, setMonth] = useState(initialSelectedDate || defaultMonth || new Date());
44
44
  const [hasDateError, setHasDateError] = useState(false);
45
45
  const [hasMissingError, setHasMissingError] = useState(false);
46
- const [isInvalid, setIsInvalid] = useState(invalid);
46
+ const [hasOtherError, setHasOtherError] = useState(false);
47
+ const hasError = hasMissingError || hasDateError || hasOtherError || invalid;
47
48
  const showInvalidError = !!hasDateError && !!invalidDateErrorMsg;
48
49
  const showMissingError = !!hasMissingError && !!missingDateErrorMsg;
49
50
  const showError = !!invalid && !!errorMsg && !isDialogOpen;
50
- useAriaDescribedBy(inputRef, errorMsgId, isInvalid, (showError || showMissingError || showInvalidError) && !noValidation);
51
+ useAriaDescribedBy(inputRef, errorMsgId, invalid, (showError || showMissingError || showInvalidError) && !noValidation);
51
52
  useFocusTrap(dialogRef.current, isDialogOpen);
52
53
  const handleOpenDialog = (e) => {
53
54
  e.preventDefault();
@@ -75,6 +76,7 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
75
76
  if (event.key === "Escape") {
76
77
  event.preventDefault();
77
78
  setIsDialogOpen(false);
79
+ triggerRef.current?.focus();
78
80
  }
79
81
  };
80
82
  document.addEventListener("keydown", handleKeyDown);
@@ -82,9 +84,7 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
82
84
  }, [isDialogOpen]);
83
85
  const handleDayPickerSelect = (date) => {
84
86
  const dateString = format(date, "yyyy-MM-dd");
85
- setHasMissingError(false);
86
- setIsInvalid(false);
87
- setHasDateError(false);
87
+ resetErrors();
88
88
  if (!date) {
89
89
  setInputValue("");
90
90
  setSelectedDate(undefined);
@@ -98,25 +98,46 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
98
98
  inputRef.current.checkValidity();
99
99
  inputRef.current.dispatchEvent(new Event("input", { bubbles: true }));
100
100
  inputRef.current.dispatchEvent(new Event("change", { bubbles: true }));
101
- setHasMissingError(!noValidation && required && inputRef.current.validity.valueMissing);
102
- setIsInvalid(!inputRef.current.validity.valid || invalid);
103
101
  }
104
102
  });
105
103
  emitValue(dateString, date);
106
104
  closeDialog();
107
105
  };
108
- const handleInvalid = (e) => {
109
- setHasMissingError(!noValidation && required && e.currentTarget.validity.valueMissing);
110
- setIsInvalid(!e.currentTarget.validity.valid || invalid);
111
- emitValue(e.currentTarget.value, undefined);
106
+ const updateErrors = (validity, isNotADate) => {
107
+ if (!noValidation) {
108
+ setHasMissingError(validity.valueMissing);
109
+ setHasOtherError(!validity.valid);
110
+ if (validity.valueMissing) {
111
+ setHasDateError(false);
112
+ }
113
+ else {
114
+ setHasDateError(!!isNotADate || validity.patternMismatch);
115
+ }
116
+ }
117
+ };
118
+ const resetErrors = () => {
119
+ setHasMissingError(false);
120
+ setHasDateError(false);
121
+ setHasOtherError(false);
122
+ };
123
+ const handleInputChange = (e) => {
124
+ resetErrors();
125
+ setInputValue(e.currentTarget.value);
126
+ const parsedDate = createNewDate(e.currentTarget.value);
127
+ if (isValid(parsedDate)) {
128
+ setSelectedDate(parsedDate);
129
+ setMonth(parsedDate);
130
+ }
131
+ else {
132
+ setSelectedDate(undefined);
133
+ }
134
+ emitValue(e.currentTarget.value, parsedDate);
112
135
  };
113
136
  // if the input value is changed programmatically
114
137
  useEffect(() => {
115
138
  if (value !== inputValue && inputRef.current) {
116
- setIsInvalid(false);
117
- setHasDateError(false);
139
+ resetErrors();
118
140
  setInputValue(value);
119
- setHasMissingError(!noValidation && required && !value);
120
141
  if (value) {
121
142
  const parsedDate = createNewDate(value);
122
143
  if (isValid(parsedDate)) {
@@ -125,28 +146,10 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
125
146
  }
126
147
  else {
127
148
  setSelectedDate(undefined);
128
- setIsInvalid(true);
129
- setHasDateError(true);
130
149
  }
131
150
  }
132
151
  }
133
152
  }, [value, inputRef]);
134
- const handleInputChange = (e) => {
135
- setHasMissingError(false);
136
- setIsInvalid(false);
137
- setHasDateError(false);
138
- setInputValue(e.currentTarget.value);
139
- const parsedDate = createNewDate(e.currentTarget.value);
140
- if (isValid(parsedDate)) {
141
- setSelectedDate(parsedDate);
142
- setMonth(parsedDate);
143
- }
144
- else {
145
- setSelectedDate(undefined);
146
- setIsInvalid(!e.currentTarget.validity.valid || invalid);
147
- }
148
- emitValue(e.currentTarget.value, parsedDate);
149
- };
150
153
  const emitValue = (val, parsedDate) => {
151
154
  const isMissing = required && !val;
152
155
  const isValidDate = parsedDate && parsedDate instanceof Date && isValid(parsedDate);
@@ -157,9 +160,29 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
157
160
  missingDate: isMissing
158
161
  });
159
162
  };
160
- const handleBlur = () => {
161
- setHasDateError(!noValidation && value.trim().length && !isValid(selectedDate));
163
+ const handleInvalid = (e) => {
164
+ updateErrors(e.currentTarget.validity);
165
+ };
166
+ const handleBlur = (e) => {
167
+ if (validationOnBlur) {
168
+ updateErrors(e.currentTarget.validity, !!e.currentTarget.value.trim().length && !isValid(selectedDate));
169
+ }
170
+ onBlur?.(e);
162
171
  };
172
+ useEffect(() => {
173
+ const form = inputRef.current?.form;
174
+ if (!form)
175
+ return;
176
+ const handleSubmit = (e) => {
177
+ if (!noValidation) {
178
+ requestAnimationFrame(() => {
179
+ updateErrors(inputRef.current.validity, !isValid(createNewDate(inputRef.current.value)));
180
+ });
181
+ }
182
+ };
183
+ form.addEventListener("submit", handleSubmit);
184
+ return () => form.removeEventListener("submit", handleSubmit);
185
+ }, []);
163
186
  function CustomNav(props) {
164
187
  // Add the nav buttons after the dropdowns for correct tab order
165
188
  const { children } = props;
@@ -190,7 +213,7 @@ function IDSDatePicker({ label, value, light = false, placeholder = "åååå/mm
190
213
  return;
191
214
  header?.focus();
192
215
  }, [isDialogOpen]);
193
- return (jsxs("div", { className: clsx("ids-datepicker", { "ids-datepicker--invalid": !noValidation && (isInvalid || hasDateError) }, className), ...props, children: [isDialogOpen && jsx("div", { className: "ids-datepicker__overlay" }), label && (jsxs("div", { className: "ids-label-wrapper ids-label-wrapper--margin-bottom", children: [jsx("label", { htmlFor: inputId, className: "ids-label", children: label }), tooltip && jsx("span", { className: "ids-label__tooltip", children: tooltip })] })), jsxs("div", { className: "ids-datepicker__input-wrapper", children: [jsx("input", { className: clsx("ids-datepicker__input", { "ids-input--light": light }), ref: inputRef, style: { fontSize: "inherit" }, id: inputId, type: "text", value: inputValue, required: required, disabled: disabled, "aria-invalid": !noValidation && (isInvalid || hasDateError), placeholder: placeholder, onChange: handleInputChange, onInvalid: handleInvalid, onBlur: handleBlur }), jsx("button", { ref: triggerRef, type: "button", className: "ids-datepicker__trigger", style: { fontSize: "inherit" }, disabled: disabled, onClick: handleOpenDialog, "aria-controls": "dialog", "aria-haspopup": "dialog", "aria-expanded": isDialogOpen, "aria-label": srOpenText }), jsxs("div", { className: clsx("ids-datepicker__dialog", { "ids-datepicker__dialog--show": isDialogOpen }), role: "dialog", ref: dialogRef, id: dialogId, "aria-modal": true, "aria-labelledby": headerId, children: [jsxs("div", { className: "ids-datepicker__dialog-bar", children: [jsx("div", { className: "ids-datepicker__dialog-header", id: headerId, ref: headerRef, tabIndex: -1, children: calendarHeader }), jsx("button", { className: "ids-datepicker__dialog-close-button", onClick: closeDialog, "aria-label": srCloseText })] }), jsx(DayPicker, { mode: "single", locale: sv, labels: {
216
+ return (jsxs("div", { className: clsx("ids-datepicker", { "ids-datepicker--invalid": !noValidation && hasError }, className), ...props, children: [isDialogOpen && jsx("div", { className: "ids-datepicker__overlay" }), label && (jsxs("div", { className: "ids-label-wrapper ids-label-wrapper--margin-bottom", children: [jsx("label", { htmlFor: inputId, className: "ids-label", children: label }), tooltip && jsx("span", { className: "ids-label__tooltip", children: tooltip })] })), jsxs("div", { className: "ids-datepicker__input-wrapper", children: [jsx("input", { className: clsx("ids-datepicker__input", { "ids-input--light": light }), ref: inputRef, style: { fontSize: "inherit" }, id: inputId, type: "text", value: inputValue, required: required, disabled: disabled, "aria-invalid": !noValidation && hasError, placeholder: placeholder, onChange: handleInputChange, onInvalid: handleInvalid, onBlur: handleBlur, pattern: "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$" }), jsx("button", { ref: triggerRef, type: "button", className: "ids-datepicker__trigger", style: { fontSize: "inherit" }, disabled: disabled, onClick: handleOpenDialog, "aria-controls": "dialog", "aria-haspopup": "dialog", "aria-expanded": isDialogOpen, "aria-label": srOpenText }), jsxs("div", { className: clsx("ids-datepicker__dialog", { "ids-datepicker__dialog--show": isDialogOpen }), role: "dialog", ref: dialogRef, id: dialogId, "aria-modal": true, "aria-labelledby": headerId, children: [jsxs("div", { className: "ids-datepicker__dialog-bar", children: [jsx("div", { className: "ids-datepicker__dialog-header", id: headerId, ref: headerRef, tabIndex: -1, children: calendarHeader }), jsx("button", { className: "ids-datepicker__dialog-close-button", onClick: closeDialog, "aria-label": srCloseText })] }), jsx(DayPicker, { mode: "single", locale: sv, labels: {
194
217
  labelWeekNumberHeader: () => "Veckonumer",
195
218
  labelWeekNumber: (weekNumber) => `vecka`,
196
219
  labelDayButton(date, modifiers, options, dateLib) {
@@ -4,6 +4,7 @@ export interface IDSInputBaseProps extends InputHTMLAttributes<HTMLInputElement>
4
4
  type?: string;
5
5
  icon?: string;
6
6
  hint?: string | ReactNode;
7
+ unit?: string;
7
8
  showSearchLabel?: boolean;
8
9
  errorMsg?: string;
9
10
  disabled?: boolean;
@@ -21,4 +22,4 @@ export interface IDSInputBaseProps extends InputHTMLAttributes<HTMLInputElement>
21
22
  inputRef?: React.Ref<HTMLInputElement>;
22
23
  style?: CSSProperties;
23
24
  }
24
- export declare function IDSInputBase({ label, type, icon, hint, showSearchLabel, errorMsg, dataTestId, disabled, invalid, required, focusAnchor, light, readOnly, tooltip, submitButton, className, id, hintId, errorMsgId, inputRef, style, ...props }: IDSInputBaseProps): import("react/jsx-runtime").JSX.Element;
25
+ export declare function IDSInputBase({ label, type, icon, hint, unit, showSearchLabel, errorMsg, dataTestId, disabled, invalid, required, focusAnchor, light, readOnly, tooltip, submitButton, className, id, hintId, errorMsgId, inputRef, style, ...props }: IDSInputBaseProps): import("react/jsx-runtime").JSX.Element;
@@ -1,9 +1,9 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { useId } from 'react';
3
3
  import clsx from 'clsx';
4
4
  import { IDSErrorMessage } from '../error-message/error-message.js';
5
5
 
6
- function IDSInputBase({ label, type = "text", icon, hint, showSearchLabel = false, errorMsg, dataTestId, disabled = false, invalid = false, required = false, focusAnchor = false, light = false, readOnly = false, tooltip, submitButton, className, id, hintId, errorMsgId, inputRef, style, ...props }) {
6
+ function IDSInputBase({ label, type = "text", icon, hint, unit, showSearchLabel = false, errorMsg, dataTestId, disabled = false, invalid = false, required = false, focusAnchor = false, light = false, readOnly = false, tooltip, submitButton, className, id, hintId, errorMsgId, inputRef, style, ...props }) {
7
7
  const reactId = useId();
8
8
  const inputId = !!id ? id : `input-base-${reactId}`;
9
9
  const baseHintId = !!hintId ? hintId : `input-base-hint-${reactId}`;
@@ -19,14 +19,14 @@ function IDSInputBase({ label, type = "text", icon, hint, showSearchLabel = fals
19
19
  }
20
20
  : {};
21
21
  ariaHandler["aria-label"] = type === "search" && !showSearchLabel ? label : "";
22
- return (jsx("div", { className: clsx("ids-input", { "ids-input--search": type === "search", "ids-inout--icon": !!icon }, className), "data-testid": dataTestId, style: style, children: jsxs("div", { className: "ids-input__wrapper", children: [label && (jsxs("div", { className: "ids-label-wrapper ids-label-wrapper--margin-bottom", children: [jsx("label", { className: clsx("ids-label", {
23
- "ids-label--disabled": disabled || readOnly,
24
- "ids-hidden": type === "search" && !showSearchLabel
25
- }), htmlFor: inputId, children: label }), tooltip && jsx("span", { className: "ids-label__tooltip", children: tooltip })] })), jsxs("div", { className: "ids-input__input-wrapper", children: [type === "search" && jsx("span", { className: "ids-input__search-icon" }), jsx("input", { ref: inputRef, id: inputId, type: type, readOnly: readOnly, className: clsx("ids-input__input", {
26
- "ids-input--light": light,
27
- "ids-input--invalid": invalid,
28
- "ids-focus-anchor": focusAnchor
29
- }), "aria-invalid": invalid, required: required, "aria-required": required, disabled: disabled, "aria-disabled": disabled, ...ariaHandler, ...props }), icon && type !== "search" && jsx("span", { className: `ids-input__icon ids-icon-${icon}` })] }), hint && (jsx("div", { id: baseHintId, className: "ids-input__hint", children: hint })), showErrorMsg && (jsx(IDSErrorMessage, { id: baseErrorMsgId, show: true, children: errorMsg }))] }) }));
22
+ return (jsxs(Fragment, { children: [jsxs("div", { className: clsx("ids-input", { "ids-input--search": type === "search", "ids-inout--icon": !!icon }, className), "data-testid": dataTestId, style: style, children: [jsxs("div", { className: "ids-input__wrapper", children: [label && (jsxs("div", { className: "ids-label-wrapper ids-label-wrapper--margin-bottom", children: [jsx("label", { className: clsx("ids-label", {
23
+ "ids-label--disabled": disabled || readOnly,
24
+ "ids-hidden": type === "search" && !showSearchLabel
25
+ }), htmlFor: inputId, children: label }), tooltip && jsx("span", { className: "ids-label__tooltip", children: tooltip })] })), jsxs("div", { className: "ids-input__unit-wrapper", children: [jsxs("div", { className: "ids-input__input-wrapper", children: [type === "search" && jsx("span", { className: "ids-input__search-icon" }), jsx("input", { ref: inputRef, id: inputId, type: type, readOnly: readOnly, className: clsx("ids-input__input", {
26
+ "ids-input--light": light,
27
+ "ids-input--invalid": invalid,
28
+ "ids-focus-anchor": focusAnchor
29
+ }), "aria-invalid": invalid, required: required, "aria-required": required, disabled: disabled, "aria-disabled": disabled, ...ariaHandler, ...props }), icon && type !== "search" && jsx("span", { className: `ids-input__icon ids-icon-${icon}` })] }), jsx("div", { className: "ids-input__unit", "aria-hidden": "true", children: unit })] }), hint && (jsx("div", { className: "ids-input__hint", id: baseHintId, children: hint }))] }), !!submitButton && submitButton] }), showErrorMsg && (jsx(IDSErrorMessage, { id: baseErrorMsgId, show: true, children: errorMsg }))] }));
30
30
  }
31
31
 
32
32
  export { IDSInputBase };
@@ -4,6 +4,7 @@ interface IDSInputProps extends InputHTMLAttributes<HTMLInputElement> {
4
4
  type?: string;
5
5
  icon?: string;
6
6
  hint?: string | ReactNode;
7
+ unit?: string;
7
8
  showSearchLabel?: boolean;
8
9
  errorMsg?: string;
9
10
  disabled?: boolean;
@@ -1,6 +1,7 @@
1
1
  import React, { ReactNode, FieldsetHTMLAttributes } from "react";
2
2
  interface IDSRadioGroupBaseProps extends FieldsetHTMLAttributes<HTMLFieldSetElement> {
3
3
  legend?: string;
4
+ hideLegend?: boolean;
4
5
  errorMsg?: string | ReactNode;
5
6
  compact?: boolean;
6
7
  required?: boolean;
@@ -9,5 +10,5 @@ interface IDSRadioGroupBaseProps extends FieldsetHTMLAttributes<HTMLFieldSetElem
9
10
  errorMsgId?: string;
10
11
  groupRef?: React.Ref<HTMLFieldSetElement>;
11
12
  }
12
- export declare function IDSRadioGroupBase({ legend, errorMsg, errorMsgId, compact, required, tooltip, className, children, invalid, groupRef, ...props }: IDSRadioGroupBaseProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function IDSRadioGroupBase({ legend, hideLegend, errorMsg, errorMsgId, compact, required, tooltip, className, children, invalid, groupRef, ...props }: IDSRadioGroupBaseProps): import("react/jsx-runtime").JSX.Element;
13
14
  export {};
@@ -2,9 +2,11 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { IDSErrorMessage } from '../error-message/error-message.js';
3
3
  import clsx from 'clsx';
4
4
 
5
- function IDSRadioGroupBase({ legend, errorMsg, errorMsgId, compact = false, required = false, tooltip, className, children, invalid, groupRef, ...props }) {
5
+ function IDSRadioGroupBase({ legend, hideLegend, errorMsg, errorMsgId, compact = false, required = false, tooltip, className, children, invalid, groupRef, ...props }) {
6
6
  const showErrorMsg = invalid && !!errorMsg && !!errorMsgId;
7
- return (jsxs("fieldset", { ref: groupRef, "aria-required": required, className: clsx("ids-form-group__fieldset", { "ids-form-group__fieldset--compact": 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 })] }) })), children, showErrorMsg && (jsx(IDSErrorMessage, { id: errorMsgId, show: true, style: { marginTop: compact ? "0.75rem" : "auto" }, children: errorMsg }))] }));
7
+ return (jsxs("fieldset", { ref: groupRef, "aria-required": required, className: clsx("ids-form-group__fieldset", { "ids-form-group__fieldset--compact": compact }, className), ...props, children: [legend && (jsx("div", { className: clsx("ids-label-wrapper", {
8
+ "ids-label-wrapper--sr-only": hideLegend
9
+ }, className), children: jsxs("legend", { children: [legend, tooltip && jsx("span", { className: "ids-legend__tooltip", children: tooltip })] }) })), children, showErrorMsg && (jsx(IDSErrorMessage, { id: errorMsgId, show: true, style: { marginTop: compact ? "0.75rem" : "auto" }, children: errorMsg }))] }));
8
10
  }
9
11
 
10
12
  export { IDSRadioGroupBase };