@titan-design/react-ui 0.1.0 → 0.2.5

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 (236) hide show
  1. package/README.md +47 -1
  2. package/dist/{chunk-MGW37MPO.mjs → chunk-UXVRPOME.mjs} +173 -3
  3. package/dist/chunk-UXVRPOME.mjs.map +1 -0
  4. package/dist/index.d.mts +101 -12
  5. package/dist/index.d.ts +101 -12
  6. package/dist/index.js +1267 -468
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +734 -112
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/theme/index.d.mts +86 -1
  11. package/dist/theme/index.d.ts +86 -1
  12. package/dist/theme/index.js +166 -0
  13. package/dist/theme/index.js.map +1 -1
  14. package/dist/theme/index.mjs +1 -1
  15. package/package.json +22 -6
  16. package/src/components/custom/DateTime/DateTime.stories.tsx +180 -0
  17. package/src/components/custom/DateTime/DateTime.test.tsx +152 -0
  18. package/src/components/custom/DateTime/DateTime.tsx +235 -0
  19. package/src/components/custom/DateTime/index.ts +2 -0
  20. package/src/components/custom/EmptyState/EmptyState.stories.tsx +99 -0
  21. package/src/components/custom/EmptyState/EmptyState.test.tsx +106 -0
  22. package/src/components/custom/EmptyState/EmptyState.tsx +68 -0
  23. package/src/components/custom/EmptyState/index.ts +2 -0
  24. package/src/components/custom/Metric/Metric.stories.tsx +133 -0
  25. package/src/components/custom/Metric/Metric.test.tsx +120 -0
  26. package/src/components/custom/Metric/Metric.tsx +92 -0
  27. package/src/components/custom/Metric/index.ts +2 -0
  28. package/src/components/custom/Sidebar/Sidebar.stories.tsx +227 -0
  29. package/src/components/custom/Sidebar/Sidebar.test.tsx +185 -0
  30. package/src/components/custom/Sidebar/Sidebar.tsx +257 -0
  31. package/src/components/custom/Sidebar/index.ts +18 -0
  32. package/src/components/custom/Table/Table.stories.tsx +481 -0
  33. package/src/components/custom/Table/Table.test.tsx +531 -0
  34. package/src/components/custom/Table/Table.tsx +696 -0
  35. package/src/components/custom/Table/index.ts +22 -0
  36. package/src/components/custom/Typography/Typography.stories.tsx +153 -0
  37. package/src/components/custom/Typography/Typography.test.tsx +107 -0
  38. package/src/components/custom/Typography/Typography.tsx +218 -0
  39. package/src/components/custom/Typography/index.ts +19 -0
  40. package/src/components/custom/Workout/RestTimer.stories.tsx +71 -0
  41. package/src/components/custom/Workout/RestTimer.test.tsx +145 -0
  42. package/src/components/custom/Workout/RestTimer.tsx +172 -0
  43. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +144 -0
  44. package/src/components/custom/Workout/SupersetWrapper.test.tsx +130 -0
  45. package/src/components/custom/Workout/SupersetWrapper.tsx +63 -0
  46. package/src/components/custom/Workout/index.ts +2 -0
  47. package/src/components/custom/index.ts +9 -0
  48. package/src/components/custom/stepper/Stepper.stories.tsx +245 -0
  49. package/src/components/custom/stepper/Stepper.test.tsx +230 -0
  50. package/src/components/custom/stepper/Stepper.tsx +250 -0
  51. package/src/components/custom/stepper/index.ts +10 -0
  52. package/src/components/index.ts +5 -0
  53. package/src/components/ui/alert/Alert.stories.tsx +154 -0
  54. package/src/components/ui/alert/Alert.test.tsx +202 -0
  55. package/src/components/ui/alert/Alert.tsx +170 -0
  56. package/src/components/ui/alert/index.ts +8 -0
  57. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +299 -0
  58. package/src/components/ui/autocomplete/Autocomplete.test.tsx +247 -0
  59. package/src/components/ui/autocomplete/Autocomplete.tsx +332 -0
  60. package/src/components/ui/autocomplete/index.ts +2 -0
  61. package/src/components/ui/avatar/Avatar.stories.tsx +105 -0
  62. package/src/components/ui/avatar/Avatar.test.tsx +152 -0
  63. package/src/components/ui/avatar/Avatar.tsx +176 -0
  64. package/src/components/ui/avatar/index.ts +2 -0
  65. package/src/components/ui/badge/Badge.stories.tsx +100 -0
  66. package/src/components/ui/badge/Badge.test.tsx +103 -0
  67. package/src/components/ui/badge/Badge.tsx +119 -0
  68. package/src/components/ui/badge/index.ts +3 -0
  69. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +70 -0
  70. package/src/components/ui/breadcrumbs/Breadcrumbs.test.tsx +156 -0
  71. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +127 -0
  72. package/src/components/ui/breadcrumbs/index.ts +2 -0
  73. package/src/components/ui/button/Button.stories.tsx +216 -0
  74. package/src/components/ui/button/Button.test.tsx +132 -0
  75. package/src/components/ui/button/Button.tsx +297 -0
  76. package/src/components/ui/button/index.ts +10 -0
  77. package/src/components/ui/card/Card.stories.tsx +443 -0
  78. package/src/components/ui/card/Card.test.tsx +294 -0
  79. package/src/components/ui/card/Card.tsx +401 -0
  80. package/src/components/ui/card/index.ts +20 -0
  81. package/src/components/ui/checkbox/Checkbox.stories.tsx +126 -0
  82. package/src/components/ui/checkbox/Checkbox.test.tsx +152 -0
  83. package/src/components/ui/checkbox/Checkbox.tsx +163 -0
  84. package/src/components/ui/checkbox/index.ts +2 -0
  85. package/src/components/ui/chip/Chip.stories.tsx +112 -0
  86. package/src/components/ui/chip/Chip.test.tsx +119 -0
  87. package/src/components/ui/chip/Chip.tsx +151 -0
  88. package/src/components/ui/chip/index.ts +2 -0
  89. package/src/components/ui/collapse/Collapse.stories.tsx +313 -0
  90. package/src/components/ui/collapse/Collapse.test.tsx +298 -0
  91. package/src/components/ui/collapse/Collapse.tsx +275 -0
  92. package/src/components/ui/collapse/index.ts +18 -0
  93. package/src/components/ui/data-row/DataRow.stories.tsx +78 -0
  94. package/src/components/ui/data-row/DataRow.test.tsx +78 -0
  95. package/src/components/ui/data-row/DataRow.tsx +29 -0
  96. package/src/components/ui/data-row/index.ts +2 -0
  97. package/src/components/ui/divider/Divider.stories.tsx +71 -0
  98. package/src/components/ui/divider/Divider.test.tsx +55 -0
  99. package/src/components/ui/divider/Divider.tsx +37 -0
  100. package/src/components/ui/divider/index.ts +2 -0
  101. package/src/components/ui/drawer/Drawer.stories.tsx +228 -0
  102. package/src/components/ui/drawer/Drawer.test.tsx +142 -0
  103. package/src/components/ui/drawer/Drawer.tsx +228 -0
  104. package/src/components/ui/drawer/index.ts +9 -0
  105. package/src/components/ui/form-field/FormField.stories.tsx +260 -0
  106. package/src/components/ui/form-field/FormField.test.tsx +280 -0
  107. package/src/components/ui/form-field/FormField.tsx +308 -0
  108. package/src/components/ui/form-field/index.ts +2 -0
  109. package/src/components/ui/help-tip/HelpTip.stories.tsx +250 -0
  110. package/src/components/ui/help-tip/HelpTip.test.tsx +198 -0
  111. package/src/components/ui/help-tip/HelpTip.tsx +229 -0
  112. package/src/components/ui/help-tip/index.ts +2 -0
  113. package/src/components/ui/icon-box/IconBox.stories.tsx +139 -0
  114. package/src/components/ui/icon-box/IconBox.test.tsx +120 -0
  115. package/src/components/ui/icon-box/IconBox.tsx +57 -0
  116. package/src/components/ui/icon-box/index.ts +1 -0
  117. package/src/components/ui/index.ts +38 -0
  118. package/src/components/ui/indicator/Indicator.stories.tsx +74 -0
  119. package/src/components/ui/indicator/Indicator.test.tsx +55 -0
  120. package/src/components/ui/indicator/Indicator.tsx +73 -0
  121. package/src/components/ui/indicator/index.ts +2 -0
  122. package/src/components/ui/input/Input.stories.tsx +192 -0
  123. package/src/components/ui/input/Input.test.tsx +86 -0
  124. package/src/components/ui/input/Input.tsx +273 -0
  125. package/src/components/ui/input/index.ts +2 -0
  126. package/src/components/ui/link/Link.stories.tsx +78 -0
  127. package/src/components/ui/link/Link.test.tsx +94 -0
  128. package/src/components/ui/link/Link.tsx +86 -0
  129. package/src/components/ui/link/index.ts +2 -0
  130. package/src/components/ui/list-item/ListItem.stories.tsx +146 -0
  131. package/src/components/ui/list-item/ListItem.test.tsx +128 -0
  132. package/src/components/ui/list-item/ListItem.tsx +89 -0
  133. package/src/components/ui/list-item/index.ts +14 -0
  134. package/src/components/ui/menu/Menu.stories.tsx +180 -0
  135. package/src/components/ui/menu/Menu.test.tsx +353 -0
  136. package/src/components/ui/menu/Menu.tsx +222 -0
  137. package/src/components/ui/menu/index.ts +2 -0
  138. package/src/components/ui/modal/Modal.stories.tsx +350 -0
  139. package/src/components/ui/modal/Modal.test.tsx +159 -0
  140. package/src/components/ui/modal/Modal.tsx +254 -0
  141. package/src/components/ui/modal/index.ts +19 -0
  142. package/src/components/ui/pill/Pill.stories.tsx +71 -0
  143. package/src/components/ui/pill/Pill.test.tsx +69 -0
  144. package/src/components/ui/pill/Pill.tsx +104 -0
  145. package/src/components/ui/pill/index.ts +2 -0
  146. package/src/components/ui/popover/Popover.stories.tsx +190 -0
  147. package/src/components/ui/popover/Popover.test.tsx +419 -0
  148. package/src/components/ui/popover/Popover.tsx +237 -0
  149. package/src/components/ui/popover/index.ts +2 -0
  150. package/src/components/ui/progress/Progress.stories.tsx +190 -0
  151. package/src/components/ui/progress/Progress.test.tsx +210 -0
  152. package/src/components/ui/progress/Progress.tsx +339 -0
  153. package/src/components/ui/progress/index.ts +9 -0
  154. package/src/components/ui/radio/Radio.stories.tsx +199 -0
  155. package/src/components/ui/radio/Radio.test.tsx +166 -0
  156. package/src/components/ui/radio/Radio.tsx +200 -0
  157. package/src/components/ui/radio/index.ts +2 -0
  158. package/src/components/ui/section/Section.stories.tsx +111 -0
  159. package/src/components/ui/section/Section.test.tsx +121 -0
  160. package/src/components/ui/section/Section.tsx +52 -0
  161. package/src/components/ui/section/index.ts +6 -0
  162. package/src/components/ui/select/Select.stories.tsx +286 -0
  163. package/src/components/ui/select/Select.test.tsx +200 -0
  164. package/src/components/ui/select/Select.tsx +243 -0
  165. package/src/components/ui/select/index.ts +2 -0
  166. package/src/components/ui/skeleton/Skeleton.stories.tsx +153 -0
  167. package/src/components/ui/skeleton/Skeleton.test.tsx +162 -0
  168. package/src/components/ui/skeleton/Skeleton.tsx +229 -0
  169. package/src/components/ui/skeleton/index.ts +16 -0
  170. package/src/components/ui/spinner/Spinner.stories.tsx +67 -0
  171. package/src/components/ui/spinner/Spinner.test.tsx +67 -0
  172. package/src/components/ui/spinner/Spinner.tsx +72 -0
  173. package/src/components/ui/spinner/index.ts +2 -0
  174. package/src/components/ui/stack/Stack.stories.tsx +127 -0
  175. package/src/components/ui/stack/Stack.test.tsx +184 -0
  176. package/src/components/ui/stack/Stack.tsx +76 -0
  177. package/src/components/ui/stack/index.ts +2 -0
  178. package/src/components/ui/surface/Surface.stories.tsx +91 -0
  179. package/src/components/ui/surface/Surface.test.tsx +63 -0
  180. package/src/components/ui/surface/Surface.tsx +51 -0
  181. package/src/components/ui/surface/index.ts +1 -0
  182. package/src/components/ui/switch/Switch.stories.tsx +111 -0
  183. package/src/components/ui/switch/Switch.test.tsx +112 -0
  184. package/src/components/ui/switch/Switch.tsx +103 -0
  185. package/src/components/ui/switch/index.ts +2 -0
  186. package/src/components/ui/tabs/Tabs.stories.tsx +213 -0
  187. package/src/components/ui/tabs/Tabs.test.tsx +192 -0
  188. package/src/components/ui/tabs/Tabs.tsx +253 -0
  189. package/src/components/ui/tabs/index.ts +16 -0
  190. package/src/components/ui/toast/Toast.stories.tsx +255 -0
  191. package/src/components/ui/toast/Toast.test.tsx +207 -0
  192. package/src/components/ui/toast/Toast.tsx +327 -0
  193. package/src/components/ui/toast/index.ts +9 -0
  194. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +415 -0
  195. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +224 -0
  196. package/src/components/ui/toolbar-button/ToolbarButton.tsx +307 -0
  197. package/src/components/ui/toolbar-button/index.ts +7 -0
  198. package/src/components/ui/tooltip/Tooltip.stories.tsx +126 -0
  199. package/src/components/ui/tooltip/Tooltip.test.tsx +262 -0
  200. package/src/components/ui/tooltip/Tooltip.tsx +234 -0
  201. package/src/components/ui/tooltip/index.ts +2 -0
  202. package/src/index.ts +10 -0
  203. package/src/stories/PresetShowcase.stories.tsx +462 -0
  204. package/src/stories/ThemePresets.stories.tsx +85 -0
  205. package/src/test/setup.ts +19 -0
  206. package/src/theme/Colors.stories.tsx +258 -0
  207. package/src/theme/config.ts +193 -0
  208. package/src/theme/elevation.stories.tsx +346 -0
  209. package/src/theme/elevation.test.ts +27 -0
  210. package/src/theme/elevation.ts +567 -0
  211. package/src/theme/global.css +129 -1
  212. package/src/theme/index.ts +40 -0
  213. package/src/theme/presets/apply.ts +97 -0
  214. package/src/theme/presets/audiobook.ts +93 -0
  215. package/src/theme/presets/default.ts +6 -0
  216. package/src/theme/presets/index.ts +4 -0
  217. package/src/theme/presets/presets.test.ts +51 -0
  218. package/src/theme/presets/types.ts +76 -0
  219. package/src/theme/shadows.stories.tsx +523 -0
  220. package/src/theme/shadows.ts +439 -0
  221. package/src/theme/tokens/index.ts +2 -0
  222. package/src/theme/tokens/primitives.ts +354 -0
  223. package/src/theme/tokens/semantic.ts +381 -0
  224. package/src/types/jest-axe.d.ts +16 -0
  225. package/src/types/nativewind.d.ts +54 -0
  226. package/src/utils/avatar-color.test.ts +30 -0
  227. package/src/utils/avatar-color.ts +20 -0
  228. package/src/utils/cn.ts +14 -0
  229. package/src/utils/colors.ts +140 -0
  230. package/src/utils/form.ts +188 -0
  231. package/src/utils/index.ts +29 -0
  232. package/src/utils/useTheme.ts +72 -0
  233. package/src/web-jsx/jsx-dev-runtime.ts +28 -0
  234. package/src/web-jsx/jsx-runtime.ts +41 -0
  235. package/tailwind.config.js +53 -3
  236. package/dist/chunk-MGW37MPO.mjs.map +0 -1
