@dbcdk/react-components 0.0.3 → 0.0.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 (223) hide show
  1. package/dist/assets/logo.cjs +10 -10
  2. package/dist/assets/logo.js +10 -10
  3. package/dist/components/__stories__/story-components/Colors.cjs +159 -0
  4. package/dist/components/__stories__/story-components/Colors.d.ts +10 -0
  5. package/dist/components/__stories__/story-components/Colors.js +151 -0
  6. package/dist/components/__stories__/story-components/Colors.module.css +27 -0
  7. package/dist/components/__stories__/story-components/Spacing.cjs +190 -0
  8. package/dist/components/__stories__/story-components/Spacing.d.ts +1 -0
  9. package/dist/components/__stories__/story-components/Spacing.js +184 -0
  10. package/dist/components/__stories__/story-components/Spacing.module.css +154 -0
  11. package/dist/components/app-header/AppHeader.module.css +10 -15
  12. package/dist/components/attribute-chip/AttributeChip.cjs +22 -0
  13. package/dist/components/attribute-chip/AttributeChip.d.ts +8 -0
  14. package/dist/components/attribute-chip/AttributeChip.js +16 -0
  15. package/dist/components/attribute-chip/AttributeChip.module.css +65 -0
  16. package/dist/components/avatar/Avatar.cjs +38 -4
  17. package/dist/components/avatar/Avatar.d.ts +4 -2
  18. package/dist/components/avatar/Avatar.js +39 -5
  19. package/dist/components/avatar/Avatar.module.css +27 -0
  20. package/dist/components/breadcrumbs/Breadcrumbs.cjs +1 -2
  21. package/dist/components/breadcrumbs/Breadcrumbs.js +1 -2
  22. package/dist/components/breadcrumbs/Breadcrumbs.module.css +19 -22
  23. package/dist/components/button/Button.cjs +20 -12
  24. package/dist/components/button/Button.d.ts +4 -1
  25. package/dist/components/button/Button.js +20 -12
  26. package/dist/components/button/Button.module.css +118 -55
  27. package/dist/components/card/Card.cjs +53 -13
  28. package/dist/components/card/Card.d.ts +21 -6
  29. package/dist/components/card/Card.js +54 -14
  30. package/dist/components/card/Card.module.css +148 -44
  31. package/dist/components/card-container/CardContainer.cjs +6 -5
  32. package/dist/components/card-container/CardContainer.d.ts +5 -2
  33. package/dist/components/card-container/CardContainer.js +6 -5
  34. package/dist/components/card-container/CardContainer.module.css +40 -0
  35. package/dist/components/checkbox/Checkbox.cjs +3 -4
  36. package/dist/components/checkbox/Checkbox.d.ts +1 -1
  37. package/dist/components/checkbox/Checkbox.js +3 -4
  38. package/dist/components/checkbox/Checkbox.module.css +10 -10
  39. package/dist/components/chip/Chip.cjs +2 -1
  40. package/dist/components/chip/Chip.d.ts +2 -1
  41. package/dist/components/chip/Chip.js +2 -1
  42. package/dist/components/chip/Chip.module.css +42 -27
  43. package/dist/components/circle/Circle.module.css +11 -11
  44. package/dist/components/clear-button/ClearButton.cjs +3 -3
  45. package/dist/components/clear-button/ClearButton.js +3 -3
  46. package/dist/components/clear-button/ClearButton.module.css +8 -7
  47. package/dist/components/code-block/CodeBlock.cjs +18 -0
  48. package/dist/components/code-block/CodeBlock.d.ts +6 -0
  49. package/dist/components/code-block/CodeBlock.js +12 -0
  50. package/dist/components/code-block/CodeBlock.module.css +60 -0
  51. package/dist/components/copy-button/CopyButton.cjs +35 -0
  52. package/dist/components/copy-button/CopyButton.d.ts +9 -0
  53. package/dist/components/copy-button/CopyButton.js +29 -0
  54. package/dist/components/copy-button/CopyButton.module.css +6 -0
  55. package/dist/components/datetime-picker/DateTimePicker.cjs +504 -0
  56. package/dist/components/datetime-picker/DateTimePicker.d.ts +39 -0
  57. package/dist/components/datetime-picker/DateTimePicker.js +498 -0
  58. package/dist/components/datetime-picker/DateTimePicker.module.css +144 -0
  59. package/dist/components/filter-field/FilterField.cjs +34 -19
  60. package/dist/components/filter-field/FilterField.d.ts +2 -2
  61. package/dist/components/filter-field/FilterField.js +35 -20
  62. package/dist/components/filter-field/FilterField.module.css +14 -20
  63. package/dist/components/headline/Headline.cjs +10 -4
  64. package/dist/components/headline/Headline.d.ts +9 -1
  65. package/dist/components/headline/Headline.js +10 -4
  66. package/dist/components/headline/Headline.module.css +32 -7
  67. package/dist/components/icon/Icon.module.css +10 -9
  68. package/dist/components/input/Input.cjs +60 -19
  69. package/dist/components/input/Input.d.ts +7 -2
  70. package/dist/components/input/Input.js +60 -19
  71. package/dist/components/input/Input.module.css +90 -43
  72. package/dist/components/link/Link.cjs +46 -0
  73. package/dist/components/link/Link.d.ts +9 -0
  74. package/dist/components/link/Link.js +21 -0
  75. package/dist/components/link/Link.module.css +32 -0
  76. package/dist/components/menu/Menu.module.css +10 -32
  77. package/dist/components/meta-bar/MetaBar.cjs +29 -0
  78. package/dist/components/meta-bar/MetaBar.d.ts +11 -0
  79. package/dist/components/meta-bar/MetaBar.js +22 -0
  80. package/dist/components/meta-bar/MetaBar.module.css +12 -0
  81. package/dist/components/modal/Modal.cjs +134 -0
  82. package/dist/components/modal/Modal.d.ts +21 -0
  83. package/dist/components/modal/Modal.js +128 -0
  84. package/dist/components/modal/Modal.module.css +66 -0
  85. package/dist/components/modal/provider/ModalProvider.cjs +80 -0
  86. package/dist/components/modal/provider/ModalProvider.d.ts +21 -0
  87. package/dist/components/modal/provider/ModalProvider.js +77 -0
  88. package/dist/components/multi-select/MultiSelect.cjs +12 -1
  89. package/dist/components/multi-select/MultiSelect.js +12 -1
  90. package/dist/components/nav-bar/NavBar.module.css +11 -16
  91. package/dist/components/page/Page.module.css +2 -2
  92. package/dist/components/page-layout/PageLayout.cjs +5 -22
  93. package/dist/components/page-layout/PageLayout.d.ts +1 -8
  94. package/dist/components/page-layout/PageLayout.js +5 -22
  95. package/dist/components/page-layout/PageLayout.module.css +4 -80
  96. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.cjs +32 -0
  97. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.d.ts +11 -0
  98. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.js +25 -0
  99. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.module.css +84 -0
  100. package/dist/components/pagination/Pagination.cjs +83 -67
  101. package/dist/components/pagination/Pagination.d.ts +3 -1
  102. package/dist/components/pagination/Pagination.js +84 -68
  103. package/dist/components/pagination/Pagination.module.css +11 -3
  104. package/dist/components/panel/Panel.module.css +5 -7
  105. package/dist/components/popover/Popover.cjs +25 -8
  106. package/dist/components/popover/Popover.d.ts +2 -1
  107. package/dist/components/popover/Popover.js +25 -8
  108. package/dist/components/popover/Popover.module.css +4 -6
  109. package/dist/components/search-box/SearchBox.cjs +50 -37
  110. package/dist/components/search-box/SearchBox.d.ts +10 -7
  111. package/dist/components/search-box/SearchBox.js +50 -37
  112. package/dist/components/search-box/SearchBox.module.css +0 -1
  113. package/dist/components/segmented-progress-bar/SegmentedProgressBar.cjs +12 -6
  114. package/dist/components/segmented-progress-bar/SegmentedProgressBar.js +12 -6
  115. package/dist/components/segmented-progress-bar/SegmentedProgressBar.module.css +5 -1
  116. package/dist/components/select/Select.cjs +82 -13
  117. package/dist/components/select/Select.d.ts +2 -1
  118. package/dist/components/select/Select.js +83 -14
  119. package/dist/components/sidebar/Sidebar.cjs +3 -30
  120. package/dist/components/sidebar/Sidebar.d.ts +2 -1
  121. package/dist/components/sidebar/Sidebar.js +4 -26
  122. package/dist/components/sidebar/components/SidebarItem.cjs +3 -1
  123. package/dist/components/sidebar/components/SidebarItem.js +3 -1
  124. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.cjs +40 -14
  125. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.d.ts +3 -1
  126. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +40 -14
  127. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.module.css +9 -38
  128. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +50 -0
  129. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.d.ts +8 -0
  130. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +43 -0
  131. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +155 -0
  132. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.cjs +16 -9
  133. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.d.ts +2 -1
  134. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +16 -9
  135. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.module.css +25 -12
  136. package/dist/components/sidebar/components/sidebar-items/SidebarItems.cjs +2 -1
  137. package/dist/components/sidebar/components/sidebar-items/SidebarItems.d.ts +1 -1
  138. package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +2 -1
  139. package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.cjs +29 -2
  140. package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.js +25 -2
  141. package/dist/components/sidebar/providers/SidebarProvider.cjs +108 -10
  142. package/dist/components/sidebar/providers/SidebarProvider.d.ts +7 -3
  143. package/dist/components/sidebar/providers/SidebarProvider.js +109 -11
  144. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.cjs +1 -1
  145. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.js +1 -1
  146. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.module.css +0 -12
  147. package/dist/components/split-pane/SplitPane.cjs +123 -0
  148. package/dist/components/split-pane/SplitPane.d.ts +34 -0
  149. package/dist/components/split-pane/SplitPane.js +114 -0
  150. package/dist/components/split-pane/SplitPane.module.css +106 -0
  151. package/dist/components/split-pane/provider/SplitPaneContext.cjs +87 -0
  152. package/dist/components/split-pane/provider/SplitPaneContext.d.ts +23 -0
  153. package/dist/components/split-pane/provider/SplitPaneContext.js +79 -0
  154. package/dist/components/table/Table.cjs +180 -112
  155. package/dist/components/table/Table.d.ts +22 -6
  156. package/dist/components/table/Table.js +181 -113
  157. package/dist/components/table/Table.module.css +74 -47
  158. package/dist/components/table/components/empty-state/EmptyState.cjs +52 -0
  159. package/dist/components/table/components/empty-state/EmptyState.d.ts +40 -0
  160. package/dist/components/table/components/empty-state/EmptyState.js +46 -0
  161. package/dist/components/table/components/empty-state/EmptyState.module.css +16 -0
  162. package/dist/components/table/components/table-settings/TableSettings.cjs +32 -0
  163. package/dist/components/table/components/table-settings/TableSettings.d.ts +7 -0
  164. package/dist/components/table/components/table-settings/TableSettings.js +30 -0
  165. package/dist/{tanstack.cjs → components/table/tanstack.cjs} +61 -99
  166. package/dist/components/table/tanstack.d.ts +14 -0
  167. package/dist/{tanstack.js → components/table/tanstack.js} +61 -99
  168. package/dist/components/tabs/Tabs.cjs +33 -17
  169. package/dist/components/tabs/Tabs.d.ts +6 -3
  170. package/dist/components/tabs/Tabs.js +33 -17
  171. package/dist/components/tabs/Tabs.module.css +9 -9
  172. package/dist/components/toast/Toast.cjs +47 -0
  173. package/dist/components/toast/Toast.d.ts +14 -0
  174. package/dist/components/toast/Toast.js +41 -0
  175. package/dist/components/toast/Toast.module.css +101 -0
  176. package/dist/components/toast/provider/ToastProvider.cjs +98 -0
  177. package/dist/components/toast/provider/ToastProvider.d.ts +23 -0
  178. package/dist/components/toast/provider/ToastProvider.js +91 -0
  179. package/dist/components/tooltip/Tooltip.cjs +134 -29
  180. package/dist/components/tooltip/Tooltip.js +135 -30
  181. package/dist/components/tooltip/Tooltip.module.css +25 -43
  182. package/dist/components/user-display/UserDisplay.module.css +2 -2
  183. package/dist/constants/severity.cjs +12 -12
  184. package/dist/constants/severity.js +12 -12
  185. package/dist/constants/sizes.cjs +1 -0
  186. package/dist/constants/sizes.d.ts +1 -1
  187. package/dist/constants/sizes.js +1 -0
  188. package/dist/hooks/usePagination.cjs +88 -0
  189. package/dist/hooks/usePagination.d.ts +33 -0
  190. package/dist/hooks/usePagination.js +86 -0
  191. package/dist/hooks/useSorting.cjs +118 -0
  192. package/dist/hooks/useSorting.d.ts +49 -0
  193. package/dist/hooks/useSorting.js +116 -0
  194. package/dist/hooks/useTableData.cjs +52 -0
  195. package/dist/hooks/useTableData.d.ts +40 -0
  196. package/dist/hooks/useTableData.js +50 -0
  197. package/dist/hooks/useTableSelection.cjs +130 -0
  198. package/dist/hooks/useTableSelection.d.ts +25 -0
  199. package/dist/hooks/useTableSelection.js +128 -0
  200. package/dist/hooks/useTableSettings.cjs +28 -0
  201. package/dist/hooks/useTableSettings.d.ts +7 -0
  202. package/dist/hooks/useTableSettings.js +26 -0
  203. package/dist/hooks/useTimeDuration.cjs +39 -0
  204. package/dist/hooks/useTimeDuration.d.ts +22 -0
  205. package/dist/hooks/useTimeDuration.js +37 -0
  206. package/dist/hooks/useViewportFill.js +1 -1
  207. package/dist/index.cjs +119 -0
  208. package/dist/index.d.ts +17 -0
  209. package/dist/index.js +17 -0
  210. package/dist/src/styles/styles.css +101 -8
  211. package/dist/styles/css-helper-classes/flex.css +97 -0
  212. package/dist/styles/css-helper-classes/typography.css +7 -0
  213. package/dist/styles/styles.css +101 -8
  214. package/dist/styles/themes/dbc/dark.css +206 -99
  215. package/dist/styles/themes/dbc/light.css +183 -89
  216. package/dist/types/sizes.types.d.ts +2 -2
  217. package/package.json +17 -11
  218. package/dist/components/data-summary/DataSummary.cjs +0 -49
  219. package/dist/components/data-summary/DataSummary.d.ts +0 -19
  220. package/dist/components/data-summary/DataSummary.js +0 -43
  221. package/dist/components/data-summary/DataSummary.module.css +0 -51
  222. package/dist/components/sidebar/Sidebar.module.css +0 -66
  223. package/dist/tanstack.d.ts +0 -25
