@accelint/design-toolkit 9.12.0 → 10.0.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 (300) hide show
  1. package/catalog-info.yaml +1 -1
  2. package/dist/components/accordion/context.d.ts +2 -2
  3. package/dist/components/accordion/group.d.ts +2 -2
  4. package/dist/components/accordion/header.d.ts +2 -2
  5. package/dist/components/accordion/index.d.ts +2 -2
  6. package/dist/components/accordion/panel.d.ts +2 -2
  7. package/dist/components/accordion/trigger.d.ts +2 -2
  8. package/dist/components/action-bar/index.d.ts +2 -2
  9. package/dist/components/audio/index.d.ts +2 -2
  10. package/dist/components/avatar/context.d.ts +4 -4
  11. package/dist/components/avatar/index.d.ts +2 -2
  12. package/dist/components/badge/context.d.ts +4 -4
  13. package/dist/components/badge/index.d.ts +2 -2
  14. package/dist/components/breadcrumbs/index.d.ts +2 -2
  15. package/dist/components/breadcrumbs/item.d.ts +2 -2
  16. package/dist/components/button/context.d.ts +8 -8
  17. package/dist/components/button/index.d.ts +2 -2
  18. package/dist/components/button/link.d.ts +2 -2
  19. package/dist/components/button/toggle.d.ts +2 -2
  20. package/dist/components/carousel/context.d.ts +4 -4
  21. package/dist/components/carousel/gallery.d.ts +2 -2
  22. package/dist/components/carousel/index.d.ts +2 -2
  23. package/dist/components/carousel/navigation.d.ts +3 -3
  24. package/dist/components/carousel/position.d.ts +2 -2
  25. package/dist/components/carousel/select.d.ts +2 -2
  26. package/dist/components/carousel/viewer.d.ts +2 -2
  27. package/dist/components/checkbox/context.d.ts +3 -3
  28. package/dist/components/checkbox/group.d.ts +2 -2
  29. package/dist/components/checkbox/index.d.ts +2 -2
  30. package/dist/components/chip/context.d.ts +4 -4
  31. package/dist/components/chip/deletable.d.ts +2 -2
  32. package/dist/components/chip/index.d.ts +2 -2
  33. package/dist/components/chip/list.d.ts +4 -4
  34. package/dist/components/chip/selectable.d.ts +2 -2
  35. package/dist/components/classification-badge/context.d.ts +4 -4
  36. package/dist/components/classification-badge/index.d.ts +2 -2
  37. package/dist/components/classification-banner/context.d.ts +4 -4
  38. package/dist/components/classification-banner/index.d.ts +2 -2
  39. package/dist/components/clock/index.d.ts +2 -2
  40. package/dist/components/color-picker/index.d.ts +2 -2
  41. package/dist/components/combobox-field/context.d.ts +4 -4
  42. package/dist/components/combobox-field/index.d.ts +2 -2
  43. package/dist/components/coordinate-field/context.d.ts +6 -6
  44. package/dist/components/coordinate-field/index.d.ts +2 -2
  45. package/dist/components/coordinate-field/segment.d.ts +2 -2
  46. package/dist/components/date-field/index.d.ts +2 -2
  47. package/dist/components/deferred-collection/index.d.ts +2 -2
  48. package/dist/components/details-list/context.d.ts +4 -4
  49. package/dist/components/details-list/index.d.ts +2 -2
  50. package/dist/components/details-list/label.d.ts +2 -2
  51. package/dist/components/details-list/value.d.ts +2 -2
  52. package/dist/components/dialog/content.d.ts +2 -2
  53. package/dist/components/dialog/context.d.ts +2 -2
  54. package/dist/components/dialog/footer.d.ts +2 -2
  55. package/dist/components/dialog/index.d.ts +2 -2
  56. package/dist/components/dialog/title.d.ts +2 -2
  57. package/dist/components/divider/context.d.ts +4 -4
  58. package/dist/components/divider/index.d.ts +2 -2
  59. package/dist/components/drawer/back.d.ts +2 -2
  60. package/dist/components/drawer/close.d.ts +2 -2
  61. package/dist/components/drawer/content.d.ts +2 -2
  62. package/dist/components/drawer/footer.d.ts +2 -2
  63. package/dist/components/drawer/header-title.d.ts +2 -2
  64. package/dist/components/drawer/header.d.ts +2 -2
  65. package/dist/components/drawer/index.d.ts +2 -2
  66. package/dist/components/drawer/layout-main.d.ts +2 -2
  67. package/dist/components/drawer/layout.d.ts +2 -2
  68. package/dist/components/drawer/menu-item.d.ts +2 -2
  69. package/dist/components/drawer/menu.d.ts +2 -2
  70. package/dist/components/drawer/panel.d.ts +2 -2
  71. package/dist/components/drawer/trigger.d.ts +2 -2
  72. package/dist/components/drawer/view.d.ts +2 -2
  73. package/dist/components/flashcard/index.d.ts +9 -9
  74. package/dist/components/flashcard/index.js +1 -1
  75. package/dist/components/flashcard/index.js.map +1 -1
  76. package/dist/components/flashcard/styles.module.css +4 -0
  77. package/dist/components/floating-card/constants.d.ts +26 -0
  78. package/dist/components/floating-card/constants.js +40 -0
  79. package/dist/components/floating-card/constants.js.map +1 -0
  80. package/dist/components/floating-card/context.d.ts +38 -6
  81. package/dist/components/floating-card/context.js +24 -3
  82. package/dist/components/floating-card/context.js.map +1 -1
  83. package/dist/components/floating-card/hooks/use-card-layout.d.ts +36 -0
  84. package/dist/components/floating-card/hooks/use-card-layout.js +106 -0
  85. package/dist/components/floating-card/hooks/use-card-layout.js.map +1 -0
  86. package/dist/components/floating-card/hooks/use-drag.d.ts +62 -0
  87. package/dist/components/floating-card/hooks/use-drag.js +100 -0
  88. package/dist/components/floating-card/hooks/use-drag.js.map +1 -0
  89. package/dist/components/floating-card/hooks/use-mouse-interaction.d.ts +58 -0
  90. package/dist/components/floating-card/hooks/use-mouse-interaction.js +91 -0
  91. package/dist/components/floating-card/hooks/use-mouse-interaction.js.map +1 -0
  92. package/dist/components/floating-card/hooks/use-resize.d.ts +56 -0
  93. package/dist/components/floating-card/hooks/use-resize.js +98 -0
  94. package/dist/components/floating-card/hooks/use-resize.js.map +1 -0
  95. package/dist/components/floating-card/index.d.ts +6 -2
  96. package/dist/components/floating-card/index.js +24 -32
  97. package/dist/components/floating-card/index.js.map +1 -1
  98. package/dist/components/floating-card/panel.d.ts +69 -0
  99. package/dist/components/floating-card/panel.js +111 -0
  100. package/dist/components/floating-card/panel.js.map +1 -0
  101. package/dist/components/floating-card/provider.d.ts +10 -6
  102. package/dist/components/floating-card/provider.js +159 -153
  103. package/dist/components/floating-card/provider.js.map +1 -1
  104. package/dist/components/floating-card/styles.module.css +93 -39
  105. package/dist/components/floating-card/types.d.ts +51 -10
  106. package/dist/components/floating-card/utils.d.ts +8 -85
  107. package/dist/components/floating-card/utils.js +12 -38
  108. package/dist/components/floating-card/utils.js.map +1 -1
  109. package/dist/components/gantt/components/base-elements/range.d.ts +2 -2
  110. package/dist/components/gantt/components/containers/external/gantt-panel-container/index.d.ts +2 -2
  111. package/dist/components/gantt/components/containers/internal/index.d.ts +2 -2
  112. package/dist/components/gantt/components/containers/internal/layout-container/index.d.ts +2 -2
  113. package/dist/components/gantt/components/containers/internal/virtualized-content-height-container/index.d.ts +2 -2
  114. package/dist/components/gantt/components/content-row/block.d.ts +2 -2
  115. package/dist/components/gantt/components/content-row/bracket.d.ts +3 -3
  116. package/dist/components/gantt/components/content-row/icon-marker.d.ts +2 -2
  117. package/dist/components/gantt/components/content-row/index.d.ts +2 -2
  118. package/dist/components/gantt/components/content-row/marker.d.ts +2 -2
  119. package/dist/components/gantt/components/content-row/spacer.d.ts +2 -2
  120. package/dist/components/gantt/components/current-time/index.d.ts +2 -2
  121. package/dist/components/gantt/components/header/index.d.ts +3 -3
  122. package/dist/components/gantt/components/panel-row/index.d.ts +2 -2
  123. package/dist/components/gantt/components/rows-virtualizer/index.d.ts +3 -3
  124. package/dist/components/gantt/components/timeline/index.d.ts +2 -2
  125. package/dist/components/gantt/context/index.d.ts +4 -4
  126. package/dist/components/gantt/context/store/index.d.ts +4 -4
  127. package/dist/components/gantt/context/temporal-data/index.d.ts +4 -4
  128. package/dist/components/gantt/hooks/use-layout-subscription/index.js +8 -8
  129. package/dist/components/gantt/hooks/use-layout-subscription/index.js.map +1 -1
  130. package/dist/components/hero/context.d.ts +2 -2
  131. package/dist/components/hero/index.d.ts +2 -2
  132. package/dist/components/hero/subtitle.d.ts +3 -3
  133. package/dist/components/hotkey/context.d.ts +2 -2
  134. package/dist/components/hotkey/index.d.ts +2 -2
  135. package/dist/components/hotkey/set.d.ts +2 -2
  136. package/dist/components/icon/context.d.ts +4 -4
  137. package/dist/components/icon/index.d.ts +2 -2
  138. package/dist/components/input/context.d.ts +2 -2
  139. package/dist/components/input/index.d.ts +2 -2
  140. package/dist/components/kanban/card-body.d.ts +2 -2
  141. package/dist/components/kanban/card-header-actions.d.ts +2 -2
  142. package/dist/components/kanban/card-header-title.d.ts +2 -2
  143. package/dist/components/kanban/card-header.d.ts +2 -2
  144. package/dist/components/kanban/card.d.ts +2 -2
  145. package/dist/components/kanban/column-actions.d.ts +2 -2
  146. package/dist/components/kanban/column-container.d.ts +2 -2
  147. package/dist/components/kanban/column-content.d.ts +2 -2
  148. package/dist/components/kanban/column-header-actions.d.ts +2 -2
  149. package/dist/components/kanban/column-header-drag-handle.d.ts +2 -2
  150. package/dist/components/kanban/column-header-title.d.ts +2 -2
  151. package/dist/components/kanban/column-header.d.ts +2 -2
  152. package/dist/components/kanban/column.d.ts +2 -2
  153. package/dist/components/kanban/context.d.ts +2 -2
  154. package/dist/components/kanban/header-actions.d.ts +2 -2
  155. package/dist/components/kanban/header-search.d.ts +2 -2
  156. package/dist/components/kanban/header-title.d.ts +2 -2
  157. package/dist/components/kanban/header.d.ts +2 -2
  158. package/dist/components/kanban/kanban.d.ts +4 -4
  159. package/dist/components/label/context.d.ts +4 -4
  160. package/dist/components/label/index.d.ts +2 -2
  161. package/dist/components/lines/index.d.ts +2 -2
  162. package/dist/components/link/context.d.ts +2 -2
  163. package/dist/components/link/index.d.ts +2 -2
  164. package/dist/components/list/context.d.ts +2 -2
  165. package/dist/components/list/index.d.ts +2 -2
  166. package/dist/components/list/item-content.d.ts +2 -2
  167. package/dist/components/list/item-description.d.ts +2 -2
  168. package/dist/components/list/item-title.d.ts +2 -2
  169. package/dist/components/list/item.d.ts +2 -2
  170. package/dist/components/media-controls/context.d.ts +4 -4
  171. package/dist/components/media-controls/fullscreen-button.d.ts +2 -2
  172. package/dist/components/media-controls/index.d.ts +2 -2
  173. package/dist/components/media-controls/mute-button.d.ts +2 -2
  174. package/dist/components/media-controls/play-button.d.ts +2 -2
  175. package/dist/components/media-controls/playback-rate.d.ts +2 -2
  176. package/dist/components/media-controls/seek-button.d.ts +2 -2
  177. package/dist/components/media-controls/time-display.d.ts +2 -2
  178. package/dist/components/media-controls/time-range.d.ts +2 -2
  179. package/dist/components/media-controls/volume-slider.d.ts +2 -2
  180. package/dist/components/menu/context.d.ts +2 -2
  181. package/dist/components/menu/index.d.ts +2 -2
  182. package/dist/components/menu/item-description.d.ts +2 -2
  183. package/dist/components/menu/item-label.d.ts +2 -2
  184. package/dist/components/menu/item.d.ts +2 -2
  185. package/dist/components/menu/section.d.ts +2 -2
  186. package/dist/components/menu/separator.d.ts +2 -2
  187. package/dist/components/menu/submenu.d.ts +2 -2
  188. package/dist/components/notice/index.d.ts +3 -2
  189. package/dist/components/notice/index.js +3 -3
  190. package/dist/components/notice/index.js.map +1 -1
  191. package/dist/components/notice/list.d.ts +2 -2
  192. package/dist/components/notice/list.js +14 -5
  193. package/dist/components/notice/list.js.map +1 -1
  194. package/dist/components/notice/notice-icon.d.ts +2 -2
  195. package/dist/components/notice/types.d.ts +6 -5
  196. package/dist/components/notice/utils.d.ts +11 -1
  197. package/dist/components/notice/utils.js +16 -1
  198. package/dist/components/notice/utils.js.map +1 -1
  199. package/dist/components/options/context.d.ts +2 -2
  200. package/dist/components/options/index.d.ts +2 -2
  201. package/dist/components/options/item-content.d.ts +2 -2
  202. package/dist/components/options/item-description.d.ts +2 -2
  203. package/dist/components/options/item-label.d.ts +2 -2
  204. package/dist/components/options/item.d.ts +2 -2
  205. package/dist/components/options/section.d.ts +2 -2
  206. package/dist/components/pagination/context.d.ts +2 -2
  207. package/dist/components/pagination/index.d.ts +2 -2
  208. package/dist/components/pagination/next.d.ts +2 -2
  209. package/dist/components/pagination/pages.d.ts +2 -2
  210. package/dist/components/pagination/prev.d.ts +2 -2
  211. package/dist/components/popover/content.d.ts +2 -2
  212. package/dist/components/popover/footer.d.ts +2 -2
  213. package/dist/components/popover/index.d.ts +2 -2
  214. package/dist/components/popover/title.d.ts +2 -2
  215. package/dist/components/popover/trigger.d.ts +2 -2
  216. package/dist/components/query-builder/action-element.d.ts +2 -2
  217. package/dist/components/query-builder/actions.d.ts +4 -4
  218. package/dist/components/query-builder/combinator-selector.d.ts +2 -2
  219. package/dist/components/query-builder/index.d.ts +2 -2
  220. package/dist/components/query-builder/rule-group.d.ts +4 -4
  221. package/dist/components/query-builder/rule.d.ts +2 -2
  222. package/dist/components/query-builder/value-editor.d.ts +2 -2
  223. package/dist/components/query-builder/value-selector.d.ts +2 -2
  224. package/dist/components/radio/context.d.ts +3 -3
  225. package/dist/components/radio/group.d.ts +2 -2
  226. package/dist/components/radio/index.d.ts +2 -2
  227. package/dist/components/search-field/context.d.ts +4 -4
  228. package/dist/components/search-field/index.d.ts +2 -2
  229. package/dist/components/select-field/context.d.ts +4 -4
  230. package/dist/components/select-field/index.d.ts +2 -2
  231. package/dist/components/sidenav/avatar.d.ts +2 -2
  232. package/dist/components/sidenav/content.d.ts +2 -2
  233. package/dist/components/sidenav/context.d.ts +2 -2
  234. package/dist/components/sidenav/footer.d.ts +2 -2
  235. package/dist/components/sidenav/header.d.ts +2 -2
  236. package/dist/components/sidenav/index.d.ts +2 -2
  237. package/dist/components/sidenav/item.d.ts +2 -2
  238. package/dist/components/sidenav/link.d.ts +2 -2
  239. package/dist/components/sidenav/menu-item.d.ts +2 -2
  240. package/dist/components/sidenav/menu.d.ts +2 -2
  241. package/dist/components/sidenav/trigger.d.ts +2 -2
  242. package/dist/components/skeleton/index.d.ts +2 -2
  243. package/dist/components/slider/index.d.ts +2 -2
  244. package/dist/components/status-indicator/index.d.ts +2 -2
  245. package/dist/components/switch/context.d.ts +4 -4
  246. package/dist/components/switch/index.d.ts +2 -2
  247. package/dist/components/table/body.d.ts +4 -3
  248. package/dist/components/table/body.js.map +1 -1
  249. package/dist/components/table/cell.d.ts +4 -3
  250. package/dist/components/table/cell.js.map +1 -1
  251. package/dist/components/table/context.d.ts +2 -2
  252. package/dist/components/table/features.d.ts +80 -0
  253. package/dist/components/table/features.js +61 -0
  254. package/dist/components/table/features.js.map +1 -0
  255. package/dist/components/table/header-cell.d.ts +4 -3
  256. package/dist/components/table/header-cell.js.map +1 -1
  257. package/dist/components/table/header.d.ts +4 -3
  258. package/dist/components/table/header.js.map +1 -1
  259. package/dist/components/table/index.d.ts +2 -2
  260. package/dist/components/table/index.js +40 -49
  261. package/dist/components/table/index.js.map +1 -1
  262. package/dist/components/table/row-ordering-feature.d.ts +88 -0
  263. package/dist/components/table/row-ordering-feature.js +115 -0
  264. package/dist/components/table/row-ordering-feature.js.map +1 -0
  265. package/dist/components/table/row.d.ts +4 -3
  266. package/dist/components/table/row.js.map +1 -1
  267. package/dist/components/table/types.d.ts +15 -13
  268. package/dist/components/tabs/context.d.ts +6 -6
  269. package/dist/components/tabs/index.d.ts +2 -2
  270. package/dist/components/tabs/list.d.ts +2 -2
  271. package/dist/components/tabs/panel.d.ts +2 -2
  272. package/dist/components/tabs/tab.d.ts +2 -2
  273. package/dist/components/text-area-field/context.d.ts +4 -4
  274. package/dist/components/text-area-field/index.d.ts +2 -2
  275. package/dist/components/text-field/context.d.ts +4 -4
  276. package/dist/components/text-field/index.d.ts +2 -2
  277. package/dist/components/time-field/index.d.ts +2 -2
  278. package/dist/components/time-field/styles.module.css +4 -0
  279. package/dist/components/tooltip/context.d.ts +2 -2
  280. package/dist/components/tooltip/index.d.ts +2 -2
  281. package/dist/components/tooltip/trigger.d.ts +2 -2
  282. package/dist/components/tree/context.d.ts +3 -3
  283. package/dist/components/tree/index.d.ts +2 -2
  284. package/dist/components/tree/item-actions.d.ts +2 -2
  285. package/dist/components/tree/item-content.d.ts +2 -2
  286. package/dist/components/tree/item-description.d.ts +2 -2
  287. package/dist/components/tree/item-label.d.ts +2 -2
  288. package/dist/components/tree/item-prefix-icon.d.ts +2 -2
  289. package/dist/components/tree/item.d.ts +2 -2
  290. package/dist/components/tree/lines.d.ts +2 -2
  291. package/dist/components/video/index.d.ts +2 -2
  292. package/dist/components/view-stack/context.d.ts +2 -2
  293. package/dist/components/view-stack/index.d.ts +2 -2
  294. package/dist/components/view-stack/trigger.d.ts +2 -2
  295. package/dist/components/view-stack/view.d.ts +2 -2
  296. package/dist/index.d.ts +5 -3
  297. package/dist/index.js +4 -2
  298. package/dist/providers/portal.d.ts +2 -2
  299. package/dist/providers/theme-provider.d.ts +2 -2
  300. package/package.json +20 -14
