@expofp/ui 0.0.0-experimental.2d6c681

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 (192) hide show
  1. package/README.md +30 -0
  2. package/dist/components/Alert/Alert.d.ts +20 -0
  3. package/dist/components/Alert/Alert.js +23 -0
  4. package/dist/components/Alert/index.d.ts +3 -0
  5. package/dist/components/Alert/index.js +1 -0
  6. package/dist/components/Autocomplete/Autocomplete.d.ts +28 -0
  7. package/dist/components/Autocomplete/Autocomplete.js +292 -0
  8. package/dist/components/Autocomplete/index.d.ts +3 -0
  9. package/dist/components/Autocomplete/index.js +1 -0
  10. package/dist/components/Badge/Badge.d.ts +14 -0
  11. package/dist/components/Badge/Badge.js +15 -0
  12. package/dist/components/Badge/index.d.ts +3 -0
  13. package/dist/components/Badge/index.js +1 -0
  14. package/dist/components/Button/Button.d.ts +30 -0
  15. package/dist/components/Button/Button.js +41 -0
  16. package/dist/components/Button/index.d.ts +3 -0
  17. package/dist/components/Button/index.js +1 -0
  18. package/dist/components/Checkbox/Checkbox.d.ts +19 -0
  19. package/dist/components/Checkbox/Checkbox.js +19 -0
  20. package/dist/components/Checkbox/index.d.ts +3 -0
  21. package/dist/components/Checkbox/index.js +1 -0
  22. package/dist/components/CheckboxButton/CheckboxButton.d.ts +12 -0
  23. package/dist/components/CheckboxButton/CheckboxButton.js +19 -0
  24. package/dist/components/CheckboxButton/index.d.ts +3 -0
  25. package/dist/components/CheckboxButton/index.js +1 -0
  26. package/dist/components/DownloadList/DownloadList.d.ts +15 -0
  27. package/dist/components/DownloadList/DownloadList.js +9 -0
  28. package/dist/components/DownloadList/index.d.ts +3 -0
  29. package/dist/components/DownloadList/index.js +2 -0
  30. package/dist/components/Draggable/Draggable.d.ts +9 -0
  31. package/dist/components/Draggable/Draggable.js +92 -0
  32. package/dist/components/Draggable/index.d.ts +3 -0
  33. package/dist/components/Draggable/index.js +2 -0
  34. package/dist/components/EntityItem/EntityItem.d.ts +46 -0
  35. package/dist/components/EntityItem/EntityItem.js +29 -0
  36. package/dist/components/EntityItem/index.d.ts +3 -0
  37. package/dist/components/EntityItem/index.js +1 -0
  38. package/dist/components/EventBadge/EventBadge.d.ts +13 -0
  39. package/dist/components/EventBadge/EventBadge.js +10 -0
  40. package/dist/components/EventBadge/index.d.ts +3 -0
  41. package/dist/components/EventBadge/index.js +1 -0
  42. package/dist/components/Gallery/Gallery.d.ts +24 -0
  43. package/dist/components/Gallery/Gallery.js +28 -0
  44. package/dist/components/Gallery/GalleryBadges/GalleryBadges.d.ts +8 -0
  45. package/dist/components/Gallery/GalleryBadges/GalleryBadges.js +5 -0
  46. package/dist/components/Gallery/GalleryControls/GalleryControls.d.ts +11 -0
  47. package/dist/components/Gallery/GalleryControls/GalleryControls.js +5 -0
  48. package/dist/components/Gallery/GalleryImg/GalleryImg.d.ts +13 -0
  49. package/dist/components/Gallery/GalleryImg/GalleryImg.js +37 -0
  50. package/dist/components/Gallery/GalleryItem/GalleryItem.d.ts +14 -0
  51. package/dist/components/Gallery/GalleryItem/GalleryItem.js +6 -0
  52. package/dist/components/Gallery/GalleryModal/GalleryModal.d.ts +20 -0
  53. package/dist/components/Gallery/GalleryModal/GalleryModal.js +90 -0
  54. package/dist/components/Gallery/GalleryPreLoader.d.ts +7 -0
  55. package/dist/components/Gallery/GalleryPreLoader.js +29 -0
  56. package/dist/components/Gallery/TransformImg/TransformImg.d.ts +10 -0
  57. package/dist/components/Gallery/TransformImg/TransformImg.js +15 -0
  58. package/dist/components/Gallery/index.d.ts +4 -0
  59. package/dist/components/Gallery/index.js +1 -0
  60. package/dist/components/Gallery/types.d.ts +6 -0
  61. package/dist/components/Gallery/types.js +1 -0
  62. package/dist/components/HeatmapLegend/HeatmapLegend.d.ts +15 -0
  63. package/dist/components/HeatmapLegend/HeatmapLegend.js +11 -0
  64. package/dist/components/HeatmapLegend/index.d.ts +3 -0
  65. package/dist/components/HeatmapLegend/index.js +2 -0
  66. package/dist/components/HighlightText/HighlightText.d.ts +7 -0
  67. package/dist/components/HighlightText/HighlightText.js +14 -0
  68. package/dist/components/HighlightText/index.d.ts +2 -0
  69. package/dist/components/HighlightText/index.js +1 -0
  70. package/dist/components/LevelBadge/LevelBadge.d.ts +9 -0
  71. package/dist/components/LevelBadge/LevelBadge.js +10 -0
  72. package/dist/components/LevelBadge/index.d.ts +3 -0
  73. package/dist/components/LevelBadge/index.js +2 -0
  74. package/dist/components/LevelSelector/LevelSelector.d.ts +18 -0
  75. package/dist/components/LevelSelector/LevelSelector.js +91 -0
  76. package/dist/components/LevelSelector/index.d.ts +3 -0
  77. package/dist/components/LevelSelector/index.js +2 -0
  78. package/dist/components/MapControls/MapControls.d.ts +33 -0
  79. package/dist/components/MapControls/MapControls.js +38 -0
  80. package/dist/components/MapControls/index.d.ts +3 -0
  81. package/dist/components/MapControls/index.js +2 -0
  82. package/dist/components/MobileToggleButton/MobileToggleButton.d.ts +11 -0
  83. package/dist/components/MobileToggleButton/MobileToggleButton.js +8 -0
  84. package/dist/components/MobileToggleButton/index.d.ts +3 -0
  85. package/dist/components/MobileToggleButton/index.js +1 -0
  86. package/dist/components/Modal/Modal.d.ts +34 -0
  87. package/dist/components/Modal/Modal.js +103 -0
  88. package/dist/components/Modal/index.d.ts +3 -0
  89. package/dist/components/Modal/index.js +1 -0
  90. package/dist/components/MultiSelectGroups/MultiSelectGroups.d.ts +37 -0
  91. package/dist/components/MultiSelectGroups/MultiSelectGroups.js +80 -0
  92. package/dist/components/MultiSelectGroups/index.d.ts +3 -0
  93. package/dist/components/MultiSelectGroups/index.js +1 -0
  94. package/dist/components/Overlay/Overlay.d.ts +30 -0
  95. package/dist/components/Overlay/Overlay.js +250 -0
  96. package/dist/components/Overlay/OverlayHeaderContext.d.ts +7 -0
  97. package/dist/components/Overlay/OverlayHeaderContext.js +7 -0
  98. package/dist/components/Overlay/OverlayKeyboardInsetContext.d.ts +7 -0
  99. package/dist/components/Overlay/OverlayKeyboardInsetContext.js +7 -0
  100. package/dist/components/Overlay/OverlayScrollContext.d.ts +7 -0
  101. package/dist/components/Overlay/OverlayScrollContext.js +7 -0
  102. package/dist/components/Overlay/index.d.ts +5 -0
  103. package/dist/components/Overlay/index.js +3 -0
  104. package/dist/components/OverlayGrip/OverlayGrip.d.ts +11 -0
  105. package/dist/components/OverlayGrip/OverlayGrip.js +8 -0
  106. package/dist/components/OverlayGrip/index.d.ts +3 -0
  107. package/dist/components/OverlayGrip/index.js +2 -0
  108. package/dist/components/PermissionNotice/PermissionNotice.d.ts +16 -0
  109. package/dist/components/PermissionNotice/PermissionNotice.js +11 -0
  110. package/dist/components/PermissionNotice/index.d.ts +3 -0
  111. package/dist/components/PermissionNotice/index.js +2 -0
  112. package/dist/components/PlanSelector/PlanSelector.d.ts +13 -0
  113. package/dist/components/PlanSelector/PlanSelector.js +10 -0
  114. package/dist/components/PlanSelector/index.d.ts +3 -0
  115. package/dist/components/PlanSelector/index.js +2 -0
  116. package/dist/components/Radio/Radio.d.ts +15 -0
  117. package/dist/components/Radio/Radio.js +13 -0
  118. package/dist/components/Radio/index.d.ts +3 -0
  119. package/dist/components/Radio/index.js +1 -0
  120. package/dist/components/RebookingNotes/RebookingNotes.d.ts +11 -0
  121. package/dist/components/RebookingNotes/RebookingNotes.js +18 -0
  122. package/dist/components/RebookingNotes/index.d.ts +3 -0
  123. package/dist/components/RebookingNotes/index.js +1 -0
  124. package/dist/components/RebookingRadioGroup/RebookingRadioGroup.d.ts +17 -0
  125. package/dist/components/RebookingRadioGroup/RebookingRadioGroup.js +13 -0
  126. package/dist/components/RebookingRadioGroup/index.d.ts +3 -0
  127. package/dist/components/RebookingRadioGroup/index.js +1 -0
  128. package/dist/components/ScrollableRow/ScrollableRow.d.ts +21 -0
  129. package/dist/components/ScrollableRow/ScrollableRow.js +155 -0
  130. package/dist/components/ScrollableRow/index.d.ts +3 -0
  131. package/dist/components/ScrollableRow/index.js +2 -0
  132. package/dist/components/Share/Share.d.ts +22 -0
  133. package/dist/components/Share/Share.js +24 -0
  134. package/dist/components/Share/index.d.ts +3 -0
  135. package/dist/components/Share/index.js +1 -0
  136. package/dist/components/ShowMoreButton/ShowMoreButton.d.ts +11 -0
  137. package/dist/components/ShowMoreButton/ShowMoreButton.js +7 -0
  138. package/dist/components/ShowMoreButton/index.d.ts +3 -0
  139. package/dist/components/ShowMoreButton/index.js +1 -0
  140. package/dist/components/SidebarActions/SidebarActions.d.ts +26 -0
  141. package/dist/components/SidebarActions/SidebarActions.js +32 -0
  142. package/dist/components/SidebarActions/index.d.ts +3 -0
  143. package/dist/components/SidebarActions/index.js +2 -0
  144. package/dist/components/SimpleRow/SimpleRow.d.ts +15 -0
  145. package/dist/components/SimpleRow/SimpleRow.js +11 -0
  146. package/dist/components/SimpleRow/index.d.ts +3 -0
  147. package/dist/components/SimpleRow/index.js +2 -0
  148. package/dist/components/Spinner/Spinner.d.ts +9 -0
  149. package/dist/components/Spinner/Spinner.js +8 -0
  150. package/dist/components/Spinner/index.d.ts +3 -0
  151. package/dist/components/Spinner/index.js +1 -0
  152. package/dist/components/ToggleButton/ToggleButton.d.ts +17 -0
  153. package/dist/components/ToggleButton/ToggleButton.js +8 -0
  154. package/dist/components/ToggleButton/index.d.ts +3 -0
  155. package/dist/components/ToggleButton/index.js +1 -0
  156. package/dist/components/ToggleSwitch/ToggleSwitch.d.ts +12 -0
  157. package/dist/components/ToggleSwitch/ToggleSwitch.js +10 -0
  158. package/dist/components/ToggleSwitch/index.d.ts +3 -0
  159. package/dist/components/ToggleSwitch/index.js +1 -0
  160. package/dist/components/TouchHand/TouchHand.d.ts +5 -0
  161. package/dist/components/TouchHand/TouchHand.js +7 -0
  162. package/dist/components/TouchHand/index.d.ts +2 -0
  163. package/dist/components/TouchHand/index.js +1 -0
  164. package/dist/components/VenuePicker/VenuePicker.d.ts +23 -0
  165. package/dist/components/VenuePicker/VenuePicker.js +70 -0
  166. package/dist/components/VenuePicker/index.d.ts +3 -0
  167. package/dist/components/VenuePicker/index.js +2 -0
  168. package/dist/components/WayfindingFloorSelector/WayfindingFloorSelector.d.ts +24 -0
  169. package/dist/components/WayfindingFloorSelector/WayfindingFloorSelector.js +27 -0
  170. package/dist/components/WayfindingFloorSelector/index.d.ts +3 -0
  171. package/dist/components/WayfindingFloorSelector/index.js +1 -0
  172. package/dist/index.d.ts +74 -0
  173. package/dist/index.js +77 -0
  174. package/dist/shared/activeElement.d.ts +7 -0
  175. package/dist/shared/activeElement.js +14 -0
  176. package/dist/shared/debounce.d.ts +2 -0
  177. package/dist/shared/debounce.js +9 -0
  178. package/dist/shared/hooks/useKeyboardInset.d.ts +9 -0
  179. package/dist/shared/hooks/useKeyboardInset.js +84 -0
  180. package/dist/shared/hooks/useOnClickOutside.d.ts +14 -0
  181. package/dist/shared/hooks/useOnClickOutside.js +43 -0
  182. package/dist/shared/hooks/useOnEscape.d.ts +14 -0
  183. package/dist/shared/hooks/useOnEscape.js +31 -0
  184. package/dist/shared/hooks/useSheetDrag.d.ts +28 -0
  185. package/dist/shared/hooks/useSheetDrag.js +274 -0
  186. package/dist/shared/hooks/useWindowSize.d.ts +5 -0
  187. package/dist/shared/hooks/useWindowSize.js +38 -0
  188. package/dist/shared/interactive.d.ts +2 -0
  189. package/dist/shared/interactive.js +4 -0
  190. package/dist/shared/selector-option.d.ts +7 -0
  191. package/dist/shared/selector-option.js +1 -0
  192. package/package.json +73 -0
