@psnext/design-system 2.6.0 → 2.7.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 (281) hide show
  1. package/DESIGN.md +4 -4
  2. package/dist/Logo.cjs +322 -315
  3. package/dist/Logo.cjs.map +1 -1
  4. package/dist/Logo.js +322 -315
  5. package/dist/Logo.js.map +1 -1
  6. package/dist/Mosaic.cjs +72 -15
  7. package/dist/Mosaic.cjs.map +1 -1
  8. package/dist/Mosaic.js +72 -15
  9. package/dist/Mosaic.js.map +1 -1
  10. package/dist/index.d.cts +5 -5
  11. package/dist/index.d.ts +5 -5
  12. package/dist/index10.d.cts +7 -7
  13. package/dist/index10.d.cts.map +1 -1
  14. package/dist/index10.d.ts +6 -6
  15. package/dist/index11.d.cts +3 -3
  16. package/dist/index11.d.cts.map +1 -1
  17. package/dist/index11.d.ts +3 -3
  18. package/dist/index12.d.cts +11 -11
  19. package/dist/index12.d.ts +12 -12
  20. package/dist/index12.d.ts.map +1 -1
  21. package/dist/index13.d.cts +6 -6
  22. package/dist/index13.d.ts +6 -6
  23. package/dist/index13.d.ts.map +1 -1
  24. package/dist/index14.d.cts +5 -5
  25. package/dist/index14.d.cts.map +1 -1
  26. package/dist/index14.d.ts +5 -5
  27. package/dist/index15.d.cts +2 -2
  28. package/dist/index15.d.ts +2 -2
  29. package/dist/index16.d.cts +3 -3
  30. package/dist/index16.d.cts.map +1 -1
  31. package/dist/index16.d.ts +3 -3
  32. package/dist/index16.d.ts.map +1 -1
  33. package/dist/index17.d.cts +2 -2
  34. package/dist/index17.d.ts +2 -2
  35. package/dist/index18.d.cts +4 -4
  36. package/dist/index18.d.cts.map +1 -1
  37. package/dist/index18.d.ts +4 -4
  38. package/dist/index19.d.cts +11 -11
  39. package/dist/index19.d.cts.map +1 -1
  40. package/dist/index19.d.ts +11 -11
  41. package/dist/index2.d.cts +8 -8
  42. package/dist/index2.d.ts +8 -8
  43. package/dist/index2.d.ts.map +1 -1
  44. package/dist/index20.d.cts +10 -10
  45. package/dist/index20.d.ts +10 -10
  46. package/dist/index21.d.cts +8 -8
  47. package/dist/index21.d.ts +8 -8
  48. package/dist/index22.d.cts +16 -11
  49. package/dist/index22.d.cts.map +1 -1
  50. package/dist/index22.d.ts +16 -11
  51. package/dist/index22.d.ts.map +1 -1
  52. package/dist/index23.d.cts +16 -16
  53. package/dist/index23.d.cts.map +1 -1
  54. package/dist/index23.d.ts +16 -16
  55. package/dist/index24.d.cts +4 -4
  56. package/dist/index24.d.cts.map +1 -1
  57. package/dist/index24.d.ts +4 -4
  58. package/dist/index25.d.cts +11 -11
  59. package/dist/index25.d.cts.map +1 -1
  60. package/dist/index25.d.ts +11 -11
  61. package/dist/index26.d.cts +16 -16
  62. package/dist/index26.d.cts.map +1 -1
  63. package/dist/index26.d.ts +16 -16
  64. package/dist/index26.d.ts.map +1 -1
  65. package/dist/index27.d.cts +10 -10
  66. package/dist/index27.d.cts.map +1 -1
  67. package/dist/index27.d.ts +10 -10
  68. package/dist/index28.d.cts +2 -2
  69. package/dist/index28.d.cts.map +1 -1
  70. package/dist/index28.d.ts +2 -2
  71. package/dist/index28.d.ts.map +1 -1
  72. package/dist/index29.d.cts +14 -14
  73. package/dist/index29.d.cts.map +1 -1
  74. package/dist/index29.d.ts +13 -13
  75. package/dist/index29.d.ts.map +1 -1
  76. package/dist/index3.d.cts +13 -13
  77. package/dist/index3.d.cts.map +1 -1
  78. package/dist/index3.d.ts +13 -13
  79. package/dist/index30.d.cts +2 -2
  80. package/dist/index30.d.ts +2 -2
  81. package/dist/index30.d.ts.map +1 -1
  82. package/dist/index31.d.cts +7 -7
  83. package/dist/index31.d.ts +7 -7
  84. package/dist/index31.d.ts.map +1 -1
  85. package/dist/index32.d.cts +4 -4
  86. package/dist/index32.d.cts.map +1 -1
  87. package/dist/index32.d.ts +5 -5
  88. package/dist/index32.d.ts.map +1 -1
  89. package/dist/index33.d.cts +4 -4
  90. package/dist/index33.d.ts +4 -4
  91. package/dist/index34.d.cts +6 -6
  92. package/dist/index34.d.cts.map +1 -1
  93. package/dist/index34.d.ts +5 -5
  94. package/dist/index34.d.ts.map +1 -1
  95. package/dist/index35.d.cts +5 -5
  96. package/dist/index35.d.cts.map +1 -1
  97. package/dist/index35.d.ts +4 -4
  98. package/dist/index36.d.cts +5 -5
  99. package/dist/index36.d.cts.map +1 -1
  100. package/dist/index36.d.ts +5 -5
  101. package/dist/index36.d.ts.map +1 -1
  102. package/dist/index37.d.cts +11 -11
  103. package/dist/index37.d.cts.map +1 -1
  104. package/dist/index37.d.ts +10 -10
  105. package/dist/index38.d.cts +5 -5
  106. package/dist/index38.d.cts.map +1 -1
  107. package/dist/index38.d.ts +5 -5
  108. package/dist/index39.d.cts +17 -17
  109. package/dist/index39.d.cts.map +1 -1
  110. package/dist/index39.d.ts +16 -16
  111. package/dist/index39.d.ts.map +1 -1
  112. package/dist/index4.d.cts +2 -2
  113. package/dist/index4.d.ts +2 -2
  114. package/dist/index40.d.cts +3 -3
  115. package/dist/index40.d.ts +3 -3
  116. package/dist/index40.d.ts.map +1 -1
  117. package/dist/index41.d.cts +4 -4
  118. package/dist/index41.d.cts.map +1 -1
  119. package/dist/index41.d.ts +4 -4
  120. package/dist/index41.d.ts.map +1 -1
  121. package/dist/index42.d.cts +3 -2
  122. package/dist/index42.d.cts.map +1 -1
  123. package/dist/index42.d.ts +3 -2
  124. package/dist/index42.d.ts.map +1 -1
  125. package/dist/index43.d.cts +17 -17
  126. package/dist/index43.d.ts +17 -17
  127. package/dist/index43.d.ts.map +1 -1
  128. package/dist/index44.d.cts +77 -11
  129. package/dist/index44.d.cts.map +1 -1
  130. package/dist/index44.d.ts +77 -11
  131. package/dist/index44.d.ts.map +1 -1
  132. package/dist/index45.d.cts +5 -5
  133. package/dist/index45.d.cts.map +1 -1
  134. package/dist/index45.d.ts +5 -5
  135. package/dist/index45.d.ts.map +1 -1
  136. package/dist/index46.d.cts +11 -11
  137. package/dist/index46.d.cts.map +1 -1
  138. package/dist/index46.d.ts +11 -11
  139. package/dist/index46.d.ts.map +1 -1
  140. package/dist/index47.d.cts +9 -9
  141. package/dist/index47.d.cts.map +1 -1
  142. package/dist/index47.d.ts +9 -9
  143. package/dist/index47.d.ts.map +1 -1
  144. package/dist/index49.d.cts +2 -2
  145. package/dist/index49.d.ts +2 -2
  146. package/dist/index5.d.cts +7 -7
  147. package/dist/index5.d.cts.map +1 -1
  148. package/dist/index5.d.ts +7 -7
  149. package/dist/index50.d.cts +8 -8
  150. package/dist/index50.d.ts +8 -8
  151. package/dist/index50.d.ts.map +1 -1
  152. package/dist/index51.d.cts +2 -2
  153. package/dist/index51.d.ts +2 -2
  154. package/dist/index51.d.ts.map +1 -1
  155. package/dist/index52.d.cts +4 -4
  156. package/dist/index52.d.ts +4 -4
  157. package/dist/index52.d.ts.map +1 -1
  158. package/dist/index53.d.cts +4 -4
  159. package/dist/index53.d.cts.map +1 -1
  160. package/dist/index53.d.ts +4 -4
  161. package/dist/index53.d.ts.map +1 -1
  162. package/dist/index54.d.cts +3 -3
  163. package/dist/index54.d.cts.map +1 -1
  164. package/dist/index54.d.ts +3 -3
  165. package/dist/index54.d.ts.map +1 -1
  166. package/dist/index55.d.cts +11 -11
  167. package/dist/index55.d.ts +11 -11
  168. package/dist/index55.d.ts.map +1 -1
  169. package/dist/index56.d.cts +9 -9
  170. package/dist/index56.d.cts.map +1 -1
  171. package/dist/index56.d.ts +9 -9
  172. package/dist/index56.d.ts.map +1 -1
  173. package/dist/index57.d.cts +5 -5
  174. package/dist/index57.d.cts.map +1 -1
  175. package/dist/index57.d.ts +5 -5
  176. package/dist/index57.d.ts.map +1 -1
  177. package/dist/index58.d.cts +25 -25
  178. package/dist/index58.d.cts.map +1 -1
  179. package/dist/index58.d.ts +27 -27
  180. package/dist/index58.d.ts.map +1 -1
  181. package/dist/index59.d.cts +5 -5
  182. package/dist/index59.d.ts +5 -5
  183. package/dist/index59.d.ts.map +1 -1
  184. package/dist/index6.d.cts +5 -5
  185. package/dist/index6.d.cts.map +1 -1
  186. package/dist/index6.d.ts +5 -5
  187. package/dist/index6.d.ts.map +1 -1
  188. package/dist/index60.d.cts +2 -2
  189. package/dist/index60.d.ts +2 -2
  190. package/dist/index60.d.ts.map +1 -1
  191. package/dist/index61.d.cts +2 -2
  192. package/dist/index61.d.cts.map +1 -1
  193. package/dist/index61.d.ts +2 -2
  194. package/dist/index61.d.ts.map +1 -1
  195. package/dist/index62.d.cts +2 -2
  196. package/dist/index62.d.cts.map +1 -1
  197. package/dist/index62.d.ts +2 -2
  198. package/dist/index62.d.ts.map +1 -1
  199. package/dist/index63.d.cts +4 -4
  200. package/dist/index63.d.ts +4 -4
  201. package/dist/index63.d.ts.map +1 -1
  202. package/dist/index64.d.cts +9 -9
  203. package/dist/index64.d.ts +9 -9
  204. package/dist/index64.d.ts.map +1 -1
  205. package/dist/index65.d.cts +10 -10
  206. package/dist/index65.d.cts.map +1 -1
  207. package/dist/index65.d.ts +11 -11
  208. package/dist/index66.d.cts +6 -6
  209. package/dist/index66.d.cts.map +1 -1
  210. package/dist/index66.d.ts +7 -7
  211. package/dist/index66.d.ts.map +1 -1
  212. package/dist/index67.d.cts +4 -4
  213. package/dist/index67.d.ts +4 -4
  214. package/dist/index67.d.ts.map +1 -1
  215. package/dist/index68.d.cts +2 -2
  216. package/dist/index68.d.cts.map +1 -1
  217. package/dist/index68.d.ts +2 -2
  218. package/dist/index68.d.ts.map +1 -1
  219. package/dist/index69.d.cts +5 -5
  220. package/dist/index69.d.ts +5 -5
  221. package/dist/index69.d.ts.map +1 -1
  222. package/dist/index7.d.cts +8 -8
  223. package/dist/index7.d.cts.map +1 -1
  224. package/dist/index7.d.ts +8 -8
  225. package/dist/index7.d.ts.map +1 -1
  226. package/dist/index70.d.cts +3 -3
  227. package/dist/index70.d.ts +3 -3
  228. package/dist/index70.d.ts.map +1 -1
  229. package/dist/index71.d.cts +4 -4
  230. package/dist/index71.d.ts +4 -4
  231. package/dist/index72.d.cts +7 -7
  232. package/dist/index72.d.cts.map +1 -1
  233. package/dist/index72.d.ts +7 -7
  234. package/dist/index72.d.ts.map +1 -1
  235. package/dist/index73.d.cts +2 -2
  236. package/dist/index73.d.cts.map +1 -1
  237. package/dist/index73.d.ts +2 -2
  238. package/dist/index74.d.cts +8 -8
  239. package/dist/index74.d.cts.map +1 -1
  240. package/dist/index74.d.ts +7 -7
  241. package/dist/index74.d.ts.map +1 -1
  242. package/dist/index75.d.cts +7 -7
  243. package/dist/index75.d.cts.map +1 -1
  244. package/dist/index75.d.ts +7 -7
  245. package/dist/index75.d.ts.map +1 -1
  246. package/dist/index76.d.cts +2 -2
  247. package/dist/index76.d.ts +2 -2
  248. package/dist/index77.d.cts +8 -8
  249. package/dist/index77.d.ts +8 -8
  250. package/dist/index77.d.ts.map +1 -1
  251. package/dist/index8.d.cts +4 -4
  252. package/dist/index8.d.cts.map +1 -1
  253. package/dist/index8.d.ts +4 -4
  254. package/dist/index9.d.cts +2 -2
  255. package/dist/index9.d.cts.map +1 -1
  256. package/dist/index9.d.ts +2 -2
  257. package/dist/index9.d.ts.map +1 -1
  258. package/dist/patterns/DataTable/index.d.cts +3 -3
  259. package/dist/patterns/DataTable/index.d.cts.map +1 -1
  260. package/dist/patterns/DataTable/index.d.ts +3 -3
  261. package/dist/patterns/DataTable/index.d.ts.map +1 -1
  262. package/dist/patterns/Footer/index.d.cts +7 -7
  263. package/dist/patterns/Footer/index.d.ts +7 -7
  264. package/dist/patterns/Footer/index.d.ts.map +1 -1
  265. package/dist/patterns/MediaObject/index.d.cts +12 -12
  266. package/dist/patterns/MediaObject/index.d.cts.map +1 -1
  267. package/dist/patterns/MediaObject/index.d.ts +12 -12
  268. package/dist/patterns/MediaObject/index.d.ts.map +1 -1
  269. package/dist/patterns/SectionCard/index.d.cts +2 -2
  270. package/dist/patterns/SectionCard/index.d.ts +2 -2
  271. package/dist/patterns/SectionCard/index.d.ts.map +1 -1
  272. package/dist/patterns/SectionHeading/index.d.cts +2 -2
  273. package/dist/patterns/SectionHeading/index.d.ts +2 -2
  274. package/dist/patterns/SectionHeading/index.d.ts.map +1 -1
  275. package/dist/primitives/Combobox/index.cjs.map +1 -1
  276. package/dist/primitives/Combobox/index.js.map +1 -1
  277. package/dist/primitives/Mosaic/index.d.cts +2 -2
  278. package/dist/primitives/Mosaic/index.d.ts +2 -2
  279. package/dist/primitives/index.d.cts +2 -2
  280. package/dist/primitives/index.d.ts +2 -2
  281. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Mosaic.js","names":[],"sources":["../src/primitives/Mosaic/Mosaic.utils.ts","../src/primitives/Mosaic/Mosaic.tsx"],"sourcesContent":["// Pure tree/geometry helpers for Mosaic, kept separate from the component so\n// the tree algorithm and drop-zone math are unit-testable without a real\n// browser — matching MultiColumn.utils.ts's split between pure logic and DOM\n// wiring.\n\n/** A pane's identity. Compared with `===`, so no object identities. */\ntype MosaicKey = string | number;\n\n/** \"row\" places children side by side (horizontal split); \"column\" stacks them (vertical split). */\ntype MosaicDirection = \"row\" | \"column\";\n\n/** Sequence of \"first\"/\"second\" steps from the tree root down to a node. */\ntype MosaicPath = (\"first\" | \"second\")[];\n\ntype MosaicParent<T extends MosaicKey = MosaicKey> = {\n direction: MosaicDirection;\n first: MosaicNode<T>;\n second: MosaicNode<T>;\n /** Percentage (0-100) of the group's size given to `first`. Defaults to 50 when omitted. */\n splitPercentage?: number;\n};\n\n/** A leaf pane id, or a parent split of two further nodes. */\ntype MosaicNode<T extends MosaicKey = MosaicKey> = T | MosaicParent<T>;\n\n/** Which edge (or center) of a pane a drag is hovering over. */\ntype DropZone = \"top\" | \"bottom\" | \"left\" | \"right\" | \"center\";\n\n/** Every recursive walk depends on this being correct — `T` is constrained to non-object keys precisely so this check can't be fooled by a leaf that happens to be an object. */\nfunction isParent<T extends MosaicKey>(node: MosaicNode<T>): node is MosaicParent<T> {\n return typeof node === \"object\" && node !== null && \"direction\" in node;\n}\n\n/** All leaf ids under `root`, in first-then-second (left-to-right / top-to-bottom) order. */\nfunction getLeaves<T extends MosaicKey>(root: MosaicNode<T> | null): T[] {\n if (root === null) return [];\n if (!isParent(root)) return [root];\n return [...getLeaves(root.first), ...getLeaves(root.second)];\n}\n\n/** Walks `path` from `root`; `null` if the path runs off a leaf or is otherwise invalid. `path: []` returns `root` itself. */\nfunction getNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n path: MosaicPath,\n): MosaicNode<T> | null {\n let node = root;\n for (const step of path) {\n if (node === null || !isParent(node)) return null;\n node = node[step];\n }\n return node;\n}\n\n/** First DFS path whose leaf `===` matches `leaf`; `null` if not found. Assumes leaf ids are unique across the tree — `Mosaic` warns in dev mode when they aren't. */\nfunction getPathToLeaf<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n leaf: T,\n): MosaicPath | null {\n if (root === null) return null;\n function search(node: MosaicNode<T>, path: MosaicPath): MosaicPath | null {\n if (!isParent(node)) {\n return node === leaf ? path : null;\n }\n return search(node.first, [...path, \"first\"]) ?? search(node.second, [...path, \"second\"]);\n }\n return search(root, []);\n}\n\n/** Immutable path-copy replace: only nodes along `path` are cloned, siblings off the path are referentially reused. `path: []` replaces the whole tree. */\nfunction replaceNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n next: MosaicNode<T>,\n): MosaicNode<T> {\n if (path.length === 0) return next;\n if (!isParent(root)) return root;\n const [step, ...rest] = path;\n if (step === \"first\") {\n return { ...root, first: replaceNodeAtPath(root.first, rest, next) };\n }\n return { ...root, second: replaceNodeAtPath(root.second, rest, next) };\n}\n\n/** Patches `splitPercentage` on the parent at `path`, used by the resize-commit callback. No-ops (dev-mode warns) if `path` doesn't resolve to a parent. */\nfunction updateSplitPercentageAtPath<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n splitPercentage: number,\n): MosaicNode<T> {\n const node = getNodeAtPath(root, path);\n if (node === null || !isParent(node)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"Mosaic: updateSplitPercentageAtPath was called with a path that doesn't resolve to a parent node.\",\n );\n }\n return root;\n }\n return replaceNodeAtPath(root, path, { ...node, splitPercentage });\n}\n\n/**\n * Removes the leaf at `path`, collapsing its parent so the sibling takes the\n * parent's position. Returns `null` only when `path` is `[]` (the sole\n * remaining leaf — the root itself — is removed).\n */\nfunction removeLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n): MosaicNode<T> | null {\n if (path.length === 0) return null;\n const parentPath = path.slice(0, -1);\n const lastStep = path[path.length - 1];\n const parent = getNodeAtPath(root, parentPath);\n if (parent === null || !isParent(parent)) return root;\n const sibling = lastStep === \"first\" ? parent.second : parent.first;\n if (parentPath.length === 0) return sibling;\n return replaceNodeAtPath(root, parentPath, sibling);\n}\n\n/**\n * Replaces the node at `path` with a new `MosaicParent` split 50/50 between\n * `newLeaf` and the existing node there. `\"before\"` (top/left drops) makes\n * `newLeaf` the `first` child; `\"after\"` (bottom/right drops) makes it `second`.\n */\nfunction splitLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n newLeaf: T,\n direction: MosaicDirection,\n position: \"before\" | \"after\",\n): MosaicNode<T> {\n const existing = getNodeAtPath(root, path);\n if (existing === null) return root;\n const parent: MosaicParent<T> =\n position === \"before\"\n ? { direction, first: newLeaf, second: existing, splitPercentage: 50 }\n : { direction, first: existing, second: newLeaf, splitPercentage: 50 };\n return replaceNodeAtPath(root, path, parent);\n}\n\n/** Swaps the two leaves at `pathA`/`pathB` in place, no restructuring. No-op if the paths are equal or either is invalid. Used for center-zone drops. */\nfunction swapLeaves<T extends MosaicKey>(\n root: MosaicNode<T>,\n pathA: MosaicPath,\n pathB: MosaicPath,\n): MosaicNode<T> {\n if (pathA.length === pathB.length && pathA.every((step, i) => step === pathB[i])) return root;\n const nodeA = getNodeAtPath(root, pathA);\n const nodeB = getNodeAtPath(root, pathB);\n if (nodeA === null || nodeB === null) return root;\n const afterA = replaceNodeAtPath(root, pathA, nodeB);\n return replaceNodeAtPath(afterA, pathB, nodeA);\n}\n\n/**\n * The drag-drop commit entry point. No-op on a self-drop. `zone: \"center\"`\n * swaps the two leaves; otherwise removes the source leaf and re-resolves the\n * target's path against the POST-REMOVAL tree (removal can shift paths on the\n * way to the target, e.g. when an ancestor collapses away) before splitting\n * at that re-resolved path — never adjusting the original path by arithmetic.\n */\nfunction moveLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n sourceLeaf: T,\n targetLeaf: T,\n zone: DropZone,\n): MosaicNode<T> | null {\n if (sourceLeaf === targetLeaf) return root;\n const sourcePath = getPathToLeaf(root, sourceLeaf);\n const targetPath = getPathToLeaf(root, targetLeaf);\n if (sourcePath === null || targetPath === null) return root;\n\n if (zone === \"center\") {\n return swapLeaves(root, sourcePath, targetPath);\n }\n\n const afterRemoval = removeLeaf(root, sourcePath);\n if (afterRemoval === null) {\n // Unreachable: root having only sourceLeaf means targetLeaf couldn't have\n // been found above (sourceLeaf === targetLeaf is already handled). Kept\n // as a defensive no-op rather than assuming it can never fire.\n return root;\n }\n const resolvedTargetPath = getPathToLeaf(afterRemoval, targetLeaf);\n if (resolvedTargetPath === null) return afterRemoval;\n\n const direction: MosaicDirection = zone === \"top\" || zone === \"bottom\" ? \"column\" : \"row\";\n const position: \"before\" | \"after\" = zone === \"top\" || zone === \"left\" ? \"before\" : \"after\";\n return splitLeaf(afterRemoval, resolvedTargetPath, sourceLeaf, direction, position);\n}\n\n/** A pane's rect in the same coordinate space as pointer `clientX`/`clientY` (i.e. `getBoundingClientRect()`). */\ntype PaneRect = { left: number; top: number; width: number; height: number };\n\n/**\n * Classifies a pointer position within a pane into one of 5 drop zones.\n * Within `dropZoneFraction` of an edge (0-1, fraction of that axis's size)\n * counts as that edge; otherwise center. At corners, where both axes are\n * within range, the axis whose edge distance is smaller wins, so corners\n * resolve deterministically instead of arbitrarily favoring x or y.\n */\nfunction classifyDropZone(\n rect: PaneRect,\n clientX: number,\n clientY: number,\n dropZoneFraction: number,\n): DropZone {\n const xFraction = rect.width === 0 ? 0.5 : (clientX - rect.left) / rect.width;\n const yFraction = rect.height === 0 ? 0.5 : (clientY - rect.top) / rect.height;\n const xEdgeDistance = Math.min(xFraction, 1 - xFraction);\n const yEdgeDistance = Math.min(yFraction, 1 - yFraction);\n\n if (xEdgeDistance >= dropZoneFraction && yEdgeDistance >= dropZoneFraction) return \"center\";\n if (xEdgeDistance < yEdgeDistance) {\n return xFraction < 0.5 ? \"left\" : \"right\";\n }\n return yFraction < 0.5 ? \"top\" : \"bottom\";\n}\n\nexport {\n isParent,\n getLeaves,\n getNodeAtPath,\n getPathToLeaf,\n replaceNodeAtPath,\n updateSplitPercentageAtPath,\n removeLeaf,\n splitLeaf,\n swapLeaves,\n moveLeaf,\n classifyDropZone,\n type MosaicKey,\n type MosaicDirection,\n type MosaicPath,\n type MosaicParent,\n type MosaicNode,\n type DropZone,\n type PaneRect,\n};\n","\"use client\";\n\nimport { GripVerticalIcon, PanelLeftIcon, PanelTopIcon, PencilIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/primitives/Button\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"@/primitives/Resizable\";\nimport { cn } from \"@/utils\";\nimport {\n type DropZone,\n type MosaicDirection,\n type MosaicKey,\n type MosaicNode,\n type MosaicPath,\n classifyDropZone,\n getLeaves,\n getNodeAtPath,\n isParent,\n moveLeaf,\n removeLeaf,\n splitLeaf,\n updateSplitPercentageAtPath,\n} from \"./Mosaic.utils\";\n\nconst DEFAULT_DROP_ZONE_FRACTION = 0.25;\nconst DEFAULT_MIN_PANE_SIZE_PERCENTAGE = 10;\n\n// The context is intentionally widened to MosaicKey rather than parameterized\n// by the consumer's T — React context can't itself be generic. This is safe\n// at runtime because every id flowing through a given <Mosaic> instance's\n// context originates from that same instance's T-typed tree; MosaicWindow\n// narrows back to T at its own boundary.\ntype MosaicContextValue = {\n renderTile: (id: MosaicKey, path: MosaicPath) => React.ReactNode;\n renderTitle: ((id: MosaicKey, path: MosaicPath) => React.ReactNode) | undefined;\n onSplitLeaf: (path: MosaicPath, direction: MosaicDirection) => void;\n onRemoveLeaf: (path: MosaicPath) => void;\n onDragStart: (path: MosaicPath) => void;\n onDragMove: (targetPath: MosaicPath | null, zone: DropZone | null) => void;\n onDragEnd: (sourceId: MosaicKey, targetPath: MosaicPath | null, zone: DropZone | null) => void;\n onDragCancel: () => void;\n draggingPath: MosaicPath | null;\n dropTarget: { path: MosaicPath; zone: DropZone } | null;\n dragToRearrange: boolean;\n dropZoneFraction: number;\n renamable: boolean;\n getPaneName: (id: MosaicKey) => string | undefined;\n onRenamePane: (id: MosaicKey, name: string) => void;\n};\n\nconst MosaicContext = React.createContext<MosaicContextValue | null>(null);\n\n/** Hook giving `MosaicWindow` access to shared drag/split/remove actions; must be used inside a `Mosaic`. */\nfunction useMosaic(): MosaicContextValue {\n const context = React.useContext(MosaicContext);\n if (!context) {\n throw new Error(\"useMosaic must be used within a Mosaic.\");\n }\n return context;\n}\n\ntype MosaicProps<T extends MosaicKey = string> = Omit<\n React.ComponentProps<\"div\">,\n \"onChange\" | \"value\" | \"defaultValue\"\n> & {\n /** The tree of panes to render. `null` (or an empty tree via `emptyPlaceholder`) renders nothing tile-related. */\n value?: MosaicNode<T> | null;\n /** Initial tree when uncontrolled. */\n defaultValue?: MosaicNode<T> | null;\n /**\n * Fires with the updated tree after a resize, toolbar split/remove, or\n * drag-drop rearrange. Pass `value` back to fully control; omit for\n * internal (uncontrolled) tracking — mirrors MultiColumn's\n * `columns`/`onColumnsChange`.\n *\n * Note: there is no strict controlled veto. If a controlled consumer's\n * `onChange` doesn't feed back an updated `value` (e.g. to reject a\n * drag/split), the optimistic change still applies locally and persists —\n * the same behavior MultiColumn already ships for resize/reorder. A true\n * veto would need a different API shape (e.g. an `onBeforeChange` returning\n * `boolean`), which is out of scope here.\n */\n onChange?: (next: MosaicNode<T> | null) => void;\n /** Renders the content for a leaf pane; required — Mosaic has no default tile content. */\n renderTile: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders the title shown in a pane's toolbar. Defaults to `String(id)`. */\n renderTitle?: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders extra toolbar actions for a pane, after the built-in split/remove buttons. */\n renderControls?: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders a rename (pencil) button in each pane's toolbar; double-clicking the title also starts editing. Renaming sets a plain-text name that overrides `renderTitle`/`String(id)` for that pane. Default off. */\n renamable?: boolean;\n /** Custom pane names, keyed by leaf id (controlled). Only panes that have been renamed need an entry. */\n paneNames?: Partial<Record<T, string>>;\n /** Initial pane names when uncontrolled. */\n defaultPaneNames?: Partial<Record<T, string>>;\n /** Fires with the updated name map after a rename commits (Enter, blur, or the confirm affordance). Clearing a pane's name back to empty removes its entry, falling back to `renderTitle`/`String(id)` again. Pass `paneNames` back to fully control; omit for internal (uncontrolled) tracking. */\n onPaneNamesChange?: (names: Partial<Record<T, string>>) => void;\n /**\n * Creates the id for a new pane when a toolbar split button is used\n * (drag-triggered splits reuse the dragged pane's existing id instead).\n * May return a Promise. `renderTile` must be able to render whatever this\n * returns.\n */\n createNode: (path: MosaicPath) => T | Promise<T>;\n /** Renders a drag handle in each pane's toolbar for drag-to-split/rearrange. Toolbar split/remove buttons remain active either way. Default enabled. */\n dragToRearrange?: boolean;\n /** Fraction (0-1) of a pane's width/height, measured from each edge, that counts as an edge drop zone rather than the center. Defaults to `0.25`. */\n dropZoneFraction?: number;\n /** Minimum size (percentage, 0-100) a pane can be resized down to. Defaults to `10`. */\n minPaneSizePercentage?: number;\n /** Rendered instead of the tree when `value`/the live tree is `null` (e.g. every pane has been removed). */\n emptyPlaceholder?: React.ReactNode;\n};\n\n/** Recursive tiling layout: panes split into rows/columns, resized via draggable dividers, and rearranged by dragging a pane's title bar onto another pane's edge or center. */\nfunction Mosaic<T extends MosaicKey = string>({\n className,\n style,\n value,\n defaultValue,\n onChange,\n renderTile,\n renderTitle,\n renderControls,\n renamable = false,\n paneNames,\n defaultPaneNames,\n onPaneNamesChange,\n createNode,\n dragToRearrange = true,\n dropZoneFraction = DEFAULT_DROP_ZONE_FRACTION,\n minPaneSizePercentage = DEFAULT_MIN_PANE_SIZE_PERCENTAGE,\n emptyPlaceholder,\n ...props\n}: MosaicProps<T>) {\n // ---- Controlled/uncontrolled sync — generalizes MultiColumn's\n // columnsKey/syncedColumnsKey render-time-sync idiom to a tree. Unlike\n // MultiColumn, `value` is genuinely optional (the tree is stateful\n // regardless of controlled mode), so the resync only fires when `value` is\n // actually passed and has changed.\n const valueKey = React.useMemo(() => JSON.stringify(value ?? null), [value]);\n const [liveTree, setLiveTree] = React.useState<MosaicNode<T> | null>(\n value !== undefined ? value : (defaultValue ?? null),\n );\n const [syncedValueKey, setSyncedValueKey] = React.useState(valueKey);\n if (value !== undefined && valueKey !== syncedValueKey) {\n setSyncedValueKey(valueKey);\n setLiveTree(value);\n }\n\n // Mirrors `liveTree` for reads inside callbacks that resume after a gap\n // (an awaited `createNode`, or a pointerdown-to-pointerup drag session) —\n // those callbacks close over whatever `liveTree` was at the time they were\n // created, which can be stale if something else committed a change during\n // the gap. Reading `liveTreeRef.current` instead always reflects the tree\n // at the moment the callback actually runs, not the moment it was defined.\n const liveTreeRef = React.useRef(liveTree);\n liveTreeRef.current = liveTree;\n\n function commitTree(next: MosaicNode<T> | null) {\n setLiveTree(next);\n onChange?.(next);\n }\n\n // ---- Pane rename state — same render-time-sync idiom as the tree above,\n // but a separate controlled pair (not folded into `value`) since a pane's\n // display name and its position in the tree are independent concerns.\n const paneNamesKey = React.useMemo(() => JSON.stringify(paneNames ?? {}), [paneNames]);\n const [livePaneNames, setLivePaneNames] = React.useState<Partial<Record<T, string>>>(\n paneNames !== undefined ? paneNames : (defaultPaneNames ?? {}),\n );\n const [syncedPaneNamesKey, setSyncedPaneNamesKey] = React.useState(paneNamesKey);\n if (paneNames !== undefined && paneNamesKey !== syncedPaneNamesKey) {\n setSyncedPaneNamesKey(paneNamesKey);\n setLivePaneNames(paneNames);\n }\n\n function onRenamePane(id: T, name: string) {\n const trimmed = name.trim();\n const next = { ...livePaneNames };\n if (trimmed.length === 0) {\n delete next[id];\n } else {\n next[id] = trimmed;\n }\n setLivePaneNames(next);\n onPaneNamesChange?.(next);\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n const leaves = getLeaves(liveTree);\n if (new Set(leaves).size !== leaves.length) {\n console.warn(\n \"Mosaic: duplicate leaf ids detected in the tree. Every pane needs a unique id, or drag/split/remove operations may target the wrong pane.\",\n );\n }\n }\n\n // ---- Split/remove ----\n function onSplitLeaf(path: MosaicPath, direction: MosaicDirection) {\n if (liveTreeRef.current === null) return;\n // `createNode` may be async — read `liveTreeRef.current` again once it\n // resolves rather than the `liveTree` closed over above, in case a\n // resize/remove/drag committed a change while the promise was in flight.\n Promise.resolve(createNode(path)).then((newLeaf) => {\n const current = liveTreeRef.current;\n if (current === null) return;\n commitTree(splitLeaf(current, path, newLeaf, direction, \"after\"));\n });\n }\n\n function onRemoveLeaf(path: MosaicPath) {\n const current = liveTreeRef.current;\n if (current === null) return;\n commitTree(removeLeaf(current, path));\n }\n\n // ---- Resize commit — wired to each Group's onLayoutChanged (fires once,\n // after the pointer is released), not Panel.onResize (fires every pointer\n // move tick) — see Mosaic.tsx rendering below.\n function onGroupLayoutChanged(\n path: MosaicPath,\n layout: Record<string, number>,\n firstPanelId: string,\n ) {\n const current = liveTreeRef.current;\n if (current === null) return;\n const percentage = layout[firstPanelId];\n if (percentage === undefined) return;\n commitTree(updateSplitPercentageAtPath(current, path, percentage));\n }\n\n // ---- Drag-to-rearrange state — shared via context so every MosaicWindow\n // can render its own drag/drop-target feedback without prop-drilling.\n const [draggingPath, setDraggingPath] = React.useState<MosaicPath | null>(null);\n const [dropTarget, setDropTarget] = React.useState<{ path: MosaicPath; zone: DropZone } | null>(\n null,\n );\n\n function onDragStart(path: MosaicPath) {\n setDraggingPath(path);\n }\n\n function onDragMove(targetPath: MosaicPath | null, zone: DropZone | null) {\n setDropTarget(targetPath && zone ? { path: targetPath, zone } : null);\n }\n\n // `sourceId` — the dragged pane's own leaf id — is passed in directly by\n // the caller (`MosaicWindow` already knows its own `id` prop) rather than\n // re-derived here via `getNodeAtPath(tree, sourcePath)`. Two reasons:\n // 1. This fires synchronously from the same pointerup handler registered\n // at pointerdown time, before React has necessarily flushed the state\n // update `onDragStart` queued — reading `draggingPath` state here would\n // close over that pre-drag (still `null`) render.\n // 2. If the tree was restructured elsewhere while this drag was in\n // progress (another split/remove, or a controlled `value` update),\n // `sourcePath` could now resolve to a different leaf than the one the\n // user actually grabbed. `moveLeaf` re-derives the source's current\n // path from its id fresh against `liveTreeRef.current`, so passing the\n // id directly can't silently move the wrong pane.\n function onDragEnd(sourceId: T, targetPath: MosaicPath | null, zone: DropZone | null) {\n const current = liveTreeRef.current;\n if (targetPath && zone && current !== null) {\n const targetNode = getNodeAtPath(current, targetPath);\n if (targetNode !== null && !isParent(targetNode)) {\n commitTree(moveLeaf(current, sourceId, targetNode, zone));\n }\n }\n setDraggingPath(null);\n setDropTarget(null);\n }\n\n function onDragCancel() {\n setDraggingPath(null);\n setDropTarget(null);\n }\n\n const contextValue: MosaicContextValue = {\n renderTile: renderTile as (id: MosaicKey, path: MosaicPath) => React.ReactNode,\n renderTitle: renderTitle as ((id: MosaicKey, path: MosaicPath) => React.ReactNode) | undefined,\n onSplitLeaf,\n onRemoveLeaf,\n onDragStart,\n onDragMove,\n onDragEnd: (sourceId, targetPath, zone) => onDragEnd(sourceId as T, targetPath, zone),\n onDragCancel,\n draggingPath,\n dropTarget,\n dragToRearrange,\n dropZoneFraction,\n renamable,\n getPaneName: (id) => livePaneNames[id as T],\n onRenamePane: (id, name) => onRenamePane(id as T, name),\n };\n\n // ---- Recursive rendering ----\n function renderNode(node: MosaicNode<T>, path: MosaicPath): React.ReactNode {\n if (!isParent(node)) {\n return (\n <MosaicWindow\n key={String(node)}\n id={node}\n path={path}\n controls={renderControls?.(node, path)}\n />\n );\n }\n\n const groupId = path.length === 0 ? \"mosaic-root\" : path.join(\".\");\n const firstPanelId = `${groupId}.first`;\n const secondPanelId = `${groupId}.second`;\n const firstLabel = String(getLeaves(node.first)[0] ?? \"pane\");\n const secondLabel = String(getLeaves(node.second)[0] ?? \"pane\");\n\n return (\n <ResizablePanelGroup\n key={groupId}\n id={groupId}\n orientation={node.direction === \"row\" ? \"horizontal\" : \"vertical\"}\n onLayoutChanged={(layout) => onGroupLayoutChanged(path, layout, firstPanelId)}\n >\n <ResizablePanel\n id={firstPanelId}\n defaultSize={node.splitPercentage ?? 50}\n minSize={minPaneSizePercentage}\n >\n {renderNode(node.first, [...path, \"first\"])}\n </ResizablePanel>\n <ResizableHandle aria-label={`Resize between pane ${firstLabel} and pane ${secondLabel}`} />\n <ResizablePanel\n id={secondPanelId}\n defaultSize={100 - (node.splitPercentage ?? 50)}\n minSize={minPaneSizePercentage}\n >\n {renderNode(node.second, [...path, \"second\"])}\n </ResizablePanel>\n </ResizablePanelGroup>\n );\n }\n\n return (\n <MosaicContext.Provider value={contextValue}>\n <div\n data-slot=\"mosaic\"\n className={cn(\"relative h-full w-full overflow-hidden\", className)}\n style={style}\n {...props}\n >\n {liveTree === null ? (emptyPlaceholder ?? null) : renderNode(liveTree, [])}\n </div>\n </MosaicContext.Provider>\n );\n}\n\nconst dropZoneOverlayClass: Record<DropZone, string> = {\n top: \"inset-x-0 top-0 h-1/2\",\n bottom: \"inset-x-0 bottom-0 h-1/2\",\n left: \"inset-y-0 left-0 w-1/2\",\n right: \"inset-y-0 right-0 w-1/2\",\n center: \"inset-0\",\n};\n\ntype MosaicWindowProps<T extends MosaicKey = string> = {\n /** This pane's leaf id. */\n id: T;\n /** This pane's path from the tree root — supplied automatically when rendered by `Mosaic`. */\n path: MosaicPath;\n className?: string;\n /** Extra toolbar actions rendered after the built-in split/remove buttons. */\n controls?: React.ReactNode;\n};\n\n/**\n * A single pane's chrome: drag handle, title, split/remove buttons, and its\n * `renderTile` content. Rendered internally by `Mosaic` for every leaf,\n * and also exported for a consumer already inside a `<Mosaic>` tree who\n * wants to add a fixed, non-tile element reusing the same toolbar chrome —\n * it calls `useMosaic()` internally, so it can't be used to build an\n * independent custom recursive renderer outside a `Mosaic`.\n *\n * The `path` you supply for such a fixed element must not collide with any\n * real leaf's path in the current tree — its split/remove/rename actions\n * operate on whatever the tree resolves at that path, so a colliding path\n * would silently act on that real pane instead of a no-op.\n */\nfunction MosaicWindow<T extends MosaicKey = string>({\n id,\n path,\n className,\n controls,\n}: MosaicWindowProps<T>) {\n const {\n renderTile,\n renderTitle,\n onSplitLeaf,\n onRemoveLeaf,\n onDragStart,\n onDragMove,\n onDragEnd,\n onDragCancel,\n draggingPath,\n dropTarget,\n dragToRearrange,\n dropZoneFraction,\n renamable,\n getPaneName,\n onRenamePane,\n } = useMosaic();\n\n const pathKey = path.join(\".\");\n const isDragging = draggingPath !== null && draggingPath.join(\".\") === pathKey;\n const isDropTarget = dropTarget !== null && dropTarget.path.join(\".\") === pathKey;\n // A plain-text identifier for this pane's toolbar aria-labels — every pane\n // otherwise shares identical button names (\"Remove pane\", etc.), which is\n // indistinguishable when tabbing through a multi-pane layout with a screen\n // reader. Falls back to the raw id rather than `renderTitle`'s output,\n // since that can be arbitrary JSX with no plain-text form.\n const accessibleName = getPaneName(id) ?? String(id);\n\n // ---- Rename editing ----\n const [isEditingName, setIsEditingName] = React.useState(false);\n const [draftName, setDraftName] = React.useState(\"\");\n // Guards against a rename being applied twice: pressing Escape unmounts the\n // input, which itself fires a native blur — without this, that blur's\n // commit would silently undo the cancel and re-apply the (unchanged) draft.\n const editResolvedRef = React.useRef(false);\n\n function startEditingName() {\n editResolvedRef.current = false;\n setDraftName(getPaneName(id) ?? String(id));\n setIsEditingName(true);\n }\n\n function commitEditingName(name: string) {\n if (editResolvedRef.current) return;\n editResolvedRef.current = true;\n setIsEditingName(false);\n onRenamePane(id, name);\n }\n\n function cancelEditingName() {\n editResolvedRef.current = true;\n setIsEditingName(false);\n }\n\n function resolveHover(clientX: number, clientY: number) {\n const hoveredEl = document\n .elementFromPoint(clientX, clientY)\n ?.closest<HTMLElement>('[data-slot=\"mosaic-window\"]');\n const hoveredPathKey = hoveredEl?.dataset.mosaicPath;\n if (!hoveredEl || hoveredPathKey === undefined || hoveredPathKey === pathKey) return null;\n const targetPath = (hoveredPathKey === \"\" ? [] : hoveredPathKey.split(\".\")) as MosaicPath;\n const rect = hoveredEl.getBoundingClientRect();\n const zone = classifyDropZone(rect, clientX, clientY, dropZoneFraction);\n return { targetPath, zone };\n }\n\n function handleGripPointerDown(event: React.PointerEvent<HTMLButtonElement>) {\n if (event.button !== 0 && event.pointerType === \"mouse\") return;\n event.preventDefault();\n onDragStart(path);\n // A body-level cursor override, since without pointer capture the cursor\n // would otherwise flicker to whatever's under the pointer during the drag.\n document.body.style.cursor = \"grabbing\";\n\n function removeListeners() {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onCancel);\n }\n const onMove = (moveEvent: PointerEvent) => {\n const hover = resolveHover(moveEvent.clientX, moveEvent.clientY);\n onDragMove(hover?.targetPath ?? null, hover?.zone ?? null);\n };\n const onUp = (upEvent: PointerEvent) => {\n removeListeners();\n document.body.style.cursor = \"\";\n const hover = resolveHover(upEvent.clientX, upEvent.clientY);\n onDragEnd(id, hover?.targetPath ?? null, hover?.zone ?? null);\n };\n // A trackpad/touch gesture the browser reinterprets as scroll/pan fires\n // `pointercancel` instead of `pointerup` — clean up, no drop.\n const onCancel = () => {\n removeListeners();\n document.body.style.cursor = \"\";\n onDragCancel();\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onCancel);\n }\n\n return (\n <div\n data-slot=\"mosaic-window\"\n data-mosaic-path={pathKey}\n className={cn(\n \"relative flex h-full w-full flex-col overflow-hidden\",\n isDragging && \"opacity-50\",\n className,\n )}\n >\n <div\n data-slot=\"mosaic-window-toolbar\"\n className=\"flex shrink-0 items-center gap-1 border-primary-border border-b bg-primary-bg px-1.5 py-1\"\n >\n {dragToRearrange && (\n <button\n type=\"button\"\n data-slot=\"mosaic-window-grip\"\n aria-label={`Drag to move pane \"${accessibleName}\". Use the split and close buttons for keyboard-accessible rearranging.`}\n draggable={false}\n className=\"flex size-6 shrink-0 cursor-grab touch-none items-center justify-center rounded-6 text-muted-txt focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-focus active:cursor-grabbing\"\n onPointerDown={handleGripPointerDown}\n >\n <GripVerticalIcon className=\"size-3.5\" />\n </button>\n )}\n {isEditingName ? (\n <input\n type=\"text\"\n data-slot=\"mosaic-window-name-input\"\n aria-label={`Pane name for \"${accessibleName}\"`}\n value={draftName}\n autoFocus\n className=\"h-6 min-w-0 flex-1 rounded-4 border border-primary-border bg-primary-bg px-1 text-primary-txt text-sm outline-hidden focus-visible:ring-1 focus-visible:ring-focus\"\n onChange={(event) => setDraftName(event.target.value)}\n onFocus={(event) => event.currentTarget.select()}\n onBlur={(event) => commitEditingName(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n commitEditingName(event.currentTarget.value);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n cancelEditingName();\n }\n }}\n />\n ) : (\n <span\n className=\"min-w-0 flex-1 truncate text-primary-txt text-sm\"\n onDoubleClick={renamable ? startEditingName : undefined}\n >\n {getPaneName(id) ?? (renderTitle ? renderTitle(id, path) : String(id))}\n </span>\n )}\n {renamable && !isEditingName && (\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Rename pane \"${accessibleName}\"`}\n onClick={startEditingName}\n >\n <PencilIcon />\n </Button>\n )}\n {controls}\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Split pane \"${accessibleName}\", side by side`}\n onClick={() => onSplitLeaf(path, \"row\")}\n >\n <PanelLeftIcon />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Split pane \"${accessibleName}\", stacked`}\n onClick={() => onSplitLeaf(path, \"column\")}\n >\n <PanelTopIcon />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Remove pane \"${accessibleName}\"`}\n onClick={() => onRemoveLeaf(path)}\n >\n <XIcon />\n </Button>\n </div>\n <div data-slot=\"mosaic-window-content\" className=\"min-h-0 flex-1 overflow-auto\">\n {renderTile(id, path)}\n </div>\n {isDropTarget && dropTarget && (\n <div\n data-slot=\"mosaic-drop-overlay\"\n className={cn(\n \"pointer-events-none absolute z-20 bg-focus/20 ring-2 ring-focus ring-inset\",\n dropZoneOverlayClass[dropTarget.zone],\n )}\n />\n )}\n </div>\n );\n}\n\n// `useMosaic` is intentionally not exported: its context value is typed\n// against the widened `MosaicKey` union (React context can't itself be\n// generic), so a consumer calling it directly on a `Mosaic<T>` instance could\n// pass a mismatched id with no compile-time error. `MosaicWindow` is the\n// supported extension point and narrows back to `T` at its own boundary.\nexport { Mosaic, MosaicWindow, type MosaicProps, type MosaicWindowProps };\nexport type {\n DropZone,\n MosaicDirection,\n MosaicKey,\n MosaicNode,\n MosaicParent,\n MosaicPath,\n} from \"./Mosaic.utils\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"Mosaic.js","names":[],"sources":["../src/primitives/Mosaic/Mosaic.utils.ts","../src/primitives/Mosaic/Mosaic.tsx"],"sourcesContent":["// Pure tree/geometry helpers for Mosaic, kept separate from the component so\n// the tree algorithm and drop-zone math are unit-testable without a real\n// browser — matching MultiColumn.utils.ts's split between pure logic and DOM\n// wiring.\n\n/** A pane's identity. Compared with `===`, so no object identities. */\ntype MosaicKey = string | number;\n\n/** \"row\" places children side by side (horizontal split); \"column\" stacks them (vertical split). */\ntype MosaicDirection = \"row\" | \"column\";\n\n/** Sequence of \"first\"/\"second\" steps from the tree root down to a node. */\ntype MosaicPath = (\"first\" | \"second\")[];\n\ntype MosaicParent<T extends MosaicKey = MosaicKey> = {\n direction: MosaicDirection;\n /** A node, or `null` for an intentionally blank slot: the space is kept (per `splitPercentage`) but no pane chrome renders there, and drags/splits can't target it. */\n first: MosaicNode<T> | null;\n /** Same as `first` — `null` renders that side as blank space. */\n second: MosaicNode<T> | null;\n /** Percentage (0-100) of the group's size given to `first`. Defaults to 50 when omitted. */\n splitPercentage?: number;\n};\n\n/** A leaf pane id, or a parent split of two further nodes. */\ntype MosaicNode<T extends MosaicKey = MosaicKey> = T | MosaicParent<T>;\n\n/** Which edge (or center) of a pane a drag is hovering over. */\ntype DropZone = \"top\" | \"bottom\" | \"left\" | \"right\" | \"center\";\n\n/**\n * A leaf supplied to `value`/`defaultValue` as an object: `id` is the pane's\n * identity, every other key is ignored by Mosaic. `direction` is reserved —\n * it's what distinguishes a parent split from an object leaf — so an object\n * leaf must not have one.\n */\ntype MosaicLeafObject<T extends MosaicKey = MosaicKey> = {\n id: T;\n direction?: never;\n [extra: string]: unknown;\n};\n\ntype MosaicInputParent<T extends MosaicKey = MosaicKey> = {\n direction: MosaicDirection;\n /** A node, or a blank slot: `null`, `undefined`, or simply omitted. Blank slots normalize to `null` in the canonical tree. */\n first?: MosaicInputNode<T> | null;\n /** Same as `first` — omit (or pass `null`/`undefined`) for a blank slot. */\n second?: MosaicInputNode<T> | null;\n /** Percentage (0-100) of the group's size given to `first`. Defaults to 50 when omitted. */\n splitPercentage?: number;\n};\n\n/**\n * The tree shape `value`/`defaultValue` accept: like `MosaicNode`, but a leaf\n * may also be written as `{ id }` (`MosaicLeafObject`). Normalized to the\n * canonical bare-id `MosaicNode` on the way in — `onChange` always emits the\n * canonical shape.\n *\n * `MosaicParent<T>` is listed even though it's structurally a subtype of\n * `MosaicInputParent<T>`: passing a value annotated as `MosaicNode<T>` /\n * `MosaicParent<T>` then infers `T` through the matching alias, instead of\n * falling back to `createNode`'s return type (which may be a narrower\n * literal).\n */\ntype MosaicInputNode<T extends MosaicKey = MosaicKey> =\n | T\n | MosaicLeafObject<T>\n | MosaicInputParent<T>\n | MosaicParent<T>;\n\n/**\n * Collapses `{ id }` object leaves to their bare id, recursively, yielding\n * the canonical `MosaicNode` every tree algorithm operates on. Extra keys on\n * an object leaf are dropped — Mosaic reads only `id`.\n */\nfunction normalizeMosaicNode<T extends MosaicKey>(node: MosaicInputNode<T>): MosaicNode<T> {\n if (typeof node !== \"object\" || node === null) return node;\n if (\"direction\" in node && node.direction !== undefined) {\n const parent = node as MosaicInputParent<T>;\n const normalized: MosaicParent<T> = {\n direction: parent.direction,\n // `== null` folds both null and undefined (an omitted side) to the\n // canonical blank-slot value, null.\n first: parent.first == null ? null : normalizeMosaicNode(parent.first),\n second: parent.second == null ? null : normalizeMosaicNode(parent.second),\n };\n if (parent.splitPercentage !== undefined) normalized.splitPercentage = parent.splitPercentage;\n return normalized;\n }\n const leaf = (node as MosaicLeafObject<T>).id;\n if (process.env.NODE_ENV !== \"production\" && leaf === undefined) {\n console.warn(\n \"Mosaic: an object in the tree has neither a `direction` (parent) nor an `id` (leaf) key.\",\n );\n }\n return leaf;\n}\n\n/** Every recursive walk depends on this being correct — `T` is constrained to non-object keys precisely so this check can't be fooled by a leaf that happens to be an object. */\nfunction isParent<T extends MosaicKey>(node: MosaicNode<T> | null): node is MosaicParent<T> {\n return typeof node === \"object\" && node !== null && \"direction\" in node;\n}\n\n/** All leaf ids under `root`, in first-then-second (left-to-right / top-to-bottom) order. */\nfunction getLeaves<T extends MosaicKey>(root: MosaicNode<T> | null): T[] {\n if (root === null) return [];\n if (!isParent(root)) return [root];\n return [...getLeaves(root.first), ...getLeaves(root.second)];\n}\n\n/** Walks `path` from `root`; `null` if the path runs off a leaf or is otherwise invalid. `path: []` returns `root` itself. */\nfunction getNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n path: MosaicPath,\n): MosaicNode<T> | null {\n let node = root;\n for (const step of path) {\n if (node === null || !isParent(node)) return null;\n node = node[step];\n }\n return node;\n}\n\n/** First DFS path whose leaf `===` matches `leaf`; `null` if not found. Assumes leaf ids are unique across the tree — `Mosaic` warns in dev mode when they aren't. */\nfunction getPathToLeaf<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n leaf: T,\n): MosaicPath | null {\n if (root === null) return null;\n function search(node: MosaicNode<T> | null, path: MosaicPath): MosaicPath | null {\n if (node === null) return null;\n if (!isParent(node)) {\n return node === leaf ? path : null;\n }\n return search(node.first, [...path, \"first\"]) ?? search(node.second, [...path, \"second\"]);\n }\n return search(root, []);\n}\n\n/** Immutable path-copy replace: only nodes along `path` are cloned, siblings off the path are referentially reused. `path: []` replaces the whole tree. */\nfunction replaceNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n next: MosaicNode<T>,\n): MosaicNode<T>;\nfunction replaceNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n path: MosaicPath,\n next: MosaicNode<T> | null,\n): MosaicNode<T> | null;\nfunction replaceNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n path: MosaicPath,\n next: MosaicNode<T> | null,\n): MosaicNode<T> | null {\n if (path.length === 0) return next;\n if (!isParent(root)) return root;\n const [step, ...rest] = path;\n if (step === \"first\") {\n return { ...root, first: replaceNodeAtPath(root.first, rest, next) };\n }\n return { ...root, second: replaceNodeAtPath(root.second, rest, next) };\n}\n\n/** Patches `splitPercentage` on the parent at `path`, used by the resize-commit callback. No-ops (dev-mode warns) if `path` doesn't resolve to a parent. */\nfunction updateSplitPercentageAtPath<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n splitPercentage: number,\n): MosaicNode<T> {\n const node = getNodeAtPath(root, path);\n if (node === null || !isParent(node)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"Mosaic: updateSplitPercentageAtPath was called with a path that doesn't resolve to a parent node.\",\n );\n }\n return root;\n }\n return replaceNodeAtPath(root, path, { ...node, splitPercentage });\n}\n\n/**\n * Removes the leaf at `path`, collapsing its parent so the sibling takes the\n * parent's position. Returns `null` only when `path` is `[]` (the sole\n * remaining leaf — the root itself — is removed).\n */\nfunction removeLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n): MosaicNode<T> | null {\n if (path.length === 0) return null;\n const parentPath = path.slice(0, -1);\n const lastStep = path[path.length - 1];\n const parent = getNodeAtPath(root, parentPath);\n if (parent === null || !isParent(parent)) return root;\n const sibling = lastStep === \"first\" ? parent.second : parent.first;\n if (parentPath.length === 0) return sibling;\n return replaceNodeAtPath(root, parentPath, sibling);\n}\n\n/**\n * Replaces the node at `path` with a new `MosaicParent` split 50/50 between\n * `newLeaf` and the existing node there. `\"before\"` (top/left drops) makes\n * `newLeaf` the `first` child; `\"after\"` (bottom/right drops) makes it `second`.\n */\nfunction splitLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n newLeaf: T,\n direction: MosaicDirection,\n position: \"before\" | \"after\",\n): MosaicNode<T> {\n const existing = getNodeAtPath(root, path);\n if (existing === null) return root;\n const parent: MosaicParent<T> =\n position === \"before\"\n ? { direction, first: newLeaf, second: existing, splitPercentage: 50 }\n : { direction, first: existing, second: newLeaf, splitPercentage: 50 };\n return replaceNodeAtPath(root, path, parent);\n}\n\n/** Swaps the two leaves at `pathA`/`pathB` in place, no restructuring. No-op if the paths are equal or either is invalid. Used for center-zone drops. */\nfunction swapLeaves<T extends MosaicKey>(\n root: MosaicNode<T>,\n pathA: MosaicPath,\n pathB: MosaicPath,\n): MosaicNode<T> {\n if (pathA.length === pathB.length && pathA.every((step, i) => step === pathB[i])) return root;\n const nodeA = getNodeAtPath(root, pathA);\n const nodeB = getNodeAtPath(root, pathB);\n if (nodeA === null || nodeB === null) return root;\n const afterA = replaceNodeAtPath(root, pathA, nodeB);\n return replaceNodeAtPath(afterA, pathB, nodeA);\n}\n\n/**\n * The drag-drop commit entry point. No-op on a self-drop. `zone: \"center\"`\n * swaps the two leaves; otherwise removes the source leaf and re-resolves the\n * target's path against the POST-REMOVAL tree (removal can shift paths on the\n * way to the target, e.g. when an ancestor collapses away) before splitting\n * at that re-resolved path — never adjusting the original path by arithmetic.\n */\nfunction moveLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n sourceLeaf: T,\n targetLeaf: T,\n zone: DropZone,\n): MosaicNode<T> | null {\n if (sourceLeaf === targetLeaf) return root;\n const sourcePath = getPathToLeaf(root, sourceLeaf);\n const targetPath = getPathToLeaf(root, targetLeaf);\n if (sourcePath === null || targetPath === null) return root;\n\n if (zone === \"center\") {\n return swapLeaves(root, sourcePath, targetPath);\n }\n\n const afterRemoval = removeLeaf(root, sourcePath);\n if (afterRemoval === null) {\n // Unreachable: root having only sourceLeaf means targetLeaf couldn't have\n // been found above (sourceLeaf === targetLeaf is already handled). Kept\n // as a defensive no-op rather than assuming it can never fire.\n return root;\n }\n const resolvedTargetPath = getPathToLeaf(afterRemoval, targetLeaf);\n if (resolvedTargetPath === null) return afterRemoval;\n\n const direction: MosaicDirection = zone === \"top\" || zone === \"bottom\" ? \"column\" : \"row\";\n const position: \"before\" | \"after\" = zone === \"top\" || zone === \"left\" ? \"before\" : \"after\";\n return splitLeaf(afterRemoval, resolvedTargetPath, sourceLeaf, direction, position);\n}\n\n/** A pane's rect in the same coordinate space as pointer `clientX`/`clientY` (i.e. `getBoundingClientRect()`). */\ntype PaneRect = { left: number; top: number; width: number; height: number };\n\n/**\n * Classifies a pointer position within a pane into one of 5 drop zones.\n * Within `dropZoneFraction` of an edge (0-1, fraction of that axis's size)\n * counts as that edge; otherwise center. At corners, where both axes are\n * within range, the axis whose edge distance is smaller wins, so corners\n * resolve deterministically instead of arbitrarily favoring x or y.\n */\nfunction classifyDropZone(\n rect: PaneRect,\n clientX: number,\n clientY: number,\n dropZoneFraction: number,\n): DropZone {\n const xFraction = rect.width === 0 ? 0.5 : (clientX - rect.left) / rect.width;\n const yFraction = rect.height === 0 ? 0.5 : (clientY - rect.top) / rect.height;\n const xEdgeDistance = Math.min(xFraction, 1 - xFraction);\n const yEdgeDistance = Math.min(yFraction, 1 - yFraction);\n\n if (xEdgeDistance >= dropZoneFraction && yEdgeDistance >= dropZoneFraction) return \"center\";\n if (xEdgeDistance < yEdgeDistance) {\n return xFraction < 0.5 ? \"left\" : \"right\";\n }\n return yFraction < 0.5 ? \"top\" : \"bottom\";\n}\n\nexport {\n isParent,\n getLeaves,\n getNodeAtPath,\n getPathToLeaf,\n replaceNodeAtPath,\n updateSplitPercentageAtPath,\n removeLeaf,\n splitLeaf,\n swapLeaves,\n moveLeaf,\n classifyDropZone,\n normalizeMosaicNode,\n type MosaicKey,\n type MosaicDirection,\n type MosaicPath,\n type MosaicParent,\n type MosaicNode,\n type MosaicLeafObject,\n type MosaicInputParent,\n type MosaicInputNode,\n type DropZone,\n type PaneRect,\n};\n","\"use client\";\n\nimport { GripVerticalIcon, PanelLeftIcon, PanelTopIcon, PencilIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport type { GroupImperativeHandle } from \"react-resizable-panels\";\n\nimport { Button } from \"@/primitives/Button\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"@/primitives/Resizable\";\nimport { cn } from \"@/utils\";\nimport {\n type DropZone,\n type MosaicDirection,\n type MosaicInputNode,\n type MosaicKey,\n type MosaicNode,\n type MosaicPath,\n classifyDropZone,\n getLeaves,\n getNodeAtPath,\n isParent,\n moveLeaf,\n normalizeMosaicNode,\n removeLeaf,\n splitLeaf,\n updateSplitPercentageAtPath,\n} from \"./Mosaic.utils\";\n\nconst DEFAULT_DROP_ZONE_FRACTION = 0.25;\nconst DEFAULT_MIN_PANE_SIZE_PERCENTAGE = 10;\n\n/**\n * Toolbar display mode for every pane in a Mosaic:\n * - `\"always\"` — toolbars are always visible (default).\n * - `\"autohide\"` — toolbars overlay the pane content and fade in on pane\n * hover or keyboard focus within the toolbar.\n * - `\"hidden\"` — toolbars are not rendered at all. The toolbar-driven\n * affordances (drag handle, split/remove/rename) are unavailable, so\n * layout changes must come from outside via the controlled `value`;\n * divider resizing still works.\n */\ntype MosaicToolbarVisibility = \"always\" | \"autohide\" | \"hidden\";\n\n// The context is intentionally widened to MosaicKey rather than parameterized\n// by the consumer's T — React context can't itself be generic. This is safe\n// at runtime because every id flowing through a given <Mosaic> instance's\n// context originates from that same instance's T-typed tree; MosaicWindow\n// narrows back to T at its own boundary.\ntype MosaicContextValue = {\n renderTile: (id: MosaicKey, path: MosaicPath) => React.ReactNode;\n renderTitle: ((id: MosaicKey, path: MosaicPath) => React.ReactNode) | undefined;\n onSplitLeaf: (path: MosaicPath, direction: MosaicDirection) => void;\n onRemoveLeaf: (path: MosaicPath) => void;\n onDragStart: (path: MosaicPath) => void;\n onDragMove: (targetPath: MosaicPath | null, zone: DropZone | null) => void;\n onDragEnd: (sourceId: MosaicKey, targetPath: MosaicPath | null, zone: DropZone | null) => void;\n onDragCancel: () => void;\n draggingPath: MosaicPath | null;\n dropTarget: { path: MosaicPath; zone: DropZone } | null;\n dragToRearrange: boolean;\n dropZoneFraction: number;\n renamable: boolean;\n getPaneName: (id: MosaicKey) => string | undefined;\n onRenamePane: (id: MosaicKey, name: string) => void;\n toolbarVisibility: MosaicToolbarVisibility;\n};\n\nconst MosaicContext = React.createContext<MosaicContextValue | null>(null);\n\n/** Hook giving `MosaicWindow` access to shared drag/split/remove actions; must be used inside a `Mosaic`. */\nfunction useMosaic(): MosaicContextValue {\n const context = React.useContext(MosaicContext);\n if (!context) {\n throw new Error(\"useMosaic must be used within a Mosaic.\");\n }\n return context;\n}\n\ntype MosaicProps<T extends MosaicKey = string> = Omit<\n React.ComponentProps<\"div\">,\n \"onChange\" | \"value\" | \"defaultValue\"\n> & {\n /**\n * The tree of panes to render. `null` (or an empty tree via\n * `emptyPlaceholder`) renders nothing tile-related. Leaves may be written\n * as bare ids or as `{ id }` objects (any extra keys are ignored); object\n * leaves are normalized to their bare id on the way in, and `onChange`\n * always emits the normalized bare-id tree.\n */\n value?: MosaicInputNode<T> | null;\n /** Initial tree when uncontrolled. Accepts the same leaf shapes as `value`. */\n defaultValue?: MosaicInputNode<T> | null;\n /**\n * Fires with the updated tree after a resize, toolbar split/remove, or\n * drag-drop rearrange. Pass `value` back to fully control; omit for\n * internal (uncontrolled) tracking — mirrors MultiColumn's\n * `columns`/`onColumnsChange`.\n *\n * Note: there is no strict controlled veto. If a controlled consumer's\n * `onChange` doesn't feed back an updated `value` (e.g. to reject a\n * drag/split), the optimistic change still applies locally and persists —\n * the same behavior MultiColumn already ships for resize/reorder. A true\n * veto would need a different API shape (e.g. an `onBeforeChange` returning\n * `boolean`), which is out of scope here.\n */\n onChange?: (next: MosaicNode<T> | null) => void;\n /** Renders the content for a leaf pane; required — Mosaic has no default tile content. */\n renderTile: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders the title shown in a pane's toolbar. Defaults to `String(id)`. */\n renderTitle?: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders extra toolbar actions for a pane, after the built-in split/remove buttons. */\n renderControls?: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders a rename (pencil) button in each pane's toolbar; double-clicking the title also starts editing. Renaming sets a plain-text name that overrides `renderTitle`/`String(id)` for that pane. Default off. */\n renamable?: boolean;\n /** Custom pane names, keyed by leaf id (controlled). Only panes that have been renamed need an entry. */\n paneNames?: Partial<Record<T, string>>;\n /** Initial pane names when uncontrolled. */\n defaultPaneNames?: Partial<Record<T, string>>;\n /** Fires with the updated name map after a rename commits (Enter, blur, or the confirm affordance). Clearing a pane's name back to empty removes its entry, falling back to `renderTitle`/`String(id)` again. Pass `paneNames` back to fully control; omit for internal (uncontrolled) tracking. */\n onPaneNamesChange?: (names: Partial<Record<T, string>>) => void;\n /**\n * Creates the id for a new pane when a toolbar split button is used\n * (drag-triggered splits reuse the dragged pane's existing id instead).\n * May return a Promise. `renderTile` must be able to render whatever this\n * returns.\n */\n createNode: (path: MosaicPath) => T | Promise<T>;\n /** Renders a drag handle in each pane's toolbar for drag-to-split/rearrange. Toolbar split/remove buttons remain active either way. Default enabled. */\n dragToRearrange?: boolean;\n /** Fraction (0-1) of a pane's width/height, measured from each edge, that counts as an edge drop zone rather than the center. Defaults to `0.25`. */\n dropZoneFraction?: number;\n /** Minimum size (percentage, 0-100) a pane can be resized down to. Defaults to `10`. */\n minPaneSizePercentage?: number;\n /**\n * How pane toolbars are shown. `\"always\"` (default) keeps them visible;\n * `\"autohide\"` overlays them on the pane content, fading in on pane hover\n * or keyboard focus; `\"hidden\"` removes them entirely — the toolbar-driven\n * affordances (drag handle, split/remove/rename) become unavailable, so\n * drive layout changes through the controlled `value` instead. Divider\n * resizing works in every mode.\n */\n toolbarVisibility?: MosaicToolbarVisibility;\n /** Rendered instead of the tree when `value`/the live tree is `null` (e.g. every pane has been removed). */\n emptyPlaceholder?: React.ReactNode;\n};\n\n/** Recursive tiling layout: panes split into rows/columns, resized via draggable dividers, and rearranged by dragging a pane's title bar onto another pane's edge or center. */\nfunction Mosaic<T extends MosaicKey = string>({\n className,\n style,\n value,\n defaultValue,\n onChange,\n renderTile,\n renderTitle,\n renderControls,\n renamable = false,\n paneNames,\n defaultPaneNames,\n onPaneNamesChange,\n createNode,\n dragToRearrange = true,\n dropZoneFraction = DEFAULT_DROP_ZONE_FRACTION,\n minPaneSizePercentage = DEFAULT_MIN_PANE_SIZE_PERCENTAGE,\n toolbarVisibility = \"always\",\n emptyPlaceholder,\n ...props\n}: MosaicProps<T>) {\n // ---- Controlled/uncontrolled sync — generalizes MultiColumn's\n // columnsKey/syncedColumnsKey render-time-sync idiom to a tree. Unlike\n // MultiColumn, `value` is genuinely optional (the tree is stateful\n // regardless of controlled mode), so the resync only fires when `value` is\n // actually passed and has changed.\n // `{ id }` object leaves collapse to bare ids here, at the input boundary —\n // every internal algorithm (and the tree `onChange` emits) is bare-id only.\n const normalizedValue = React.useMemo(\n () => (value == null ? value : normalizeMosaicNode(value)),\n [value],\n );\n const valueKey = React.useMemo(() => JSON.stringify(normalizedValue ?? null), [normalizedValue]);\n const [liveTree, setLiveTree] = React.useState<MosaicNode<T> | null>(() =>\n normalizedValue !== undefined\n ? normalizedValue\n : defaultValue == null\n ? null\n : normalizeMosaicNode(defaultValue),\n );\n const [syncedValueKey, setSyncedValueKey] = React.useState(valueKey);\n if (normalizedValue !== undefined && valueKey !== syncedValueKey) {\n setSyncedValueKey(valueKey);\n setLiveTree(normalizedValue);\n }\n\n // Mirrors `liveTree` for reads inside callbacks that resume after a gap\n // (an awaited `createNode`, or a pointerdown-to-pointerup drag session) —\n // those callbacks close over whatever `liveTree` was at the time they were\n // created, which can be stale if something else committed a change during\n // the gap. Reading `liveTreeRef.current` instead always reflects the tree\n // at the moment the callback actually runs, not the moment it was defined.\n const liveTreeRef = React.useRef(liveTree);\n liveTreeRef.current = liveTree;\n\n function commitTree(next: MosaicNode<T> | null) {\n setLiveTree(next);\n onChange?.(next);\n }\n\n // ---- Pane rename state — same render-time-sync idiom as the tree above,\n // but a separate controlled pair (not folded into `value`) since a pane's\n // display name and its position in the tree are independent concerns.\n const paneNamesKey = React.useMemo(() => JSON.stringify(paneNames ?? {}), [paneNames]);\n const [livePaneNames, setLivePaneNames] = React.useState<Partial<Record<T, string>>>(\n paneNames !== undefined ? paneNames : (defaultPaneNames ?? {}),\n );\n const [syncedPaneNamesKey, setSyncedPaneNamesKey] = React.useState(paneNamesKey);\n if (paneNames !== undefined && paneNamesKey !== syncedPaneNamesKey) {\n setSyncedPaneNamesKey(paneNamesKey);\n setLivePaneNames(paneNames);\n }\n\n function onRenamePane(id: T, name: string) {\n const trimmed = name.trim();\n const next = { ...livePaneNames };\n if (trimmed.length === 0) {\n delete next[id];\n } else {\n next[id] = trimmed;\n }\n setLivePaneNames(next);\n onPaneNamesChange?.(next);\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n const leaves = getLeaves(liveTree);\n if (new Set(leaves).size !== leaves.length) {\n console.warn(\n \"Mosaic: duplicate leaf ids detected in the tree. Every pane needs a unique id, or drag/split/remove operations may target the wrong pane.\",\n );\n }\n }\n\n // ---- Split/remove ----\n function onSplitLeaf(path: MosaicPath, direction: MosaicDirection) {\n if (liveTreeRef.current === null) return;\n // `createNode` may be async — read `liveTreeRef.current` again once it\n // resolves rather than the `liveTree` closed over above, in case a\n // resize/remove/drag committed a change while the promise was in flight.\n Promise.resolve(createNode(path)).then((newLeaf) => {\n const current = liveTreeRef.current;\n if (current === null) return;\n commitTree(splitLeaf(current, path, newLeaf, direction, \"after\"));\n });\n }\n\n function onRemoveLeaf(path: MosaicPath) {\n const current = liveTreeRef.current;\n if (current === null) return;\n commitTree(removeLeaf(current, path));\n }\n\n // ---- Resize commit — wired to each Group's onLayoutChanged (fires once,\n // after the pointer is released), not Panel.onResize (fires every pointer\n // move tick) — see Mosaic.tsx rendering below.\n function onGroupLayoutChanged(\n path: MosaicPath,\n layout: Record<string, number>,\n firstPanelId: string,\n ) {\n const current = liveTreeRef.current;\n if (current === null) return;\n const percentage = layout[firstPanelId];\n if (percentage === undefined) return;\n // Echo guard: skip the commit when the reported layout already matches\n // the tree — a layout change we pushed ourselves (the sync effect below)\n // must not bounce back as a tree commit.\n const node = getNodeAtPath(current, path);\n if (isParent(node) && Math.abs((node.splitPercentage ?? 50) - percentage) < 0.1) return;\n commitTree(updateSplitPercentageAtPath(current, path, percentage));\n }\n\n // react-resizable-panels resolves groups from a module-level registry BY ID\n // STRING (first match wins), so group ids must be unique across the whole\n // document — with several Mosaics on one page, bare path-derived ids\n // (\"mosaic-root\", \"first\", …) collide and every collided instance reads the\n // first one's state, leaving its own dividers dead. Prefixing with useId\n // makes each instance's ids document-unique.\n const instanceId = React.useId();\n const groupIdForPath = (path: MosaicPath) =>\n `${instanceId}mosaic-${path.length === 0 ? \"root\" : path.join(\".\")}`;\n\n // ---- Tree → layout sync. `defaultSize`/`defaultLayout` are initial-mount\n // only in react-resizable-panels: a mounted Group keeps its own internal\n // layout. Mosaic's groups are keyed by tree *path*, and paths survive\n // restructuring — so after a drag-rearrange (or a controlled `value` update\n // that changes `splitPercentage`), a surviving group would keep stale\n // percentages for entirely different content, and the next resize would\n // commit those stale numbers back into the tree. Each group registers its\n // imperative handle here, and after every tree change the tree's\n // splitPercentage is pushed into any mounted group whose layout drifted.\n const groupHandlesRef = React.useRef(new Map<string, GroupImperativeHandle>());\n\n React.useEffect(() => {\n function syncGroupLayouts(node: MosaicNode<T> | null, path: MosaicPath) {\n if (!isParent(node)) return;\n const groupId = groupIdForPath(path);\n const handle = groupHandlesRef.current.get(groupId);\n if (handle) {\n const firstPanelId = `${groupId}.first`;\n const expected = node.splitPercentage ?? 50;\n const actual = handle.getLayout()[firstPanelId];\n if (actual !== undefined && Math.abs(actual - expected) > 0.1) {\n handle.setLayout({\n [firstPanelId]: expected,\n [`${groupId}.second`]: 100 - expected,\n });\n }\n }\n syncGroupLayouts(node.first, [...path, \"first\"]);\n syncGroupLayouts(node.second, [...path, \"second\"]);\n }\n syncGroupLayouts(liveTree, []);\n }, [liveTree]);\n\n // ---- Drag-to-rearrange state — shared via context so every MosaicWindow\n // can render its own drag/drop-target feedback without prop-drilling.\n const [draggingPath, setDraggingPath] = React.useState<MosaicPath | null>(null);\n const [dropTarget, setDropTarget] = React.useState<{ path: MosaicPath; zone: DropZone } | null>(\n null,\n );\n\n function onDragStart(path: MosaicPath) {\n setDraggingPath(path);\n }\n\n function onDragMove(targetPath: MosaicPath | null, zone: DropZone | null) {\n setDropTarget(targetPath && zone ? { path: targetPath, zone } : null);\n }\n\n // `sourceId` — the dragged pane's own leaf id — is passed in directly by\n // the caller (`MosaicWindow` already knows its own `id` prop) rather than\n // re-derived here via `getNodeAtPath(tree, sourcePath)`. Two reasons:\n // 1. This fires synchronously from the same pointerup handler registered\n // at pointerdown time, before React has necessarily flushed the state\n // update `onDragStart` queued — reading `draggingPath` state here would\n // close over that pre-drag (still `null`) render.\n // 2. If the tree was restructured elsewhere while this drag was in\n // progress (another split/remove, or a controlled `value` update),\n // `sourcePath` could now resolve to a different leaf than the one the\n // user actually grabbed. `moveLeaf` re-derives the source's current\n // path from its id fresh against `liveTreeRef.current`, so passing the\n // id directly can't silently move the wrong pane.\n function onDragEnd(sourceId: T, targetPath: MosaicPath | null, zone: DropZone | null) {\n const current = liveTreeRef.current;\n if (targetPath && zone && current !== null) {\n const targetNode = getNodeAtPath(current, targetPath);\n if (targetNode !== null && !isParent(targetNode)) {\n commitTree(moveLeaf(current, sourceId, targetNode, zone));\n }\n }\n setDraggingPath(null);\n setDropTarget(null);\n }\n\n function onDragCancel() {\n setDraggingPath(null);\n setDropTarget(null);\n }\n\n const contextValue: MosaicContextValue = {\n renderTile: renderTile as (id: MosaicKey, path: MosaicPath) => React.ReactNode,\n renderTitle: renderTitle as ((id: MosaicKey, path: MosaicPath) => React.ReactNode) | undefined,\n onSplitLeaf,\n onRemoveLeaf,\n onDragStart,\n onDragMove,\n onDragEnd: (sourceId, targetPath, zone) => onDragEnd(sourceId as T, targetPath, zone),\n onDragCancel,\n draggingPath,\n dropTarget,\n dragToRearrange,\n dropZoneFraction,\n renamable,\n getPaneName: (id) => livePaneNames[id as T],\n onRenamePane: (id, name) => onRenamePane(id as T, name),\n toolbarVisibility,\n };\n\n // ---- Recursive rendering ----\n function renderNode(node: MosaicNode<T> | null, path: MosaicPath): React.ReactNode {\n // An intentionally blank slot: the panel keeps its share of the space,\n // but no pane chrome (toolbar, tile, drop target) renders there.\n if (node === null) {\n return <div data-slot=\"mosaic-empty-slot\" className=\"h-full w-full\" />;\n }\n if (!isParent(node)) {\n return (\n <MosaicWindow\n key={String(node)}\n id={node}\n path={path}\n controls={renderControls?.(node, path)}\n />\n );\n }\n\n const groupId = groupIdForPath(path);\n const firstPanelId = `${groupId}.first`;\n const secondPanelId = `${groupId}.second`;\n const describeSide = (side: MosaicNode<T> | null) => {\n const leaf = getLeaves(side)[0];\n return leaf === undefined ? \"empty space\" : `pane ${String(leaf)}`;\n };\n\n return (\n <ResizablePanelGroup\n key={groupId}\n id={groupId}\n orientation={node.direction === \"row\" ? \"horizontal\" : \"vertical\"}\n groupRef={(handle) => {\n if (handle) {\n groupHandlesRef.current.set(groupId, handle);\n } else {\n groupHandlesRef.current.delete(groupId);\n }\n }}\n onLayoutChanged={(layout) => onGroupLayoutChanged(path, layout, firstPanelId)}\n >\n <ResizablePanel\n id={firstPanelId}\n defaultSize={node.splitPercentage ?? 50}\n minSize={minPaneSizePercentage}\n >\n {renderNode(node.first, [...path, \"first\"])}\n </ResizablePanel>\n <ResizableHandle\n aria-label={`Resize between ${describeSide(node.first)} and ${describeSide(node.second)}`}\n />\n <ResizablePanel\n id={secondPanelId}\n defaultSize={100 - (node.splitPercentage ?? 50)}\n minSize={minPaneSizePercentage}\n >\n {renderNode(node.second, [...path, \"second\"])}\n </ResizablePanel>\n </ResizablePanelGroup>\n );\n }\n\n return (\n <MosaicContext.Provider value={contextValue}>\n <div\n data-slot=\"mosaic\"\n className={cn(\"relative h-full w-full overflow-hidden\", className)}\n style={style}\n {...props}\n >\n {liveTree === null ? (emptyPlaceholder ?? null) : renderNode(liveTree, [])}\n </div>\n </MosaicContext.Provider>\n );\n}\n\nconst dropZoneOverlayClass: Record<DropZone, string> = {\n top: \"inset-x-0 top-0 h-1/2\",\n bottom: \"inset-x-0 bottom-0 h-1/2\",\n left: \"inset-y-0 left-0 w-1/2\",\n right: \"inset-y-0 right-0 w-1/2\",\n center: \"inset-0\",\n};\n\ntype MosaicWindowProps<T extends MosaicKey = string> = {\n /** This pane's leaf id. */\n id: T;\n /** This pane's path from the tree root — supplied automatically when rendered by `Mosaic`. */\n path: MosaicPath;\n className?: string;\n /** Extra toolbar actions rendered after the built-in split/remove buttons. */\n controls?: React.ReactNode;\n};\n\n/**\n * A single pane's chrome: drag handle, title, split/remove buttons, and its\n * `renderTile` content. Rendered internally by `Mosaic` for every leaf,\n * and also exported for a consumer already inside a `<Mosaic>` tree who\n * wants to add a fixed, non-tile element reusing the same toolbar chrome —\n * it calls `useMosaic()` internally, so it can't be used to build an\n * independent custom recursive renderer outside a `Mosaic`.\n *\n * The `path` you supply for such a fixed element must not collide with any\n * real leaf's path in the current tree — its split/remove/rename actions\n * operate on whatever the tree resolves at that path, so a colliding path\n * would silently act on that real pane instead of a no-op.\n */\nfunction MosaicWindow<T extends MosaicKey = string>({\n id,\n path,\n className,\n controls,\n}: MosaicWindowProps<T>) {\n const {\n renderTile,\n renderTitle,\n onSplitLeaf,\n onRemoveLeaf,\n onDragStart,\n onDragMove,\n onDragEnd,\n onDragCancel,\n draggingPath,\n dropTarget,\n dragToRearrange,\n dropZoneFraction,\n renamable,\n getPaneName,\n onRenamePane,\n toolbarVisibility,\n } = useMosaic();\n\n const pathKey = path.join(\".\");\n const isDragging = draggingPath !== null && draggingPath.join(\".\") === pathKey;\n const isDropTarget = dropTarget !== null && dropTarget.path.join(\".\") === pathKey;\n // A plain-text identifier for this pane's toolbar aria-labels — every pane\n // otherwise shares identical button names (\"Remove pane\", etc.), which is\n // indistinguishable when tabbing through a multi-pane layout with a screen\n // reader. Falls back to the raw id rather than `renderTitle`'s output,\n // since that can be arbitrary JSX with no plain-text form.\n const accessibleName = getPaneName(id) ?? String(id);\n\n // ---- Rename editing ----\n const [isEditingName, setIsEditingName] = React.useState(false);\n const [draftName, setDraftName] = React.useState(\"\");\n // Guards against a rename being applied twice: pressing Escape unmounts the\n // input, which itself fires a native blur — without this, that blur's\n // commit would silently undo the cancel and re-apply the (unchanged) draft.\n const editResolvedRef = React.useRef(false);\n\n function startEditingName() {\n editResolvedRef.current = false;\n setDraftName(getPaneName(id) ?? String(id));\n setIsEditingName(true);\n }\n\n function commitEditingName(name: string) {\n if (editResolvedRef.current) return;\n editResolvedRef.current = true;\n setIsEditingName(false);\n onRenamePane(id, name);\n }\n\n function cancelEditingName() {\n editResolvedRef.current = true;\n setIsEditingName(false);\n }\n\n function resolveHover(clientX: number, clientY: number) {\n const hoveredEl = document\n .elementFromPoint(clientX, clientY)\n ?.closest<HTMLElement>('[data-slot=\"mosaic-window\"]');\n const hoveredPathKey = hoveredEl?.dataset.mosaicPath;\n if (!hoveredEl || hoveredPathKey === undefined || hoveredPathKey === pathKey) return null;\n const targetPath = (hoveredPathKey === \"\" ? [] : hoveredPathKey.split(\".\")) as MosaicPath;\n const rect = hoveredEl.getBoundingClientRect();\n const zone = classifyDropZone(rect, clientX, clientY, dropZoneFraction);\n return { targetPath, zone };\n }\n\n function handleGripPointerDown(event: React.PointerEvent<HTMLButtonElement>) {\n if (event.button !== 0 && event.pointerType === \"mouse\") return;\n event.preventDefault();\n onDragStart(path);\n // A body-level cursor override, since without pointer capture the cursor\n // would otherwise flicker to whatever's under the pointer during the drag.\n document.body.style.cursor = \"grabbing\";\n\n function removeListeners() {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onCancel);\n }\n const onMove = (moveEvent: PointerEvent) => {\n const hover = resolveHover(moveEvent.clientX, moveEvent.clientY);\n onDragMove(hover?.targetPath ?? null, hover?.zone ?? null);\n };\n const onUp = (upEvent: PointerEvent) => {\n removeListeners();\n document.body.style.cursor = \"\";\n const hover = resolveHover(upEvent.clientX, upEvent.clientY);\n onDragEnd(id, hover?.targetPath ?? null, hover?.zone ?? null);\n };\n // A trackpad/touch gesture the browser reinterprets as scroll/pan fires\n // `pointercancel` instead of `pointerup` — clean up, no drop.\n const onCancel = () => {\n removeListeners();\n document.body.style.cursor = \"\";\n onDragCancel();\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onCancel);\n }\n\n return (\n <div\n data-slot=\"mosaic-window\"\n data-mosaic-path={pathKey}\n className={cn(\n \"relative flex h-full w-full flex-col overflow-hidden\",\n toolbarVisibility === \"autohide\" && \"group/mosaic-window\",\n isDragging && \"opacity-50\",\n className,\n )}\n >\n {toolbarVisibility !== \"hidden\" && (\n <div\n data-slot=\"mosaic-window-toolbar\"\n className={cn(\n \"flex shrink-0 items-center gap-1 border-primary-border border-b bg-primary-bg px-1.5 py-1\",\n // Autohide: overlay the content's top edge and fade in on pane\n // hover, or on keyboard focus landing inside the toolbar (which\n // also keeps it visible while the rename input holds focus).\n toolbarVisibility === \"autohide\" &&\n \"absolute inset-x-0 top-0 z-10 opacity-0 transition-opacity duration-150 focus-within:opacity-100 group-hover/mosaic-window:opacity-100\",\n )}\n >\n {dragToRearrange && (\n <button\n type=\"button\"\n data-slot=\"mosaic-window-grip\"\n aria-label={`Drag to move pane \"${accessibleName}\". Use the split and close buttons for keyboard-accessible rearranging.`}\n draggable={false}\n className=\"flex size-6 shrink-0 cursor-grab touch-none items-center justify-center rounded-6 text-muted-txt focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-focus active:cursor-grabbing\"\n onPointerDown={handleGripPointerDown}\n >\n <GripVerticalIcon className=\"size-3.5\" />\n </button>\n )}\n {isEditingName ? (\n <input\n type=\"text\"\n data-slot=\"mosaic-window-name-input\"\n aria-label={`Pane name for \"${accessibleName}\"`}\n value={draftName}\n autoFocus\n className=\"h-6 min-w-0 flex-1 rounded-4 border border-primary-border bg-primary-bg px-1 text-primary-txt text-sm outline-hidden focus-visible:ring-1 focus-visible:ring-focus\"\n onChange={(event) => setDraftName(event.target.value)}\n onFocus={(event) => event.currentTarget.select()}\n onBlur={(event) => commitEditingName(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n commitEditingName(event.currentTarget.value);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n cancelEditingName();\n }\n }}\n />\n ) : (\n <span\n className=\"min-w-0 flex-1 truncate text-primary-txt text-sm\"\n onDoubleClick={renamable ? startEditingName : undefined}\n >\n {getPaneName(id) ?? (renderTitle ? renderTitle(id, path) : String(id))}\n </span>\n )}\n {renamable && !isEditingName && (\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Rename pane \"${accessibleName}\"`}\n onClick={startEditingName}\n >\n <PencilIcon />\n </Button>\n )}\n {controls}\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Split pane \"${accessibleName}\", side by side`}\n onClick={() => onSplitLeaf(path, \"row\")}\n >\n <PanelLeftIcon />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Split pane \"${accessibleName}\", stacked`}\n onClick={() => onSplitLeaf(path, \"column\")}\n >\n <PanelTopIcon />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Remove pane \"${accessibleName}\"`}\n onClick={() => onRemoveLeaf(path)}\n >\n <XIcon />\n </Button>\n </div>\n )}\n <div data-slot=\"mosaic-window-content\" className=\"min-h-0 flex-1 overflow-auto\">\n {renderTile(id, path)}\n </div>\n {isDropTarget && dropTarget && (\n <div\n data-slot=\"mosaic-drop-overlay\"\n className={cn(\n \"pointer-events-none absolute z-20 bg-focus/20 ring-2 ring-focus ring-inset\",\n dropZoneOverlayClass[dropTarget.zone],\n )}\n />\n )}\n </div>\n );\n}\n\n// `useMosaic` is intentionally not exported: its context value is typed\n// against the widened `MosaicKey` union (React context can't itself be\n// generic), so a consumer calling it directly on a `Mosaic<T>` instance could\n// pass a mismatched id with no compile-time error. `MosaicWindow` is the\n// supported extension point and narrows back to `T` at its own boundary.\nexport {\n Mosaic,\n MosaicWindow,\n type MosaicProps,\n type MosaicToolbarVisibility,\n type MosaicWindowProps,\n};\nexport type {\n DropZone,\n MosaicDirection,\n MosaicInputNode,\n MosaicInputParent,\n MosaicKey,\n MosaicLeafObject,\n MosaicNode,\n MosaicParent,\n MosaicPath,\n} from \"./Mosaic.utils\";\n"],"mappings":";;;;;;;;;;;;AA2EA,SAAS,oBAAyC,MAAyC;CACzF,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,OAAO;CACtD,IAAI,eAAe,QAAQ,KAAK,cAAc,KAAA,GAAW;EACvD,MAAM,SAAS;EACf,MAAM,aAA8B;GAClC,WAAW,OAAO;GAGlB,OAAO,OAAO,SAAS,OAAO,OAAO,oBAAoB,OAAO,KAAK;GACrE,QAAQ,OAAO,UAAU,OAAO,OAAO,oBAAoB,OAAO,MAAM;EAC1E;EACA,IAAI,OAAO,oBAAoB,KAAA,GAAW,WAAW,kBAAkB,OAAO;EAC9E,OAAO;CACT;CACA,MAAM,OAAQ,KAA6B;CAC3C,IAAI,QAAQ,IAAI,aAAa,gBAAgB,SAAS,KAAA,GACpD,QAAQ,KACN,0FACF;CAEF,OAAO;AACT;;AAGA,SAAS,SAA8B,MAAqD;CAC1F,OAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,eAAe;AACrE;;AAGA,SAAS,UAA+B,MAAiC;CACvE,IAAI,SAAS,MAAM,OAAO,CAAC;CAC3B,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO,CAAC,IAAI;CACjC,OAAO,CAAC,GAAG,UAAU,KAAK,KAAK,GAAG,GAAG,UAAU,KAAK,MAAM,CAAC;AAC7D;;AAGA,SAAS,cACP,MACA,MACsB;CACtB,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,MAAM;EACvB,IAAI,SAAS,QAAQ,CAAC,SAAS,IAAI,GAAG,OAAO;EAC7C,OAAO,KAAK;CACd;CACA,OAAO;AACT;;AAGA,SAAS,cACP,MACA,MACmB;CACnB,IAAI,SAAS,MAAM,OAAO;CAC1B,SAAS,OAAO,MAA4B,MAAqC;EAC/E,IAAI,SAAS,MAAM,OAAO;EAC1B,IAAI,CAAC,SAAS,IAAI,GAChB,OAAO,SAAS,OAAO,OAAO;EAEhC,OAAO,OAAO,KAAK,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,KAAK,OAAO,KAAK,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC;CAC1F;CACA,OAAO,OAAO,MAAM,CAAC,CAAC;AACxB;AAaA,SAAS,kBACP,MACA,MACA,MACsB;CACtB,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO;CAC5B,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,IAAI,SAAS,SACX,OAAO;EAAE,GAAG;EAAM,OAAO,kBAAkB,KAAK,OAAO,MAAM,IAAI;CAAE;CAErE,OAAO;EAAE,GAAG;EAAM,QAAQ,kBAAkB,KAAK,QAAQ,MAAM,IAAI;CAAE;AACvE;;AAGA,SAAS,4BACP,MACA,MACA,iBACe;CACf,MAAM,OAAO,cAAc,MAAM,IAAI;CACrC,IAAI,SAAS,QAAQ,CAAC,SAAS,IAAI,GAAG;EACpC,IAAI,QAAQ,IAAI,aAAa,cAC3B,QAAQ,KACN,mGACF;EAEF,OAAO;CACT;CACA,OAAO,kBAAkB,MAAM,MAAM;EAAE,GAAG;EAAM;CAAgB,CAAC;AACnE;;;;;;AAOA,SAAS,WACP,MACA,MACsB;CACtB,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,MAAM,aAAa,KAAK,MAAM,GAAG,EAAE;CACnC,MAAM,WAAW,KAAK,KAAK,SAAS;CACpC,MAAM,SAAS,cAAc,MAAM,UAAU;CAC7C,IAAI,WAAW,QAAQ,CAAC,SAAS,MAAM,GAAG,OAAO;CACjD,MAAM,UAAU,aAAa,UAAU,OAAO,SAAS,OAAO;CAC9D,IAAI,WAAW,WAAW,GAAG,OAAO;CACpC,OAAO,kBAAkB,MAAM,YAAY,OAAO;AACpD;;;;;;AAOA,SAAS,UACP,MACA,MACA,SACA,WACA,UACe;CACf,MAAM,WAAW,cAAc,MAAM,IAAI;CACzC,IAAI,aAAa,MAAM,OAAO;CAK9B,OAAO,kBAAkB,MAAM,MAH7B,aAAa,WACT;EAAE;EAAW,OAAO;EAAS,QAAQ;EAAU,iBAAiB;CAAG,IACnE;EAAE;EAAW,OAAO;EAAU,QAAQ;EAAS,iBAAiB;CAAG,CAC9B;AAC7C;;AAGA,SAAS,WACP,MACA,OACA,OACe;CACf,IAAI,MAAM,WAAW,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM,SAAS,MAAM,EAAE,GAAG,OAAO;CACzF,MAAM,QAAQ,cAAc,MAAM,KAAK;CACvC,MAAM,QAAQ,cAAc,MAAM,KAAK;CACvC,IAAI,UAAU,QAAQ,UAAU,MAAM,OAAO;CAE7C,OAAO,kBADQ,kBAAkB,MAAM,OAAO,KAChB,GAAG,OAAO,KAAK;AAC/C;;;;;;;;AASA,SAAS,SACP,MACA,YACA,YACA,MACsB;CACtB,IAAI,eAAe,YAAY,OAAO;CACtC,MAAM,aAAa,cAAc,MAAM,UAAU;CACjD,MAAM,aAAa,cAAc,MAAM,UAAU;CACjD,IAAI,eAAe,QAAQ,eAAe,MAAM,OAAO;CAEvD,IAAI,SAAS,UACX,OAAO,WAAW,MAAM,YAAY,UAAU;CAGhD,MAAM,eAAe,WAAW,MAAM,UAAU;CAChD,IAAI,iBAAiB,MAInB,OAAO;CAET,MAAM,qBAAqB,cAAc,cAAc,UAAU;CACjE,IAAI,uBAAuB,MAAM,OAAO;CAIxC,OAAO,UAAU,cAAc,oBAAoB,YAFhB,SAAS,SAAS,SAAS,WAAW,WAAW,OAC/C,SAAS,SAAS,SAAS,SAAS,WAAW,OACF;AACpF;;;;;;;;AAYA,SAAS,iBACP,MACA,SACA,SACA,kBACU;CACV,MAAM,YAAY,KAAK,UAAU,IAAI,MAAO,UAAU,KAAK,QAAQ,KAAK;CACxE,MAAM,YAAY,KAAK,WAAW,IAAI,MAAO,UAAU,KAAK,OAAO,KAAK;CACxE,MAAM,gBAAgB,KAAK,IAAI,WAAW,IAAI,SAAS;CACvD,MAAM,gBAAgB,KAAK,IAAI,WAAW,IAAI,SAAS;CAEvD,IAAI,iBAAiB,oBAAoB,iBAAiB,kBAAkB,OAAO;CACnF,IAAI,gBAAgB,eAClB,OAAO,YAAY,KAAM,SAAS;CAEpC,OAAO,YAAY,KAAM,QAAQ;AACnC;;;AChRA,MAAM,6BAA6B;AACnC,MAAM,mCAAmC;AAsCzC,MAAM,gBAAgB,MAAM,cAAyC,IAAI;;AAGzE,SAAS,YAAgC;CACvC,MAAM,UAAU,MAAM,WAAW,aAAa;CAC9C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,yCAAyC;CAE3D,OAAO;AACT;;AAuEA,SAAS,OAAqC,EAC5C,WACA,OACA,OACA,cACA,UACA,YACA,aACA,gBACA,YAAY,OACZ,WACA,kBACA,mBACA,YACA,kBAAkB,MAClB,mBAAmB,4BACnB,wBAAwB,kCACxB,oBAAoB,UACpB,kBACA,GAAG,SACc;CAQjB,MAAM,kBAAkB,MAAM,cACrB,SAAS,OAAO,QAAQ,oBAAoB,KAAK,GACxD,CAAC,KAAK,CACR;CACA,MAAM,WAAW,MAAM,cAAc,KAAK,UAAU,mBAAmB,IAAI,GAAG,CAAC,eAAe,CAAC;CAC/F,MAAM,CAAC,UAAU,eAAe,MAAM,eACpC,oBAAoB,KAAA,IAChB,kBACA,gBAAgB,OACd,OACA,oBAAoB,YAAY,CACxC;CACA,MAAM,CAAC,gBAAgB,qBAAqB,MAAM,SAAS,QAAQ;CACnE,IAAI,oBAAoB,KAAA,KAAa,aAAa,gBAAgB;EAChE,kBAAkB,QAAQ;EAC1B,YAAY,eAAe;CAC7B;CAQA,MAAM,cAAc,MAAM,OAAO,QAAQ;CACzC,YAAY,UAAU;CAEtB,SAAS,WAAW,MAA4B;EAC9C,YAAY,IAAI;EAChB,WAAW,IAAI;CACjB;CAKA,MAAM,eAAe,MAAM,cAAc,KAAK,UAAU,aAAa,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;CACrF,MAAM,CAAC,eAAe,oBAAoB,MAAM,SAC9C,cAAc,KAAA,IAAY,YAAa,oBAAoB,CAAC,CAC9D;CACA,MAAM,CAAC,oBAAoB,yBAAyB,MAAM,SAAS,YAAY;CAC/E,IAAI,cAAc,KAAA,KAAa,iBAAiB,oBAAoB;EAClE,sBAAsB,YAAY;EAClC,iBAAiB,SAAS;CAC5B;CAEA,SAAS,aAAa,IAAO,MAAc;EACzC,MAAM,UAAU,KAAK,KAAK;EAC1B,MAAM,OAAO,EAAE,GAAG,cAAc;EAChC,IAAI,QAAQ,WAAW,GACrB,OAAO,KAAK;OAEZ,KAAK,MAAM;EAEb,iBAAiB,IAAI;EACrB,oBAAoB,IAAI;CAC1B;CAEA,IAAI,QAAQ,IAAI,aAAa,cAAc;EACzC,MAAM,SAAS,UAAU,QAAQ;EACjC,IAAI,IAAI,IAAI,MAAM,EAAE,SAAS,OAAO,QAClC,QAAQ,KACN,2IACF;CAEJ;CAGA,SAAS,YAAY,MAAkB,WAA4B;EACjE,IAAI,YAAY,YAAY,MAAM;EAIlC,QAAQ,QAAQ,WAAW,IAAI,CAAC,EAAE,MAAM,YAAY;GAClD,MAAM,UAAU,YAAY;GAC5B,IAAI,YAAY,MAAM;GACtB,WAAW,UAAU,SAAS,MAAM,SAAS,WAAW,OAAO,CAAC;EAClE,CAAC;CACH;CAEA,SAAS,aAAa,MAAkB;EACtC,MAAM,UAAU,YAAY;EAC5B,IAAI,YAAY,MAAM;EACtB,WAAW,WAAW,SAAS,IAAI,CAAC;CACtC;CAKA,SAAS,qBACP,MACA,QACA,cACA;EACA,MAAM,UAAU,YAAY;EAC5B,IAAI,YAAY,MAAM;EACtB,MAAM,aAAa,OAAO;EAC1B,IAAI,eAAe,KAAA,GAAW;EAI9B,MAAM,OAAO,cAAc,SAAS,IAAI;EACxC,IAAI,SAAS,IAAI,KAAK,KAAK,KAAK,KAAK,mBAAmB,MAAM,UAAU,IAAI,IAAK;EACjF,WAAW,4BAA4B,SAAS,MAAM,UAAU,CAAC;CACnE;CAQA,MAAM,aAAa,MAAM,MAAM;CAC/B,MAAM,kBAAkB,SACtB,GAAG,WAAW,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,KAAK,GAAG;CAWnE,MAAM,kBAAkB,MAAM,uBAAO,IAAI,IAAmC,CAAC;CAE7E,MAAM,gBAAgB;EACpB,SAAS,iBAAiB,MAA4B,MAAkB;GACtE,IAAI,CAAC,SAAS,IAAI,GAAG;GACrB,MAAM,UAAU,eAAe,IAAI;GACnC,MAAM,SAAS,gBAAgB,QAAQ,IAAI,OAAO;GAClD,IAAI,QAAQ;IACV,MAAM,eAAe,GAAG,QAAQ;IAChC,MAAM,WAAW,KAAK,mBAAmB;IACzC,MAAM,SAAS,OAAO,UAAU,EAAE;IAClC,IAAI,WAAW,KAAA,KAAa,KAAK,IAAI,SAAS,QAAQ,IAAI,IACxD,OAAO,UAAU;MACd,eAAe;MACf,GAAG,QAAQ,WAAW,MAAM;IAC/B,CAAC;GAEL;GACA,iBAAiB,KAAK,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;GAC/C,iBAAiB,KAAK,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC;EACnD;EACA,iBAAiB,UAAU,CAAC,CAAC;CAC/B,GAAG,CAAC,QAAQ,CAAC;CAIb,MAAM,CAAC,cAAc,mBAAmB,MAAM,SAA4B,IAAI;CAC9E,MAAM,CAAC,YAAY,iBAAiB,MAAM,SACxC,IACF;CAEA,SAAS,YAAY,MAAkB;EACrC,gBAAgB,IAAI;CACtB;CAEA,SAAS,WAAW,YAA+B,MAAuB;EACxE,cAAc,cAAc,OAAO;GAAE,MAAM;GAAY;EAAK,IAAI,IAAI;CACtE;CAeA,SAAS,UAAU,UAAa,YAA+B,MAAuB;EACpF,MAAM,UAAU,YAAY;EAC5B,IAAI,cAAc,QAAQ,YAAY,MAAM;GAC1C,MAAM,aAAa,cAAc,SAAS,UAAU;GACpD,IAAI,eAAe,QAAQ,CAAC,SAAS,UAAU,GAC7C,WAAW,SAAS,SAAS,UAAU,YAAY,IAAI,CAAC;EAE5D;EACA,gBAAgB,IAAI;EACpB,cAAc,IAAI;CACpB;CAEA,SAAS,eAAe;EACtB,gBAAgB,IAAI;EACpB,cAAc,IAAI;CACpB;CAEA,MAAM,eAAmC;EAC3B;EACC;EACb;EACA;EACA;EACA;EACA,YAAY,UAAU,YAAY,SAAS,UAAU,UAAe,YAAY,IAAI;EACpF;EACA;EACA;EACA;EACA;EACA;EACA,cAAc,OAAO,cAAc;EACnC,eAAe,IAAI,SAAS,aAAa,IAAS,IAAI;EACtD;CACF;CAGA,SAAS,WAAW,MAA4B,MAAmC;EAGjF,IAAI,SAAS,MACX,OAAO,oBAAC,OAAD;GAAK,aAAU;GAAoB,WAAU;EAAiB,CAAA;EAEvE,IAAI,CAAC,SAAS,IAAI,GAChB,OACE,oBAAC,cAAD;GAEE,IAAI;GACE;GACN,UAAU,iBAAiB,MAAM,IAAI;EACtC,GAJM,OAAO,IAAI,CAIjB;EAIL,MAAM,UAAU,eAAe,IAAI;EACnC,MAAM,eAAe,GAAG,QAAQ;EAChC,MAAM,gBAAgB,GAAG,QAAQ;EACjC,MAAM,gBAAgB,SAA+B;GACnD,MAAM,OAAO,UAAU,IAAI,EAAE;GAC7B,OAAO,SAAS,KAAA,IAAY,gBAAgB,QAAQ,OAAO,IAAI;EACjE;EAEA,OACE,qBAAC,qBAAD;GAEE,IAAI;GACJ,aAAa,KAAK,cAAc,QAAQ,eAAe;GACvD,WAAW,WAAW;IACpB,IAAI,QACF,gBAAgB,QAAQ,IAAI,SAAS,MAAM;SAE3C,gBAAgB,QAAQ,OAAO,OAAO;GAE1C;GACA,kBAAkB,WAAW,qBAAqB,MAAM,QAAQ,YAAY;aAX9E;IAaE,oBAAC,gBAAD;KACE,IAAI;KACJ,aAAa,KAAK,mBAAmB;KACrC,SAAS;eAER,WAAW,KAAK,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;IAC5B,CAAA;IAChB,oBAAC,iBAAD,EACE,cAAY,kBAAkB,aAAa,KAAK,KAAK,EAAE,OAAO,aAAa,KAAK,MAAM,IACvF,CAAA;IACD,oBAAC,gBAAD;KACE,IAAI;KACJ,aAAa,OAAO,KAAK,mBAAmB;KAC5C,SAAS;eAER,WAAW,KAAK,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC;IAC9B,CAAA;GACG;KA7Bd,OA6Bc;CAEzB;CAEA,OACE,oBAAC,cAAc,UAAf;EAAwB,OAAO;YAC7B,oBAAC,OAAD;GACE,aAAU;GACV,WAAW,GAAG,0CAA0C,SAAS;GAC1D;GACP,GAAI;aAEH,aAAa,OAAQ,oBAAoB,OAAQ,WAAW,UAAU,CAAC,CAAC;EACtE,CAAA;CACiB,CAAA;AAE5B;AAEA,MAAM,uBAAiD;CACrD,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACP,QAAQ;AACV;;;;;;;;;;;;;;AAyBA,SAAS,aAA2C,EAClD,IACA,MACA,WACA,YACuB;CACvB,MAAM,EACJ,YACA,aACA,aACA,cACA,aACA,YACA,WACA,cACA,cACA,YACA,iBACA,kBACA,WACA,aACA,cACA,sBACE,UAAU;CAEd,MAAM,UAAU,KAAK,KAAK,GAAG;CAC7B,MAAM,aAAa,iBAAiB,QAAQ,aAAa,KAAK,GAAG,MAAM;CACvE,MAAM,eAAe,eAAe,QAAQ,WAAW,KAAK,KAAK,GAAG,MAAM;CAM1E,MAAM,iBAAiB,YAAY,EAAE,KAAK,OAAO,EAAE;CAGnD,MAAM,CAAC,eAAe,oBAAoB,MAAM,SAAS,KAAK;CAC9D,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAS,EAAE;CAInD,MAAM,kBAAkB,MAAM,OAAO,KAAK;CAE1C,SAAS,mBAAmB;EAC1B,gBAAgB,UAAU;EAC1B,aAAa,YAAY,EAAE,KAAK,OAAO,EAAE,CAAC;EAC1C,iBAAiB,IAAI;CACvB;CAEA,SAAS,kBAAkB,MAAc;EACvC,IAAI,gBAAgB,SAAS;EAC7B,gBAAgB,UAAU;EAC1B,iBAAiB,KAAK;EACtB,aAAa,IAAI,IAAI;CACvB;CAEA,SAAS,oBAAoB;EAC3B,gBAAgB,UAAU;EAC1B,iBAAiB,KAAK;CACxB;CAEA,SAAS,aAAa,SAAiB,SAAiB;EACtD,MAAM,YAAY,SACf,iBAAiB,SAAS,OAAO,GAChC,QAAqB,+BAA6B;EACtD,MAAM,iBAAiB,WAAW,QAAQ;EAC1C,IAAI,CAAC,aAAa,mBAAmB,KAAA,KAAa,mBAAmB,SAAS,OAAO;EAIrF,OAAO;GAAE,YAHW,mBAAmB,KAAK,CAAC,IAAI,eAAe,MAAM,GAAG;GAGpD,MADR,iBADA,UAAU,sBACU,GAAG,SAAS,SAAS,gBAC9B;EAAE;CAC5B;CAEA,SAAS,sBAAsB,OAA8C;EAC3E,IAAI,MAAM,WAAW,KAAK,MAAM,gBAAgB,SAAS;EACzD,MAAM,eAAe;EACrB,YAAY,IAAI;EAGhB,SAAS,KAAK,MAAM,SAAS;EAE7B,SAAS,kBAAkB;GACzB,OAAO,oBAAoB,eAAe,MAAM;GAChD,OAAO,oBAAoB,aAAa,IAAI;GAC5C,OAAO,oBAAoB,iBAAiB,QAAQ;EACtD;EACA,MAAM,UAAU,cAA4B;GAC1C,MAAM,QAAQ,aAAa,UAAU,SAAS,UAAU,OAAO;GAC/D,WAAW,OAAO,cAAc,MAAM,OAAO,QAAQ,IAAI;EAC3D;EACA,MAAM,QAAQ,YAA0B;GACtC,gBAAgB;GAChB,SAAS,KAAK,MAAM,SAAS;GAC7B,MAAM,QAAQ,aAAa,QAAQ,SAAS,QAAQ,OAAO;GAC3D,UAAU,IAAI,OAAO,cAAc,MAAM,OAAO,QAAQ,IAAI;EAC9D;EAGA,MAAM,iBAAiB;GACrB,gBAAgB;GAChB,SAAS,KAAK,MAAM,SAAS;GAC7B,aAAa;EACf;EACA,OAAO,iBAAiB,eAAe,MAAM;EAC7C,OAAO,iBAAiB,aAAa,IAAI;EACzC,OAAO,iBAAiB,iBAAiB,QAAQ;CACnD;CAEA,OACE,qBAAC,OAAD;EACE,aAAU;EACV,oBAAkB;EAClB,WAAW,GACT,wDACA,sBAAsB,cAAc,uBACpC,cAAc,cACd,SACF;YARF;GAUG,sBAAsB,YACrB,qBAAC,OAAD;IACE,aAAU;IACV,WAAW,GACT,6FAIA,sBAAsB,cACpB,wIACJ;cATF;KAWG,mBACC,oBAAC,UAAD;MACE,MAAK;MACL,aAAU;MACV,cAAY,sBAAsB,eAAe;MACjD,WAAW;MACX,WAAU;MACV,eAAe;gBAEf,oBAAC,kBAAD,EAAkB,WAAU,WAAY,CAAA;KAClC,CAAA;KAET,gBACC,oBAAC,SAAD;MACE,MAAK;MACL,aAAU;MACV,cAAY,kBAAkB,eAAe;MAC7C,OAAO;MACP,WAAA;MACA,WAAU;MACV,WAAW,UAAU,aAAa,MAAM,OAAO,KAAK;MACpD,UAAU,UAAU,MAAM,cAAc,OAAO;MAC/C,SAAS,UAAU,kBAAkB,MAAM,cAAc,KAAK;MAC9D,YAAY,UAAU;OACpB,IAAI,MAAM,QAAQ,SAAS;QACzB,MAAM,eAAe;QACrB,kBAAkB,MAAM,cAAc,KAAK;OAC7C,OAAO,IAAI,MAAM,QAAQ,UAAU;QACjC,MAAM,eAAe;QACrB,kBAAkB;OACpB;MACF;KACD,CAAA,IAED,oBAAC,QAAD;MACE,WAAU;MACV,eAAe,YAAY,mBAAmB,KAAA;gBAE7C,YAAY,EAAE,MAAM,cAAc,YAAY,IAAI,IAAI,IAAI,OAAO,EAAE;KAChE,CAAA;KAEP,aAAa,CAAC,iBACb,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,cAAY,gBAAgB,eAAe;MAC3C,SAAS;gBAET,oBAAC,YAAD,CAAa,CAAA;KACP,CAAA;KAET;KACD,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,cAAY,eAAe,eAAe;MAC1C,eAAe,YAAY,MAAM,KAAK;gBAEtC,oBAAC,eAAD,CAAgB,CAAA;KACV,CAAA;KACR,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,cAAY,eAAe,eAAe;MAC1C,eAAe,YAAY,MAAM,QAAQ;gBAEzC,oBAAC,cAAD,CAAe,CAAA;KACT,CAAA;KACR,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,cAAY,gBAAgB,eAAe;MAC3C,eAAe,aAAa,IAAI;gBAEhC,oBAAC,OAAD,CAAQ,CAAA;KACF,CAAA;IACL;;GAEP,oBAAC,OAAD;IAAK,aAAU;IAAwB,WAAU;cAC9C,WAAW,IAAI,IAAI;GACjB,CAAA;GACJ,gBAAgB,cACf,oBAAC,OAAD;IACE,aAAU;IACV,WAAW,GACT,8EACA,qBAAqB,WAAW,KAClC;GACD,CAAA;EAEA;;AAET"}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime296 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime123 from "react/jsx-runtime";