@@ -14,55 +14,26 @@
14
14
  import { Icon } from "../icon/index.js";
15
15
  import { Button } from "../button/index.js";
16
16
  import { Divider } from "../divider/index.js";
17
- import { FloatingCardContext, useFloatingCard } from "./context.js";
18
- import { createHeaderAdapter } from "./utils.js";
19
- import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
17
+ import { FloatingCardContext, FloatingCardRegistryContext } from "./context.js";
18
+ import { useCardLayout } from "./hooks/use-card-layout.js";
19
+ import { FloatingCardPanel } from "./panel.js";
20
+ import { resolveMaybeFactory } from "./utils.js";
21
+ import { useCallback, useMemo, useRef, useState, useSyncExternalStore } from "react";
20
22
  import { clsx } from "@accelint/design-foundation/lib/utils";
21
- import { jsx, jsxs } from "react/jsx-runtime";
23
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
22
24
  import Cancel from "@accelint/icons/cancel";
23
25
  import PinIcon from "@accelint/icons/pin";
24
- import { DockviewReact } from "dockview-react";
25
26
  import styles from "./styles.module.css";
26
27
 
27
28
  //#region src/components/floating-card/provider.tsx
28
- /**
29
- * Internal component that registers a DOM ref for a card container.
30
- *
31
- * Used by the floating card engine to mount portal targets. Also manages
32
- * the data-pinned attribute on the resize container to control drag handle visibility.
33
- *
34
- * @param props - Dockview panel props containing the card ID.
35
- */
36
- function FloatingCardContainer(props) {
37
- const { addRef, isPinned, subscribeToPinState } = useFloatingCard();
38
- const cardId = props.api.id;
39
- const pinned = useSyncExternalStore(subscribeToPinState, () => isPinned(cardId), () => false);
40
- const cardRef = useRef(null);
41
- const refCallback = useCallback((ref) => {
42
- cardRef.current = ref;
43
- addRef(cardId, ref);
44
- }, [addRef, cardId]);
45
- useEffect(() => {
46
- const container = cardRef.current?.closest(".dv-resize-container");
47
- if (!container) return;
48
- if (pinned) container.dataset.pinned = "";
49
- else delete container.dataset.pinned;
50
- }, [pinned]);
51
- return /* @__PURE__ */ jsx("div", {
52
- className: styles.cardContent,
53
- ref: refCallback
54
- });
55
- }
56
- /**
57
- * Default left header showing an optional custom icon and the card's title.
58
- */
59
- function DefaultLeftHeader({ title, icon, id }) {
29
+ /** Header shown at the start of a card: optional icon plus the title. */
30
+ function CardHeaderStart({ icon, title }) {
60
31
  return /* @__PURE__ */ jsxs("div", {
61
32
  className: styles.headerSide,
62
33
  children: [icon ? /* @__PURE__ */ jsx(Icon, {
63
34
  size: "small",
64
35
  children: icon
65
- }) : null, title && title !== id ? /* @__PURE__ */ jsx("div", {
36
+ }) : null, title ? /* @__PURE__ */ jsx("div", {
66
37
  className: styles.headerTitleContainer,
67
38
  children: /* @__PURE__ */ jsx("div", {
68
39
  className: styles.headerTitle,
@@ -71,64 +42,55 @@ function DefaultLeftHeader({ title, icon, id }) {
71
42
  }) : null]
72
43
  });
73
44
  }
74
- /** Stable no-op subscribe for useSyncExternalStore when no pin subscription is available. */
75
- const noopSubscribe = () => () => void 0;
76
- /**
77
- * Default right header showing optional action buttons and an always-present close button.
78
- *
79
- * @remarks Handles rendering of 'divider' and 'pin' action types specially.
80
- */
81
- function DefaultRightHeader({ closeGroup, headerActions, id, togglePinCard, isPinned, subscribeToPinState }) {
82
- const pinned = useSyncExternalStore(subscribeToPinState ?? noopSubscribe, () => id && isPinned ? isPinned(id) : false, () => false);
83
- return /* @__PURE__ */ jsxs("div", {
84
- className: styles.headerSide,
85
- children: [headerActions?.map((action, index) => {
86
- if (action === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, `${id}-divider-${index}`);
87
- if (action === "pin") return /* @__PURE__ */ jsx(Button, {
88
- className: styles.pinButton,
89
- variant: "icon",
90
- size: "small",
91
- color: pinned ? "accent" : void 0,
92
- "aria-label": "Pin",
93
- "aria-pressed": pinned,
94
- onClick: () => {
95
- if (id && togglePinCard) togglePinCard(id);
96
- },
97
- children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PinIcon, {}) })
98
- }, `${id}-pin-${index}`);
99
- return /* @__PURE__ */ jsx(Button, {
100
- variant: "icon",
101
- size: "small",
102
- onClick: action.onClick,
103
- children: /* @__PURE__ */ jsx(Icon, { children: action.icon })
104
- }, `${id}-${index}`);
105
- }), /* @__PURE__ */ jsx(Button, {
45
+ /** Action buttons for a card, ending in the always-present close button. */
46
+ function CardHeaderActions({ actions, id, isPinned, onClose, onTogglePin }) {
47
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [actions?.map((action, index) => {
48
+ if (action === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, `${id}-divider-${index}`);
49
+ if (action === "pin") return /* @__PURE__ */ jsx(Button, {
50
+ "aria-label": "Pin",
51
+ "aria-pressed": isPinned,
52
+ color: isPinned ? "accent" : void 0,
53
+ onPress: onTogglePin,
54
+ size: "small",
106
55
  variant: "icon",
56
+ children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PinIcon, {}) })
57
+ }, `${id}-pin-${index}`);
58
+ return /* @__PURE__ */ jsx(Button, {
59
+ "aria-label": action.label,
60
+ onPress: action.onClick,
107
61
  size: "small",
108
- onClick: closeGroup,
109
- children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Cancel, {}) })
110
- })]
111
- });
62
+ variant: "icon",
63
+ children: /* @__PURE__ */ jsx(Icon, { children: action.icon })
64
+ }, `${id}-action-${index}`);
65
+ }), /* @__PURE__ */ jsx(Button, {
66
+ "aria-label": "Close",
67
+ onPress: onClose,
68
+ size: "small",
69
+ variant: "icon",
70
+ children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Cancel, {}) })
71
+ })] });
112
72
  }
