@expofp/ui 3.21.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 (304) hide show
  1. package/README.md +30 -0
  2. package/dist/Alert/Alert.d.ts +20 -0
  3. package/dist/Alert/Alert.js +23 -0
  4. package/dist/Alert/index.d.ts +3 -0
  5. package/dist/Alert/index.js +1 -0
  6. package/dist/Autocomplete/Autocomplete.d.ts +21 -0
  7. package/dist/Autocomplete/Autocomplete.js +183 -0
  8. package/dist/Autocomplete/index.d.ts +3 -0
  9. package/dist/Autocomplete/index.js +1 -0
  10. package/dist/Badge/Badge.d.ts +14 -0
  11. package/dist/Badge/Badge.js +15 -0
  12. package/dist/Badge/index.d.ts +3 -0
  13. package/dist/Badge/index.js +1 -0
  14. package/dist/Button/Button.d.ts +30 -0
  15. package/dist/Button/Button.js +41 -0
  16. package/dist/Button/index.d.ts +3 -0
  17. package/dist/Button/index.js +1 -0
  18. package/dist/Checkbox/Checkbox.d.ts +19 -0
  19. package/dist/Checkbox/Checkbox.js +19 -0
  20. package/dist/Checkbox/index.d.ts +3 -0
  21. package/dist/Checkbox/index.js +1 -0
  22. package/dist/CheckboxButton/CheckboxButton.d.ts +12 -0
  23. package/dist/CheckboxButton/CheckboxButton.js +19 -0
  24. package/dist/CheckboxButton/index.d.ts +3 -0
  25. package/dist/CheckboxButton/index.js +1 -0
  26. package/dist/DownloadList/DownloadList.d.ts +15 -0
  27. package/dist/DownloadList/DownloadList.js +9 -0
  28. package/dist/DownloadList/index.d.ts +3 -0
  29. package/dist/DownloadList/index.js +2 -0
  30. package/dist/Draggable/Draggable.d.ts +9 -0
  31. package/dist/Draggable/Draggable.js +92 -0
  32. package/dist/Draggable/index.d.ts +3 -0
  33. package/dist/Draggable/index.js +2 -0
  34. package/dist/EntityItem/EntityItem.d.ts +46 -0
  35. package/dist/EntityItem/EntityItem.js +29 -0
  36. package/dist/EntityItem/index.d.ts +3 -0
  37. package/dist/EntityItem/index.js +1 -0
  38. package/dist/EventBadge/EventBadge.d.ts +13 -0
  39. package/dist/EventBadge/EventBadge.js +10 -0
  40. package/dist/EventBadge/index.d.ts +3 -0
  41. package/dist/EventBadge/index.js +1 -0
  42. package/dist/HeatmapLegend/HeatmapLegend.d.ts +15 -0
  43. package/dist/HeatmapLegend/HeatmapLegend.js +11 -0
  44. package/dist/HeatmapLegend/index.d.ts +3 -0
  45. package/dist/HeatmapLegend/index.js +2 -0
  46. package/dist/HighlightText/HighlightText.d.ts +7 -0
  47. package/dist/HighlightText/HighlightText.js +14 -0
  48. package/dist/HighlightText/index.d.ts +2 -0
  49. package/dist/HighlightText/index.js +1 -0
  50. package/dist/LevelBadge/LevelBadge.d.ts +9 -0
  51. package/dist/LevelBadge/LevelBadge.js +10 -0
  52. package/dist/LevelBadge/index.d.ts +3 -0
  53. package/dist/LevelBadge/index.js +2 -0
  54. package/dist/LevelSelector/LevelSelector.d.ts +19 -0
  55. package/dist/LevelSelector/LevelSelector.js +91 -0
  56. package/dist/LevelSelector/index.d.ts +3 -0
  57. package/dist/LevelSelector/index.js +2 -0
  58. package/dist/MapControls/MapControls.d.ts +33 -0
  59. package/dist/MapControls/MapControls.js +38 -0
  60. package/dist/MapControls/index.d.ts +3 -0
  61. package/dist/MapControls/index.js +2 -0
  62. package/dist/MobileToggleButton/MobileToggleButton.d.ts +12 -0
  63. package/dist/MobileToggleButton/MobileToggleButton.js +8 -0
  64. package/dist/MobileToggleButton/index.d.ts +3 -0
  65. package/dist/MobileToggleButton/index.js +1 -0
  66. package/dist/Modal/Modal.d.ts +34 -0
  67. package/dist/Modal/Modal.js +98 -0
  68. package/dist/Modal/index.d.ts +3 -0
  69. package/dist/Modal/index.js +1 -0
  70. package/dist/MultiSelectGroups/MultiSelectGroups.d.ts +37 -0
  71. package/dist/MultiSelectGroups/MultiSelectGroups.js +80 -0
  72. package/dist/MultiSelectGroups/index.d.ts +3 -0
  73. package/dist/MultiSelectGroups/index.js +1 -0
  74. package/dist/OverlayGrip/OverlayGrip.d.ts +11 -0
  75. package/dist/OverlayGrip/OverlayGrip.js +8 -0
  76. package/dist/OverlayGrip/index.d.ts +3 -0
  77. package/dist/OverlayGrip/index.js +2 -0
  78. package/dist/PermissionNotice/PermissionNotice.d.ts +16 -0
  79. package/dist/PermissionNotice/PermissionNotice.js +11 -0
  80. package/dist/PermissionNotice/index.d.ts +3 -0
  81. package/dist/PermissionNotice/index.js +2 -0
  82. package/dist/Radio/Radio.d.ts +15 -0
  83. package/dist/Radio/Radio.js +13 -0
  84. package/dist/Radio/index.d.ts +3 -0
  85. package/dist/Radio/index.js +1 -0
  86. package/dist/RebookingNotes/RebookingNotes.d.ts +11 -0
  87. package/dist/RebookingNotes/RebookingNotes.js +18 -0
  88. package/dist/RebookingNotes/index.d.ts +3 -0
  89. package/dist/RebookingNotes/index.js +1 -0
  90. package/dist/RebookingRadioGroup/RebookingRadioGroup.d.ts +17 -0
  91. package/dist/RebookingRadioGroup/RebookingRadioGroup.js +13 -0
  92. package/dist/RebookingRadioGroup/index.d.ts +3 -0
  93. package/dist/RebookingRadioGroup/index.js +1 -0
  94. package/dist/ScrollableRow/ScrollableRow.d.ts +21 -0
  95. package/dist/ScrollableRow/ScrollableRow.js +155 -0
  96. package/dist/ScrollableRow/index.d.ts +3 -0
  97. package/dist/ScrollableRow/index.js +2 -0
  98. package/dist/Share/Share.d.ts +22 -0
  99. package/dist/Share/Share.js +24 -0
  100. package/dist/Share/index.d.ts +3 -0
  101. package/dist/Share/index.js +1 -0
  102. package/dist/ShowMoreButton/ShowMoreButton.d.ts +11 -0
  103. package/dist/ShowMoreButton/ShowMoreButton.js +7 -0
  104. package/dist/ShowMoreButton/index.d.ts +3 -0
  105. package/dist/ShowMoreButton/index.js +1 -0
  106. package/dist/SidebarActions/SidebarActions.d.ts +26 -0
  107. package/dist/SidebarActions/SidebarActions.js +32 -0
  108. package/dist/SidebarActions/index.d.ts +3 -0
  109. package/dist/SidebarActions/index.js +2 -0
  110. package/dist/SimpleRow/SimpleRow.d.ts +15 -0
  111. package/dist/SimpleRow/SimpleRow.js +11 -0
  112. package/dist/SimpleRow/index.d.ts +3 -0
  113. package/dist/SimpleRow/index.js +2 -0
  114. package/dist/Spinner/Spinner.d.ts +9 -0
  115. package/dist/Spinner/Spinner.js +8 -0
  116. package/dist/Spinner/index.d.ts +3 -0
  117. package/dist/Spinner/index.js +1 -0
  118. package/dist/ToggleButton/ToggleButton.d.ts +17 -0
  119. package/dist/ToggleButton/ToggleButton.js +8 -0
  120. package/dist/ToggleButton/index.d.ts +3 -0
  121. package/dist/ToggleButton/index.js +1 -0
  122. package/dist/ToggleSwitch/ToggleSwitch.d.ts +12 -0
  123. package/dist/ToggleSwitch/ToggleSwitch.js +10 -0
  124. package/dist/ToggleSwitch/index.d.ts +3 -0
  125. package/dist/ToggleSwitch/index.js +1 -0
  126. package/dist/TouchHand/TouchHand.d.ts +5 -0
  127. package/dist/TouchHand/TouchHand.js +7 -0
  128. package/dist/TouchHand/index.d.ts +2 -0
  129. package/dist/TouchHand/index.js +1 -0
  130. package/dist/WayfindingFloorSelector/WayfindingFloorSelector.d.ts +24 -0
  131. package/dist/WayfindingFloorSelector/WayfindingFloorSelector.js +27 -0
  132. package/dist/WayfindingFloorSelector/index.d.ts +3 -0
  133. package/dist/WayfindingFloorSelector/index.js +1 -0
  134. package/dist/components/Alert/Alert.d.ts +20 -0
  135. package/dist/components/Alert/Alert.js +23 -0
  136. package/dist/components/Alert/index.d.ts +3 -0
  137. package/dist/components/Alert/index.js +1 -0
  138. package/dist/components/Autocomplete/Autocomplete.d.ts +21 -0
  139. package/dist/components/Autocomplete/Autocomplete.js +183 -0
  140. package/dist/components/Autocomplete/index.d.ts +3 -0
  141. package/dist/components/Autocomplete/index.js +1 -0
  142. package/dist/components/Badge/Badge.d.ts +14 -0
  143. package/dist/components/Badge/Badge.js +15 -0
  144. package/dist/components/Badge/index.d.ts +3 -0
  145. package/dist/components/Badge/index.js +1 -0
  146. package/dist/components/Button/Button.d.ts +30 -0
  147. package/dist/components/Button/Button.js +41 -0
  148. package/dist/components/Button/index.d.ts +3 -0
  149. package/dist/components/Button/index.js +1 -0
  150. package/dist/components/Checkbox/Checkbox.d.ts +19 -0
  151. package/dist/components/Checkbox/Checkbox.js +19 -0
  152. package/dist/components/Checkbox/index.d.ts +3 -0
  153. package/dist/components/Checkbox/index.js +1 -0
  154. package/dist/components/CheckboxButton/CheckboxButton.d.ts +12 -0
  155. package/dist/components/CheckboxButton/CheckboxButton.js +19 -0
  156. package/dist/components/CheckboxButton/index.d.ts +3 -0
  157. package/dist/components/CheckboxButton/index.js +1 -0
  158. package/dist/components/DownloadList/DownloadList.d.ts +15 -0
  159. package/dist/components/DownloadList/DownloadList.js +9 -0
  160. package/dist/components/DownloadList/index.d.ts +3 -0
  161. package/dist/components/DownloadList/index.js +2 -0
  162. package/dist/components/Draggable/Draggable.d.ts +9 -0
  163. package/dist/components/Draggable/Draggable.js +92 -0
  164. package/dist/components/Draggable/index.d.ts +3 -0
  165. package/dist/components/Draggable/index.js +2 -0
  166. package/dist/components/EntityItem/EntityItem.d.ts +46 -0
  167. package/dist/components/EntityItem/EntityItem.js +29 -0
  168. package/dist/components/EntityItem/index.d.ts +3 -0
  169. package/dist/components/EntityItem/index.js +1 -0
  170. package/dist/components/EventBadge/EventBadge.d.ts +13 -0
  171. package/dist/components/EventBadge/EventBadge.js +10 -0
  172. package/dist/components/EventBadge/index.d.ts +3 -0
  173. package/dist/components/EventBadge/index.js +1 -0
  174. package/dist/components/Gallery/Gallery.d.ts +25 -0
  175. package/dist/components/Gallery/Gallery.js +25 -0
  176. package/dist/components/Gallery/GalleryBadges/GalleryBadges.d.ts +8 -0
  177. package/dist/components/Gallery/GalleryBadges/GalleryBadges.js +5 -0
  178. package/dist/components/Gallery/GalleryControls/GalleryControls.d.ts +11 -0
  179. package/dist/components/Gallery/GalleryControls/GalleryControls.js +5 -0
  180. package/dist/components/Gallery/GalleryImg/GalleryImg.d.ts +13 -0
  181. package/dist/components/Gallery/GalleryImg/GalleryImg.js +37 -0
  182. package/dist/components/Gallery/GalleryItem/GalleryItem.d.ts +14 -0
  183. package/dist/components/Gallery/GalleryItem/GalleryItem.js +6 -0
  184. package/dist/components/Gallery/GalleryModal/GalleryModal.d.ts +18 -0
  185. package/dist/components/Gallery/GalleryModal/GalleryModal.js +88 -0
  186. package/dist/components/Gallery/GalleryPreLoader.d.ts +7 -0
  187. package/dist/components/Gallery/GalleryPreLoader.js +29 -0
  188. package/dist/components/Gallery/TransformImg/TransformImg.d.ts +10 -0
  189. package/dist/components/Gallery/TransformImg/TransformImg.js +15 -0
  190. package/dist/components/Gallery/index.d.ts +3 -0
  191. package/dist/components/Gallery/index.js +1 -0
  192. package/dist/components/HeatmapLegend/HeatmapLegend.d.ts +15 -0
  193. package/dist/components/HeatmapLegend/HeatmapLegend.js +11 -0
  194. package/dist/components/HeatmapLegend/index.d.ts +3 -0
  195. package/dist/components/HeatmapLegend/index.js +2 -0
  196. package/dist/components/HighlightText/HighlightText.d.ts +7 -0
  197. package/dist/components/HighlightText/HighlightText.js +14 -0
  198. package/dist/components/HighlightText/index.d.ts +2 -0
  199. package/dist/components/HighlightText/index.js +1 -0
  200. package/dist/components/LevelBadge/LevelBadge.d.ts +9 -0
  201. package/dist/components/LevelBadge/LevelBadge.js +10 -0
  202. package/dist/components/LevelBadge/index.d.ts +3 -0
  203. package/dist/components/LevelBadge/index.js +2 -0
  204. package/dist/components/LevelSelector/LevelSelector.d.ts +19 -0
  205. package/dist/components/LevelSelector/LevelSelector.js +91 -0
  206. package/dist/components/LevelSelector/index.d.ts +3 -0
  207. package/dist/components/LevelSelector/index.js +2 -0
  208. package/dist/components/MapControls/MapControls.d.ts +33 -0
  209. package/dist/components/MapControls/MapControls.js +38 -0
  210. package/dist/components/MapControls/index.d.ts +3 -0
  211. package/dist/components/MapControls/index.js +2 -0
  212. package/dist/components/MobileToggleButton/MobileToggleButton.d.ts +12 -0
  213. package/dist/components/MobileToggleButton/MobileToggleButton.js +8 -0
  214. package/dist/components/MobileToggleButton/index.d.ts +3 -0
  215. package/dist/components/MobileToggleButton/index.js +1 -0
  216. package/dist/components/Modal/Modal.d.ts +34 -0
  217. package/dist/components/Modal/Modal.js +98 -0
  218. package/dist/components/Modal/index.d.ts +3 -0
  219. package/dist/components/Modal/index.js +1 -0
  220. package/dist/components/MultiSelectGroups/MultiSelectGroups.d.ts +37 -0
  221. package/dist/components/MultiSelectGroups/MultiSelectGroups.js +80 -0
  222. package/dist/components/MultiSelectGroups/index.d.ts +3 -0
  223. package/dist/components/MultiSelectGroups/index.js +1 -0
  224. package/dist/components/Overlay/Overlay.d.ts +29 -0
  225. package/dist/components/Overlay/Overlay.js +251 -0
  226. package/dist/components/Overlay/OverlayScrollContext.d.ts +7 -0
  227. package/dist/components/Overlay/OverlayScrollContext.js +7 -0
  228. package/dist/components/Overlay/index.d.ts +4 -0
  229. package/dist/components/Overlay/index.js +2 -0
  230. package/dist/components/OverlayGrip/OverlayGrip.d.ts +11 -0
  231. package/dist/components/OverlayGrip/OverlayGrip.js +8 -0
  232. package/dist/components/OverlayGrip/index.d.ts +3 -0
  233. package/dist/components/OverlayGrip/index.js +2 -0
  234. package/dist/components/PermissionNotice/PermissionNotice.d.ts +16 -0
  235. package/dist/components/PermissionNotice/PermissionNotice.js +11 -0
  236. package/dist/components/PermissionNotice/index.d.ts +3 -0
  237. package/dist/components/PermissionNotice/index.js +2 -0
  238. package/dist/components/Radio/Radio.d.ts +15 -0
  239. package/dist/components/Radio/Radio.js +13 -0
  240. package/dist/components/Radio/index.d.ts +3 -0
  241. package/dist/components/Radio/index.js +1 -0
  242. package/dist/components/RebookingNotes/RebookingNotes.d.ts +11 -0
  243. package/dist/components/RebookingNotes/RebookingNotes.js +18 -0
  244. package/dist/components/RebookingNotes/index.d.ts +3 -0
  245. package/dist/components/RebookingNotes/index.js +1 -0
  246. package/dist/components/RebookingRadioGroup/RebookingRadioGroup.d.ts +17 -0
  247. package/dist/components/RebookingRadioGroup/RebookingRadioGroup.js +13 -0
  248. package/dist/components/RebookingRadioGroup/index.d.ts +3 -0
  249. package/dist/components/RebookingRadioGroup/index.js +1 -0
  250. package/dist/components/ScrollableRow/ScrollableRow.d.ts +21 -0
  251. package/dist/components/ScrollableRow/ScrollableRow.js +155 -0
  252. package/dist/components/ScrollableRow/index.d.ts +3 -0
  253. package/dist/components/ScrollableRow/index.js +2 -0
  254. package/dist/components/Share/Share.d.ts +22 -0
  255. package/dist/components/Share/Share.js +24 -0
  256. package/dist/components/Share/index.d.ts +3 -0
  257. package/dist/components/Share/index.js +1 -0
  258. package/dist/components/ShowMoreButton/ShowMoreButton.d.ts +11 -0
  259. package/dist/components/ShowMoreButton/ShowMoreButton.js +7 -0
  260. package/dist/components/ShowMoreButton/index.d.ts +3 -0
  261. package/dist/components/ShowMoreButton/index.js +1 -0
  262. package/dist/components/SidebarActions/SidebarActions.d.ts +26 -0
  263. package/dist/components/SidebarActions/SidebarActions.js +32 -0
  264. package/dist/components/SidebarActions/index.d.ts +3 -0
  265. package/dist/components/SidebarActions/index.js +2 -0
  266. package/dist/components/SimpleRow/SimpleRow.d.ts +15 -0
  267. package/dist/components/SimpleRow/SimpleRow.js +11 -0
  268. package/dist/components/SimpleRow/index.d.ts +3 -0
  269. package/dist/components/SimpleRow/index.js +2 -0
  270. package/dist/components/Spinner/Spinner.d.ts +9 -0
  271. package/dist/components/Spinner/Spinner.js +8 -0
  272. package/dist/components/Spinner/index.d.ts +3 -0
  273. package/dist/components/Spinner/index.js +1 -0
  274. package/dist/components/ToggleButton/ToggleButton.d.ts +17 -0
  275. package/dist/components/ToggleButton/ToggleButton.js +8 -0
  276. package/dist/components/ToggleButton/index.d.ts +3 -0
  277. package/dist/components/ToggleButton/index.js +1 -0
  278. package/dist/components/ToggleSwitch/ToggleSwitch.d.ts +12 -0
  279. package/dist/components/ToggleSwitch/ToggleSwitch.js +10 -0
  280. package/dist/components/ToggleSwitch/index.d.ts +3 -0
  281. package/dist/components/ToggleSwitch/index.js +1 -0
  282. package/dist/components/TouchHand/TouchHand.d.ts +5 -0
  283. package/dist/components/TouchHand/TouchHand.js +7 -0
  284. package/dist/components/TouchHand/index.d.ts +2 -0
  285. package/dist/components/TouchHand/index.js +1 -0
  286. package/dist/components/WayfindingFloorSelector/WayfindingFloorSelector.d.ts +24 -0
  287. package/dist/components/WayfindingFloorSelector/WayfindingFloorSelector.js +27 -0
  288. package/dist/components/WayfindingFloorSelector/index.d.ts +3 -0
  289. package/dist/components/WayfindingFloorSelector/index.js +1 -0
  290. package/dist/index.d.ts +65 -0
  291. package/dist/index.js +69 -0
  292. package/dist/shared/debounce.d.ts +2 -0
  293. package/dist/shared/debounce.js +9 -0
  294. package/dist/shared/hooks/useDragGesture.d.ts +19 -0
  295. package/dist/shared/hooks/useDragGesture.js +45 -0
  296. package/dist/shared/hooks/useOnClickOutside.d.ts +14 -0
  297. package/dist/shared/hooks/useOnClickOutside.js +43 -0
  298. package/dist/shared/hooks/useOnEscape.d.ts +14 -0
  299. package/dist/shared/hooks/useOnEscape.js +31 -0
  300. package/dist/shared/hooks/useWindowSize.d.ts +5 -0
  301. package/dist/shared/hooks/useWindowSize.js +40 -0
  302. package/dist/shared/interactive.d.ts +2 -0
  303. package/dist/shared/interactive.js +4 -0
  304. package/package.json +70 -0