@@ -0,0 +1,91 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { createContext, useState, useRef, useCallback, useEffect, useContext } from 'react';
3
+ import { Toast } from '../Toast';
4
+ import styles from '../Toast.module.css';
5
+
6
+ const ToastContext = createContext(void 0);
7
+ function ToastProvider({
8
+ children,
9
+ defaultDuration = 1e4
10
+ }) {
11
+ const [toasts, setToasts] = useState([]);
12
+ const timeouts = useRef(/* @__PURE__ */ new Map());
13
+ const clearTimeoutForId = (id) => {
14
+ const timeoutId = timeouts.current.get(id);
15
+ if (timeoutId) {
16
+ window.clearTimeout(timeoutId);
17
+ timeouts.current.delete(id);
18
+ }
19
+ };
20
+ const hideToast = useCallback((id) => {
21
+ clearTimeoutForId(id);
22
+ setToasts((prev) => prev.filter((t) => t.id !== id));
23
+ }, []);
24
+ const scheduleAutoDismiss = useCallback(
25
+ (toast) => {
26
+ var _a;
27
+ const duration = (_a = toast.duration) != null ? _a : defaultDuration;
28
+ if (!duration || duration <= 0) return;
29
+ clearTimeoutForId(toast.id);
30
+ const timeoutId = window.setTimeout(() => {
31
+ hideToast(toast.id);
32
+ }, duration);
33
+ timeouts.current.set(toast.id, timeoutId);
34
+ },
35
+ [defaultDuration, hideToast]
36
+ );
37
+ const showToast = useCallback(
38
+ (config) => {
39
+ var _a, _b, _c;
40
+ const id = (_c = (_b = config.id) != null ? _b : (_a = crypto.randomUUID) == null ? void 0 : _a.call(crypto)) != null ? _c : `${Date.now()}-${Math.random()}`;
41
+ const toast = { ...config, id };
42
+ setToasts((prev) => [...prev, toast]);
43
+ scheduleAutoDismiss(toast);
44
+ return id;
45
+ },
46
+ [scheduleAutoDismiss]
47
+ );
48
+ const clearToasts = useCallback(() => {
49
+ toasts.forEach((t) => clearTimeoutForId(t.id));
50
+ setToasts([]);
51
+ }, [toasts]);
52
+ useEffect(
53
+ () => () => {
54
+ toasts.forEach((t) => clearTimeoutForId(t.id));
55
+ },
56
+ [toasts]
57
+ );
58
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { showToast, hideToast, clearToasts }, children: [
59
+ children,
60
+ toasts.length > 0 && /* @__PURE__ */ jsx("div", { className: styles.container, "aria-live": "polite", "aria-atomic": "false", children: toasts.map((toast) => {
61
+ var _a;
62
+ return /* @__PURE__ */ jsx(
63
+ Toast,
64
+ {
65
+ title: toast.title,
66
+ message: toast.message,
67
+ severity: (_a = toast.severity) != null ? _a : "info",
68
+ action: toast.action && {
69
+ label: toast.action.label,
70
+ onClick: () => {
71
+ var _a2, _b;
72
+ (_b = (_a2 = toast.action) == null ? void 0 : _a2.onClick) == null ? void 0 : _b.call(_a2);
73
+ hideToast(toast.id);
74
+ }
75
+ },
76
+ onClose: () => hideToast(toast.id)
77
+ },
78
+ toast.id
79
+ );
80
+ }) })
81
+ ] });
82
+ }
83
+ function useToast() {
84
+ const ctx = useContext(ToastContext);
85
+ if (!ctx) {
86
+ throw new Error("useToast must be used within a ToastProvider");
87
+ }
88
+ return ctx;
89
+ }
90
+
91
+ export { ToastProvider, useToast };
@@ -2,12 +2,57 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var react = require('react');
5
+ var reactDom = require('react-dom');
5
6
  var styles = require('./Tooltip.module.css');
