@financedistrict/apps-ui 0.1.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.
Files changed (136) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +119 -0
  3. package/dist/Radio-BYWz1n7p.d.cts +32 -0
  4. package/dist/Radio-BYWz1n7p.d.ts +32 -0
  5. package/dist/SelectTrigger-By0iPBI3.d.cts +78 -0
  6. package/dist/SelectTrigger-By0iPBI3.d.ts +78 -0
  7. package/dist/accordion.cjs +322 -0
  8. package/dist/accordion.d.cts +156 -0
  9. package/dist/accordion.d.ts +156 -0
  10. package/dist/accordion.js +2 -0
  11. package/dist/apps-ui.umd.js +1 -0
  12. package/dist/button.cjs +366 -0
  13. package/dist/button.d.cts +52 -0
  14. package/dist/button.d.ts +52 -0
  15. package/dist/button.js +3 -0
  16. package/dist/checkbox.cjs +74 -0
  17. package/dist/checkbox.d.cts +63 -0
  18. package/dist/checkbox.d.ts +63 -0
  19. package/dist/checkbox.js +2 -0
  20. package/dist/chunk-3RU7JMFE.js +27 -0
  21. package/dist/chunk-5TWRK4NW.js +783 -0
  22. package/dist/chunk-7EOSDFS3.js +9 -0
  23. package/dist/chunk-AIQ4UOGK.js +142 -0
  24. package/dist/chunk-B3MMGTPV.js +200 -0
  25. package/dist/chunk-DAHQYLUI.js +146 -0
  26. package/dist/chunk-DGBXADSS.js +1 -0
  27. package/dist/chunk-E6KPNTWW.js +295 -0
  28. package/dist/chunk-EOAB6G2D.js +149 -0
  29. package/dist/chunk-FAOVKDVM.js +32 -0
  30. package/dist/chunk-FV76Z4Z2.js +78 -0
  31. package/dist/chunk-GLTLBUZ7.js +285 -0
  32. package/dist/chunk-GTZFV43T.js +154 -0
  33. package/dist/chunk-HRGZNL4A.js +88 -0
  34. package/dist/chunk-IEVN3J2F.js +98 -0
  35. package/dist/chunk-IRS3T6LF.js +352 -0
  36. package/dist/chunk-IYYHCQXG.js +146 -0
  37. package/dist/chunk-JIXW3455.js +89 -0
  38. package/dist/chunk-N4VAP2GB.js +77 -0
  39. package/dist/chunk-SJ2ZRYVV.js +167 -0
  40. package/dist/chunk-SNU4YXOR.js +66 -0
  41. package/dist/chunk-TT6JQATV.js +99 -0
  42. package/dist/chunk-UPQ3ZPCO.js +66 -0
  43. package/dist/chunk-UVUSVFOH.js +264 -0
  44. package/dist/chunk-WJFPGGJB.js +255 -0
  45. package/dist/chunk-WXEBQA7A.js +371 -0
  46. package/dist/chunk-Y2O4YYZQ.js +184 -0
  47. package/dist/cut-corner.cjs +111 -0
  48. package/dist/cut-corner.d.cts +49 -0
  49. package/dist/cut-corner.d.ts +49 -0
  50. package/dist/cut-corner.js +1 -0
  51. package/dist/dialog.cjs +441 -0
  52. package/dist/dialog.d.cts +240 -0
  53. package/dist/dialog.d.ts +240 -0
  54. package/dist/dialog.js +3 -0
  55. package/dist/feature-card.cjs +182 -0
  56. package/dist/feature-card.d.cts +54 -0
  57. package/dist/feature-card.d.ts +54 -0
  58. package/dist/feature-card.js +2 -0
  59. package/dist/filter.cjs +873 -0
  60. package/dist/filter.d.cts +129 -0
  61. package/dist/filter.d.ts +129 -0
  62. package/dist/filter.js +6 -0
  63. package/dist/index.cjs +4583 -0
  64. package/dist/index.d.cts +29 -0
  65. package/dist/index.d.ts +29 -0
  66. package/dist/index.js +27 -0
  67. package/dist/inline-select.cjs +856 -0
  68. package/dist/inline-select.d.cts +92 -0
  69. package/dist/inline-select.d.ts +92 -0
  70. package/dist/inline-select.js +6 -0
  71. package/dist/input.cjs +263 -0
  72. package/dist/input.d.cts +157 -0
  73. package/dist/input.d.ts +157 -0
  74. package/dist/input.js +4 -0
  75. package/dist/panel.cjs +185 -0
  76. package/dist/panel.d.cts +103 -0
  77. package/dist/panel.d.ts +103 -0
  78. package/dist/panel.js +2 -0
  79. package/dist/property-grid.cjs +110 -0
  80. package/dist/property-grid.d.cts +56 -0
  81. package/dist/property-grid.d.ts +56 -0
  82. package/dist/property-grid.js +2 -0
  83. package/dist/radio.cjs +74 -0
  84. package/dist/radio.d.cts +39 -0
  85. package/dist/radio.d.ts +39 -0
  86. package/dist/radio.js +2 -0
  87. package/dist/scrollbar.cjs +34 -0
  88. package/dist/scrollbar.d.cts +35 -0
  89. package/dist/scrollbar.d.ts +35 -0
  90. package/dist/scrollbar.js +1 -0
  91. package/dist/search-bar.cjs +408 -0
  92. package/dist/search-bar.d.cts +42 -0
  93. package/dist/search-bar.d.ts +42 -0
  94. package/dist/search-bar.js +4 -0
  95. package/dist/select.cjs +998 -0
  96. package/dist/select.d.cts +357 -0
  97. package/dist/select.d.ts +357 -0
  98. package/dist/select.js +5 -0
  99. package/dist/selectable-feature-card.cjs +159 -0
  100. package/dist/selectable-feature-card.d.cts +74 -0
  101. package/dist/selectable-feature-card.d.ts +74 -0
  102. package/dist/selectable-feature-card.js +3 -0
  103. package/dist/sidebar-item.cjs +175 -0
  104. package/dist/sidebar-item.d.cts +75 -0
  105. package/dist/sidebar-item.d.ts +75 -0
  106. package/dist/sidebar-item.js +2 -0
  107. package/dist/switch.cjs +86 -0
  108. package/dist/switch.d.cts +72 -0
  109. package/dist/switch.d.ts +72 -0
  110. package/dist/switch.js +2 -0
  111. package/dist/table-cell.cjs +196 -0
  112. package/dist/table-cell.d.cts +76 -0
  113. package/dist/table-cell.d.ts +76 -0
  114. package/dist/table-cell.js +2 -0
  115. package/dist/table-title.cjs +34 -0
  116. package/dist/table-title.d.cts +16 -0
  117. package/dist/table-title.d.ts +16 -0
  118. package/dist/table-title.js +2 -0
  119. package/dist/tabs.cjs +299 -0
  120. package/dist/tabs.d.cts +116 -0
  121. package/dist/tabs.d.ts +116 -0
  122. package/dist/tabs.js +2 -0
  123. package/dist/toast.cjs +87 -0
  124. package/dist/toast.d.cts +48 -0
  125. package/dist/toast.d.ts +48 -0
  126. package/dist/toast.js +2 -0
  127. package/dist/token-input.cjs +415 -0
  128. package/dist/token-input.d.cts +90 -0
  129. package/dist/token-input.d.ts +90 -0
  130. package/dist/token-input.js +3 -0
  131. package/dist/tooltip.cjs +384 -0
  132. package/dist/tooltip.d.cts +142 -0
  133. package/dist/tooltip.d.ts +142 -0
  134. package/dist/tooltip.js +2 -0
  135. package/package.json +200 -0
  136. package/src/fonts.css +33 -0
