@hanzogui/tooltip 2.0.0-rc.41-hanzoai.3

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/Tooltip.cjs +241 -0
  3. package/dist/cjs/Tooltip.native.js +50 -0
  4. package/dist/cjs/Tooltip.native.js.map +1 -0
  5. package/dist/cjs/TooltipSimple.cjs +112 -0
  6. package/dist/cjs/TooltipSimple.native.js +34 -0
  7. package/dist/cjs/TooltipSimple.native.js.map +1 -0
  8. package/dist/cjs/index.cjs +21 -0
  9. package/dist/cjs/index.native.js +24 -0
  10. package/dist/cjs/index.native.js.map +1 -0
  11. package/dist/esm/Tooltip.mjs +202 -0
  12. package/dist/esm/Tooltip.mjs.map +1 -0
  13. package/dist/esm/Tooltip.native.js +20 -0
  14. package/dist/esm/Tooltip.native.js.map +1 -0
  15. package/dist/esm/TooltipSimple.mjs +76 -0
  16. package/dist/esm/TooltipSimple.mjs.map +1 -0
  17. package/dist/esm/TooltipSimple.native.js +6 -0
  18. package/dist/esm/TooltipSimple.native.js.map +1 -0
  19. package/dist/esm/index.js +3 -0
  20. package/dist/esm/index.js.map +1 -0
  21. package/dist/esm/index.mjs +3 -0
  22. package/dist/esm/index.mjs.map +1 -0
  23. package/dist/esm/index.native.js +3 -0
  24. package/dist/esm/index.native.js.map +1 -0
  25. package/dist/jsx/Tooltip.mjs +202 -0
  26. package/dist/jsx/Tooltip.mjs.map +1 -0
  27. package/dist/jsx/Tooltip.native.js +50 -0
  28. package/dist/jsx/Tooltip.native.js.map +1 -0
  29. package/dist/jsx/TooltipSimple.mjs +76 -0
  30. package/dist/jsx/TooltipSimple.mjs.map +1 -0
  31. package/dist/jsx/TooltipSimple.native.js +34 -0
  32. package/dist/jsx/TooltipSimple.native.js.map +1 -0
  33. package/dist/jsx/index.js +3 -0
  34. package/dist/jsx/index.js.map +1 -0
  35. package/dist/jsx/index.mjs +3 -0
  36. package/dist/jsx/index.mjs.map +1 -0
  37. package/dist/jsx/index.native.js +24 -0
  38. package/dist/jsx/index.native.js.map +1 -0
  39. package/package.json +62 -0
  40. package/src/Tooltip.native.tsx +26 -0
  41. package/src/Tooltip.tsx +291 -0
  42. package/src/TooltipSimple.native.tsx +5 -0
  43. package/src/TooltipSimple.tsx +85 -0
  44. package/src/index.tsx +2 -0
  45. package/types/Tooltip.d.ts +92 -0
  46. package/types/Tooltip.d.ts.map +1 -0
  47. package/types/Tooltip.native.d.ts +10 -0
  48. package/types/Tooltip.native.d.ts.map +1 -0
  49. package/types/TooltipSimple.d.ts +11 -0
  50. package/types/TooltipSimple.d.ts.map +1 -0
  51. package/types/TooltipSimple.native.d.ts +2 -0
  52. package/types/TooltipSimple.native.d.ts.map +1 -0
  53. package/types/index.d.ts +3 -0
  54. package/types/index.d.ts.map +1 -0