2
2
  import { Accordion } from "radix-ui";
3
3
 
4
4
  //#region src/primitives/Accordion/Accordion.d.ts
@@ -10,24 +10,24 @@ declare function Accordion$1({
10
10
  }: React.ComponentProps<typeof Accordion.Root> & {
11
11
  /** Visual style: `line` (divider rows) or `bordered` (rounded border with inset rows). */
12
12
  variant?: "line" | "bordered";
13
- }): react_jsx_runtime296.JSX.Element;
13
+ }): react_jsx_runtime123.JSX.Element;
14
14
  /** A single collapsible section; identified by its required `value`. */
15
15
  declare function AccordionItem({
16
16
  className,
17
17
  ...props
18
- }: React.ComponentProps<typeof Accordion.Item>): react_jsx_runtime296.JSX.Element;
18
+ }: React.ComponentProps<typeof Accordion.Item>): react_jsx_runtime123.JSX.Element;
19
19
  /** The clickable header that toggles its section open or closed. */
20
20
  declare function AccordionTrigger({
21
21
  className,
22
22
  children,
23
23
  ...props
24
- }: React.ComponentProps<typeof Accordion.Trigger>): react_jsx_runtime296.JSX.Element;
24
+ }: React.ComponentProps<typeof Accordion.Trigger>): react_jsx_runtime123.JSX.Element;
25
25
  /** The animated collapsible panel revealed when its section is open. */
