@cratis/components 4.21.0 → 4.22.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 (269) hide show
  1. package/MIGRATION.md +3 -3
  2. package/compat-manifest.json +16 -16
  3. package/dist/esm/Canvas/Canvas.d.ts +12 -81
  4. package/dist/esm/Canvas/Canvas.d.ts.map +1 -1
  5. package/dist/esm/Canvas/Canvas.js +83 -676
  6. package/dist/esm/Canvas/Canvas.js.map +1 -1
  7. package/dist/esm/Canvas/CanvasCaptureAttributes.d.ts +10 -0
  8. package/dist/esm/Canvas/CanvasCaptureAttributes.d.ts.map +1 -0
  9. package/dist/esm/Canvas/CanvasCaptureAttributes.js +4 -0
  10. package/dist/esm/Canvas/CanvasCaptureAttributes.js.map +1 -0
  11. package/dist/esm/Canvas/CanvasContext.d.ts +9 -0
  12. package/dist/esm/Canvas/CanvasContext.d.ts.map +1 -0
  13. package/dist/esm/Canvas/CanvasContext.js +4 -0
  14. package/dist/esm/Canvas/CanvasContext.js.map +1 -0
  15. package/dist/esm/Canvas/CanvasHandle.d.ts +13 -0
  16. package/dist/esm/Canvas/CanvasHandle.d.ts.map +1 -0
  17. package/dist/esm/Canvas/CanvasHandle.js +4 -0
  18. package/dist/esm/Canvas/CanvasHandle.js.map +1 -0
  19. package/dist/esm/Canvas/CanvasItem.js +4 -1
  20. package/dist/esm/Canvas/CanvasItem.js.map +1 -1
  21. package/dist/esm/Canvas/CanvasItemData.d.ts +10 -0
  22. package/dist/esm/Canvas/CanvasItemData.d.ts.map +1 -0
  23. package/dist/esm/Canvas/CanvasItemData.js +4 -0
  24. package/dist/esm/Canvas/CanvasItemData.js.map +1 -0
  25. package/dist/esm/Canvas/CanvasItemRegistryContext.d.ts +5 -0
  26. package/dist/esm/Canvas/CanvasItemRegistryContext.d.ts.map +1 -0
  27. package/dist/esm/Canvas/CanvasItemRegistryContext.js +6 -0
  28. package/dist/esm/Canvas/CanvasItemRegistryContext.js.map +1 -0
  29. package/dist/esm/Canvas/CanvasItemRegistryContextValue.d.ts +26 -0
  30. package/dist/esm/Canvas/CanvasItemRegistryContextValue.d.ts.map +1 -0
  31. package/dist/esm/Canvas/CanvasItemRegistryContextValue.js +4 -0
  32. package/dist/esm/Canvas/CanvasItemRegistryContextValue.js.map +1 -0
  33. package/dist/esm/Canvas/CanvasItemRegistryEntry.d.ts +19 -0
  34. package/dist/esm/Canvas/CanvasItemRegistryEntry.d.ts.map +1 -0
  35. package/dist/esm/Canvas/CanvasItemRegistryEntry.js +4 -0
  36. package/dist/esm/Canvas/CanvasItemRegistryEntry.js.map +1 -0
  37. package/dist/esm/Canvas/WebKitGestureEvent.d.ts +13 -0
  38. package/dist/esm/Canvas/WebKitGestureEvent.d.ts.map +1 -0
  39. package/dist/esm/Canvas/WebKitGestureEvent.js +4 -0
  40. package/dist/esm/Canvas/WebKitGestureEvent.js.map +1 -0
  41. package/dist/esm/Canvas/canvasEasing.d.ts +8 -0
  42. package/dist/esm/Canvas/canvasEasing.d.ts.map +1 -0
  43. package/dist/esm/Canvas/canvasEasing.js +8 -0
  44. package/dist/esm/Canvas/canvasEasing.js.map +1 -0
  45. package/dist/esm/Canvas/canvasGestureTuning.d.ts +6 -0
  46. package/dist/esm/Canvas/canvasGestureTuning.d.ts.map +1 -0
  47. package/dist/esm/Canvas/canvasGestureTuning.js +7 -0
  48. package/dist/esm/Canvas/canvasGestureTuning.js.map +1 -0
  49. package/dist/esm/Canvas/index.js +2 -1
  50. package/dist/esm/Canvas/index.js.map +1 -1
  51. package/dist/esm/Canvas/shapes/Region/Region.js +4 -1
  52. package/dist/esm/Canvas/shapes/Region/Region.js.map +1 -1
  53. package/dist/esm/Canvas/useCanvasCamera.d.ts +37 -0
  54. package/dist/esm/Canvas/useCanvasCamera.d.ts.map +1 -0
  55. package/dist/esm/Canvas/useCanvasCamera.js +79 -0
  56. package/dist/esm/Canvas/useCanvasCamera.js.map +1 -0
  57. package/dist/esm/Canvas/useCanvasItemRegistry.d.ts +14 -0
  58. package/dist/esm/Canvas/useCanvasItemRegistry.d.ts.map +1 -0
  59. package/dist/esm/Canvas/useCanvasItemRegistry.js +59 -0
  60. package/dist/esm/Canvas/useCanvasItemRegistry.js.map +1 -0
  61. package/dist/esm/Canvas/useCanvasNavigation.d.ts +36 -0
  62. package/dist/esm/Canvas/useCanvasNavigation.d.ts.map +1 -0
  63. package/dist/esm/Canvas/useCanvasNavigation.js +186 -0
  64. package/dist/esm/Canvas/useCanvasNavigation.js.map +1 -0
  65. package/dist/esm/Canvas/useCanvasPointerGestures.d.ts +34 -0
  66. package/dist/esm/Canvas/useCanvasPointerGestures.d.ts.map +1 -0
  67. package/dist/esm/Canvas/useCanvasPointerGestures.js +178 -0
  68. package/dist/esm/Canvas/useCanvasPointerGestures.js.map +1 -0
  69. package/dist/esm/Canvas/useCanvasWheelZoom.d.ts +23 -0
  70. package/dist/esm/Canvas/useCanvasWheelZoom.d.ts.map +1 -0
  71. package/dist/esm/Canvas/useCanvasWheelZoom.js +146 -0
  72. package/dist/esm/Canvas/useCanvasWheelZoom.js.map +1 -0
  73. package/dist/esm/Canvas/useLatestRef.d.ts +8 -0
  74. package/dist/esm/Canvas/useLatestRef.d.ts.map +1 -0
  75. package/dist/esm/Canvas/useLatestRef.js +12 -0
  76. package/dist/esm/Canvas/useLatestRef.js.map +1 -0
  77. package/dist/esm/Canvas/usePixiApplication.d.ts +32 -0
  78. package/dist/esm/Canvas/usePixiApplication.d.ts.map +1 -0
  79. package/dist/esm/Canvas/usePixiApplication.js +92 -0
  80. package/dist/esm/Canvas/usePixiApplication.js.map +1 -0
  81. package/dist/esm/Canvas/usePixiItems.d.ts +19 -0
  82. package/dist/esm/Canvas/usePixiItems.d.ts.map +1 -0
  83. package/dist/esm/Canvas/usePixiItems.js +49 -0
  84. package/dist/esm/Canvas/usePixiItems.js.map +1 -0
  85. package/dist/esm/Chat/ChatSidebar.d.ts.map +1 -1
  86. package/dist/esm/Chat/ChatSidebar.js +1 -1
  87. package/dist/esm/Chat/ChatSidebar.js.map +1 -1
  88. package/dist/esm/ClassNames/classNames.d.ts +7 -0
  89. package/dist/esm/ClassNames/classNames.d.ts.map +1 -0
  90. package/dist/esm/ClassNames/classNames.js +4 -0
  91. package/dist/esm/ClassNames/classNames.js.map +1 -0
  92. package/dist/esm/Common/Breadcrumbs.d.ts.map +1 -1
  93. package/dist/esm/Common/Breadcrumbs.js +1 -1
  94. package/dist/esm/Common/Breadcrumbs.js.map +1 -1
  95. package/dist/esm/Common/ComboBox.d.ts.map +1 -1
  96. package/dist/esm/Common/ComboBox.js +1 -1
  97. package/dist/esm/Common/ComboBox.js.map +1 -1
  98. package/dist/esm/Common/DatePickerInputImplementation.d.ts.map +1 -1
  99. package/dist/esm/Common/DatePickerInputImplementation.js +1 -1
  100. package/dist/esm/Common/DatePickerInputImplementation.js.map +1 -1
  101. package/dist/esm/Common/NumberInput.d.ts.map +1 -1
  102. package/dist/esm/Common/NumberInput.js +1 -1
  103. package/dist/esm/Common/NumberInput.js.map +1 -1
  104. package/dist/esm/Common/Tabs.d.ts.map +1 -1
  105. package/dist/esm/Common/Tabs.js +1 -1
  106. package/dist/esm/Common/Tabs.js.map +1 -1
  107. package/dist/esm/Common/TagGroup.d.ts.map +1 -1
  108. package/dist/esm/Common/TagGroup.js +1 -1
  109. package/dist/esm/Common/TagGroup.js.map +1 -1
  110. package/dist/esm/Common/ToggleGroup.d.ts.map +1 -1
  111. package/dist/esm/Common/ToggleGroup.js +1 -1
  112. package/dist/esm/Common/ToggleGroup.js.map +1 -1
  113. package/dist/esm/DataTables/ColumnFilterMenu.d.ts.map +1 -1
  114. package/dist/esm/DataTables/ColumnFilterMenu.js +1 -1
  115. package/dist/esm/DataTables/ColumnFilterMenu.js.map +1 -1
  116. package/dist/esm/DataTables/DataTableBody.d.ts +22 -0
  117. package/dist/esm/DataTables/DataTableBody.d.ts.map +1 -0
  118. package/dist/esm/DataTables/DataTableBody.js +10 -0
  119. package/dist/esm/DataTables/DataTableBody.js.map +1 -0
  120. package/dist/esm/DataTables/DataTableCore.d.ts +8 -48
  121. package/dist/esm/DataTables/DataTableCore.d.ts.map +1 -1
  122. package/dist/esm/DataTables/DataTableCore.js +50 -278
  123. package/dist/esm/DataTables/DataTableCore.js.map +1 -1
  124. package/dist/esm/DataTables/DataTableHeaderCell.d.ts +25 -0
  125. package/dist/esm/DataTables/DataTableHeaderCell.d.ts.map +1 -0
  126. package/dist/esm/DataTables/DataTableHeaderCell.js +26 -0
  127. package/dist/esm/DataTables/DataTableHeaderCell.js.map +1 -0
  128. package/dist/esm/DataTables/DataTableMessageOverrides.d.ts +12 -0
  129. package/dist/esm/DataTables/DataTableMessageOverrides.d.ts.map +1 -0
  130. package/dist/esm/DataTables/DataTableMessageOverrides.js +4 -0
  131. package/dist/esm/DataTables/DataTableMessageOverrides.js.map +1 -0
  132. package/dist/esm/DataTables/DataTableMessages.d.ts +12 -0
  133. package/dist/esm/DataTables/DataTableMessages.d.ts.map +1 -0
  134. package/dist/esm/DataTables/DataTableMessages.js +4 -0
  135. package/dist/esm/DataTables/DataTableMessages.js.map +1 -0
  136. package/dist/esm/DataTables/DataTableParts.d.ts +40 -0
  137. package/dist/esm/DataTables/DataTableParts.d.ts.map +1 -0
  138. package/dist/esm/DataTables/DataTableParts.js +4 -0
  139. package/dist/esm/DataTables/DataTableParts.js.map +1 -0
  140. package/dist/esm/DataTables/DataTableRow.d.ts +22 -0
  141. package/dist/esm/DataTables/DataTableRow.d.ts.map +1 -0
  142. package/dist/esm/DataTables/DataTableRow.js +25 -0
  143. package/dist/esm/DataTables/DataTableRow.js.map +1 -0
  144. package/dist/esm/DataTables/DataTableRowClickEvent.d.ts +8 -0
  145. package/dist/esm/DataTables/DataTableRowClickEvent.d.ts.map +1 -0
  146. package/dist/esm/DataTables/DataTableRowClickEvent.js +4 -0
  147. package/dist/esm/DataTables/DataTableRowClickEvent.js.map +1 -0
  148. package/dist/esm/DataTables/DataTableSearch.d.ts +13 -0
  149. package/dist/esm/DataTables/DataTableSearch.d.ts.map +1 -0
  150. package/dist/esm/DataTables/DataTableSearch.js +7 -0
  151. package/dist/esm/DataTables/DataTableSearch.js.map +1 -0
  152. package/dist/esm/DataTables/DataTableState.d.ts +18 -0
  153. package/dist/esm/DataTables/DataTableState.d.ts.map +1 -0
  154. package/dist/esm/DataTables/DataTableState.js +4 -0
  155. package/dist/esm/DataTables/DataTableState.js.map +1 -0
  156. package/dist/esm/DataTables/DataTableStateProps.d.ts +20 -0
  157. package/dist/esm/DataTables/DataTableStateProps.d.ts.map +1 -0
  158. package/dist/esm/DataTables/DataTableStateProps.js +4 -0
  159. package/dist/esm/DataTables/DataTableStateProps.js.map +1 -0
  160. package/dist/esm/DataTables/ProcessedRow.d.ts +8 -0
  161. package/dist/esm/DataTables/ProcessedRow.d.ts.map +1 -0
  162. package/dist/esm/DataTables/ProcessedRow.js +4 -0
  163. package/dist/esm/DataTables/ProcessedRow.js.map +1 -0
  164. package/dist/esm/DataTables/RowProcessingState.d.ts +17 -0
  165. package/dist/esm/DataTables/RowProcessingState.d.ts.map +1 -0
  166. package/dist/esm/DataTables/RowProcessingState.js +4 -0
  167. package/dist/esm/DataTables/RowProcessingState.js.map +1 -0
  168. package/dist/esm/DataTables/RowSelection.d.ts +19 -0
  169. package/dist/esm/DataTables/RowSelection.d.ts.map +1 -0
  170. package/dist/esm/DataTables/RowSelection.js +4 -0
  171. package/dist/esm/DataTables/RowSelection.js.map +1 -0
  172. package/dist/esm/DataTables/RowSelectionSource.d.ts +16 -0
  173. package/dist/esm/DataTables/RowSelectionSource.d.ts.map +1 -0
  174. package/dist/esm/DataTables/RowSelectionSource.js +4 -0
  175. package/dist/esm/DataTables/RowSelectionSource.js.map +1 -0
  176. package/dist/esm/DataTables/matchesFilterEntry.d.ts +15 -0
  177. package/dist/esm/DataTables/matchesFilterEntry.d.ts.map +1 -0
  178. package/dist/esm/DataTables/matchesFilterEntry.js +70 -0
  179. package/dist/esm/DataTables/matchesFilterEntry.js.map +1 -0
  180. package/dist/esm/DataTables/processRows.d.ts +10 -0
  181. package/dist/esm/DataTables/processRows.d.ts.map +1 -0
  182. package/dist/esm/DataTables/processRows.js +42 -0
  183. package/dist/esm/DataTables/processRows.js.map +1 -0
  184. package/dist/esm/DataTables/useDataTableMessages.d.ts +9 -0
  185. package/dist/esm/DataTables/useDataTableMessages.d.ts.map +1 -0
  186. package/dist/esm/DataTables/useDataTableMessages.js +33 -0
  187. package/dist/esm/DataTables/useDataTableMessages.js.map +1 -0
  188. package/dist/esm/DataTables/useDataTableState.d.ts +10 -0
  189. package/dist/esm/DataTables/useDataTableState.d.ts.map +1 -0
  190. package/dist/esm/DataTables/useDataTableState.js +19 -0
  191. package/dist/esm/DataTables/useDataTableState.js.map +1 -0
  192. package/dist/esm/DataTables/useRowSelection.d.ts +9 -0
  193. package/dist/esm/DataTables/useRowSelection.d.ts.map +1 -0
  194. package/dist/esm/DataTables/useRowSelection.js +87 -0
  195. package/dist/esm/DataTables/useRowSelection.js.map +1 -0
  196. package/dist/esm/DataTables/valueAtPath.d.ts +10 -0
  197. package/dist/esm/DataTables/valueAtPath.d.ts.map +1 -0
  198. package/dist/esm/DataTables/valueAtPath.js +18 -0
  199. package/dist/esm/DataTables/valueAtPath.js.map +1 -0
  200. package/dist/esm/Dialogs/DialogImplementation.d.ts.map +1 -1
  201. package/dist/esm/Dialogs/DialogImplementation.js +1 -1
  202. package/dist/esm/Dialogs/DialogImplementation.js.map +1 -1
  203. package/dist/esm/Display/Message.d.ts +8 -1
  204. package/dist/esm/Display/Message.d.ts.map +1 -1
  205. package/dist/esm/Display/Message.js +1 -1
  206. package/dist/esm/Display/Message.js.map +1 -1
  207. package/dist/esm/Dropdown/DropdownImplementation.d.ts.map +1 -1
  208. package/dist/esm/Dropdown/DropdownImplementation.js +1 -1
  209. package/dist/esm/Dropdown/DropdownImplementation.js.map +1 -1
  210. package/dist/esm/Notifications/Toaster.d.ts.map +1 -1
  211. package/dist/esm/Notifications/Toaster.js +1 -1
  212. package/dist/esm/Notifications/Toaster.js.map +1 -1
  213. package/dist/esm/PivotViewer/components/PivotCanvas.d.ts +7 -50
  214. package/dist/esm/PivotViewer/components/PivotCanvas.d.ts.map +1 -1
  215. package/dist/esm/PivotViewer/components/PivotCanvas.js +34 -433
  216. package/dist/esm/PivotViewer/components/PivotCanvas.js.map +1 -1
  217. package/dist/esm/PivotViewer/components/PivotCanvasProps.d.ts +51 -0
  218. package/dist/esm/PivotViewer/components/PivotCanvasProps.d.ts.map +1 -0
  219. package/dist/esm/PivotViewer/components/PivotCanvasProps.js +4 -0
  220. package/dist/esm/PivotViewer/components/PivotCanvasProps.js.map +1 -0
  221. package/dist/esm/PivotViewer/components/pivot/PivotRenderContext.d.ts +16 -0
  222. package/dist/esm/PivotViewer/components/pivot/PivotRenderContext.d.ts.map +1 -0
  223. package/dist/esm/PivotViewer/components/pivot/PivotRenderContext.js +4 -0
  224. package/dist/esm/PivotViewer/components/pivot/PivotRenderContext.js.map +1 -0
  225. package/dist/esm/PivotViewer/components/pivot/PivotStage.d.ts +19 -0
  226. package/dist/esm/PivotViewer/components/pivot/PivotStage.d.ts.map +1 -0
  227. package/dist/esm/PivotViewer/components/pivot/PivotStage.js +4 -0
  228. package/dist/esm/PivotViewer/components/pivot/PivotStage.js.map +1 -0
  229. package/dist/esm/PivotViewer/components/pivot/PivotTransitionState.d.ts +21 -0
  230. package/dist/esm/PivotViewer/components/pivot/PivotTransitionState.d.ts.map +1 -0
  231. package/dist/esm/PivotViewer/components/pivot/PivotTransitionState.js +4 -0
  232. package/dist/esm/PivotViewer/components/pivot/PivotTransitionState.js.map +1 -0
  233. package/dist/esm/PivotViewer/components/pivot/asReactMouseEvent.d.ts +8 -0
  234. package/dist/esm/PivotViewer/components/pivot/asReactMouseEvent.d.ts.map +1 -0
  235. package/dist/esm/PivotViewer/components/pivot/asReactMouseEvent.js +6 -0
  236. package/dist/esm/PivotViewer/components/pivot/asReactMouseEvent.js.map +1 -0
  237. package/dist/esm/PivotViewer/components/pivot/sprites.js +1 -1
  238. package/dist/esm/PivotViewer/components/pivot/usePivotCardColors.d.ts +22 -0
  239. package/dist/esm/PivotViewer/components/pivot/usePivotCardColors.d.ts.map +1 -0
  240. package/dist/esm/PivotViewer/components/pivot/usePivotCardColors.js +25 -0
  241. package/dist/esm/PivotViewer/components/pivot/usePivotCardColors.js.map +1 -0
  242. package/dist/esm/PivotViewer/components/pivot/usePivotGroupBackgrounds.d.ts +8 -0
  243. package/dist/esm/PivotViewer/components/pivot/usePivotGroupBackgrounds.d.ts.map +1 -0
  244. package/dist/esm/PivotViewer/components/pivot/usePivotGroupBackgrounds.js +53 -0
  245. package/dist/esm/PivotViewer/components/pivot/usePivotGroupBackgrounds.js.map +1 -0
  246. package/dist/esm/PivotViewer/components/pivot/usePivotScrollSync.d.ts +8 -0
  247. package/dist/esm/PivotViewer/components/pivot/usePivotScrollSync.d.ts.map +1 -0
  248. package/dist/esm/PivotViewer/components/pivot/usePivotScrollSync.js +100 -0
  249. package/dist/esm/PivotViewer/components/pivot/usePivotScrollSync.js.map +1 -0
  250. package/dist/esm/PivotViewer/components/pivot/usePivotSelectionHighlight.d.ts +7 -0
  251. package/dist/esm/PivotViewer/components/pivot/usePivotSelectionHighlight.d.ts.map +1 -0
  252. package/dist/esm/PivotViewer/components/pivot/usePivotSelectionHighlight.js +35 -0
  253. package/dist/esm/PivotViewer/components/pivot/usePivotSelectionHighlight.js.map +1 -0
  254. package/dist/esm/PivotViewer/components/pivot/usePivotSpriteSync.d.ts +8 -0
  255. package/dist/esm/PivotViewer/components/pivot/usePivotSpriteSync.d.ts.map +1 -0
  256. package/dist/esm/PivotViewer/components/pivot/usePivotSpriteSync.js +123 -0
  257. package/dist/esm/PivotViewer/components/pivot/usePivotSpriteSync.js.map +1 -0
  258. package/dist/esm/PivotViewer/components/pivot/usePivotStage.d.ts +21 -0
  259. package/dist/esm/PivotViewer/components/pivot/usePivotStage.d.ts.map +1 -0
  260. package/dist/esm/PivotViewer/components/pivot/usePivotStage.js +171 -0
  261. package/dist/esm/PivotViewer/components/pivot/usePivotStage.js.map +1 -0
  262. package/dist/esm/PivotViewer/components/pivot/usePivotTransitionState.d.ts +13 -0
  263. package/dist/esm/PivotViewer/components/pivot/usePivotTransitionState.d.ts.map +1 -0
  264. package/dist/esm/PivotViewer/components/pivot/usePivotTransitionState.js +31 -0
  265. package/dist/esm/PivotViewer/components/pivot/usePivotTransitionState.js.map +1 -0
  266. package/dist/esm/TimeMachine/EventsView.d.ts.map +1 -1
  267. package/dist/esm/TimeMachine/EventsView.js +1 -1
  268. package/dist/esm/TimeMachine/EventsView.js.map +1 -1
  269. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCanvasWheelZoom.js","sources":["../../../Canvas/useCanvasWheelZoom.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useCallback, useEffect, type RefObject } from 'react';\nimport { ZOOM_INTENSITY } from './canvasGestureTuning';\nimport { isWithinScrollableContent } from './isWithinScrollableContent';\nimport type { PointerPosition } from './pinchGesture';\nimport type { WebKitGestureEvent } from './WebKitGestureEvent';\n\n/** The camera state and operations {@link useCanvasWheelZoom} drives. */\nexport interface CanvasWheelZoomOptions {\n containerRef: RefObject<HTMLDivElement | null>;\n animationFrameRef: RefObject<number | null>;\n panRef: RefObject<{ x: number; y: number }>;\n /** Touch pointers currently down; a touch pinch owns zooming while any are. */\n touchPointersRef: RefObject<Map<number, PointerPosition>>;\n zoomTowards: (focusX: number, focusY: number, factor: number) => void;\n noteGestureActivity: () => void;\n scheduleTransformApply: () => void;\n}\n\n/**\n * Wheel pan, Ctrl/Cmd+wheel zoom, and Safari's trackpad gesture events, on the canvas and for\n * floating content over it, without letting the browser zoom the page.\n * @param options The container, camera state and operations.\n */\nexport const useCanvasWheelZoom = ({\n containerRef,\n animationFrameRef,\n panRef,\n touchPointersRef,\n zoomTowards,\n noteGestureActivity,\n scheduleTransformApply,\n}: CanvasWheelZoomOptions) => {\n // Wheel: pan (scroll) or zoom (Ctrl+scroll / pinch)\n const handleWheel = useCallback(\n (e: WheelEvent) => {\n const container = containerRef.current;\n if (!container) return;\n\n // A plain scroll/trackpad gesture landing over a scrollable overlay (a chat's message list\n // and similar) scrolls that content instead of panning the board underneath it. A zoom\n // gesture (ctrl/cmd) always wins — pinch-to-zoom over a chat\n // panel is still a zoom, not a captured scroll.\n if (\n !(e.ctrlKey || e.metaKey) &&\n isWithinScrollableContent(e.target, container)\n )\n return;\n\n e.preventDefault();\n\n // A fresh gesture always wins over a still-coasting one from the last touch pan.\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n\n if (e.ctrlKey || e.metaKey) {\n zoomTowards(mouseX, mouseY, Math.exp(-e.deltaY * ZOOM_INTENSITY));\n } else {\n panRef.current = {\n x: panRef.current.x - e.deltaX,\n y: panRef.current.y - e.deltaY,\n };\n noteGestureActivity();\n scheduleTransformApply();\n }\n },\n [\n zoomTowards,\n noteGestureActivity,\n scheduleTransformApply,\n animationFrameRef,\n containerRef,\n panRef,\n ],\n );\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n container.addEventListener('wheel', handleWheel, { passive: false });\n return () => container.removeEventListener('wheel', handleWheel);\n }, [handleWheel, containerRef]);\n\n // Safari/WebKit reports a trackpad pinch through its own non-standard gesture events —\n // including on iPadOS with a Magic Keyboard trackpad — separately from the wheel+ctrlKey path\n // above, which Safari never fires for a trackpad pinch. Left unhandled, Safari's default action\n // is to zoom the whole page instead of the canvas — but canceling that alone would swallow the\n // pinch entirely, so gesturechange also drives the same zoom-towards-focus the ctrl+wheel path\n // applies. A touchscreen pinch fires these gesture events too, alongside the pointer events the\n // touch path already zooms from — with touch pointers down, this handler only cancels the page\n // zoom and leaves the zooming to the touch path. The events don't exist outside WebKit, so all\n // of this is a no-op everywhere else.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let lastScale = 1;\n const handleGestureStart = (event: Event) => {\n event.preventDefault();\n lastScale = (event as WebKitGestureEvent).scale || 1;\n };\n const handleGestureChange = (event: Event) => {\n event.preventDefault();\n if (touchPointersRef.current.size > 0) return;\n\n const gesture = event as WebKitGestureEvent;\n if (!gesture.scale || !lastScale) return;\n\n const rect = container.getBoundingClientRect();\n zoomTowards(\n gesture.clientX - rect.left,\n gesture.clientY - rect.top,\n gesture.scale / lastScale,\n );\n lastScale = gesture.scale;\n };\n const handleGestureEnd = (event: Event) => event.preventDefault();\n\n // Explicitly non-passive: WebKit is free to treat an options-less gesture listener as\n // passive, silently ignoring preventDefault() — which would zoom the browser page instead\n // of the canvas on an iPad Magic Keyboard trackpad.\n container.addEventListener('gesturestart', handleGestureStart, {\n passive: false,\n });\n container.addEventListener('gesturechange', handleGestureChange, {\n passive: false,\n });\n container.addEventListener('gestureend', handleGestureEnd, { passive: false });\n return () => {\n container.removeEventListener('gesturestart', handleGestureStart);\n container.removeEventListener('gesturechange', handleGestureChange);\n container.removeEventListener('gestureend', handleGestureEnd);\n };\n }, [zoomTowards, containerRef, touchPointersRef]);\n\n // The two handlers above only ever see events that bubble through the canvas surface's own DOM\n // subtree — but a toolbar, panel, or minimap floating over the canvas is frequently portalled to\n // document.body (or otherwise rendered as a sibling, not a descendant), so a pinch or Ctrl/Cmd+\n // wheel with the cursor sitting over one of those never reaches the listeners above at all, and\n // the browser is free to zoom the whole page instead. Listen at the window level too, and go\n // purely by screen position — no matter what element actually receives the\n // event, if it lands within the canvas's own rectangle the browser's native zoom is canceled.\n // For events whose target sits inside the canvas subtree this only cancels the browser zoom —\n // the container's own listeners drive the canvas zoom, so applying it here too would double up.\n // For a pinch whose target is a portalled sibling (never reaching the container listeners), it\n // also drives the same zoom-towards-focus, so a pinch over a floating panel zooms the board\n // instead of being swallowed after the browser zoom is canceled.\n useEffect(() => {\n const isWithinCanvas = (x: number, y: number) => {\n const rect = containerRef.current?.getBoundingClientRect();\n return (\n !!rect &&\n x >= rect.left &&\n x <= rect.right &&\n y >= rect.top &&\n y <= rect.bottom\n );\n };\n const reachesContainerListeners = (event: Event) =>\n event.target instanceof Node &&\n !!containerRef.current?.contains(event.target);\n const handleWindowWheel = (event: WheelEvent) => {\n if (\n (event.ctrlKey || event.metaKey) &&\n isWithinCanvas(event.clientX, event.clientY)\n ) {\n event.preventDefault();\n }\n };\n\n let lastScale = 1;\n const handleWindowGestureStart = (event: Event) => {\n const gesture = event as WebKitGestureEvent;\n if (!isWithinCanvas(gesture.clientX, gesture.clientY)) return;\n event.preventDefault();\n lastScale = gesture.scale || 1;\n };\n const handleWindowGestureChange = (event: Event) => {\n const gesture = event as WebKitGestureEvent;\n if (!isWithinCanvas(gesture.clientX, gesture.clientY)) return;\n event.preventDefault();\n if (reachesContainerListeners(event)) return;\n if (touchPointersRef.current.size > 0) return;\n if (!gesture.scale || !lastScale) return;\n\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n zoomTowards(\n gesture.clientX - rect.left,\n gesture.clientY - rect.top,\n gesture.scale / lastScale,\n );\n lastScale = gesture.scale;\n };\n const handleWindowGestureEnd = (event: Event) => {\n const gesture = event as WebKitGestureEvent;\n if (isWithinCanvas(gesture.clientX, gesture.clientY)) event.preventDefault();\n };\n\n // Non-passive everywhere: WebKit treating any of these as passive is what lets the page\n // zoom through, and window-level listeners are exactly where it is most inclined to.\n window.addEventListener('wheel', handleWindowWheel, { passive: false });\n window.addEventListener('gesturestart', handleWindowGestureStart, {\n passive: false,\n });\n window.addEventListener('gesturechange', handleWindowGestureChange, {\n passive: false,\n });\n window.addEventListener('gestureend', handleWindowGestureEnd, { passive: false });\n return () => {\n window.removeEventListener('wheel', handleWindowWheel);\n window.removeEventListener('gesturestart', handleWindowGestureStart);\n window.removeEventListener('gesturechange', handleWindowGestureChange);\n window.removeEventListener('gestureend', handleWindowGestureEnd);\n };\n }, [zoomTowards, containerRef, touchPointersRef]);\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A ref that follows the latest value, updated after each commit, so long-lived event handlers
3
+ * read current callbacks without being re-bound.
4
+ * @param value The value to follow.
5
+ * @returns The ref.
6
+ */
7
+ export declare const useLatestRef: <TValue>(value: TValue) => import("react").RefObject<TValue>;
8
+ //# sourceMappingURL=useLatestRef.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLatestRef.d.ts","sourceRoot":"","sources":["../../../Canvas/useLatestRef.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,sCAMjD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { useRef, useEffect } from 'react';
2
+
3
+ const useLatestRef = (value) => {
4
+ const ref = useRef(value);
5
+ useEffect(() => {
6
+ ref.current = value;
7
+ }, [value]);
8
+ return ref;
9
+ };
10
+
11
+ export { useLatestRef };
12
+ //# sourceMappingURL=useLatestRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLatestRef.js","sources":["../../../Canvas/useLatestRef.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef } from 'react';\n\n/**\n * A ref that follows the latest value, updated after each commit, so long-lived event handlers\n * read current callbacks without being re-bound.\n * @param value The value to follow.\n * @returns The ref.\n */\nexport const useLatestRef = <TValue>(value: TValue) => {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref;\n};\n"],"names":[],"mappings":";;AAWO,MAAM,YAAY,GAAG,CAAS,KAAa,KAAI;AAClD,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;IACzB,SAAS,CAAC,MAAK;AACX,QAAA,GAAG,CAAC,OAAO,GAAG,KAAK;AACvB,IAAA,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AACX,IAAA,OAAO,GAAG;AACd;;"}
@@ -0,0 +1,32 @@
1
+ import { type RefObject } from 'react';
2
+ import * as PIXI from 'pixi.js';
3
+ import type { CanvasContext } from './CanvasContext.js';
4
+ /** What {@link usePixiApplication} renders into and reports to. */
5
+ export interface PixiApplicationOptions {
6
+ /** The element the Pixi canvas is appended to and sized from. */
7
+ containerRef: RefObject<HTMLDivElement | null>;
8
+ /** The camera pan the world starts at. */
9
+ panRef: RefObject<{
10
+ x: number;
11
+ y: number;
12
+ }>;
13
+ /** The camera zoom the world starts at. */
14
+ zoomRef: RefObject<number>;
15
+ /** Receives the application once it is initialized. */
16
+ onReadyRef: RefObject<((context: CanvasContext) => void) | undefined>;
17
+ /** The capture marker attribute placed on the Pixi canvas, if any. */
18
+ captureLayer?: string;
19
+ }
20
+ /**
21
+ * Creates the Pixi application once, keeps it sized to its container, and renders on demand.
22
+ * @param options The container, camera and callbacks.
23
+ * @returns The application, its world, the item sprites, whether it is ready, and a render function.
24
+ */
25
+ export declare const usePixiApplication: ({ containerRef, panRef, zoomRef, onReadyRef, captureLayer, }: PixiApplicationOptions) => {
26
+ appRef: RefObject<PIXI.Application<PIXI.Renderer> | null>;
27
+ worldRef: RefObject<PIXI.Container<PIXI.ContainerChild> | null>;
28
+ spritesRef: RefObject<Map<string, PIXI.Container<PIXI.ContainerChild>>>;
29
+ pixiReady: boolean;
30
+ render: () => void;
31
+ };
32
+ //# sourceMappingURL=usePixiApplication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePixiApplication.d.ts","sourceRoot":"","sources":["../../../Canvas/usePixiApplication.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAiB,CAAC;AAErD,mEAAmE;AACnE,MAAM,WAAW,sBAAsB;IACnC,iEAAiE;IACjE,YAAY,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,0CAA0C;IAC1C,MAAM,EAAE,SAAS,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,2CAA2C;IAC3C,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC3B,uDAAuD;IACvD,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;IACtE,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,iEAM5B,sBAAsB;;;;;;CAiHxB,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { useRef, useState, useCallback, useEffect } from 'react';
2
+ import * as PIXI from 'pixi.js';
3
+
4
+ const usePixiApplication = ({ containerRef, panRef, zoomRef, onReadyRef, captureLayer, }) => {
5
+ const appRef = useRef(null);
6
+ const worldRef = useRef(null);
7
+ const spritesRef = useRef(new Map());
8
+ const [pixiReady, setPixiReady] = useState(false);
9
+ const render = useCallback(() => {
10
+ const app = appRef.current;
11
+ if (!app)
12
+ return;
13
+ if ((worldRef.current?.children.length ?? 0) === 0)
14
+ return;
15
+ PIXI.Ticker.system.update();
16
+ app.renderer.render(app.stage);
17
+ }, []);
18
+ useEffect(() => {
19
+ const container = containerRef.current;
20
+ if (!container || appRef.current)
21
+ return;
22
+ let mounted = true;
23
+ (async () => {
24
+ const rect = container.getBoundingClientRect();
25
+ const width = rect.width > 0 ? rect.width : container.clientWidth || 800;
26
+ const height = rect.height > 0 ? rect.height : container.clientHeight || 600;
27
+ const app = new PIXI.Application();
28
+ await app.init({
29
+ backgroundAlpha: 0,
30
+ antialias: true,
31
+ autoDensity: true,
32
+ resolution: window.devicePixelRatio || 1,
33
+ width,
34
+ height,
35
+ autoStart: false,
36
+ });
37
+ if (!mounted || !containerRef.current) {
38
+ app.destroy(true, { children: true });
39
+ return;
40
+ }
41
+ appRef.current = app;
42
+ const world = new PIXI.Container();
43
+ world.position.set(panRef.current.x, panRef.current.y);
44
+ world.scale.set(zoomRef.current);
45
+ app.stage.addChild(world);
46
+ worldRef.current = world;
47
+ const canvas = app.canvas;
48
+ canvas.style.display = 'block';
49
+ canvas.style.touchAction = 'none';
50
+ containerRef.current.appendChild(canvas);
51
+ setPixiReady(true);
52
+ app.renderer.render(app.stage);
53
+ PIXI.Ticker.system.stop();
54
+ onReadyRef.current?.({ app, world });
55
+ })();
56
+ return () => {
57
+ mounted = false;
58
+ if (appRef.current) {
59
+ appRef.current.destroy(true, { children: true });
60
+ appRef.current = null;
61
+ worldRef.current = null;
62
+ }
63
+ spritesRef.current.clear();
64
+ };
65
+ }, [containerRef, onReadyRef, panRef, zoomRef]);
66
+ useEffect(() => {
67
+ const canvas = appRef.current?.canvas;
68
+ const attribute = captureLayer;
69
+ if (!canvas || !attribute)
70
+ return;
71
+ canvas.setAttribute(attribute, 'true');
72
+ return () => canvas.removeAttribute(attribute);
73
+ }, [pixiReady, captureLayer]);
74
+ useEffect(() => {
75
+ const container = containerRef.current;
76
+ if (!container)
77
+ return;
78
+ const observer = new ResizeObserver(() => {
79
+ const app = appRef.current;
80
+ if (!app)
81
+ return;
82
+ app.renderer.resize(container.clientWidth, container.clientHeight);
83
+ render();
84
+ });
85
+ observer.observe(container);
86
+ return () => observer.disconnect();
87
+ }, [render, containerRef]);
88
+ return { appRef, worldRef, spritesRef, pixiReady, render };
89
+ };
90
+
91
+ export { usePixiApplication };
92
+ //# sourceMappingURL=usePixiApplication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePixiApplication.js","sources":["../../../Canvas/usePixiApplication.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\nimport * as PIXI from 'pixi.js';\nimport type { CanvasContext } from './CanvasContext';\n\n/** What {@link usePixiApplication} renders into and reports to. */\nexport interface PixiApplicationOptions {\n /** The element the Pixi canvas is appended to and sized from. */\n containerRef: RefObject<HTMLDivElement | null>;\n /** The camera pan the world starts at. */\n panRef: RefObject<{ x: number; y: number }>;\n /** The camera zoom the world starts at. */\n zoomRef: RefObject<number>;\n /** Receives the application once it is initialized. */\n onReadyRef: RefObject<((context: CanvasContext) => void) | undefined>;\n /** The capture marker attribute placed on the Pixi canvas, if any. */\n captureLayer?: string;\n}\n\n/**\n * Creates the Pixi application once, keeps it sized to its container, and renders on demand.\n * @param options The container, camera and callbacks.\n * @returns The application, its world, the item sprites, whether it is ready, and a render function.\n */\nexport const usePixiApplication = ({\n containerRef,\n panRef,\n zoomRef,\n onReadyRef,\n captureLayer,\n}: PixiApplicationOptions) => {\n const appRef = useRef<PIXI.Application | null>(null);\n const worldRef = useRef<PIXI.Container | null>(null);\n const spritesRef = useRef<Map<string, PIXI.Container>>(new Map());\n const [pixiReady, setPixiReady] = useState(false);\n\n const render = useCallback(() => {\n const app = appRef.current;\n if (!app) return;\n // Boards that only use the HTML overlay leave the PIXI world empty — skip the per-frame\n // GPU pass entirely rather than clearing and presenting an empty stage on every gesture frame.\n if ((worldRef.current?.children.length ?? 0) === 0) return;\n // The system ticker is stopped (see the init effect below) — drive pixi's scheduled\n // housekeeping (texture GC and friends) from the frames that actually render instead.\n PIXI.Ticker.system.update();\n app.renderer.render(app.stage);\n }, []);\n\n // Initialize PIXI once\n useEffect(() => {\n const container = containerRef.current;\n if (!container || appRef.current) return;\n\n let mounted = true;\n\n (async () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width > 0 ? rect.width : container.clientWidth || 800;\n const height = rect.height > 0 ? rect.height : container.clientHeight || 600;\n\n const app = new PIXI.Application();\n await app.init({\n // Transparent clear: the body carries the surface color and the user-selected\n // appearance background, which must show through the canvas like everywhere else.\n backgroundAlpha: 0,\n antialias: true,\n autoDensity: true,\n resolution: window.devicePixelRatio || 1,\n width,\n height,\n autoStart: false,\n });\n\n if (!mounted || !containerRef.current) {\n app.destroy(true, { children: true });\n return;\n }\n\n appRef.current = app;\n\n // World container - all items live here; zoom/pan applied via transform\n const world = new PIXI.Container();\n world.position.set(panRef.current.x, panRef.current.y);\n world.scale.set(zoomRef.current);\n app.stage.addChild(world);\n worldRef.current = world;\n\n const canvas = app.canvas as HTMLCanvasElement;\n canvas.style.display = 'block';\n canvas.style.touchAction = 'none';\n containerRef.current.appendChild(canvas);\n\n setPixiReady(true);\n app.renderer.render(app.stage);\n\n // Initializing a renderer hooks pixi's SchedulerSystem onto the auto-starting system\n // ticker, which then runs a requestAnimationFrame loop forever even though nothing here\n // renders from a ticker (autoStart is false and every render is explicit) — one of the\n // permanent loops that kept an idle canvas busy. Stop it after every init, because each\n // new renderer restarts it; render() drives the scheduled\n // housekeeping instead.\n PIXI.Ticker.system.stop();\n\n onReadyRef.current?.({ app, world });\n })();\n\n return () => {\n mounted = false;\n if (appRef.current) {\n appRef.current.destroy(true, { children: true });\n appRef.current = null;\n worldRef.current = null;\n }\n spritesRef.current.clear();\n };\n }, [containerRef, onReadyRef, panRef, zoomRef]); // intentional: PIXI init runs exactly once\n\n // Products with a capture/compositor pipeline can mark the Pixi canvas without making that\n // provider a Components dependency. Keep the marker synchronized if product configuration changes.\n useEffect(() => {\n const canvas = appRef.current?.canvas as HTMLCanvasElement | undefined;\n const attribute = captureLayer;\n if (!canvas || !attribute) return;\n canvas.setAttribute(attribute, 'true');\n return () => canvas.removeAttribute(attribute);\n }, [pixiReady, captureLayer]);\n\n // Handle container resize\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const observer = new ResizeObserver(() => {\n const app = appRef.current;\n if (!app) return;\n app.renderer.resize(container.clientWidth, container.clientHeight);\n render();\n });\n observer.observe(container);\n return () => observer.disconnect();\n }, [render, containerRef]);\n\n return { appRef, worldRef, spritesRef, pixiReady, render };\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type RefObject } from 'react';
2
+ import * as PIXI from 'pixi.js';
3
+ import type { CanvasItemData } from './CanvasItemData.js';
4
+ /** The Pixi world and the items {@link usePixiItems} keeps in sync. */
5
+ export interface PixiItemsOptions<T extends CanvasItemData> {
6
+ pixiReady: boolean;
7
+ appRef: RefObject<PIXI.Application | null>;
8
+ worldRef: RefObject<PIXI.Container | null>;
9
+ spritesRef: RefObject<Map<string, PIXI.Container>>;
10
+ items: T[];
11
+ renderItem?: (item: T) => PIXI.Container;
12
+ onItemPointerDownRef: RefObject<((item: T, event: PIXI.FederatedPointerEvent) => void) | undefined>;
13
+ }
14
+ /**
15
+ * Adds, moves and removes the Pixi containers for the items, rendering once after each change.
16
+ * @param options The world, sprites and items.
17
+ */
18
+ export declare const usePixiItems: <T extends CanvasItemData>({ pixiReady, appRef, worldRef, spritesRef, items, renderItem, onItemPointerDownRef, }: PixiItemsOptions<T>) => void;
19
+ //# sourceMappingURL=usePixiItems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePixiItems.d.ts","sourceRoot":"","sources":["../../../Canvas/usePixiItems.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAkB,CAAC;AAEvD,uEAAuE;AACvE,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,cAAc;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC3C,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC;IACzC,oBAAoB,EAAE,SAAS,CAC3B,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,qBAAqB,KAAK,IAAI,CAAC,GAAG,SAAS,CACrE,CAAC;CACL;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,cAAc,yFAQlD,gBAAgB,CAAC,CAAC,CAAC,SAmDrB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { useEffect } from 'react';
2
+
3
+ const usePixiItems = ({ pixiReady, appRef, worldRef, spritesRef, items, renderItem, onItemPointerDownRef, }) => {
4
+ useEffect(() => {
5
+ const world = worldRef.current;
6
+ if (!pixiReady || !world || !renderItem)
7
+ return;
8
+ const incoming = new Map(items.map((item) => [item.id, item]));
9
+ spritesRef.current.forEach((container, id) => {
10
+ if (!incoming.has(id)) {
11
+ world.removeChild(container);
12
+ container.destroy({ children: true });
13
+ spritesRef.current.delete(id);
14
+ }
15
+ });
16
+ items.forEach((item) => {
17
+ const existing = spritesRef.current.get(item.id);
18
+ if (existing) {
19
+ existing.position.set(item.x, item.y);
20
+ existing.removeAllListeners('pointerdown');
21
+ existing.on('pointerdown', (event) => {
22
+ onItemPointerDownRef.current?.(item, event);
23
+ });
24
+ }
25
+ else {
26
+ const container = renderItem(item);
27
+ container.position.set(item.x, item.y);
28
+ container.eventMode = 'static';
29
+ container.on('pointerdown', (event) => {
30
+ onItemPointerDownRef.current?.(item, event);
31
+ });
32
+ world.addChild(container);
33
+ spritesRef.current.set(item.id, container);
34
+ }
35
+ });
36
+ appRef.current?.renderer.render(appRef.current.stage);
37
+ }, [
38
+ pixiReady,
39
+ items,
40
+ renderItem,
41
+ appRef,
42
+ onItemPointerDownRef,
43
+ spritesRef,
44
+ worldRef,
45
+ ]);
46
+ };
47
+
48
+ export { usePixiItems };
49
+ //# sourceMappingURL=usePixiItems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePixiItems.js","sources":["../../../Canvas/usePixiItems.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, type RefObject } from 'react';\nimport * as PIXI from 'pixi.js';\nimport type { CanvasItemData } from './CanvasItemData';\n\n/** The Pixi world and the items {@link usePixiItems} keeps in sync. */\nexport interface PixiItemsOptions<T extends CanvasItemData> {\n pixiReady: boolean;\n appRef: RefObject<PIXI.Application | null>;\n worldRef: RefObject<PIXI.Container | null>;\n spritesRef: RefObject<Map<string, PIXI.Container>>;\n items: T[];\n renderItem?: (item: T) => PIXI.Container;\n onItemPointerDownRef: RefObject<\n ((item: T, event: PIXI.FederatedPointerEvent) => void) | undefined\n >;\n}\n\n/**\n * Adds, moves and removes the Pixi containers for the items, rendering once after each change.\n * @param options The world, sprites and items.\n */\nexport const usePixiItems = <T extends CanvasItemData>({\n pixiReady,\n appRef,\n worldRef,\n spritesRef,\n items,\n renderItem,\n onItemPointerDownRef,\n}: PixiItemsOptions<T>) => {\n // Sync items → PIXI containers\n useEffect(() => {\n const world = worldRef.current;\n if (!pixiReady || !world || !renderItem) return;\n\n const incoming = new Map(items.map((item) => [item.id, item]));\n\n // Remove deleted items\n spritesRef.current.forEach((container, id) => {\n if (!incoming.has(id)) {\n world.removeChild(container);\n container.destroy({ children: true });\n spritesRef.current.delete(id);\n }\n });\n\n // Add new items; update positions of existing ones\n items.forEach((item) => {\n const existing = spritesRef.current.get(item.id);\n if (existing) {\n existing.position.set(item.x, item.y);\n // Refresh handler so it always references the latest item object\n existing.removeAllListeners('pointerdown');\n existing.on('pointerdown', (event: PIXI.FederatedPointerEvent) => {\n onItemPointerDownRef.current?.(item, event);\n });\n } else {\n const container = renderItem(item);\n container.position.set(item.x, item.y);\n container.eventMode = 'static';\n container.on('pointerdown', (event: PIXI.FederatedPointerEvent) => {\n onItemPointerDownRef.current?.(item, event);\n });\n world.addChild(container);\n spritesRef.current.set(item.id, container);\n }\n });\n\n // Render directly (not via the empty-world-skipping render()) so removing the last item\n // still clears its pixels from the canvas.\n appRef.current?.renderer.render(appRef.current.stage);\n }, [\n pixiReady,\n items,\n renderItem,\n appRef,\n onItemPointerDownRef,\n spritesRef,\n worldRef,\n ]);\n};\n"],"names":[],"mappings":";;MAwBa,YAAY,GAAG,CAA2B,EACnD,SAAS,EACT,MAAM,EACN,QAAQ,EACR,UAAU,EACV,KAAK,EACL,UAAU,EACV,oBAAoB,GACF,KAAI;IAEtB,SAAS,CAAC,MAAK;AACX,QAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO;AAC9B,QAAA,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,UAAU;YAAE;QAEzC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QAG9D,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,KAAI;YACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AACnB,gBAAA,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC;gBAC5B,SAAS,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACrC,gBAAA,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC;AACJ,QAAA,CAAC,CAAC;AAGF,QAAA,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,KAAI;AACnB,YAAA,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,QAAQ,EAAE;AACV,gBAAA,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAErC,gBAAA,QAAQ,CAAC,kBAAkB,CAAC,aAAa,CAAC;gBAC1C,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,KAAiC,KAAI;oBAC7D,oBAAoB,CAAC,OAAO,GAAG,IAAI,EAAE,KAAK,CAAC;AAC/C,gBAAA,CAAC,CAAC;YACN;iBAAO;AACH,gBAAA,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC;AAClC,gBAAA,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACtC,gBAAA,SAAS,CAAC,SAAS,GAAG,QAAQ;gBAC9B,SAAS,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,KAAiC,KAAI;oBAC9D,oBAAoB,CAAC,OAAO,GAAG,IAAI,EAAE,KAAK,CAAC;AAC/C,gBAAA,CAAC,CAAC;AACF,gBAAA,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;gBACzB,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC;YAC9C;AACJ,QAAA,CAAC,CAAC;AAIF,QAAA,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;AACzD,IAAA,CAAC,EAAE;QACC,SAAS;QACT,KAAK;QACL,UAAU;QACV,MAAM;QACN,oBAAoB;QACpB,UAAU;QACV,QAAQ;AACX,KAAA,CAAC;AACN;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChatSidebar.d.ts","sourceRoot":"","sources":["../../../Chat/ChatSidebar.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatSidebar.d.ts","sourceRoot":"","sources":["../../../Chat/ChatSidebar.tsx"],"names":[],"mappings":"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"}
@@ -9,8 +9,8 @@ import { isTopicUnnamed } from './isTopicUnnamed.js';
9
9
  import { shouldRequestTopicName } from './shouldRequestTopicName.js';
10
10
  import { useCratisIcon } from '../configuration/useCratisIcon.js';
11
11
  import { unstable_useOverlayEnvironment } from '../renderer/RendererContext.js';
12
+ import { classNames } from '../ClassNames/classNames.js';
12
13
 
13
- const classNames = (...values) => values.filter(Boolean).join(' ');
14
14
  const BackIcon = () => (jsxs("svg", { width: '14', height: '14', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2.5', "aria-hidden": 'true', children: [jsx("line", { x1: '19', y1: '12', x2: '5', y2: '12' }), jsx("polyline", { points: '12 19 5 12 12 5' })] }));
15
15
  const ChatSidebar = ({ open, onClose, topics, messages, topicActions, renderHeaderActions, topicsStatus, messagesStatus, selectedTopicId, onTopicSelected, onStartTopic, onSendMessage, onRequestTopicName, isTopicUnnamed: isTopicUnnamed$1, position = 'right', width = '24rem', modal = false, labels, className, pt, ...conversation }) => {
16
16
  const icon = useCratisIcon();
@@ -1 +1 @@
1
- {"version":3,"file":"ChatSidebar.js","sources":["../../../Chat/ChatSidebar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Modal, ModalOverlay } from 'react-aria-components';\nimport type { ChatConversationLabels, ChatConversationProps } from './ChatConversation';\nimport { ChatConversation } from './ChatConversation';\nimport { sameChatIdentifier, type ChatIdentifier } from './ChatIdentifier';\nimport type { ChatMention } from './ChatMention';\nimport type { ChatMessage } from './ChatMessage';\nimport type { ChatTopic } from './ChatTopic';\nimport type { ChatTopicAction } from './ChatTopicAction';\nimport type { ChatStatus } from './ChatStatus';\nimport type { ChatTopicListLabels } from './ChatTopicList';\nimport { ChatTopicList } from './ChatTopicList';\nimport { isTopicUnnamed as defaultIsTopicUnnamed } from './isTopicUnnamed';\nimport { shouldRequestTopicName } from './shouldRequestTopicName';\nimport { useCratisIcon } from '../configuration/useCratisIcon';\nimport { unstable_useOverlayEnvironment } from '../renderer/RendererContext';\nimport type { ExactPartKeys } from '../types/ExactPartKeys';\nimport type { PartsOf } from '../types/parts';\n\ntype ChatSidebarPartAttributes<TElement> = HTMLAttributes<TElement> & {\n [attribute: `data-${string}`]: string | number | boolean | undefined;\n};\n\ntype ChatSidebarButtonAttributes = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n 'onClick' | 'type'\n>;\n\n/** Stable Cratis-owned parts for styling a {@link ChatSidebar}. */\nexport interface ChatSidebarParts {\n /** Viewport overlay layer the sidebar portals into — only paints/blocks when {@link ChatSidebarProps.modal} is true. */\n backdrop?: ChatSidebarPartAttributes<HTMLDivElement>;\n /** The sidebar panel itself. */\n root?: ChatSidebarPartAttributes<HTMLDivElement>;\n /** Header containing the back affordance, title, and close button. */\n header?: ChatSidebarPartAttributes<HTMLElement>;\n /** The topic list title, or the open topic's name. */\n title?: ChatSidebarPartAttributes<HTMLHeadingElement>;\n /** Back-to-topics button, present only while a topic is open. */\n back?: ChatSidebarButtonAttributes;\n /** Close button. */\n close?: ChatSidebarButtonAttributes;\n /** The topic list / conversation content region. */\n content?: ChatSidebarPartAttributes<HTMLDivElement>;\n}\n\nconst chatSidebarPartsMatchManifest: ExactPartKeys<\n ChatSidebarParts,\n PartsOf<'ChatSidebar'>\n> = true;\nvoid chatSidebarPartsMatchManifest;\n\n/** Overrides for every label the {@link ChatSidebar} and its children render. Any field left\n * unset falls back to a literal English default. */\nexport interface ChatSidebarLabels {\n /** The sidebar's title while the topic list is showing. Defaults to `'Topics'`. */\n topics?: string;\n\n /** Placeholder title for a topic that has not been named yet. Defaults to `'New topic'`. */\n unnamedTopic?: string;\n\n /** Tooltip/accessible label for the back-to-topics button. Defaults to `'Back to topics'`. */\n back?: string;\n\n /** Accessible label for the close button. Defaults to `'Close chat'`. */\n close?: string;\n\n /** Labels forwarded to the {@link ChatTopicList}. */\n topicList?: ChatTopicListLabels;\n\n /** Labels forwarded to the {@link ChatConversation}. */\n conversation?: ChatConversationLabels;\n}\n\n/**\n * Props for {@link ChatSidebar}.\n * @typeParam TMessage The host's message type — anything extending {@link ChatMessage}.\n * @typeParam TTopic The host's topic type — anything extending {@link ChatTopic}.\n */\nexport interface ChatSidebarProps<\n TMessage extends ChatMessage = ChatMessage,\n TTopic extends ChatTopic = ChatTopic,\n> extends Omit<\n ChatConversationProps<TMessage>,\n 'messages' | 'onSendMessage' | 'labels' | 'className' | 'status'\n> {\n /**\n * Renders host content in the header, between the title and the close button, for example a\n * rename control for the open topic. Nothing is rendered when it returns null or undefined.\n * @param openTopic The open topic, or undefined while the topic list is shown.\n * @returns What to render in the header.\n */\n renderHeaderActions?: (openTopic: TTopic | undefined) => ReactNode;\n\n /** Whether the sidebar is open. */\n open: boolean;\n\n /** Invoked when the sidebar asks to close — the host owns {@link open}, so closing means the host flips it. */\n onClose: () => void;\n\n /**\n * The topics, in any order. Hand this the array a live (observable) query delivers and the\n * sidebar re-renders as it changes.\n */\n topics: TTopic[];\n\n /**\n * The messages — either the whole chat or just the open topic's; the sidebar shows those of\n * the open topic by matching on `topicId` either way. Hand this the array a live\n * (observable) query delivers and the conversation re-renders as it changes.\n */\n messages: TMessage[];\n\n /** The host's actions to offer on each topic where they are available. The inherited `actions` prop applies only to messages. */\n topicActions?: ChatTopicAction<TTopic>[];\n\n /** Topic-list query display state. Defaults to ready when omitted. */\n topicsStatus?: ChatStatus;\n\n /** Conversation query display state. Defaults to ready when omitted. */\n messagesStatus?: ChatStatus;\n\n /**\n * The open topic, for hosts that own the selection themselves: an identifier opens that\n * topic's conversation, `null` shows the topic list, and leaving the prop unset lets the\n * sidebar keep the selection internally.\n */\n selectedTopicId?: ChatIdentifier | null;\n\n /**\n * Invoked when the open topic changes — a topic was opened (or just started), or the person\n * went back to the list.\n * @param topicId The identifier of the topic now open, or undefined for the list.\n * @param topic The topic itself, when it is known in {@link topics}.\n */\n onTopicSelected?: (topicId: ChatIdentifier | undefined, topic?: TTopic) => void;\n\n /**\n * Invoked when a new topic is asked for. Creating the topic is the host's business; answer\n * with its identifier (directly or through a promise) and the sidebar opens it, ready for\n * the first message. Omit to leave the new-topic affordance off.\n * @returns The identifier of the topic that was started, when the host created one.\n */\n onStartTopic?: () => ChatIdentifier | undefined | Promise<ChatIdentifier | undefined>;\n\n /**\n * Invoked when a message is sent, with the topic it belongs to, the trimmed body and who it\n * mentions. Everything else about persisting the message is the host's business.\n * @param topicId The identifier of the topic the message was sent in.\n * @param body The message text, mentions written into it as plain `@Name`.\n * @param mentions Who the body mentions.\n */\n onSendMessage: (\n topicId: ChatIdentifier,\n body: string,\n mentions: ChatMention[],\n ) => void;\n\n /**\n * Invoked when the very first message is sent in a topic that has no name yet — the host\n * asks its LLM (or whatever it prefers) for a good name and supplies it through the topic\n * data; until then the topic renders its pending placeholder. Not invoked again for later\n * messages, and never for a topic that already has a name.\n * @param topic The topic that needs a name.\n * @param firstMessageBody The message to derive the name from.\n */\n onRequestTopicName?: (topic: TTopic, firstMessageBody: string) => void;\n\n /**\n * Decides whether a topic counts as unnamed — see {@link ChatTopicListProps.isTopicUnnamed}.\n * @param topic The topic to check.\n * @returns True when the topic has no usable name yet.\n */\n isTopicUnnamed?: (topic: TTopic) => boolean;\n\n /** Which edge the sidebar opens from. Defaults to `'right'`. */\n position?: 'left' | 'right';\n\n /** The sidebar's width, any CSS length. Defaults to `'24rem'`. */\n width?: string;\n\n /**\n * Whether the sidebar is modal — a backdrop behind it, and dismissing by Escape or clicking\n * outside. Defaults to false: a chat lives *next to* the work, so it should not block it —\n * the background stays visible and interactive, and only the close/back affordances dismiss it.\n */\n modal?: boolean;\n\n /** Overrides for every label rendered. Unset fields fall back to literal English defaults. */\n labels?: ChatSidebarLabels;\n\n /** Additional class name for the sidebar's panel element. */\n className?: string;\n\n /** Cratis-owned per-part attributes. */\n pt?: ChatSidebarParts;\n}\n\nconst classNames = (...values: Array<string | undefined>) =>\n values.filter(Boolean).join(' ');\n\nconst BackIcon = () => (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2.5'\n aria-hidden='true'\n >\n <line x1='19' y1='12' x2='5' y2='12' />\n <polyline points='12 19 5 12 12 5' />\n </svg>\n);\n\n/**\n * A topic-based chat in a sidebar next to the view, built on Components' own overlay primitives\n * (React Aria internally, for accessible dismissal and focus handling). It opens on the topic\n * list; picking a topic (or starting a new one) slides into that conversation, with a back\n * affordance to the list. Everything about *data* is the host's: topics and messages come in as\n * arrays (hand it live query data and it stays current), sends and new topics go out as\n * callbacks, and when the first message lands in an unnamed topic the sidebar asks the host for\n * a name through {@link ChatSidebarProps.onRequestTopicName | onRequestTopicName} — rendering a\n * pending placeholder until the name arrives.\n */\nexport const ChatSidebar = <\n TMessage extends ChatMessage = ChatMessage,\n TTopic extends ChatTopic = ChatTopic,\n>({\n open,\n onClose,\n topics,\n messages,\n topicActions,\n renderHeaderActions,\n topicsStatus,\n messagesStatus,\n selectedTopicId,\n onTopicSelected,\n onStartTopic,\n onSendMessage,\n onRequestTopicName,\n isTopicUnnamed,\n position = 'right',\n width = '24rem',\n modal = false,\n labels,\n className,\n pt,\n ...conversation\n}: ChatSidebarProps<TMessage, TTopic>) => {\n const icon = useCratisIcon();\n const overlayEnvironment = unstable_useOverlayEnvironment();\n const [mounted, setMounted] = useState(false);\n const nonModalPanel = useRef<HTMLDivElement>(null);\n const [nonModalPhase, setNonModalPhase] = useState<\n 'closed' | 'entering' | 'open' | 'exiting'\n >('closed');\n\n useEffect(() => setMounted(true), []);\n useEffect(() => {\n setNonModalPhase((phase) =>\n open ? 'entering' : phase === 'closed' ? 'closed' : 'exiting',\n );\n }, [open]);\n const portalContainer = !modal && mounted && nonModalPhase !== 'closed'\n ? overlayEnvironment.getContainer()\n : null;\n useEffect(() => {\n if (nonModalPhase !== 'entering' && nonModalPhase !== 'exiting') return;\n if (!modal && (\n window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ||\n nonModalPanel.current?.getAnimations?.().length === 0\n )) {\n setNonModalPhase(nonModalPhase === 'entering' ? 'open' : 'closed');\n return;\n }\n const timeout = setTimeout(() => {\n setNonModalPhase(nonModalPhase === 'entering' ? 'open' : 'closed');\n }, 250);\n return () => clearTimeout(timeout);\n }, [modal, nonModalPhase, portalContainer]);\n\n const [internalSelectedId, setInternalSelectedId] = useState<\n ChatIdentifier | undefined\n >();\n const isControlled = selectedTopicId !== undefined;\n const openTopicId = isControlled\n ? (selectedTopicId ?? undefined)\n : internalSelectedId;\n const openTopic =\n openTopicId === undefined\n ? undefined\n : topics.find((topic) => sameChatIdentifier(topic.id, openTopicId));\n const unnamed = isTopicUnnamed ?? defaultIsTopicUnnamed;\n\n const select = (topicId: ChatIdentifier | undefined, topic?: TTopic) => {\n if (!isControlled) {\n setInternalSelectedId(topicId);\n }\n onTopicSelected?.(\n topicId,\n topic ??\n (topicId === undefined\n ? undefined\n : topics.find((candidate) =>\n sameChatIdentifier(candidate.id, topicId),\n )),\n );\n };\n\n const startTopic = async () => {\n const topicId = await onStartTopic?.();\n if (topicId !== undefined) {\n select(topicId);\n }\n };\n\n const openMessages =\n openTopicId === undefined\n ? []\n : messages.filter((message) =>\n sameChatIdentifier(message.topicId, openTopicId),\n );\n\n const send = (body: string, mentions: ChatMention[]) => {\n if (openTopicId === undefined) return;\n onSendMessage(openTopicId, body, mentions);\n if (\n openTopic &&\n shouldRequestTopicName(unnamed(openTopic), openMessages.length)\n ) {\n onRequestTopicName?.(openTopic, body);\n }\n };\n\n const title =\n openTopicId === undefined\n ? (labels?.topics ?? 'Topics')\n : openTopic && !unnamed(openTopic)\n ? openTopic.name\n : (labels?.unnamedTopic ?? 'New topic');\n const titleIsPending =\n openTopicId !== undefined && (!openTopic || unnamed(openTopic));\n\n const panel = (\n <>\n <header\n {...pt?.header}\n className={classNames(\n 'cratis-chat-sidebar__header',\n pt?.header?.className,\n )}\n data-cratis-part='header'\n >\n {openTopicId !== undefined && (\n <button\n {...pt?.back}\n type='button'\n className={classNames(\n 'cratis-chat-sidebar__back',\n pt?.back?.className,\n )}\n data-cratis-part='back'\n title={labels?.back ?? 'Back to topics'}\n aria-label={labels?.back ?? 'Back to topics'}\n onClick={() => select(undefined)}\n >\n <BackIcon />\n </button>\n )}\n <h2\n {...pt?.title}\n className={classNames(\n 'cratis-chat-sidebar__title',\n titleIsPending\n ? 'cratis-chat-sidebar__title--pending'\n : undefined,\n pt?.title?.className,\n )}\n data-cratis-part='title'\n >\n {title}\n </h2>\n {renderHeaderActions?.(openTopic)}\n <button\n {...pt?.close}\n type='button'\n className={classNames(\n 'cratis-chat-sidebar__close',\n pt?.close?.className,\n )}\n data-cratis-part='close'\n aria-label={labels?.close ?? 'Close chat'}\n onClick={onClose}\n >\n <span aria-hidden='true'>{icon('close', '×')}</span>\n </button>\n </header>\n <div\n {...pt?.content}\n className={classNames(\n 'cratis-chat-sidebar__content',\n pt?.content?.className,\n )}\n data-cratis-part='content'\n >\n {openTopicId === undefined ? (\n <ChatTopicList<TTopic>\n topics={topics}\n topicActions={topicActions}\n status={topicsStatus}\n onOpen={(topic) => select(topic.id, topic)}\n onStart={\n onStartTopic\n ? () => {\n void startTopic();\n }\n : undefined\n }\n authorOf={conversation.authorOf}\n renderAvatar={conversation.renderAvatar}\n isTopicUnnamed={isTopicUnnamed}\n buildAvatarUrl={conversation.buildAvatarUrl}\n labels={{\n unnamedTopic: labels?.unnamedTopic,\n ...labels?.topicList,\n }}\n />\n ) : (\n <ChatConversation<TMessage>\n {...conversation}\n messages={openMessages}\n status={messagesStatus}\n onSendMessage={send}\n labels={labels?.conversation}\n />\n )}\n </div>\n </>\n );\n\n return modal ? (\n <ModalOverlay\n {...pt?.backdrop}\n isOpen={open}\n onOpenChange={(openState) => {\n if (!openState) onClose();\n }}\n isDismissable={modal}\n isKeyboardDismissDisabled={!modal}\n className={classNames(\n 'cratis-chat-sidebar__backdrop',\n pt?.backdrop?.className,\n )}\n data-cratis-part='backdrop'\n data-modal={modal}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n >\n <Modal\n {...pt?.root}\n className={classNames(\n 'cratis-chat-sidebar',\n pt?.root?.className,\n className,\n )}\n style={{ width, ...pt?.root?.style }}\n data-cratis-part='root'\n data-position={position}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n >\n {panel}\n </Modal>\n </ModalOverlay>\n ) : (\n // Non-modal: a chat lives *next to* the work, so the background must stay visible and\n // interactive. React Aria's Modal blocks its backdrop by design (its dismissal props only\n // gate how it closes, never whether it intercepts), so the default is a plain portaled\n // layer with no dismissal behavior at all — only the close/back affordances dismiss it.\n nonModalPhase !== 'closed' &&\n portalContainer &&\n createPortal(\n <div\n {...pt?.backdrop}\n className={classNames(\n 'cratis-chat-sidebar__backdrop',\n pt?.backdrop?.className,\n )}\n data-cratis-part='backdrop'\n data-modal={false}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n data-entering={nonModalPhase === 'entering' || undefined}\n data-exiting={nonModalPhase === 'exiting' || undefined}\n >\n <div\n {...pt?.root}\n ref={nonModalPanel}\n className={classNames(\n 'cratis-chat-sidebar',\n pt?.root?.className,\n className,\n )}\n style={{ width, ...pt?.root?.style }}\n data-cratis-part='root'\n data-position={position}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n data-entering={nonModalPhase === 'entering' || undefined}\n data-exiting={nonModalPhase === 'exiting' || undefined}\n onAnimationEnd={(event) => {\n pt?.root?.onAnimationEnd?.(event);\n if (event.target !== event.currentTarget) return;\n setNonModalPhase((phase) =>\n phase === 'entering' ? 'open' : phase === 'exiting' ? 'closed' : phase,\n );\n }}\n >\n {panel}\n </div>\n </div>,\n portalContainer,\n )\n );\n};\n"],"names":["_jsxs","_jsx","isTopicUnnamed","defaultIsTopicUnnamed","_Fragment"],"mappings":";;;;;;;;;;;;AA2MA,MAAM,UAAU,GAAG,CAAC,GAAG,MAAiC,KACpD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAEpC,MAAM,QAAQ,GAAG,OACbA,IAAA,CAAA,KAAA,EAAA,EACI,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EAAA,aAAA,EACL,MAAM,EAAA,QAAA,EAAA,CAElBC,GAAA,CAAA,MAAA,EAAA,EAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,EACvCA,GAAA,CAAA,UAAA,EAAA,EAAU,MAAM,EAAC,iBAAiB,EAAA,CAAG,CAAA,EAAA,CACnC,CACT;AAYM,MAAM,WAAW,GAAG,CAGzB,EACE,IAAI,EACJ,OAAO,EACP,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,kBAClBC,gBAAc,EACd,QAAQ,GAAG,OAAO,EAClB,KAAK,GAAG,OAAO,EACf,KAAK,GAAG,KAAK,EACb,MAAM,EACN,SAAS,EACT,EAAE,EACF,GAAG,YAAY,EACkB,KAAI;AACrC,IAAA,MAAM,IAAI,GAAG,aAAa,EAAE;AAC5B,IAAA,MAAM,kBAAkB,GAAG,8BAA8B,EAAE;IAC3D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AAC7C,IAAA,MAAM,aAAa,GAAG,MAAM,CAAiB,IAAI,CAAC;IAClD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAEhD,QAAQ,CAAC;IAEX,SAAS,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IACrC,SAAS,CAAC,MAAK;QACX,gBAAgB,CAAC,CAAC,KAAK,KACnB,IAAI,GAAG,UAAU,GAAG,KAAK,KAAK,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAChE;AACL,IAAA,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACV,MAAM,eAAe,GAAG,CAAC,KAAK,IAAI,OAAO,IAAI,aAAa,KAAK;AAC3D,UAAE,kBAAkB,CAAC,YAAY;UAC/B,IAAI;IACV,SAAS,CAAC,MAAK;AACX,QAAA,IAAI,aAAa,KAAK,UAAU,IAAI,aAAa,KAAK,SAAS;YAAE;AACjE,QAAA,IAAI,CAAC,KAAK,KACN,MAAM,CAAC,UAAU,GAAG,kCAAkC,CAAC,CAAC,OAAO;AAC/D,YAAA,aAAa,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,MAAM,KAAK,CAAC,CACxD,EAAE;AACC,YAAA,gBAAgB,CAAC,aAAa,KAAK,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;YAClE;QACJ;AACA,QAAA,MAAM,OAAO,GAAG,UAAU,CAAC,MAAK;AAC5B,YAAA,gBAAgB,CAAC,aAAa,KAAK,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;QACtE,CAAC,EAAE,GAAG,CAAC;AACP,QAAA,OAAO,MAAM,YAAY,CAAC,OAAO,CAAC;IACtC,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC;IAE3C,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,EAEzD;AACH,IAAA,MAAM,YAAY,GAAG,eAAe,KAAK,SAAS;IAClD,MAAM,WAAW,GAAG;AAChB,WAAG,eAAe,IAAI,SAAS;UAC7B,kBAAkB;AACxB,IAAA,MAAM,SAAS,GACX,WAAW,KAAK;AACZ,UAAE;AACF,UAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AAC3E,IAAA,MAAM,OAAO,GAAGA,gBAAc,IAAIC,cAAqB;AAEvD,IAAA,MAAM,MAAM,GAAG,CAAC,OAAmC,EAAE,KAAc,KAAI;QACnE,IAAI,CAAC,YAAY,EAAE;YACf,qBAAqB,CAAC,OAAO,CAAC;QAClC;AACA,QAAA,eAAe,GACX,OAAO,EACP,KAAK;aACA,OAAO,KAAK;AACT,kBAAE;kBACA,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,KAClB,kBAAkB,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAC5C,CAAC,CACf;AACL,IAAA,CAAC;AAED,IAAA,MAAM,UAAU,GAAG,YAAW;AAC1B,QAAA,MAAM,OAAO,GAAG,MAAM,YAAY,IAAI;AACtC,QAAA,IAAI,OAAO,KAAK,SAAS,EAAE;YACvB,MAAM,CAAC,OAAO,CAAC;QACnB;AACJ,IAAA,CAAC;AAED,IAAA,MAAM,YAAY,GACd,WAAW,KAAK;AACZ,UAAE;AACF,UAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,KACpB,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CACnD;AAEX,IAAA,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,QAAuB,KAAI;QACnD,IAAI,WAAW,KAAK,SAAS;YAAE;AAC/B,QAAA,aAAa,CAAC,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC;AAC1C,QAAA,IACI,SAAS;YACT,sBAAsB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,EACjE;AACE,YAAA,kBAAkB,GAAG,SAAS,EAAE,IAAI,CAAC;QACzC;AACJ,IAAA,CAAC;AAED,IAAA,MAAM,KAAK,GACP,WAAW,KAAK;AACZ,WAAG,MAAM,EAAE,MAAM,IAAI,QAAQ;AAC7B,UAAE,SAAS,IAAI,CAAC,OAAO,CAAC,SAAS;cAC7B,SAAS,CAAC;eACT,MAAM,EAAE,YAAY,IAAI,WAAW,CAAC;AACjD,IAAA,MAAM,cAAc,GAChB,WAAW,KAAK,SAAS,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAEnE,MAAM,KAAK,IACPH,IAAA,CAAAI,QAAA,EAAA,EAAA,QAAA,EAAA,CACIJ,oBACQ,EAAE,EAAE,MAAM,EACd,SAAS,EAAE,UAAU,CACjB,6BAA6B,EAC7B,EAAE,EAAE,MAAM,EAAE,SAAS,CACxB,EAAA,kBAAA,EACgB,QAAQ,EAAA,QAAA,EAAA,CAExB,WAAW,KAAK,SAAS,KACtBC,GAAA,CAAA,QAAA,EAAA,EAAA,GACQ,EAAE,EAAE,IAAI,EACZ,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,UAAU,CACjB,2BAA2B,EAC3B,EAAE,EAAE,IAAI,EAAE,SAAS,CACtB,sBACgB,MAAM,EACvB,KAAK,EAAE,MAAM,EAAE,IAAI,IAAI,gBAAgB,EAAA,YAAA,EAC3B,MAAM,EAAE,IAAI,IAAI,gBAAgB,EAC5C,OAAO,EAAE,MAAM,MAAM,CAAC,SAAS,CAAC,EAAA,QAAA,EAEhCA,IAAC,QAAQ,EAAA,EAAA,CAAG,GACP,CACZ,EACDA,eACQ,EAAE,EAAE,KAAK,EACb,SAAS,EAAE,UAAU,CACjB,4BAA4B,EAC5B;AACI,8BAAE;AACF,8BAAE,SAAS,EACf,EAAE,EAAE,KAAK,EAAE,SAAS,CACvB,EAAA,kBAAA,EACgB,OAAO,EAAA,QAAA,EAEvB,KAAK,EAAA,CACL,EACJ,mBAAmB,GAAG,SAAS,CAAC,EACjCA,GAAA,CAAA,QAAA,EAAA,EAAA,GACQ,EAAE,EAAE,KAAK,EACb,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,UAAU,CACjB,4BAA4B,EAC5B,EAAE,EAAE,KAAK,EAAE,SAAS,CACvB,EAAA,kBAAA,EACgB,OAAO,EAAA,YAAA,EACZ,MAAM,EAAE,KAAK,IAAI,YAAY,EACzC,OAAO,EAAE,OAAO,EAAA,QAAA,EAEhBA,GAAA,CAAA,MAAA,EAAA,EAAA,aAAA,EAAkB,MAAM,EAAA,QAAA,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAA,CAAQ,EAAA,CAC/C,CAAA,EAAA,CACJ,EACTA,GAAA,CAAA,KAAA,EAAA,EAAA,GACQ,EAAE,EAAE,OAAO,EACf,SAAS,EAAE,UAAU,CACjB,8BAA8B,EAC9B,EAAE,EAAE,OAAO,EAAE,SAAS,CACzB,EAAA,kBAAA,EACgB,SAAS,EAAA,QAAA,EAEzB,WAAW,KAAK,SAAS,IACtBA,GAAA,CAAC,aAAa,EAAA,EACV,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAC1C,OAAO,EACH;0BACM,MAAK;4BACD,KAAK,UAAU,EAAE;wBACrB;0BACA,SAAS,EAEnB,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAC/B,YAAY,EAAE,YAAY,CAAC,YAAY,EACvC,cAAc,EAAEC,gBAAc,EAC9B,cAAc,EAAE,YAAY,CAAC,cAAc,EAC3C,MAAM,EAAE;wBACJ,YAAY,EAAE,MAAM,EAAE,YAAY;wBAClC,GAAG,MAAM,EAAE,SAAS;AACvB,qBAAA,EAAA,CACH,KAEFD,GAAA,CAAC,gBAAgB,EAAA,EAAA,GACT,YAAY,EAChB,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,IAAI,EACnB,MAAM,EAAE,MAAM,EAAE,YAAY,EAAA,CAC9B,CACL,EAAA,CACC,CAAA,EAAA,CACP,CACN;IAED,OAAO,KAAK,IACRA,GAAA,CAAC,YAAY,OACL,EAAE,EAAE,QAAQ,EAChB,MAAM,EAAE,IAAI,EACZ,YAAY,EAAE,CAAC,SAAS,KAAI;AACxB,YAAA,IAAI,CAAC,SAAS;AAAE,gBAAA,OAAO,EAAE;QAC7B,CAAC,EACD,aAAa,EAAE,KAAK,EACpB,yBAAyB,EAAE,CAAC,KAAK,EACjC,SAAS,EAAE,UAAU,CACjB,+BAA+B,EAC/B,EAAE,EAAE,QAAQ,EAAE,SAAS,CAC1B,EAAA,kBAAA,EACgB,UAAU,EAAA,YAAA,EACf,KAAK,eACN,IAAI,IAAI,SAAS,EAAA,eAAA,EACb,WAAW,KAAK,SAAS,IAAI,SAAS,EAAA,QAAA,EAErDA,GAAA,CAAC,KAAK,EAAA,EAAA,GACE,EAAE,EAAE,IAAI,EACZ,SAAS,EAAE,UAAU,CACjB,qBAAqB,EACrB,EAAE,EAAE,IAAI,EAAE,SAAS,EACnB,SAAS,CACZ,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAA,kBAAA,EACnB,MAAM,mBACR,QAAQ,EAAA,WAAA,EACZ,IAAI,IAAI,SAAS,mBACb,WAAW,KAAK,SAAS,IAAI,SAAS,YAEpD,KAAK,EAAA,CACF,GACG,KAMf,aAAa,KAAK,QAAQ;QAC1B,eAAe;QACf,YAAY,CACRA,GAAA,CAAA,KAAA,EAAA,EAAA,GACQ,EAAE,EAAE,QAAQ,EAChB,SAAS,EAAE,UAAU,CACjB,+BAA+B,EAC/B,EAAE,EAAE,QAAQ,EAAE,SAAS,CAC1B,EAAA,kBAAA,EACgB,UAAU,EAAA,YAAA,EACf,KAAK,EAAA,WAAA,EACN,IAAI,IAAI,SAAS,EAAA,eAAA,EACb,WAAW,KAAK,SAAS,IAAI,SAAS,EAAA,eAAA,EACtC,aAAa,KAAK,UAAU,IAAI,SAAS,EAAA,cAAA,EAC1C,aAAa,KAAK,SAAS,IAAI,SAAS,EAAA,QAAA,EAEtDA,GAAA,CAAA,KAAA,EAAA,EAAA,GACQ,EAAE,EAAE,IAAI,EACZ,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,UAAU,CACjB,qBAAqB,EACrB,EAAE,EAAE,IAAI,EAAE,SAAS,EACnB,SAAS,CACZ,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAA,kBAAA,EACnB,MAAM,EAAA,eAAA,EACR,QAAQ,eACZ,IAAI,IAAI,SAAS,EAAA,eAAA,EACb,WAAW,KAAK,SAAS,IAAI,SAAS,EAAA,eAAA,EACtC,aAAa,KAAK,UAAU,IAAI,SAAS,EAAA,cAAA,EAC1C,aAAa,KAAK,SAAS,IAAI,SAAS,EACtD,cAAc,EAAE,CAAC,KAAK,KAAI;oBACtB,EAAE,EAAE,IAAI,EAAE,cAAc,GAAG,KAAK,CAAC;AACjC,oBAAA,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,aAAa;wBAAE;AAC1C,oBAAA,gBAAgB,CAAC,CAAC,KAAK,KACnB,KAAK,KAAK,UAAU,GAAG,MAAM,GAAG,KAAK,KAAK,SAAS,GAAG,QAAQ,GAAG,KAAK,CACzE;gBACL,CAAC,EAAA,QAAA,EAEA,KAAK,EAAA,CACJ,EAAA,CACJ,EACN,eAAe,CAClB,CACJ;AACL;;"}
1
+ {"version":3,"file":"ChatSidebar.js","sources":["../../../Chat/ChatSidebar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Modal, ModalOverlay } from 'react-aria-components';\nimport type { ChatConversationLabels, ChatConversationProps } from './ChatConversation';\nimport { ChatConversation } from './ChatConversation';\nimport { sameChatIdentifier, type ChatIdentifier } from './ChatIdentifier';\nimport type { ChatMention } from './ChatMention';\nimport type { ChatMessage } from './ChatMessage';\nimport type { ChatTopic } from './ChatTopic';\nimport type { ChatTopicAction } from './ChatTopicAction';\nimport type { ChatStatus } from './ChatStatus';\nimport type { ChatTopicListLabels } from './ChatTopicList';\nimport { ChatTopicList } from './ChatTopicList';\nimport { isTopicUnnamed as defaultIsTopicUnnamed } from './isTopicUnnamed';\nimport { shouldRequestTopicName } from './shouldRequestTopicName';\nimport { useCratisIcon } from '../configuration/useCratisIcon';\nimport { unstable_useOverlayEnvironment } from '../renderer/RendererContext';\nimport type { ExactPartKeys } from '../types/ExactPartKeys';\nimport type { PartsOf } from '../types/parts';\nimport { classNames } from '../ClassNames/classNames';\n\ntype ChatSidebarPartAttributes<TElement> = HTMLAttributes<TElement> & {\n [attribute: `data-${string}`]: string | number | boolean | undefined;\n};\n\ntype ChatSidebarButtonAttributes = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n 'onClick' | 'type'\n>;\n\n/** Stable Cratis-owned parts for styling a {@link ChatSidebar}. */\nexport interface ChatSidebarParts {\n /** Viewport overlay layer the sidebar portals into — only paints/blocks when {@link ChatSidebarProps.modal} is true. */\n backdrop?: ChatSidebarPartAttributes<HTMLDivElement>;\n /** The sidebar panel itself. */\n root?: ChatSidebarPartAttributes<HTMLDivElement>;\n /** Header containing the back affordance, title, and close button. */\n header?: ChatSidebarPartAttributes<HTMLElement>;\n /** The topic list title, or the open topic's name. */\n title?: ChatSidebarPartAttributes<HTMLHeadingElement>;\n /** Back-to-topics button, present only while a topic is open. */\n back?: ChatSidebarButtonAttributes;\n /** Close button. */\n close?: ChatSidebarButtonAttributes;\n /** The topic list / conversation content region. */\n content?: ChatSidebarPartAttributes<HTMLDivElement>;\n}\n\nconst chatSidebarPartsMatchManifest: ExactPartKeys<\n ChatSidebarParts,\n PartsOf<'ChatSidebar'>\n> = true;\nvoid chatSidebarPartsMatchManifest;\n\n/** Overrides for every label the {@link ChatSidebar} and its children render. Any field left\n * unset falls back to a literal English default. */\nexport interface ChatSidebarLabels {\n /** The sidebar's title while the topic list is showing. Defaults to `'Topics'`. */\n topics?: string;\n\n /** Placeholder title for a topic that has not been named yet. Defaults to `'New topic'`. */\n unnamedTopic?: string;\n\n /** Tooltip/accessible label for the back-to-topics button. Defaults to `'Back to topics'`. */\n back?: string;\n\n /** Accessible label for the close button. Defaults to `'Close chat'`. */\n close?: string;\n\n /** Labels forwarded to the {@link ChatTopicList}. */\n topicList?: ChatTopicListLabels;\n\n /** Labels forwarded to the {@link ChatConversation}. */\n conversation?: ChatConversationLabels;\n}\n\n/**\n * Props for {@link ChatSidebar}.\n * @typeParam TMessage The host's message type — anything extending {@link ChatMessage}.\n * @typeParam TTopic The host's topic type — anything extending {@link ChatTopic}.\n */\nexport interface ChatSidebarProps<\n TMessage extends ChatMessage = ChatMessage,\n TTopic extends ChatTopic = ChatTopic,\n> extends Omit<\n ChatConversationProps<TMessage>,\n 'messages' | 'onSendMessage' | 'labels' | 'className' | 'status'\n> {\n /**\n * Renders host content in the header, between the title and the close button, for example a\n * rename control for the open topic. Nothing is rendered when it returns null or undefined.\n * @param openTopic The open topic, or undefined while the topic list is shown.\n * @returns What to render in the header.\n */\n renderHeaderActions?: (openTopic: TTopic | undefined) => ReactNode;\n\n /** Whether the sidebar is open. */\n open: boolean;\n\n /** Invoked when the sidebar asks to close — the host owns {@link open}, so closing means the host flips it. */\n onClose: () => void;\n\n /**\n * The topics, in any order. Hand this the array a live (observable) query delivers and the\n * sidebar re-renders as it changes.\n */\n topics: TTopic[];\n\n /**\n * The messages — either the whole chat or just the open topic's; the sidebar shows those of\n * the open topic by matching on `topicId` either way. Hand this the array a live\n * (observable) query delivers and the conversation re-renders as it changes.\n */\n messages: TMessage[];\n\n /** The host's actions to offer on each topic where they are available. The inherited `actions` prop applies only to messages. */\n topicActions?: ChatTopicAction<TTopic>[];\n\n /** Topic-list query display state. Defaults to ready when omitted. */\n topicsStatus?: ChatStatus;\n\n /** Conversation query display state. Defaults to ready when omitted. */\n messagesStatus?: ChatStatus;\n\n /**\n * The open topic, for hosts that own the selection themselves: an identifier opens that\n * topic's conversation, `null` shows the topic list, and leaving the prop unset lets the\n * sidebar keep the selection internally.\n */\n selectedTopicId?: ChatIdentifier | null;\n\n /**\n * Invoked when the open topic changes — a topic was opened (or just started), or the person\n * went back to the list.\n * @param topicId The identifier of the topic now open, or undefined for the list.\n * @param topic The topic itself, when it is known in {@link topics}.\n */\n onTopicSelected?: (topicId: ChatIdentifier | undefined, topic?: TTopic) => void;\n\n /**\n * Invoked when a new topic is asked for. Creating the topic is the host's business; answer\n * with its identifier (directly or through a promise) and the sidebar opens it, ready for\n * the first message. Omit to leave the new-topic affordance off.\n * @returns The identifier of the topic that was started, when the host created one.\n */\n onStartTopic?: () => ChatIdentifier | undefined | Promise<ChatIdentifier | undefined>;\n\n /**\n * Invoked when a message is sent, with the topic it belongs to, the trimmed body and who it\n * mentions. Everything else about persisting the message is the host's business.\n * @param topicId The identifier of the topic the message was sent in.\n * @param body The message text, mentions written into it as plain `@Name`.\n * @param mentions Who the body mentions.\n */\n onSendMessage: (\n topicId: ChatIdentifier,\n body: string,\n mentions: ChatMention[],\n ) => void;\n\n /**\n * Invoked when the very first message is sent in a topic that has no name yet — the host\n * asks its LLM (or whatever it prefers) for a good name and supplies it through the topic\n * data; until then the topic renders its pending placeholder. Not invoked again for later\n * messages, and never for a topic that already has a name.\n * @param topic The topic that needs a name.\n * @param firstMessageBody The message to derive the name from.\n */\n onRequestTopicName?: (topic: TTopic, firstMessageBody: string) => void;\n\n /**\n * Decides whether a topic counts as unnamed — see {@link ChatTopicListProps.isTopicUnnamed}.\n * @param topic The topic to check.\n * @returns True when the topic has no usable name yet.\n */\n isTopicUnnamed?: (topic: TTopic) => boolean;\n\n /** Which edge the sidebar opens from. Defaults to `'right'`. */\n position?: 'left' | 'right';\n\n /** The sidebar's width, any CSS length. Defaults to `'24rem'`. */\n width?: string;\n\n /**\n * Whether the sidebar is modal — a backdrop behind it, and dismissing by Escape or clicking\n * outside. Defaults to false: a chat lives *next to* the work, so it should not block it —\n * the background stays visible and interactive, and only the close/back affordances dismiss it.\n */\n modal?: boolean;\n\n /** Overrides for every label rendered. Unset fields fall back to literal English defaults. */\n labels?: ChatSidebarLabels;\n\n /** Additional class name for the sidebar's panel element. */\n className?: string;\n\n /** Cratis-owned per-part attributes. */\n pt?: ChatSidebarParts;\n}\n\nconst BackIcon = () => (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2.5'\n aria-hidden='true'\n >\n <line x1='19' y1='12' x2='5' y2='12' />\n <polyline points='12 19 5 12 12 5' />\n </svg>\n);\n\n/**\n * A topic-based chat in a sidebar next to the view, built on Components' own overlay primitives\n * (React Aria internally, for accessible dismissal and focus handling). It opens on the topic\n * list; picking a topic (or starting a new one) slides into that conversation, with a back\n * affordance to the list. Everything about *data* is the host's: topics and messages come in as\n * arrays (hand it live query data and it stays current), sends and new topics go out as\n * callbacks, and when the first message lands in an unnamed topic the sidebar asks the host for\n * a name through {@link ChatSidebarProps.onRequestTopicName | onRequestTopicName} — rendering a\n * pending placeholder until the name arrives.\n */\nexport const ChatSidebar = <\n TMessage extends ChatMessage = ChatMessage,\n TTopic extends ChatTopic = ChatTopic,\n>({\n open,\n onClose,\n topics,\n messages,\n topicActions,\n renderHeaderActions,\n topicsStatus,\n messagesStatus,\n selectedTopicId,\n onTopicSelected,\n onStartTopic,\n onSendMessage,\n onRequestTopicName,\n isTopicUnnamed,\n position = 'right',\n width = '24rem',\n modal = false,\n labels,\n className,\n pt,\n ...conversation\n}: ChatSidebarProps<TMessage, TTopic>) => {\n const icon = useCratisIcon();\n const overlayEnvironment = unstable_useOverlayEnvironment();\n const [mounted, setMounted] = useState(false);\n const nonModalPanel = useRef<HTMLDivElement>(null);\n const [nonModalPhase, setNonModalPhase] = useState<\n 'closed' | 'entering' | 'open' | 'exiting'\n >('closed');\n\n useEffect(() => setMounted(true), []);\n useEffect(() => {\n setNonModalPhase((phase) =>\n open ? 'entering' : phase === 'closed' ? 'closed' : 'exiting',\n );\n }, [open]);\n const portalContainer = !modal && mounted && nonModalPhase !== 'closed'\n ? overlayEnvironment.getContainer()\n : null;\n useEffect(() => {\n if (nonModalPhase !== 'entering' && nonModalPhase !== 'exiting') return;\n if (!modal && (\n window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ||\n nonModalPanel.current?.getAnimations?.().length === 0\n )) {\n setNonModalPhase(nonModalPhase === 'entering' ? 'open' : 'closed');\n return;\n }\n const timeout = setTimeout(() => {\n setNonModalPhase(nonModalPhase === 'entering' ? 'open' : 'closed');\n }, 250);\n return () => clearTimeout(timeout);\n }, [modal, nonModalPhase, portalContainer]);\n\n const [internalSelectedId, setInternalSelectedId] = useState<\n ChatIdentifier | undefined\n >();\n const isControlled = selectedTopicId !== undefined;\n const openTopicId = isControlled\n ? (selectedTopicId ?? undefined)\n : internalSelectedId;\n const openTopic =\n openTopicId === undefined\n ? undefined\n : topics.find((topic) => sameChatIdentifier(topic.id, openTopicId));\n const unnamed = isTopicUnnamed ?? defaultIsTopicUnnamed;\n\n const select = (topicId: ChatIdentifier | undefined, topic?: TTopic) => {\n if (!isControlled) {\n setInternalSelectedId(topicId);\n }\n onTopicSelected?.(\n topicId,\n topic ??\n (topicId === undefined\n ? undefined\n : topics.find((candidate) =>\n sameChatIdentifier(candidate.id, topicId),\n )),\n );\n };\n\n const startTopic = async () => {\n const topicId = await onStartTopic?.();\n if (topicId !== undefined) {\n select(topicId);\n }\n };\n\n const openMessages =\n openTopicId === undefined\n ? []\n : messages.filter((message) =>\n sameChatIdentifier(message.topicId, openTopicId),\n );\n\n const send = (body: string, mentions: ChatMention[]) => {\n if (openTopicId === undefined) return;\n onSendMessage(openTopicId, body, mentions);\n if (\n openTopic &&\n shouldRequestTopicName(unnamed(openTopic), openMessages.length)\n ) {\n onRequestTopicName?.(openTopic, body);\n }\n };\n\n const title =\n openTopicId === undefined\n ? (labels?.topics ?? 'Topics')\n : openTopic && !unnamed(openTopic)\n ? openTopic.name\n : (labels?.unnamedTopic ?? 'New topic');\n const titleIsPending =\n openTopicId !== undefined && (!openTopic || unnamed(openTopic));\n\n const panel = (\n <>\n <header\n {...pt?.header}\n className={classNames(\n 'cratis-chat-sidebar__header',\n pt?.header?.className,\n )}\n data-cratis-part='header'\n >\n {openTopicId !== undefined && (\n <button\n {...pt?.back}\n type='button'\n className={classNames(\n 'cratis-chat-sidebar__back',\n pt?.back?.className,\n )}\n data-cratis-part='back'\n title={labels?.back ?? 'Back to topics'}\n aria-label={labels?.back ?? 'Back to topics'}\n onClick={() => select(undefined)}\n >\n <BackIcon />\n </button>\n )}\n <h2\n {...pt?.title}\n className={classNames(\n 'cratis-chat-sidebar__title',\n titleIsPending\n ? 'cratis-chat-sidebar__title--pending'\n : undefined,\n pt?.title?.className,\n )}\n data-cratis-part='title'\n >\n {title}\n </h2>\n {renderHeaderActions?.(openTopic)}\n <button\n {...pt?.close}\n type='button'\n className={classNames(\n 'cratis-chat-sidebar__close',\n pt?.close?.className,\n )}\n data-cratis-part='close'\n aria-label={labels?.close ?? 'Close chat'}\n onClick={onClose}\n >\n <span aria-hidden='true'>{icon('close', '×')}</span>\n </button>\n </header>\n <div\n {...pt?.content}\n className={classNames(\n 'cratis-chat-sidebar__content',\n pt?.content?.className,\n )}\n data-cratis-part='content'\n >\n {openTopicId === undefined ? (\n <ChatTopicList<TTopic>\n topics={topics}\n topicActions={topicActions}\n status={topicsStatus}\n onOpen={(topic) => select(topic.id, topic)}\n onStart={\n onStartTopic\n ? () => {\n void startTopic();\n }\n : undefined\n }\n authorOf={conversation.authorOf}\n renderAvatar={conversation.renderAvatar}\n isTopicUnnamed={isTopicUnnamed}\n buildAvatarUrl={conversation.buildAvatarUrl}\n labels={{\n unnamedTopic: labels?.unnamedTopic,\n ...labels?.topicList,\n }}\n />\n ) : (\n <ChatConversation<TMessage>\n {...conversation}\n messages={openMessages}\n status={messagesStatus}\n onSendMessage={send}\n labels={labels?.conversation}\n />\n )}\n </div>\n </>\n );\n\n return modal ? (\n <ModalOverlay\n {...pt?.backdrop}\n isOpen={open}\n onOpenChange={(openState) => {\n if (!openState) onClose();\n }}\n isDismissable={modal}\n isKeyboardDismissDisabled={!modal}\n className={classNames(\n 'cratis-chat-sidebar__backdrop',\n pt?.backdrop?.className,\n )}\n data-cratis-part='backdrop'\n data-modal={modal}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n >\n <Modal\n {...pt?.root}\n className={classNames(\n 'cratis-chat-sidebar',\n pt?.root?.className,\n className,\n )}\n style={{ width, ...pt?.root?.style }}\n data-cratis-part='root'\n data-position={position}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n >\n {panel}\n </Modal>\n </ModalOverlay>\n ) : (\n // Non-modal: a chat lives *next to* the work, so the background must stay visible and\n // interactive. React Aria's Modal blocks its backdrop by design (its dismissal props only\n // gate how it closes, never whether it intercepts), so the default is a plain portaled\n // layer with no dismissal behavior at all — only the close/back affordances dismiss it.\n nonModalPhase !== 'closed' &&\n portalContainer &&\n createPortal(\n <div\n {...pt?.backdrop}\n className={classNames(\n 'cratis-chat-sidebar__backdrop',\n pt?.backdrop?.className,\n )}\n data-cratis-part='backdrop'\n data-modal={false}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n data-entering={nonModalPhase === 'entering' || undefined}\n data-exiting={nonModalPhase === 'exiting' || undefined}\n >\n <div\n {...pt?.root}\n ref={nonModalPanel}\n className={classNames(\n 'cratis-chat-sidebar',\n pt?.root?.className,\n className,\n )}\n style={{ width, ...pt?.root?.style }}\n data-cratis-part='root'\n data-position={position}\n data-open={open || undefined}\n data-selected={openTopicId !== undefined || undefined}\n data-entering={nonModalPhase === 'entering' || undefined}\n data-exiting={nonModalPhase === 'exiting' || undefined}\n onAnimationEnd={(event) => {\n pt?.root?.onAnimationEnd?.(event);\n if (event.target !== event.currentTarget) return;\n setNonModalPhase((phase) =>\n phase === 'entering' ? 'open' : phase === 'exiting' ? 'closed' : phase,\n );\n }}\n >\n {panel}\n </div>\n </div>,\n portalContainer,\n )\n );\n};\n"],"names":["_jsxs","_jsx","isTopicUnnamed","defaultIsTopicUnnamed","_Fragment"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Joins the class names that are set, skipping empty, undefined and false values.
3
+ * @param values Class names, some possibly unset.
4
+ * @returns The space-separated class names.
5
+ */
6
+ export declare const classNames: (...values: Array<string | undefined | false>) => string;
7
+ //# sourceMappingURL=classNames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classNames.d.ts","sourceRoot":"","sources":["../../../ClassNames/classNames.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,UAAU,cAAe,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,WACnC,CAAC"}
@@ -0,0 +1,4 @@
1
+ const classNames = (...values) => values.filter(Boolean).join(' ');
2
+
3
+ export { classNames };
4
+ //# sourceMappingURL=classNames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classNames.js","sources":["../../../ClassNames/classNames.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Joins the class names that are set, skipping empty, undefined and false values.\n * @param values Class names, some possibly unset.\n * @returns The space-separated class names.\n */\nexport const classNames = (...values: Array<string | undefined | false>) =>\n values.filter(Boolean).join(' ');\n"],"names":[],"mappings":"MAQa,UAAU,GAAG,CAAC,GAAG,MAAyC,KACnE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../Common/Breadcrumbs.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAS5D,+GAA+G;AAC/G,MAAM,MAAM,yBAAyB,GAAG,IAAI,CACxC,cAAc,CAAC,WAAW,CAAC,EAC3B,WAAW,GAAG,OAAO,GAAG,OAAO,CAClC,GAAG;IACA,CAAC,aAAa,EAAE,QAAQ,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CAC5E,CAAC;AAEF,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC3B,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAC7B,kDAAkD;IAClD,IAAI,CAAC,EAAE,yBAAyB,CAAC;IACjC,mBAAmB;IACnB,IAAI,CAAC,EAAE,yBAAyB,CAAC;IACjC,iFAAiF;IACjF,IAAI,CAAC,EAAE,yBAAyB,CAAC;IACjC,0CAA0C;IAC1C,SAAS,CAAC,EAAE,yBAAyB,CAAC;CACzC;AAQD,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC7B,qEAAqE;IACrE,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,uFAAuF;IACvF,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,EAAE,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAKD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,kEAMrB,gBAAgB,gCAuDlB,CAAC"}
1
+ {"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../Common/Breadcrumbs.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAU5D,+GAA+G;AAC/G,MAAM,MAAM,yBAAyB,GAAG,IAAI,CACxC,cAAc,CAAC,WAAW,CAAC,EAC3B,WAAW,GAAG,OAAO,GAAG,OAAO,CAClC,GAAG;IACA,CAAC,aAAa,EAAE,QAAQ,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CAC5E,CAAC;AAEF,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC3B,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAC7B,kDAAkD;IAClD,IAAI,CAAC,EAAE,yBAAyB,CAAC;IACjC,mBAAmB;IACnB,IAAI,CAAC,EAAE,yBAAyB,CAAC;IACjC,iFAAiF;IACjF,IAAI,CAAC,EAAE,yBAAyB,CAAC;IACjC,0CAA0C;IAC1C,SAAS,CAAC,EAAE,yBAAyB,CAAC;CACzC;AAQD,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC7B,qEAAqE;IACrE,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,uFAAuF;IACvF,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,EAAE,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,kEAMrB,gBAAgB,gCAuDlB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { Breadcrumbs as Breadcrumbs$1, Breadcrumb, Link } from 'react-aria-components/Breadcrumbs';
3
+ import { classNames } from '../ClassNames/classNames.js';
3
4
 
4
- const classNames = (...values) => values.filter(Boolean).join(' ');
5
5
  const Breadcrumbs = ({ items, separator = '/', 'aria-label': ariaLabel, className, pt, }) => (jsx("nav", { "aria-label": ariaLabel, children: jsx(Breadcrumbs$1, { ...pt?.root, className: classNames('cratis-breadcrumbs', pt?.root?.className, className), "data-cratis-part": 'root', children: items.map((item, index) => {
6
6
  const current = index === items.length - 1;
7
7
  return (jsxs(Breadcrumb, { ...pt?.item, className: classNames('cratis-breadcrumbs__item', pt?.item?.className), "data-cratis-part": 'item', "data-selected": current || undefined, children: [jsx(Link, { ...pt?.link, href: current ? undefined : item.href, onPress: current ? undefined : item.onNavigate, className: classNames('cratis-breadcrumbs__link', pt?.link?.className), "data-cratis-part": 'link', "data-selected": current || undefined, children: item.label }), !current && (jsx("span", { ...pt?.separator, "aria-hidden": 'true', className: classNames('cratis-breadcrumbs__separator', pt?.separator?.className), "data-cratis-part": 'separator', children: separator }))] }, `${index}-${String(item.href ?? '')}`));
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumbs.js","sources":["../../../Common/Breadcrumbs.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { type HTMLAttributes, type ReactNode } from 'react';\nimport {\n Breadcrumb as AriaBreadcrumb,\n Breadcrumbs as AriaBreadcrumbs,\n Link as AriaLink,\n} from 'react-aria-components/Breadcrumbs';\nimport type { ExactPartKeys } from '../types/ExactPartKeys';\nimport type { PartsOf } from '../types/parts';\n\n/** Attributes a consumer may hand to one {@link Breadcrumbs} part: class, style, title and data attributes. */\nexport type BreadcrumbsPartAttributes = Pick<\n HTMLAttributes<HTMLElement>,\n 'className' | 'style' | 'title'\n> & {\n [dataAttribute: `data-${string}`]: string | number | boolean | undefined;\n};\n\n/** One segment of a {@link Breadcrumbs} trail. */\nexport interface BreadcrumbItem {\n /** Visible label. */\n label: ReactNode;\n /** Destination. A segment without one is text rather than a link — as the last segment is. */\n href?: string;\n /** Called instead of navigating, for a router that owns navigation. */\n onNavigate?: () => void;\n}\n\n/** Stable Cratis-owned parts for styling a {@link Breadcrumbs} trail. */\nexport interface BreadcrumbsParts {\n /** The navigation landmark wrapping the trail. */\n root?: BreadcrumbsPartAttributes;\n /** One segment. */\n item?: BreadcrumbsPartAttributes;\n /** A segment's link, rendered for every segment that is not the current page. */\n link?: BreadcrumbsPartAttributes;\n /** The separator between two segments. */\n separator?: BreadcrumbsPartAttributes;\n}\n\nconst breadcrumbsPartsMatchManifest: ExactPartKeys<\n BreadcrumbsParts,\n PartsOf<'Breadcrumbs'>\n> = true;\nvoid breadcrumbsPartsMatchManifest;\n\n/** Props for {@link Breadcrumbs}. */\nexport interface BreadcrumbsProps {\n /** The trail, outermost first. The last item is the current page. */\n items: BreadcrumbItem[];\n /** Separator rendered between segments. Defaults to a slash; decorative either way. */\n separator?: ReactNode;\n /** Accessible name for the landmark. Name it when a page carries more than one trail. */\n 'aria-label'?: string;\n /** Extra class name for the root element. */\n className?: string;\n /** Cratis-owned per-part attributes. */\n pt?: BreadcrumbsParts;\n}\n\nconst classNames = (...values: Array<string | undefined>) =>\n values.filter(Boolean).join(' ');\n\n/**\n * A breadcrumb trail.\n *\n * The last segment is the current page: it carries `aria-current=\"page\"` and is never a link, which\n * is what tells a screen-reader user where the trail ends. Earlier segments are links when they have\n * a destination. The trail is an ordered list inside a navigation landmark, so it can be jumped to\n * and its length announced.\n */\nexport const Breadcrumbs = ({\n items,\n separator = '/',\n 'aria-label': ariaLabel,\n className,\n pt,\n}: BreadcrumbsProps) => (\n // React Aria renders the ordered list; the navigation landmark around it is ours, because a\n // trail a screen-reader user cannot jump to is only a list of links.\n <nav aria-label={ariaLabel}>\n <AriaBreadcrumbs\n {...pt?.root}\n className={classNames('cratis-breadcrumbs', pt?.root?.className, className)}\n data-cratis-part='root'\n >\n {items.map((item, index) => {\n const current = index === items.length - 1;\n return (\n <AriaBreadcrumb\n key={`${index}-${String(item.href ?? '')}`}\n {...pt?.item}\n className={classNames('cratis-breadcrumbs__item', pt?.item?.className)}\n data-cratis-part='item'\n data-selected={current || undefined}\n >\n {/*\n * Every segment is a link, including the current page: React Aria hands\n * aria-current=\"page\" and the disabled state to the last one through its link\n * context, so a segment rendered as plain text would silently lose both.\n */}\n <AriaLink\n {...pt?.link}\n href={current ? undefined : item.href}\n onPress={current ? undefined : item.onNavigate}\n className={classNames(\n 'cratis-breadcrumbs__link',\n pt?.link?.className,\n )}\n data-cratis-part='link'\n data-selected={current || undefined}\n >\n {item.label}\n </AriaLink>\n {!current && (\n <span\n {...pt?.separator}\n aria-hidden='true'\n className={classNames(\n 'cratis-breadcrumbs__separator',\n pt?.separator?.className,\n )}\n data-cratis-part='separator'\n >\n {separator}\n </span>\n )}\n </AriaBreadcrumb>\n );\n })}\n </AriaBreadcrumbs>\n </nav>\n);\n"],"names":["_jsx","AriaBreadcrumbs","_jsxs","AriaBreadcrumb","AriaLink"],"mappings":";;;AA8DA,MAAM,UAAU,GAAG,CAAC,GAAG,MAAiC,KACpD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAU7B,MAAM,WAAW,GAAG,CAAC,EACxB,KAAK,EACL,SAAS,GAAG,GAAG,EACf,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,EAAE,GACa,MAGfA,GAAA,CAAA,KAAA,EAAA,EAAA,YAAA,EAAiB,SAAS,EAAA,QAAA,EACtBA,GAAA,CAACC,aAAe,EAAA,EAAA,GACR,EAAE,EAAE,IAAI,EACZ,SAAS,EAAE,UAAU,CAAC,oBAAoB,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,EAAA,kBAAA,EAC1D,MAAM,EAAA,QAAA,EAE1B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;YACvB,MAAM,OAAO,GAAG,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;AAC1C,YAAA,QACIC,IAAA,CAACC,UAAc,EAAA,EAAA,GAEP,EAAE,EAAE,IAAI,EACZ,SAAS,EAAE,UAAU,CAAC,0BAA0B,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,EAAA,kBAAA,EACrD,MAAM,EAAA,eAAA,EACR,OAAO,IAAI,SAAS,EAAA,QAAA,EAAA,CAOnCH,GAAA,CAACI,IAAQ,EAAA,EAAA,GACD,EAAE,EAAE,IAAI,EACZ,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,EACrC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,UAAU,EAC9C,SAAS,EAAE,UAAU,CACjB,0BAA0B,EAC1B,EAAE,EAAE,IAAI,EAAE,SAAS,CACtB,EAAA,kBAAA,EACgB,MAAM,EAAA,eAAA,EACR,OAAO,IAAI,SAAS,EAAA,QAAA,EAElC,IAAI,CAAC,KAAK,EAAA,CACJ,EACV,CAAC,OAAO,KACLJ,GAAA,CAAA,MAAA,EAAA,EAAA,GACQ,EAAE,EAAE,SAAS,EAAA,aAAA,EACL,MAAM,EAClB,SAAS,EAAE,UAAU,CACjB,+BAA+B,EAC/B,EAAE,EAAE,SAAS,EAAE,SAAS,CAC3B,EAAA,kBAAA,EACgB,WAAW,EAAA,QAAA,EAE3B,SAAS,EAAA,CACP,CACV,CAAA,EAAA,EApCI,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA,CAAE,CAqC7B;AAErB,QAAA,CAAC,CAAC,EAAA,CACY,EAAA,CAChB;;"}
1
+ {"version":3,"file":"Breadcrumbs.js","sources":["../../../Common/Breadcrumbs.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { type HTMLAttributes, type ReactNode } from 'react';\nimport {\n Breadcrumb as AriaBreadcrumb,\n Breadcrumbs as AriaBreadcrumbs,\n Link as AriaLink,\n} from 'react-aria-components/Breadcrumbs';\nimport type { ExactPartKeys } from '../types/ExactPartKeys';\nimport type { PartsOf } from '../types/parts';\nimport { classNames } from '../ClassNames/classNames';\n\n/** Attributes a consumer may hand to one {@link Breadcrumbs} part: class, style, title and data attributes. */\nexport type BreadcrumbsPartAttributes = Pick<\n HTMLAttributes<HTMLElement>,\n 'className' | 'style' | 'title'\n> & {\n [dataAttribute: `data-${string}`]: string | number | boolean | undefined;\n};\n\n/** One segment of a {@link Breadcrumbs} trail. */\nexport interface BreadcrumbItem {\n /** Visible label. */\n label: ReactNode;\n /** Destination. A segment without one is text rather than a link — as the last segment is. */\n href?: string;\n /** Called instead of navigating, for a router that owns navigation. */\n onNavigate?: () => void;\n}\n\n/** Stable Cratis-owned parts for styling a {@link Breadcrumbs} trail. */\nexport interface BreadcrumbsParts {\n /** The navigation landmark wrapping the trail. */\n root?: BreadcrumbsPartAttributes;\n /** One segment. */\n item?: BreadcrumbsPartAttributes;\n /** A segment's link, rendered for every segment that is not the current page. */\n link?: BreadcrumbsPartAttributes;\n /** The separator between two segments. */\n separator?: BreadcrumbsPartAttributes;\n}\n\nconst breadcrumbsPartsMatchManifest: ExactPartKeys<\n BreadcrumbsParts,\n PartsOf<'Breadcrumbs'>\n> = true;\nvoid breadcrumbsPartsMatchManifest;\n\n/** Props for {@link Breadcrumbs}. */\nexport interface BreadcrumbsProps {\n /** The trail, outermost first. The last item is the current page. */\n items: BreadcrumbItem[];\n /** Separator rendered between segments. Defaults to a slash; decorative either way. */\n separator?: ReactNode;\n /** Accessible name for the landmark. Name it when a page carries more than one trail. */\n 'aria-label'?: string;\n /** Extra class name for the root element. */\n className?: string;\n /** Cratis-owned per-part attributes. */\n pt?: BreadcrumbsParts;\n}\n\n/**\n * A breadcrumb trail.\n *\n * The last segment is the current page: it carries `aria-current=\"page\"` and is never a link, which\n * is what tells a screen-reader user where the trail ends. Earlier segments are links when they have\n * a destination. The trail is an ordered list inside a navigation landmark, so it can be jumped to\n * and its length announced.\n */\nexport const Breadcrumbs = ({\n items,\n separator = '/',\n 'aria-label': ariaLabel,\n className,\n pt,\n}: BreadcrumbsProps) => (\n // React Aria renders the ordered list; the navigation landmark around it is ours, because a\n // trail a screen-reader user cannot jump to is only a list of links.\n <nav aria-label={ariaLabel}>\n <AriaBreadcrumbs\n {...pt?.root}\n className={classNames('cratis-breadcrumbs', pt?.root?.className, className)}\n data-cratis-part='root'\n >\n {items.map((item, index) => {\n const current = index === items.length - 1;\n return (\n <AriaBreadcrumb\n key={`${index}-${String(item.href ?? '')}`}\n {...pt?.item}\n className={classNames('cratis-breadcrumbs__item', pt?.item?.className)}\n data-cratis-part='item'\n data-selected={current || undefined}\n >\n {/*\n * Every segment is a link, including the current page: React Aria hands\n * aria-current=\"page\" and the disabled state to the last one through its link\n * context, so a segment rendered as plain text would silently lose both.\n */}\n <AriaLink\n {...pt?.link}\n href={current ? undefined : item.href}\n onPress={current ? undefined : item.onNavigate}\n className={classNames(\n 'cratis-breadcrumbs__link',\n pt?.link?.className,\n )}\n data-cratis-part='link'\n data-selected={current || undefined}\n >\n {item.label}\n </AriaLink>\n {!current && (\n <span\n {...pt?.separator}\n aria-hidden='true'\n className={classNames(\n 'cratis-breadcrumbs__separator',\n pt?.separator?.className,\n )}\n data-cratis-part='separator'\n >\n {separator}\n </span>\n )}\n </AriaBreadcrumb>\n );\n })}\n </AriaBreadcrumbs>\n </nav>\n);\n"],"names":["_jsx","AriaBreadcrumbs","_jsxs","AriaBreadcrumb","AriaLink"],"mappings":";;;;AAuEO,MAAM,WAAW,GAAG,CAAC,EACxB,KAAK,EACL,SAAS,GAAG,GAAG,EACf,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,EAAE,GACa,MAGfA,GAAA,CAAA,KAAA,EAAA,EAAA,YAAA,EAAiB,SAAS,EAAA,QAAA,EACtBA,GAAA,CAACC,aAAe,EAAA,EAAA,GACR,EAAE,EAAE,IAAI,EACZ,SAAS,EAAE,UAAU,CAAC,oBAAoB,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,EAAA,kBAAA,EAC1D,MAAM,EAAA,QAAA,EAE1B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;YACvB,MAAM,OAAO,GAAG,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;AAC1C,YAAA,QACIC,IAAA,CAACC,UAAc,EAAA,EAAA,GAEP,EAAE,EAAE,IAAI,EACZ,SAAS,EAAE,UAAU,CAAC,0BAA0B,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,EAAA,kBAAA,EACrD,MAAM,EAAA,eAAA,EACR,OAAO,IAAI,SAAS,EAAA,QAAA,EAAA,CAOnCH,GAAA,CAACI,IAAQ,EAAA,EAAA,GACD,EAAE,EAAE,IAAI,EACZ,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,EACrC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,UAAU,EAC9C,SAAS,EAAE,UAAU,CACjB,0BAA0B,EAC1B,EAAE,EAAE,IAAI,EAAE,SAAS,CACtB,EAAA,kBAAA,EACgB,MAAM,EAAA,eAAA,EACR,OAAO,IAAI,SAAS,EAAA,QAAA,EAElC,IAAI,CAAC,KAAK,EAAA,CACJ,EACV,CAAC,OAAO,KACLJ,GAAA,CAAA,MAAA,EAAA,EAAA,GACQ,EAAE,EAAE,SAAS,EAAA,aAAA,EACL,MAAM,EAClB,SAAS,EAAE,UAAU,CACjB,+BAA+B,EAC/B,EAAE,EAAE,SAAS,EAAE,SAAS,CAC3B,EAAA,kBAAA,EACgB,WAAW,EAAA,QAAA,EAE3B,SAAS,EAAA,CACP,CACV,CAAA,EAAA,EApCI,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA,CAAE,CAqC7B;AAErB,QAAA,CAAC,CAAC,EAAA,CACY,EAAA,CAChB;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../Common/ComboBox.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../Common/ComboBox.tsx"],"names":[],"mappings":"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"}