@impulse-ui-native/popover 6.3.0 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -57,7 +57,7 @@ The convenience form assembles Trigger and Content:
57
57
  - `surface` selects elevated (default) or inverse appearance for Popover. Tooltip uses inverse. Override `components.popover` on ThemeProvider for shared geometry, typography, and surface styling.
58
58
  - Elevated content defaults to 320dp wide; inverse hints size to their content. Both are constrained to the available host width. Content spacing and width can be customized with primitive style props or `style`.
59
59
  - Anchors and host bounds are measured on opening and polled every 100ms while open, following scrolling and layout changes. Only one measurement is in flight; slow native callbacks are allowed to finish. Closed overlays have no measurement timer. Content stays hidden until measured and when its anchor is outside the usable host bounds.
60
- - Collision handling flips to the opposite side when it has more space, then shifts into safe-area bounds. The arrow tracks the anchor and hides if a constrained panel cannot point accurately. Extremely large content can overlap the anchor after clamping.
60
+ - Popover and Tooltip use rounded panels without arrows. Collision handling flips to the opposite side when it has more space, then shifts into safe-area bounds. Extremely large content can overlap the anchor after clamping.
61
61
 
62
62
  ## Exports and verification
63
63
 
@@ -4,7 +4,6 @@ import { StyleSheet } from "react-native";
4
4
  import { Pressable, View } from "@impulse-ui-native/primitives";
5
5
  import { useStyleProps, useThemedStyles } from "@impulse-ui-native/theme";
6
6
  import { usePopoverSurface } from "../hooks/use-popover-surface.hook";
