@indico-data/design-system 3.9.0 → 3.10.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.
package/lib/index.js CHANGED
@@ -2308,7 +2308,7 @@ function roundByDPR(element, value) {
2308
2308
  return Math.round(value * dpr) / dpr;
2309
2309
  }
2310
2310
 
2311
- function useLatestRef(value) {
2311
+ function useLatestRef$1(value) {
2312
2312
  const ref = React__namespace.useRef(value);
2313
2313
  index$1(() => {
2314
2314
  ref.current = value;
@@ -2369,8 +2369,8 @@ function useFloating$1(options) {
2369
2369
  const floatingRef = React__namespace.useRef(null);
2370
2370
  const dataRef = React__namespace.useRef(data);
2371
2371
  const hasWhileElementsMounted = whileElementsMounted != null;
2372
- const whileElementsMountedRef = useLatestRef(whileElementsMounted);
2373
- const platformRef = useLatestRef(platform);
2372
+ const whileElementsMountedRef = useLatestRef$1(whileElementsMounted);
2373
+ const platformRef = useLatestRef$1(platform);
2374
2374
  const update = React__namespace.useCallback(() => {
2375
2375
  if (!referenceRef.current || !floatingRef.current) {
2376
2376
  return;
@@ -11958,6 +11958,9 @@ function isMouseLikePointerType(pointerType, strict) {
11958
11958
  // On some Linux machines with Chromium, mouse inputs return a `pointerType`
11959
11959
  // of "pen": https://github.com/floating-ui/floating-ui/issues/2015
11960
11960
  const values = ['mouse', 'pen'];
11961
+ if (!strict) {
11962
+ values.push('', undefined);
11963
+ }
11961
11964
  return values.includes(pointerType);
11962
11965
  }
11963
11966
  function isReactEvent(event) {
@@ -12653,6 +12656,320 @@ function createAttribute(name) {
12653
12656
  return "data-floating-ui-" + name;
12654
12657
  }
12655
12658
 
12659
+ function useLatestRef(value) {
12660
+ const ref = React.useRef(value);
12661
+ index(() => {
12662
+ ref.current = value;
12663
+ });
12664
+ return ref;
12665
+ }
12666
+
12667
+ const safePolygonIdentifier = /*#__PURE__*/createAttribute('safe-polygon');
12668
+ function getDelay(value, prop, pointerType) {
12669
+ if (pointerType && !isMouseLikePointerType(pointerType)) {
12670
+ return 0;
12671
+ }
12672
+ if (typeof value === 'number') {
12673
+ return value;
12674
+ }
12675
+ return value == null ? void 0 : value[prop];
12676
+ }
12677
+ /**
12678
+ * Opens the floating element while hovering over the reference element, like
12679
+ * CSS `:hover`.
12680
+ * @see https://floating-ui.com/docs/useHover
12681
+ */
12682
+ function useHover(context, props) {
12683
+ if (props === void 0) {
12684
+ props = {};
12685
+ }
12686
+ const {
12687
+ open,
12688
+ onOpenChange,
12689
+ dataRef,
12690
+ events,
12691
+ elements
12692
+ } = context;
12693
+ const {
12694
+ enabled = true,
12695
+ delay = 0,
12696
+ handleClose = null,
12697
+ mouseOnly = false,
12698
+ restMs = 0,
12699
+ move = true
12700
+ } = props;
12701
+ const tree = useFloatingTree();
12702
+ const parentId = useFloatingParentNodeId();
12703
+ const handleCloseRef = useLatestRef(handleClose);
12704
+ const delayRef = useLatestRef(delay);
12705
+ const openRef = useLatestRef(open);
12706
+ const pointerTypeRef = React__namespace.useRef();
12707
+ const timeoutRef = React__namespace.useRef(-1);
12708
+ const handlerRef = React__namespace.useRef();
12709
+ const restTimeoutRef = React__namespace.useRef(-1);
12710
+ const blockMouseMoveRef = React__namespace.useRef(true);
12711
+ const performedPointerEventsMutationRef = React__namespace.useRef(false);
12712
+ const unbindMouseMoveRef = React__namespace.useRef(() => {});
12713
+ const isHoverOpen = React__namespace.useCallback(() => {
12714
+ var _dataRef$current$open;
12715
+ const type = (_dataRef$current$open = dataRef.current.openEvent) == null ? void 0 : _dataRef$current$open.type;
12716
+ return (type == null ? void 0 : type.includes('mouse')) && type !== 'mousedown';
12717
+ }, [dataRef]);
12718
+
12719
+ // When closing before opening, clear the delay timeouts to cancel it
12720
+ // from showing.
12721
+ React__namespace.useEffect(() => {
12722
+ if (!enabled) return;
12723
+ function onOpenChange(_ref) {
12724
+ let {
12725
+ open
12726
+ } = _ref;
12727
+ if (!open) {
12728
+ clearTimeout(timeoutRef.current);
12729
+ clearTimeout(restTimeoutRef.current);
12730
+ blockMouseMoveRef.current = true;
12731
+ }
12732
+ }
12733
+ events.on('openchange', onOpenChange);
12734
+ return () => {
12735
+ events.off('openchange', onOpenChange);
12736
+ };
12737
+ }, [enabled, events]);
12738
+ React__namespace.useEffect(() => {
12739
+ if (!enabled) return;
12740
+ if (!handleCloseRef.current) return;
12741
+ if (!open) return;
12742
+ function onLeave(event) {
12743
+ if (isHoverOpen()) {
12744
+ onOpenChange(false, event, 'hover');
12745
+ }
12746
+ }
12747
+ const html = getDocument(elements.floating).documentElement;
12748
+ html.addEventListener('mouseleave', onLeave);
12749
+ return () => {
12750
+ html.removeEventListener('mouseleave', onLeave);
12751
+ };
12752
+ }, [elements.floating, open, onOpenChange, enabled, handleCloseRef, isHoverOpen]);
12753
+ const closeWithDelay = React__namespace.useCallback(function (event, runElseBranch, reason) {
12754
+ if (runElseBranch === void 0) {
12755
+ runElseBranch = true;
12756
+ }
12757
+ if (reason === void 0) {
12758
+ reason = 'hover';
12759
+ }
12760
+ const closeDelay = getDelay(delayRef.current, 'close', pointerTypeRef.current);
12761
+ if (closeDelay && !handlerRef.current) {
12762
+ clearTimeout(timeoutRef.current);
12763
+ timeoutRef.current = window.setTimeout(() => onOpenChange(false, event, reason), closeDelay);
12764
+ } else if (runElseBranch) {
12765
+ clearTimeout(timeoutRef.current);
12766
+ onOpenChange(false, event, reason);
12767
+ }
12768
+ }, [delayRef, onOpenChange]);
12769
+ const cleanupMouseMoveHandler = useEffectEvent(() => {
12770
+ unbindMouseMoveRef.current();
12771
+ handlerRef.current = undefined;
12772
+ });
12773
+ const clearPointerEvents = useEffectEvent(() => {
12774
+ if (performedPointerEventsMutationRef.current) {
12775
+ const body = getDocument(elements.floating).body;
12776
+ body.style.pointerEvents = '';
12777
+ body.removeAttribute(safePolygonIdentifier);
12778
+ performedPointerEventsMutationRef.current = false;
12779
+ }
12780
+ });
12781
+
12782
+ // Registering the mouse events on the reference directly to bypass React's
12783
+ // delegation system. If the cursor was on a disabled element and then entered
12784
+ // the reference (no gap), `mouseenter` doesn't fire in the delegation system.
12785
+ React__namespace.useEffect(() => {
12786
+ if (!enabled) return;
12787
+ function isClickLikeOpenEvent() {
12788
+ return dataRef.current.openEvent ? ['click', 'mousedown'].includes(dataRef.current.openEvent.type) : false;
12789
+ }
12790
+ function onMouseEnter(event) {
12791
+ clearTimeout(timeoutRef.current);
12792
+ blockMouseMoveRef.current = false;
12793
+ if (mouseOnly && !isMouseLikePointerType(pointerTypeRef.current) || restMs > 0 && !getDelay(delayRef.current, 'open')) {
12794
+ return;
12795
+ }
12796
+ const openDelay = getDelay(delayRef.current, 'open', pointerTypeRef.current);
12797
+ if (openDelay) {
12798
+ timeoutRef.current = window.setTimeout(() => {
12799
+ if (!openRef.current) {
12800
+ onOpenChange(true, event, 'hover');
12801
+ }
12802
+ }, openDelay);
12803
+ } else {
12804
+ onOpenChange(true, event, 'hover');
12805
+ }
12806
+ }
12807
+ function onMouseLeave(event) {
12808
+ if (isClickLikeOpenEvent()) return;
12809
+ unbindMouseMoveRef.current();
12810
+ const doc = getDocument(elements.floating);
12811
+ clearTimeout(restTimeoutRef.current);
12812
+ if (handleCloseRef.current && dataRef.current.floatingContext) {
12813
+ // Prevent clearing `onScrollMouseLeave` timeout.
12814
+ if (!open) {
12815
+ clearTimeout(timeoutRef.current);
12816
+ }
12817
+ handlerRef.current = handleCloseRef.current({
12818
+ ...dataRef.current.floatingContext,
12819
+ tree,
12820
+ x: event.clientX,
12821
+ y: event.clientY,
12822
+ onClose() {
12823
+ clearPointerEvents();
12824
+ cleanupMouseMoveHandler();
12825
+ closeWithDelay(event, true, 'safe-polygon');
12826
+ }
12827
+ });
12828
+ const handler = handlerRef.current;
12829
+ doc.addEventListener('mousemove', handler);
12830
+ unbindMouseMoveRef.current = () => {
12831
+ doc.removeEventListener('mousemove', handler);
12832
+ };
12833
+ return;
12834
+ }
12835
+
12836
+ // Allow interactivity without `safePolygon` on touch devices. With a
12837
+ // pointer, a short close delay is an alternative, so it should work
12838
+ // consistently.
12839
+ const shouldClose = pointerTypeRef.current === 'touch' ? !contains(elements.floating, event.relatedTarget) : true;
12840
+ if (shouldClose) {
12841
+ closeWithDelay(event);
12842
+ }
12843
+ }
12844
+
12845
+ // Ensure the floating element closes after scrolling even if the pointer
12846
+ // did not move.
12847
+ // https://github.com/floating-ui/floating-ui/discussions/1692
12848
+ function onScrollMouseLeave(event) {
12849
+ if (isClickLikeOpenEvent()) return;
12850
+ if (!dataRef.current.floatingContext) return;
12851
+ handleCloseRef.current == null || handleCloseRef.current({
12852
+ ...dataRef.current.floatingContext,
12853
+ tree,
12854
+ x: event.clientX,
12855
+ y: event.clientY,
12856
+ onClose() {
12857
+ clearPointerEvents();
12858
+ cleanupMouseMoveHandler();
12859
+ closeWithDelay(event);
12860
+ }
12861
+ })(event);
12862
+ }
12863
+ if (isElement$1(elements.domReference)) {
12864
+ var _elements$floating;
12865
+ const ref = elements.domReference;
12866
+ open && ref.addEventListener('mouseleave', onScrollMouseLeave);
12867
+ (_elements$floating = elements.floating) == null || _elements$floating.addEventListener('mouseleave', onScrollMouseLeave);
12868
+ move && ref.addEventListener('mousemove', onMouseEnter, {
12869
+ once: true
12870
+ });
12871
+ ref.addEventListener('mouseenter', onMouseEnter);
12872
+ ref.addEventListener('mouseleave', onMouseLeave);
12873
+ return () => {
12874
+ var _elements$floating2;
12875
+ open && ref.removeEventListener('mouseleave', onScrollMouseLeave);
12876
+ (_elements$floating2 = elements.floating) == null || _elements$floating2.removeEventListener('mouseleave', onScrollMouseLeave);
12877
+ move && ref.removeEventListener('mousemove', onMouseEnter);
12878
+ ref.removeEventListener('mouseenter', onMouseEnter);
12879
+ ref.removeEventListener('mouseleave', onMouseLeave);
12880
+ };
12881
+ }
12882
+ }, [elements, enabled, context, mouseOnly, restMs, move, closeWithDelay, cleanupMouseMoveHandler, clearPointerEvents, onOpenChange, open, openRef, tree, delayRef, handleCloseRef, dataRef]);
12883
+
12884
+ // Block pointer-events of every element other than the reference and floating
12885
+ // while the floating element is open and has a `handleClose` handler. Also
12886
+ // handles nested floating elements.
12887
+ // https://github.com/floating-ui/floating-ui/issues/1722
12888
+ index(() => {
12889
+ var _handleCloseRef$curre;
12890
+ if (!enabled) return;
12891
+ if (open && (_handleCloseRef$curre = handleCloseRef.current) != null && _handleCloseRef$curre.__options.blockPointerEvents && isHoverOpen()) {
12892
+ const body = getDocument(elements.floating).body;
12893
+ body.setAttribute(safePolygonIdentifier, '');
12894
+ body.style.pointerEvents = 'none';
12895
+ performedPointerEventsMutationRef.current = true;
12896
+ const floatingEl = elements.floating;
12897
+ if (isElement$1(elements.domReference) && floatingEl) {
12898
+ var _tree$nodesRef$curren;
12899
+ const ref = elements.domReference;
12900
+ const parentFloating = tree == null || (_tree$nodesRef$curren = tree.nodesRef.current.find(node => node.id === parentId)) == null || (_tree$nodesRef$curren = _tree$nodesRef$curren.context) == null ? void 0 : _tree$nodesRef$curren.elements.floating;
12901
+ if (parentFloating) {
12902
+ parentFloating.style.pointerEvents = '';
12903
+ }
12904
+ ref.style.pointerEvents = 'auto';
12905
+ floatingEl.style.pointerEvents = 'auto';
12906
+ return () => {
12907
+ ref.style.pointerEvents = '';
12908
+ floatingEl.style.pointerEvents = '';
12909
+ };
12910
+ }
12911
+ }
12912
+ }, [enabled, open, parentId, elements, tree, handleCloseRef, isHoverOpen]);
12913
+ index(() => {
12914
+ if (!open) {
12915
+ pointerTypeRef.current = undefined;
12916
+ cleanupMouseMoveHandler();
12917
+ clearPointerEvents();
12918
+ }
12919
+ }, [open, cleanupMouseMoveHandler, clearPointerEvents]);
12920
+ React__namespace.useEffect(() => {
12921
+ return () => {
12922
+ cleanupMouseMoveHandler();
12923
+ clearTimeout(timeoutRef.current);
12924
+ clearTimeout(restTimeoutRef.current);
12925
+ clearPointerEvents();
12926
+ };
12927
+ }, [enabled, elements.domReference, cleanupMouseMoveHandler, clearPointerEvents]);
12928
+ const reference = React__namespace.useMemo(() => {
12929
+ function setPointerRef(event) {
12930
+ pointerTypeRef.current = event.pointerType;
12931
+ }
12932
+ return {
12933
+ onPointerDown: setPointerRef,
12934
+ onPointerEnter: setPointerRef,
12935
+ onMouseMove(event) {
12936
+ const {
12937
+ nativeEvent
12938
+ } = event;
12939
+ function handleMouseMove() {
12940
+ if (!blockMouseMoveRef.current && !openRef.current) {
12941
+ onOpenChange(true, nativeEvent, 'hover');
12942
+ }
12943
+ }
12944
+ if (mouseOnly && !isMouseLikePointerType(pointerTypeRef.current)) {
12945
+ return;
12946
+ }
12947
+ if (open || restMs === 0) {
12948
+ return;
12949
+ }
12950
+ clearTimeout(restTimeoutRef.current);
12951
+ if (pointerTypeRef.current === 'touch') {
12952
+ handleMouseMove();
12953
+ } else {
12954
+ restTimeoutRef.current = window.setTimeout(handleMouseMove, restMs);
12955
+ }
12956
+ }
12957
+ };
12958
+ }, [mouseOnly, onOpenChange, open, openRef, restMs]);
12959
+ const floating = React__namespace.useMemo(() => ({
12960
+ onMouseEnter() {
12961
+ clearTimeout(timeoutRef.current);
12962
+ },
12963
+ onMouseLeave(event) {
12964
+ closeWithDelay(event.nativeEvent, false);
12965
+ }
12966
+ }), [closeWithDelay]);
12967
+ return React__namespace.useMemo(() => enabled ? {
12968
+ reference,
12969
+ floating
12970
+ } : {}, [enabled, reference, floating]);
12971
+ }
12972
+
12656
12973
  function getChildren(nodes, id) {
12657
12974
  let allChildren = nodes.filter(node => {
12658
12975
  var _node$context;
@@ -12978,7 +13295,7 @@ function useClick(context, props) {
12978
13295
  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
12979
13296
  if (event.button !== 0) return;
12980
13297
  if (eventOption === 'click') return;
12981
- if (isMouseLikePointerType(pointerType) && ignoreMouse) return;
13298
+ if (isMouseLikePointerType(pointerType, true) && ignoreMouse) return;
12982
13299
  if (open && toggle && (dataRef.current.openEvent ? dataRef.current.openEvent.type === 'mousedown' : true)) {
12983
13300
  onOpenChange(false, event.nativeEvent, 'click');
12984
13301
  } else {
@@ -12993,7 +13310,7 @@ function useClick(context, props) {
12993
13310
  pointerTypeRef.current = undefined;
12994
13311
  return;
12995
13312
  }
12996
- if (isMouseLikePointerType(pointerType) && ignoreMouse) return;
13313
+ if (isMouseLikePointerType(pointerType, true) && ignoreMouse) return;
12997
13314
  if (open && toggle && (dataRef.current.openEvent ? dataRef.current.openEvent.type === 'click' : true)) {
12998
13315
  onOpenChange(false, event.nativeEvent, 'click');
12999
13316
  } else {
@@ -13534,7 +13851,7 @@ const defaultOptions$1 = {
13534
13851
  placement: 'bottom-start',
13535
13852
  middleware: [offset$2(5), flip$2(), shift$2()],
13536
13853
  };
13537
- function FloatUI({ children, ariaLabel, isOpen: controlledIsOpen, setIsOpen: controlledSetIsOpen, isPortal = false, portalOptions = {}, floatingOptions = defaultOptions$1, className, }) {
13854
+ function FloatUI({ children, ariaLabel, isOpen: controlledIsOpen, setIsOpen: controlledSetIsOpen, isPortal = false, portalOptions = {}, floatingOptions = defaultOptions$1, className, hover = false, }) {
13538
13855
  const [internalIsOpen, setInternalIsOpen] = React.useState(false);
13539
13856
  // Determine whether the component is controlled or uncontrolled
13540
13857
  const isControlled = controlledIsOpen !== undefined && controlledSetIsOpen !== undefined;
@@ -13553,9 +13870,11 @@ function FloatUI({ children, ariaLabel, isOpen: controlledIsOpen, setIsOpen: con
13553
13870
  const { refs, floatingStyles, context } = useFloating(Object.assign(Object.assign({}, floatingOptions), { open: isOpen, onOpenChange: setIsOpen, elements: {
13554
13871
  reference: referenceElementRef.current,
13555
13872
  } }));
13556
- const click = useClick(context);
13873
+ // Can't call hooks conditionally so this enabled option is needed.
13874
+ const click = useClick(context, { enabled: !hover });
13875
+ const hoverHook = useHover(context, { enabled: hover });
13557
13876
  const dismiss = useDismiss(context);
13558
- const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
13877
+ const { getReferenceProps, getFloatingProps } = useInteractions([click, hoverHook, dismiss]);
13559
13878
  const tooltipContent = (jsxRuntime.jsx("div", Object.assign({ ref: refs.setFloating }, getFloatingProps(), { style: floatingStyles, role: "dialog", "aria-label": ariaLabel, className: `floatui-container ${className}`, children: jsxRuntime.jsx("div", { ref: floatUIContentRef, className: "floatui-content", children: content }) })));
13560
13879
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", Object.assign({ ref: refs.setReference }, getReferenceProps(), { children: trigger })), isOpen &&
13561
13880
  (isPortal ? (jsxRuntime.jsx(FloatingPortal, { id: portalOptions === null || portalOptions === void 0 ? void 0 : portalOptions.rootId, children: tooltipContent })) : (tooltipContent))] }));