6
7
 
7
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
9
 
9
10
  var styles__default = /*#__PURE__*/_interopDefault(styles);
10
11
 
12
+ const VIEWPORT_PADDING = 8;
13
+ function clamp(n, min, max) {
14
+ return Math.max(min, Math.min(n, max));
15
+ }
16
+ function computePosition(args) {
17
+ const { triggerRect, bubbleRect, placement, offset } = args;
18
+ switch (placement) {
19
+ case "top":
20
+ return {
21
+ left: triggerRect.left + triggerRect.width / 2 - bubbleRect.width / 2,
22
+ top: triggerRect.top - bubbleRect.height - offset
23
+ };
24
+ case "bottom":
25
+ return {
26
+ left: triggerRect.left + triggerRect.width / 2 - bubbleRect.width / 2,
27
+ top: triggerRect.bottom + offset
28
+ };
29
+ case "left":
30
+ return {
31
+ left: triggerRect.left - bubbleRect.width - offset,
32
+ top: triggerRect.top + triggerRect.height / 2 - bubbleRect.height / 2
33
+ };
34
+ case "right":
35
+ return {
36
+ left: triggerRect.right + offset,
37
+ top: triggerRect.top + triggerRect.height / 2 - bubbleRect.height / 2
38
+ };
39
+ }
40
+ }
41
+ function fitsViewport(pos, bubbleRect) {
42
+ const vw = window.innerWidth;
43
+ const vh = window.innerHeight;
44
+ const leftOk = pos.left >= VIEWPORT_PADDING;
45
+ const rightOk = pos.left + bubbleRect.width <= vw - VIEWPORT_PADDING;
46
+ const topOk = pos.top >= VIEWPORT_PADDING;
47
+ const bottomOk = pos.top + bubbleRect.height <= vh - VIEWPORT_PADDING;
48
+ return leftOk && rightOk && topOk && bottomOk;
49
+ }
50
+ function flippedPlacement(p) {
51
+ if (p === "top") return "bottom";
52
+ if (p === "bottom") return "top";
53
+ if (p === "left") return "right";
54
+ return "left";
55
+ }
11
56
  const Tooltip = ({
12
57
  children,
13
58
  content,
@@ -21,55 +66,115 @@ const Tooltip = ({
21
66
  const id = react.useId();
22
67
  const wrapperRef = react.useRef(null);
23
68
  const bubbleRef = react.useRef(null);
24
- const [resolvedPlacement, setResolvedPlacement] = react.useState(placement);
25
- react.useEffect(() => setResolvedPlacement(placement), [placement]);
26
- const recomputePlacement = () => {
27
- if (!flip) return setResolvedPlacement(placement);
69
+ const [internalOpen, setInternalOpen] = react.useState(false);
70
+ const [coords, setCoords] = react.useState({
71
+ top: 0,
72
+ left: 0,
73
+ placement,
74
+ visible: false
75
+ });
76
+ const isControlled = open !== void 0;
77
+ const isOpen = isControlled ? !!open : internalOpen;
78
+ react.useEffect(() => {
79
+ setCoords((c) => ({ ...c, placement }));
80
+ }, [placement]);
81
+ const recompute = () => {
28
82
  const wrapper = wrapperRef.current;
29
83
  const bubble = bubbleRef.current;
30
84
  if (!wrapper || !bubble) return;
31
- const wrapperRect = wrapper.getBoundingClientRect();
85
+ const triggerRect = wrapper.getBoundingClientRect();
32
86
  const bubbleRect = bubble.getBoundingClientRect();
33
- const spaceAbove = wrapperRect.top - (bubbleRect.height + offset);
34
- const spaceBelow = window.innerHeight - wrapperRect.bottom - (bubbleRect.height + offset);
35
- if (placement === "top") {
36
- setResolvedPlacement(spaceAbove >= 0 ? "top" : "bottom");
37
- } else if (placement === "bottom") {
38
- setResolvedPlacement(spaceBelow >= 0 ? "bottom" : "top");
39
- } else {
40
- setResolvedPlacement(placement);
87
+ const candidates = flip ? [placement, flippedPlacement(placement)] : [placement];
88
+ let chosen = candidates[0];
89
+ let pos = computePosition({ triggerRect, bubbleRect, placement: chosen, offset });
90
+ if (flip && !fitsViewport(pos, bubbleRect) && candidates.length > 1) {
91
+ const alt = candidates[1];
92
+ const altPos = computePosition({ triggerRect, bubbleRect, placement: alt, offset });
93
+ if (fitsViewport(altPos, bubbleRect)) {
94
+ chosen = alt;
95
+ pos = altPos;
96
+ }
41
97
  }
98
+ const vw = window.innerWidth;
99
+ const vh = window.innerHeight;
100
+ const clampedLeft = clamp(pos.left, VIEWPORT_PADDING, vw - bubbleRect.width - VIEWPORT_PADDING);
101
+ const clampedTop = clamp(pos.top, VIEWPORT_PADDING, vh - bubbleRect.height - VIEWPORT_PADDING);
102
+ setCoords({
103
+ left: clampedLeft,
104
+ top: clampedTop,
105
+ placement: chosen,
106
+ visible: true
107
+ });
42
108
  };
43
109
  react.useLayoutEffect(() => {
44
- const wrapper = wrapperRef.current;
45
- if (!wrapper) return;
46
- const onShow = () => recomputePlacement();
47
- const onResize = () => recomputePlacement();
48
- const onScroll = () => recomputePlacement();
49
- wrapper.addEventListener("mouseenter", onShow);
50
- wrapper.addEventListener("focusin", onShow);
110
+ if (!isOpen) {
111
+ setCoords((c) => ({ ...c, visible: false }));
112
+ return;
113
+ }
114
+ const raf = requestAnimationFrame(() => recompute());
115
+ const onResize = () => recompute();
116
+ const onScroll = () => recompute();
51
117
  window.addEventListener("resize", onResize);
52
- window.addEventListener("scroll", onScroll, { passive: true });
53
- if (open) recomputePlacement();
118
+ window.addEventListener("scroll", onScroll, { passive: true, capture: true });
54
119
  return () => {
55
- wrapper.removeEventListener("mouseenter", onShow);
56
- wrapper.removeEventListener("focusin", onShow);
120
+ cancelAnimationFrame(raf);
57
121
  window.removeEventListener("resize", onResize);
122
+ window.removeEventListener("scroll", onScroll, true);
123
+ window.removeEventListener("scroll", onScroll, true);
58
124
  window.removeEventListener("scroll", onScroll);
59
125
  };
60
- }, [open, placement, flip, offset]);
61
- const rootClass = [styles__default.default.container, className].filter(Boolean).join(" ");
126
+ }, [isOpen, placement, flip, offset, content]);
127
+ const onMouseEnter = () => {
128
+ if (!isControlled) setInternalOpen(true);
129
+ };
130
+ const onMouseLeave = () => {
131
+ if (!isControlled) setInternalOpen(false);
132
+ };
133
+ const onFocusIn = () => {
134
+ if (!isControlled) setInternalOpen(true);
135
+ };
136
+ const onFocusOut = () => {
137
+ if (!isControlled) setInternalOpen(false);
138
+ };
139
+ const rootClass = react.useMemo(
140
+ () => [styles__default.default.container, className].filter(Boolean).join(" "),
141
+ [className]
142
+ );
143
+ const [mounted, setMounted] = react.useState(false);
144
+ react.useEffect(() => setMounted(true), []);
62
145
  return /* @__PURE__ */ jsxRuntime.jsxs(
63
146
  "div",
64
147
  {
65
148
  ref: wrapperRef,
66
149
  className: rootClass,
67
- "data-open": open ? "true" : void 0,
68
- "data-placement": resolvedPlacement,
150
+ onMouseEnter,
151
+ onMouseLeave,
152
+ onFocusCapture: onFocusIn,
153
+ onBlurCapture: onFocusOut,
69
154
  ...rest,
70
155
  children: [
71
156
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.trigger, "aria-describedby": id, tabIndex: 0, children }),
72
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: bubbleRef, id, role: "tooltip", className: styles__default.default.bubble, children: content })
157
+ mounted && isOpen ? reactDom.createPortal(
158
+ /* @__PURE__ */ jsxRuntime.jsx(
159
+ "div",
160
+ {
161
+ ref: bubbleRef,
162
+ id,
163
+ role: "tooltip",
164
+ className: styles__default.default.bubble,
165
+ "data-open": coords.visible ? "true" : "false",
166
+ "data-placement": coords.placement,
167
+ style: {
168
+ top: coords.top,
169
+ left: coords.left,
170
+ visibility: coords.visible ? "visible" : "hidden"
171
+ },
172
+ "aria-hidden": !coords.visible,
173
+ children: content
174
+ }
175
+ ),
176
+ document.body
177
+ ) : null
73
178
  ]
74
179
  }
75
180
  );