7
- import { getArrowStyle } from "../utils/popover-position.utils";
8
7
  const PopoverSurfaceView = memo(function PopoverSurfaceView2({
9
8
  children,
10
9
  style,
@@ -27,7 +26,7 @@ const PopoverSurfaceView = memo(function PopoverSurfaceView2({
27
26
  style: styles.host,
28
27
  children: [
29
28
  /* @__PURE__ */ jsx(Pressable, { style: StyleSheet.absoluteFill, onPress: close }),
30
- /* @__PURE__ */ jsxs(
29
+ /* @__PURE__ */ jsx(
31
30
  View,
32
31
  {
33
32
  shadow: "sm",
@@ -35,10 +34,7 @@ const PopoverSurfaceView = memo(function PopoverSurfaceView2({
35
34
  pointerEvents: styleProps.ready ? "auto" : "none",
36
35
  style: panelStyle,
37
36
  onLayout: handleLayout,
38
- children: [
39
- children,
40
- styleProps.ready && styleProps.position?.showArrow ? /* @__PURE__ */ jsx(View, { pointerEvents: "none", style: styles.arrow }) : null
41
- ]
37
+ children
42
38
  }
43
39
  )
44
40
  ]
@@ -66,16 +62,6 @@ function themedStyles(theme, { surface, bounds, host, position, ready }) {
66
62
  paddingHorizontal: appearance.paddingHorizontal,
67
63
  paddingVertical: appearance.paddingVertical,
68
64
  gap: tokens.gap
69
- },
70
- arrow: {
71
- position: "absolute",
72
- ...position ? getArrowStyle(
73
- position,
74
- tokens.arrowSize,
75
- appearance.value,
76
- appearance.borderWidth,
77
- appearance.borderColor
78
- ) : {}
79
65
  }
80
66
  });
81
67
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/popover-surface.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { Pressable, View } from \"@impulse-ui-native/primitives\";\nimport { useStyleProps, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { PopoverContentProps } from \"../types\";\nimport type { PopoverSurfaceStyleProps } from \"../types/popover.types\";\nimport { usePopoverSurface } from \"../hooks/use-popover-surface.hook\";\nimport { getArrowStyle } from \"../utils/popover-position.utils\";\n\nexport const PopoverSurfaceView = memo(function PopoverSurfaceView({\n children,\n style,\n onLayout,\n ...props\n}: PopoverContentProps) {\n const { hostRef, styleProps, close, handleLayout } =\n usePopoverSurface(onLayout);\n\n const extractedStyleProps = useStyleProps(props);\n const styles = useThemedStyles(themedStyles, styleProps, [styleProps]);\n\n const panelStyle = useMemo(\n () => [styles.panel, extractedStyleProps, style, styles.position],\n [styles.panel, extractedStyleProps, style, styles.position],\n );\n\n return (\n <View\n ref={hostRef}\n collapsable={false}\n pointerEvents=\"box-none\"\n style={styles.host}\n >\n <Pressable style={StyleSheet.absoluteFill} onPress={close} />\n <View\n shadow=\"sm\"\n {...props}\n pointerEvents={styleProps.ready ? \"auto\" : \"none\"}\n style={panelStyle}\n onLayout={handleLayout}\n >\n {children}\n {styleProps.ready && styleProps.position?.showArrow ? (\n <View pointerEvents=\"none\" style={styles.arrow} />\n ) : null}\n </View>\n </View>\n );\n});\n\nfunction themedStyles(\n theme: AppTheme,\n { surface, bounds, host, position, ready }: PopoverSurfaceStyleProps,\n) {\n const tokens = theme.components.popover;\n const appearance = tokens.surfaces[surface];\n\n return StyleSheet.create({\n host: { ...StyleSheet.absoluteFill, zIndex: tokens.zIndexBase },\n\n position: {\n position: \"absolute\",\n left: (position?.x ?? bounds.x) - (host?.x ?? 0),\n top: (position?.y ?? bounds.y) - (host?.y ?? 0),\n maxWidth: Math.min(tokens.maxWidth, bounds.width),\n opacity: ready ? 1 : 0,\n },\n\n panel: {\n width: surface === \"elevated\" ? tokens.maxWidth : undefined,\n backgroundColor: appearance.value,\n borderColor: appearance.borderColor,\n borderWidth: appearance.borderWidth,\n borderRadius: appearance.borderRadius,\n paddingHorizontal: appearance.paddingHorizontal,\n paddingVertical: appearance.paddingVertical,\n gap: tokens.gap,\n },\n\n arrow: {\n position: \"absolute\",\n ...(position\n ? getArrowStyle(\n position,\n tokens.arrowSize,\n appearance.value,\n appearance.borderWidth,\n appearance.borderColor,\n )\n : {}),\n },\n });\n}\n"],"mappings":"AAoCM,cACA,YADA;AApCN,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,WAAW,YAAY;AAChC,SAAS,eAAe,uBAAuB;AAI/C,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAEvB,MAAM,qBAAqB,KAAK,SAASA,oBAAmB;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwB;AACtB,QAAM,EAAE,SAAS,YAAY,OAAO,aAAa,IAC/C,kBAAkB,QAAQ;AAE5B,QAAM,sBAAsB,cAAc,KAAK;AAC/C,QAAM,SAAS,gBAAgB,cAAc,YAAY,CAAC,UAAU,CAAC;AAErE,QAAM,aAAa;AAAA,IACjB,MAAM,CAAC,OAAO,OAAO,qBAAqB,OAAO,OAAO,QAAQ;AAAA,IAChE,CAAC,OAAO,OAAO,qBAAqB,OAAO,OAAO,QAAQ;AAAA,EAC5D;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,aAAa;AAAA,MACb,eAAc;AAAA,MACd,OAAO,OAAO;AAAA,MAEd;AAAA,4BAAC,aAAU,OAAO,WAAW,cAAc,SAAS,OAAO;AAAA,QAC3D;AAAA,UAAC;AAAA;AAAA,YACC,QAAO;AAAA,YACN,GAAG;AAAA,YACJ,eAAe,WAAW,QAAQ,SAAS;AAAA,YAC3C,OAAO;AAAA,YACP,UAAU;AAAA,YAET;AAAA;AAAA,cACA,WAAW,SAAS,WAAW,UAAU,YACxC,oBAAC,QAAK,eAAc,QAAO,OAAO,OAAO,OAAO,IAC9C;AAAA;AAAA;AAAA,QACN;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;AAED,SAAS,aACP,OACA,EAAE,SAAS,QAAQ,MAAM,UAAU,MAAM,GACzC;AACA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,aAAa,OAAO,SAAS,OAAO;AAE1C,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM,EAAE,GAAG,WAAW,cAAc,QAAQ,OAAO,WAAW;AAAA,IAE9D,UAAU;AAAA,MACR,UAAU;AAAA,MACV,OAAO,UAAU,KAAK,OAAO,MAAM,MAAM,KAAK;AAAA,MAC9C,MAAM,UAAU,KAAK,OAAO,MAAM,MAAM,KAAK;AAAA,MAC7C,UAAU,KAAK,IAAI,OAAO,UAAU,OAAO,KAAK;AAAA,MAChD,SAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,IAEA,OAAO;AAAA,MACL,OAAO,YAAY,aAAa,OAAO,WAAW;AAAA,MAClD,iBAAiB,WAAW;AAAA,MAC5B,aAAa,WAAW;AAAA,MACxB,aAAa,WAAW;AAAA,MACxB,cAAc,WAAW;AAAA,MACzB,mBAAmB,WAAW;AAAA,MAC9B,iBAAiB,WAAW;AAAA,MAC5B,KAAK,OAAO;AAAA,IACd;AAAA,IAEA,OAAO;AAAA,MACL,UAAU;AAAA,MACV,GAAI,WACA;AAAA,QACE;AAAA,QACA,OAAO;AAAA,QACP,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,MACb,IACA,CAAC;AAAA,IACP;AAAA,EACF,CAAC;AACH;","names":["PopoverSurfaceView"]}
1
+ {"version":3,"sources":["../../src/components/popover-surface.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { Pressable, View } from \"@impulse-ui-native/primitives\";\nimport { useStyleProps, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { PopoverContentProps } from \"../types\";\nimport type { PopoverSurfaceStyleProps } from \"../types/popover.types\";\nimport { usePopoverSurface } from \"../hooks/use-popover-surface.hook\";\n\nexport const PopoverSurfaceView = memo(function PopoverSurfaceView({\n children,\n style,\n onLayout,\n ...props\n}: PopoverContentProps) {\n const { hostRef, styleProps, close, handleLayout } =\n usePopoverSurface(onLayout);\n\n const extractedStyleProps = useStyleProps(props);\n const styles = useThemedStyles(themedStyles, styleProps, [styleProps]);\n\n const panelStyle = useMemo(\n () => [styles.panel, extractedStyleProps, style, styles.position],\n [styles.panel, extractedStyleProps, style, styles.position],\n );\n\n return (\n <View\n ref={hostRef}\n collapsable={false}\n pointerEvents=\"box-none\"\n style={styles.host}\n >\n <Pressable style={StyleSheet.absoluteFill} onPress={close} />\n <View\n shadow=\"sm\"\n {...props}\n pointerEvents={styleProps.ready ? \"auto\" : \"none\"}\n style={panelStyle}\n onLayout={handleLayout}\n >\n {children}\n </View>\n </View>\n );\n});\n\nfunction themedStyles(\n theme: AppTheme,\n { surface, bounds, host, position, ready }: PopoverSurfaceStyleProps,\n) {\n const tokens = theme.components.popover;\n const appearance = tokens.surfaces[surface];\n\n return StyleSheet.create({\n host: { ...StyleSheet.absoluteFill, zIndex: tokens.zIndexBase },\n\n position: {\n position: \"absolute\",\n left: (position?.x ?? bounds.x) - (host?.x ?? 0),\n top: (position?.y ?? bounds.y) - (host?.y ?? 0),\n maxWidth: Math.min(tokens.maxWidth, bounds.width),\n opacity: ready ? 1 : 0,\n },\n\n panel: {\n width: surface === \"elevated\" ? tokens.maxWidth : undefined,\n backgroundColor: appearance.value,\n borderColor: appearance.borderColor,\n borderWidth: appearance.borderWidth,\n borderRadius: appearance.borderRadius,\n paddingHorizontal: appearance.paddingHorizontal,\n paddingVertical: appearance.paddingVertical,\n gap: tokens.gap,\n },\n });\n}\n"],"mappings":"AA6BI,SAME,KANF;AA7BJ,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,WAAW,YAAY;AAChC,SAAS,eAAe,uBAAuB;AAI/C,SAAS,yBAAyB;AAE3B,MAAM,qBAAqB,KAAK,SAASA,oBAAmB;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwB;AACtB,QAAM,EAAE,SAAS,YAAY,OAAO,aAAa,IAC/C,kBAAkB,QAAQ;AAE5B,QAAM,sBAAsB,cAAc,KAAK;AAC/C,QAAM,SAAS,gBAAgB,cAAc,YAAY,CAAC,UAAU,CAAC;AAErE,QAAM,aAAa;AAAA,IACjB,MAAM,CAAC,OAAO,OAAO,qBAAqB,OAAO,OAAO,QAAQ;AAAA,IAChE,CAAC,OAAO,OAAO,qBAAqB,OAAO,OAAO,QAAQ;AAAA,EAC5D;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,aAAa;AAAA,MACb,eAAc;AAAA,MACd,OAAO,OAAO;AAAA,MAEd;AAAA,4BAAC,aAAU,OAAO,WAAW,cAAc,SAAS,OAAO;AAAA,QAC3D;AAAA,UAAC;AAAA;AAAA,YACC,QAAO;AAAA,YACN,GAAG;AAAA,YACJ,eAAe,WAAW,QAAQ,SAAS;AAAA,YAC3C,OAAO;AAAA,YACP,UAAU;AAAA,YAET;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;AAED,SAAS,aACP,OACA,EAAE,SAAS,QAAQ,MAAM,UAAU,MAAM,GACzC;AACA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,aAAa,OAAO,SAAS,OAAO;AAE1C,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM,EAAE,GAAG,WAAW,cAAc,QAAQ,OAAO,WAAW;AAAA,IAE9D,UAAU;AAAA,MACR,UAAU;AAAA,MACV,OAAO,UAAU,KAAK,OAAO,MAAM,MAAM,KAAK;AAAA,MAC9C,MAAM,UAAU,KAAK,OAAO,MAAM,MAAM,KAAK;AAAA,MAC7C,UAAU,KAAK,IAAI,OAAO,UAAU,OAAO,KAAK;AAAA,MAChD,SAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,IAEA,OAAO;AAAA,MACL,OAAO,YAAY,aAAa,OAAO,WAAW;AAAA,MAClD,iBAAiB,WAAW;AAAA,MAC5B,aAAa,WAAW;AAAA,MACxB,aAAa,WAAW;AAAA,MACxB,cAAc,WAAW;AAAA,MACzB,mBAAmB,WAAW;AAAA,MAC9B,iBAAiB,WAAW;AAAA,MAC5B,KAAK,OAAO;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["PopoverSurfaceView"]}
@@ -16,10 +16,9 @@ function usePopoverSurface(onLayout) {
16
16
  bounds,
17
17
  ...size,
18
18
  placement,
19
- gap: tokens.gap,
20
- arrowInset: tokens.surfaces[surface].borderRadius + tokens.arrowSize
19
+ gap: tokens.gap
21
20
  }) : null,
22
- [measurement, bounds, size, placement, surface, tokens]
21
+ [measurement, bounds, size, placement, tokens.gap]
23
22
  );
24
23
  const ready = visible && size.width > 0 && size.height > 0;
25
24
  const styleProps = useMemo(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/use-popover-surface.hook.ts"],"sourcesContent":["import type { LayoutChangeEvent, View } from \"react-native\";\nimport { useMemo, useRef, useState } from \"react\";\n\nimport { useBackHandler, useEventCallback } from \"@impulse-ui-native/core\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { PopoverContentProps } from \"../types\";\nimport type { PopoverSurfaceStyleProps } from \"../types/popover.types\";\nimport { getPopoverPosition } from \"../utils/popover-position.utils\";\nimport { usePopoverContext } from \"./use-popover-context.hook\";\nimport { usePopoverPosition } from \"./use-popover-position.hook\";\n\nexport function usePopoverSurface(onLayout: PopoverContentProps[\"onLayout\"]) {\n const { surface, placement, setOpen } = usePopoverContext();\n\n const [size, setSize] = useState({ width: 0, height: 0 });\n const hostRef = useRef<View>(null);\n\n const tokens = useComponentsTokens().popover;\n const { measurement, bounds, visible } = usePopoverPosition(hostRef);\n\n const position = useMemo(\n () =>\n measurement\n ? getPopoverPosition({\n anchor: measurement.anchor,\n bounds,\n ...size,\n placement,\n gap: tokens.gap,\n arrowInset:\n tokens.surfaces[surface].borderRadius + tokens.arrowSize,\n })\n : null,\n [measurement, bounds, size, placement, surface, tokens],\n );\n\n const ready = visible && size.width > 0 && size.height > 0;\n const styleProps = useMemo<PopoverSurfaceStyleProps>(\n () => ({ surface, bounds, host: measurement?.host, position, ready }),\n [surface, bounds, measurement?.host, position, ready],\n );\n\n const close = useEventCallback(() => setOpen(false));\n\n const handleLayout = useEventCallback((event: LayoutChangeEvent) => {\n const { width, height } = event.nativeEvent.layout;\n\n setSize((previous) =>\n previous.width === width && previous.height === height\n ? previous\n : { width, height },\n );\n\n onLayout?.(event);\n });\n\n useBackHandler(() => {\n close();\n\n return true;\n });\n\n return { hostRef, styleProps, close, handleLayout };\n}\n"],"mappings":"AACA,SAAS,SAAS,QAAQ,gBAAgB;AAE1C,SAAS,gBAAgB,wBAAwB;AACjD,SAAS,2BAA2B;AAIpC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AAE5B,SAAS,kBAAkB,UAA2C;AAC3E,QAAM,EAAE,SAAS,WAAW,QAAQ,IAAI,kBAAkB;AAE1D,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AACxD,QAAM,UAAU,OAAa,IAAI;AAEjC,QAAM,SAAS,oBAAoB,EAAE;AACrC,QAAM,EAAE,aAAa,QAAQ,QAAQ,IAAI,mBAAmB,OAAO;AAEnE,QAAM,WAAW;AAAA,IACf,MACE,cACI,mBAAmB;AAAA,MACjB,QAAQ,YAAY;AAAA,MACpB;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA,KAAK,OAAO;AAAA,MACZ,YACE,OAAO,SAAS,OAAO,EAAE,eAAe,OAAO;AAAA,IACnD,CAAC,IACD;AAAA,IACN,CAAC,aAAa,QAAQ,MAAM,WAAW,SAAS,MAAM;AAAA,EACxD;AAEA,QAAM,QAAQ,WAAW,KAAK,QAAQ,KAAK,KAAK,SAAS;AACzD,QAAM,aAAa;AAAA,IACjB,OAAO,EAAE,SAAS,QAAQ,MAAM,aAAa,MAAM,UAAU,MAAM;AAAA,IACnE,CAAC,SAAS,QAAQ,aAAa,MAAM,UAAU,KAAK;AAAA,EACtD;AAEA,QAAM,QAAQ,iBAAiB,MAAM,QAAQ,KAAK,CAAC;AAEnD,QAAM,eAAe,iBAAiB,CAAC,UAA6B;AAClE,UAAM,EAAE,OAAO,OAAO,IAAI,MAAM,YAAY;AAE5C;AAAA,MAAQ,CAAC,aACP,SAAS,UAAU,SAAS,SAAS,WAAW,SAC5C,WACA,EAAE,OAAO,OAAO;AAAA,IACtB;AAEA,eAAW,KAAK;AAAA,EAClB,CAAC;AAED,iBAAe,MAAM;AACnB,UAAM;AAEN,WAAO;AAAA,EACT,CAAC;AAED,SAAO,EAAE,SAAS,YAAY,OAAO,aAAa;AACpD;","names":[]}
1
+ {"version":3,"sources":["../../src/hooks/use-popover-surface.hook.ts"],"sourcesContent":["import type { LayoutChangeEvent, View } from \"react-native\";\nimport { useMemo, useRef, useState } from \"react\";\n\nimport { useBackHandler, useEventCallback } from \"@impulse-ui-native/core\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { PopoverContentProps } from \"../types\";\nimport type { PopoverSurfaceStyleProps } from \"../types/popover.types\";\nimport { getPopoverPosition } from \"../utils/popover-position.utils\";\nimport { usePopoverContext } from \"./use-popover-context.hook\";\nimport { usePopoverPosition } from \"./use-popover-position.hook\";\n\nexport function usePopoverSurface(onLayout: PopoverContentProps[\"onLayout\"]) {\n const { surface, placement, setOpen } = usePopoverContext();\n\n const [size, setSize] = useState({ width: 0, height: 0 });\n const hostRef = useRef<View>(null);\n\n const tokens = useComponentsTokens().popover;\n const { measurement, bounds, visible } = usePopoverPosition(hostRef);\n\n const position = useMemo(\n () =>\n measurement\n ? getPopoverPosition({\n anchor: measurement.anchor,\n bounds,\n ...size,\n placement,\n gap: tokens.gap,\n })\n : null,\n [measurement, bounds, size, placement, tokens.gap],\n );\n\n const ready = visible && size.width > 0 && size.height > 0;\n const styleProps = useMemo<PopoverSurfaceStyleProps>(\n () => ({ surface, bounds, host: measurement?.host, position, ready }),\n [surface, bounds, measurement?.host, position, ready],\n );\n\n const close = useEventCallback(() => setOpen(false));\n\n const handleLayout = useEventCallback((event: LayoutChangeEvent) => {\n const { width, height } = event.nativeEvent.layout;\n\n setSize((previous) =>\n previous.width === width && previous.height === height\n ? previous\n : { width, height },\n );\n\n onLayout?.(event);\n });\n\n useBackHandler(() => {\n close();\n\n return true;\n });\n\n return { hostRef, styleProps, close, handleLayout };\n}\n"],"mappings":"AACA,SAAS,SAAS,QAAQ,gBAAgB;AAE1C,SAAS,gBAAgB,wBAAwB;AACjD,SAAS,2BAA2B;AAIpC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AAE5B,SAAS,kBAAkB,UAA2C;AAC3E,QAAM,EAAE,SAAS,WAAW,QAAQ,IAAI,kBAAkB;AAE1D,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AACxD,QAAM,UAAU,OAAa,IAAI;AAEjC,QAAM,SAAS,oBAAoB,EAAE;AACrC,QAAM,EAAE,aAAa,QAAQ,QAAQ,IAAI,mBAAmB,OAAO;AAEnE,QAAM,WAAW;AAAA,IACf,MACE,cACI,mBAAmB;AAAA,MACjB,QAAQ,YAAY;AAAA,MACpB;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA,KAAK,OAAO;AAAA,IACd,CAAC,IACD;AAAA,IACN,CAAC,aAAa,QAAQ,MAAM,WAAW,OAAO,GAAG;AAAA,EACnD;AAEA,QAAM,QAAQ,WAAW,KAAK,QAAQ,KAAK,KAAK,SAAS;AACzD,QAAM,aAAa;AAAA,IACjB,OAAO,EAAE,SAAS,QAAQ,MAAM,aAAa,MAAM,UAAU,MAAM;AAAA,IACnE,CAAC,SAAS,QAAQ,aAAa,MAAM,UAAU,KAAK;AAAA,EACtD;AAEA,QAAM,QAAQ,iBAAiB,MAAM,QAAQ,KAAK,CAAC;AAEnD,QAAM,eAAe,iBAAiB,CAAC,UAA6B;AAClE,UAAM,EAAE,OAAO,OAAO,IAAI,MAAM,YAAY;AAE5C;AAAA,MAAQ,CAAC,aACP,SAAS,UAAU,SAAS,SAAS,WAAW,SAC5C,WACA,EAAE,OAAO,OAAO;AAAA,IACtB;AAEA,eAAW,KAAK;AAAA,EAClB,CAAC;AAED,iBAAe,MAAM;AACnB,UAAM;AAEN,WAAO;AAAA,EACT,CAAC;AAED,SAAO,EAAE,SAAS,YAAY,OAAO,aAAa;AACpD;","names":[]}
@@ -50,8 +50,6 @@ interface PopoverPosition {
50
50
  x: number;
51
51
  y: number;
52
52
  placement: PopoverPlacement;
53
- arrowOffset: number;
54
- showArrow: boolean;
55
53
  }
56
54
  interface PopoverPositionOptions {
57
55
  anchor: PopoverRect;
@@ -60,7 +58,6 @@ interface PopoverPositionOptions {
60
58
  height: number;
61
59
  placement: PopoverPlacement;
62
60
  gap: number;
63
- arrowInset: number;
64
61
  }
65
62
  interface PopoverSurfaceStyleProps {
66
63
  surface: PopoverSurface;
@@ -1,11 +1,10 @@
1
- import { ViewStyle } from 'react-native';
2
- import { PopoverRect, PopoverPosition, PopoverPositionOptions } from '../types/popover.types.mjs';
1
+ import { PopoverRect, PopoverPositionOptions, PopoverPosition } from '../types/popover.types.mjs';
3
2
  import 'react';
3
+ import 'react-native';
4
4
  import '@impulse-ui-native/primitives';
5
5
 
6
6
  declare function clamp(value: number, min: number, max: number): number;
7
7
  declare function equalRects(a: PopoverRect | null, b: PopoverRect): boolean;
8
- declare function getPopoverPosition({ anchor, bounds, width, height, placement: preferred, gap, arrowInset, }: PopoverPositionOptions): PopoverPosition;
9
- declare function getArrowStyle(position: PopoverPosition, size: number, color: string, borderWidth: number, borderColor: string): ViewStyle;
8
+ declare function getPopoverPosition({ anchor, bounds, width, height, placement: preferred, gap, }: PopoverPositionOptions): PopoverPosition;
10
9
 
11
- export { clamp, equalRects, getArrowStyle, getPopoverPosition };
10
+ export { clamp, equalRects, getPopoverPosition };
@@ -11,8 +11,7 @@ function getPopoverPosition({
11
11
  width,
12
12
  height,
13
13
  placement: preferred,
14
- gap,
15
- arrowInset
14
+ gap
16
15
  }) {
17
16
  const right = bounds.x + bounds.width;
18
17
  const bottom = bounds.y + bounds.height;
@@ -38,65 +37,11 @@ function getPopoverPosition({
38
37
  bounds.y,
39
38
  bottom - height
40
39
  );
41
- const edgeLength = vertical ? width : height;
42
- const inset = Math.min(arrowInset, edgeLength / 2);
43
- const offset = vertical ? centerX - x : centerY - y;
44
- const facing = placement === "top" ? y + height <= anchor.y : placement === "bottom" ? y >= anchor.y + anchor.height : placement === "left" ? x + width <= anchor.x : x >= anchor.x + anchor.width;
45
- return {
46
- x,
47
- y,
48
- placement,
49
- arrowOffset: clamp(offset, inset, edgeLength - inset),
50
- showArrow: facing && offset >= inset && offset <= edgeLength - inset
51
- };
52
- }
53
- function getArrowStyle(position, size, color, borderWidth, borderColor) {
54
- const side = size * Math.SQRT2;
55
- const offset = position.arrowOffset - borderWidth - side / 2;
56
- const edge = -(side + borderWidth) / 2;
57
- const shared = {
58
- width: side,
59
- height: side,
60
- backgroundColor: color,
61
- borderColor,
62
- transform: [{ rotate: "45deg" }],
63
- ...position.placement === "top" || position.placement === "bottom" ? { left: offset } : { top: offset }
64
- };
65
- switch (position.placement) {
66
- case "top":
67
- return {
68
- ...shared,
69
- bottom: edge,
70
- borderBottomWidth: borderWidth,
71
- borderRightWidth: borderWidth
72
- };
73
- case "bottom":
74
- return {
75
- ...shared,
76
- top: edge,
77
- borderTopWidth: borderWidth,
78
- borderLeftWidth: borderWidth
79
- };
80
- case "left":
81
- return {
82
- ...shared,
83
- right: edge,
84
- borderTopWidth: borderWidth,
85
- borderRightWidth: borderWidth
86
- };
87
- case "right":
88
- return {
89
- ...shared,
90
- left: edge,
91
- borderBottomWidth: borderWidth,
92
- borderLeftWidth: borderWidth
93
- };
94
- }
40
+ return { x, y, placement };
95
41
  }
96
42
  export {
97
43
  clamp,
98
44
  equalRects,
99
- getArrowStyle,
100
45
  getPopoverPosition
101
46
  };
102
47
  //# sourceMappingURL=popover-position.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/popover-position.utils.ts"],"sourcesContent":["import type { ViewStyle } from \"react-native\";\n\nimport type {\n PopoverPlacement,\n PopoverPosition,\n PopoverPositionOptions,\n PopoverRect,\n} from \"../types/popover.types\";\nimport { OppositePlacement } from \"../constants/popover.constants\";\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), Math.max(min, max));\n}\n\nexport function equalRects(a: PopoverRect | null, b: PopoverRect): boolean {\n return (\n a !== null &&\n a.x === b.x &&\n a.y === b.y &&\n a.width === b.width &&\n a.height === b.height\n );\n}\n\nexport function getPopoverPosition({\n anchor,\n bounds,\n width,\n height,\n placement: preferred,\n gap,\n arrowInset,\n}: PopoverPositionOptions): PopoverPosition {\n const right = bounds.x + bounds.width;\n const bottom = bounds.y + bounds.height;\n\n const available: Record<PopoverPlacement, number> = {\n top: anchor.y - bounds.y - gap,\n bottom: bottom - anchor.y - anchor.height - gap,\n left: anchor.x - bounds.x - gap,\n right: right - anchor.x - anchor.width - gap,\n };\n\n const vertical = preferred === \"top\" || preferred === \"bottom\";\n const extent = vertical ? height : width;\n const opposite = OppositePlacement[preferred];\n const placement =\n available[preferred] < extent && available[opposite] > available[preferred]\n ? opposite\n : preferred;\n\n const centerX = anchor.x + anchor.width / 2;\n const centerY = anchor.y + anchor.height / 2;\n const x = clamp(\n vertical\n ? centerX - width / 2\n : placement === \"left\"\n ? anchor.x - width - gap\n : anchor.x + anchor.width + gap,\n bounds.x,\n right - width,\n );\n const y = clamp(\n vertical\n ? placement === \"top\"\n ? anchor.y - height - gap\n : anchor.y + anchor.height + gap\n : centerY - height / 2,\n bounds.y,\n bottom - height,\n );\n\n const edgeLength = vertical ? width : height;\n const inset = Math.min(arrowInset, edgeLength / 2);\n const offset = vertical ? centerX - x : centerY - y;\n const facing =\n placement === \"top\"\n ? y + height <= anchor.y\n : placement === \"bottom\"\n ? y >= anchor.y + anchor.height\n : placement === \"left\"\n ? x + width <= anchor.x\n : x >= anchor.x + anchor.width;\n\n return {\n x,\n y,\n placement,\n arrowOffset: clamp(offset, inset, edgeLength - inset),\n showArrow: facing && offset >= inset && offset <= edgeLength - inset,\n };\n}\n\nexport function getArrowStyle(\n position: PopoverPosition,\n size: number,\n color: string,\n borderWidth: number,\n borderColor: string,\n): ViewStyle {\n const side = size * Math.SQRT2;\n const offset = position.arrowOffset - borderWidth - side / 2;\n const edge = -(side + borderWidth) / 2;\n\n // The inner half covers the panel's border; only the outward edges are outlined.\n const shared: ViewStyle = {\n width: side,\n height: side,\n backgroundColor: color,\n borderColor,\n transform: [{ rotate: \"45deg\" }],\n ...(position.placement === \"top\" || position.placement === \"bottom\"\n ? { left: offset }\n : { top: offset }),\n };\n\n switch (position.placement) {\n case \"top\":\n return {\n ...shared,\n bottom: edge,\n borderBottomWidth: borderWidth,\n borderRightWidth: borderWidth,\n };\n\n case \"bottom\":\n return {\n ...shared,\n top: edge,\n borderTopWidth: borderWidth,\n borderLeftWidth: borderWidth,\n };\n\n case \"left\":\n return {\n ...shared,\n right: edge,\n borderTopWidth: borderWidth,\n borderRightWidth: borderWidth,\n };\n\n case \"right\":\n return {\n ...shared,\n left: edge,\n borderBottomWidth: borderWidth,\n borderLeftWidth: borderWidth,\n };\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/utils/popover-position.utils.ts"],"sourcesContent":["import type {\n PopoverPlacement,\n PopoverPosition,\n PopoverPositionOptions,\n PopoverRect,\n} from \"../types/popover.types\";\nimport { OppositePlacement } from \"../constants/popover.constants\";\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), Math.max(min, max));\n}\n\nexport function equalRects(a: PopoverRect | null, b: PopoverRect): boolean {\n return (\n a !== null &&\n a.x === b.x &&\n a.y === b.y &&\n a.width === b.width &&\n a.height === b.height\n );\n}\n\nexport function getPopoverPosition({\n anchor,\n bounds,\n width,\n height,\n placement: preferred,\n gap,\n}: PopoverPositionOptions): PopoverPosition {\n const right = bounds.x + bounds.width;\n const bottom = bounds.y + bounds.height;\n\n const available: Record<PopoverPlacement, number> = {\n top: anchor.y - bounds.y - gap,\n bottom: bottom - anchor.y - anchor.height - gap,\n left: anchor.x - bounds.x - gap,\n right: right - anchor.x - anchor.width - gap,\n };\n\n const vertical = preferred === \"top\" || preferred === \"bottom\";\n const extent = vertical ? height : width;\n const opposite = OppositePlacement[preferred];\n const placement =\n available[preferred] < extent && available[opposite] > available[preferred]\n ? opposite\n : preferred;\n\n const centerX = anchor.x + anchor.width / 2;\n const centerY = anchor.y + anchor.height / 2;\n const x = clamp(\n vertical\n ? centerX - width / 2\n : placement === \"left\"\n ? anchor.x - width - gap\n : anchor.x + anchor.width + gap,\n bounds.x,\n right - width,\n );\n const y = clamp(\n vertical\n ? placement === \"top\"\n ? anchor.y - height - gap\n : anchor.y + anchor.height + gap\n : centerY - height / 2,\n bounds.y,\n bottom - height,\n );\n\n return { x, y, placement };\n}\n"],"mappings":"AAMA,SAAS,yBAAyB;AAE3B,SAAS,MAAM,OAAe,KAAa,KAAqB;AACrE,SAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC;AAC1D;AAEO,SAAS,WAAW,GAAuB,GAAyB;AACzE,SACE,MAAM,QACN,EAAE,MAAM,EAAE,KACV,EAAE,MAAM,EAAE,KACV,EAAE,UAAU,EAAE,SACd,EAAE,WAAW,EAAE;AAEnB;AAEO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAA4C;AAC1C,QAAM,QAAQ,OAAO,IAAI,OAAO;AAChC,QAAM,SAAS,OAAO,IAAI,OAAO;AAEjC,QAAM,YAA8C;AAAA,IAClD,KAAK,OAAO,IAAI,OAAO,IAAI;AAAA,IAC3B,QAAQ,SAAS,OAAO,IAAI,OAAO,SAAS;AAAA,IAC5C,MAAM,OAAO,IAAI,OAAO,IAAI;AAAA,IAC5B,OAAO,QAAQ,OAAO,IAAI,OAAO,QAAQ;AAAA,EAC3C;AAEA,QAAM,WAAW,cAAc,SAAS,cAAc;AACtD,QAAM,SAAS,WAAW,SAAS;AACnC,QAAM,WAAW,kBAAkB,SAAS;AAC5C,QAAM,YACJ,UAAU,SAAS,IAAI,UAAU,UAAU,QAAQ,IAAI,UAAU,SAAS,IACtE,WACA;AAEN,QAAM,UAAU,OAAO,IAAI,OAAO,QAAQ;AAC1C,QAAM,UAAU,OAAO,IAAI,OAAO,SAAS;AAC3C,QAAM,IAAI;AAAA,IACR,WACI,UAAU,QAAQ,IAClB,cAAc,SACZ,OAAO,IAAI,QAAQ,MACnB,OAAO,IAAI,OAAO,QAAQ;AAAA,IAChC,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACA,QAAM,IAAI;AAAA,IACR,WACI,cAAc,QACZ,OAAO,IAAI,SAAS,MACpB,OAAO,IAAI,OAAO,SAAS,MAC7B,UAAU,SAAS;AAAA,IACvB,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AAEA,SAAO,EAAE,GAAG,GAAG,UAAU;AAC3B;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/popover",
3
- "version": "6.3.0",
3
+ "version": "6.3.1",
4
4
  "description": "Portal-rendered tooltips and compound anchored popovers for ImpulseUI Native.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -27,10 +27,10 @@
27
27
  ],
28
28
  "sideEffects": false,
29
29
  "dependencies": {
30
- "@impulse-ui-native/core": "6.3.0",
31
- "@impulse-ui-native/primitives": "6.3.0",
32
- "@impulse-ui-native/portal": "6.3.0",
33
- "@impulse-ui-native/theme": "6.3.0"
30
+ "@impulse-ui-native/theme": "6.3.1",
31
+ "@impulse-ui-native/core": "6.3.1",
32
+ "@impulse-ui-native/portal": "6.3.1",
33
+ "@impulse-ui-native/primitives": "6.3.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/react": "~19.2.14",