@synerise/ds-popover 1.1.2 → 1.3.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/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.3.0](https://github.com/Synerise/synerise-design/compare/@synerise/ds-popover@1.2.0...@synerise/ds-popover@1.3.0) (2026-01-20)
7
+
8
+ ### Features
9
+
10
+ - **information-card:** migrate to popover ([de900e4](https://github.com/Synerise/synerise-design/commit/de900e4bc1c32a4bbbf175401374619e691023f2))
11
+
12
+ # [1.2.0](https://github.com/Synerise/synerise-design/compare/@synerise/ds-popover@1.1.2...@synerise/ds-popover@1.2.0) (2025-12-19)
13
+
14
+ ### Features
15
+
16
+ - **popconfirm:** migrate to popover ([f14f74e](https://github.com/Synerise/synerise-design/commit/f14f74e1f9879ddd8264dc2614723a298b656d2f))
17
+
6
18
  ## [1.1.2](https://github.com/Synerise/synerise-design/compare/@synerise/ds-popover@1.1.1...@synerise/ds-popover@1.1.2) (2025-12-15)
7
19
 
8
20
  **Note:** Version bump only for package @synerise/ds-popover
@@ -1,2 +1,5 @@
1
+ import { type Placement } from '@floating-ui/react';
2
+ import { type LegacyPlacement } from './Popover.types';
1
3
  export declare const HOVER_OPEN_DELAY = 100;
2
4
  export declare const HOVER_CLOSE_DELAY = 100;
5
+ export declare const PLACEMENT_MAP: Record<LegacyPlacement, Placement>;
@@ -1,2 +1,18 @@
1
1
  export var HOVER_OPEN_DELAY = 100;
2
- export var HOVER_CLOSE_DELAY = 100;
2
+ export var HOVER_CLOSE_DELAY = 100;
3
+ export var PLACEMENT_MAP = {
4
+ top: 'top',
5
+ bottom: 'bottom',
6
+ left: 'left',
7
+ right: 'right',
8
+ leftTop: 'left-start',
9
+ leftBottom: 'left-end',
10
+ rightTop: 'right-start',
11
+ rightBottom: 'right-end',
12
+ topRight: 'top-end',
13
+ topLeft: 'top-start',
14
+ topCenter: 'top',
15
+ bottomCenter: 'bottom',
16
+ bottomLeft: 'bottom-start',
17
+ bottomRight: 'bottom-end'
18
+ };
@@ -1,5 +1,5 @@
1
- import { type CSSProperties, type Dispatch, type ReactNode, type SetStateAction } from 'react';
2
- import { type AutoUpdateOptions, type FlipOptions, type OffsetOptions, type OpenChangeReason, type Placement, type ShiftOptions, type UseDismissProps, type UseFloatingReturn, type UseInteractionsReturn, type UseListNavigationProps, type UseTransitionStylesProps } from '@floating-ui/react';
1
+ import { type CSSProperties, type Dispatch, type ReactNode, type RefObject, type SetStateAction } from 'react';
2
+ import { type ArrowOptions, type AutoUpdateOptions, type Delay, type FlipOptions, type OffsetOptions, type OpenChangeReason, type Placement, type ShiftOptions, type UseDismissProps, type UseFloatingReturn, type UseHoverProps, type UseInteractionsReturn, type UseListNavigationProps, type UseTransitionStylesProps } from '@floating-ui/react';
3
3
  export type PopoverProps = {
4
4
  children: ReactNode;
5
5
  } & PopoverOptions;
@@ -10,6 +10,8 @@ type SharedMiddlewareConfig = {
10
10
  export type OffsetConfig = SharedMiddlewareConfig & Exclude<OffsetOptions, number>;
11
11
  export type FlipConfig = SharedMiddlewareConfig & FlipOptions;
12
12
  export type ShiftConfig = SharedMiddlewareConfig & ShiftOptions;
13
+ export type HoverConfig = Omit<UseHoverProps, 'enabled'>;
14
+ export type DelayConfig = Delay;
13
15
  export type PopoverOptions = {
14
16
  initialOpen?: boolean;
15
17
  placement?: Placement;
@@ -26,6 +28,8 @@ export type PopoverOptions = {
26
28
  offsetConfig?: OffsetConfig;
27
29
  flipConfig?: FlipConfig;
28
30
  shiftConfig?: ShiftConfig;
31
+ hoverConfig?: HoverConfig;
32
+ arrowConfig?: Omit<ArrowOptions, 'element'>;
29
33
  dismissConfig?: UseDismissProps;
30
34
  listNavigationConfig?: UseListNavigationProps;
31
35
  trigger?: PopoverTriggerType | PopoverTriggerType[];
@@ -56,5 +60,9 @@ export type UsePopoverReturn = Omit<UseFloatingReturn, 'open'> & UseInteractions
56
60
  zIndex?: number;
57
61
  returnFocus?: boolean;
58
62
  componentId?: string;
63
+ arrowRef: RefObject<HTMLElement>;
59
64
  };
65
+ export type LegacyDropdownPlacement = Exclude<LegacyPlacement, 'right' | 'left' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom'>;
66
+ export type LegacyPopconfirmPlacement = LegacyPlacement;
67
+ export type LegacyPlacement = 'topLeft' | 'top' | 'topCenter' | 'topRight' | 'bottomLeft' | 'bottom' | 'bottomCenter' | 'bottomRight' | 'right' | 'left' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
60
68
  export {};
@@ -0,0 +1,6 @@
1
+ import { type ReactElement } from 'react';
2
+ import { type Placement } from '@floating-ui/react';
3
+ export declare const PopoverArrow: ({ children, getClassNameFromPlacement, }: {
4
+ children?: ReactElement;
5
+ getClassNameFromPlacement?: (placement: Placement) => string;
6
+ }) => ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
@@ -0,0 +1,31 @@
1
+ import classNames from 'classnames';
2
+ import { cloneElement, isValidElement } from 'react';
3
+ import { useTheme } from '@synerise/ds-core';
4
+ import { usePopoverContext } from '../hooks';
5
+ export var PopoverArrow = function PopoverArrow(_ref) {
6
+ var children = _ref.children,
7
+ getClassNameFromPlacement = _ref.getClassNameFromPlacement;
8
+ var theme = useTheme();
9
+ var _usePopoverContext = usePopoverContext(),
10
+ arrowRef = _usePopoverContext.arrowRef,
11
+ placement = _usePopoverContext.placement,
12
+ zIndex = _usePopoverContext.zIndex,
13
+ middlewareData = _usePopoverContext.middlewareData;
14
+ var placementClassName = (getClassNameFromPlacement == null ? void 0 : getClassNameFromPlacement(placement)) || "ds-popover-arrow-" + placement;
15
+ if (/*#__PURE__*/isValidElement(children)) {
16
+ var _children$props, _middlewareData$arrow, _middlewareData$arrow2;
17
+ return /*#__PURE__*/cloneElement(children, {
18
+ // @ts-expect-error ref unknown
19
+ ref: arrowRef,
20
+ // @ts-expect-error props.className may not exist
21
+ className: classNames(placementClassName, (_children$props = children.props) == null ? void 0 : _children$props.className),
22
+ style: {
23
+ zIndex: zIndex !== undefined ? "" + zIndex : theme.variables['zindex-dropdown'],
24
+ position: 'absolute',
25
+ left: (_middlewareData$arrow = middlewareData.arrow) == null ? void 0 : _middlewareData$arrow.x,
26
+ top: (_middlewareData$arrow2 = middlewareData.arrow) == null ? void 0 : _middlewareData$arrow2.y
27
+ }
28
+ });
29
+ }
30
+ return children;
31
+ };
@@ -5,6 +5,7 @@ import React, { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
5
5
  import { FloatingFocusManager, FloatingPortal, useMergeRefs } from '@floating-ui/react';
6
6
  import { useTheme } from '@synerise/ds-core';
7
7
  import { usePopoverContext } from '../hooks/usePopoverContext';
8
+ import { GlobalStyles } from './PopoverContent.styles';
8
9
  export var PopoverContent = /*#__PURE__*/forwardRef(function PopoverContent(_ref, propRef) {
9
10
  var style = _ref.style,
10
11
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
@@ -54,7 +55,7 @@ export var PopoverContent = /*#__PURE__*/forwardRef(function PopoverContent(_ref
54
55
  }
55
56
  return /*#__PURE__*/React.createElement(FloatingPortal, {
56
57
  root: getPopupContainer ? popupContainerRef : undefined
57
- }, /*#__PURE__*/React.createElement(FloatingFocusManager, {
58
+ }, /*#__PURE__*/React.createElement(GlobalStyles, null), /*#__PURE__*/React.createElement(FloatingFocusManager, {
58
59
  initialFocus: -1,
59
60
  context: floatingContext,
60
61
  modal: modal,
@@ -0,0 +1 @@
1
+ export declare const GlobalStyles: import("styled-components").GlobalStyleComponent<{}, import("styled-components").DefaultTheme>;
@@ -0,0 +1,2 @@
1
+ import { createGlobalStyle } from 'styled-components';
2
+ export var GlobalStyles = createGlobalStyle(["[data-popover-trigger] ~ span[aria-hidden],div[data-floating-ui-portal]{display:contents;}"]);
@@ -13,11 +13,13 @@ export var PopoverTrigger = /*#__PURE__*/forwardRef(function (_ref, propRef) {
13
13
  var context = usePopoverContext();
14
14
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
15
  var childrenRef = children.ref;
16
- var ref = useMergeRefs([context.refs.setReference, propRef, childrenRef]);
16
+ var renderAsChild = asChild && /*#__PURE__*/isValidElement(children);
17
+ var refsArray = [propRef, childrenRef, !renderAsChild && context.refs.setReference];
18
+ var ref = useMergeRefs(refsArray.filter(Boolean));
17
19
  // `asChild` allows the user to pass any element as the anchor
18
20
  // if the child is a component it needs to forward the ref to a html element
19
21
  // so that the Popover can position itself correctly.
20
- if (asChild && /*#__PURE__*/isValidElement(children)) {
22
+ if (renderAsChild) {
21
23
  var referenceProps = context.getReferenceProps(_extends({
22
24
  ref: ref,
23
25
  'data-popover-trigger': true,
@@ -25,7 +27,14 @@ export var PopoverTrigger = /*#__PURE__*/forwardRef(function (_ref, propRef) {
25
27
  }, props, children.props, {
26
28
  'data-state': context.open ? 'open' : 'closed'
27
29
  }));
28
- return /*#__PURE__*/cloneElement(children, _extends({}, referenceProps));
30
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(S.TriggerAnchor, {
31
+ "aria-hidden": "true",
32
+ hidden: true,
33
+ ref: function ref(node) {
34
+ // TODO - skip any TriggerAnchors .....
35
+ context.refs.setReference((node == null ? void 0 : node.nextElementSibling) || null);
36
+ }
37
+ }), /*#__PURE__*/cloneElement(children, _extends({}, referenceProps)));
29
38
  }
30
39
  return /*#__PURE__*/React.createElement(S.Trigger, _extends({
31
40
  ref: ref
@@ -1 +1,2 @@
1
1
  export declare const Trigger: import("styled-components").StyledComponent<"span", any, {}, never>;
2
+ export declare const TriggerAnchor: import("styled-components").StyledComponent<"span", any, {}, never>;
@@ -2,4 +2,8 @@ import styled from 'styled-components';
2
2
  export var Trigger = styled.span.withConfig({
3
3
  displayName: "PopoverTriggerstyles__Trigger",
4
4
  componentId: "sc-1irht31-0"
5
- })(["display:flex;"]);
5
+ })(["display:flex;"]);
6
+ export var TriggerAnchor = styled.span.withConfig({
7
+ displayName: "PopoverTriggerstyles__TriggerAnchor",
8
+ componentId: "sc-1irht31-1"
9
+ })(["display:contents !important;"]);
@@ -1,3 +1,4 @@
1
1
  export * from './PopoverTrigger';
2
2
  export * from './PopoverClose';
3
3
  export * from './PopoverContent';
4
+ export * from './PopoverArrow';
@@ -1,3 +1,4 @@
1
1
  export * from './PopoverTrigger';
2
2
  export * from './PopoverClose';
3
- export * from './PopoverContent';
3
+ export * from './PopoverContent';
4
+ export * from './PopoverArrow';
@@ -1,2 +1,2 @@
1
1
  import { type PopoverOptions, type UsePopoverReturn } from '../Popover.types';
2
- export declare const usePopover: ({ initialOpen, placement, modal, trigger, open: controlledOpen, onOpenChange: setControlledOpen, onDismiss, transitionDuration, getPopupContainer, autoUpdate: autoUpdateWhileMounted, dismissConfig, offsetConfig, flipConfig, shiftConfig, testId, componentId, returnFocus, listNavigationConfig, getTransitionConfig, zIndex, }?: PopoverOptions) => UsePopoverReturn;
2
+ export declare const usePopover: ({ initialOpen, placement, modal, trigger, open: controlledOpen, onOpenChange: setControlledOpen, onDismiss, transitionDuration, getPopupContainer, autoUpdate: autoUpdateWhileMounted, dismissConfig, offsetConfig, flipConfig, shiftConfig, arrowConfig, hoverConfig, testId, componentId, returnFocus, listNavigationConfig, getTransitionConfig, zIndex, }?: PopoverOptions) => UsePopoverReturn;
@@ -1,6 +1,6 @@
1
1
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
- import { useMemo, useState } from 'react';
3
- import { autoUpdate, useClick, useDismiss, useFloating, useHover, useInteractions, useListNavigation, useRole, useTransitionStyles } from '@floating-ui/react';
2
+ import { useMemo, useRef, useState } from 'react';
3
+ import { autoUpdate, useClick, useDelayGroup, useDismiss, useFloating, useHover, useInteractions, useListNavigation, useRole, useTransitionStyles } from '@floating-ui/react';
4
4
  import { HOVER_CLOSE_DELAY, HOVER_OPEN_DELAY } from '../Popover.const';
5
5
  import { getDefaultTransitionConfig, getMiddleware } from '../utils';
6
6
  import { useListNavigationConfig } from './useListNavigationConfig';
@@ -27,6 +27,10 @@ export var usePopover = function usePopover(_temp) {
27
27
  flipConfig = _ref$flipConfig === void 0 ? {} : _ref$flipConfig,
28
28
  _ref$shiftConfig = _ref.shiftConfig,
29
29
  shiftConfig = _ref$shiftConfig === void 0 ? {} : _ref$shiftConfig,
30
+ _ref$arrowConfig = _ref.arrowConfig,
31
+ arrowConfig = _ref$arrowConfig === void 0 ? {} : _ref$arrowConfig,
32
+ _ref$hoverConfig = _ref.hoverConfig,
33
+ hoverConfig = _ref$hoverConfig === void 0 ? {} : _ref$hoverConfig,
30
34
  _ref$testId = _ref.testId,
31
35
  testId = _ref$testId === void 0 ? 'noTestId' : _ref$testId,
32
36
  componentId = _ref.componentId,
@@ -46,6 +50,7 @@ export var usePopover = function usePopover(_temp) {
46
50
  setDescriptionId = _useState3[1];
47
51
  var open = controlledOpen != null ? controlledOpen : uncontrolledOpen;
48
52
  var setOpen = setControlledOpen != null ? setControlledOpen : setUncontrolledOpen;
53
+ var arrowRef = useRef(null);
49
54
  var triggerArray = Array.isArray(trigger) ? trigger : [trigger];
50
55
  var whileElementsMounted = useMemo(function () {
51
56
  if (!autoUpdateWhileMounted) {
@@ -72,7 +77,10 @@ export var usePopover = function usePopover(_temp) {
72
77
  middleware: getMiddleware({
73
78
  offsetConfig: offsetConfig,
74
79
  flipConfig: flipConfig,
75
- shiftConfig: shiftConfig
80
+ shiftConfig: shiftConfig,
81
+ arrowConfig: _extends({}, arrowConfig, {
82
+ element: arrowRef.current
83
+ })
76
84
  })
77
85
  });
78
86
  var context = data.context;
@@ -83,13 +91,15 @@ export var usePopover = function usePopover(_temp) {
83
91
  var click = useClick(context, {
84
92
  enabled: isClickEnabled && controlledOpen === undefined
85
93
  });
86
- var hover = useHover(context, {
94
+ var _useDelayGroup = useDelayGroup(context),
95
+ delay = _useDelayGroup.delay;
96
+ var hover = useHover(context, _extends({
87
97
  enabled: isHoverEnabled,
88
- delay: {
98
+ delay: delay || {
89
99
  open: HOVER_OPEN_DELAY,
90
100
  close: HOVER_CLOSE_DELAY
91
101
  }
92
- });
102
+ }, hoverConfig));
93
103
  var dismiss = useDismiss(context, dismissConfig);
94
104
  var role = useRole(context);
95
105
  var interactions = useInteractions([click, hover, dismiss, role, listNav]);
@@ -113,7 +123,8 @@ export var usePopover = function usePopover(_temp) {
113
123
  testId: testId,
114
124
  zIndex: zIndex,
115
125
  returnFocus: returnFocus,
116
- componentId: componentId
126
+ componentId: componentId,
127
+ arrowRef: arrowRef
117
128
  });
118
129
  }, [getPopupContainer, isMounted, setOpen, transitionDuration, styles, interactions, data, modal, labelId, descriptionId, zIndex, testId, returnFocus, componentId]);
119
130
  };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export * from './Popover';
2
2
  export * from './components';
3
3
  export { Popover as default } from './Popover';
4
+ export { FloatingDelayGroup } from '@floating-ui/react';
4
5
  export * from './Popover.types';
6
+ export { getPlacement } from './utils/getPlacement';
7
+ export { PLACEMENT_MAP } from './Popover.const';
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  export * from './Popover';
2
2
  export * from './components';
3
3
  export { Popover as default } from './Popover';
4
- export * from './Popover.types';
4
+ export { FloatingDelayGroup } from '@floating-ui/react';
5
+ export * from './Popover.types';
6
+ export { getPlacement } from './utils/getPlacement';
7
+ export { PLACEMENT_MAP } from './Popover.const';
@@ -1,10 +1,12 @@
1
+ import { type ArrowOptions } from '@floating-ui/react';
1
2
  import { type FlipConfig, type OffsetConfig, type ShiftConfig } from '../Popover.types';
2
3
  type GetMiddleware = {
3
4
  offsetConfig: OffsetConfig;
4
5
  flipConfig: FlipConfig;
5
6
  shiftConfig: ShiftConfig;
7
+ arrowConfig?: ArrowOptions;
6
8
  };
7
- export declare const getMiddleware: ({ offsetConfig, flipConfig, shiftConfig, }: GetMiddleware) => {
9
+ export declare const getMiddleware: ({ offsetConfig, flipConfig, shiftConfig, arrowConfig, }: GetMiddleware) => {
8
10
  name: string;
9
11
  options?: any;
10
12
  fn: (state: import("@floating-ui/react").MiddlewareState) => import("@floating-ui/react").MiddlewareReturn | Promise<import("@floating-ui/react").MiddlewareReturn>;
@@ -2,11 +2,12 @@ var _excluded = ["enabled"],
2
2
  _excluded2 = ["enabled"],
3
3
  _excluded3 = ["enabled"];
4
4
  function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
5
- import { flip, offset, shift } from '@floating-ui/react';
5
+ import { arrow, flip, offset, shift } from '@floating-ui/react';
6
6
  export var getMiddleware = function getMiddleware(_ref) {
7
7
  var offsetConfig = _ref.offsetConfig,
8
8
  flipConfig = _ref.flipConfig,
9
- shiftConfig = _ref.shiftConfig;
9
+ shiftConfig = _ref.shiftConfig,
10
+ arrowConfig = _ref.arrowConfig;
10
11
  var middleware = [];
11
12
  var _ref2 = offsetConfig || {},
12
13
  _ref2$enabled = _ref2.enabled,
@@ -29,5 +30,8 @@ export var getMiddleware = function getMiddleware(_ref) {
29
30
  if (shiftEnabled) {
30
31
  middleware.push(shift(shiftOptions));
31
32
  }
33
+ if (arrowConfig != null && arrowConfig.element) {
34
+ middleware.push(arrow(arrowConfig));
35
+ }
32
36
  return middleware;
33
37
  };
@@ -0,0 +1,3 @@
1
+ import { type Placement } from '@floating-ui/react';
2
+ import { type LegacyPlacement } from '../Popover.types';
3
+ export declare const getPlacement: (placement: LegacyPlacement) => Placement;
@@ -0,0 +1,4 @@
1
+ import { PLACEMENT_MAP } from '../Popover.const';
2
+ export var getPlacement = function getPlacement(placement) {
3
+ return PLACEMENT_MAP[placement];
4
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-popover",
3
- "version": "1.1.2",
3
+ "version": "1.3.0",
4
4
  "description": "Popover UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -34,14 +34,16 @@
34
34
  ],
35
35
  "types": "dist/index.d.ts",
36
36
  "dependencies": {
37
- "@floating-ui/react": "^0.27.16"
37
+ "@floating-ui/react": "^0.27.16",
38
+ "classnames": "^2.5.1"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@testing-library/user-event": "^14"
41
42
  },
42
43
  "peerDependencies": {
43
44
  "@synerise/ds-core": "*",
44
- "react": ">=16.9.0 <= 18.3.1"
45
+ "react": ">=16.9.0 <= 18.3.1",
46
+ "styled-components": "^5.3.3"
45
47
  },
46
- "gitHead": "b1279d5354132a2bf0b6f0cfa343db4c6c928f72"
48
+ "gitHead": "db758824923a2a231a0de460f0d6d10739514cda"
47
49
  }