@corefoundry-labs/forge-ui 1.0.2 → 1.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 (147) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +78 -0
  3. package/dist/components/layout/ThemeScope/ThemeScope.d.ts +11 -0
  4. package/dist/components/layout/ThemeScope/ThemeScope.d.ts.map +1 -0
  5. package/dist/components/layout/ThemeScope/ThemeScope.js +13 -0
  6. package/dist/components/layout/ThemeScope/index.d.ts +3 -0
  7. package/dist/components/layout/ThemeScope/index.d.ts.map +1 -0
  8. package/dist/components/layout/ThemeScope/index.js +1 -0
  9. package/dist/componentsV2/actions/ButtonV2/ButtonV2.d.ts +21 -0
  10. package/dist/componentsV2/actions/ButtonV2/ButtonV2.d.ts.map +1 -0
  11. package/dist/componentsV2/actions/ButtonV2/ButtonV2.js +17 -0
  12. package/dist/componentsV2/actions/ButtonV2/ButtonV2.module.css +158 -0
  13. package/dist/componentsV2/actions/ButtonV2/index.d.ts +3 -0
  14. package/dist/componentsV2/actions/ButtonV2/index.d.ts.map +1 -0
  15. package/dist/componentsV2/actions/ButtonV2/index.js +1 -0
  16. package/dist/componentsV2/data-display/AvatarV2/AvatarV2.d.ts +36 -0
  17. package/dist/componentsV2/data-display/AvatarV2/AvatarV2.d.ts.map +1 -0
  18. package/dist/componentsV2/data-display/AvatarV2/AvatarV2.js +23 -0
  19. package/dist/componentsV2/data-display/AvatarV2/AvatarV2.module.css +156 -0
  20. package/dist/componentsV2/data-display/AvatarV2/index.d.ts +3 -0
  21. package/dist/componentsV2/data-display/AvatarV2/index.d.ts.map +1 -0
  22. package/dist/componentsV2/data-display/AvatarV2/index.js +1 -0
  23. package/dist/componentsV2/feedback/AlertV2/AlertV2.d.ts +25 -0
  24. package/dist/componentsV2/feedback/AlertV2/AlertV2.d.ts.map +1 -0
  25. package/dist/componentsV2/feedback/AlertV2/AlertV2.js +16 -0
  26. package/dist/componentsV2/feedback/AlertV2/AlertV2.module.css +144 -0
  27. package/dist/componentsV2/feedback/AlertV2/index.d.ts +3 -0
  28. package/dist/componentsV2/feedback/AlertV2/index.d.ts.map +1 -0
  29. package/dist/componentsV2/feedback/AlertV2/index.js +1 -0
  30. package/dist/componentsV2/feedback/FeedbackStateV2/FeedbackStateV2.d.ts +13 -0
  31. package/dist/componentsV2/feedback/FeedbackStateV2/FeedbackStateV2.d.ts.map +1 -0
  32. package/dist/componentsV2/feedback/FeedbackStateV2/FeedbackStateV2.js +18 -0
  33. package/dist/componentsV2/feedback/FeedbackStateV2/FeedbackStateV2.module.css +102 -0
  34. package/dist/componentsV2/feedback/FeedbackStateV2/index.d.ts +3 -0
  35. package/dist/componentsV2/feedback/FeedbackStateV2/index.d.ts.map +1 -0
  36. package/dist/componentsV2/feedback/FeedbackStateV2/index.js +1 -0
  37. package/dist/componentsV2/feedback/ProgressV2/ProgressV2.d.ts +35 -0
  38. package/dist/componentsV2/feedback/ProgressV2/ProgressV2.d.ts.map +1 -0
  39. package/dist/componentsV2/feedback/ProgressV2/ProgressV2.js +15 -0
  40. package/dist/componentsV2/feedback/ProgressV2/ProgressV2.module.css +161 -0
  41. package/dist/componentsV2/feedback/ProgressV2/index.d.ts +3 -0
  42. package/dist/componentsV2/feedback/ProgressV2/index.d.ts.map +1 -0
  43. package/dist/componentsV2/feedback/ProgressV2/index.js +1 -0
  44. package/dist/componentsV2/feedback/SkeletonV2/SkeletonV2.d.ts +20 -0
  45. package/dist/componentsV2/feedback/SkeletonV2/SkeletonV2.d.ts.map +1 -0
  46. package/dist/componentsV2/feedback/SkeletonV2/SkeletonV2.js +8 -0
  47. package/dist/componentsV2/feedback/SkeletonV2/SkeletonV2.module.css +92 -0
  48. package/dist/componentsV2/feedback/SkeletonV2/index.d.ts +3 -0
  49. package/dist/componentsV2/feedback/SkeletonV2/index.d.ts.map +1 -0
  50. package/dist/componentsV2/feedback/SkeletonV2/index.js +1 -0
  51. package/dist/componentsV2/feedback/SnackbarV2/SnackbarV2.d.ts +35 -0
  52. package/dist/componentsV2/feedback/SnackbarV2/SnackbarV2.d.ts.map +1 -0
  53. package/dist/componentsV2/feedback/SnackbarV2/SnackbarV2.js +90 -0
  54. package/dist/componentsV2/feedback/SnackbarV2/SnackbarV2.module.css +162 -0
  55. package/dist/componentsV2/feedback/SnackbarV2/index.d.ts +3 -0
  56. package/dist/componentsV2/feedback/SnackbarV2/index.d.ts.map +1 -0
  57. package/dist/componentsV2/feedback/SnackbarV2/index.js +1 -0
  58. package/dist/componentsV2/forms/CheckboxV2/CheckboxV2.d.ts +10 -0
  59. package/dist/componentsV2/forms/CheckboxV2/CheckboxV2.d.ts.map +1 -0
  60. package/dist/componentsV2/forms/CheckboxV2/CheckboxV2.js +18 -0
  61. package/dist/componentsV2/forms/CheckboxV2/CheckboxV2.module.css +137 -0
  62. package/dist/componentsV2/forms/CheckboxV2/index.d.ts +3 -0
  63. package/dist/componentsV2/forms/CheckboxV2/index.d.ts.map +1 -0
  64. package/dist/componentsV2/forms/CheckboxV2/index.js +1 -0
  65. package/dist/componentsV2/forms/SelectV2/SelectV2.d.ts +10 -0
  66. package/dist/componentsV2/forms/SelectV2/SelectV2.d.ts.map +1 -0
  67. package/dist/componentsV2/forms/SelectV2/SelectV2.js +7 -0
  68. package/dist/componentsV2/forms/SelectV2/SelectV2.module.css +90 -0
  69. package/dist/componentsV2/forms/SelectV2/index.d.ts +3 -0
  70. package/dist/componentsV2/forms/SelectV2/index.d.ts.map +1 -0
  71. package/dist/componentsV2/forms/SelectV2/index.js +1 -0
  72. package/dist/componentsV2/forms/SwitchV2/SwitchV2.d.ts +8 -0
  73. package/dist/componentsV2/forms/SwitchV2/SwitchV2.d.ts.map +1 -0
  74. package/dist/componentsV2/forms/SwitchV2/SwitchV2.js +8 -0
  75. package/dist/componentsV2/forms/SwitchV2/SwitchV2.module.css +129 -0
  76. package/dist/componentsV2/forms/SwitchV2/index.d.ts +3 -0
  77. package/dist/componentsV2/forms/SwitchV2/index.d.ts.map +1 -0
  78. package/dist/componentsV2/forms/SwitchV2/index.js +1 -0
  79. package/dist/componentsV2/forms/TextInputV2/TextInputV2.d.ts +10 -0
  80. package/dist/componentsV2/forms/TextInputV2/TextInputV2.d.ts.map +1 -0
  81. package/dist/componentsV2/forms/TextInputV2/TextInputV2.js +7 -0
  82. package/dist/componentsV2/forms/TextInputV2/TextInputV2.module.css +64 -0
  83. package/dist/componentsV2/forms/TextInputV2/index.d.ts +3 -0
  84. package/dist/componentsV2/forms/TextInputV2/index.d.ts.map +1 -0
  85. package/dist/componentsV2/forms/TextInputV2/index.js +1 -0
  86. package/dist/componentsV2/forms/selectionControl.d.ts +14 -0
  87. package/dist/componentsV2/forms/selectionControl.d.ts.map +1 -0
  88. package/dist/componentsV2/forms/selectionControl.js +1 -0
  89. package/dist/componentsV2/navigation/TabsV2/TabsV2.d.ts +30 -0
  90. package/dist/componentsV2/navigation/TabsV2/TabsV2.d.ts.map +1 -0
  91. package/dist/componentsV2/navigation/TabsV2/TabsV2.js +54 -0
  92. package/dist/componentsV2/navigation/TabsV2/TabsV2.module.css +128 -0
  93. package/dist/componentsV2/navigation/TabsV2/index.d.ts +3 -0
  94. package/dist/componentsV2/navigation/TabsV2/index.d.ts.map +1 -0
  95. package/dist/componentsV2/navigation/TabsV2/index.js +1 -0
  96. package/dist/componentsV2/overlays/DialogV2/DialogV2.d.ts +22 -0
  97. package/dist/componentsV2/overlays/DialogV2/DialogV2.d.ts.map +1 -0
  98. package/dist/componentsV2/overlays/DialogV2/DialogV2.js +77 -0
  99. package/dist/componentsV2/overlays/DialogV2/DialogV2.module.css +91 -0
  100. package/dist/componentsV2/overlays/DialogV2/index.d.ts +3 -0
  101. package/dist/componentsV2/overlays/DialogV2/index.d.ts.map +1 -0
  102. package/dist/componentsV2/overlays/DialogV2/index.js +1 -0
  103. package/dist/componentsV2/overlays/DropdownMenuV2/DropdownMenuV2.d.ts +40 -0
  104. package/dist/componentsV2/overlays/DropdownMenuV2/DropdownMenuV2.d.ts.map +1 -0
  105. package/dist/componentsV2/overlays/DropdownMenuV2/DropdownMenuV2.js +115 -0
  106. package/dist/componentsV2/overlays/DropdownMenuV2/DropdownMenuV2.module.css +122 -0
  107. package/dist/componentsV2/overlays/DropdownMenuV2/index.d.ts +3 -0
  108. package/dist/componentsV2/overlays/DropdownMenuV2/index.d.ts.map +1 -0
  109. package/dist/componentsV2/overlays/DropdownMenuV2/index.js +1 -0
  110. package/dist/componentsV2/overlays/PopoverV2/PopoverV2.d.ts +46 -0
  111. package/dist/componentsV2/overlays/PopoverV2/PopoverV2.d.ts.map +1 -0
  112. package/dist/componentsV2/overlays/PopoverV2/PopoverV2.js +41 -0
  113. package/dist/componentsV2/overlays/PopoverV2/PopoverV2.module.css +63 -0
  114. package/dist/componentsV2/overlays/PopoverV2/index.d.ts +3 -0
  115. package/dist/componentsV2/overlays/PopoverV2/index.d.ts.map +1 -0
  116. package/dist/componentsV2/overlays/PopoverV2/index.js +1 -0
  117. package/dist/componentsV2/overlays/TooltipV2/TooltipV2.d.ts +18 -0
  118. package/dist/componentsV2/overlays/TooltipV2/TooltipV2.d.ts.map +1 -0
  119. package/dist/componentsV2/overlays/TooltipV2/TooltipV2.js +66 -0
  120. package/dist/componentsV2/overlays/TooltipV2/TooltipV2.module.css +69 -0
  121. package/dist/componentsV2/overlays/TooltipV2/index.d.ts +3 -0
  122. package/dist/componentsV2/overlays/TooltipV2/index.d.ts.map +1 -0
  123. package/dist/componentsV2/overlays/TooltipV2/index.js +1 -0
  124. package/dist/componentsV2/overlays/layer.d.ts +29 -0
  125. package/dist/componentsV2/overlays/layer.d.ts.map +1 -0
  126. package/dist/componentsV2/overlays/layer.js +224 -0
  127. package/dist/componentsV2/overlays/position.d.ts +32 -0
  128. package/dist/componentsV2/overlays/position.d.ts.map +1 -0
  129. package/dist/componentsV2/overlays/position.js +42 -0
  130. package/dist/componentsV2/status/BadgeV2/BadgeV2.d.ts +18 -0
  131. package/dist/componentsV2/status/BadgeV2/BadgeV2.d.ts.map +1 -0
  132. package/dist/componentsV2/status/BadgeV2/BadgeV2.js +7 -0
  133. package/dist/componentsV2/status/BadgeV2/BadgeV2.module.css +94 -0
  134. package/dist/componentsV2/status/BadgeV2/index.d.ts +3 -0
  135. package/dist/componentsV2/status/BadgeV2/index.d.ts.map +1 -0
  136. package/dist/componentsV2/status/BadgeV2/index.js +1 -0
  137. package/dist/componentsV2/surfaces/CardV2/CardV2.d.ts +28 -0
  138. package/dist/componentsV2/surfaces/CardV2/CardV2.d.ts.map +1 -0
  139. package/dist/componentsV2/surfaces/CardV2/CardV2.js +16 -0
  140. package/dist/componentsV2/surfaces/CardV2/CardV2.module.css +84 -0
  141. package/dist/componentsV2/surfaces/CardV2/index.d.ts +3 -0
  142. package/dist/componentsV2/surfaces/CardV2/index.d.ts.map +1 -0
  143. package/dist/componentsV2/surfaces/CardV2/index.js +1 -0
  144. package/dist/index.d.ts +38 -0
  145. package/dist/index.d.ts.map +1 -1
  146. package/dist/index.js +20 -0
  147. package/package.json +16 -5