@@ -0,0 +1,234 @@
1
+ import React, { useState, useRef, useEffect } from 'react'
2
+ import { View, Text, Pressable, Platform, type ViewProps } from 'react-native'
3
+ import { cn } from '../../../utils/cn'
4
+
5
+ let createPortal: typeof import('react-dom').createPortal | undefined
6
+ if (Platform.OS === 'web') {
7
+ try {
8
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
9
+ createPortal = require('react-dom').createPortal
10
+ } catch {
11
+ // react-dom unavailable
12
+ }
13
+ }
14
+
15
+ type PortalPosition = { top: number; left: number; transform: string }
16
+
17
+ export type TooltipPlacement =
18
+ | 'top'
19
+ | 'top-start'
20
+ | 'top-end'
21
+ | 'bottom'
22
+ | 'bottom-start'
23
+ | 'bottom-end'
24
+ | 'left'
25
+ | 'right'
26
+
27
+ export interface TooltipProps extends ViewProps {
28
+ /** Plain-text tooltip content */
29
+ label?: string
30
+ /** Rich tooltip content (takes precedence over label) */
31
+ content?: React.ReactNode
32
+ /** Trigger element */
33
+ children: React.ReactNode
34
+ /** Tooltip placement */
35
+ placement?: TooltipPlacement
36
+ /** Delay before showing (ms) */
37
+ openDelay?: number
38
+ /** Delay before hiding (ms) */
39
+ closeDelay?: number
40
+ /** Whether tooltip has an arrow */
41
+ hasArrow?: boolean
42
+ /** Whether tooltip is disabled */
43
+ isDisabled?: boolean
44
+ /** Additional className for tooltip */
45
+ className?: string
46
+ /** Render tooltip via portal to escape overflow:hidden ancestors (web only) */
47
+ usePortal?: boolean
48
+ }
49
+
50
+ /**
51
+ * Tooltip component for showing additional information on hover/press.
52
+ *
53
+ * Note: On native, tooltips appear on long press. On web, they appear on hover.
54
+ *
55
+ * @example
56
+ * // String-only tooltip
57
+ * <Tooltip label="This is a tooltip">
58
+ * <Button><ButtonText>Hover me</ButtonText></Button>
59
+ * </Tooltip>
60
+ *
61
+ * // Rich content tooltip
62
+ * <Tooltip content={<View><Text>Bold tip</Text><Text>with details</Text></View>}>
63
+ * <Button><ButtonText>Hover me</ButtonText></Button>
64
+ * </Tooltip>
65
+ */
66
+ export function Tooltip({
67
+ label,
68
+ content,
69
+ children,
70
+ placement = 'top',
71
+ openDelay = 0,
72
+ closeDelay = 0,
73
+ hasArrow = true,
74
+ isDisabled = false,
75
+ className,
76
+ usePortal: usePortalProp = false,
77
+ ...props
78
+ }: TooltipProps) {
79
+ const [isVisible, setIsVisible] = useState(false)
80
+ const [portalPos, setPortalPos] = useState<PortalPosition | null>(null)
81
+ const openTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
82
+ const closeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
83
+ const triggerRef = useRef<View>(null)
84
+
85
+ const isPortalMode = usePortalProp && Platform.OS === 'web' && !!createPortal
86
+
87
+ useEffect(() => {
88
+ if (!isVisible || !isPortalMode || !triggerRef.current) return
89
+ const node = triggerRef.current as unknown as HTMLElement
90
+ const id = requestAnimationFrame(() => {
91
+ const rect = node.getBoundingClientRect()
92
+ const gap = 8
93
+ const cardinal = placement.split('-')[0] as 'top' | 'bottom' | 'left' | 'right'
94
+
95
+ const positions: Record<string, PortalPosition> = {
96
+ top: {
97
+ top: rect.top - gap,
98
+ left: rect.left + rect.width / 2,
99
+ transform: 'translate(-50%, -100%)',
100
+ },
101
+ bottom: {
102
+ top: rect.bottom + gap,
103
+ left: rect.left + rect.width / 2,
104
+ transform: 'translate(-50%, 0%)',
105
+ },
106
+ left: {
107
+ top: rect.top + rect.height / 2,
108
+ left: rect.left - gap,
109
+ transform: 'translate(-100%, -50%)',
110
+ },
111
+ right: {
112
+ top: rect.top + rect.height / 2,
113
+ left: rect.right + gap,
114
+ transform: 'translate(0%, -50%)',
115
+ },
116
+ }
117
+
118
+ setPortalPos(positions[cardinal] ?? positions.top)
119
+ })
120
+ return () => cancelAnimationFrame(id)
121
+ }, [isVisible, isPortalMode, placement])
122
+
123
+ const clearTimeouts = () => {
124
+ if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)
125
+ if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)
126
+ }
127
+
128
+ const show = () => {
129
+ if (isDisabled) return
130
+ clearTimeouts()
131
+ if (openDelay > 0) {
132
+ openTimeoutRef.current = setTimeout(() => setIsVisible(true), openDelay)
133
+ } else {
134
+ setIsVisible(true)
135
+ }
136
+ }
137
+
138
+ const hide = () => {
139
+ clearTimeouts()
140
+ if (closeDelay > 0) {
141
+ closeTimeoutRef.current = setTimeout(() => setIsVisible(false), closeDelay)
142
+ } else {
143
+ setIsVisible(false)
144
+ }
145
+ }
146
+
147
+ // Arrow positioning
148
+ const arrowStyles = {
149
+ top: 'bottom-0 left-1/2 -translate-x-1/2 translate-y-full border-l-transparent border-r-transparent border-b-transparent border-t-neutral-800',
150
+ 'top-start': 'bottom-0 left-4 translate-y-full border-l-transparent border-r-transparent border-b-transparent border-t-neutral-800',
151
+ 'top-end': 'bottom-0 right-4 translate-y-full border-l-transparent border-r-transparent border-b-transparent border-t-neutral-800',
152
+ bottom: 'top-0 left-1/2 -translate-x-1/2 -translate-y-full border-l-transparent border-r-transparent border-t-transparent border-b-neutral-800',
153
+ 'bottom-start': 'top-0 left-4 -translate-y-full border-l-transparent border-r-transparent border-t-transparent border-b-neutral-800',
154
+ 'bottom-end': 'top-0 right-4 -translate-y-full border-l-transparent border-r-transparent border-t-transparent border-b-neutral-800',
155
+ left: 'right-0 top-1/2 translate-x-full -translate-y-1/2 border-t-transparent border-b-transparent border-r-transparent border-l-neutral-800',
156
+ right: 'left-0 top-1/2 -translate-x-full -translate-y-1/2 border-t-transparent border-b-transparent border-l-transparent border-r-neutral-800',
157
+ }
158
+
159
+ // Tooltip positioning
160
+ const tooltipPositionStyles = {
161
+ top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
162
+ 'top-start': 'bottom-full left-0 mb-2',
163
+ 'top-end': 'bottom-full right-0 mb-2',
164
+ bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
165
+ 'bottom-start': 'top-full left-0 mt-2',
166
+ 'bottom-end': 'top-full right-0 mt-2',
167
+ left: 'right-full top-1/2 -translate-y-1/2 mr-2',
168
+ right: 'left-full top-1/2 -translate-y-1/2 ml-2',
169
+ }
170
+
171
+ const tooltipContent = (
172
+ <View className="bg-neutral-800 px-3 py-2 rounded-md shadow-lg max-w-xs">
173
+ {content ?? <Text className="text-white text-sm">{label}</Text>}
174
+ {hasArrow && (
175
+ <View
176
+ className={cn(
177
+ 'absolute w-0 h-0 border-4',
178
+ arrowStyles[placement]
179
+ )}
180
+ />
181
+ )}
182
+ </View>
183
+ )
184
+
185
+ const renderPortalTooltip = () => {
186
+ if (!isVisible || !isPortalMode || !createPortal) return null
187
+ return createPortal(
188
+ <div
189
+ style={{
190
+ position: 'fixed',
191
+ top: portalPos?.top ?? 0,
192
+ left: portalPos?.left ?? 0,
193
+ transform: portalPos?.transform ?? 'translate(-50%, -100%)',
194
+ zIndex: 10000,
195
+ pointerEvents: 'none',
196
+ }}
197
+ data-testid="tooltip-portal"
198
+ className={className}
199
+ >
200
+ {tooltipContent}
201
+ </div>,
202
+ document.body
203
+ )
204
+ }
205
+
206
+ return (
207
+ <View className="relative" ref={triggerRef} {...props}>
208
+ <Pressable
209
+ onHoverIn={show}
210
+ onHoverOut={hide}
211
+ onLongPress={show}
212
+ onPressOut={hide}
213
+ delayLongPress={500}
214
+ >
215
+ {children}
216
+ </Pressable>
217
+
218
+ {isPortalMode
219
+ ? renderPortalTooltip()
220
+ : isVisible && (
221
+ <View
222
+ className={cn(
223
+ 'absolute z-50 web:animate-fade-in',
224
+ tooltipPositionStyles[placement],
225
+ className
226
+ )}
227
+ pointerEvents="none"
228
+ >
229
+ {tooltipContent}
230
+ </View>
231
+ )}
232
+ </View>
233
+ )
234
+ }
@@ -0,0 +1,2 @@
1
+ export { Tooltip } from './Tooltip'
2
+ export type { TooltipProps, TooltipPlacement } from './Tooltip'
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ // Main entry point for @titan-design/react-ui
2
+
3
+ // Components
4
+ export * from './components'
5
+
6
+ // Theme
7
+ export * from './theme'
8
+
9
+ // Utilities
10
+ export * from './utils'