26
26
  declare function AccordionContent({
27
27
  className,
28
28
  children,
29
29
  ...props
30
- }: React.ComponentProps<typeof Accordion.Content>): react_jsx_runtime296.JSX.Element;
30
+ }: React.ComponentProps<typeof Accordion.Content>): react_jsx_runtime123.JSX.Element;
31
31
  //#endregion
32
32
  export { AccordionTrigger as i, AccordionContent as n, AccordionItem as r, Accordion$1 as t };
33
33
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime350 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime143 from "react/jsx-runtime";
2
2
  import { Accordion } from "radix-ui";
3
3
 
4
4
  //#region src/primitives/Accordion/Accordion.d.ts
@@ -10,24 +10,24 @@ declare function Accordion$1({
10
10
  }: React.ComponentProps<typeof Accordion.Root> & {
11
11
  /** Visual style: `line` (divider rows) or `bordered` (rounded border with inset rows). */
12
12
  variant?: "line" | "bordered";
13
- }): react_jsx_runtime350.JSX.Element;
13
+ }): react_jsx_runtime143.JSX.Element;
14
14
  /** A single collapsible section; identified by its required `value`. */
15
15
  declare function AccordionItem({
16
16
  className,
17
17
  ...props
18
- }: React.ComponentProps<typeof Accordion.Item>): react_jsx_runtime350.JSX.Element;
18
+ }: React.ComponentProps<typeof Accordion.Item>): react_jsx_runtime143.JSX.Element;
19
19
  /** The clickable header that toggles its section open or closed. */