@@ -1,7 +1,52 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useId, useRef, useState, useEffect, useLayoutEffect } from 'react';
2
+ import { useId, useRef, useState, useEffect, useLayoutEffect, useMemo } from 'react';
3
+ import { createPortal } from 'react-dom';
3
4
  import styles from './Tooltip.module.css';
4
5
 
6
+ const VIEWPORT_PADDING = 8;
7
+ function clamp(n, min, max) {
8
+ return Math.max(min, Math.min(n, max));
9
+ }
10
+ function computePosition(args) {
11
+ const { triggerRect, bubbleRect, placement, offset } = args;
12
+ switch (placement) {
13
+ case "top":
14
+ return {
15
+ left: triggerRect.left + triggerRect.width / 2 - bubbleRect.width / 2,
16
+ top: triggerRect.top - bubbleRect.height - offset
17
+ };
18
+ case "bottom":
19
+ return {
20
+ left: triggerRect.left + triggerRect.width / 2 - bubbleRect.width / 2,
21
+ top: triggerRect.bottom + offset
22
+ };
23
+ case "left":
24
+ return {
25
+ left: triggerRect.left - bubbleRect.width - offset,
26
+ top: triggerRect.top + triggerRect.height / 2 - bubbleRect.height / 2
27
+ };
28
+ case "right":
29
+ return {
30
+ left: triggerRect.right + offset,
31
+ top: triggerRect.top + triggerRect.height / 2 - bubbleRect.height / 2
32
+ };
33
+ }
34
+ }
35
+ function fitsViewport(pos, bubbleRect) {
36
+ const vw = window.innerWidth;
37
+ const vh = window.innerHeight;
38
+ const leftOk = pos.left >= VIEWPORT_PADDING;
39
+ const rightOk = pos.left + bubbleRect.width <= vw - VIEWPORT_PADDING;
40
+ const topOk = pos.top >= VIEWPORT_PADDING;
41
+ const bottomOk = pos.top + bubbleRect.height <= vh - VIEWPORT_PADDING;
42
+ return leftOk && rightOk && topOk && bottomOk;
43
+ }
44
+ function flippedPlacement(p) {
45
+ if (p === "top") return "bottom";
46
+ if (p === "bottom") return "top";
47
+ if (p === "left") return "right";
48
+ return "left";
49
+ }
5
50
  const Tooltip = ({
6
51
  children,
7
52
  content,
@@ -15,55 +60,115 @@ const Tooltip = ({
15
60
  const id = useId();
16
61
  const wrapperRef = useRef(null);
17
62
  const bubbleRef = useRef(null);
18
- const [resolvedPlacement, setResolvedPlacement] = useState(placement);
19
- useEffect(() => setResolvedPlacement(placement), [placement]);
20
- const recomputePlacement = () => {
21
- if (!flip) return setResolvedPlacement(placement);
63
+ const [internalOpen, setInternalOpen] = useState(false);
64
+ const [coords, setCoords] = useState({
65
+ top: 0,
66
+ left: 0,
67
+ placement,
68
+ visible: false
69
+ });
70
+ const isControlled = open !== void 0;
71
+ const isOpen = isControlled ? !!open : internalOpen;
72
+ useEffect(() => {
73
+ setCoords((c) => ({ ...c, placement }));
74
+ }, [placement]);
75
+ const recompute = () => {
22
76
  const wrapper = wrapperRef.current;
23
77
  const bubble = bubbleRef.current;
24
78
  if (!wrapper || !bubble) return;
25
- const wrapperRect = wrapper.getBoundingClientRect();
79
+ const triggerRect = wrapper.getBoundingClientRect();
26
80
  const bubbleRect = bubble.getBoundingClientRect();
27
- const spaceAbove = wrapperRect.top - (bubbleRect.height + offset);
28
- const spaceBelow = window.innerHeight - wrapperRect.bottom - (bubbleRect.height + offset);
29
- if (placement === "top") {
30
- setResolvedPlacement(spaceAbove >= 0 ? "top" : "bottom");
31
- } else if (placement === "bottom") {
32
- setResolvedPlacement(spaceBelow >= 0 ? "bottom" : "top");
33
- } else {
34
- setResolvedPlacement(placement);
81
+ const candidates = flip ? [placement, flippedPlacement(placement)] : [placement];
82
+ let chosen = candidates[0];
83
+ let pos = computePosition({ triggerRect, bubbleRect, placement: chosen, offset });
84
+ if (flip && !fitsViewport(pos, bubbleRect) && candidates.length > 1) {
85
+ const alt = candidates[1];
86
+ const altPos = computePosition({ triggerRect, bubbleRect, placement: alt, offset });
87
+ if (fitsViewport(altPos, bubbleRect)) {
88
+ chosen = alt;
89
+ pos = altPos;
90
+ }
35
91
  }
92
+ const vw = window.innerWidth;
93
+ const vh = window.innerHeight;
94
+ const clampedLeft = clamp(pos.left, VIEWPORT_PADDING, vw - bubbleRect.width - VIEWPORT_PADDING);
95
+ const clampedTop = clamp(pos.top, VIEWPORT_PADDING, vh - bubbleRect.height - VIEWPORT_PADDING);
96
+ setCoords({
97
+ left: clampedLeft,
98
+ top: clampedTop,
99
+ placement: chosen,
100
+ visible: true
101
+ });
36
102
  };
37
103
  useLayoutEffect(() => {
38
- const wrapper = wrapperRef.current;
39
- if (!wrapper) return;
40
- const onShow = () => recomputePlacement();
41
- const onResize = () => recomputePlacement();
42
- const onScroll = () => recomputePlacement();
43
- wrapper.addEventListener("mouseenter", onShow);
44
- wrapper.addEventListener("focusin", onShow);
104
+ if (!isOpen) {
105
+ setCoords((c) => ({ ...c, visible: false }));
106
+ return;
107
+ }
108
+ const raf = requestAnimationFrame(() => recompute());
109
+ const onResize = () => recompute();
110
+ const onScroll = () => recompute();
45
111
  window.addEventListener("resize", onResize);
46
- window.addEventListener("scroll", onScroll, { passive: true });
47
- if (open) recomputePlacement();
112
+ window.addEventListener("scroll", onScroll, { passive: true, capture: true });
48
113
  return () => {
49
- wrapper.removeEventListener("mouseenter", onShow);
50
- wrapper.removeEventListener("focusin", onShow);
114
+ cancelAnimationFrame(raf);
51
115
  window.removeEventListener("resize", onResize);
116
+ window.removeEventListener("scroll", onScroll, true);
117
+ window.removeEventListener("scroll", onScroll, true);
52
118
  window.removeEventListener("scroll", onScroll);
53
119
  };
54
- }, [open, placement, flip, offset]);
55
- const rootClass = [styles.container, className].filter(Boolean).join(" ");
120
+ }, [isOpen, placement, flip, offset, content]);
121
+ const onMouseEnter = () => {
122
+ if (!isControlled) setInternalOpen(true);
123
+ };
124
+ const onMouseLeave = () => {
125
+ if (!isControlled) setInternalOpen(false);
126
+ };
127
+ const onFocusIn = () => {
128
+ if (!isControlled) setInternalOpen(true);
129
+ };
130
+ const onFocusOut = () => {
131
+ if (!isControlled) setInternalOpen(false);
132
+ };
133
+ const rootClass = useMemo(
134
+ () => [styles.container, className].filter(Boolean).join(" "),
135
+ [className]
136
+ );
137
+ const [mounted, setMounted] = useState(false);
138
+ useEffect(() => setMounted(true), []);
56
139
  return /* @__PURE__ */ jsxs(
57
140
  "div",
58
141
  {
59
142
  ref: wrapperRef,
60
143
  className: rootClass,
61
- "data-open": open ? "true" : void 0,
62
- "data-placement": resolvedPlacement,
144
+ onMouseEnter,
145
+ onMouseLeave,
146
+ onFocusCapture: onFocusIn,
147
+ onBlurCapture: onFocusOut,
63
148
  ...rest,
64
149
  children: [
65
150
  /* @__PURE__ */ jsx("div", { className: styles.trigger, "aria-describedby": id, tabIndex: 0, children }),
66
- /* @__PURE__ */ jsx("div", { ref: bubbleRef, id, role: "tooltip", className: styles.bubble, children: content })
151
+ mounted && isOpen ? createPortal(
152
+ /* @__PURE__ */ jsx(
153
+ "div",
154
+ {
155
+ ref: bubbleRef,
156
+ id,
157
+ role: "tooltip",
158
+ className: styles.bubble,
159
+ "data-open": coords.visible ? "true" : "false",
160
+ "data-placement": coords.placement,
161
+ style: {
162
+ top: coords.top,
163
+ left: coords.left,
164
+ visibility: coords.visible ? "visible" : "hidden"
165
+ },
166
+ "aria-hidden": !coords.visible,
167
+ children: content
168
+ }
169
+ ),
170
+ document.body
171
+ ) : null
67
172
  ]
68
173
  }
69
174
  );
@@ -1,5 +1,4 @@
1
1
  .container {
2
- position: relative;
3
2
  display: inline-flex;
4
3
  }
5
4
 
@@ -13,9 +12,9 @@
13
12
  }
14
13
 
15
14
  .bubble {
16
- position: absolute;
17
- background: var(--color-text);
18
- color: var(--color-text-inverse);
15
+ position: fixed;
16
+ background: var(--color-fg-default);
17
+ color: var(--color-fg-on-strong);
19
18
  font-size: var(--font-size-xs);
20
19
  padding: var(--spacing-xxs) var(--spacing-sm);
21
20
  border-radius: var(--border-radius-default);
@@ -23,58 +22,41 @@
23
22
  white-space: nowrap;
24
23
  z-index: var(--z-tooltip);
25
24
  pointer-events: none;
25
+
26
26
  opacity: 0;
27
- transform: translate(-50%, -8px);
28
- left: 50%;
29
- bottom: calc(100% + var(--spacing-xs));
27
+ transform: translateY(-6px);
30
28
  transition:
31
29
  opacity var(--transition-fast),
32
30
  transform var(--transition-fast);
33
31
  }
34
32
 
35
- .container[data-placement='top'] .bubble {
36
- left: 50%;
37
- bottom: calc(100% + var(--spacing-xs));
38
- transform: translate(-50%, -8px);
39
- }
40
- .container[data-placement='bottom'] .bubble {
41
- top: calc(100% + var(--spacing-xs));
42
- left: 50%;
43
- transform: translate(-50%, 8px);
33
+ .bubble[data-open='true'] {
34
+ opacity: 1;
35
+ transform: translateY(0);
44
36
  }
45
- .container[data-placement='left'] .bubble {
46
- right: calc(100% + var(--spacing-xs));
47
- top: 50%;
48
- transform: translate(-8px, -50%);
37
+
38
+ .bubble[data-placement='bottom'] {
39
+ transform: translateY(6px);
49
40
  }
50
- .container[data-placement='right'] .bubble {
51
- left: calc(100% + var(--spacing-xs));
52
- top: 50%;
53
- transform: translate(8px, -50%);
41
+ .bubble[data-placement='bottom'][data-open='true'] {
42
+ transform: translateY(0);
54
43
  }
55
44
 
56
- .container:hover .bubble,
57
- .container:focus-within .bubble,
58
- .container[data-open='true'] .bubble {
59
- opacity: 1;
60
- height: fit-content;
61
- transform: translate(-50%, 0);
45
+ .bubble[data-placement='left'],
46
+ .bubble[data-placement='right'] {
47
+ transform: translateX(6px);
62
48
  }
63
-
64
- .container[data-placement='bottom']:hover .bubble,
65
- .container[data-placement='bottom']:focus-within .bubble,
66
- .container[data-placement='bottom'][data-open='true'] .bubble {
67
- transform: translate(-50%, 0);
49
+ .bubble[data-placement='left'] {
50
+ transform: translateX(-6px);
68
51
  }
69
- .container[data-placement='left']:hover .bubble,
70
- .container[data-placement='left']:focus-within .bubble,
71
- .container[data-placement='left'][data-open='true'] .bubble {
72
- transform: translate(0, -50%);
52
+ .bubble[data-placement='left'][data-open='true'],
53
+ .bubble[data-placement='right'][data-open='true'] {
54
+ transform: translateX(0);
73
55
  }
74
- .container[data-placement='right']:hover .bubble,
75
- .container[data-placement='right']:focus-within .bubble,
76
- .container[data-placement='right'][data-open='true'] .bubble {
77
- transform: translate(0, -50%);
56
+
57
+ .bubble svg {
58
+ height: 20px;
59
+ width: 20px;
78
60
  }
79
61
 
80
62
  @media (prefers-reduced-motion: reduce) {
@@ -12,11 +12,11 @@
12
12
  justify-content: center;
13
13
  padding: var(--spacing-sm);
14
14
  flex-grow: 0;
15
- color: var(--color-text-muted);
15
+ color: var(--color-fg-muted);
16
16
  }
17
17
 
18
18
  .userInfo h4 {
19
- color: var(--color-text);
19
+ color: var(--color-fg-default);
20
20
  margin: 0;
21
21
  }
22
22
 
@@ -1,20 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  const SeverityBgColor = {
4
- neutral: "var(--color-secondary)",
5
- brand: "var(--color-primary)",
6
- success: "var(--color-success)",
7
- error: "var(--color-error)",
8
- info: "var(--color-info)",
9
- warning: "var(--color-warning)"
4
+ neutral: "var(--color-neutral-strong)",
5
+ brand: "var(--color-brand)",
6
+ success: "var(--color-status-success)",
7
+ error: "var(--color-status-error)",
8
+ info: "var(--color-status-info)",
9
+ warning: "var(--color-status-warning)"
10
10
  };
11
11
  const SeverityTextColor = {
12
- neutral: "var(--color-text-inverse)",
13
- brand: "var(--color-text-on-primary)",
14
- success: "var(--color-text-inverse)",
15
- error: "var(--color-text-inverse)",
16
- info: "var(--color-text-inverse)",
17
- warning: "var(--color-text-inverse)"
12
+ neutral: "var(--color-neutral-strong-fg)",
13
+ brand: "var(--color-fg-on-brand)",
14
+ success: "var(--color-status-success-fg)",
15
+ error: "var(--color-status-error-fg)",
16
+ info: "var(--color-status-info-fg)",
17
+ warning: "var(--color-status-warning-fg)"
18
18
  };
19
19
 
20
20
  exports.SeverityBgColor = SeverityBgColor;
@@ -1,18 +1,18 @@
1
1
  const SeverityBgColor = {
2
- neutral: "var(--color-secondary)",
3
- brand: "var(--color-primary)",
4
- success: "var(--color-success)",
5
- error: "var(--color-error)",
6
- info: "var(--color-info)",
7
- warning: "var(--color-warning)"
2
+ neutral: "var(--color-neutral-strong)",
3
+ brand: "var(--color-brand)",
4
+ success: "var(--color-status-success)",
5
+ error: "var(--color-status-error)",
6
+ info: "var(--color-status-info)",
7
+ warning: "var(--color-status-warning)"
8
8
  };
9
9
  const SeverityTextColor = {
10
- neutral: "var(--color-text-inverse)",
11
- brand: "var(--color-text-on-primary)",
12
- success: "var(--color-text-inverse)",
13
- error: "var(--color-text-inverse)",
14
- info: "var(--color-text-inverse)",
15
- warning: "var(--color-text-inverse)"
10
+ neutral: "var(--color-neutral-strong-fg)",
11
+ brand: "var(--color-fg-on-brand)",
12
+ success: "var(--color-status-success-fg)",
13
+ error: "var(--color-status-error-fg)",
14
+ info: "var(--color-status-info-fg)",
15
+ warning: "var(--color-status-warning-fg)"
16
16
  };
17
17
 
18
18
  export { SeverityBgColor, SeverityTextColor };