@inera/ids-react 6.2.0 → 7.0.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.
Files changed (219) hide show
  1. package/components/accordion/accordion.d.ts +1 -1
  2. package/components/accordion/accordion.js +6 -7
  3. package/components/agent/agent.d.ts +1 -1
  4. package/components/agent/agent.js +2 -2
  5. package/components/alert/alert.d.ts +1 -1
  6. package/components/alert/alert.js +9 -2
  7. package/components/alert-global/alert-global.d.ts +2 -2
  8. package/components/alert-global/alert-global.js +6 -7
  9. package/components/badge/badge.d.ts +4 -3
  10. package/components/badge/badge.js +4 -3
  11. package/components/box-link/box-link.d.ts +11 -3
  12. package/components/box-link/box-link.js +9 -9
  13. package/components/breadcrumbs/breadcrumbs.d.ts +1 -1
  14. package/components/breadcrumbs/breadcrumbs.js +4 -2
  15. package/components/button/button.d.ts +23 -5
  16. package/components/button/button.js +95 -11
  17. package/components/button-group/button-group.d.ts +13 -3
  18. package/components/button-group/button-group.js +10 -9
  19. package/components/card/card.d.ts +4 -3
  20. package/components/card/card.js +16 -8
  21. package/components/carousel/carousel-item.d.ts +10 -0
  22. package/components/carousel/carousel-item.js +24 -0
  23. package/components/carousel/carousel.d.ts +11 -5
  24. package/components/carousel/carousel.js +167 -16
  25. package/components/date-label/date-label.d.ts +2 -2
  26. package/components/date-label/date-label.js +4 -40
  27. package/components/dialog/dialog.d.ts +23 -6
  28. package/components/dialog/dialog.js +75 -13
  29. package/components/dropdown/dropdown-content-link.d.ts +6 -0
  30. package/components/dropdown/dropdown-content-link.js +20 -0
  31. package/components/dropdown/dropdown.d.ts +16 -8
  32. package/components/dropdown/dropdown.js +72 -20
  33. package/components/footer-1177/footer-1177.d.ts +23 -3
  34. package/components/footer-1177/footer-1177.js +64 -9
  35. package/components/footer-1177-admin/footer-1177-admin.d.ts +21 -3
  36. package/components/footer-1177-admin/footer-1177-admin.js +63 -9
  37. package/components/footer-1177-pro/footer-1177-pro.d.ts +17 -3
  38. package/components/footer-1177-pro/footer-1177-pro.js +39 -9
  39. package/components/footer-inera/footer-inera.d.ts +23 -3
  40. package/components/footer-inera/footer-inera.js +64 -9
  41. package/components/footer-inera-admin/footer-inera-admin.d.ts +23 -3
  42. package/components/footer-inera-admin/footer-inera-admin.js +61 -9
  43. package/components/form/check-button/check-button.d.ts +7 -3
  44. package/components/form/check-button/check-button.js +12 -5
  45. package/components/form/checkbox/checkbox-group.d.ts +13 -3
  46. package/components/form/checkbox/checkbox-group.js +51 -9
  47. package/components/form/checkbox/checkbox.d.ts +17 -3
  48. package/components/form/checkbox/checkbox.js +52 -5
  49. package/components/form/error-message/error-message.d.ts +10 -0
  50. package/components/form/error-message/error-message.js +12 -0
  51. package/components/form/form-hooks/useAriaDescribedBy.d.ts +1 -0
  52. package/components/form/form-hooks/useAriaDescribedBy.js +26 -0
  53. package/components/form/form-hooks/useGroupValidity.d.ts +1 -0
  54. package/components/form/form-hooks/useGroupValidity.js +60 -0
  55. package/components/form/form-hooks/useInputValidity.d.ts +1 -0
  56. package/components/form/form-hooks/useInputValidity.js +27 -0
  57. package/components/form/input/input.d.ts +22 -3
  58. package/components/form/input/input.js +58 -8
  59. package/components/form/radio/radio-group.d.ts +13 -3
  60. package/components/form/radio/radio-group.js +28 -5
  61. package/components/form/radio/radio.d.ts +17 -3
  62. package/components/form/radio/radio.js +24 -8
  63. package/components/form/radio-button/radio-button-group.d.ts +9 -0
  64. package/components/form/radio-button/radio-button-group.js +22 -0
  65. package/components/form/radio-button/radio-button.d.ts +9 -0
  66. package/components/form/radio-button/radio-button.js +15 -0
  67. package/components/form/range/range.d.ts +16 -3
  68. package/components/form/range/range.js +30 -8
  69. package/components/form/select/select.d.ts +15 -3
  70. package/components/form/select/select.js +20 -8
  71. package/components/form/select-multiple/select-multiple.d.ts +18 -3
  72. package/components/form/select-multiple/select-multiple.js +60 -9
  73. package/components/form/spinner/spinner.d.ts +9 -3
  74. package/components/form/spinner/spinner.js +9 -9
  75. package/components/form/textarea/textarea.d.ts +18 -3
  76. package/components/form/textarea/textarea.js +27 -8
  77. package/components/form/time/time.d.ts +13 -3
  78. package/components/form/time/time.js +22 -8
  79. package/components/form/toggle/toggle.d.ts +8 -3
  80. package/components/form/toggle/toggle.js +11 -8
  81. package/components/grid/column.d.ts +16 -0
  82. package/components/grid/column.js +13 -0
  83. package/components/grid/container.d.ts +9 -0
  84. package/components/grid/container.js +24 -0
  85. package/components/grid/row.d.ts +9 -0
  86. package/components/grid/row.js +18 -0
  87. package/components/header-1177/header-1177-avatar.d.ts +10 -2
  88. package/components/header-1177/header-1177-avatar.js +30 -8
  89. package/components/header-1177/header-1177-item.d.ts +12 -2
  90. package/components/header-1177/header-1177-item.js +25 -8
  91. package/components/header-1177/header-1177-menu-mobile.d.ts +11 -0
  92. package/components/header-1177/header-1177-menu-mobile.js +42 -0
  93. package/components/header-1177/header-1177-nav-item-mobile.d.ts +11 -2
  94. package/components/header-1177/header-1177-nav-item-mobile.js +24 -8
  95. package/components/header-1177/header-1177-nav-item.d.ts +15 -2
  96. package/components/header-1177/header-1177-nav-item.js +22 -8
  97. package/components/header-1177/header-1177-nav.d.ts +8 -2
  98. package/components/header-1177/header-1177-nav.js +14 -8
  99. package/components/header-1177/header-1177.d.ts +22 -5
  100. package/components/header-1177/header-1177.js +41 -12
  101. package/components/header-1177-admin/header-1177-admin-avatar-mobile.d.ts +9 -2
  102. package/components/header-1177-admin/header-1177-admin-avatar-mobile.js +6 -8
  103. package/components/header-1177-admin/header-1177-admin-avatar.d.ts +10 -2
  104. package/components/header-1177-admin/header-1177-admin-avatar.js +31 -8
  105. package/components/header-1177-admin/header-1177-admin-item.d.ts +12 -2
  106. package/components/header-1177-admin/header-1177-admin-item.js +26 -8
  107. package/components/header-1177-admin/header-1177-admin-nav-item.d.ts +15 -2
  108. package/components/header-1177-admin/header-1177-admin-nav-item.js +24 -8
  109. package/components/header-1177-admin/header-1177-admin-nav.d.ts +7 -2
  110. package/components/header-1177-admin/header-1177-admin-nav.js +12 -8
  111. package/components/header-1177-admin/header-1177-admin.d.ts +22 -3
  112. package/components/header-1177-admin/header-1177-admin.js +26 -9
  113. package/components/header-1177-pro/header-1177-pro-avatar-mobile.d.ts +9 -2
  114. package/components/header-1177-pro/header-1177-pro-avatar-mobile.js +6 -8
  115. package/components/header-1177-pro/header-1177-pro-avatar.d.ts +10 -2
  116. package/components/header-1177-pro/header-1177-pro-avatar.js +31 -8
  117. package/components/header-1177-pro/header-1177-pro-item.d.ts +12 -2
  118. package/components/header-1177-pro/header-1177-pro-item.js +23 -8
  119. package/components/header-1177-pro/header-1177-pro-nav-item.d.ts +15 -2
  120. package/components/header-1177-pro/header-1177-pro-nav-item.js +33 -8
  121. package/components/header-1177-pro/header-1177-pro-nav-menu-mobile.d.ts +11 -5
  122. package/components/header-1177-pro/header-1177-pro-nav-menu-mobile.js +32 -12
  123. package/components/header-1177-pro/header-1177-pro-nav.d.ts +10 -2
  124. package/components/header-1177-pro/header-1177-pro-nav.js +27 -8
  125. package/components/header-1177-pro/header-1177-pro.d.ts +23 -5
  126. package/components/header-1177-pro/header-1177-pro.js +37 -12
  127. package/components/header-inera/header-inera-item.d.ts +13 -2
  128. package/components/header-inera/header-inera-item.js +24 -8
  129. package/components/header-inera/header-inera-nav-item.d.ts +15 -2
  130. package/components/header-inera/header-inera-nav-item.js +54 -8
  131. package/components/header-inera/header-inera-nav-mobile.d.ts +11 -5
  132. package/components/header-inera/header-inera-nav-mobile.js +44 -12
  133. package/components/header-inera/header-inera-nav.d.ts +7 -2
  134. package/components/header-inera/header-inera-nav.js +13 -8
  135. package/components/header-inera/header-inera.d.ts +16 -3
  136. package/components/header-inera/header-inera.js +16 -9
  137. package/components/header-inera-admin/header-inera-admin-avatar-mobile.d.ts +9 -2
  138. package/components/header-inera-admin/header-inera-admin-avatar-mobile.js +11 -8
  139. package/components/header-inera-admin/header-inera-admin-avatar.d.ts +12 -2
  140. package/components/header-inera-admin/header-inera-admin-avatar.js +32 -8
  141. package/components/header-inera-admin/header-inera-admin-item.d.ts +13 -2
  142. package/components/header-inera-admin/header-inera-admin-item.js +24 -8
  143. package/components/header-inera-admin/header-inera-admin-nav-item.d.ts +16 -2
  144. package/components/header-inera-admin/header-inera-admin-nav-item.js +54 -8
  145. package/components/header-inera-admin/header-inera-admin-nav-mobile.d.ts +12 -5
  146. package/components/header-inera-admin/header-inera-admin-nav-mobile.js +32 -12
  147. package/components/header-inera-admin/header-inera-admin-nav.d.ts +8 -2
  148. package/components/header-inera-admin/header-inera-admin-nav.js +13 -8
  149. package/components/header-inera-admin/header-inera-admin.d.ts +15 -3
  150. package/components/header-inera-admin/header-inera-admin.js +24 -9
  151. package/components/header-patient/header-patient.d.ts +13 -0
  152. package/components/header-patient/header-patient.js +21 -0
  153. package/components/link/link.d.ts +17 -3
  154. package/components/link/link.js +42 -9
  155. package/components/mobile/menu/item/mobile-item.d.ts +15 -4
  156. package/components/mobile/menu/item/mobile-item.js +58 -11
  157. package/components/mobile/menu/mobile-menu.d.ts +7 -3
  158. package/components/mobile/menu/mobile-menu.js +9 -9
  159. package/components/navigation/content/navigation-content.d.ts +7 -3
  160. package/components/navigation/content/navigation-content.js +18 -9
  161. package/components/navigation/local/navigation-local.d.ts +7 -3
  162. package/components/navigation/local/navigation-local.js +6 -9
  163. package/components/notification/badge/notification-badge.d.ts +4 -2
  164. package/components/notification/badge/notification-badge.js +4 -3
  165. package/components/pagination/data-pagination/data-pagination.d.ts +24 -3
  166. package/components/pagination/data-pagination/data-pagination.js +14 -9
  167. package/components/pagination/list-pagination/list-pagination.d.ts +19 -7
  168. package/components/pagination/list-pagination/list-pagination.js +51 -14
  169. package/components/popover/popover.d.ts +20 -5
  170. package/components/popover/popover.js +192 -16
  171. package/components/progressbar/progressbar.d.ts +1 -1
  172. package/components/progressbar/progressbar.js +4 -2
  173. package/components/puff-list/puff-list-item/puff-list-item-info.d.ts +7 -0
  174. package/components/puff-list/puff-list-item/puff-list-item-info.js +8 -0
  175. package/components/puff-list/puff-list-item/puff-list-item.d.ts +19 -3
  176. package/components/puff-list/puff-list-item/puff-list-item.js +56 -9
  177. package/components/puff-list/puff-list.d.ts +7 -3
  178. package/components/puff-list/puff-list.js +6 -9
  179. package/components/region-icon/region-icon.d.ts +12 -0
  180. package/components/region-icon/region-icon.js +25 -0
  181. package/components/side-menu/side-menu.d.ts +16 -6
  182. package/components/side-menu/side-menu.js +52 -13
  183. package/components/side-panel/side-panel.d.ts +21 -6
  184. package/components/side-panel/side-panel.js +74 -13
  185. package/components/stepper/step.d.ts +18 -0
  186. package/components/stepper/step.js +41 -0
  187. package/components/stepper/stepper.d.ts +9 -7
  188. package/components/stepper/stepper.js +21 -19
  189. package/components/tabs/tab-panel.d.ts +11 -0
  190. package/components/tabs/tab-panel.js +20 -0
  191. package/components/tabs/tab.d.ts +15 -0
  192. package/components/tabs/tab.js +19 -0
  193. package/components/tabs/tabs.d.ts +14 -9
  194. package/components/tabs/tabs.js +79 -25
  195. package/components/tag/tag.d.ts +5 -6
  196. package/components/tag/tag.js +9 -9
  197. package/components/tooltip/tooltip.d.ts +10 -3
  198. package/components/tooltip/tooltip.js +79 -9
  199. package/components/utils/contexts/HeaderContext.d.ts +9 -0
  200. package/components/utils/contexts/HeaderContext.js +7 -0
  201. package/components/utils/hooks/useElementId.d.ts +5 -0
  202. package/components/utils/hooks/useElementId.js +12 -0
  203. package/components/utils/hooks/useFocusTrap.d.ts +1 -0
  204. package/components/utils/hooks/useFocusTrap.js +44 -0
  205. package/components/utils/utils.d.ts +6 -0
  206. package/components/utils/utils.js +44 -0
  207. package/index.d.ts +15 -5
  208. package/index.js +20 -10
  209. package/package.json +2 -2
  210. package/components/form/errormessage/error-message.d.ts +0 -3
  211. package/components/form/errormessage/error-message.js +0 -12
  212. package/components/grid/grid.d.ts +0 -9
  213. package/components/grid/grid.js +0 -26
  214. package/components/header-1177/header-1177-nav-menu-mobile.d.ts +0 -5
  215. package/components/header-1177/header-1177-nav-menu-mobile.js +0 -15
  216. package/components/icon-region/icon-region.d.ts +0 -3
  217. package/components/icon-region/icon-region.js +0 -12
  218. package/components/puff-list/puff-list-item/puff-list-info/puff-list-item-info.d.ts +0 -3
  219. package/components/puff-list/puff-list-item/puff-list-info/puff-list-item-info.js +0 -12