@@ -0,0 +1,30 @@
1
+ import './Overlay.scss';
2
+ import { type ReactNode } from 'react';
3
+ export type Size = 'small' | 'medium' | 'full';
4
+ export interface OverlayProps {
5
+ children?: ReactNode;
6
+ open: boolean;
7
+ size?: Size;
8
+ /** Slot rendered above the content (e.g. a particles canvas); nothing when omitted. */
9
+ particles?: ReactNode;
10
+ className?: string;
11
+ smallSizeMultiplier?: number;
12
+ mediumSizeMultiplier?: number;
13
+ fullSizeOffset?: number;
14
+ scrollThreshold?: number;
15
+ disableDrag?: boolean;
16
+ forceFull?: boolean;
17
+ scrollResetKey?: unknown;
18
+ /** Viewport width (px) at or below which the overlay switches to its mobile bottom-sheet mode. */
19
+ mobileBreakpoint?: number;
20
+ /** Shown when `children` is empty. */
21
+ noContentLabel: string;
22
+ withFloatingButton?: boolean;
23
+ onChangeSize?: (size: Size) => void;
24
+ onScrollStateChange?: (isScrolled: boolean) => void;
25
+ /** Fired (debounced) on scroll — lets the host react to user activity. */
26
+ onScrollActivity?: () => void;
27
+ }
28
+ declare const Overlay: ({ children, open, size, particles, className, onChangeSize, onScrollStateChange, onScrollActivity, smallSizeMultiplier, mediumSizeMultiplier, fullSizeOffset, scrollThreshold, disableDrag, forceFull, scrollResetKey, mobileBreakpoint, noContentLabel, withFloatingButton, }: OverlayProps) => import("react").JSX.Element | null;
29
+ export default Overlay;
30
+ //# sourceMappingURL=Overlay.d.ts.map
@@ -0,0 +1,250 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './Overlay.scss';
3
+ import cn from 'classnames';
4
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
5
+ import debounce from '../../shared/debounce';
6
+ import { useKeyboardInset } from '../../shared/hooks/useKeyboardInset';
7
+ import { useSheetDrag } from '../../shared/hooks/useSheetDrag';
8
+ import { useWindowSize } from '../../shared/hooks/useWindowSize';
9
+ import { OverlayHeaderContext } from './OverlayHeaderContext';
10
+ import { OverlayKeyboardInsetContext } from './OverlayKeyboardInsetContext';
11
+ import { OverlayScrollContext } from './OverlayScrollContext';
12
+ const TRANSITION_DURATION = '0.3s';
13
+ const DEFAULT_SCROLL_THRESHOLD = 10;
14
+ const DEFAULT_MOBILE_BREAKPOINT = 768;
15
+ const getActualViewportHeight = () => {
16
+ const isInIframe = window !== window.top;
17
+ if (isInIframe) {
18
+ return (document.documentElement.clientHeight || document.body.clientHeight || window.innerHeight);
19
+ }
20
+ return window.innerHeight;
21
+ };
22
+ const generateSizes = (height = getActualViewportHeight(), smallMultiplier, mediumMultiplier, fullSizeOffset) => ({
23
+ small: height / smallMultiplier,
24
+ medium: height / mediumMultiplier,
25
+ full: height - fullSizeOffset,
26
+ });
27
+ const Overlay = ({ children, open, size = 'medium', particles, className, onChangeSize, onScrollStateChange, onScrollActivity, smallSizeMultiplier = 12.6, mediumSizeMultiplier = 2.6, fullSizeOffset = 0, scrollThreshold = DEFAULT_SCROLL_THRESHOLD, disableDrag = false, forceFull = false, scrollResetKey, mobileBreakpoint = DEFAULT_MOBILE_BREAKPOINT, noContentLabel, withFloatingButton = false, }) => {
28
+ const { width: windowWidth, height: windowHeight } = useWindowSize();
29
+ // Pure derivations of the window size — computed in render, not stored/synced via an effect.
30
+ const mobile = windowWidth <= mobileBreakpoint;
31
+ const sizes = useMemo(() => generateSizes(windowHeight, smallSizeMultiplier, mediumSizeMultiplier, fullSizeOffset), [windowHeight, smallSizeMultiplier, mediumSizeMultiplier, fullSizeOffset]);
32
+ // The on-screen keyboard covers the sheet without resizing the window (#1567):
33
+ // give up the height the keyboard took, and let the content scroll clear of it.
34
+ const keyboardInset = useKeyboardInset(mobile);
35
+ // What the sheet can show right now. Snap points and visible heights must
36
+ // come from the same numbers, or a drag lands where the sheet is not.
37
+ const effectiveSizes = useMemo(() => {
38
+ if (keyboardInset <= 0)
39
+ return sizes;
40
+ // Never below the smallest snap point: a collapsed sheet reads as a white screen.
41
+ const full = Math.max(sizes.full - keyboardInset, sizes.small);
42
+ return {
43
+ small: Math.min(sizes.small, full),
44
+ medium: Math.min(sizes.medium, full),
45
+ full,
46
+ };
47
+ }, [sizes, keyboardInset]);
48
+ const [dragging, setDragging] = useState(false);
49
+ // The sheet is at zero height: closed, or mounted and about to animate open.
50
+ const [collapsed, setCollapsed] = useState(!open);
51
+ const [isAnimating, setIsAnimating] = useState(false);
52
+ const [shouldRender, setShouldRender] = useState(open);
53
+ const [isScrolled, setIsScrolled] = useState(false);
54
+ const overlayPanelRef = useRef(null);
55
+ const scrollRef = useRef(null);
56
+ const openedAtRef = useRef(undefined);
57
+ // The scroll container is published to descendants through context, and context is read during
58
+ // render — where a ref is still null on the render that mounts the element. Held as state as
59
+ // well, written from the ref callback: that write lands in the mount commit, so consumers see the
60
+ // element as soon as it exists rather than on whichever later render happens to come by.
61
+ const [scrollElement, setScrollElement] = useState(null);
62
+ const attachScroll = useCallback((node) => {
63
+ scrollRef.current = node;
64
+ setScrollElement(node);
65
+ }, []);
66
+ // The header slot, held as state for the same reason.
67
+ const [headerElement, setHeaderElement] = useState(null);
68
+ // The snap point the sheet actually sits on. The prop may be undefined
69
+ // before the host has chosen one, and a drag needs a value to start from.
70
+ const [currentSnap, setCurrentSnap] = useState(size);
71
+ // Mirror for the identity-stable callbacks below. Written after paint, not
72
+ // during render, so a concurrent re-render cannot observe a torn value.
73
+ const snapRef = useRef(currentSnap);
74
+ const sizeRef = useRef(size);
75
+ const onChangeSizeRef = useRef(onChangeSize);
76
+ useLayoutEffect(() => {
77
+ snapRef.current = currentSnap;
78
+ sizeRef.current = size;
79
+ onChangeSizeRef.current = onChangeSize;
80
+ });
81
+ // The snap point is the state; the height follows from it every render. Storing
82
+ // pixels instead would freeze whatever the keyboard allowed at that moment and
83
+ // keep the sheet short after it closes.
84
+ const setSize = useCallback((newSize) => {
85
+ setCurrentSnap(newSize);
86
+ setCollapsed(false);
87
+ onChangeSizeRef.current?.(newSize);
88
+ }, []);
89
+ const positioningStyles = useMemo(() => {
90
+ if (mobile) {
91
+ // The sheet stays on the bottom edge and runs on under the keyboard. A
92
+ // sheet lifted whole leaves the page showing below it, through the
93
+ // translucent bars iOS 26 floats there (#1712).
94
+ const sheet = (visible) => ({ height: visible + keyboardInset });
95
+ if (forceFull && open) {
96
+ // Covers the screen: `fullSizeOffset` keeps room for the search box above a
97
+ // regular sheet, and a forced-full one is drawn over it (#1713). Only the
98
+ // keyboard takes visible height away, never below the smallest snap point.
99
+ return sheet(Math.max(getActualViewportHeight() - keyboardInset, sizes.small));
100
+ }
101
+ // A gesture freezes the sheet at its tallest point and moves it with
102
+ // `translate3d`, keeping the drag off the layout path.
103
+ if (dragging)
104
+ return sheet(effectiveSizes.full);
105
+ // Closed, it takes no room at all, the part under the keyboard included.
106
+ if (collapsed || !(open || isAnimating))
107
+ return { height: 0 };
108
+ return sheet(effectiveSizes[currentSnap]);
109
+ }
110
+ return {
111
+ height: open ? 'auto' : undefined,
112
+ };
113
+ }, [
114
+ mobile,
115
+ open,
116
+ collapsed,
117
+ currentSnap,
118
+ isAnimating,
119
+ forceFull,
120
+ dragging,
121
+ sizes,
122
+ effectiveSizes,
123
+ keyboardInset,
124
+ ]);
125
+ // The content runs on under the keyboard with the sheet (#1712). The padding
126
+ // is the covered part: with it the end of the content scrolls clear of the
127
+ // keyboard, and what the browser scrolls into view lands above it.
128
+ const scrollStyles = useMemo(() => mobile && keyboardInset > 0
129
+ ? { paddingBottom: keyboardInset, scrollPaddingBottom: keyboardInset }
130
+ : undefined, [mobile, keyboardInset]);
131
+ const snapPoints = useMemo(() => [
132
+ { name: 'small', height: effectiveSizes.small },
133
+ { name: 'medium', height: effectiveSizes.medium },
134
+ { name: 'full', height: effectiveSizes.full },
135
+ ], [effectiveSizes]);
136
+ const handleDragStart = useCallback(() => setDragging(true), []);
137
+ const handleSettle = useCallback(() => setDragging(false), []);
138
+ const handleTriggerClick = useCallback(() => {
139
+ const currentSize = snapRef.current;
140
+ const nextSize = currentSize === 'small' ? 'medium' : currentSize === 'medium' ? 'full' : 'small';
141
+ setSize(nextSize);
142
+ }, [setSize]);
143
+ const { onPointerDown } = useSheetDrag({
144
+ enabled: mobile && !disableDrag && !forceFull,
145
+ panelRef: overlayPanelRef,
146
+ scrollElement,
147
+ snapPoints,
148
+ current: currentSnap,
149
+ openedAtRef,
150
+ onDragStart: handleDragStart,
151
+ onSnap: setSize,
152
+ onSettle: handleSettle,
153
+ onHandleTap: handleTriggerClick,
154
+ });
155
+ // The gesture owns `transform`; React owns `height`. Clear the transform in
156
+ // the same paint as the height React just wrote, so the sheet does not jump.
157
+ useLayoutEffect(() => {
158
+ if (dragging)
159
+ return;
160
+ const panel = overlayPanelRef.current;
161
+ if (!panel)
162
+ return;
163
+ // The swap must not run through the `height` transition — it would flash
164
+ // the sheet to the top of the screen.
165
+ panel.style.transition = 'none';
166
+ panel.style.removeProperty('transform');
167
+ const frame = requestAnimationFrame(() => panel.style.removeProperty('transition'));
168
+ return () => cancelAnimationFrame(frame);
169
+ }, [dragging]);
170
+ const handleScroll = useCallback(() => {
171
+ const scrollEl = scrollRef.current;
172
+ if (!scrollEl)
173
+ return;
174
+ const scrollTop = scrollEl.scrollTop;
175
+ const shouldAddClass = scrollTop >= scrollThreshold;
176
+ if (isScrolled !== shouldAddClass) {
177
+ setIsScrolled(shouldAddClass);
178
+ onScrollStateChange?.(shouldAddClass);
179
+ }
180
+ }, [scrollThreshold, isScrolled, onScrollStateChange]);
181
+ const debouncedScrollActivity = useMemo(() => debounce(() => {
182
+ onScrollActivity?.();
183
+ }, 250), [onScrollActivity]);
184
+ // Runs on open/close only. A `size` prop change (or a host re-creating
185
+ // `onChangeSize`) is not a re-open: re-running this would re-arm the opening
186
+ // lock and, 10ms later, write the prop over the snap point a drag just chose.
187
+ useEffect(() => {
188
+ if (open) {
189
+ setShouldRender(true);
190
+ setIsAnimating(true);
191
+ openedAtRef.current = performance.now();
192
+ return;
193
+ }
194
+ setIsAnimating(true);
195
+ openedAtRef.current = undefined;
196
+ if (mobile) {
197
+ setCollapsed(true);
198
+ }
199
+ const timer = setTimeout(() => {
200
+ setShouldRender(false);
201
+ setIsAnimating(false);
202
+ setIsScrolled(false);
203
+ }, parseFloat(TRANSITION_DURATION) * 1000);
204
+ return () => clearTimeout(timer);
205
+ }, [open, mobile]);
206
+ // The step after the mount: the sheet mounts at zero height and takes its size a tick later, so
207
+ // the height transition has a frame to start from. Keyed on `shouldRender` rather than run from
208
+ // the effect above, which fires on the render that only *asked* for the mount and returned null:
209
+ // a timer started there raced the mount render, and when it won, React batched the size flip
210
+ // into the mount itself — no transition, and no second render for anything the mount render
211
+ // could not yet know.
212
+ useEffect(() => {
213
+ if (!open || !shouldRender)
214
+ return;
215
+ const timer = setTimeout(() => {
216
+ setSize(sizeRef.current);
217
+ setIsAnimating(false);
218
+ }, 10);
219
+ return () => clearTimeout(timer);
220
+ }, [open, shouldRender, setSize]);
221
+ // Host-driven size changes (details open at full, the planner at medium).
222
+ // The sheet's own reports come back through here too, already applied.
223
+ useEffect(() => {
224
+ setCurrentSnap(size);
225
+ }, [size]);
226
+ useEffect(() => {
227
+ if (open && !isAnimating) {
228
+ scrollRef.current?.scrollTo({ top: 0 });
229
+ setIsScrolled(false);
230
+ onScrollStateChange?.(false);
231
+ }
232
+ }, [open, isAnimating, onScrollStateChange, scrollResetKey]);
233
+ if (!shouldRender)
234
+ return null;
235
+ return (_jsx(OverlayScrollContext, { value: scrollElement, children: _jsxs("div", { className: cn('efp-overlay', {
236
+ 'efp-overlay--draggable': dragging,
237
+ 'efp-overlay--keyboard': mobile && keyboardInset > 0,
238
+ 'efp-overlay--full': currentSnap === 'full',
239
+ 'efp-overlay--mobile': mobile,
240
+ 'efp-overlay--desktop': !mobile,
241
+ 'efp-overlay--hidden': !mobile && !open,
242
+ 'efp-overlay--scrolled': isScrolled,
243
+ 'efp-overlay--forced-full': forceFull && mobile,
244
+ 'efp-overlay--button-inset': mobile && withFloatingButton,
245
+ }, className), style: positioningStyles, ref: overlayPanelRef, onPointerDown: onPointerDown, children: [!disableDrag && _jsx("div", { className: "efp-overlay__draghandle", "data-sheet-handle": true }), _jsx("div", { className: "efp-overlay__header", ref: setHeaderElement }), _jsxs("div", { className: "efp-overlay__scroll", style: scrollStyles, ref: attachScroll, onScroll: () => {
246
+ handleScroll();
247
+ debouncedScrollActivity();
248
+ }, children: [particles, _jsx("div", { className: "efp-overlay__content", children: _jsx(OverlayHeaderContext, { value: headerElement, children: _jsx(OverlayKeyboardInsetContext, { value: mobile ? keyboardInset : 0, children: children ? children : noContentLabel }) }) })] })] }) }));
249
+ };
250
+ export default Overlay;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The overlay's header slot: a node above the scroll container that descendants can portal into
3
+ * (e.g. a toolbar that must not scroll with the content). Provided by {@link Overlay}; `null` when
4
+ * rendered outside an overlay.
5
+ */
6
+ export declare const OverlayHeaderContext: import("react").Context<HTMLDivElement | null>;
7
+ //# sourceMappingURL=OverlayHeaderContext.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { createContext } from 'react';
2
+ /**
3
+ * The overlay's header slot: a node above the scroll container that descendants can portal into
4
+ * (e.g. a toolbar that must not scroll with the content). Provided by {@link Overlay}; `null` when
5
+ * rendered outside an overlay.
6
+ */
7
+ export const OverlayHeaderContext = createContext(null);
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Height in px of the on-screen keyboard over the bottom of the overlay's scroll container, which
3
+ * runs on under it: whatever has to stay reachable must end that much above the container's
4
+ * bottom edge. Provided by {@link Overlay}; `0` with no keyboard, and outside an overlay.
5
+ */
6
+ export declare const OverlayKeyboardInsetContext: import("react").Context<number>;
7
+ //# sourceMappingURL=OverlayKeyboardInsetContext.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { createContext } from 'react';
2
+ /**
3
+ * Height in px of the on-screen keyboard over the bottom of the overlay's scroll container, which
4
+ * runs on under it: whatever has to stay reachable must end that much above the container's
5
+ * bottom edge. Provided by {@link Overlay}; `0` with no keyboard, and outside an overlay.
6
+ */
7
+ export const OverlayKeyboardInsetContext = createContext(0);
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Exposes the overlay's inner scroll container to descendants so they can
3
+ * observe / drive it (e.g. a virtualized list syncing its scroll position).
4
+ * Provided by {@link Overlay}; `null` when rendered outside an overlay.
5
+ */
6
+ export declare const OverlayScrollContext: import("react").Context<HTMLDivElement | null>;
7
+ //# sourceMappingURL=OverlayScrollContext.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { createContext } from 'react';
2
+ /**
3
+ * Exposes the overlay's inner scroll container to descendants so they can
4
+ * observe / drive it (e.g. a virtualized list syncing its scroll position).
5
+ * Provided by {@link Overlay}; `null` when rendered outside an overlay.
6
+ */
7
+ export const OverlayScrollContext = createContext(null);
@@ -0,0 +1,5 @@
1
+ export type { OverlayProps, Size } from './Overlay';
2
+ export { default } from './Overlay';
3
+ export { OverlayHeaderContext } from './OverlayHeaderContext';
4
+ export { OverlayScrollContext } from './OverlayScrollContext';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { default } from './Overlay';
2
+ export { OverlayHeaderContext } from './OverlayHeaderContext';
3
+ export { OverlayScrollContext } from './OverlayScrollContext';
@@ -0,0 +1,11 @@
1
+ import './OverlayGrip.scss';
2
+ import React from 'react';
3
+ export interface OverlayGripProps {
4
+ isFull: boolean;
5
+ onToggle: () => void;
6
+ ariaLabel: string;
7
+ className?: string;
8
+ }
9
+ declare const OverlayGrip: ({ isFull, onToggle, ariaLabel, className }: OverlayGripProps) => React.JSX.Element;
10
+ export default OverlayGrip;
11
+ //# sourceMappingURL=OverlayGrip.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // @ts-nocheck
3
+ import './OverlayGrip.scss';
4
+ import cn from 'classnames';
5
+ const OverlayGrip = ({ isFull, onToggle, ariaLabel, className }) => {
6
+ return (_jsx("button", { type: "button", className: cn('efp-overlay-grip', { 'efp-overlay-grip--full': isFull }, className), onClick: onToggle, "aria-label": ariaLabel, "aria-expanded": isFull, children: _jsxs("svg", { viewBox: "0 0 1200 200", preserveAspectRatio: "xMidYMid meet", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("path", { d: "M100,100 l 500 100 L 1100 100" }), _jsx("path", { d: "M100,150 l 500 0 L 1100 150" })] }) }));
7
+ };
8
+ export default OverlayGrip;
@@ -0,0 +1,3 @@
1
+ export { default } from './OverlayGrip';
2
+ export type { OverlayGripProps } from './OverlayGrip';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export { default } from './OverlayGrip';
@@ -0,0 +1,16 @@
1
+ import './PermissionNotice.scss';
2
+ import React from 'react';
3
+ export type PermissionNoticePlacement = 'bottom-right' | 'bottom-left';
4
+ export interface PermissionNoticeProps {
5
+ title: string;
6
+ acceptText: string;
7
+ rejectText: string;
8
+ children: React.ReactNode;
9
+ placement?: PermissionNoticePlacement;
10
+ onAccept?: () => void;
11
+ onReject?: () => void;
12
+ className?: string;
13
+ }
14
+ declare const PermissionNotice: ({ title, acceptText, rejectText, children, placement, onAccept, onReject, className, }: PermissionNoticeProps) => React.JSX.Element;
15
+ export default PermissionNotice;
16
+ //# sourceMappingURL=PermissionNotice.d.ts.map
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './PermissionNotice.scss';
3
+ import cn from 'classnames';
4
+ import { useId } from 'react';
5
+ import Button from '../Button';
6
+ const PermissionNotice = ({ title, acceptText, rejectText, children, placement = 'bottom-right', onAccept, onReject, className, }) => {
7
+ const titleId = useId();
8
+ const descId = useId();
9
+ return (_jsxs("div", { className: cn('efp-permission-notice', `efp-permission-notice--${placement}`, className), role: "dialog", "aria-labelledby": titleId, "aria-describedby": descId, children: [_jsx("div", { className: "efp-permission-notice__title", id: titleId, children: title }), _jsx("div", { className: "efp-permission-notice__text", id: descId, children: children }), _jsxs("div", { className: "efp-permission-notice__bottom", children: [_jsx(Button, { size: "md", onClick: onAccept, children: acceptText }), _jsx(Button, { size: "md", variant: "gray", onClick: onReject, children: rejectText })] })] }));
10
+ };
11
+ export default PermissionNotice;
@@ -0,0 +1,3 @@
1
+ export { default } from './PermissionNotice';
2
+ export type { PermissionNoticeProps } from './PermissionNotice';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export { default } from './PermissionNotice';
@@ -0,0 +1,13 @@
1
+ import './PlanSelector.scss';
2
+ import type { ReactNode } from 'react';
3
+ export interface PlanSelectorProps {
4
+ /** Plan-scope controls, stacked top to bottom (venue picker, then levels). */
5
+ children: ReactNode;
6
+ }
7
+ /**
8
+ * Places the plan-scope controls in the map's top corner. This is the only
9
+ * component of the stack that positions itself — the controls inside stay
10
+ * layout-agnostic, so composing them never means undoing their own placement.
11
+ */
12
+ export default function PlanSelector({ children }: PlanSelectorProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=PlanSelector.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import './PlanSelector.scss';
3
+ /**
4
+ * Places the plan-scope controls in the map's top corner. This is the only
5
+ * component of the stack that positions itself — the controls inside stay
6
+ * layout-agnostic, so composing them never means undoing their own placement.
7
+ */
8
+ export default function PlanSelector({ children }) {
9
+ return _jsx("div", { className: "efp-plan-selector", children: children });
10
+ }
@@ -0,0 +1,3 @@
1
+ export { default } from './PlanSelector';
2
+ export type { PlanSelectorProps } from './PlanSelector';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export { default } from './PlanSelector';
@@ -0,0 +1,15 @@
1
+ import './Radio.scss';
2
+ import React from 'react';
3
+ export interface RadioProps {
4
+ name: string;
5
+ label: string;
6
+ value: string | number;
7
+ checked?: boolean;
8
+ disabled?: boolean;
9
+ className?: string;
10
+ ariaLabel?: string;
11
+ onChange?: () => void;
12
+ }
13
+ declare const Radio: ({ name, label, value, checked, disabled, className, ariaLabel, onChange, }: RadioProps) => React.JSX.Element;
14
+ export default Radio;
15
+ //# sourceMappingURL=Radio.d.ts.map
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // @ts-nocheck
3
+ import './Radio.scss';
4
+ import classNames from 'classnames';
5
+ import { useId } from 'react';
6
+ const Radio = ({ name, label, value, checked, disabled, className, ariaLabel, onChange, }) => {
7
+ const id = useId();
8
+ return (_jsxs("label", { htmlFor: id, className: classNames('efp-radio', className, {
9
+ 'efp-radio--checked': checked,
10
+ 'efp-radio--disabled': disabled,
11
+ }), children: [_jsx("input", { type: "radio", className: "efp-radio__input", id: id, name: name, value: value, checked: checked, disabled: disabled, "aria-label": ariaLabel, onChange: onChange }), _jsx("span", { className: "efp-radio__control", "aria-hidden": "true" }), _jsx("span", { className: "efp-radio__label", children: label })] }));
12
+ };
13
+ export default Radio;
@@ -0,0 +1,3 @@
1
+ export type { RadioProps } from './Radio';
2
+ export { default } from './Radio';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { default } from './Radio';
@@ -0,0 +1,11 @@
1
+ import './RebookingNotes.scss';
2
+ export interface RebookingNotesProps {
3
+ value?: string;
4
+ noteLabel: string;
5
+ saveButtonLabel: string;
6
+ saveButtonAriaLabel: string;
7
+ onSave: (value: string) => void;
8
+ }
9
+ declare const RebookingNotes: ({ value, noteLabel, saveButtonLabel, saveButtonAriaLabel, onSave, }: RebookingNotesProps) => import("react").JSX.Element;
10
+ export default RebookingNotes;
11
+ //# sourceMappingURL=RebookingNotes.d.ts.map
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './RebookingNotes.scss';
3
+ import { useId, useState } from 'react';
4
+ import Button from '../Button';
5
+ const RebookingNotes = ({ value, noteLabel, saveButtonLabel, saveButtonAriaLabel, onSave, }) => {
6
+ const id = useId();
7
+ const labelId = `${id}-label`;
8
+ const textareaId = `${id}-textarea`;
9
+ // Uncontrolled editing buffer seeded from `value`; consumers reset it by remounting via `key`
10
+ // (see RebookingNotesContainer usage). Committed to the parent only on save.
11
+ const [internalValue, setInternalValue] = useState(value ?? '');
12
+ const handleChange = (event) => setInternalValue(event.target.value);
13
+ const handleSave = () => {
14
+ onSave(internalValue);
15
+ };
16
+ return (_jsxs("div", { className: "rebooking-notes", children: [_jsx("div", { className: "rebooking-notes__view-header", children: _jsx("strong", { id: labelId, children: noteLabel }) }), _jsxs("div", { className: "rebooking-notes__edit", children: [_jsx("div", { className: "rebooking-notes__val", children: _jsx("textarea", { id: textareaId, value: internalValue, onChange: handleChange, "aria-labelledby": labelId }) }), _jsx("div", { className: "rebooking-notes__buttons", children: _jsx(Button, { inline: true, onClick: handleSave, disabled: (value ?? '') === internalValue, "aria-label": saveButtonAriaLabel, children: saveButtonLabel }) })] })] }));
17
+ };
18
+ export default RebookingNotes;
@@ -0,0 +1,3 @@
1
+ export type { RebookingNotesProps } from './RebookingNotes';
2
+ export { default } from './RebookingNotes';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { default } from './RebookingNotes';
@@ -0,0 +1,17 @@
1
+ import './RebookingRadioGroup.scss';
2
+ export interface RebookingOption {
3
+ value: string;
4
+ label: string;
5
+ iconName?: string;
6
+ disabled?: boolean;
7
+ color: string;
8
+ }
9
+ export interface RebookingRadioGroupProps {
10
+ options: RebookingOption[];
11
+ value: string;
12
+ title?: string;
13
+ onChange: (value: string) => void;
14
+ }
15
+ declare const RebookingRadioGroup: ({ options, value, title, onChange }: RebookingRadioGroupProps) => import("react").JSX.Element;
16
+ export default RebookingRadioGroup;
17
+ //# sourceMappingURL=RebookingRadioGroup.d.ts.map
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './RebookingRadioGroup.scss';
3
+ import { useId } from 'react';
4
+ const RebookingRadioGroup = ({ options, value, title, onChange }) => {
5
+ const idPrefix = useId();
6
+ return (_jsxs("div", { className: "rebooking-radio-group", children: [title && _jsx("div", { className: "rebooking-radio-group__title", children: title }), _jsx("div", { className: "rebooking-radio-group__options", children: options.map((option) => {
7
+ const optionId = `${idPrefix}-${option.value}`;
8
+ return (_jsxs("div", { className: "rebooking-radio", style: {
9
+ '--rebooking-color-primary': option.color,
10
+ }, children: [_jsx("input", { type: "radio", name: idPrefix, value: option.value, id: optionId, checked: option.value === value, disabled: option.disabled, onChange: () => onChange(option.value) }), _jsxs("label", { htmlFor: optionId, children: [_jsx("div", { className: "rebooking-radio__label", children: option.label }), _jsx("div", { className: "rebooking-radio__icon", children: _jsx("i", { className: option.iconName, "aria-hidden": "true" }) })] })] }, option.value));
11
+ }) })] }));
12
+ };
13
+ export default RebookingRadioGroup;
@@ -0,0 +1,3 @@
1
+ export type { RebookingOption, RebookingRadioGroupProps } from './RebookingRadioGroup';
2
+ export { default } from './RebookingRadioGroup';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { default } from './RebookingRadioGroup';
@@ -0,0 +1,21 @@
1
+ import './ScrollableRow.scss';
2
+ import React, { ReactNode } from 'react';
3
+ export interface ScrollableRowProps {
4
+ children: ReactNode;
5
+ ariaLabel: string;
6
+ leftAriaLabel: string;
7
+ rightAriaLabel: string;
8
+ className?: string;
9
+ scrollAmount?: number;
10
+ mobileBreakpoint?: number;
11
+ showArrowsOnMobile?: boolean;
12
+ arrowPosition?: 'inside' | 'outside';
13
+ scrollBehavior?: 'smooth' | 'auto';
14
+ isRtl?: boolean;
15
+ enableDragScroll?: boolean;
16
+ dragScrollSensitivity?: number;
17
+ onScroll?: (scrollLeft: number) => void;
18
+ }
19
+ declare const ScrollableRow: ({ children, ariaLabel, leftAriaLabel, rightAriaLabel, className, scrollAmount, mobileBreakpoint, showArrowsOnMobile, arrowPosition, scrollBehavior, isRtl, enableDragScroll, dragScrollSensitivity, onScroll, }: ScrollableRowProps) => React.JSX.Element;
20
+ export default ScrollableRow;
21
+ //# sourceMappingURL=ScrollableRow.d.ts.map