@@ -0,0 +1,384 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactDom = require('react-dom');
5
+ var clsx = require('clsx');
6
+ var tailwindMerge = require('tailwind-merge');
7
+ var classVarianceAuthority = require('class-variance-authority');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+
30
+ // src/tooltip/Tooltip.tsx
31
+ function cn(...inputs) {
32
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
33
+ }
34
+ var tooltipVariants = classVarianceAuthority.cva([
35
+ "pointer-events-none max-w-[244px] rounded-sm bg-card-reversed-background px-1.5 py-1",
36
+ "body-04 text-center text-card-reversed-foreground shadow-xs"
37
+ ]);
38
+ var TOOLTIP_OFFSET = 6;
39
+ var VIEWPORT_MARGIN = 8;
40
+ var OPPOSITE_SIDE = {
41
+ top: "bottom",
42
+ bottom: "top",
43
+ left: "right",
44
+ right: "left"
45
+ };
46
+ function sideFits(trigger, content, side, viewport) {
47
+ switch (side) {
48
+ case "top":
49
+ return trigger.top - TOOLTIP_OFFSET - content.height >= 0;
50
+ case "bottom":
51
+ return trigger.top + trigger.height + TOOLTIP_OFFSET + content.height <= viewport.height;
52
+ case "left":
53
+ return trigger.left - TOOLTIP_OFFSET - content.width >= 0;
54
+ case "right":
55
+ return trigger.left + trigger.width + TOOLTIP_OFFSET + content.width <= viewport.width;
56
+ }
57
+ }
58
+ function alignCoord(anchorStart, anchorSize, contentSize, align) {
59
+ switch (align) {
60
+ case "start":
61
+ return anchorStart;
62
+ case "center":
63
+ return anchorStart + anchorSize / 2 - contentSize / 2;
64
+ case "end":
65
+ return anchorStart + anchorSize - contentSize;
66
+ }
67
+ }
68
+ function clamp(value, min, max) {
69
+ return Math.max(min, Math.min(value, Math.max(min, max)));
70
+ }
71
+ function computeTooltipPosition(trigger, content, side, align, viewport) {
72
+ const resolvedSide = sideFits(trigger, content, side, viewport) || !sideFits(trigger, content, OPPOSITE_SIDE[side], viewport) ? side : OPPOSITE_SIDE[side];
73
+ const vertical = resolvedSide === "top" || resolvedSide === "bottom";
74
+ let top;
75
+ let left;
76
+ if (vertical) {
77
+ top = resolvedSide === "top" ? trigger.top - TOOLTIP_OFFSET - content.height : trigger.top + trigger.height + TOOLTIP_OFFSET;
78
+ left = alignCoord(trigger.left, trigger.width, content.width, align);
79
+ left = clamp(
80
+ left,
81
+ VIEWPORT_MARGIN,
82
+ viewport.width - content.width - VIEWPORT_MARGIN
83
+ );
84
+ } else {
85
+ left = resolvedSide === "left" ? trigger.left - TOOLTIP_OFFSET - content.width : trigger.left + trigger.width + TOOLTIP_OFFSET;
86
+ top = alignCoord(trigger.top, trigger.height, content.height, align);
87
+ top = clamp(
88
+ top,
89
+ VIEWPORT_MARGIN,
90
+ viewport.height - content.height - VIEWPORT_MARGIN
91
+ );
92
+ }
93
+ return { top, left, side: resolvedSide };
94
+ }
95
+ var TooltipContext = React__namespace.createContext(null);
96
+ function useTooltipContext(part) {
97
+ const context = React__namespace.useContext(TooltipContext);
98
+ if (context === null) {
99
+ throw new Error(`${part} must be used within <Tooltip.Root>`);
100
+ }
101
+ return context;
102
+ }
103
+ function setRef(ref, node) {
104
+ if (typeof ref === "function") ref(node);
105
+ else if (ref) ref.current = node;
106
+ }
107
+ function TooltipRoot({
108
+ open: openProp,
109
+ defaultOpen = false,
110
+ onOpenChange,
111
+ delayDuration = 600,
112
+ side = "top",
113
+ align = "center",
114
+ disabled = false,
115
+ children
116
+ }) {
117
+ const [uncontrolledOpen, setUncontrolledOpen] = React__namespace.useState(defaultOpen);
118
+ const isControlled = openProp !== void 0;
119
+ const rawOpen = isControlled ? openProp : uncontrolledOpen;
120
+ const open = disabled ? false : rawOpen;
121
+ const reactId = React__namespace.useId();
122
+ const contentId = `${reactId}-tooltip`;
123
+ const anchorRef = React__namespace.useRef(null);
124
+ const [anchorRect, setAnchorRect] = React__namespace.useState(null);
125
+ const timerRef = React__namespace.useRef(null);
126
+ const setOpen = React__namespace.useCallback(
127
+ (next) => {
128
+ if (!isControlled) setUncontrolledOpen(next);
129
+ onOpenChange?.(next);
130
+ },
131
+ [isControlled, onOpenChange]
132
+ );
133
+ const clearTimer = React__namespace.useCallback(() => {
134
+ if (timerRef.current !== null) {
135
+ clearTimeout(timerRef.current);
136
+ timerRef.current = null;
137
+ }
138
+ }, []);
139
+ React__namespace.useEffect(() => clearTimer, [clearTimer]);
140
+ const onTriggerPointerEnter = () => {
141
+ if (disabled) return;
142
+ clearTimer();
143
+ timerRef.current = setTimeout(() => setOpen(true), delayDuration);
144
+ };
145
+ const onTriggerPointerLeave = () => {
146
+ clearTimer();
147
+ setOpen(false);
148
+ };
149
+ const onTriggerFocus = () => {
150
+ if (disabled) return;
151
+ clearTimer();
152
+ setOpen(true);
153
+ };
154
+ const onTriggerBlur = () => {
155
+ clearTimer();
156
+ setOpen(false);
157
+ };
158
+ React__namespace.useLayoutEffect(() => {
159
+ if (!open) {
160
+ setAnchorRect(null);
161
+ return;
162
+ }
163
+ const measure = () => {
164
+ const node = anchorRef.current;
165
+ if (node) setAnchorRect(node.getBoundingClientRect());
166
+ };
167
+ measure();
168
+ window.addEventListener("scroll", measure, true);
169
+ window.addEventListener("resize", measure);
170
+ return () => {
171
+ window.removeEventListener("scroll", measure, true);
172
+ window.removeEventListener("resize", measure);
173
+ };
174
+ }, [open]);
175
+ React__namespace.useEffect(() => {
176
+ if (!open) return;
177
+ const handleEscape = (event) => {
178
+ if (event.key === "Escape") {
179
+ clearTimer();
180
+ setOpen(false);
181
+ }
182
+ };
183
+ document.addEventListener("keydown", handleEscape);
184
+ return () => document.removeEventListener("keydown", handleEscape);
185
+ }, [open, setOpen, clearTimer]);
186
+ const value = {
187
+ open,
188
+ setOpen,
189
+ disabled,
190
+ contentId,
191
+ side,
192
+ align,
193
+ anchorRef,
194
+ anchorRect,
195
+ onTriggerPointerEnter,
196
+ onTriggerPointerLeave,
197
+ onTriggerFocus,
198
+ onTriggerBlur
199
+ };
200
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipContext.Provider, { value, children });
201
+ }
202
+ function TooltipTrigger({
203
+ asChild = false,
204
+ className,
205
+ children,
206
+ ref,
207
+ onPointerEnter,
208
+ onPointerLeave,
209
+ onFocus,
210
+ onBlur,
211
+ ...props
212
+ }) {
213
+ const {
214
+ open,
215
+ disabled,
216
+ contentId,
217
+ anchorRef,
218
+ onTriggerPointerEnter,
219
+ onTriggerPointerLeave,
220
+ onTriggerFocus,
221
+ onTriggerBlur
222
+ } = useTooltipContext("Tooltip.Trigger");
223
+ const describedBy = !disabled && open ? contentId : void 0;
224
+ const handlePointerEnter = (event) => {
225
+ onPointerEnter?.(event);
226
+ onTriggerPointerEnter();
227
+ };
228
+ const handlePointerLeave = (event) => {
229
+ onPointerLeave?.(event);
230
+ onTriggerPointerLeave();
231
+ };
232
+ const handleFocus = (event) => {
233
+ onFocus?.(event);
234
+ onTriggerFocus();
235
+ };
236
+ const handleBlur = (event) => {
237
+ onBlur?.(event);
238
+ onTriggerBlur();
239
+ };
240
+ if (asChild) {
241
+ if (!React__namespace.isValidElement(children)) {
242
+ throw new Error(
243
+ "Tooltip.Trigger: `asChild` requires a single React element child"
244
+ );
245
+ }
246
+ const child = children;
247
+ const childProps = child.props;
248
+ const childHandlers = childProps;
249
+ return React__namespace.cloneElement(
250
+ child,
251
+ {
252
+ ...props,
253
+ ...childProps,
254
+ "data-slot": "tooltip-trigger",
255
+ "aria-describedby": describedBy,
256
+ onPointerEnter: (event) => {
257
+ childHandlers.onPointerEnter?.(event);
258
+ onPointerEnter?.(event);
259
+ onTriggerPointerEnter();
260
+ },
261
+ onPointerLeave: (event) => {
262
+ childHandlers.onPointerLeave?.(event);
263
+ onPointerLeave?.(event);
264
+ onTriggerPointerLeave();
265
+ },
266
+ onFocus: (event) => {
267
+ childHandlers.onFocus?.(event);
268
+ onFocus?.(event);
269
+ onTriggerFocus();
270
+ },
271
+ onBlur: (event) => {
272
+ childHandlers.onBlur?.(event);
273
+ onBlur?.(event);
274
+ onTriggerBlur();
275
+ },
276
+ className: cn(className, childHandlers.className),
277
+ ref: (node) => {
278
+ anchorRef.current = node;
279
+ setRef(ref, node);
280
+ setRef(childHandlers.ref, node);
281
+ }
282
+ },
283
+ childProps.children
284
+ );
285
+ }
286
+ return /* @__PURE__ */ jsxRuntime.jsx(
287
+ "button",
288
+ {
289
+ ...props,
290
+ type: props.type ?? "button",
291
+ "data-slot": "tooltip-trigger",
292
+ "aria-describedby": describedBy,
293
+ className,
294
+ onPointerEnter: handlePointerEnter,
295
+ onPointerLeave: handlePointerLeave,
296
+ onFocus: handleFocus,
297
+ onBlur: handleBlur,
298
+ ref: (node) => {
299
+ anchorRef.current = node;
300
+ setRef(ref, node);
301
+ },
302
+ children
303
+ }
304
+ );
305
+ }
306
+ function TooltipContent({
307
+ className,
308
+ children,
309
+ style,
310
+ ref,
311
+ ...props
312
+ }) {
313
+ const { open, contentId, side, align, anchorRect } = useTooltipContext("Tooltip.Content");
314
+ const contentRef = React__namespace.useRef(null);
315
+ const [placement, setPlacement] = React__namespace.useState(null);
316
+ React__namespace.useLayoutEffect(() => {
317
+ if (!open || anchorRect == null) {
318
+ setPlacement(null);
319
+ return;
320
+ }
321
+ const node = contentRef.current;
322
+ if (!node) return;
323
+ const rect = node.getBoundingClientRect();
324
+ setPlacement(
325
+ computeTooltipPosition(
326
+ anchorRect,
327
+ { width: rect.width, height: rect.height },
328
+ side,
329
+ align,
330
+ { width: window.innerWidth, height: window.innerHeight }
331
+ )
332
+ );
333
+ }, [open, anchorRect, side, align]);
334
+ if (!open) return null;
335
+ const positioned = placement !== null;
336
+ const positionStyle = positioned ? {
337
+ position: "absolute",
338
+ top: placement.top + window.scrollY,
339
+ left: placement.left + window.scrollX,
340
+ zIndex: 50,
341
+ ...style
342
+ } : {
343
+ position: "absolute",
344
+ top: 0,
345
+ left: 0,
346
+ visibility: "hidden",
347
+ zIndex: 50,
348
+ ...style
349
+ };
350
+ const setContentRef = (node) => {
351
+ contentRef.current = node;
352
+ setRef(ref, node);
353
+ };
354
+ return reactDom.createPortal(
355
+ /* @__PURE__ */ jsxRuntime.jsx(
356
+ "div",
357
+ {
358
+ ...props,
359
+ ref: setContentRef,
360
+ role: "tooltip",
361
+ id: contentId,
362
+ "data-slot": "tooltip-content",
363
+ "data-side": positioned ? placement.side : side,
364
+ "data-align": align,
365
+ className: cn(tooltipVariants(), className),
366
+ style: positionStyle,
367
+ children
368
+ }
369
+ ),
370
+ document.body
371
+ );
372
+ }
373
+ var Tooltip = {
374
+ Root: TooltipRoot,
375
+ Trigger: TooltipTrigger,
376
+ Content: TooltipContent
377
+ };
378
+
379
+ exports.Tooltip = Tooltip;
380
+ exports.TooltipContent = TooltipContent;
381
+ exports.TooltipRoot = TooltipRoot;
382
+ exports.TooltipTrigger = TooltipTrigger;
383
+ exports.computeTooltipPosition = computeTooltipPosition;
384
+ exports.tooltipVariants = tooltipVariants;
@@ -0,0 +1,142 @@
1
+ import * as React from 'react';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+
4
+ /** Preferred side of the trigger the bubble is placed on. */
5
+ type TooltipSide = "top" | "bottom" | "left" | "right";
6
+ /** Alignment of the bubble along the trigger's edge. */
7
+ type TooltipAlign = "start" | "center" | "end";
8
+ /** The minimal rect shape the placement math needs (a `DOMRect` satisfies it). */
9
+ interface TooltipRect {
10
+ top: number;
11
+ left: number;
12
+ width: number;
13
+ height: number;
14
+ }
15
+ /**
16
+ * Pure placement math for the portaled bubble. Given the trigger rect, the
17
+ * measured bubble size, the preferred `side`/`align`, and the viewport, returns
18
+ * the viewport-relative `top`/`left` and the RESOLVED `side` (after flip). The
19
+ * caller offsets by `scrollX`/`scrollY` for absolute document coordinates.
20
+ *
21
+ * Rules: place on the preferred `side`; **flip** to the opposite side only when
22
+ * the preferred side overflows the viewport AND the opposite side has room
23
+ * (otherwise keep the preferred side); then clamp the CROSS axis into the
24
+ * viewport so the bubble never bleeds off-screen. The main axis is owned by the
25
+ * side/flip, so only the cross axis is clamped. Kept free of the DOM/React so
26
+ * every branch is unit-testable.
27
+ */
28
+ declare function computeTooltipPosition(trigger: TooltipRect, content: {
29
+ width: number;
30
+ height: number;
31
+ }, side: TooltipSide, align: TooltipAlign, viewport: {
32
+ width: number;
33
+ height: number;
34
+ }): {
35
+ top: number;
36
+ left: number;
37
+ side: TooltipSide;
38
+ };
39
+ interface TooltipRootProps {
40
+ /** Controlled open state. Pair with `onOpenChange`. Omit for uncontrolled. */
41
+ open?: boolean;
42
+ /** Initial open state when uncontrolled. Ignored if `open` is provided. Default `false`. */
43
+ defaultOpen?: boolean;
44
+ /** Called with the next open state from hover/focus/leave/blur/Escape. */
45
+ onOpenChange?: (open: boolean) => void;
46
+ /**
47
+ * Milliseconds a pointer must hover the trigger before the tooltip opens.
48
+ * Default `600`. Keyboard focus opens immediately (no delay).
49
+ */
50
+ delayDuration?: number;
51
+ /** Preferred side of the trigger to place the bubble on. Default `"top"`. */
52
+ side?: TooltipSide;
53
+ /** Alignment of the bubble along the trigger's edge. Default `"center"`. */
54
+ align?: TooltipAlign;
55
+ /**
56
+ * When `true` the tooltip never opens: the trigger still renders, but no
57
+ * `aria-describedby` is wired and no hover/focus fires an open.
58
+ */
59
+ disabled?: boolean;
60
+ children?: React.ReactNode;
61
+ }
62
+ /**
63
+ * State owner + context provider for the compound `Tooltip`. Renders no DOM of
64
+ * its own (a fragment) — it only coordinates the trigger and the portaled
65
+ * bubble. Owns the open state (controlled via `open`/`onOpenChange`, or
66
+ * uncontrolled via `defaultOpen`), the hover-open timer, the anchor rect + its
67
+ * reposition listeners, and the Escape-to-close listener.
68
+ */
69
+ declare function TooltipRoot({ open: openProp, defaultOpen, onOpenChange, delayDuration, side, align, disabled, children, }: TooltipRootProps): React.JSX.Element;
70
+ interface TooltipTriggerProps extends React.ComponentProps<"button"> {
71
+ /**
72
+ * Render the single child element as the trigger instead of a `<button>`, so
73
+ * an existing control (an `IconButton`, `Button`, anchor…) becomes the anchor.
74
+ * The clone pattern: merge `ref`, compose event handlers, merge `className`.
75
+ */
76
+ asChild?: boolean;
77
+ }
78
+ /**
79
+ * The anchor the tooltip describes. Renders a native `<button type="button">`
80
+ * by default (focusable, correct semantics), or projects its props/ref onto the
81
+ * single child when `asChild`. Binds the pointer/focus handlers that drive
82
+ * open/close (composed with any consumer handler of the same name) and, while
83
+ * open and not `disabled`, wires `aria-describedby` to the bubble. Registers the
84
+ * anchor node for positioning. Forwards `ref` to the trigger element.
85
+ */
86
+ declare function TooltipTrigger({ asChild, className, children, ref, onPointerEnter, onPointerLeave, onFocus, onBlur, ...props }: TooltipTriggerProps): React.JSX.Element;
87
+ interface TooltipContentProps extends React.ComponentProps<"div"> {
88
+ }
89
+ /**
90
+ * The bubble. Portaled to `document.body` via `createPortal` (escaping
91
+ * `overflow`/stacking ancestors, like `SelectListbox`/`DialogContent`), rendered
92
+ * **only while open** — closed, it is removed from the DOM and the a11y tree.
93
+ * Absolutely positioned from the trigger rect via {@link computeTooltipPosition}
94
+ * (preferred side, flips when it would overflow, clamps the cross-axis).
95
+ * `role="tooltip"`; `data-side`/`data-align` reflect the RESOLVED placement.
96
+ *
97
+ * **Content must be non-interactive** — the WAI-ARIA tooltip pattern forbids
98
+ * focusable/interactive content inside a tooltip (there is no accessible way to
99
+ * reach it, and the bubble is `pointer-events-none`). Pass text or decorative
100
+ * `ReactNode` only. Forwards `ref` to the bubble.
101
+ */
102
+ declare function TooltipContent({ className, children, style, ref, ...props }: TooltipContentProps): React.ReactPortal | null;
103
+ /**
104
+ * Compound tooltip — a small floating label shown on hover (after
105
+ * `delayDuration`) or keyboard focus (immediately), describing its trigger.
106
+ * Assemble from its namespaced parts:
107
+ *
108
+ * ```tsx
109
+ * <Tooltip.Root side="top">
110
+ * <Tooltip.Trigger asChild>
111
+ * <IconButton aria-label="Info" />
112
+ * </Tooltip.Trigger>
113
+ * <Tooltip.Content>Explanatory text</Tooltip.Content>
114
+ * </Tooltip.Root>
115
+ * ```
116
+ */
117
+ declare const Tooltip: {
118
+ Root: typeof TooltipRoot;
119
+ Trigger: typeof TooltipTrigger;
120
+ Content: typeof TooltipContent;
121
+ };
122
+
123
+ /**
124
+ * Tooltip bubble styling — the Figma `Tooltip` (node `5153:4063`). Binds ONLY to
125
+ * the semantic token layer (never primitives); theme switching is automatic via
126
+ * `.dark`, so no `dark:` variants.
127
+ *
128
+ * The surface is the fixed dark "reversed" card — the SAME utilities
129
+ * `toastVariants.ts` binds (`bg-card-reversed-background` /
130
+ * `text-card-reversed-foreground`) — so the two dark surfaces stay in lock-step.
131
+ * There is no `variation`/`size` axis (the Figma frame shows a single bubble),
132
+ * and no arrow/caret element (absent from Figma).
133
+ *
134
+ * `max-w-[244px]` is the one allowed arbitrary value: it is the Figma-exact wrap
135
+ * boundary (long text wraps; the sample's single-word `whitespace-nowrap` is a
136
+ * content artifact and is intentionally NOT carried over). `pointer-events-none`
137
+ * is intrinsic — the bubble is descriptive, never interactive, so it can never
138
+ * steal the pointer or cause a hover-leave flicker.
139
+ */
140
+ declare const tooltipVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
141
+
142
+ export { Tooltip, type TooltipAlign, TooltipContent, type TooltipContentProps, type TooltipRect, TooltipRoot, type TooltipRootProps, type TooltipSide, TooltipTrigger, type TooltipTriggerProps, computeTooltipPosition, tooltipVariants };
@@ -0,0 +1,142 @@
1
+ import * as React from 'react';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+
4
+ /** Preferred side of the trigger the bubble is placed on. */
5
+ type TooltipSide = "top" | "bottom" | "left" | "right";
6
+ /** Alignment of the bubble along the trigger's edge. */
7
+ type TooltipAlign = "start" | "center" | "end";
8
+ /** The minimal rect shape the placement math needs (a `DOMRect` satisfies it). */
9
+ interface TooltipRect {
10
+ top: number;
11
+ left: number;
12
+ width: number;
13
+ height: number;
14
+ }
15
+ /**
16
+ * Pure placement math for the portaled bubble. Given the trigger rect, the
17
+ * measured bubble size, the preferred `side`/`align`, and the viewport, returns
18
+ * the viewport-relative `top`/`left` and the RESOLVED `side` (after flip). The
19
+ * caller offsets by `scrollX`/`scrollY` for absolute document coordinates.
20
+ *
21
+ * Rules: place on the preferred `side`; **flip** to the opposite side only when
22
+ * the preferred side overflows the viewport AND the opposite side has room
23
+ * (otherwise keep the preferred side); then clamp the CROSS axis into the
24
+ * viewport so the bubble never bleeds off-screen. The main axis is owned by the
25
+ * side/flip, so only the cross axis is clamped. Kept free of the DOM/React so
26
+ * every branch is unit-testable.
27
+ */
28
+ declare function computeTooltipPosition(trigger: TooltipRect, content: {
29
+ width: number;
30
+ height: number;
31
+ }, side: TooltipSide, align: TooltipAlign, viewport: {
32
+ width: number;
33
+ height: number;
34
+ }): {
35
+ top: number;
36
+ left: number;
37
+ side: TooltipSide;
38
+ };
39
+ interface TooltipRootProps {
40
+ /** Controlled open state. Pair with `onOpenChange`. Omit for uncontrolled. */
41
+ open?: boolean;
42
+ /** Initial open state when uncontrolled. Ignored if `open` is provided. Default `false`. */
43
+ defaultOpen?: boolean;
44
+ /** Called with the next open state from hover/focus/leave/blur/Escape. */
45
+ onOpenChange?: (open: boolean) => void;
46
+ /**
47
+ * Milliseconds a pointer must hover the trigger before the tooltip opens.
48
+ * Default `600`. Keyboard focus opens immediately (no delay).
49
+ */
50
+ delayDuration?: number;
51
+ /** Preferred side of the trigger to place the bubble on. Default `"top"`. */
52
+ side?: TooltipSide;
53
+ /** Alignment of the bubble along the trigger's edge. Default `"center"`. */
54
+ align?: TooltipAlign;
55
+ /**
56
+ * When `true` the tooltip never opens: the trigger still renders, but no
57
+ * `aria-describedby` is wired and no hover/focus fires an open.
58
+ */
59
+ disabled?: boolean;
60
+ children?: React.ReactNode;
61
+ }
62
+ /**
63
+ * State owner + context provider for the compound `Tooltip`. Renders no DOM of
64
+ * its own (a fragment) — it only coordinates the trigger and the portaled
65
+ * bubble. Owns the open state (controlled via `open`/`onOpenChange`, or
66
+ * uncontrolled via `defaultOpen`), the hover-open timer, the anchor rect + its
67
+ * reposition listeners, and the Escape-to-close listener.
68
+ */
69
+ declare function TooltipRoot({ open: openProp, defaultOpen, onOpenChange, delayDuration, side, align, disabled, children, }: TooltipRootProps): React.JSX.Element;
70
+ interface TooltipTriggerProps extends React.ComponentProps<"button"> {
71
+ /**
72
+ * Render the single child element as the trigger instead of a `<button>`, so
73
+ * an existing control (an `IconButton`, `Button`, anchor…) becomes the anchor.
74
+ * The clone pattern: merge `ref`, compose event handlers, merge `className`.
75
+ */
76
+ asChild?: boolean;
77
+ }
78
+ /**
79
+ * The anchor the tooltip describes. Renders a native `<button type="button">`
80
+ * by default (focusable, correct semantics), or projects its props/ref onto the
81
+ * single child when `asChild`. Binds the pointer/focus handlers that drive
82
+ * open/close (composed with any consumer handler of the same name) and, while
83
+ * open and not `disabled`, wires `aria-describedby` to the bubble. Registers the
84
+ * anchor node for positioning. Forwards `ref` to the trigger element.
85
+ */
86
+ declare function TooltipTrigger({ asChild, className, children, ref, onPointerEnter, onPointerLeave, onFocus, onBlur, ...props }: TooltipTriggerProps): React.JSX.Element;
87
+ interface TooltipContentProps extends React.ComponentProps<"div"> {
88
+ }
89
+ /**
90
+ * The bubble. Portaled to `document.body` via `createPortal` (escaping
91
+ * `overflow`/stacking ancestors, like `SelectListbox`/`DialogContent`), rendered
92
+ * **only while open** — closed, it is removed from the DOM and the a11y tree.
93
+ * Absolutely positioned from the trigger rect via {@link computeTooltipPosition}
94
+ * (preferred side, flips when it would overflow, clamps the cross-axis).
95
+ * `role="tooltip"`; `data-side`/`data-align` reflect the RESOLVED placement.
96
+ *
97
+ * **Content must be non-interactive** — the WAI-ARIA tooltip pattern forbids
98
+ * focusable/interactive content inside a tooltip (there is no accessible way to
99
+ * reach it, and the bubble is `pointer-events-none`). Pass text or decorative
100
+ * `ReactNode` only. Forwards `ref` to the bubble.
101
+ */
102
+ declare function TooltipContent({ className, children, style, ref, ...props }: TooltipContentProps): React.ReactPortal | null;
103
+ /**
104
+ * Compound tooltip — a small floating label shown on hover (after
105
+ * `delayDuration`) or keyboard focus (immediately), describing its trigger.
106
+ * Assemble from its namespaced parts:
107
+ *
108
+ * ```tsx
109
+ * <Tooltip.Root side="top">
110
+ * <Tooltip.Trigger asChild>
111
+ * <IconButton aria-label="Info" />
112
+ * </Tooltip.Trigger>
113
+ * <Tooltip.Content>Explanatory text</Tooltip.Content>
114
+ * </Tooltip.Root>
115
+ * ```
116
+ */
117
+ declare const Tooltip: {
118
+ Root: typeof TooltipRoot;
119
+ Trigger: typeof TooltipTrigger;
120
+ Content: typeof TooltipContent;
121
+ };
122
+
123
+ /**
124
+ * Tooltip bubble styling — the Figma `Tooltip` (node `5153:4063`). Binds ONLY to
125
+ * the semantic token layer (never primitives); theme switching is automatic via
126
+ * `.dark`, so no `dark:` variants.
127
+ *
128
+ * The surface is the fixed dark "reversed" card — the SAME utilities
129
+ * `toastVariants.ts` binds (`bg-card-reversed-background` /
130
+ * `text-card-reversed-foreground`) — so the two dark surfaces stay in lock-step.
131
+ * There is no `variation`/`size` axis (the Figma frame shows a single bubble),
132
+ * and no arrow/caret element (absent from Figma).
133
+ *
134
+ * `max-w-[244px]` is the one allowed arbitrary value: it is the Figma-exact wrap
135
+ * boundary (long text wraps; the sample's single-word `whitespace-nowrap` is a
136
+ * content artifact and is intentionally NOT carried over). `pointer-events-none`
137
+ * is intrinsic — the bubble is descriptive, never interactive, so it can never
138
+ * steal the pointer or cause a hover-leave flicker.
139
+ */
140
+ declare const tooltipVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
141
+
142
+ export { Tooltip, type TooltipAlign, TooltipContent, type TooltipContentProps, type TooltipRect, TooltipRoot, type TooltipRootProps, type TooltipSide, TooltipTrigger, type TooltipTriggerProps, computeTooltipPosition, tooltipVariants };
@@ -0,0 +1,2 @@
1
+ export { Tooltip, TooltipContent, TooltipRoot, TooltipTrigger, computeTooltipPosition, tooltipVariants } from './chunk-IRS3T6LF.js';
2
+ import './chunk-7EOSDFS3.js';