20
20
  declare function AccordionTrigger({
21
21
  className,
22
22
  children,
23
23
  ...props
24
- }: React.ComponentProps<typeof Accordion.Trigger>): react_jsx_runtime350.JSX.Element;
24
+ }: React.ComponentProps<typeof Accordion.Trigger>): react_jsx_runtime143.JSX.Element;
25
25
  /** The animated collapsible panel revealed when its section is open. */
26
26
  declare function AccordionContent({
27
27
  className,
28
28
  children,
29
29
  ...props
30
- }: React.ComponentProps<typeof Accordion.Content>): react_jsx_runtime350.JSX.Element;
30
+ }: React.ComponentProps<typeof Accordion.Content>): react_jsx_runtime143.JSX.Element;
31
31
  //#endregion
32
32
  export { AccordionTrigger as i, AccordionContent as n, AccordionItem as r, Accordion$1 as t };
33
33
  //# sourceMappingURL=index.d.ts.map
@@ -1,12 +1,12 @@
1
1
  import { t as Separator } from "./index9.cjs";
2
- import * as react_jsx_runtime170 from "react/jsx-runtime";
3
- import * as class_variance_authority_types12 from "class-variance-authority/types";
2
+ import * as react_jsx_runtime80 from "react/jsx-runtime";
3
+ import * as class_variance_authority_types7 from "class-variance-authority/types";
4
4
  import { VariantProps } from "class-variance-authority";