@@ -0,0 +1,76 @@
1
+ import { getSpace } from "@hanzogui/get-token";
2
+ import { Paragraph } from "@hanzogui/text";
3
+ import * as React from "react";
4
+ import { Tooltip } from "./Tooltip.mjs";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ const TooltipSimple = React.forwardRef(({
7
+ label,
8
+ children,
9
+ contentProps,
10
+ disabled,
11
+ ...tooltipProps
12
+ }, ref) => {
13
+ "use no memo";
14
+
15
+ const child = React.Children.only(children);
16
+ if (!label) {
17
+ return children;
18
+ }
19
+ return /* @__PURE__ */jsxs(Tooltip, {
20
+ disableRTL: true,
21
+ offset: 15,
22
+ restMs: 40,
23
+ delay: 40,
24
+ zIndex: 1e6,
25
+ ...tooltipProps,
26
+ ...(disabled ? {
27
+ open: false
28
+ } : null),
29
+ children: [/* @__PURE__ */jsx(Tooltip.Trigger, {
30
+ ...(typeof label === "string" && {
31
+ "aria-label": label
32
+ }),
33
+ asChild: "except-style",
34
+ children: ref && React.isValidElement(child) ? React.cloneElement(child, {
35
+ ref
36
+ }) : child
37
+ }), /* @__PURE__ */jsxs(Tooltip.Content, {
38
+ enterStyle: {
39
+ y: -4,
40
+ opacity: 0,
41
+ scale: 0.96
42
+ },
43
+ exitStyle: {
44
+ y: -4,
45
+ opacity: 0,
46
+ scale: 0.96
47
+ },
48
+ scale: 1,
49
+ elevation: "$0.5",
50
+ opacity: 1,
51
+ pointerEvents: "none",
52
+ paddingVertical: getSpace(tooltipProps.size || "$true", {
53
+ shift: -4
54
+ }),
55
+ animateOnly: ["transform", "opacity"],
56
+ transition: ["quicker", {
57
+ opacity: {
58
+ overshootClamping: true
59
+ }
60
+ }],
61
+ ...contentProps,
62
+ children: [/* @__PURE__ */jsx(Tooltip.Arrow, {}), /* @__PURE__ */jsx(Paragraph, {
63
+ maxWidth: 350,
64
+ overflow: "hidden",
65
+ size: "$3",
66
+ textAlign: "center",
67
+ "$platform-web": {
68
+ textWrap: "balance"
69
+ },
70
+ children: label
71
+ })]
72
+ })]
73
+ });
74
+ });
75
+ export { TooltipSimple };
76
+ //# sourceMappingURL=TooltipSimple.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getSpace","Paragraph","React","Tooltip","jsx","jsxs","TooltipSimple","forwardRef","label","children","contentProps","disabled","tooltipProps","ref","child","Children","only","disableRTL","offset","restMs","delay","zIndex","open","Trigger","asChild","isValidElement","cloneElement","Content","enterStyle","y","opacity","scale","exitStyle","elevation","pointerEvents","paddingVertical","size","shift","animateOnly","transition","overshootClamping","Arrow","maxWidth","overflow","textAlign","textWrap"],"sources":["../../src/TooltipSimple.tsx"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,QAAgB;AAEzB,SAASC,SAAA,QAAiB;AAC1B,YAAYC,KAAA,MAAW;AAGvB,SAASC,OAAA,QAAe;AA8BhB,SAAAC,GAAA,EAWAC,IAAA,QAXA;AArBD,MAAMC,aAAA,GAA8CJ,KAAA,CAAMK,UAAA,CAC/D,CAAC;EAAEC,KAAA;EAAOC,QAAA;EAAUC,YAAA;EAAcC,QAAA;EAAU,GAAGC;AAAa,GAAGC,GAAA,KAAQ;EACrE;;EAEA,MAAMC,KAAA,GAAQZ,KAAA,CAAMa,QAAA,CAASC,IAAA,CAAKP,QAAQ;EAE1C,IAAI,CAACD,KAAA,EAAO;IACV,OAAOC,QAAA;EACT;EAEA,OACE,eAAAJ,IAAA,CAACF,OAAA;IACCc,UAAA,EAAU;IACVC,MAAA,EAAQ;IACRC,MAAA,EAAQ;IACRC,KAAA,EAAO;IAEPC,MAAA,EAAQ;IACP,GAAGT,YAAA;IACH,IAAID,QAAA,GAAW;MAAEW,IAAA,EAAM;IAAM,IAAI;IAElCb,QAAA,kBAAAL,GAAA,CAACD,OAAA,CAAQoB,OAAA,EAAR;MACE,IAAI,OAAOf,KAAA,KAAU,YAAY;QAChC,cAAcA;MAChB;MACAgB,OAAA,EAAQ;MAEPf,QAAA,EAAAI,GAAA,IAAOX,KAAA,CAAMuB,cAAA,CAAeX,KAAK,IAC9BZ,KAAA,CAAMwB,YAAA,CAAaZ,KAAA,EAAO;QAAED;MAAI,CAAQ,IACxCC;IAAA,CACN,GAEA,eAAAT,IAAA,CAACF,OAAA,CAAQwB,OAAA,EAAR;MACCC,UAAA,EAAY;QAAEC,CAAA,EAAG;QAAIC,OAAA,EAAS;QAAGC,KAAA,EAAO;MAAK;MAC7CC,SAAA,EAAW;QAAEH,CAAA,EAAG;QAAIC,OAAA,EAAS;QAAGC,KAAA,EAAO;MAAK;MAC5CA,KAAA,EAAO;MACPE,SAAA,EAAU;MACVH,OAAA,EAAS;MACTI,aAAA,EAAc;MACdC,eAAA,EAAiBnC,QAAA,CAASY,YAAA,CAAawB,IAAA,IAAQ,SAAS;QACtDC,KAAA,EAAO;MACT,CAAC;MACDC,WAAA,EAAa,CAAC,aAAa,SAAS;MACpCC,UAAA,EAAY,CACV,WACA;QACET,OAAA,EAAS;UACPU,iBAAA,EAAmB;QACrB;MACF,EACF;MACC,GAAG9B,YAAA;MAEJD,QAAA,kBAAAL,GAAA,CAACD,OAAA,CAAQsC,KAAA,EAAR,EAAc,GACf,eAAArC,GAAA,CAACH,SAAA;QACCyC,QAAA,EAAU;QACVC,QAAA,EAAS;QACTP,IAAA,EAAK;QACLQ,SAAA,EAAU;QACV,iBAAe;UACbC,QAAA,EAAU;QACZ;QAECpC,QAAA,EAAAD;MAAA,CACH;IAAA,CACF;EAAA,CACF;AAEJ,CACF","ignoreList":[]}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: () => from[key],
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
23
+ value: true
24
+ }), mod);
25
+ var TooltipSimple_native_exports = {};
26
+ __export(TooltipSimple_native_exports, {
27
+ TooltipSimple: () => TooltipSimple
28
+ });
29
+ module.exports = __toCommonJS(TooltipSimple_native_exports);
30
+ var RenderChildren = function (props) {
31
+ return props.children;
32
+ };
33
+ var TooltipSimple = RenderChildren;
34
+ //# sourceMappingURL=TooltipSimple.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TooltipSimple_native_exports","__export","TooltipSimple","module","exports","__toCommonJS","RenderChildren","props","children"],"sources":["../../src/TooltipSimple.native.tsx"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,4BAAA;AAAAC,QAAA,CAAAD,4BAAA;EAAAE,aAAA,EAAAA,CAAA,KAAAA;AAAA;AAAAC,MAAA,CAAAC,OAAA,GAAAC,YAAA,CAAAL,4BAAA;AAAA,IAAIM,cAAA,GAAiB,SAAAA,CAASC,KAAA,EAAO;EACjC,OAAOA,KAAA,CAAMC,QAAA;AACjB;AACO,IAAIN,aAAA,GAAgBI,cAAA","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ export * from "./Tooltip.mjs";
2
+ export * from "./TooltipSimple.mjs";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["../../src/index.tsx"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ export * from "./Tooltip.mjs";
2
+ export * from "./TooltipSimple.mjs";
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["../../src/index.tsx"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __copyProps = (to, from, except, desc) => {
8
+ if (from && typeof from === "object" || typeof from === "function") {
9
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
10
+ get: () => from[key],
11
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
12
+ });
13
+ }
14
+ return to;
15
+ };
16
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
17
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
18
+ value: true
19
+ }), mod);
20
+ var index_exports = {};
21
+ module.exports = __toCommonJS(index_exports);
22
+ __reExport(index_exports, require("./Tooltip.native.js"), module.exports);
23
+ __reExport(index_exports, require("./TooltipSimple.native.js"), module.exports);
24
+ //# sourceMappingURL=index.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["__defProp","Object","defineProperty"],"sources":["../../src/index.tsx"],"sourcesContent":[null],"mappings":"AAAA;;AACA,IAAAA,SAAA,GAAcC,MAAA,CAAAC,cAAA","ignoreList":[]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@hanzogui/tooltip",
3
+ "version": "2.0.0-rc.41-hanzoai.3",
4
+ "source": "src/index.tsx",
5
+ "files": [
6
+ "src",
7
+ "types",
8
+ "dist"
9
+ ],
10
+ "type": "module",
11
+ "sideEffects": [
12
+ "*.css"
13
+ ],
14
+ "main": "dist/cjs",
15
+ "module": "dist/esm",
16
+ "types": "./types/index.d.ts",
17
+ "exports": {
18
+ "./package.json": "./package.json",
19
+ ".": {
20
+ "types": "./types/index.d.ts",
21
+ "react-native": "./dist/esm/index.native.js",
22
+ "browser": "./dist/esm/index.mjs",
23
+ "module": "./dist/esm/index.mjs",
24
+ "import": "./dist/esm/index.mjs",
25
+ "require": "./dist/cjs/index.cjs",
26
+ "default": "./dist/esm/index.mjs"
27
+ }
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "scripts": {
33
+ "build": "hanzogui-build",
34
+ "watch": "hanzogui-build --watch",
35
+ "clean": "hanzogui-build clean",
36
+ "clean:build": "hanzogui-build clean:build"
37
+ },
38
+ "dependencies": {
39
+ "@hanzogui/compose-refs": "2.0.0-rc.41-hanzoai.3",
40
+ "@hanzogui/core": "2.0.0-rc.41-hanzoai.3",
41
+ "@hanzogui/create-context": "2.0.0-rc.41-hanzoai.3",
42
+ "@hanzogui/floating": "2.0.0-rc.41-hanzoai.3",
43
+ "@hanzogui/get-token": "2.0.0-rc.41-hanzoai.3",
44
+ "@hanzogui/helpers": "2.0.0-rc.41-hanzoai.3",
45
+ "@hanzogui/polyfill-dev": "2.0.0-rc.41-hanzoai.3",
46
+ "@hanzogui/popover": "2.0.0-rc.41-hanzoai.3",
47
+ "@hanzogui/popper": "2.0.0-rc.41-hanzoai.3",
48
+ "@hanzogui/stacks": "2.0.0-rc.41-hanzoai.3",
49
+ "@hanzogui/text": "2.0.0-rc.41-hanzoai.3",
50
+ "@hanzogui/use-controllable-state": "2.0.0-rc.41-hanzoai.3"
51
+ },
52
+ "devDependencies": {
53
+ "@hanzogui/build": "2.0.0-rc.41-hanzoai.3",
54
+ "react": ">=19",
55
+ "react-native": "0.83.2"
56
+ },
57
+ "peerDependencies": {
58
+ "react": ">=19",
59
+ "react-native": "*"
60
+ },
61
+ "module:jsx": "dist/jsx"
62
+ }
@@ -0,0 +1,26 @@
1
+ import { withStaticProperties } from '@hanzogui/helpers'
2
+
3
+ // no output on native for now
4
+ // could have an option to long-press or similar to show in a context menu/drawer
5
+
6
+ const RenderChildren = (props: any) => {
7
+ return props.children
8
+ }
9
+
10
+ const RenderNull = (props: any) => {
11
+ return null
12
+ }
13
+
14
+ export const TooltipGroup = () => null
15
+
16
+ export const closeOpenTooltips = () => {
17
+ /* noop */
18
+ }
19
+
20
+ export const Tooltip = withStaticProperties(RenderChildren, {
21
+ Anchor: RenderChildren,
22
+ Arrow: RenderNull,
23
+ Close: RenderNull,
24
+ Content: RenderNull,
25
+ Trigger: RenderChildren,
26
+ })
@@ -0,0 +1,291 @@
1
+ import '@hanzogui/polyfill-dev'
2
+
3
+ import { FloatingDelayGroup, useDelayGroupContext, type Delay } from '@hanzogui/floating'
4
+ import type { SizeTokens, HanzoguiElement } from '@hanzogui/core'
5
+ import { useEvent } from '@hanzogui/core'
6
+ import { FloatingOverrideContext } from '@hanzogui/floating'
7
+ import { getSize } from '@hanzogui/get-token'
8
+ import { withStaticProperties } from '@hanzogui/helpers'
9
+ import type {
10
+ PopoverAnchorProps,
11
+ PopoverContentProps,
12
+ PopoverTriggerProps,
13
+ } from '@hanzogui/popover'
14
+ import {
15
+ PopoverAnchor,
16
+ PopoverArrow,
17
+ PopoverContent,
18
+ PopoverContextProvider,
19
+ PopoverTrigger,
20
+ useFloatingContext,
21
+ } from '@hanzogui/popover'
22
+ import type { PopperArrowProps, PopperProps } from '@hanzogui/popper'
23
+ import { Popper, PopperContentFrame } from '@hanzogui/popper'
24
+ import { useControllableState } from '@hanzogui/use-controllable-state'
25
+ import * as React from 'react'
26
+
27
+ const TOOLTIP_SCOPE = ''
28
+
29
+ export type TooltipScopes = string
30
+
31
+ type ScopedProps<P> = Omit<P, 'scope'> & { scope?: TooltipScopes }
32
+
33
+ export type TooltipContentProps = ScopedProps<PopoverContentProps>
34
+
35
+ // warning: setting to stylebale causes issues with themeInverse across portal root
36
+
37
+ // performance: avoid 2 components we never use
38
+ const ALWAYS_DISABLE_TOOLTIP = {
39
+ focus: true,
40
+ 'remove-scroll': true,
41
+ // it's nice to hit escape to hide a tooltip
42
+ // dismiss: true
43
+ } as const
44
+
45
+ const TooltipContent = PopperContentFrame.styleable<TooltipContentProps>(
46
+ (props, ref) => {
47
+ const preventAnimation = React.useContext(PreventTooltipAnimationContext)
48
+ const zIndexFromContext = React.useContext(TooltipZIndexContext)
49
+
50
+ return (
51
+ <PopoverContent
52
+ scope={props.scope || TOOLTIP_SCOPE}
53
+ alwaysDisable={ALWAYS_DISABLE_TOOLTIP}
54
+ {...(!props.unstyled && {
55
+ backgroundColor: '$background',
56
+ alignItems: 'center',
57
+ pointerEvents: 'none',
58
+ size: '$true',
59
+ })}
60
+ ref={ref}
61
+ // zIndex from root Tooltip prop flows to portal
62
+ {...(zIndexFromContext !== undefined && { zIndex: zIndexFromContext })}
63
+ {...props}
64
+ {...(preventAnimation && {
65
+ transition: null,
66
+ })}
67
+ />
68
+ )
69
+ },
70
+ {
71
+ staticConfig: {
72
+ componentName: 'Tooltip',
73
+ },
74
+ }
75
+ )
76
+
77
+ const TooltipArrow = React.forwardRef<HanzoguiElement, PopperArrowProps>((props, ref) => {
78
+ return (
79
+ <PopoverArrow
80
+ scope={props.scope || TOOLTIP_SCOPE}
81
+ componentName="Tooltip"
82
+ ref={ref}
83
+ {...props}
84
+ />
85
+ )
86
+ })
87
+
88
+ export type TooltipProps = ScopedProps<
89
+ PopperProps & {
90
+ open?: boolean
91
+ unstyled?: boolean
92
+ children?: React.ReactNode
93
+ onOpenChange?: (open: boolean) => void
94
+ focus?: {
95
+ enabled?: boolean
96
+ visibleOnly?: boolean
97
+ }
98
+ groupId?: string
99
+ restMs?: number
100
+ delay?:
101
+ | number
102
+ | {
103
+ open?: number
104
+ close?: number
105
+ }
106
+ disableAutoCloseOnScroll?: boolean
107
+ /**
108
+ * z-index for the tooltip portal. Use this when tooltips need to appear
109
+ * above other portaled content like dialogs.
110
+ */
111
+ zIndex?: number
112
+ }
113
+ >
114
+
115
+ const PreventTooltipAnimationContext = React.createContext(false)
116
+ const TooltipZIndexContext = React.createContext<number | undefined>(undefined)
117
+
118
+ export const TooltipGroup = ({
119
+ children,
120
+ delay,
121
+ preventAnimation = false,
122
+ timeoutMs,
123
+ }: {
124
+ children?: any
125
+ delay: Delay
126
+ preventAnimation?: boolean
127
+ timeoutMs?: number
128
+ }) => {
129
+ return (
130
+ <PreventTooltipAnimationContext.Provider value={preventAnimation}>
131
+ <FloatingDelayGroup
132
+ timeoutMs={timeoutMs}
133
+ delay={React.useMemo(() => delay, [JSON.stringify(delay)])}
134
+ >
135
+ {children}
136
+ </FloatingDelayGroup>
137
+ </PreventTooltipAnimationContext.Provider>
138
+ )
139
+ }
140
+
141
+ const setOpens = new Set<React.Dispatch<React.SetStateAction<boolean>>>()
142
+
143
+ export const closeOpenTooltips = () => {
144
+ setOpens.forEach((x) => x(false))
145
+ }
146
+
147
+ const TooltipComponent = React.forwardRef(function Tooltip(
148
+ props: TooltipProps,
149
+ // no real ref here but React complaining need to see why see SandboxCustomStyledAnimatedTooltip.ts
150
+ ref
151
+ ) {
152
+ // hooks inside useFloatingFn confuse the React Compiler
153
+ 'use no memo'
154
+
155
+ const {
156
+ children,
157
+ delay: delayProp,
158
+ restMs: restMsProp,
159
+ onOpenChange: onOpenChangeProp,
160
+ focus,
161
+ open: openProp,
162
+ disableAutoCloseOnScroll,
163
+ zIndex,
164
+ scope = TOOLTIP_SCOPE,
165
+ ...restProps
166
+ } = props
167
+ const triggerRef = React.useRef<HTMLButtonElement>(null)
168
+ const [hasCustomAnchor, setHasCustomAnchor] = React.useState(false)
169
+ const { delay: delayGroup, setCurrentId } = useDelayGroupContext()
170
+ // Use delayProp if explicitly provided, otherwise fall back to group delay or default 400
171
+ const delay = delayProp !== undefined ? delayProp : (delayGroup ?? 400)
172
+ const restMs = restMsProp ?? (typeof delay === 'number' ? delay : 0)
173
+ const [open, setOpen] = useControllableState({
174
+ prop: openProp,
175
+ defaultProp: false,
176
+ onChange: onOpenChangeProp,
177
+ })
178
+ const id = props.groupId
179
+
180
+ const onOpenChange = useEvent((open: boolean) => {
181
+ if (open) {
182
+ setCurrentId(id)
183
+ }
184
+ setOpen(open)
185
+ })
186
+
187
+ // Auto close when document scroll
188
+ React.useEffect(() => {
189
+ if (!open) return
190
+ if (disableAutoCloseOnScroll) return
191
+ if (typeof document === 'undefined') return
192
+ const closeIt = () => {
193
+ setOpen(false)
194
+ }
195
+ setOpens.add(setOpen)
196
+ document.documentElement.addEventListener('scroll', closeIt)
197
+ return () => {
198
+ setOpens.delete(setOpen)
199
+ document.documentElement.removeEventListener('scroll', closeIt)
200
+ }
201
+ }, [open, disableAutoCloseOnScroll])
202
+
203
+ // use the shared floating context from popover — gives us multi-trigger
204
+ // hover coordination (onHoverReference/onLeaveReference + grace period)
205
+ // and safePolygon for free
206
+ const floatingContext = useFloatingContext({
207
+ open,
208
+ setOpen: onOpenChange,
209
+ disable: false,
210
+ disableFocus: false,
211
+ hoverable: true,
212
+ role: 'tooltip',
213
+ focus,
214
+ groupId: id,
215
+ delay,
216
+ restMs,
217
+ })
218
+
219
+ const onCustomAnchorAdd = React.useCallback(() => setHasCustomAnchor(true), [])
220
+ const onCustomAnchorRemove = React.useCallback(() => setHasCustomAnchor(false), [])
221
+ const contentId = React.useId()
222
+ const smallerSize = props.unstyled
223
+ ? null
224
+ : getSize('$true', {
225
+ shift: -2,
226
+ bounds: [0],
227
+ })
228
+
229
+ const content = (
230
+ <FloatingOverrideContext.Provider value={floatingContext}>
231
+ {/* default tooltip to a smaller size */}
232
+ <Popper
233
+ scope={scope}
234
+ size={smallerSize?.key as SizeTokens}
235
+ allowFlip
236
+ stayInFrame
237
+ open={open}
238
+ {...restProps}
239
+ >
240
+ <PopoverContextProvider
241
+ scope={scope}
242
+ contentId={contentId}
243
+ triggerRef={triggerRef}
244
+ open={open}
245
+ onOpenChange={setOpen}
246
+ onOpenToggle={voidFn}
247
+ hasCustomAnchor={hasCustomAnchor}
248
+ onCustomAnchorAdd={onCustomAnchorAdd}
249
+ onCustomAnchorRemove={onCustomAnchorRemove}
250
+ >
251
+ {children}
252
+ </PopoverContextProvider>
253
+ </Popper>
254
+ </FloatingOverrideContext.Provider>
255
+ )
256
+
257
+ if (zIndex !== undefined) {
258
+ return (
259
+ <TooltipZIndexContext.Provider value={zIndex}>
260
+ {content}
261
+ </TooltipZIndexContext.Provider>
262
+ )
263
+ }
264
+
265
+ return content
266
+ })
267
+
268
+ const TooltipTrigger = React.forwardRef(function TooltipTrigger(
269
+ props: ScopedProps<PopoverTriggerProps>,
270
+ ref: any
271
+ ) {
272
+ const { scope, ...rest } = props
273
+ return <PopoverTrigger {...rest} scope={scope || TOOLTIP_SCOPE} ref={ref} />
274
+ })
275
+
276
+ const TooltipAnchor = React.forwardRef(function TooltipAnchor(
277
+ props: ScopedProps<PopoverAnchorProps>,
278
+ ref: any
279
+ ) {
280
+ const { scope, ...rest } = props
281
+ return <PopoverAnchor {...rest} scope={scope || TOOLTIP_SCOPE} ref={ref} />
282
+ })
283
+
284
+ export const Tooltip = withStaticProperties(TooltipComponent, {
285
+ Anchor: TooltipAnchor,
286
+ Arrow: TooltipArrow,
287
+ Content: TooltipContent,
288
+ Trigger: TooltipTrigger,
289
+ })
290
+
291
+ const voidFn = () => {}
@@ -0,0 +1,5 @@
1
+ const RenderChildren = (props: any) => {
2
+ return props.children
3
+ }
4
+
5
+ export const TooltipSimple = RenderChildren
@@ -0,0 +1,85 @@
1
+ import { getSpace } from '@hanzogui/get-token'
2
+ import type { SizableStackProps } from '@hanzogui/stacks'
3
+ import { Paragraph } from '@hanzogui/text'
4
+ import * as React from 'react'
5
+
6
+ import type { TooltipProps } from './Tooltip'
7
+ import { Tooltip } from './Tooltip'
8
+
9
+ export type TooltipSimpleProps = TooltipProps & {
10
+ disabled?: boolean
11
+ label?: React.ReactNode
12
+ children?: React.ReactNode
13
+ contentProps?: SizableStackProps
14
+ }
15
+
16
+ export const TooltipSimple: React.FC<TooltipSimpleProps> = React.forwardRef(
17
+ ({ label, children, contentProps, disabled, ...tooltipProps }, ref) => {
18
+ 'use no memo'
19
+
20
+ const child = React.Children.only(children)
21
+
22
+ if (!label) {
23
+ return children
24
+ }
25
+
26
+ return (
27
+ <Tooltip
28
+ disableRTL
29
+ offset={15}
30
+ restMs={40}
31
+ delay={40}
32
+ // ensure tooltips appear above dialogs and other portaled content
33
+ zIndex={1_000_000}
34
+ {...tooltipProps}
35
+ {...(disabled ? { open: false } : null)}
36
+ >
37
+ <Tooltip.Trigger
38
+ {...(typeof label === 'string' && {
39
+ 'aria-label': label,
40
+ })}
41
+ asChild="except-style"
42
+ >
43
+ {ref && React.isValidElement(child)
44
+ ? React.cloneElement(child, { ref } as any)
45
+ : child}
46
+ </Tooltip.Trigger>
47
+
48
+ <Tooltip.Content
49
+ enterStyle={{ y: -4, opacity: 0, scale: 0.96 }}
50
+ exitStyle={{ y: -4, opacity: 0, scale: 0.96 }}
51
+ scale={1}
52
+ elevation="$0.5"
53
+ opacity={1}
54
+ pointerEvents="none"
55
+ paddingVertical={getSpace(tooltipProps.size || '$true', {
56
+ shift: -4,
57
+ })}
58
+ animateOnly={['transform', 'opacity']}
59
+ transition={[
60
+ 'quicker',
61
+ {
62
+ opacity: {
63
+ overshootClamping: true,
64
+ },
65
+ },
66
+ ]}
67
+ {...contentProps}
68
+ >
69
+ <Tooltip.Arrow />
70
+ <Paragraph
71
+ maxWidth={350}
72
+ overflow="hidden"
73
+ size="$3"
74
+ textAlign="center"
75
+ $platform-web={{
76
+ textWrap: 'balance',
77
+ }}
78
+ >
79
+ {label}
80
+ </Paragraph>
81
+ </Tooltip.Content>
82
+ </Tooltip>
83
+ )
84
+ }
85
+ )
package/src/index.tsx ADDED
@@ -0,0 +1,2 @@
1
+ export * from './Tooltip'
2
+ export * from './TooltipSimple'