113
- const components = { default: FloatingCardContainer };
114
73
  /**
115
74
  * Provides a context and layout area for floating cards within the application.
116
75
  *
117
- * Wraps children with floating card context and renders a Dockview instance to manage
118
- * docking, dragging, and layout of floating cards.
76
+ * Wraps children with floating card context and renders each registered card as
77
+ * a draggable, resizable panel bounded by the provider's own box.
119
78
  *
120
79
  * @param props - The props for the FloatingCardProvider component.
121
80
  * @param props.children - Child components rendered inside the floating card provider.
122
81
  * @param props.icon - Optional icon rendered in all card headers (static or factory).
123
82
  * @param props.headerActions - Optional action buttons for card headers (static or factory).
83
+ * @param props.initialPinned - Card IDs that start pinned.
84
+ * @param props.bounds - Region cards are confined to. Defaults to `'provider'`.
124
85
  * @param props.className - Additional CSS class names for styling.
125
86
  * @returns The FloatingCardProvider component that manages floating card layout and context.
126
87
  *
127
88
  * @remarks
128
89
  * - Manages registration and cleanup of floating card DOM references
129
90
  * - Exposes closeCard, togglePinCard, and isPinned via context
130
- * - Automatically cleans up refs when cards are removed via any path (drag close, group close, API close)
131
- * - Cards are bounded within the viewport
91
+ * - Cards are bounded within the provider element by default; `bounds='viewport'`
92
+ * lets them move anywhere on screen
93
+ * - Cards are dragged by their header; pinning a card freezes drag and resize
132
94
  *
133
95
  * @example
134
96
  * ```tsx
@@ -146,113 +108,157 @@ const components = { default: FloatingCardContainer };
146
108
  * </FloatingCardProvider>
147
109
  * ```
148
110
  */