5
5
 
6
6
  //#region src/primitives/ButtonGroup/ButtonGroup.d.ts
7
7
  declare const buttonGroupVariants: (props?: ({
8
- orientation?: "vertical" | "horizontal" | null | undefined;
9
- } & class_variance_authority_types12.ClassProp) | undefined) => string;
8
+ orientation?: "horizontal" | "vertical" | null | undefined;
9
+ } & class_variance_authority_types7.ClassProp) | undefined) => string;
10
10
  /** Props for the {@link ButtonGroup} container. */
11
11
  type ButtonGroupProps = React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>;
12
12
  /** Groups related buttons into a single attached unit with merged borders and shared corners. */
@@ -15,7 +15,7 @@ declare function ButtonGroup({
15
15
  /** Lays the group out left-to-right (`horizontal`, default) or stacked (`vertical`). */
16
16
  orientation,
17
17
  ...props
18
- }: ButtonGroupProps): react_jsx_runtime170.JSX.Element;
18
+ }: ButtonGroupProps): react_jsx_runtime80.JSX.Element;
19
19
  /** A non-interactive label/affix segment styled to sit inline with the grouped buttons. */
20
20
  declare function ButtonGroupText({
21
21
  className,
@@ -25,14 +25,14 @@ declare function ButtonGroupText({
25
25
  }: React.ComponentProps<"div"> & {
26
26
  /** Renders into the child element via Radix `Slot` instead of a wrapping `div`. */
27
27
  asChild?: boolean;
28
- }): react_jsx_runtime170.JSX.Element;
28
+ }): react_jsx_runtime80.JSX.Element;
29
29
  /** A divider between segments inside a {@link ButtonGroup}, defaulting to a vertical rule. */