@@ -1,18 +1,169 @@
1
- import * as React from 'react';
2
- import '@inera/ids-core/components/carousel/register.js';
3
- import { IDSCarousel as IDSCarousel$1 } from '@inera/ids-core/components/carousel/carousel-element.js';
4
- import { IDSCarouselItem as IDSCarouselItem$1 } from '@inera/ids-core/components/carousel/carousel-item/carousel-item-element.js';
5
- import { createComponent } from '@lit-labs/react';
1
+ "use client";
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import React__default, { useState, useRef, Children, useEffect } from 'react';
4
+ import '@inera/ids-design/components/carousel/carousel.css';
5
+ import clsx from 'clsx';
6
+ import { breakPoints } from '../utils/utils.js';
6
7
 
7
- const IDSCarousel = createComponent({
8
- tagName: 'ids-carousel',
9
- elementClass: IDSCarousel$1,
10
- react: React,
11
- });
12
- const IDSCarouselItem = createComponent({
13
- tagName: 'ids-carousel-item',
14
- elementClass: IDSCarouselItem$1,
15
- react: React,
16
- });
8
+ const IDSCarousel = ({ autoplay = false, autoplayDelay = 5000, srNextLabel = "Nästa slide", srPrevLabel = "Föregående slide", className, children }) => {
9
+ const [activeSlideIndex, setActiveSlideIndex] = useState(0);
10
+ const [isAnimating, setIsAnimating] = useState(false);
11
+ const [isAnimatingLeft, setIsAnimatingLeft] = useState(false);
12
+ const [isAnimatingRight, setIsAnimatingRight] = useState(false);
13
+ const [buttonPosition, setButtonPosition] = useState({ top: 0, height: 0 });
14
+ const carouselRef = useRef(null);
15
+ const slideCount = Children.count(children);
16
+ let windowWidth = window.innerWidth;
17
+ // Validate slide count
18
+ useEffect(() => {
19
+ if (slideCount < 3) {
20
+ console.warn("Carousel requires at least 3 carousel-items.");
21
+ }
22
+ }, [slideCount]);
23
+ // Initial setup
24
+ useEffect(() => {
25
+ if (slideCount > 2) {
26
+ setActiveSlideIndex(0);
27
+ }
28
+ }, []);
29
+ // Recalculate window width on resize
30
+ useEffect(() => {
31
+ windowWidth = window.innerWidth;
32
+ }, [windowWidth]);
33
+ // Resize observer
34
+ useEffect(() => {
35
+ const resizeObserver = new ResizeObserver(entries => {
36
+ window.requestAnimationFrame(() => {
37
+ if (!Array.isArray(entries) || !entries.length)
38
+ return;
39
+ setButtonLocation();
40
+ });
41
+ });
42
+ const carouselSlide = carouselRef.current?.querySelector(".js-carousel-slide");
43
+ if (carouselSlide)
44
+ resizeObserver.observe(carouselSlide);
45
+ return () => resizeObserver.disconnect();
46
+ }, []);
47
+ // Set button location and display buttons after image load
48
+ useEffect(() => {
49
+ const firstImage = carouselRef.current?.querySelector(".ids-carousel-item__image img");
50
+ const buttons = carouselRef.current?.querySelectorAll("button");
51
+ const handleImageLoad = () => {
52
+ setButtonLocation();
53
+ buttons?.forEach(btn => {
54
+ setTimeout(() => {
55
+ btn.style.opacity = "1";
56
+ }, 200);
57
+ });
58
+ };
59
+ firstImage?.addEventListener("load", handleImageLoad);
60
+ return () => firstImage?.removeEventListener("load", handleImageLoad);
61
+ }, []);
62
+ // Set button location
63
+ const setButtonLocation = () => {
64
+ const imageHeight = carouselRef.current
65
+ ?.querySelector(".ids-carousel-item__image")
66
+ ?.getBoundingClientRect().height;
67
+ const buttonPlacement = imageHeight / 2;
68
+ if (imageHeight && buttonPlacement) {
69
+ setButtonPosition({
70
+ top: buttonPlacement,
71
+ height: imageHeight
72
+ });
73
+ }
74
+ };
75
+ useEffect(() => {
76
+ if (!autoplay)
77
+ return;
78
+ const delay = Math.max(autoplayDelay, 500);
79
+ const timer = setInterval(() => {
80
+ handleNext();
81
+ }, delay);
82
+ return () => clearInterval(timer);
83
+ }, [autoplay, autoplayDelay]);
84
+ // change slide
85
+ const handleNext = () => {
86
+ if (isAnimating)
87
+ return;
88
+ setIsAnimating(true);
89
+ setIsAnimatingRight(true);
90
+ setActiveSlideIndex(prev => (prev + 1) % slideCount);
91
+ setTimeout(() => {
92
+ setIsAnimating(false);
93
+ setIsAnimatingRight(false);
94
+ }, 500);
95
+ };
96
+ // Previous slide
97
+ const handlePrev = () => {
98
+ if (isAnimating)
99
+ return;
100
+ setIsAnimating(true);
101
+ setIsAnimatingLeft(true);
102
+ setActiveSlideIndex(prev => (prev - 1 + slideCount) % slideCount);
103
+ setTimeout(() => {
104
+ setIsAnimating(false);
105
+ setIsAnimatingLeft(false);
106
+ }, 500);
107
+ };
108
+ // Touch/swipe
109
+ const touchStartX = useRef(null);
110
+ const handleTouchStart = (e) => {
111
+ touchStartX.current = e.touches[0].clientX;
112
+ };
113
+ const handleTouchEnd = (e) => {
114
+ const distance = e.changedTouches[0].clientX - touchStartX.current;
115
+ if (distance > 100)
116
+ handlePrev();
117
+ if (distance < -100)
118
+ handleNext();
119
+ touchStartX.current = null;
120
+ };
121
+ const setTabIndexRecursively = (node, tabIndex) => {
122
+ if (React__default.isValidElement(node)) {
123
+ const props = {};
124
+ // Skip recursion into IDSLink — set tabIndex only at the top level if needed
125
+ if (node.type.displayName === "IDSLink" || node.type.name === "IDSLink") {
126
+ return React__default.cloneElement(node, {
127
+ tabIndex
128
+ });
129
+ }
130
+ if (typeof node.type === "string") {
131
+ const focusableTags = ["a", "button", "input", "select", "textarea"];
132
+ if (focusableTags.includes(node.type)) {
133
+ props.tabIndex = tabIndex;
134
+ }
135
+ }
136
+ if (node.props && node.props.children) {
137
+ props.children = React__default.Children.map(node.props.children, child => setTabIndexRecursively(child, tabIndex));
138
+ }
139
+ return React__default.cloneElement(node, props);
140
+ }
141
+ return node;
142
+ };
143
+ const slides = Children.map(children, (child, index) => {
144
+ const isActive = index === activeSlideIndex;
145
+ const isPrev = index === (activeSlideIndex - 1 + slideCount) % slideCount;
146
+ const isNext = index === (activeSlideIndex + 1) % slideCount;
147
+ let itemClass = "ids-carousel-item-wrapper";
148
+ if (isActive)
149
+ itemClass += " active";
150
+ else if (isPrev)
151
+ itemClass += " prev";
152
+ else if (isNext)
153
+ itemClass += " next";
154
+ // Disable tabbing for all elements inside inactive slides
155
+ const processedChild = isActive ? child : setTabIndexRecursively(child, -1);
156
+ return (jsx("div", { className: itemClass, "aria-hidden": !isActive, children: processedChild }, index));
157
+ });
158
+ const isMobile = windowWidth < breakPoints.medium;
159
+ return (jsxs("div", { className: clsx("ids-carousel", className), ref: carouselRef, children: [jsx("button", { "aria-label": srPrevLabel, className: clsx("ids-carousel__button-prev", {
160
+ "ids-carousel__button-prev--mobile": isMobile
161
+ }), onClick: handlePrev, style: buttonPosition, children: isMobile && jsx("div", { className: "ids-carousel-btn__inner" }) }), jsx("button", { "aria-label": srNextLabel, className: clsx("ids-carousel__button-next", {
162
+ "ids-carousel__button-next--mobile": isMobile
163
+ }), onClick: handleNext, style: buttonPosition, children: isMobile && jsx("div", { className: "ids-carousel-btn__inner" }) }), jsx("div", { className: clsx("ids-carousel-slide js-carousel-slide", {
164
+ "animating-left": isAnimatingLeft,
165
+ "animating-right": isAnimatingRight
166
+ }), onTouchStart: handleTouchStart, onTouchEnd: handleTouchEnd, children: jsx("div", { "aria-live": "polite", children: slides }) })] }));
167
+ };
17
168
 