149
- function FloatingCardProvider({ children, icon, headerActions, initialPinned, className }) {
150
- const [api, setApi] = useState(null);
111
+ function FloatingCardProvider({ children, icon, headerActions, initialPinned, bounds = "provider", className }) {
112
+ const rootRef = useRef(null);
151
113
  const [cards, setCards] = useState({});
152
- const pinnedCardsRef = useRef(new Set(initialPinned));
114
+ const pinnedRef = useRef(new Set(initialPinned));
153
115
  const pinListenersRef = useRef(/* @__PURE__ */ new Set());
154
- const closeCard = useCallback((id) => {
155
- api?.getPanel(id)?.api.close();
156
- }, [api]);
157
- const togglePinCard = useCallback((id) => {
158
- const next = new Set(pinnedCardsRef.current);
159
- if (next.has(id)) next.delete(id);
160
- else next.add(id);
161
- pinnedCardsRef.current = next;
116
+ const { layouts, registerCard, unregisterCard, moveCard, resizeCard, bringToFront } = useCardLayout();
117
+ const notifyPinChange = useCallback(() => {
162
118
  for (const listener of pinListenersRef.current) listener();
163
119
  }, []);
164
- const isPinned = useCallback((id) => pinnedCardsRef.current.has(id), []);
120
+ const isPinned = useCallback((id) => pinnedRef.current.has(id), []);
165
121
  const subscribeToPinState = useCallback((callback) => {
166
122
  pinListenersRef.current.add(callback);
167
123
  return () => {
168
124
  pinListenersRef.current.delete(callback);
169
125
  };
170
126
  }, []);
171
- const removeRef = useCallback((view) => {
172
- setCards((prev) => {
173
- const newCards = { ...prev };
174
- delete newCards[view];
175
- return newCards;
127
+ const togglePinCard = useCallback((id) => {
128
+ const next = new Set(pinnedRef.current);
129
+ if (next.has(id)) next.delete(id);
130
+ else next.add(id);
131
+ pinnedRef.current = next;
132
+ notifyPinChange();
133
+ }, [notifyPinChange]);
134
+ const removeRef = useCallback((id) => {
135
+ setCards((current) => {
136
+ if (!current[id]) return current;
137
+ const next = { ...current };
138
+ delete next[id];
139
+ return next;
176
140
  });
177
- if (pinnedCardsRef.current.has(view)) {
178
- const next = new Set(pinnedCardsRef.current);
179
- next.delete(view);
180
- pinnedCardsRef.current = next;
181
- for (const listener of pinListenersRef.current) listener();
141
+ if (pinnedRef.current.has(id)) {
142
+ const next = new Set(pinnedRef.current);
143
+ next.delete(id);
144
+ pinnedRef.current = next;
145
+ notifyPinChange();
182
146
  }
183
- }, []);
147
+ }, [notifyPinChange]);
184
148
  const addRef = useCallback((id, ref) => {
185
- if (ref) setCards((prev) => {
186
- if (prev[id]) return prev;
187
- return {
188
- ...prev,
189
- [id]: ref
190
- };
149
+ if (!ref) return;
150
+ setCards((current) => current[id] === ref ? current : {
151
+ ...current,
152
+ [id]: ref
191
153
  });
192
154
  }, []);
193
- useEffect(() => {
194
- if (!api) return;
195
- const disposable = api.onDidRemovePanel((event) => {
196
- removeRef(event.id);
197
- });
198
- return () => {
199
- disposable.dispose();
155
+ const closeCard = useCallback((id) => {
156
+ unregisterCard(id);
157
+ removeRef(id);
158
+ }, [removeRef, unregisterCard]);
159
+ const getBounds = useCallback(() => {
160
+ const element = rootRef.current;
161
+ if (!element) return {
162
+ top: 0,
163
+ left: 0,
164
+ right: 0,
165
+ bottom: 0
166
+ };
167
+ const rect = element.getBoundingClientRect();
168
+ if (bounds === "viewport") return {
169
+ top: -rect.top,
170
+ left: -rect.left,
171
+ right: window.innerWidth - rect.left,
172
+ bottom: window.innerHeight - rect.top
173
+ };
174
+ return {
175
+ top: 0,
176
+ left: 0,
177
+ right: rect.width,
178
+ bottom: rect.height
200
179
  };
201
- }, [api, removeRef]);
180
+ }, [bounds]);
202
181
  const contextValue = useMemo(() => ({
203
182
  cards,
204
- addRef,
205
- removeRef,
206
183
  closeCard,
207
184
  togglePinCard,
208
185
  isPinned,
209
- subscribeToPinState,
210
- api
186
+ subscribeToPinState
211
187
  }), [
212
188
  cards,
213
189
  closeCard,
214
- removeRef,
215
- api,
216
- addRef,
217
190
  togglePinCard,
218
191
  isPinned,
219
192
  subscribeToPinState
220
193
  ]);
221
- const leftAdapter = useMemo(() => createHeaderAdapter(DefaultLeftHeader, { icon }), [icon]);
222
- const rightAdapter = useMemo(() => createHeaderAdapter(DefaultRightHeader, {
223
- headerActions,
224
- togglePinCard,
225
- isPinned,
226
- subscribeToPinState
227
- }), [
228
- headerActions,
229
- togglePinCard,
230
- isPinned,
231
- subscribeToPinState
232
- ]);
233
- const theme = useMemo(() => ({
234
- name: "accelint",
235
- className: styles.floatingCardProvider ?? ""
236
- }), []);
237
- const onReady = useCallback((event) => {
238
- setApi(event.api);
239
- }, []);
194
+ const registryValue = useMemo(() => ({
195
+ openCard: registerCard,
196
+ addRef
197
+ }), [registerCard, addRef]);
240
198
  return /* @__PURE__ */ jsx(FloatingCardContext.Provider, {
241
199
  value: contextValue,
242
- children: /* @__PURE__ */ jsxs("div", {
243
- className: clsx(styles.providerRoot, className),
244
- children: [/* @__PURE__ */ jsx(DockviewReact, {
245
- locked: true,
246
- floatingGroupBounds: "boundedWithinViewport",
247
- components,
248
- prefixHeaderActionsComponent: leftAdapter,
249
- rightHeaderActionsComponent: rightAdapter,
250
- onReady,
251
- theme
252
- }), children]
200
+ children: /* @__PURE__ */ jsx(FloatingCardRegistryContext.Provider, {
201
+ value: registryValue,
202
+ children: /* @__PURE__ */ jsxs("div", {
203
+ className: clsx(styles.providerRoot, className),
204
+ ref: rootRef,
205
+ children: [Object.entries(layouts).map(([id, layout]) => /* @__PURE__ */ jsx(CardPanel, {
206
+ actions: resolveMaybeFactory(headerActions, id),
207
+ getBounds,
208
+ icon: resolveMaybeFactory(icon, id),
209
+ id,
210
+ isPinned,
211
+ layout,
212
+ onAddRef: addRef,
213
+ onClose: closeCard,
214
+ onFocus: bringToFront,
215
+ onMove: moveCard,
216
+ onResize: resizeCard,
217
+ onTogglePin: togglePinCard,
218
+ subscribeToPinState
219
+ }, id)), children]
220
+ })
253
221
  })
254
222
  });
255
223
  }
224
+ /**
225
+ * Binds one card's identity to the provider's callbacks so {@link FloatingCardPanel}
226
+ * can stay a plain presentational component.
227
+ *
228
+ * @remarks
229
+ * Pin state lives in a mutable store rather than React state, so it is read
230
+ * through `useSyncExternalStore` -- only the cards whose pin state changed
231
+ * re-render.
232
+ */
233
+ function CardPanel({ actions, getBounds, icon, id, isPinned, layout, onAddRef, onClose, onFocus, onMove, onResize, onTogglePin, subscribeToPinState }) {
234
+ const { title } = layout;
235
+ const pinned = useSyncExternalStore(subscribeToPinState, () => isPinned(id), () => false);
236
+ const contentRef = useCallback((element) => {
237
+ onAddRef(id, element);
238
+ }, [id, onAddRef]);
239
+ return /* @__PURE__ */ jsx(FloatingCardPanel, {
240
+ actions: /* @__PURE__ */ jsx(CardHeaderActions, {
241
+ actions,
242
+ id,
243
+ isPinned: pinned,
244
+ onClose: () => onClose(id),
245
+ onTogglePin: () => onTogglePin(id)
246
+ }),
247
+ contentRef,
248
+ getBounds,
249
+ header: /* @__PURE__ */ jsx(CardHeaderStart, {
250
+ icon,
251
+ title
252
+ }),
253
+ id,
254
+ isPinned: pinned,
255
+ label: title ?? "Floating card",
256
+ layout,
257
+ onFocus: () => onFocus(id),
258
+ onMove: (position) => onMove(id, position),
259
+ onResize: (dimensions, position) => onResize(id, dimensions, position)
260
+ });
261
+ }
256
262
 
257
263
  //#endregion
258
264
  export { FloatingCardProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","names":["CloseIcon","components: Record<string, FunctionComponent<IDockviewPanelProps>>"],"sources":["../../../src/components/floating-card/provider.tsx"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { clsx } from '@accelint/design-foundation/lib/utils';\nimport CloseIcon from '@accelint/icons/cancel';\nimport PinIcon from '@accelint/icons/pin';\nimport {\n type DockviewApi,\n DockviewReact,\n type DockviewReadyEvent,\n type IDockviewPanelProps,\n} from 'dockview-react';\nimport {\n type FunctionComponent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { Button } from '../button';\nimport { Divider } from '../divider';\nimport { Icon } from '../icon';\nimport { FloatingCardContext, useFloatingCard } from './context';\nimport styles from './styles.module.css';\nimport { createHeaderAdapter, type FloatingCardHeaderProps } from './utils';\nimport type { UniqueId } from '@accelint/core/utility/uuid';\nimport type {\n FloatingCardContextValue,\n FloatingCardProviderProps,\n} from './types';\n\n/**\n * Internal component that registers a DOM ref for a card container.\n *\n * Used by the floating card engine to mount portal targets. Also manages\n * the data-pinned attribute on the resize container to control drag handle visibility.\n *\n * @param props - Dockview panel props containing the card ID.\n */\nfunction FloatingCardContainer(props: Readonly<IDockviewPanelProps>) {\n const { addRef, isPinned, subscribeToPinState } = useFloatingCard();\n const cardId = props.api.id as UniqueId;\n\n const pinned = useSyncExternalStore(\n subscribeToPinState,\n () => isPinned(cardId),\n () => false,\n );\n\n const cardRef = useRef<HTMLDivElement | null>(null);\n\n const refCallback = useCallback(\n (ref: HTMLDivElement | null) => {\n cardRef.current = ref;\n addRef(cardId, ref);\n },\n [addRef, cardId],\n );\n\n // Toggle a data-pinned attribute on the ancestor .dv-resize-container\n // so CSS can disable pointer-events on the drag handle.\n useEffect(() => {\n const el = cardRef.current;\n const container = el?.closest<HTMLElement>('.dv-resize-container');\n\n if (!container) {\n return;\n }\n\n if (pinned) {\n container.dataset.pinned = '';\n } else {\n delete container.dataset.pinned;\n }\n }, [pinned]);\n\n return <div className={styles.cardContent} ref={refCallback} />;\n}\n\n/**\n * Default left header showing an optional custom icon and the card's title.\n */\nfunction DefaultLeftHeader({\n title,\n icon,\n id,\n}: Readonly<FloatingCardHeaderProps>) {\n return (\n <div className={styles.headerSide}>\n {icon ? <Icon size='small'>{icon}</Icon> : null}\n {title && title !== id ? (\n <div className={styles.headerTitleContainer}>\n <div className={styles.headerTitle}>{title}</div>\n </div>\n ) : null}\n </div>\n );\n}\n\n/** Stable no-op subscribe for useSyncExternalStore when no pin subscription is available. */\nconst noopSubscribe = () => () => undefined;\n\n/**\n * Default right header showing optional action buttons and an always-present close button.\n *\n * @remarks Handles rendering of 'divider' and 'pin' action types specially.\n */\nfunction DefaultRightHeader({\n closeGroup,\n headerActions,\n id,\n togglePinCard,\n isPinned,\n subscribeToPinState,\n}: Readonly<FloatingCardHeaderProps>) {\n const pinned = useSyncExternalStore(\n subscribeToPinState ?? noopSubscribe,\n () => (id && isPinned ? isPinned(id as UniqueId) : false),\n () => false,\n );\n\n return (\n <div className={styles.headerSide}>\n {headerActions?.map((action, index) => {\n if (action === 'divider') {\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: Using index as key is acceptable here because the order of actions is unlikely to change.\n <Divider key={`${id}-divider-${index}`} orientation='vertical' />\n );\n }\n if (action === 'pin') {\n return (\n <Button\n className={styles.pinButton}\n // biome-ignore lint/suspicious/noArrayIndexKey: Using index as key is acceptable here because the order of actions is unlikely to change.\n key={`${id}-pin-${index}`}\n variant='icon'\n size='small'\n color={pinned ? 'accent' : undefined}\n aria-label='Pin'\n aria-pressed={pinned}\n onClick={() => {\n if (id && togglePinCard) {\n togglePinCard(id as UniqueId);\n }\n }}\n >\n <Icon>\n <PinIcon />\n </Icon>\n </Button>\n );\n }\n return (\n <Button\n key={`${id}-${\n // biome-ignore lint/suspicious/noArrayIndexKey: Using index as key is acceptable here because the order of actions is unlikely to change.\n index\n }`}\n variant='icon'\n size='small'\n onClick={action.onClick}\n >\n <Icon>{action.icon}</Icon>\n </Button>\n );\n })}\n <Button variant='icon' size='small' onClick={closeGroup}>\n <Icon>\n <CloseIcon />\n </Icon>\n </Button>\n </div>\n );\n}\n\nconst components: Record<string, FunctionComponent<IDockviewPanelProps>> = {\n default: FloatingCardContainer,\n};\n\n/**\n * Provides a context and layout area for floating cards within the application.\n *\n * Wraps children with floating card context and renders a Dockview instance to manage\n * docking, dragging, and layout of floating cards.\n *\n * @param props - The props for the FloatingCardProvider component.\n * @param props.children - Child components rendered inside the floating card provider.\n * @param props.icon - Optional icon rendered in all card headers (static or factory).\n * @param props.headerActions - Optional action buttons for card headers (static or factory).\n * @param props.className - Additional CSS class names for styling.\n * @returns The FloatingCardProvider component that manages floating card layout and context.\n *\n * @remarks\n * - Manages registration and cleanup of floating card DOM references\n * - Exposes closeCard, togglePinCard, and isPinned via context\n * - Automatically cleans up refs when cards are removed via any path (drag close, group close, API close)\n * - Cards are bounded within the viewport\n *\n * @example\n * ```tsx\n * <FloatingCardProvider\n * icon={<AppLogo />}\n * headerActions={[\n * { icon: <SettingsIcon />, onClick: openSettings },\n * 'divider',\n * 'pin'\n * ]}\n * >\n * <FloatingCard id=\"panel-1\" title=\"My Panel\">\n * <div>Panel content</div>\n * </FloatingCard>\n * </FloatingCardProvider>\n * ```\n */\nexport function FloatingCardProvider({\n children,\n icon,\n headerActions,\n initialPinned,\n className,\n}: FloatingCardProviderProps) {\n const [api, setApi] = useState<DockviewApi | null>(null);\n const [cards, setCards] = useState<Record<UniqueId, HTMLDivElement>>({});\n const pinnedCardsRef = useRef<Set<UniqueId>>(new Set(initialPinned));\n const pinListenersRef = useRef<Set<() => void>>(new Set());\n\n const closeCard = useCallback(\n (id: UniqueId) => {\n api?.getPanel(id)?.api.close();\n },\n [api],\n );\n\n const togglePinCard = useCallback((id: UniqueId) => {\n const next = new Set(pinnedCardsRef.current);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n pinnedCardsRef.current = next;\n for (const listener of pinListenersRef.current) {\n listener();\n }\n }, []);\n\n const isPinned = useCallback(\n (id: UniqueId) => pinnedCardsRef.current.has(id),\n [],\n );\n\n const subscribeToPinState = useCallback((callback: () => void) => {\n pinListenersRef.current.add(callback);\n return () => {\n pinListenersRef.current.delete(callback);\n };\n }, []);\n\n const removeRef = useCallback((view: UniqueId) => {\n setCards((prev) => {\n const newCards = { ...prev };\n delete newCards[view];\n return newCards;\n });\n if (pinnedCardsRef.current.has(view)) {\n const next = new Set(pinnedCardsRef.current);\n next.delete(view);\n pinnedCardsRef.current = next;\n for (const listener of pinListenersRef.current) {\n listener();\n }\n }\n }, []);\n\n const addRef = useCallback((id: UniqueId, ref: HTMLDivElement | null) => {\n if (ref) {\n setCards((prev) => {\n if (prev[id]) {\n return prev;\n }\n return { ...prev, [id]: ref };\n });\n }\n }, []);\n\n // Clean up stale refs when cards are removed via any path\n // (drag close, group close, API close, etc.)\n useEffect(() => {\n if (!api) {\n return;\n }\n\n const disposable = api.onDidRemovePanel((event) => {\n removeRef(event.id as UniqueId);\n });\n\n return () => {\n disposable.dispose();\n };\n }, [api, removeRef]);\n\n const contextValue = useMemo<FloatingCardContextValue>(\n () => ({\n cards,\n addRef,\n removeRef,\n closeCard,\n togglePinCard,\n isPinned,\n subscribeToPinState,\n api,\n }),\n [\n cards,\n closeCard,\n removeRef,\n api,\n addRef,\n togglePinCard,\n isPinned,\n subscribeToPinState,\n ],\n );\n\n const leftAdapter = useMemo(\n () =>\n createHeaderAdapter(DefaultLeftHeader, {\n icon,\n }),\n [icon],\n );\n\n const rightAdapter = useMemo(\n () =>\n createHeaderAdapter(DefaultRightHeader, {\n headerActions,\n togglePinCard,\n isPinned,\n subscribeToPinState,\n }),\n [headerActions, togglePinCard, isPinned, subscribeToPinState],\n );\n\n const theme = useMemo(\n () => ({\n name: 'accelint',\n className: styles.floatingCardProvider ?? '',\n }),\n [],\n );\n\n const onReady = useCallback((event: DockviewReadyEvent) => {\n setApi(event.api);\n }, []);\n\n return (\n <FloatingCardContext.Provider value={contextValue}>\n <div className={clsx(styles.providerRoot, className)}>\n <DockviewReact\n locked\n floatingGroupBounds={'boundedWithinViewport'}\n components={components}\n prefixHeaderActionsComponent={leftAdapter}\n rightHeaderActionsComponent={rightAdapter}\n onReady={onReady}\n theme={theme}\n />\n {children}\n </div>\n </FloatingCardContext.Provider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,SAAS,sBAAsB,OAAsC;CACnE,MAAM,EAAE,QAAQ,UAAU,wBAAwB,iBAAiB;CACnE,MAAM,SAAS,MAAM,IAAI;CAEzB,MAAM,SAAS,qBACb,2BACM,SAAS,OAAO,QAChB,MACP;CAED,MAAM,UAAU,OAA8B,KAAK;CAEnD,MAAM,cAAc,aACjB,QAA+B;AAC9B,UAAQ,UAAU;AAClB,SAAO,QAAQ,IAAI;IAErB,CAAC,QAAQ,OAAO,CACjB;AAID,iBAAgB;EAEd,MAAM,YADK,QAAQ,SACG,QAAqB,uBAAuB;AAElE,MAAI,CAAC,UACH;AAGF,MAAI,OACF,WAAU,QAAQ,SAAS;MAE3B,QAAO,UAAU,QAAQ;IAE1B,CAAC,OAAO,CAAC;AAEZ,QAAO,oBAAC;EAAI,WAAW,OAAO;EAAa,KAAK;GAAe;;;;;AAMjE,SAAS,kBAAkB,EACzB,OACA,MACA,MACoC;AACpC,QACE,qBAAC;EAAI,WAAW,OAAO;aACpB,OAAO,oBAAC;GAAK,MAAK;aAAS;IAAY,GAAG,MAC1C,SAAS,UAAU,KAClB,oBAAC;GAAI,WAAW,OAAO;aACrB,oBAAC;IAAI,WAAW,OAAO;cAAc;KAAY;IAC7C,GACJ;GACA;;;AAKV,MAAM,4BAA4B;;;;;;AAOlC,SAAS,mBAAmB,EAC1B,YACA,eACA,IACA,eACA,UACA,uBACoC;CACpC,MAAM,SAAS,qBACb,uBAAuB,qBAChB,MAAM,WAAW,SAAS,GAAe,GAAG,aAC7C,MACP;AAED,QACE,qBAAC;EAAI,WAAW,OAAO;aACpB,eAAe,KAAK,QAAQ,UAAU;AACrC,OAAI,WAAW,UACb,QAEE,oBAAC,WAAuC,aAAY,cAAtC,GAAG,GAAG,WAAW,QAAkC;AAGrE,OAAI,WAAW,MACb,QACE,oBAAC;IACC,WAAW,OAAO;IAGlB,SAAQ;IACR,MAAK;IACL,OAAO,SAAS,WAAW;IAC3B,cAAW;IACX,gBAAc;IACd,eAAe;AACb,SAAI,MAAM,cACR,eAAc,GAAe;;cAIjC,oBAAC,kBACC,oBAAC,YAAU,GACN;MAdF,GAAG,GAAG,OAAO,QAeX;AAGb,UACE,oBAAC;IAKC,SAAQ;IACR,MAAK;IACL,SAAS,OAAO;cAEhB,oBAAC,kBAAM,OAAO,OAAY;MARrB,GAAG,GAAG,GAET,QAOK;IAEX,EACF,oBAAC;GAAO,SAAQ;GAAO,MAAK;GAAQ,SAAS;aAC3C,oBAAC,kBACC,oBAACA,WAAY,GACR;IACA;GACL;;AAIV,MAAMC,aAAqE,EACzE,SAAS,uBACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCD,SAAgB,qBAAqB,EACnC,UACA,MACA,eACA,eACA,aAC4B;CAC5B,MAAM,CAAC,KAAK,UAAU,SAA6B,KAAK;CACxD,MAAM,CAAC,OAAO,YAAY,SAA2C,EAAE,CAAC;CACxE,MAAM,iBAAiB,OAAsB,IAAI,IAAI,cAAc,CAAC;CACpE,MAAM,kBAAkB,uBAAwB,IAAI,KAAK,CAAC;CAE1D,MAAM,YAAY,aACf,OAAiB;AAChB,OAAK,SAAS,GAAG,EAAE,IAAI,OAAO;IAEhC,CAAC,IAAI,CACN;CAED,MAAM,gBAAgB,aAAa,OAAiB;EAClD,MAAM,OAAO,IAAI,IAAI,eAAe,QAAQ;AAC5C,MAAI,KAAK,IAAI,GAAG,CACd,MAAK,OAAO,GAAG;MAEf,MAAK,IAAI,GAAG;AAEd,iBAAe,UAAU;AACzB,OAAK,MAAM,YAAY,gBAAgB,QACrC,WAAU;IAEX,EAAE,CAAC;CAEN,MAAM,WAAW,aACd,OAAiB,eAAe,QAAQ,IAAI,GAAG,EAChD,EAAE,CACH;CAED,MAAM,sBAAsB,aAAa,aAAyB;AAChE,kBAAgB,QAAQ,IAAI,SAAS;AACrC,eAAa;AACX,mBAAgB,QAAQ,OAAO,SAAS;;IAEzC,EAAE,CAAC;CAEN,MAAM,YAAY,aAAa,SAAmB;AAChD,YAAU,SAAS;GACjB,MAAM,WAAW,EAAE,GAAG,MAAM;AAC5B,UAAO,SAAS;AAChB,UAAO;IACP;AACF,MAAI,eAAe,QAAQ,IAAI,KAAK,EAAE;GACpC,MAAM,OAAO,IAAI,IAAI,eAAe,QAAQ;AAC5C,QAAK,OAAO,KAAK;AACjB,kBAAe,UAAU;AACzB,QAAK,MAAM,YAAY,gBAAgB,QACrC,WAAU;;IAGb,EAAE,CAAC;CAEN,MAAM,SAAS,aAAa,IAAc,QAA+B;AACvE,MAAI,IACF,WAAU,SAAS;AACjB,OAAI,KAAK,IACP,QAAO;AAET,UAAO;IAAE,GAAG;KAAO,KAAK;IAAK;IAC7B;IAEH,EAAE,CAAC;AAIN,iBAAgB;AACd,MAAI,CAAC,IACH;EAGF,MAAM,aAAa,IAAI,kBAAkB,UAAU;AACjD,aAAU,MAAM,GAAe;IAC/B;AAEF,eAAa;AACX,cAAW,SAAS;;IAErB,CAAC,KAAK,UAAU,CAAC;CAEpB,MAAM,eAAe,eACZ;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;CAED,MAAM,cAAc,cAEhB,oBAAoB,mBAAmB,EACrC,MACD,CAAC,EACJ,CAAC,KAAK,CACP;CAED,MAAM,eAAe,cAEjB,oBAAoB,oBAAoB;EACtC;EACA;EACA;EACA;EACD,CAAC,EACJ;EAAC;EAAe;EAAe;EAAU;EAAoB,CAC9D;CAED,MAAM,QAAQ,eACL;EACL,MAAM;EACN,WAAW,OAAO,wBAAwB;EAC3C,GACD,EAAE,CACH;CAED,MAAM,UAAU,aAAa,UAA8B;AACzD,SAAO,MAAM,IAAI;IAChB,EAAE,CAAC;AAEN,QACE,oBAAC,oBAAoB;EAAS,OAAO;YACnC,qBAAC;GAAI,WAAW,KAAK,OAAO,cAAc,UAAU;cAClD,oBAAC;IACC;IACA,qBAAqB;IACT;IACZ,8BAA8B;IAC9B,6BAA6B;IACpB;IACF;KACP,EACD;IACG;GACuB"}
1
+ {"version":3,"file":"provider.js","names":["CloseIcon"],"sources":["../../../src/components/floating-card/provider.tsx"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { clsx } from '@accelint/design-foundation/lib/utils';\nimport CloseIcon from '@accelint/icons/cancel';\nimport PinIcon from '@accelint/icons/pin';\nimport {\n useCallback,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { Button } from '../button';\nimport { Divider } from '../divider';\nimport { Icon } from '../icon';\nimport { FloatingCardContext, FloatingCardRegistryContext } from './context';\nimport type { FloatingCardRegistryValue } from './context';\nimport { useCardLayout } from './hooks/use-card-layout';\nimport { FloatingCardPanel } from './panel';\nimport styles from './styles.module.css';\nimport { resolveMaybeFactory } from './utils';\nimport type { UniqueId } from '@accelint/core/utility/uuid';\nimport type {\n Bounds,\n Dimensions,\n FloatingCardContextValue,\n FloatingCardHeaderAction,\n FloatingCardLayout,\n FloatingCardProviderProps,\n Position,\n} from './types';\n\n/** Header shown at the start of a card: optional icon plus the title. */\nfunction CardHeaderStart({\n icon,\n title,\n}: Readonly<{ icon: React.ReactNode; title: string | undefined }>) {\n return (\n <div className={styles.headerSide}>\n {icon ? <Icon size='small'>{icon}</Icon> : null}\n {title ? (\n <div className={styles.headerTitleContainer}>\n <div className={styles.headerTitle}>{title}</div>\n </div>\n ) : null}\n </div>\n );\n}\n\n/** Action buttons for a card, ending in the always-present close button. */\nfunction CardHeaderActions({\n actions,\n id,\n isPinned,\n onClose,\n onTogglePin,\n}: Readonly<{\n actions: FloatingCardHeaderAction[] | undefined;\n id: UniqueId;\n isPinned: boolean;\n onClose: () => void;\n onTogglePin: () => void;\n}>) {\n return (\n <>\n {actions?.map((action, index) => {\n if (action === 'divider') {\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: Using index as key is acceptable here because the order of actions is unlikely to change.\n <Divider key={`${id}-divider-${index}`} orientation='vertical' />\n );\n }\n\n if (action === 'pin') {\n return (\n <Button\n aria-label='Pin'\n aria-pressed={isPinned}\n color={isPinned ? 'accent' : undefined}\n // biome-ignore lint/suspicious/noArrayIndexKey: Using index as key is acceptable here because the order of actions is unlikely to change.\n key={`${id}-pin-${index}`}\n onPress={onTogglePin}\n size='small'\n variant='icon'\n >\n <Icon>\n <PinIcon />\n </Icon>\n </Button>\n );\n }\n\n return (\n <Button\n aria-label={action.label}\n // biome-ignore lint/suspicious/noArrayIndexKey: Using index as key is acceptable here because the order of actions is unlikely to change.\n key={`${id}-action-${index}`}\n onPress={action.onClick}\n size='small'\n variant='icon'\n >\n <Icon>{action.icon}</Icon>\n </Button>\n );\n })}\n <Button aria-label='Close' onPress={onClose} size='small' variant='icon'>\n <Icon>\n <CloseIcon />\n </Icon>\n </Button>\n </>\n );\n}\n\n/**\n * Provides a context and layout area for floating cards within the application.\n *\n * Wraps children with floating card context and renders each registered card as\n * a draggable, resizable panel bounded by the provider's own box.\n *\n * @param props - The props for the FloatingCardProvider component.\n * @param props.children - Child components rendered inside the floating card provider.\n * @param props.icon - Optional icon rendered in all card headers (static or factory).\n * @param props.headerActions - Optional action buttons for card headers (static or factory).\n * @param props.initialPinned - Card IDs that start pinned.\n * @param props.bounds - Region cards are confined to. Defaults to `'provider'`.\n * @param props.className - Additional CSS class names for styling.\n * @returns The FloatingCardProvider component that manages floating card layout and context.\n *\n * @remarks\n * - Manages registration and cleanup of floating card DOM references\n * - Exposes closeCard, togglePinCard, and isPinned via context\n * - Cards are bounded within the provider element by default; `bounds='viewport'`\n * lets them move anywhere on screen\n * - Cards are dragged by their header; pinning a card freezes drag and resize\n *\n * @example\n * ```tsx\n * <FloatingCardProvider\n * icon={<AppLogo />}\n * headerActions={[\n * { icon: <SettingsIcon />, onClick: openSettings },\n * 'divider',\n * 'pin'\n * ]}\n * >\n * <FloatingCard id=\"panel-1\" title=\"My Panel\">\n * <div>Panel content</div>\n * </FloatingCard>\n * </FloatingCardProvider>\n * ```\n */\nexport function FloatingCardProvider({\n children,\n icon,\n headerActions,\n initialPinned,\n bounds = 'provider',\n className,\n}: FloatingCardProviderProps) {\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [cards, setCards] = useState<Record<UniqueId, HTMLDivElement>>({});\n\n const pinnedRef = useRef<Set<UniqueId>>(new Set(initialPinned));\n const pinListenersRef = useRef<Set<() => void>>(new Set());\n\n const {\n layouts,\n registerCard,\n unregisterCard,\n moveCard,\n resizeCard,\n bringToFront,\n } = useCardLayout();\n\n const notifyPinChange = useCallback(() => {\n for (const listener of pinListenersRef.current) {\n listener();\n }\n }, []);\n\n const isPinned = useCallback((id: UniqueId) => pinnedRef.current.has(id), []);\n\n const subscribeToPinState = useCallback((callback: () => void) => {\n pinListenersRef.current.add(callback);\n\n return () => {\n pinListenersRef.current.delete(callback);\n };\n }, []);\n\n const togglePinCard = useCallback(\n (id: UniqueId) => {\n const next = new Set(pinnedRef.current);\n\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n\n pinnedRef.current = next;\n notifyPinChange();\n },\n [notifyPinChange],\n );\n\n const removeRef = useCallback(\n (id: UniqueId) => {\n setCards((current) => {\n if (!current[id]) {\n return current;\n }\n\n const next = { ...current };\n delete next[id];\n\n return next;\n });\n\n if (pinnedRef.current.has(id)) {\n const next = new Set(pinnedRef.current);\n next.delete(id);\n pinnedRef.current = next;\n notifyPinChange();\n }\n },\n [notifyPinChange],\n );\n\n const addRef = useCallback((id: UniqueId, ref: HTMLDivElement | null) => {\n if (!ref) {\n return;\n }\n\n setCards((current) =>\n current[id] === ref ? current : { ...current, [id]: ref },\n );\n }, []);\n\n const closeCard = useCallback(\n (id: UniqueId) => {\n unregisterCard(id);\n removeRef(id);\n },\n [removeRef, unregisterCard],\n );\n\n const getBounds = useCallback((): Bounds => {\n const element = rootRef.current;\n\n if (!element) {\n return { top: 0, left: 0, right: 0, bottom: 0 };\n }\n\n const rect = element.getBoundingClientRect();\n\n if (bounds === 'viewport') {\n // Cards are positioned relative to the provider, so the viewport box is\n // expressed in that coordinate space by subtracting the provider offset.\n return {\n top: -rect.top,\n left: -rect.left,\n right: window.innerWidth - rect.left,\n bottom: window.innerHeight - rect.top,\n };\n }\n\n return { top: 0, left: 0, right: rect.width, bottom: rect.height };\n }, [bounds]);\n\n const contextValue = useMemo<FloatingCardContextValue>(\n () => ({\n cards,\n closeCard,\n togglePinCard,\n isPinned,\n subscribeToPinState,\n }),\n [cards, closeCard, togglePinCard, isPinned, subscribeToPinState],\n );\n\n const registryValue = useMemo<FloatingCardRegistryValue>(\n () => ({ openCard: registerCard, addRef }),\n [registerCard, addRef],\n );\n\n return (\n <FloatingCardContext.Provider value={contextValue}>\n <FloatingCardRegistryContext.Provider value={registryValue}>\n <div className={clsx(styles.providerRoot, className)} ref={rootRef}>\n {Object.entries(layouts).map(([id, layout]) => (\n <CardPanel\n actions={resolveMaybeFactory(headerActions, id)}\n getBounds={getBounds}\n icon={resolveMaybeFactory(icon, id)}\n id={id as UniqueId}\n isPinned={isPinned}\n key={id}\n layout={layout}\n onAddRef={addRef}\n onClose={closeCard}\n onFocus={bringToFront}\n onMove={moveCard}\n onResize={resizeCard}\n onTogglePin={togglePinCard}\n subscribeToPinState={subscribeToPinState}\n />\n ))}\n {children}\n </div>\n </FloatingCardRegistryContext.Provider>\n </FloatingCardContext.Provider>\n );\n}\n\ntype CardPanelProps = {\n actions: FloatingCardHeaderAction[] | undefined;\n getBounds: () => Bounds;\n icon: React.ReactNode;\n id: UniqueId;\n isPinned: (id: UniqueId) => boolean;\n layout: FloatingCardLayout;\n onAddRef: (id: UniqueId, ref: HTMLDivElement | null) => void;\n onClose: (id: UniqueId) => void;\n onFocus: (id: UniqueId) => void;\n onMove: (id: UniqueId, position: Position) => void;\n onResize: (id: UniqueId, dimensions: Dimensions, position: Position) => void;\n onTogglePin: (id: UniqueId) => void;\n subscribeToPinState: (callback: () => void) => () => void;\n};\n\n/**\n * Binds one card's identity to the provider's callbacks so {@link FloatingCardPanel}\n * can stay a plain presentational component.\n *\n * @remarks\n * Pin state lives in a mutable store rather than React state, so it is read\n * through `useSyncExternalStore` -- only the cards whose pin state changed\n * re-render.\n */\nfunction CardPanel({\n actions,\n getBounds,\n icon,\n id,\n isPinned,\n layout,\n onAddRef,\n onClose,\n onFocus,\n onMove,\n onResize,\n onTogglePin,\n subscribeToPinState,\n}: CardPanelProps) {\n const { title } = layout;\n\n const pinned = useSyncExternalStore(\n subscribeToPinState,\n () => isPinned(id),\n () => false,\n );\n\n const contentRef = useCallback(\n (element: HTMLDivElement | null) => {\n onAddRef(id, element);\n },\n [id, onAddRef],\n );\n\n return (\n <FloatingCardPanel\n actions={\n <CardHeaderActions\n actions={actions}\n id={id}\n isPinned={pinned}\n onClose={() => onClose(id)}\n onTogglePin={() => onTogglePin(id)}\n />\n }\n contentRef={contentRef}\n getBounds={getBounds}\n header={<CardHeaderStart icon={icon} title={title} />}\n id={id}\n isPinned={pinned}\n // Ids are typically uuids, which read as noise to a screen reader, so an\n // untitled card gets a generic name instead.\n label={title ?? 'Floating card'}\n layout={layout}\n onFocus={() => onFocus(id)}\n onMove={(position) => onMove(id, position)}\n onResize={(dimensions, position) => onResize(id, dimensions, position)}\n />\n );\n}\n"],"mappings":"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"}
@@ -13,21 +13,36 @@
13
13
  @reference '@accelint/design-foundation/styles';
14
14
 
15
15
  @layer components.l3 {
16
- .cardContent {
17
- @apply h-full w-full;
18
- }
19
-
16
+ /* The provider covers its container but stays transparent to pointer events,
17
+ so only the cards themselves are interactive and the application content
18
+ beneath keeps working normally. */
20
19
  .providerRoot {
21
20
  @apply pointer-events-none absolute inset-0;
22
21
  }
23
22
 
23
+ .panel {
24
+ @apply bg-surface-default rounded-large shadow-elevation-overlay-bold pointer-events-auto absolute flex flex-col overflow-hidden;
25
+ }
26
+
27
+ .header {
28
+ @apply p-xs gap-xs text-header-m @container/floating-card-header flex h-32 shrink-0 cursor-grab items-center;
29
+ }
30
+
31
+ /* A pinned card cannot be moved, so its header stops advertising a drag. */
32
+ .panel[data-pinned] .header {
33
+ @apply cursor-default;
34
+ }
35
+
24
36
  .headerSide {
25
37
  @apply gap-xs flex h-full items-center;
26
38
  }
27
39
 
28
- /* Zero width + pointer-events-none lets the title visually overflow the
29
- flex row without consuming drag-handle space or intercepting pointer
30
- gestures meant for dockview's drag handle (.dv-void-container). */
40
+ .headerActions {
41
+ @apply gap-xs ml-auto flex h-full items-center;
42
+ }
43
+
44
+ /* Zero width + pointer-events-none lets the title visually overflow the flex
45
+ row without consuming space or swallowing the header's drag gesture. */
31
46
  .headerTitleContainer {
32
47
  @apply text-header-m pl-xs pointer-events-none h-full w-0;
33
48
  }
@@ -42,37 +57,76 @@
42
57
  @apply h-full truncate leading-24 @min-[1rem]/floating-card-header:w-[calc(100cqw-10rem)];
43
58
  }
44
59
 
45
- .floatingCardProvider {
46
- @apply absolute inset-0;
47
- :global(.dv-dockview) {
48
- --dv-group-view-background-color: transparent;
49
- --dv-tabs-and-actions-container-background-color: var(
50
- --bg-surface-default
51
- );
52
- --dv-floating-box-shadow: var(--shadow-elevation-overlay-bold);
53
- }
54
- :global(.dv-groupview) {
55
- --dv-group-view-background-color: var(--bg-surface-default);
56
- @apply pointer-events-auto;
57
- }
58
- :global(.dv-resize-container) {
59
- @apply rounded-large pointer-events-auto;
60
- }
61
-
62
- :global(.dv-tabs-and-actions-container) {
63
- --dv-tabs-and-actions-container-height: 32px;
64
- @apply p-xs text-header-m @container/floating-card-header;
65
- }
66
- :global(.dv-scrollable) {
67
- display: none;
68
- }
69
- :global(.dv-void-container) {
70
- cursor: grab;
71
- }
72
-
73
- :global(.dv-resize-container[data-pinned]) :global(.dv-void-container) {
74
- pointer-events: none;
75
- cursor: default;
76
- }
60
+ .content {
61
+ @apply min-h-0 flex-1;
62
+ }
63
+
64
+ /* Resize handles are invisible hit areas laid over the card's edges and
65
+ corners. Corners sit above edges so the diagonal cursors win where the two
66
+ overlap. */
67
+ .resize-n,
68
+ .resize-s,
69
+ .resize-e,
70
+ .resize-w,
71
+ .resize-ne,
72
+ .resize-nw,
73
+ .resize-se,
74
+ .resize-sw {
75
+ @apply absolute;
76
+ }
77
+
78
+ .resize-n,
79
+ .resize-s {
80
+ @apply h-xxs inset-x-0;
81
+ cursor: ns-resize;
82
+ }
83
+
84
+ .resize-e,
85
+ .resize-w {
86
+ @apply w-xxs inset-y-0;
87
+ cursor: ew-resize;
88
+ }
89
+
90
+ .resize-n {
91
+ @apply top-0;
92
+ }
93
+
94
+ .resize-s {
95
+ @apply bottom-0;
96
+ }
97
+
98
+ .resize-e {
99
+ @apply right-0;
100
+ }
101
+
102
+ .resize-w {
103
+ @apply left-0;
104
+ }
105
+
106
+ .resize-ne,
107
+ .resize-nw,
108
+ .resize-se,
109
+ .resize-sw {
110
+ @apply size-s z-1;
111
+ }
112
+
113
+ .resize-ne {
114
+ @apply top-0 right-0;
115
+ cursor: nesw-resize;
116
+ }
117
+
118
+ .resize-nw {
119
+ @apply top-0 left-0;
120
+ cursor: nwse-resize;
121
+ }
122
+
123
+ .resize-se {
124
+ @apply right-0 bottom-0;
125
+ cursor: nwse-resize;
126
+ }
127
+
128
+ .resize-sw {
129
+ @apply bottom-0 left-0;
130
+ cursor: nesw-resize;
77
131
  }
78
132
  }