30
30
  declare function ButtonGroupSeparator({
31
31
  className,
32
32
  /** Divider direction; defaults to `vertical` to split horizontally-laid buttons. */
33
33
  orientation,
34
34
  ...props
35
- }: React.ComponentProps<typeof Separator>): react_jsx_runtime170.JSX.Element;
35
+ }: React.ComponentProps<typeof Separator>): react_jsx_runtime80.JSX.Element;
36
36
  //#endregion
37
37
  export { buttonGroupVariants as i, ButtonGroupSeparator as n, ButtonGroupText as r, ButtonGroup as t };
38
38
  //# sourceMappingURL=index10.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index10.d.cts","names":[],"sources":["../src/primitives/ButtonGroup/ButtonGroup.tsx"],"mappings":";;;;;;cAMM;;IAeL,gCAAA,CAAA;;AAlBkD,KAqB9C,gBAAA,GAAmB,KAAA,CAAM,cAH7B,CAAA,KAAA,CAAA,GAGqD,YAHrD,CAAA,OAGyE,mBAHzE,CAAA;;iBAMQ,WAAA,CAHY;EAAA,SAAA;;aAAqD;EAAA,GAAA;AAAA,CAAA,EAQvE,gBARuE,CAAA,EAQvD,oBAAA,CAAA,GAAA,CAAA,OARuD;;AAAR,iBAqBzD,eAAA,CArByD;EAAA,SAAA;EAAA;SAG9C;EAAA,GAAA;CAAA,EAuBjB,KAAA,CAAM,cAvBW,CAAA,KAAA,CAAA,GAAA;;SAGlB,CAAA,EAAA,OAAA;IAuBD,oBAAA,CAAA,GAAA,CAAA,OArBE;;AAAgB,iBAoCV,oBAAA,CApCU;EAAA,SAAA;EAAA;aAaK;EAAA,GAAA;AAAA,CAAA,EA4BrB,KAAA,CAAM,cA5Be,CAAA,OA4BO,SA5BP,CAAA,CAAA,EA4BiB,oBAAA,CAAA,GAAA,CAAA,OA5BjB"}