@@ -0,0 +1,13 @@
1
+ import './EventBadge.scss';
2
+ export type EventBadgeStatus = 'live' | 'upcoming' | 'starting-soon' | 'past' | 'none';
3
+ export interface EventBadgeProps {
4
+ status: EventBadgeStatus;
5
+ statusLabel?: string;
6
+ showFullBadge?: boolean;
7
+ fullLabel: string;
8
+ isUrgent?: boolean;
9
+ className?: string;
10
+ }
11
+ declare const EventBadge: ({ status, statusLabel, showFullBadge, fullLabel, isUrgent, className, }: EventBadgeProps) => import("react").JSX.Element | null;
12
+ export default EventBadge;
13
+ //# sourceMappingURL=EventBadge.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './EventBadge.scss';
3
+ import classNames from 'classnames';
4
+ const EventBadge = ({ status, statusLabel, showFullBadge = false, fullLabel, isUrgent = false, className = '', }) => {
5
+ const mainBadge = status !== 'none' ? (_jsx("div", { className: classNames('efp-event-badge', `efp-event-badge--${status}`, { 'is-urgent': isUrgent }, className), children: statusLabel })) : null;
6
+ if (!mainBadge && !showFullBadge)
7
+ return null;
8
+ return (_jsxs(_Fragment, { children: [mainBadge, showFullBadge && (_jsx("div", { className: classNames('efp-event-badge', 'efp-event-badge--full', className), children: fullLabel }))] }));
9
+ };
10
+ export default EventBadge;
@@ -0,0 +1,3 @@
1
+ export type { EventBadgeProps, EventBadgeStatus } from './EventBadge';
2
+ export { default } from './EventBadge';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { default } from './EventBadge';
@@ -0,0 +1,25 @@
1
+ import './Gallery.scss';
2
+ import React from 'react';
3
+ export interface GalleryImage {
4
+ thumbnailUrl: string;
5
+ fullUrl: string;
6
+ }
7
+ export interface GalleryProps {
8
+ images: GalleryImage[];
9
+ leading?: boolean;
10
+ closeLabel: string;
11
+ zoomInLabel: string;
12
+ zoomOutLabel: string;
13
+ nextSlideLabel: string;
14
+ prevSlideLabel: string;
15
+ fullscreenLabel: string;
16
+ itemLabel: (index: number) => string;
17
+ renderTarget?: HTMLElement | null;
18
+ onImageLoadHeightUpdate?: () => void;
19
+ onOpenGallery?: () => void;
20
+ onCloseGallery?: () => void;
21
+ className?: string;
22
+ }
23
+ declare const Gallery: (props: GalleryProps) => React.JSX.Element;
24
+ export default Gallery;
25
+ //# sourceMappingURL=Gallery.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './Gallery.scss';
3
+ import classNames from 'classnames';
4
+ import React, { useState } from 'react';
5
+ import GalleryBadges from './GalleryBadges/GalleryBadges';
6
+ import GalleryItem from './GalleryItem/GalleryItem';
7
+ import GalleryModal from './GalleryModal/GalleryModal';
8
+ const Gallery = (props) => {
9
+ const { images, leading = false, closeLabel, zoomInLabel, zoomOutLabel, nextSlideLabel, prevSlideLabel, fullscreenLabel, itemLabel, renderTarget, onImageLoadHeightUpdate, onOpenGallery, onCloseGallery, className, } = props;
10
+ const [isModalOpen, setIsModalOpen] = useState(false);
11
+ const [currentSlideIndex, setCurrentSlideIndex] = useState(0);
12
+ const openModal = (initialSlideIndex) => {
13
+ setCurrentSlideIndex(initialSlideIndex);
14
+ setIsModalOpen(true);
15
+ onOpenGallery?.();
16
+ };
17
+ const closeModal = () => {
18
+ setIsModalOpen(false);
19
+ onCloseGallery?.();
20
+ };
21
+ return (_jsxs(React.Fragment, { children: [_jsxs("div", { className: classNames('efp-gallery', {
22
+ 'efp-gallery--leading': leading,
23
+ }, className), children: [_jsx("div", { className: "efp-gallery__wrapper", children: leading ? (_jsx(GalleryItem, { url: images[0].thumbnailUrl, index: 0, itemLabel: itemLabel, leading: leading, autoHeight: true, fillMode: "contain", onClick: () => openModal(0), onImageLoadHeightUpdate: onImageLoadHeightUpdate })) : (images.map((image, i) => (_jsx(GalleryItem, { url: image.thumbnailUrl, index: i, itemLabel: itemLabel, position: "top", fillMode: "cover", onClick: () => openModal(i), onImageLoadHeightUpdate: onImageLoadHeightUpdate }, image.thumbnailUrl + i)))) }), !leading && (_jsx(GalleryBadges, { fullscreenLabel: fullscreenLabel, onFullscreen: () => openModal(0), count: images.length }))] }), isModalOpen && (_jsx(GalleryModal, { className: className, images: images.map((image) => image.fullUrl), leading: leading, initialSlideIndex: currentSlideIndex, closeLabel: closeLabel, zoomInLabel: zoomInLabel, zoomOutLabel: zoomOutLabel, nextSlideLabel: nextSlideLabel, prevSlideLabel: prevSlideLabel, itemLabel: itemLabel, renderTarget: renderTarget, onClose: closeModal }))] }));
24
+ };
25
+ export default Gallery;
@@ -0,0 +1,8 @@
1
+ export interface GalleryBadgesProps {
2
+ count: number;
3
+ fullscreenLabel: string;
4
+ onFullscreen: () => void;
5
+ }
6
+ declare const GalleryBadges: ({ count, fullscreenLabel, onFullscreen }: GalleryBadgesProps) => import("react").JSX.Element;
7
+ export default GalleryBadges;
8
+ //# sourceMappingURL=GalleryBadges.d.ts.map
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ const GalleryBadges = ({ count, fullscreenLabel, onFullscreen }) => {
3
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "efp-gallery__badge efp-gallery__badge-count", children: [_jsx("i", { className: "icon-image", "aria-hidden": "true" }), _jsx("span", { children: count })] }), _jsx("button", { type: "button", className: "efp-gallery__badge efp-gallery__badge-fullscreen", "aria-label": fullscreenLabel, title: fullscreenLabel, onClick: onFullscreen, children: _jsx("i", { className: "icon-maximize", "aria-hidden": "true" }) })] }));
4
+ };
5
+ export default GalleryBadges;
@@ -0,0 +1,11 @@
1
+ export interface GalleryControlsProps {
2
+ closeLabel: string;
3
+ zoomInLabel: string;
4
+ zoomOutLabel: string;
5
+ zoomIn: () => void;
6
+ zoomOut: () => void;
7
+ onClose: () => void;
8
+ }
9
+ declare const GalleryControls: ({ closeLabel, zoomInLabel, zoomOutLabel, zoomIn, zoomOut, onClose, }: GalleryControlsProps) => import("react").JSX.Element;
10
+ export default GalleryControls;
11
+ //# sourceMappingURL=GalleryControls.d.ts.map
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const GalleryControls = ({ closeLabel, zoomInLabel, zoomOutLabel, zoomIn, zoomOut, onClose, }) => {
3
+ return (_jsxs("div", { className: "efp-gallery-slider__controls", children: [_jsx("button", { type: "button", className: "efp-gallery-slider__btn efp-gallery-slider__btn--close", title: closeLabel, "aria-label": closeLabel, onClick: onClose, children: _jsx("i", { className: "icon-close", "aria-hidden": "true" }) }), _jsx("button", { type: "button", className: "efp-gallery-slider__btn efp-gallery-slider__btn--zoom-in", title: zoomInLabel, "aria-label": zoomInLabel, onClick: () => zoomIn(), children: _jsx("i", { className: "icon-zoom-in", "aria-hidden": "true" }) }), _jsx("button", { type: "button", className: "efp-gallery-slider__btn efp-gallery-slider__btn--zoom-out", title: zoomOutLabel, "aria-label": zoomOutLabel, onClick: () => zoomOut(), children: _jsx("i", { className: "icon-zoom-out", "aria-hidden": "true" }) })] }));
4
+ };
5
+ export default GalleryControls;
@@ -0,0 +1,13 @@
1
+ type FillMode = 'cover' | 'contain';
2
+ export interface GalleryImgProps {
3
+ url: string;
4
+ fillMode?: FillMode;
5
+ leading?: boolean;
6
+ autoHeight?: boolean;
7
+ fullscreen?: boolean;
8
+ position?: 'center' | 'top';
9
+ onImageLoadHeightUpdate?: () => void;
10
+ }
11
+ declare const GalleryImg: ({ url, autoHeight, position, fullscreen, leading, fillMode, onImageLoadHeightUpdate, }: GalleryImgProps) => import("react").JSX.Element;
12
+ export default GalleryImg;
13
+ //# sourceMappingURL=GalleryImg.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef } from 'react';
3
+ import GalleryPreLoader from '../GalleryPreLoader';
4
+ const GalleryImg = ({ url, autoHeight = false, position = 'center', fullscreen = false, leading = false, fillMode = 'contain', onImageLoadHeightUpdate, }) => {
5
+ const imgRef = useRef(null);
6
+ const containerRef = useRef(null);
7
+ const loadImage = useCallback(async (imageUrl) => {
8
+ if (!autoHeight || !containerRef.current)
9
+ return;
10
+ const container = containerRef.current;
11
+ try {
12
+ const loadedImage = await GalleryPreLoader.load(imageUrl);
13
+ if (!loadedImage)
14
+ return;
15
+ container.style.height =
16
+ (loadedImage.height * container.clientWidth) / loadedImage.width + 'px';
17
+ onImageLoadHeightUpdate?.();
18
+ }
19
+ catch {
20
+ // image failed to load — keep default height
21
+ }
22
+ }, [autoHeight, onImageLoadHeightUpdate]);
23
+ useEffect(() => {
24
+ if (!imgRef.current || !containerRef.current || !leading)
25
+ return;
26
+ void loadImage(url);
27
+ }, [url, leading, loadImage]);
28
+ const style = {
29
+ backgroundImage: `url("${url}")`,
30
+ backgroundSize: fillMode,
31
+ backgroundRepeat: 'no-repeat',
32
+ transition: leading ? 'all 0.5s ease 0s' : 'none',
33
+ backgroundPosition: position,
34
+ };
35
+ return (_jsx("div", { ref: containerRef, style: { width: '100%', height: leading && !fullscreen ? '250px' : '100%' }, children: _jsx("div", { ref: imgRef, className: "efp-gallery__img", style: style }) }));
36
+ };
37
+ export default GalleryImg;
@@ -0,0 +1,14 @@
1
+ export interface GalleryItemProps {
2
+ url: string;
3
+ index: number;
4
+ itemLabel: (index: number) => string;
5
+ leading?: boolean;
6
+ autoHeight?: boolean;
7
+ fillMode?: 'cover' | 'contain';
8
+ position?: 'center' | 'top';
9
+ onClick: () => void;
10
+ onImageLoadHeightUpdate?: () => void;
11
+ }
12
+ declare const GalleryItem: ({ url, index, itemLabel, position, leading, autoHeight, fillMode, onClick, onImageLoadHeightUpdate, }: GalleryItemProps) => import("react").JSX.Element;
13
+ export default GalleryItem;
14
+ //# sourceMappingURL=GalleryItem.d.ts.map
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import GalleryImg from '../GalleryImg/GalleryImg';
3
+ const GalleryItem = ({ url, index, itemLabel, position = 'center', leading = false, autoHeight = false, fillMode, onClick, onImageLoadHeightUpdate, }) => {
4
+ return (_jsx("button", { type: "button", className: "efp-gallery__item", "aria-label": itemLabel(index), onClick: onClick, children: _jsx(GalleryImg, { position: position, fillMode: fillMode, url: url, leading: leading, autoHeight: autoHeight, onImageLoadHeightUpdate: onImageLoadHeightUpdate }) }));
5
+ };
6
+ export default GalleryItem;
@@ -0,0 +1,18 @@
1
+ import './GalleryModal.scss';
2
+ export interface GalleryModalProps {
3
+ images: string[];
4
+ leading: boolean;
5
+ initialSlideIndex: number;
6
+ closeLabel: string;
7
+ zoomInLabel: string;
8
+ zoomOutLabel: string;
9
+ nextSlideLabel: string;
10
+ prevSlideLabel: string;
11
+ itemLabel: (index: number) => string;
12
+ renderTarget?: HTMLElement | null;
13
+ onClose: () => void;
14
+ className?: string;
15
+ }
16
+ declare const GalleryModal: (props: GalleryModalProps) => import("react").ReactPortal | null;
17
+ export default GalleryModal;
18
+ //# sourceMappingURL=GalleryModal.d.ts.map
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './GalleryModal.scss';
3
+ import classNames from 'classnames';
4
+ import { useEffect, useRef, useState } from 'react';
5
+ import { createPortal } from 'react-dom';
6
+ import { TransformWrapper } from 'react-zoom-pan-pinch-sr';
7
+ import { Navigation } from 'swiper';
8
+ import { Swiper as SwiperComponent, SwiperSlide } from 'swiper/react';
9
+ import useOnEscape from '../../../shared/hooks/useOnEscape';
10
+ import GalleryControls from '../GalleryControls/GalleryControls';
11
+ import TransformImg from '../TransformImg/TransformImg';
12
+ const isElementVisible = (el) => el.getClientRects().length > 0 && getComputedStyle(el).visibility !== 'hidden';
13
+ const GalleryModal = (props) => {
14
+ const { images, leading, initialSlideIndex, closeLabel, zoomInLabel, zoomOutLabel, nextSlideLabel, prevSlideLabel, itemLabel, renderTarget, onClose, className, } = props;
15
+ const [currentSlideIndex, setCurrentSlideIndex] = useState(initialSlideIndex);
16
+ const [zoomUtils, setZoomUtils] = useState([]);
17
+ const swiperRef = useRef(null);
18
+ const prevRef = useRef(null);
19
+ const nextRef = useRef(null);
20
+ const modalRef = useRef(null);
21
+ useOnEscape(onClose);
22
+ // Scroll lock + focus trap/restore. Runs once for the modal's whole mounted
23
+ // lifetime — the parent only mounts this component while the modal is open.
24
+ useEffect(() => {
25
+ const previousFocus = document.activeElement;
26
+ const previousBodyOverflow = document.body.style.overflow;
27
+ document.body.style.overflow = 'hidden';
28
+ let inner = 0;
29
+ const outer = requestAnimationFrame(() => {
30
+ inner = requestAnimationFrame(() => modalRef.current?.focus());
31
+ });
32
+ const handleKeyDown = (e) => {
33
+ if (e.key !== 'Tab')
34
+ return;
35
+ const container = modalRef.current;
36
+ if (!container)
37
+ return;
38
+ const focusable = Array.from(container.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter(isElementVisible);
39
+ if (focusable.length === 0) {
40
+ e.preventDefault();
41
+ return;
42
+ }
43
+ const first = focusable[0];
44
+ const last = focusable[focusable.length - 1];
45
+ const active = document.activeElement;
46
+ if (e.shiftKey) {
47
+ if (active === first || active === container) {
48
+ e.preventDefault();
49
+ last.focus();
50
+ }
51
+ }
52
+ else if (active === last) {
53
+ e.preventDefault();
54
+ first.focus();
55
+ }
56
+ };
57
+ document.addEventListener('keydown', handleKeyDown);
58
+ return () => {
59
+ cancelAnimationFrame(outer);
60
+ cancelAnimationFrame(inner);
61
+ document.removeEventListener('keydown', handleKeyDown);
62
+ document.body.style.overflow = previousBodyOverflow;
63
+ previousFocus?.focus();
64
+ };
65
+ }, []);
66
+ const mainSliderOptions = {
67
+ initialSlide: initialSlideIndex,
68
+ draggable: false,
69
+ modules: [Navigation],
70
+ spaceBetween: 50,
71
+ slidesPerView: 1,
72
+ navigation: {
73
+ prevEl: prevRef.current,
74
+ nextEl: nextRef.current,
75
+ },
76
+ grabCursor: true,
77
+ };
78
+ if (!renderTarget)
79
+ return null;
80
+ const modalContent = (_jsx("div", { className: classNames('efp-gallery-modal', className), role: "dialog", "aria-modal": "true", "aria-label": itemLabel(currentSlideIndex), ref: modalRef, tabIndex: -1, children: _jsxs(SwiperComponent, { onSwiper: (swiper) => (swiperRef.current = swiper), className: "efp-gallery-slider", onSlideChange: (swiper) => {
81
+ setCurrentSlideIndex(swiper.activeIndex);
82
+ zoomUtils[swiper.previousIndex]?.resetTransform();
83
+ }, ...mainSliderOptions, children: [zoomUtils[currentSlideIndex] ? (_jsx(GalleryControls, { closeLabel: closeLabel, zoomInLabel: zoomInLabel, zoomOutLabel: zoomOutLabel, onClose: onClose, zoomIn: zoomUtils[currentSlideIndex].zoomIn, zoomOut: zoomUtils[currentSlideIndex].zoomOut })) : null, images.length > 1 && (_jsx("button", { type: "button", ref: nextRef, title: nextSlideLabel, "aria-label": nextSlideLabel, className: "efp-gallery-slider__btn efp-gallery-slider__btn--next", children: _jsx("i", { className: "icon-chevron-right", "aria-hidden": "true" }) })), images.length > 1 && (_jsx("button", { type: "button", ref: prevRef, title: prevSlideLabel, "aria-label": prevSlideLabel, className: "efp-gallery-slider__btn efp-gallery-slider__btn--prev", children: _jsx("i", { className: "icon-chevron-left", "aria-hidden": "true" }) })), images.map((url, i) => (_jsx(SwiperSlide, { children: _jsx(TransformWrapper, { initialScale: 1, alignmentAnimation: { sizeX: 0, sizeY: 0 }, onInit: (controls) => {
84
+ setZoomUtils((state) => [...state, controls]);
85
+ }, children: _jsx(TransformImg, { leading: leading, swiperRef: swiperRef, url: url }) }) }, url + i)))] }) }));
86
+ return createPortal(modalContent, renderTarget);
87
+ };
88
+ export default GalleryModal;
@@ -0,0 +1,7 @@
1
+ declare class GalleryPreLoader {
2
+ private cache;
3
+ load: (url: string) => Promise<HTMLImageElement | null>;
4
+ }
5
+ declare const _default: GalleryPreLoader;
6
+ export default _default;
7
+ //# sourceMappingURL=GalleryPreLoader.d.ts.map
@@ -0,0 +1,29 @@
1
+ class GalleryPreLoader {
2
+ cache = [];
3
+ load = (url) => {
4
+ return new Promise((resolve, reject) => {
5
+ if (!url) {
6
+ resolve(null);
7
+ return;
8
+ }
9
+ const cached = this.cache.find((i) => i.src === url);
10
+ if (cached) {
11
+ resolve(cached);
12
+ return;
13
+ }
14
+ const image = new Image();
15
+ image.crossOrigin = 'anonymous';
16
+ image.src = url;
17
+ image.onload = () => {
18
+ if (this.cache.length > 10)
19
+ this.cache.shift();
20
+ this.cache.push(image);
21
+ resolve(image);
22
+ };
23
+ image.onerror = () => {
24
+ reject(new Error(`Failed to load image: ${url}`));
25
+ };
26
+ });
27
+ };
28
+ }
29
+ export default new GalleryPreLoader();
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { type Swiper as SwiperInstance } from 'swiper';
3
+ export interface TransformImgProps {
4
+ swiperRef: React.RefObject<SwiperInstance | null>;
5
+ url: string;
6
+ leading: boolean;
7
+ }
8
+ declare const TransformImg: ({ swiperRef, leading, url }: TransformImgProps) => React.JSX.Element;
9
+ export default TransformImg;
10
+ //# sourceMappingURL=TransformImg.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { TransformComponent, useTransformEffect } from 'react-zoom-pan-pinch-sr';
3
+ import GalleryImg from '../GalleryImg/GalleryImg';
4
+ const TransformImg = ({ swiperRef, leading, url }) => {
5
+ useTransformEffect(({ state, instance }) => {
6
+ if (!swiperRef.current)
7
+ return;
8
+ swiperRef.current.allowTouchMove = state.scale === 1;
9
+ if (state.scale === 1 && state.positionX !== 0 && state.positionY !== 0) {
10
+ instance.setCenter();
11
+ }
12
+ });
13
+ return (_jsx(TransformComponent, { wrapperClass: "efp-gallery-slider__zoom", contentClass: "efp-gallery-slider__zoom-content", children: _jsx(GalleryImg, { fullscreen: true, leading: leading, url: url }) }));
14
+ };
15
+ export default TransformImg;
@@ -0,0 +1,3 @@
1
+ export type { GalleryImage, GalleryProps } from './Gallery';
2
+ export { default } from './Gallery';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { default } from './Gallery';
@@ -0,0 +1,15 @@
1
+ import './HeatmapLegend.scss';
2
+ import React from 'react';
3
+ export interface HeatmapLegendTick {
4
+ value: number;
5
+ color: string;
6
+ }
7
+ export interface HeatmapLegendProps {
8
+ ticks: HeatmapLegendTick[];
9
+ ariaLabel: string;
10
+ className?: string;
11
+ style?: React.CSSProperties;
12
+ }
13
+ declare const HeatmapLegend: ({ ticks, ariaLabel, className, style }: HeatmapLegendProps) => React.JSX.Element | null;
14
+ export default HeatmapLegend;
15
+ //# sourceMappingURL=HeatmapLegend.d.ts.map
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './HeatmapLegend.scss';
3
+ import classNames from 'classnames';
4
+ const HeatmapLegend = ({ ticks, ariaLabel, className, style }) => {
5
+ if (ticks.length === 0)
6
+ return null;
7
+ const colors = ticks.map((tick) => tick.color);
8
+ const background = colors.length === 1 ? colors[0] : `linear-gradient(to right, ${colors.join(', ')})`;
9
+ return (_jsxs("div", { className: classNames('efp-heatmap-legend', className), style: style, role: "img", "aria-label": ariaLabel, children: [_jsx("div", { className: "efp-heatmap-legend__colors", style: { background }, "aria-hidden": "true" }), _jsx("div", { className: "efp-heatmap-legend__values", children: ticks.map(({ value }, index) => (_jsx("span", { "aria-hidden": "true", children: value }, index))) })] }));
10
+ };
11
+ export default HeatmapLegend;
@@ -0,0 +1,3 @@
1
+ export { default } from './HeatmapLegend';
2
+ export type { HeatmapLegendProps, HeatmapLegendTick } from './HeatmapLegend';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export { default } from './HeatmapLegend';
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ declare const HighlightText: ({ text, highlight }: {
3
+ text: string;
4
+ highlight?: string;
5
+ }) => React.JSX.Element;
6
+ export default HighlightText;
7
+ //# sourceMappingURL=HighlightText.d.ts.map
@@ -0,0 +1,14 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const HIGHLIGHT_COLOR = '#FFFF99';
3
+ const HighlightText = ({ text, highlight }) => {
4
+ if (!highlight || !text) {
5
+ return _jsx(_Fragment, { children: text });
6
+ }
7
+ const startIndex = text.toLowerCase().indexOf(highlight.toLowerCase());
8
+ if (startIndex === -1) {
9
+ return _jsx(_Fragment, { children: text });
10
+ }
11
+ const endIndex = startIndex + highlight.length;
12
+ return (_jsxs(_Fragment, { children: [text.slice(0, startIndex), _jsx("mark", { style: { background: `linear-gradient(to top, ${HIGHLIGHT_COLOR}, transparent)` }, children: text.slice(startIndex, endIndex) }), text.slice(endIndex)] }));
13
+ };
14
+ export default HighlightText;
@@ -0,0 +1,2 @@
1
+ export { default } from './HighlightText';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { default } from './HighlightText';
@@ -0,0 +1,9 @@
1
+ import './LevelBadge.scss';
2
+ import React from 'react';
3
+ export interface LevelBadgeProps {
4
+ level: string;
5
+ levelLabel: string;
6
+ }
7
+ declare const LevelBadge: ({ level, levelLabel }: LevelBadgeProps) => React.JSX.Element | null;
8
+ export default LevelBadge;
9
+ //# sourceMappingURL=LevelBadge.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @ts-nocheck
3
+ import './LevelBadge.scss';
4
+ const isNumeric = (input) => /^\d+$/.test(input);
5
+ const LevelBadge = ({ level, levelLabel }) => {
6
+ if (!level)
7
+ return null;
8
+ return (_jsx("div", { className: "efp-level-badge", children: _jsx("span", { children: isNumeric(level) ? `${levelLabel} ${level}` : level }) }));
9
+ };
10
+ export default LevelBadge;
@@ -0,0 +1,3 @@
1
+ export { default } from './LevelBadge';
2
+ export type { LevelBadgeProps } from './LevelBadge';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export { default } from './LevelBadge';
@@ -0,0 +1,19 @@
1
+ import './LevelSelector.scss';
2
+ export interface LevelSelectorFloor {
3
+ /** Stable identifier for the floor (used as React key and passed to `onSelect`). */
4
+ id: string;
5
+ /** Display name shown to the user (already resolved to short/full by the caller). */
6
+ label: string;
7
+ active: boolean;
8
+ disabled: boolean;
9
+ }
10
+ export interface LevelSelectorProps {
11
+ floors: LevelSelectorFloor[];
12
+ layout: 'compact-list' | 'dropdown';
13
+ onSelect: (id: string) => void;
14
+ floorSelectionLabel: string;
15
+ currentFloorLabel: string;
16
+ floorLabel: string;
17
+ }
18
+ export default function LevelSelector({ floors, layout, onSelect, floorSelectionLabel, currentFloorLabel, floorLabel, }: LevelSelectorProps): import("react").JSX.Element | null;
19
+ //# sourceMappingURL=LevelSelector.d.ts.map
@@ -0,0 +1,91 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './LevelSelector.scss';
3
+ import classNames from 'classnames';
4
+ import { useCallback, useLayoutEffect, useRef, useState } from 'react';
5
+ import useOnClickOutside from '../../shared/hooks/useOnClickOutside';
6
+ import useOnEscape from '../../shared/hooks/useOnEscape';
7
+ export default function LevelSelector({ floors, layout, onSelect, floorSelectionLabel, currentFloorLabel, floorLabel, }) {
8
+ const dropdownRef = useRef(null);
9
+ const triggerRef = useRef(null);
10
+ const itemRefs = useRef(new Map());
11
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
12
+ const [menuPosition, setMenuPosition] = useState('down');
13
+ const closeAndRefocus = useCallback(() => {
14
+ setIsDropdownOpen(false);
15
+ triggerRef.current?.focus();
16
+ }, []);
17
+ useOnClickOutside([dropdownRef, triggerRef], () => setIsDropdownOpen(false), isDropdownOpen);
18
+ useOnEscape(closeAndRefocus, isDropdownOpen);
19
+ useLayoutEffect(() => {
20
+ if (isDropdownOpen && triggerRef.current) {
21
+ const buttonRect = triggerRef.current.getBoundingClientRect();
22
+ const windowHeight = window.innerHeight;
23
+ const spaceBelow = windowHeight - buttonRect.bottom;
24
+ const minSpaceRequired = 200;
25
+ setMenuPosition(spaceBelow < minSpaceRequired ? 'up' : 'down');
26
+ }
27
+ }, [isDropdownOpen]);
28
+ const handleFloorSelect = useCallback((floor) => {
29
+ if (floor.disabled)
30
+ return;
31
+ onSelect(floor.id);
32
+ setIsDropdownOpen(false);
33
+ triggerRef.current?.focus();
34
+ }, [onSelect]);
35
+ const focusAdjacentFloor = useCallback((e, floor) => {
36
+ if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp')
37
+ return;
38
+ e.preventDefault();
39
+ const currentIndex = floors.findIndex((f) => f.id === floor.id);
40
+ const direction = e.key === 'ArrowDown' ? 1 : -1;
41
+ let nextIndex = currentIndex + direction;
42
+ while (nextIndex >= 0 && nextIndex < floors.length) {
43
+ if (!floors[nextIndex].disabled) {
44
+ itemRefs.current.get(floors[nextIndex].id)?.focus();
45
+ return;
46
+ }
47
+ nextIndex += direction;
48
+ }
49
+ }, [floors]);
50
+ const handleDropdownItemKeyDown = useCallback((e, floor) => {
51
+ if (e.key === 'Enter' || e.key === ' ') {
52
+ if (floor.disabled)
53
+ return;
54
+ e.preventDefault();
55
+ handleFloorSelect(floor);
56
+ return;
57
+ }
58
+ focusAdjacentFloor(e, floor);
59
+ }, [focusAdjacentFloor, handleFloorSelect]);
60
+ if (floors.length === 0)
61
+ return null;
62
+ const activeFloor = floors.find((floor) => floor.active);
63
+ if (layout === 'compact-list') {
64
+ // Roving tabindex: only the active floor (or the first enabled one as a
65
+ // fallback) is a tab stop; arrows move focus, Enter/Space select.
66
+ const tabbableFloor = activeFloor && !activeFloor.disabled ? activeFloor : floors.find((floor) => !floor.disabled);
67
+ return (_jsx("div", { className: classNames('efp-level-selector', 'efp-level-selector--compact-list'), role: "radiogroup", "aria-label": floorSelectionLabel, children: floors.map((floor) => (_jsx("button", { ref: (el) => {
68
+ if (el)
69
+ itemRefs.current.set(floor.id, el);
70
+ else
71
+ itemRefs.current.delete(floor.id);
72
+ }, type: "button", className: classNames('efp-level-selector__item', {
73
+ 'efp-level-selector__item--active': floor.active,
74
+ 'efp-level-selector__item--disabled': floor.disabled,
75
+ }), role: "radio", title: `${floor.active ? currentFloorLabel : floorLabel} ${floor.label}`, "aria-label": `${floor.active ? currentFloorLabel : floorLabel} ${floor.label}`, "aria-checked": floor.active, "aria-disabled": floor.disabled, tabIndex: floor.id === tabbableFloor?.id ? 0 : -1, onClick: () => handleFloorSelect(floor), onKeyDown: (e) => focusAdjacentFloor(e, floor), children: _jsx("span", { dir: "auto", children: floor.label }) }, floor.id))) }));
76
+ }
77
+ return (_jsxs("div", { className: classNames('efp-level-selector', 'efp-level-selector--dropdown'), children: [_jsxs("button", { ref: triggerRef, type: "button", className: classNames('efp-level-selector__trigger', {
78
+ 'efp-level-selector__trigger--open': isDropdownOpen,
79
+ }), onClick: () => setIsDropdownOpen(!isDropdownOpen), "aria-haspopup": "listbox", "aria-expanded": isDropdownOpen, "aria-label": `${currentFloorLabel}: ${activeFloor?.label ?? ''}`, children: [_jsxs("div", { className: "efp-level-selector__trigger-text", children: [_jsx("i", { className: "icon-layers", "aria-hidden": "true" }), _jsx("span", { dir: "auto", children: activeFloor?.label ?? '' })] }), _jsx("div", { className: "efp-level-selector__trigger-chevron", children: _jsx("i", { className: "icon-chevron-down", "aria-hidden": "true" }) })] }), isDropdownOpen && (_jsx("div", { ref: dropdownRef, className: classNames('efp-level-selector__dropdown', 'efp-level-selector__dropdown--full', {
80
+ 'efp-level-selector__dropdown--opens-up': menuPosition === 'up',
81
+ 'efp-level-selector__dropdown--opens-down': menuPosition === 'down',
82
+ }), role: "listbox", "aria-label": floorSelectionLabel, children: floors.map((floor) => (_jsxs("div", { ref: (el) => {
83
+ if (el)
84
+ itemRefs.current.set(floor.id, el);
85
+ else
86
+ itemRefs.current.delete(floor.id);
87
+ }, className: classNames('efp-level-selector__dropdown-item', {
88
+ 'efp-level-selector__dropdown-item--active': floor.active,
89
+ 'efp-level-selector__dropdown-item--disabled': floor.disabled,
90
+ }), role: "option", "aria-selected": floor.active, "aria-disabled": floor.disabled, tabIndex: floor.disabled ? -1 : 0, onClick: () => handleFloorSelect(floor), onKeyDown: (e) => handleDropdownItemKeyDown(e, floor), children: [_jsx("span", { className: "efp-level-selector__dropdown-item-icon", children: floor.active && _jsx("i", { className: "icon-checkmark-solid", "aria-hidden": "true" }) }), _jsx("span", { className: "efp-level-selector__dropdown-item-name", dir: "auto", children: floor.label })] }, floor.id))) }))] }));
91
+ }
@@ -0,0 +1,3 @@
1
+ export { default } from './LevelSelector';
2
+ export type { LevelSelectorProps, LevelSelectorFloor } from './LevelSelector';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export { default } from './LevelSelector';