@@ -0,0 +1,46 @@
1
+ import '@corefoundry-labs/forge-tokens/theme-v2/tokens.css';
2
+ import { type AriaRole, type HTMLAttributes, type ReactNode, type RefObject } from 'react';
3
+ import { type OverlayTrigger } from '../layer';
4
+ import type { OverlayAlign, OverlayPlacement } from '../position';
5
+ export type PopoverV2Width = 'compact' | 'regular';
6
+ export type PopoverV2Placement = OverlayPlacement;
7
+ export type PopoverV2Align = OverlayAlign;
8
+ type PopoverV2Base = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'role' | 'popover' | 'aria-label' | 'aria-labelledby'> & {
9
+ description?: ReactNode;
10
+ children?: ReactNode;
11
+ width?: PopoverV2Width;
12
+ placement?: PopoverV2Placement;
13
+ align?: PopoverV2Align;
14
+ role?: AriaRole;
15
+ initialFocus?: 'content' | 'none';
16
+ };
17
+ type PopoverV2Name = {
18
+ title: ReactNode;
19
+ 'aria-label'?: undefined;
20
+ 'aria-labelledby'?: undefined;
21
+ } | {
22
+ title?: undefined;
23
+ 'aria-label': string;
24
+ 'aria-labelledby'?: undefined;
25
+ } | {
26
+ title?: undefined;
27
+ 'aria-label'?: undefined;
28
+ 'aria-labelledby': string;
29
+ };
30
+ type PopoverV2Anchor = {
31
+ trigger: OverlayTrigger;
32
+ anchorRef?: undefined;
33
+ open?: boolean;
34
+ defaultOpen?: boolean;
35
+ onOpenChange?: (open: boolean) => void;
36
+ } | {
37
+ trigger?: undefined;
38
+ anchorRef: RefObject<HTMLElement | null>;
39
+ open: boolean;
40
+ defaultOpen?: undefined;
41
+ onOpenChange: (open: boolean) => void;
42
+ };
43
+ export type PopoverV2Props = PopoverV2Base & PopoverV2Name & PopoverV2Anchor;
44
+ export declare const PopoverV2: import("react").ForwardRefExoticComponent<PopoverV2Props & import("react").RefAttributes<HTMLDivElement>>;
45
+ export {};
46
+ //# sourceMappingURL=PopoverV2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PopoverV2.d.ts","sourceRoot":"","sources":["../../../../src/componentsV2/overlays/PopoverV2/PopoverV2.tsx"],"names":[],"mappings":"AAAA,OAAO,oDAAoD,CAAC;AAC5D,OAAO,EAML,KAAK,QAAQ,EACb,KAAK,cAAc,EAEnB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGlE,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,CAAC;AACnD,MAAM,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAClD,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC;AAE1C,KAAK,aAAa,GAAG,IAAI,CACvB,cAAc,CAAC,cAAc,CAAC,EAC9B,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,iBAAiB,CAChE,GAAG;IACF,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CACnC,CAAC;AAEF,KAAK,aAAa,GACd;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,GAC7E;IAAE,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,GAC1E;IAAE,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,KAAK,eAAe,GAChB;IACE,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,GACD;IACE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAEN,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,aAAa,GAAG,eAAe,CAAC;AAE7E,eAAO,MAAM,SAAS,2GAuFpB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import '@corefoundry-labs/forge-tokens/theme-v2/tokens.css';
3
+ import { cloneElement, forwardRef, useId, useImperativeHandle, useRef, } from 'react';
4
+ import { chain, focusableIn, useAnchoredPanel, useDismiss, useEscapeLayer, useOpenState, useTriggerRef, } from '../layer';
5
+ import styles from './PopoverV2.module.css';
6
+ export const PopoverV2 = forwardRef(function PopoverV2({ trigger, anchorRef: externalAnchor, open: openProp, defaultOpen, onOpenChange, title, description, children, width = 'compact', placement = 'bottom', align = 'start', role = 'dialog', initialFocus = 'content', id, className, 'aria-label': label, 'aria-labelledby': labelledBy, ...props }, ref) {
7
+ const generated = useId();
8
+ const panelId = id ?? generated;
9
+ const [open, setOpen] = useOpenState(openProp, defaultOpen, onOpenChange);
10
+ const panelRef = useRef(null);
11
+ const triggerRef = useRef(null);
12
+ const anchorRef = externalAnchor ?? triggerRef;
13
+ const attachTrigger = useTriggerRef(triggerRef, trigger?.props.ref);
14
+ useImperativeHandle(ref, () => panelRef.current);
15
+ const close = () => setOpen(false);
16
+ useEscapeLayer(open, panelRef, close);
17
+ useDismiss(open, panelRef, anchorRef, close);
18
+ useAnchoredPanel({
19
+ open,
20
+ anchorRef,
21
+ panelRef,
22
+ placement,
23
+ align,
24
+ restoreFocus: true,
25
+ onShown: () => {
26
+ const panel = panelRef.current;
27
+ if (initialFocus === 'none' || !panel)
28
+ return;
29
+ (focusableIn(panel)[0] ?? panel).focus({ preventScroll: true });
30
+ },
31
+ });
32
+ const titleId = `${panelId}-title`;
33
+ return (_jsxs(_Fragment, { children: [trigger &&
34
+ cloneElement(trigger, {
35
+ ref: attachTrigger,
36
+ 'aria-haspopup': role === 'dialog' ? 'dialog' : undefined,
37
+ 'aria-expanded': open,
38
+ 'aria-controls': role === 'dialog' ? undefined : panelId,
39
+ onClick: chain(trigger.props.onClick, (_event) => setOpen(!open)),
40
+ }), _jsxs("div", { ...props, ref: panelRef, id: panelId, role: role, popover: "manual", tabIndex: -1, "aria-label": label, "aria-labelledby": labelledBy ?? (title != null ? titleId : undefined), "data-state": open ? 'open' : 'closed', "data-width": width, className: [styles.popover, styles[width], className].filter(Boolean).join(' '), children: [title != null && (_jsxs(_Fragment, { children: [_jsx("div", { id: titleId, className: styles.title, children: title }), _jsx("div", { className: styles.separator, "aria-hidden": "true" })] })), description != null && _jsx("div", { className: styles.description, children: description }), children] })] }));
41
+ });
@@ -0,0 +1,63 @@
1
+ .popover {
2
+ --overlay-offset: var(--cf-v2-popover-offset);
3
+ position: fixed;
4
+ inset: auto;
5
+ box-sizing: border-box;
6
+ max-width: calc(100vw - 2 * var(--cf-v2-overlay-viewport-margin));
7
+ max-height: calc(100dvh - 2 * var(--cf-v2-overlay-viewport-margin));
8
+ margin: 0;
9
+ padding: var(--cf-v2-popover-padding-block) var(--cf-v2-popover-padding-inline);
10
+ overflow: auto;
11
+ border: var(--cf-v2-popover-border-width) solid var(--cf-v2-outline);
12
+ border-radius: var(--cf-v2-popover-radius);
13
+ background: var(--cf-v2-surface-container);
14
+ color: var(--cf-v2-on-surface);
15
+ font-family: inherit;
16
+ font-size: var(--cf-v2-popover-body-font-size);
17
+ line-height: normal;
18
+ }
19
+
20
+ .popover[data-state='open'] {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: var(--cf-v2-popover-gap);
24
+ }
25
+
26
+ .popover[data-state='closed'] {
27
+ display: none;
28
+ }
29
+
30
+ .popover:focus {
31
+ outline: none;
32
+ }
33
+
34
+ .popover:focus-visible {
35
+ outline: var(--cf-v2-popover-focus-width) solid var(--cf-v2-focus-ring);
36
+ outline-offset: calc(-1 * var(--cf-v2-popover-focus-width));
37
+ }
38
+
39
+ .compact {
40
+ width: var(--cf-v2-popover-width-compact);
41
+ }
42
+
43
+ .regular {
44
+ width: var(--cf-v2-popover-width-regular);
45
+ }
46
+
47
+ .title {
48
+ font-size: var(--cf-v2-popover-title-font-size);
49
+ font-weight: var(--cf-v2-popover-title-font-weight);
50
+ overflow-wrap: anywhere;
51
+ }
52
+
53
+ .separator {
54
+ flex: none;
55
+ height: var(--cf-v2-popover-border-width);
56
+ background: var(--cf-v2-outline);
57
+ opacity: var(--cf-v2-popover-separator-opacity);
58
+ }
59
+
60
+ .description {
61
+ color: color-mix(in srgb, var(--cf-v2-on-surface) calc(var(--cf-v2-popover-description-opacity) * 100%), transparent);
62
+ overflow-wrap: anywhere;
63
+ }
@@ -0,0 +1,3 @@
1
+ export { PopoverV2 } from './PopoverV2';
2
+ export type { PopoverV2Align, PopoverV2Placement, PopoverV2Props, PopoverV2Width } from './PopoverV2';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/componentsV2/overlays/PopoverV2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ export { PopoverV2 } from './PopoverV2';
@@ -0,0 +1,18 @@
1
+ import '@corefoundry-labs/forge-tokens/theme-v2/tokens.css';
2
+ import { type HTMLAttributes } from 'react';
3
+ import { type OverlayTrigger } from '../layer';
4
+ import type { OverlayPlacement } from '../position';
5
+ export type TooltipV2Placement = OverlayPlacement;
6
+ export type TooltipV2Props = Omit<HTMLAttributes<HTMLDivElement>, 'content' | 'children' | 'role' | 'popover'> & {
7
+ content: string;
8
+ children: OverlayTrigger;
9
+ placement?: TooltipV2Placement;
10
+ delay?: number;
11
+ };
12
+ export declare const TooltipV2: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "role" | "content" | "popover" | "children"> & {
13
+ content: string;
14
+ children: OverlayTrigger;
15
+ placement?: TooltipV2Placement;
16
+ delay?: number;
17
+ } & import("react").RefAttributes<HTMLDivElement>>;
18
+ //# sourceMappingURL=TooltipV2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TooltipV2.d.ts","sourceRoot":"","sources":["../../../../src/componentsV2/overlays/TooltipV2/TooltipV2.tsx"],"names":[],"mappings":"AAAA,OAAO,oDAAoD,CAAC;AAC5D,OAAO,EASL,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAqE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAClH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,MAAM,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG;IAC/G,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,eAAO,MAAM,SAAS;aATX,MAAM;cACL,cAAc;gBACZ,kBAAkB;YACtB,MAAM;kDA+Fd,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import '@corefoundry-labs/forge-tokens/theme-v2/tokens.css';
3
+ import { cloneElement, forwardRef, useEffect, useId, useImperativeHandle, useRef, useState, } from 'react';
4
+ import { chain, useAnchoredPanel, useEscapeLayer, useLatest, useTriggerRef } from '../layer';
5
+ import styles from './TooltipV2.module.css';
6
+ const hoverGrace = 120;
7
+ let visible = null;
8
+ export const TooltipV2 = forwardRef(function TooltipV2({ content, children, placement = 'top', delay = 300, id, className, onPointerEnter, onPointerLeave, ...props }, ref) {
9
+ const generated = useId();
10
+ const tooltipId = id ?? generated;
11
+ const [open, setOpen] = useState(false);
12
+ const panelRef = useRef(null);
13
+ const anchorRef = useRef(null);
14
+ const sources = useRef({ hover: false, focus: false });
15
+ const timer = useRef(undefined);
16
+ useImperativeHandle(ref, () => panelRef.current);
17
+ const dismiss = () => {
18
+ sources.current = { hover: false, focus: false };
19
+ clearTimeout(timer.current);
20
+ if (visible === self)
21
+ visible = null;
22
+ setOpen(false);
23
+ };
24
+ const self = useLatest(dismiss);
25
+ useEffect(() => () => {
26
+ clearTimeout(timer.current);
27
+ if (visible === self)
28
+ visible = null;
29
+ }, [self]);
30
+ const track = (source, active) => {
31
+ sources.current[source] = active;
32
+ const wanted = sources.current.hover || sources.current.focus;
33
+ clearTimeout(timer.current);
34
+ timer.current = setTimeout(() => {
35
+ if (wanted && visible !== self) {
36
+ visible?.current();
37
+ visible = self;
38
+ }
39
+ else if (!wanted && visible === self) {
40
+ visible = null;
41
+ }
42
+ setOpen(wanted);
43
+ }, wanted ? delay : hoverGrace);
44
+ };
45
+ const enter = (event) => {
46
+ if (event.pointerType !== 'touch')
47
+ track('hover', true);
48
+ };
49
+ const leave = () => track('hover', false);
50
+ useEscapeLayer(open, panelRef, dismiss);
51
+ useAnchoredPanel({ open, anchorRef, panelRef, placement, align: 'center' });
52
+ const trigger = children.props;
53
+ const attachTrigger = useTriggerRef(anchorRef, trigger.ref);
54
+ return (_jsxs(_Fragment, { children: [cloneElement(children, {
55
+ ref: attachTrigger,
56
+ 'aria-describedby': [trigger['aria-describedby'], tooltipId].filter(Boolean).join(' '),
57
+ onPointerEnter: chain(trigger.onPointerEnter, enter),
58
+ onPointerLeave: chain(trigger.onPointerLeave, leave),
59
+ onPointerDown: chain(trigger.onPointerDown, dismiss),
60
+ onFocus: chain(trigger.onFocus, (event) => {
61
+ if (event.currentTarget.matches(':focus-visible'))
62
+ track('focus', true);
63
+ }),
64
+ onBlur: chain(trigger.onBlur, () => track('focus', false)),
65
+ }), _jsxs("div", { ...props, ref: panelRef, id: tooltipId, role: "tooltip", popover: "manual", "data-state": open ? 'open' : 'closed', onPointerEnter: chain(onPointerEnter, enter), onPointerLeave: chain(onPointerLeave, leave), className: [styles.tooltip, className].filter(Boolean).join(' '), children: [content, _jsx("svg", { className: styles.arrow, viewBox: "0 0 12 9", "aria-hidden": "true", children: _jsx("path", { d: "M0 9 6 0l6 9" }) })] })] }));
66
+ });
@@ -0,0 +1,69 @@
1
+ .tooltip {
2
+ --overlay-offset: var(--cf-v2-tooltip-offset);
3
+ --tooltip-arrow-shift: calc(
4
+ (var(--cf-v2-tooltip-arrow-height) - var(--cf-v2-tooltip-arrow-width)) / 2 - var(--cf-v2-tooltip-border-width)
5
+ );
6
+ position: fixed;
7
+ inset: auto;
8
+ box-sizing: border-box;
9
+ width: max-content;
10
+ max-width: min(var(--cf-v2-tooltip-max-width), calc(100vw - 2 * var(--cf-v2-overlay-viewport-margin)));
11
+ margin: 0;
12
+ padding: var(--cf-v2-tooltip-padding-block) var(--cf-v2-tooltip-padding-inline);
13
+ overflow: visible;
14
+ border: var(--cf-v2-tooltip-border-width) solid var(--cf-v2-outline);
15
+ border-radius: var(--cf-v2-tooltip-radius);
16
+ background: var(--cf-v2-surface-container);
17
+ color: var(--cf-v2-on-surface);
18
+ font-family: inherit;
19
+ font-size: var(--cf-v2-tooltip-font-size);
20
+ font-weight: var(--cf-v2-tooltip-font-weight);
21
+ line-height: normal;
22
+ text-align: center;
23
+ overflow-wrap: anywhere;
24
+ }
25
+
26
+ .tooltip[data-state='closed'] {
27
+ display: none;
28
+ }
29
+
30
+ .arrow {
31
+ position: absolute;
32
+ width: var(--cf-v2-tooltip-arrow-width);
33
+ height: var(--cf-v2-tooltip-arrow-height);
34
+ overflow: visible;
35
+ fill: var(--cf-v2-surface-container);
36
+ stroke: var(--cf-v2-outline);
37
+ stroke-width: var(--cf-v2-tooltip-border-width);
38
+ pointer-events: none;
39
+ }
40
+
41
+ .tooltip[data-placement='bottom'] .arrow,
42
+ .tooltip[data-placement='top'] .arrow {
43
+ left: calc(var(--overlay-arrow) - var(--cf-v2-tooltip-border-width));
44
+ }
45
+
46
+ .tooltip[data-placement='left'] .arrow,
47
+ .tooltip[data-placement='right'] .arrow {
48
+ top: calc(var(--overlay-arrow) - var(--cf-v2-tooltip-border-width));
49
+ }
50
+
51
+ .tooltip[data-placement='bottom'] .arrow {
52
+ bottom: calc(100% - var(--cf-v2-tooltip-border-width));
53
+ transform: translateX(-50%);
54
+ }
55
+
56
+ .tooltip[data-placement='top'] .arrow {
57
+ top: calc(100% - var(--cf-v2-tooltip-border-width));
58
+ transform: translateX(-50%) rotate(180deg);
59
+ }
60
+
61
+ .tooltip[data-placement='left'] .arrow {
62
+ left: calc(100% + var(--tooltip-arrow-shift));
63
+ transform: translateY(-50%) rotate(90deg);
64
+ }
65
+
66
+ .tooltip[data-placement='right'] .arrow {
67
+ right: calc(100% + var(--tooltip-arrow-shift));
68
+ transform: translateY(-50%) rotate(-90deg);
69
+ }
@@ -0,0 +1,3 @@
1
+ export { TooltipV2 } from './TooltipV2';
2
+ export type { TooltipV2Placement, TooltipV2Props } from './TooltipV2';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/componentsV2/overlays/TooltipV2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ export { TooltipV2 } from './TooltipV2';
@@ -0,0 +1,29 @@
1
+ import { type HTMLAttributes, type ReactElement, type Ref, type RefObject } from 'react';
2
+ import { type OverlayAlign, type OverlayPlacement } from './position';
3
+ export type OverlayTriggerProps = HTMLAttributes<HTMLElement> & {
4
+ ref?: Ref<HTMLElement>;
5
+ };
6
+ export type OverlayTrigger = ReactElement<OverlayTriggerProps>;
7
+ type NodeRef = RefObject<HTMLElement | null>;
8
+ export declare function focusableIn(root: HTMLElement): HTMLElement[];
9
+ export declare function useTriggerRef(target: RefObject<HTMLElement | null>, external: Ref<HTMLElement> | undefined): (node: HTMLElement | null) => () => void;
10
+ export declare function chain<E>(...handlers: (((event: E) => void) | undefined)[]): (event: E) => void;
11
+ export declare function useLatest<T>(value: T): RefObject<T>;
12
+ export declare function useOpenLifecycle(open: boolean, onOpen: () => () => void): void;
13
+ export declare function returnFocus(element: Element | null): void;
14
+ export declare function useEscapeLayer(active: boolean, nodeRef: NodeRef, onEscape: () => void): void;
15
+ export declare function useDismiss(active: boolean, panelRef: NodeRef, anchorRef: NodeRef, onDismiss: () => void): void;
16
+ export declare function useOpenState(open: boolean | undefined, defaultOpen: boolean | undefined, onOpenChange: ((open: boolean) => void) | undefined): readonly [boolean, (next: boolean) => void];
17
+ type AnchoredPanel = {
18
+ open: boolean;
19
+ anchorRef: NodeRef;
20
+ panelRef: NodeRef;
21
+ placement: OverlayPlacement;
22
+ align: OverlayAlign;
23
+ restoreFocus?: boolean;
24
+ onShown?: () => void;
25
+ };
26
+ export declare function useAnchoredPanel({ open, anchorRef, panelRef, placement, align, restoreFocus, onShown, }: AnchoredPanel): void;
27
+ export declare function lockScroll(): () => void;
28
+ export {};
29
+ //# sourceMappingURL=layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../../src/componentsV2/overlays/layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,GAAG,EACR,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAmB,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvF,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,WAAW,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAA;CAAE,CAAC;AAC3F,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAE/D,KAAK,OAAO,GAAG,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAe7C,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,iBAI5C;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,SAAS,UAEhG,WAAW,GAAG,IAAI,gBAa5B;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,EAAE,IAChE,OAAO,CAAC,UAGjB;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,gBAMpC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,IAAI,QAcvE;AAID,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,QAQlD;AAkBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,QAWrF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,QAiBvG;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,WAAW,EAAE,OAAO,GAAG,SAAS,EAChC,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,6BAO1C,OAAO,WAOjB;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAoB,EACpB,OAAO,GACR,EAAE,aAAa,QA6Df;AAKD,wBAAgB,UAAU,eAoBzB"}
@@ -0,0 +1,224 @@
1
+ import { useCallback, useLayoutEffect, useRef, useState, } from 'react';
2
+ import { computePosition } from './position';
3
+ const focusableSelector = [
4
+ 'a[href]',
5
+ 'button:not([disabled])',
6
+ 'input:not([disabled]):not([type="hidden"])',
7
+ 'select:not([disabled])',
8
+ 'textarea:not([disabled])',
9
+ 'summary',
10
+ 'iframe',
11
+ '[contenteditable]:not([contenteditable="false"])',
12
+ '[tabindex]',
13
+ ].join(',');
14
+ export function focusableIn(root) {
15
+ return [...root.querySelectorAll(focusableSelector)].filter((element) => element.tabIndex >= 0 && element.checkVisibility?.() !== false);
16
+ }
17
+ export function useTriggerRef(target, external) {
18
+ return useCallback((node) => {
19
+ target.current = node;
20
+ const cleanup = typeof external === 'function' ? external(node) : undefined;
21
+ if (external && typeof external !== 'function')
22
+ external.current = node;
23
+ return () => {
24
+ target.current = null;
25
+ if (typeof cleanup === 'function')
26
+ cleanup();
27
+ else if (typeof external === 'function')
28
+ external(null);
29
+ else if (external)
30
+ external.current = null;
31
+ };
32
+ }, [target, external]);
33
+ }
34
+ export function chain(...handlers) {
35
+ return (event) => {
36
+ for (const handler of handlers)
37
+ handler?.(event);
38
+ };
39
+ }
40
+ export function useLatest(value) {
41
+ const latest = useRef(value);
42
+ useLayoutEffect(() => {
43
+ latest.current = value;
44
+ });
45
+ return latest;
46
+ }
47
+ export function useOpenLifecycle(open, onOpen) {
48
+ const opener = useLatest(onOpen);
49
+ const teardown = useRef(null);
50
+ const finish = useCallback(() => {
51
+ teardown.current?.();
52
+ teardown.current = null;
53
+ }, []);
54
+ useLayoutEffect(() => {
55
+ if (open)
56
+ teardown.current = opener.current();
57
+ else
58
+ finish();
59
+ }, [open, opener, finish]);
60
+ useLayoutEffect(() => finish, [finish]);
61
+ }
62
+ const anchors = new WeakMap();
63
+ export function returnFocus(element) {
64
+ let target = element;
65
+ while (target instanceof HTMLElement) {
66
+ target.focus({ preventScroll: true });
67
+ if (document.activeElement === target)
68
+ return;
69
+ const panel = target.closest('[popover]');
70
+ target = panel ? (anchors.get(panel)?.() ?? null) : null;
71
+ }
72
+ }
73
+ const layers = [];
74
+ function topLayer() {
75
+ return [...layers]
76
+ .reverse()
77
+ .find((layer) => !layers.some((other) => other !== layer && layer.node()?.contains(other.node())));
78
+ }
79
+ function onDocumentKeyDown(event) {
80
+ if (event.key !== 'Escape' || event.defaultPrevented)
81
+ return;
82
+ const layer = topLayer();
83
+ if (!layer)
84
+ return;
85
+ event.preventDefault();
86
+ layer.escape();
87
+ }
88
+ export function useEscapeLayer(active, nodeRef, onEscape) {
89
+ const latest = useLatest(onEscape);
90
+ useLayoutEffect(() => {
91
+ if (!active)
92
+ return;
93
+ const layer = { node: () => nodeRef.current, escape: () => latest.current() };
94
+ if (layers.push(layer) === 1)
95
+ document.addEventListener('keydown', onDocumentKeyDown);
96
+ return () => {
97
+ layers.splice(layers.indexOf(layer), 1);
98
+ if (layers.length === 0)
99
+ document.removeEventListener('keydown', onDocumentKeyDown);
100
+ };
101
+ }, [active, nodeRef, latest]);
102
+ }
103
+ export function useDismiss(active, panelRef, anchorRef, onDismiss) {
104
+ const latest = useLatest(onDismiss);
105
+ useLayoutEffect(() => {
106
+ if (!active)
107
+ return;
108
+ const dismiss = (event) => {
109
+ const target = event.target;
110
+ if (!(target instanceof Node))
111
+ return;
112
+ if (panelRef.current?.contains(target) || anchorRef.current?.contains(target))
113
+ return;
114
+ latest.current();
115
+ };
116
+ document.addEventListener('pointerdown', dismiss, true);
117
+ document.addEventListener('focusin', dismiss);
118
+ return () => {
119
+ document.removeEventListener('pointerdown', dismiss, true);
120
+ document.removeEventListener('focusin', dismiss);
121
+ };
122
+ }, [active, panelRef, anchorRef, latest]);
123
+ }
124
+ export function useOpenState(open, defaultOpen, onOpenChange) {
125
+ const [internal, setInternal] = useState(defaultOpen ?? false);
126
+ const latest = useLatest(onOpenChange);
127
+ const controlled = open !== undefined;
128
+ const current = controlled ? open : internal;
129
+ const change = useCallback((next) => {
130
+ if (!controlled)
131
+ setInternal(next);
132
+ latest.current?.(next);
133
+ }, [controlled, latest]);
134
+ return [current, change];
135
+ }
136
+ export function useAnchoredPanel({ open, anchorRef, panelRef, placement, align, restoreFocus = false, onShown, }) {
137
+ const shown = useLatest(onShown);
138
+ const [attempt, retry] = useState(0);
139
+ useOpenLifecycle(open, () => {
140
+ const panel = panelRef.current;
141
+ const previous = document.activeElement;
142
+ if (panel)
143
+ anchors.set(panel, () => anchorRef.current);
144
+ panel?.showPopover?.();
145
+ return () => {
146
+ const active = document.activeElement;
147
+ const lost = !active || active === document.body || panel?.contains(active);
148
+ panel?.hidePopover?.();
149
+ if (!restoreFocus || !lost)
150
+ return;
151
+ const target = previous instanceof HTMLElement && previous !== document.body ? previous : anchorRef.current;
152
+ returnFocus(target);
153
+ };
154
+ });
155
+ useLayoutEffect(() => {
156
+ const panel = panelRef.current;
157
+ const anchor = anchorRef.current;
158
+ if (!open || !panel)
159
+ return;
160
+ if (!anchor) {
161
+ if (attempt === 0)
162
+ retry(1);
163
+ return;
164
+ }
165
+ const update = () => {
166
+ const styles = getComputedStyle(panel);
167
+ const { width, height } = panel.getBoundingClientRect();
168
+ const { left, top, placement: side, arrow } = computePosition({
169
+ anchor: anchor.getBoundingClientRect(),
170
+ panel: { width, height },
171
+ viewport: { width: document.documentElement.clientWidth, height: window.innerHeight },
172
+ placement,
173
+ align,
174
+ offset: parseFloat(styles.getPropertyValue('--overlay-offset')) || 0,
175
+ margin: parseFloat(styles.getPropertyValue('--cf-v2-overlay-viewport-margin')) || 0,
176
+ rtl: styles.direction === 'rtl',
177
+ });
178
+ panel.style.left = `${left}px`;
179
+ panel.style.top = `${top}px`;
180
+ panel.style.setProperty('--overlay-arrow', `${arrow}px`);
181
+ panel.dataset.placement = side;
182
+ };
183
+ update();
184
+ window.addEventListener('resize', update);
185
+ window.addEventListener('scroll', update, true);
186
+ const observer = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(update);
187
+ observer?.observe(panel);
188
+ observer?.observe(anchor);
189
+ return () => {
190
+ window.removeEventListener('resize', update);
191
+ window.removeEventListener('scroll', update, true);
192
+ observer?.disconnect();
193
+ };
194
+ }, [open, panelRef, anchorRef, placement, align, attempt]);
195
+ useLayoutEffect(() => {
196
+ if (open)
197
+ shown.current?.();
198
+ }, [open, shown]);
199
+ }
200
+ let locks = 0;
201
+ let unlock = () => { };
202
+ export function lockScroll() {
203
+ if (locks === 0) {
204
+ const root = document.documentElement;
205
+ const { body } = document;
206
+ const gutter = window.innerWidth - root.clientWidth;
207
+ const overflow = root.style.overflow;
208
+ const padding = body.style.paddingInlineEnd;
209
+ const current = parseFloat(getComputedStyle(body).paddingInlineEnd) || 0;
210
+ root.style.overflow = 'hidden';
211
+ if (gutter > 0)
212
+ body.style.paddingInlineEnd = `${current + gutter}px`;
213
+ unlock = () => {
214
+ root.style.overflow = overflow;
215
+ body.style.paddingInlineEnd = padding;
216
+ };
217
+ }
218
+ locks += 1;
219
+ return () => {
220
+ locks -= 1;
221
+ if (locks === 0)
222
+ unlock();
223
+ };
224
+ }
@@ -0,0 +1,32 @@
1
+ export type OverlayPlacement = 'top' | 'bottom' | 'left' | 'right';
2
+ export type OverlayAlign = 'start' | 'center' | 'end';
3
+ type Box = {
4
+ left: number;
5
+ top: number;
6
+ width: number;
7
+ height: number;
8
+ };
9
+ export type PositionInput = {
10
+ anchor: Box;
11
+ panel: {
12
+ width: number;
13
+ height: number;
14
+ };
15
+ viewport: {
16
+ width: number;
17
+ height: number;
18
+ };
19
+ placement: OverlayPlacement;
20
+ align: OverlayAlign;
21
+ offset: number;
22
+ margin: number;
23
+ rtl?: boolean;
24
+ };
25
+ export declare function computePosition({ anchor, panel, viewport, placement, align, offset, margin, rtl }: PositionInput): {
26
+ left: number;
27
+ top: number;
28
+ placement: OverlayPlacement;
29
+ arrow: number;
30
+ };
31
+ export {};
32
+ //# sourceMappingURL=position.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../../src/componentsV2/overlays/position.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AACnE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtD,KAAK,GAAG,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,GAAG,CAAC;IACZ,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAgBF,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAW,EAAE,EAAE,aAAa;;;;;EAgCxH"}