1
+ {"version":3,"file":"index10.d.cts","names":[],"sources":["../src/primitives/ButtonGroup/ButtonGroup.tsx"],"mappings":";;;;;;cAMM;;IAeL,+BAAA,CAAA;;AAlBkD,KAqB9C,gBAAA,GAAmB,KAAA,CAAM,cAH7B,CAAA,KAAA,CAAA,GAGqD,YAHrD,CAAA,OAGyE,mBAHzE,CAAA;;iBAMQ,WAAA,CAHY;EAAA,SAAA;;aAAqD;EAAA,GAAA;AAAA,CAAA,EAQvE,gBARuE,CAAA,EAQvD,mBAAA,CAAA,GAAA,CAAA,OARuD;;AAAR,iBAqBzD,eAAA,CArByD;EAAA,SAAA;EAAA;SAG9C;EAAA,GAAA;CAAA,EAuBjB,KAAA,CAAM,cAvBW,CAAA,KAAA,CAAA,GAAA;;SAGlB,CAAA,EAAA,OAAA;IAuBD,mBAAA,CAAA,GAAA,CAAA,OArBE;;AAAgB,iBAoCV,oBAAA,CApCU;EAAA,SAAA;EAAA;aAaK;EAAA,GAAA;AAAA,CAAA,EA4BrB,KAAA,CAAM,cA5Be,CAAA,OA4BO,SA5BP,CAAA,CAAA,EA4BiB,mBAAA,CAAA,GAAA,CAAA,OA5BjB"}
package/dist/index10.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { t as Separator } from "./index9.js";
2
2
  import { VariantProps } from "class-variance-authority";