18
- export { IDSCarousel, IDSCarouselItem };
169
+ export { IDSCarousel };
@@ -1,6 +1,6 @@
1
- import React from "react";
1
+ import React, { DetailedHTMLProps, TimeHTMLAttributes } from "react";
2
2
  import "@inera/ids-design/components/date-label/date-label.css";
3
- interface IDSDateLabelProps {
3
+ interface IDSDateLabelProps extends DetailedHTMLProps<TimeHTMLAttributes<HTMLTimeElement>, HTMLTimeElement> {
4
4
  date?: Date | null;
5
5
  year?: number;
6
6
  month?: number;
@@ -2,8 +2,10 @@
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { useState, useEffect } from 'react';
4
4
  import '@inera/ids-design/components/date-label/date-label.css';
5
+ import { getDayAsText, getMonthAsSweText } from '../utils/utils.js';
6
+ import clsx from 'clsx';
5
7
 
6
- const IDSDateLabel = ({ date = null, year = 0, month = 0, monthLabel = "", day = 0 }) => {
8
+ const IDSDateLabel = ({ date = null, year = 0, month = 0, monthLabel = "", day = 0, className, ...props }) => {
7
9
  const [presentedDate, setPresentedDate] = useState(null);
8
10
  useEffect(() => {
9
11
  if (date) {
@@ -17,45 +19,7 @@ const IDSDateLabel = ({ date = null, year = 0, month = 0, monthLabel = "", day =
17
19
  return getDayAsText(dayNumber);
18
20
  };
19
21
  const getMonthText = () => (monthLabel ? monthLabel : getMonthAsSweText(getMonth() - 1, 3));
20
- const getDayAsText = (day) => {
21
- if (day > 0) {
22
- return day < 10 ? "0" + day : "" + day;
23
- }
24
- else {
25
- return "";
26
- }
27
- };
28
- const getMonthAsSweText = (date, letters) => {
29
- switch (date) {
30
- case 0:
31
- return "Januari".substring(0, letters);
32
- case 1:
33
- return "Februari".substring(0, letters);
34
- case 2:
35
- return "Mars".substring(0, letters);
36
- case 3:
37
- return "April".substring(0, letters);
38
- case 4:
39
- return "Maj".substring(0, letters);
40
- case 5:
41
- return "Juni".substring(0, letters);
42
- case 6:
43
- return "Juli".substring(0, letters);
44
- case 7:
45
- return "Augusti".substring(0, letters);
46
- case 8:
47
- return "September".substring(0, letters);
48
- case 9:
49
- return "Oktober".substring(0, letters);
50
- case 10:
51
- return "November".substring(0, letters);
52
- case 11:
53
- return "December".substring(0, letters);
54
- default:
55
- return "";
56
- }
57
- };
58
- return (jsxs("time", { className: "ids-date-label", dateTime: `${getDay()}-${getMonth().toString().padStart(2, "0")}-${getYear()}`, children: [jsx("span", { className: "ids-date-label__day", children: getDay() }), jsx("span", { className: "ids-date-label__month", children: getMonthText() }), jsx("span", { className: "ids-date-label__year", children: getYear() })] }));
22
+ return (jsxs("time", { className: clsx("ids-date-label", className), dateTime: `${getDay()}-${getMonth().toString().padStart(2, "0")}-${getYear()}`, ...props, children: [jsx("span", { className: "ids-date-label__day", children: getDay() }), jsx("span", { className: "ids-date-label__month", children: getMonthText() }), jsx("span", { className: "ids-date-label__year", children: getYear() })] }));
59
23
  };
60
24
 
61
25
  export { IDSDateLabel };
@@ -1,6 +1,23 @@
1
- import '@inera/ids-core/components/dialog/register.js';
2
- import { IDSDialog as Dialog } from '@inera/ids-core/components/dialog/dialog-element.js';
3
- export declare const IDSDialog: import("@lit-labs/react").ReactWebComponent<Dialog, {
4
- onClosed: string;
5
- onOpen: string;
6
- }>;
1
+ import React, { ReactNode } from "react";
2
+ import "@inera/ids-design/components/dialog/dialog.css";
3
+ interface IDSDialogProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ show?: boolean;
5
+ srClose?: string;
6
+ dismissible?: boolean;
7
+ autoFocus?: boolean;
8
+ noOverlay?: boolean;
9
+ noFocusTrap?: boolean;
10
+ keepScrollbar?: boolean;
11
+ persistent?: boolean;
12
+ noScrollAreaFocus?: boolean;
13
+ width?: string;
14
+ maxWidth?: string;
15
+ height?: string;
16
+ trigger?: ReactNode;
17
+ headline?: ReactNode;
18
+ actions?: ReactNode;
19
+ children?: ReactNode;
20
+ onVisibilityChange?: (value: boolean) => void;
21
+ }
22
+ export declare const IDSDialog: React.FC<IDSDialogProps>;
23
+ export {};
@@ -1,16 +1,78 @@
1
- import * as React from 'react';
2
- import '@inera/ids-core/components/dialog/register.js';
3
- import { IDSDialog as IDSDialog$1 } from '@inera/ids-core/components/dialog/dialog-element.js';
4
- import { createComponent } from '@lit-labs/react';
1
+ "use client";
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
+ import { useState, useRef, useId, useEffect } from 'react';
4
+ import '@inera/ids-design/components/dialog/dialog.css';
5
+ import { useFocusTrap } from '../utils/hooks/useFocusTrap.js';
6
+ import clsx from 'clsx';
5
7
 
6
- const IDSDialog = createComponent({
7
- tagName: 'ids-dialog',
8
- elementClass: IDSDialog$1,
9
- react: React,
10
- events: {
11
- onClosed: 'closed',
12
- onOpen: 'open'
13
- }
14
- });
8
+ const IDSDialog = ({ show = false, srClose = "Stäng", dismissible = false, autoFocus = true, noOverlay = false, noFocusTrap = false, keepScrollbar = false, persistent = false, noScrollAreaFocus = false, width = "", maxWidth = "", height = "", trigger, headline, actions, children, className, onVisibilityChange, ...props }) => {
9
+ const [isVisible, setIsVisible] = useState(show);
10
+ const dialogRef = useRef(null);
11
+ const bodyRef = useRef(null);
12
+ const headlineId = useId();
13
+ const contentId = useId();
14
+ const [hasScrollbar, setHasScrollbar] = useState(false);
15
+ useFocusTrap(dialogRef.current, isVisible && !noFocusTrap);
16
+ useEffect(() => {
17
+ setIsVisible(show);
18
+ }, [show]);
19
+ useEffect(() => {
20
+ onVisibilityChange?.(isVisible);
21
+ }, [isVisible]);
22
+ useEffect(() => {
23
+ const checkScrollbar = () => {
24
+ if (bodyRef.current) {
25
+ setHasScrollbar(bodyRef.current.clientHeight < bodyRef.current.scrollHeight);
26
+ }
27
+ };
28
+ if (isVisible) {
29
+ !keepScrollbar && document.body.classList.add("ids-hide-overflow");
30
+ checkScrollbar();
31
+ }
32
+ else {
33
+ document.body.classList.remove("ids-hide-overflow");
34
+ }
35
+ return () => {
36
+ document.body.classList.remove("ids-hide-overflow");
37
+ };
38
+ }, [isVisible, keepScrollbar]);
39
+ useEffect(() => {
40
+ const handleKeyDown = (e) => {
41
+ if (e.key === "Escape" && isVisible && !persistent) {
42
+ setIsVisible(false);
43
+ }
44
+ };
45
+ document.addEventListener("keydown", handleKeyDown);
46
+ return () => document.removeEventListener("keydown", handleKeyDown);
47
+ }, [isVisible, persistent, setIsVisible]);
48
+ useEffect(() => {
49
+ if (isVisible && autoFocus) {
50
+ setTimeout(() => {
51
+ const focusable = bodyRef.current?.querySelector(".ids-focus-anchor") ||
52
+ bodyRef.current?.querySelector("h1, h2, h3, [tabindex]:not([tabindex='-1']), button:not([disabled]), a, input:not([disabled]), textarea:not([disabled])") ||
53
+ dialogRef.current?.querySelector("button.ids-dialog__header__button");
54
+ focusable?.focus();
55
+ });
56
+ }
57
+ }, [isVisible, autoFocus]);
58
+ const overlayClick = () => {
59
+ if (!persistent) {
60
+ setIsVisible(false);
61
+ }
62
+ };
63
+ return (jsxs(Fragment, { children: [jsx("div", { className: "ids-dialog__trigger", children: trigger }), jsx("div", { className: clsx("ids-dialog-overlay", {
64
+ "ids-dialog-overlay--hidden": !isVisible || noOverlay
65
+ }), onClick: overlayClick }), jsxs("div", { ref: dialogRef, className: clsx("ids-dialog", {
66
+ "ids-dialog--hidden": !isVisible
67
+ }, className), role: "dialog", "aria-modal": "true", "aria-labelledby": headlineId, "aria-describedby": contentId, style: {
68
+ width,
69
+ maxWidth,
70
+ height,
71
+ maxHeight: height || undefined
72
+ }, ...props, children: [dismissible && (jsx("div", { className: "ids-dialog__header", children: jsx("button", { "aria-label": srClose, className: "ids-dialog__header__button", onClick: () => setIsVisible(false) }) })), jsxs("div", { ref: bodyRef, className: clsx("ids-dialog__body", {
73
+ "ids-dialog__body--has-scrollbar": hasScrollbar,
74
+ "ids-dialog__body--scroll-area-focus": !noScrollAreaFocus
75
+ }), tabIndex: noScrollAreaFocus ? -1 : 0, children: [jsx("div", { id: headlineId, className: "ids-dialog__body__headline", children: headline }), jsx("div", { id: contentId, className: "ids-dialog__body__content", children: children }), actions && jsx("div", { className: "ids-dialog__footer", children: actions })] })] })] }));
76
+ };
15
77
 
16
78
  export { IDSDialog };
@@ -0,0 +1,6 @@
1
+ import React, { ReactElement, HTMLAttributes } from "react";
2
+ import "@inera/ids-design/components/dropdown/dropdown.css";
3
+ export interface IDSDropdownContentLinkProps extends Omit<HTMLAttributes<HTMLAnchorElement>, "children"> {
4
+ children: ReactElement;
5
+ }
6
+ export declare const IDSDropdownContentLink: React.FC<IDSDropdownContentLinkProps>;
@@ -0,0 +1,20 @@
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
2
+ import { isValidElement, cloneElement } from 'react';
3
+ import '@inera/ids-design/components/dropdown/dropdown.css';
4
+ import clsx from 'clsx';
5
+
6
+ const IDSDropdownContentLink = ({ children, className, ...props }) => {
7
+ if (!isValidElement(children) || children.type !== "a") {
8
+ console.error("IDSDropdownContentLink expects a single <a> element as its child.");
9
+ return null;
10
+ }
11
+ const childClassName = clsx("ids-dropdown-content-link", children.props.className, className);
12
+ const content = jsx(Fragment, { children: children.props.children });
13
+ return cloneElement(children, {
14
+ ...props,
15
+ className: childClassName,
16
+ children: content
17
+ });
18
+ };
19
+
20
+ export { IDSDropdownContentLink };
@@ -1,8 +1,16 @@
1
- import "@inera/ids-core/components/dropdown/register.js";
2
- import { IDSDropdown as Dropdown } from "@inera/ids-core/components/dropdown/dropdown-element.js";
3
- import { IDSDropdownContent as DropdownContent } from "@inera/ids-core/components/dropdown/content/dropdown-content-element.js";
4
- export declare const IDSDropdown: import("@lit-labs/react").ReactWebComponent<Dropdown, {
5
- onClosed: string;
6
- onOpened: string;
7
- }>;
8
- export declare const IDSDropdownContent: import("@lit-labs/react").ReactWebComponent<DropdownContent, {}>;
1
+ import React, { ReactNode, ReactElement } from "react";
2
+ import "@inera/ids-design/components/dropdown/dropdown.css";
3
+ type Position = "left" | "right";
4
+ interface IDSDropdownProps extends React.HTMLAttributes<HTMLSpanElement> {
5
+ expanded?: boolean;
6
+ persistent?: boolean;
7
+ position?: Position;
8
+ sBlock?: boolean;
9
+ mBlock?: boolean;
10
+ onOpened?: () => void;
11
+ onClosed?: () => void;
12
+ button: ReactElement;
13
+ children: ReactNode;
14
+ }
15
+ export declare const IDSDropdown: React.FC<IDSDropdownProps>;
16
+ export {};
@@ -1,22 +1,74 @@
1
- import * as React from 'react';
2
- import '@inera/ids-core/components/dropdown/register.js';
3
- import { IDSDropdown as IDSDropdown$1 } from '@inera/ids-core/components/dropdown/dropdown-element.js';
4
- import { IDSDropdownContent as IDSDropdownContent$1 } from '@inera/ids-core/components/dropdown/content/dropdown-content-element.js';
5
- import { createComponent } from '@lit-labs/react';
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import React__default, { useState, useRef, useEffect, isValidElement, cloneElement } from 'react';
4
+ import '@inera/ids-design/components/dropdown/dropdown.css';
5
+ import { useElementId } from '../utils/hooks/useElementId.js';
6
+ import clsx from 'clsx';
6
7
 
7
- const IDSDropdown = createComponent({
8
- tagName: "ids-dropdown",
9
- elementClass: IDSDropdown$1,
10
- react: React,
11
- events: {
12
- onClosed: "closed",
13
- onOpened: "opened"
14
- }
15
- });
16
- const IDSDropdownContent = createComponent({
17
- tagName: "ids-dropdown-content",
18
- elementClass: IDSDropdownContent$1,
19
- react: React
20
- });
8
+ const IDSDropdown = ({ expanded = false, persistent = false, position = "right", sBlock = false, mBlock = false, onOpened, onClosed, children, className, button, ...props }) => {
9
+ const [isExpanded, setIsExpanded] = useState(expanded);
10
+ const triggerRef = useRef(null);
11
+ const contentRef = useRef(null);
12
+ const buttonId = useElementId();
13
+ const contentId = useElementId();
14
+ useEffect(() => {
15
+ setIsExpanded(expanded);
16
+ }, [expanded]);
17
+ useEffect(() => {
18
+ if (!persistent && isExpanded) {
19
+ const handleClickOutside = (event) => {
20
+ if (triggerRef.current &&
21
+ !triggerRef.current.contains(event.target) &&
22
+ contentRef.current &&
23
+ !contentRef.current.contains(event.target)) {
24
+ setIsExpanded(false);
25
+ onClosed?.();
26
+ }
27
+ };
28
+ document.addEventListener("mousedown", handleClickOutside);
29
+ return () => document.removeEventListener("mousedown", handleClickOutside);
30
+ }
31
+ }, [isExpanded, persistent, onClosed]);
32
+ const handleToggle = (e) => {
33
+ setIsExpanded(prev => {
34
+ const next = !prev;
35
+ if (next)
36
+ onOpened?.();
37
+ else
38
+ onClosed?.();
39
+ return next;
40
+ });
41
+ };
42
+ const renderTrigger = () => {
43
+ if (isValidElement(button)) {
44
+ return cloneElement(button, {
45
+ id: buttonId,
46
+ ref: triggerRef,
47
+ onClick: handleToggle,
48
+ "aria-controls": contentId,
49
+ "aria-expanded": isExpanded,
50
+ className: clsx(button.props.className)
51
+ });
52
+ }
53
+ return null;
54
+ };
55
+ const renderDropdownContent = () => {
56
+ const enhancedChildren = React__default.Children.map(children, (child, i) => {
57
+ if (!React__default.isValidElement(child))
58
+ return child;
59
+ return cloneElement(child, {
60
+ key: `dropdown-content-link-${i}`
61
+ });
62
+ });
63
+ return (jsx("div", { id: contentId, ref: contentRef, "aria-labelledby": buttonId, className: clsx(`ids-dropdown__content ids-dropdown__content--position-${position}`, {
64
+ "ids-dropdown__content--mblock": mBlock,
65
+ "ids-dropdown__content--sblock": sBlock
66
+ }), ...props, children: enhancedChildren }));
67
+ };
68
+ return (jsxs("span", { className: clsx(`ids-dropdown`, className, {
69
+ "ids-dropdown--mblock": mBlock,
70
+ "ids-dropdown--sblock": sBlock
71
+ }), children: [renderTrigger(), isExpanded && renderDropdownContent()] }));
72
+ };
21
73
 
22
- export { IDSDropdown, IDSDropdownContent };
74
+ export { IDSDropdown };
@@ -1,3 +1,23 @@
1
- import '@inera/ids-core/components/footer-1177/register.js';
2
- import { IDSFooter1177 as Footer } from '@inera/ids-core/components/footer-1177/footer-1177-element.js';
3
- export declare const IDSFooter1177: import("@lit-labs/react").ReactWebComponent<Footer, {}>;
1
+ import React, { ReactElement, ReactNode } from "react";
2
+ import "@inera/ids-design/components/footer-1177/footer-1177.css";
3
+ import { IDSLinkProps } from "../link/link";
4
+ interface Footer1177Props extends React.HTMLAttributes<HTMLDivElement> {
5
+ headline?: string;
6
+ srHeadline?: string;
7
+ subHeadline?: string;
8
+ cols?: 1 | 2 | 3;
9
+ col1?: ReactElement<IDSLinkProps>[];
10
+ col2?: ReactElement<IDSLinkProps>[];
11
+ col3?: ReactElement<IDSLinkProps>[];
12
+ col1Size?: string;
13
+ col2Size?: string;
14
+ col3Size?: string;
15
+ subFooterLeft?: ReactNode;
16
+ subFooterRight?: ReactNode;
17
+ mobileMenu?: ReactNode;
18
+ mobileLinks?: ReactNode;
19
+ subFooterMobile?: ReactNode;
20
+ children?: ReactNode;
21
+ }
22
+ export declare const IDSFooter1177: React.FC<Footer1177Props>;
23
+ export {};
@@ -1,12 +1,67 @@
1
- import * as React from 'react';
2
- import '@inera/ids-core/components/footer-1177/register.js';
3
- import { IDSFooter1177 as IDSFooter1177$1 } from '@inera/ids-core/components/footer-1177/footer-1177-element.js';
4
- import { createComponent } from '@lit-labs/react';
1
+ "use client";
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
+ import React__default, { useRef, useEffect } from 'react';
4
+ import clsx from 'clsx';
5
+ import '@inera/ids-design/components/footer-1177/footer-1177.css';
5
6
 
6
- const IDSFooter1177 = createComponent({
7
- tagName: 'ids-footer-1177',
8
- elementClass: IDSFooter1177$1,
9
- react: React,
10
- });
7
+ const IDSFooter1177 = ({ headline = "", srHeadline = "", subHeadline = "", cols = 3, col1 = [], col2 = [], col3 = [], col1Size = "2", col2Size = "2", col3Size = "2", subFooterLeft, subFooterRight, mobileMenu, mobileLinks, subFooterMobile, children, className, ...props }) => {
8
+ const ref = useRef(null);
9
+ useEffect(() => {
10
+ }, [cols, col1Size, col2Size, col3Size]);
11
+ const getColumnWidth = (col) => {
12
+ const map = { 1: col1Size, 2: col2Size, 3: col3Size };
13
+ return `ids-footer-1177__col-size-${map[col]}`;
14
+ };
15
+ const renderHeadline = () => {
16
+ if (srHeadline) {
17
+ return (jsxs(Fragment, { children: [jsxs("h1", { className: "ids-footer-1177__headline--sr", children: [srHeadline, jsx("span", { className: "ids-footer-1177__headline--sub", children: subHeadline })] }), jsxs("h1", { "aria-hidden": "true", className: "ids-footer-1177__headline", children: [headline, jsx("span", { className: "ids-footer-1177__headline--sub", children: subHeadline })] })] }));
18
+ }
19
+ return (jsxs("h1", { className: "ids-footer-1177__headline", children: [headline, jsx("span", { className: "ids-footer-1177__headline--sub", children: subHeadline })] }));
20
+ };
21
+ const renderCol = (column) => {
22
+ return column?.map((link, idx) => {
23
+ if (React__default.isValidElement(link)) {
24
+ return React__default.cloneElement(link, {
25
+ key: `footer-link-${idx}`,
26
+ colorPreset: 2,
27
+ block: true
28
+ });
29
+ }
30
+ return link;
31
+ });
32
+ };
33
+ const renderCols = () => {
34
+ if (cols === 1) {
35
+ return (jsx("div", { className: clsx("ids-footer-1177__link-col", "ids-footer-1177__link-col--1", getColumnWidth(1)), children: renderCol(col1) }));
36
+ }
37
+ else if (cols === 2) {
38
+ return (jsxs(Fragment, { children: [jsx("div", { className: clsx("ids-footer-1177__link-col", "ids-footer-1177__link-col--2", getColumnWidth(1)), children: renderCol(col1) }), jsx("div", { className: clsx("ids-footer-1177__link-col", "ids-footer-1177__link-col--2", getColumnWidth(2)), children: renderCol(col2) })] }));
39
+ }
40
+ return (jsxs(Fragment, { children: [jsx("div", { className: clsx("ids-footer-1177__link-col", getColumnWidth(1)), children: renderCol(col1) }), jsx("div", { className: clsx("ids-footer-1177__link-col", getColumnWidth(2)), children: renderCol(col2) }), jsx("div", { className: clsx("ids-footer-1177__link-col", getColumnWidth(3)), children: renderCol(col3) })] }));
41
+ };
42
+ const renderCookieLinks = (content) => {
43
+ const applyProps = (node, keyPrefix = "") => {
44
+ if (!node)
45
+ return null;
46
+ if (Array.isArray(node)) {
47
+ return node.map((child, idx) => applyProps(child, `${keyPrefix}-${idx}`));
48
+ }
49
+ if (React__default.isValidElement(node)) {
50
+ if (node.type === React__default.Fragment) {
51
+ return (jsx(React__default.Fragment, { children: applyProps(node.props.children, keyPrefix) }, keyPrefix));
52
+ }
53
+ return React__default.cloneElement(node, {
54
+ key: `footer-sub-footer-right-link-${keyPrefix}`,
55
+ colorPreset: 4,
56
+ small: true,
57
+ ...node.props
58
+ });
59
+ }
60
+ return node;
61
+ };
62
+ return applyProps(content, "root");
63
+ };
64
+ return (jsxs("footer", { className: clsx("ids-footer-1177", className), ref: ref, ...props, children: [jsx("div", { className: "ids-footer-1177__inner-wrapper", children: jsxs("div", { className: "ids-footer-1177__inner", children: [jsx("div", { className: "ids-footer-1177__headline-row", children: renderHeadline() }), jsxs("div", { className: "ids-footer-1177__content", children: [jsx("div", { className: "ids-footer-1177__text", children: children }), renderCols()] })] }) }), jsxs("div", { className: "ids-footer-1177__sub-footer", children: [jsx("div", { className: "ids-footer-1177__sub-footer-container", children: jsxs("div", { className: "ids-footer-1177__sub-footer-row", children: [jsx("div", { className: "ids-footer-1177__sub-footer-left", children: subFooterLeft }), jsx("div", { className: "ids-footer-1177__sub-footer-right", children: renderCookieLinks(subFooterRight) }), jsx("div", { className: "ids-footer-1177__mobile-menu", children: mobileMenu }), jsx("div", { className: "ids-footer-1177__mobile-links", children: renderCookieLinks(mobileLinks) })] }) }), jsx("div", { className: "ids-footer-1177__sub-footer-mobile", children: jsx("div", { className: "ids-footer-1177__sub-footer-mobile-text", children: subFooterMobile }) })] })] }));
65
+ };
11
66
 
12
67
  export { IDSFooter1177 };