3
- import * as react_jsx_runtime272 from "react/jsx-runtime";
4
- import * as class_variance_authority_types20 from "class-variance-authority/types";
3
+ import * as react_jsx_runtime289 from "react/jsx-runtime";
4
+ import * as class_variance_authority_types22 from "class-variance-authority/types";
5
5
 
6
6
  //#region src/primitives/ButtonGroup/ButtonGroup.d.ts
7
7
  declare const buttonGroupVariants: (props?: ({
8
8
  orientation?: "vertical" | "horizontal" | null | undefined;
9
- } & class_variance_authority_types20.ClassProp) | undefined) => string;
9
+ } & class_variance_authority_types22.ClassProp) | undefined) => string;
10
10
  /** Props for the {@link ButtonGroup} container. */
11
11
  type ButtonGroupProps = React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>;
12
12
  /** Groups related buttons into a single attached unit with merged borders and shared corners. */
@@ -15,7 +15,7 @@ declare function ButtonGroup({
15
15
  /** Lays the group out left-to-right (`horizontal`, default) or stacked (`vertical`). */
16
16
  orientation,
17
17
  ...props
18
- }: ButtonGroupProps): react_jsx_runtime272.JSX.Element;
18
+ }: ButtonGroupProps): react_jsx_runtime289.JSX.Element;
19
19
  /** A non-interactive label/affix segment styled to sit inline with the grouped buttons. */
20
20
  declare function ButtonGroupText({
21
21
  className,
@@ -25,14 +25,14 @@ declare function ButtonGroupText({
25
25
  }: React.ComponentProps<"div"> & {
26
26
  /** Renders into the child element via Radix `Slot` instead of a wrapping `div`. */
27
27
  asChild?: boolean;
28
- }): react_jsx_runtime272.JSX.Element;
28
+ }): react_jsx_runtime289.JSX.Element;
29
29
  /** A divider between segments inside a {@link ButtonGroup}, defaulting to a vertical rule. */
30
30
  declare function ButtonGroupSeparator({
31
31
  className,
32
32
  /** Divider direction; defaults to `vertical` to split horizontally-laid buttons. */
33
33
  orientation,
34
34
  ...props
35
- }: React.ComponentProps<typeof Separator>): react_jsx_runtime272.JSX.Element;
35
+ }: React.ComponentProps<typeof Separator>): react_jsx_runtime289.JSX.Element;
36
36
  //#endregion
37
37
  export { buttonGroupVariants as i, ButtonGroupSeparator as n, ButtonGroupText as r, ButtonGroup as t };
38
38
  //# sourceMappingURL=index10.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { t as Button } from "./index8.cjs";
2
- import * as react_jsx_runtime335 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { DayButton, DayPicker } from "react-day-picker";
5
5
 
@@ -17,14 +17,14 @@ declare function Calendar({
17
17
  }: React.ComponentProps<typeof DayPicker> & {
18
18
  /** Button variant used for the previous/next navigation controls. */
19
19
  buttonVariant?: React.ComponentProps<typeof Button>["variant"];
20
- }): react_jsx_runtime335.JSX.Element;
20
+ }): react_jsx_runtime0.JSX.Element;
21
21
  /** Single day cell button, applying selected/range styling from the day's modifiers. */
22
22
  declare function CalendarDayButton({
23
23
  className,
24
24
  day,
25
25
  modifiers,
26
26
  ...props
27
- }: React.ComponentProps<typeof DayButton>): react_jsx_runtime335.JSX.Element;
27
+ }: React.ComponentProps<typeof DayButton>): react_jsx_runtime0.JSX.Element;
28
28
  //#endregion
29
29
  export { CalendarDayButton as n, Calendar as t };
30
30
  //# sourceMappingURL=index11.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index11.d.cts","names":[],"sources":["../src/primitives/Calendar/Calendar.tsx"],"mappings":";;;;;;;iBASS,QAAA;;;;;;;;;GASN,KAAA,CAAM,sBAAsB;;EATtB,aAAQ,CAAA,EAWC,KAAA,CAAM,cAXP,CAAA,OAW6B,MAX7B,CAAA,CAAA,SAAA,CAAA;CAAA,CAAA,EAYhB,oBAAA,CAAA,GAAA,CAAA,OAZgB;;iBAwIR,iBAAA,CAtIP;EAAA,SAAA;EAAA,GAAA;EAAA,SAAA;EAAA,GAAA;AAAA,CAAA,EA2IC,KAAA,CAAM,cA3IP,CAAA,OA2I6B,SA3I7B,CAAA,CAAA,EA2IuC,oBAAA,CAAA,GAAA,CAAA,OA3IvC"}
1
+ {"version":3,"file":"index11.d.cts","names":[],"sources":["../src/primitives/Calendar/Calendar.tsx"],"mappings":";;;;;;;iBASS,QAAA;;;;;;;;;GASN,KAAA,CAAM,sBAAsB;;EATtB,aAAQ,CAAA,EAWC,KAAA,CAAM,cAXP,CAAA,OAW6B,MAX7B,CAAA,CAAA,SAAA,CAAA;CAAA,CAAA,EAYhB,kBAAA,CAAA,GAAA,CAAA,OAZgB;;iBAwIR,iBAAA,CAtIP;EAAA,SAAA;EAAA,GAAA;EAAA,SAAA;EAAA,GAAA;AAAA,CAAA,EA2IC,KAAA,CAAM,cA3IP,CAAA,OA2I6B,SA3I7B,CAAA,CAAA,EA2IuC,kBAAA,CAAA,GAAA,CAAA,OA3IvC"}
package/dist/index11.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as Button } from "./index8.js";
2
2
  import * as React from "react";
3
- import * as react_jsx_runtime180 from "react/jsx-runtime";
3
+ import * as react_jsx_runtime287 from "react/jsx-runtime";
4
4
  import { DayButton, DayPicker } from "react-day-picker";
5
5
 
6
6
  //#region src/primitives/Calendar/Calendar.d.ts
@@ -17,14 +17,14 @@ declare function Calendar({
17
17
  }: React.ComponentProps<typeof DayPicker> & {
18
18
  /** Button variant used for the previous/next navigation controls. */
19
19
  buttonVariant?: React.ComponentProps<typeof Button>["variant"];
20
- }): react_jsx_runtime180.JSX.Element;
20
+ }): react_jsx_runtime287.JSX.Element;
21
21
  /** Single day cell button, applying selected/range styling from the day's modifiers. */
22
22
  declare function CalendarDayButton({
23
23
  className,
24
24
  day,
25
25
  modifiers,
26
26
  ...props
27
- }: React.ComponentProps<typeof DayButton>): react_jsx_runtime180.JSX.Element;
27
+ }: React.ComponentProps<typeof DayButton>): react_jsx_runtime287.JSX.Element;
28
28
  //#endregion
29
29
  export { CalendarDayButton as n, Calendar as t };
30
30
  //# sourceMappingURL=index11.d.ts.map
@@ -1,13 +1,13 @@
1
- import * as react_jsx_runtime185 from "react/jsx-runtime";
2
- import * as class_variance_authority_types15 from "class-variance-authority/types";
1
+ import * as react_jsx_runtime127 from "react/jsx-runtime";
2
+ import * as class_variance_authority_types14 from "class-variance-authority/types";
3
3
  import { VariantProps } from "class-variance-authority";
4
4
  import * as React from "react";
5
5
 
6
6
  //#region src/primitives/Card/Card.d.ts
7
7
  declare const cardVariants: (props?: ({
8
8
  variant?: "default" | "ai" | "inverted" | "glass" | "brand" | null | undefined;
9
- tint?: "medium" | "light" | "subtle" | "heavy" | null | undefined;
10
- } & class_variance_authority_types15.ClassProp) | undefined) => string;
9
+ tint?: "subtle" | "medium" | "light" | "heavy" | null | undefined;
10
+ } & class_variance_authority_types14.ClassProp) | undefined) => string;
11
11
  type CardProps = React.ComponentProps<"div"> & VariantProps<typeof cardVariants> & {
12
12
  /** Surface treatment of the card. Default `default` (solid surface). */
13
13
  variant?: VariantProps<typeof cardVariants>["variant"];
@@ -20,7 +20,7 @@ declare function Card({
20
20
  variant,
21
21
  tint,
22
22
  ...props
23
- }: CardProps): react_jsx_runtime185.JSX.Element;
23
+ }: CardProps): react_jsx_runtime127.JSX.Element;
24
24
  declare const cardHeaderAlign: {
25
25
  readonly start: "items-start";
26
26
  readonly center: "items-center";
@@ -34,28 +34,28 @@ declare function CardHeader({
34
34
  }: React.ComponentProps<"div"> & {
35
35
  /** Vertical alignment of the header items. Default `center`. */
36
36
  align?: keyof typeof cardHeaderAlign;
37
- }): react_jsx_runtime185.JSX.Element;
37
+ }): react_jsx_runtime127.JSX.Element;
38
38
  /** Card heading rendered as an `h4`. Figma binds the body font (Inter Semibold
39
39
  16/24), so we override the base heading styles explicitly. */
40
40
  declare function CardTitle({
41
41
  className,
42
42
  ...props
43
- }: React.ComponentProps<"div">): react_jsx_runtime185.JSX.Element;
43
+ }: React.ComponentProps<"div">): react_jsx_runtime127.JSX.Element;
44
44
  /** Muted supporting text shown beneath the title. */
45
45
  declare function CardDescription({
46
46
  className,
47
47
  ...props
48
- }: React.ComponentProps<"div">): react_jsx_runtime185.JSX.Element;
48
+ }: React.ComponentProps<"div">): react_jsx_runtime127.JSX.Element;
49
49
  /** Action slot in the header row, aligned to the end alongside the title. */
50
50
  declare function CardAction({
51
51
  className,
52
52
  ...props
53
- }: React.ComponentProps<"div">): react_jsx_runtime185.JSX.Element;
53
+ }: React.ComponentProps<"div">): react_jsx_runtime127.JSX.Element;
54
54
  /** Main body region of the card. */
55
55
  declare function CardContent({
56
56
  className,
57
57
  ...props
58
- }: React.ComponentProps<"div">): react_jsx_runtime185.JSX.Element;
58
+ }: React.ComponentProps<"div">): react_jsx_runtime127.JSX.Element;
59
59
  declare const cardFooterTone: {
60
60
  readonly default: "px-6 pb-6 [.border-t]:pt-6";
61
61
  readonly brand: "justify-center rounded-b-8 bg-brand-200 px-6 py-3 text-brand-800";
@@ -70,7 +70,7 @@ declare function CardFooter({
70
70
  }: React.ComponentProps<"div"> & {
71
71
  /** Footer fill. `brand`/`muted` render a full-width tinted band. */
72
72
  tone?: keyof typeof cardFooterTone;
73
- }): react_jsx_runtime185.JSX.Element;
73
+ }): react_jsx_runtime127.JSX.Element;
74
74
  //#endregion
75
75
  export { CardFooter as a, CardTitle as c, CardDescription as i, cardVariants as l, CardAction as n, CardHeader as o, CardContent as r, CardProps as s, Card as t };
76
76
  //# sourceMappingURL=index12.d.cts.map
package/dist/index12.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { VariantProps } from "class-variance-authority";
2
2
  import * as React from "react";
3
- import * as react_jsx_runtime66 from "react/jsx-runtime";
4
- import * as class_variance_authority_types5 from "class-variance-authority/types";
3
+ import * as react_jsx_runtime271 from "react/jsx-runtime";
4
+ import * as class_variance_authority_types21 from "class-variance-authority/types";
5
5
 
6
6
  //#region src/primitives/Card/Card.d.ts
7
7
  declare const cardVariants: (props?: ({
8
- variant?: "default" | "glass" | "inverted" | "brand" | "ai" | null | undefined;
9
- tint?: "subtle" | "medium" | "light" | "heavy" | null | undefined;
10
- } & class_variance_authority_types5.ClassProp) | undefined) => string;
8
+ variant?: "default" | "glass" | "ai" | "inverted" | "brand" | null | undefined;
9
+ tint?: "medium" | "light" | "subtle" | "heavy" | null | undefined;
10
+ } & class_variance_authority_types21.ClassProp) | undefined) => string;
11
11
  type CardProps = React.ComponentProps<"div"> & VariantProps<typeof cardVariants> & {
12
12
  /** Surface treatment of the card. Default `default` (solid surface). */
13
13
  variant?: VariantProps<typeof cardVariants>["variant"];
@@ -20,7 +20,7 @@ declare function Card({
20
20
  variant,
21
21
  tint,
22
22
  ...props
23
- }: CardProps): react_jsx_runtime66.JSX.Element;
23
+ }: CardProps): react_jsx_runtime271.JSX.Element;
24
24
  declare const cardHeaderAlign: {
25
25
  readonly start: "items-start";
26
26
  readonly center: "items-center";
@@ -34,28 +34,28 @@ declare function CardHeader({
34
34
  }: React.ComponentProps<"div"> & {
35
35
  /** Vertical alignment of the header items. Default `center`. */
36
36
  align?: keyof typeof cardHeaderAlign;
37
- }): react_jsx_runtime66.JSX.Element;
37
+ }): react_jsx_runtime271.JSX.Element;
38
38
  /** Card heading rendered as an `h4`. Figma binds the body font (Inter Semibold
39
39
  16/24), so we override the base heading styles explicitly. */
40
40
  declare function CardTitle({
41
41
  className,
42
42
  ...props
43
- }: React.ComponentProps<"div">): react_jsx_runtime66.JSX.Element;
43
+ }: React.ComponentProps<"div">): react_jsx_runtime271.JSX.Element;
44
44
  /** Muted supporting text shown beneath the title. */
45
45
  declare function CardDescription({
46
46
  className,
47
47
  ...props
48
- }: React.ComponentProps<"div">): react_jsx_runtime66.JSX.Element;
48
+ }: React.ComponentProps<"div">): react_jsx_runtime271.JSX.Element;
49
49
  /** Action slot in the header row, aligned to the end alongside the title. */
50
50
  declare function CardAction({
51
51
  className,
52
52
  ...props
53
- }: React.ComponentProps<"div">): react_jsx_runtime66.JSX.Element;
53
+ }: React.ComponentProps<"div">): react_jsx_runtime271.JSX.Element;
54
54
  /** Main body region of the card. */
55
55
  declare function CardContent({
56
56
  className,
57
57
  ...props
58
- }: React.ComponentProps<"div">): react_jsx_runtime66.JSX.Element;
58
+ }: React.ComponentProps<"div">): react_jsx_runtime271.JSX.Element;
59
59
  declare const cardFooterTone: {
60
60
  readonly default: "px-6 pb-6 [.border-t]:pt-6";
61
61
  readonly brand: "justify-center rounded-b-8 bg-brand-200 px-6 py-3 text-brand-800";
@@ -70,7 +70,7 @@ declare function CardFooter({
70
70
  }: React.ComponentProps<"div"> & {
71
71
  /** Footer fill. `brand`/`muted` render a full-width tinted band. */
72
72
  tone?: keyof typeof cardFooterTone;
73
- }): react_jsx_runtime66.JSX.Element;
73
+ }): react_jsx_runtime271.JSX.Element;
74
74
  //#endregion
75
75
  export { CardFooter as a, CardTitle as c, CardDescription as i, cardVariants as l, CardAction as n, CardHeader as o, CardContent as r, CardProps as s, Card as t };
76
76
  //# sourceMappingURL=index12.d.ts.map