@workbench-kit/react 0.0.2-prototype.0.1.2 → 0.0.2-prototype.0.2.10

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 (543) hide show
  1. package/README.md +87 -0
  2. package/package.json +37 -27
  3. package/src/brand/TilepaperAppIcon.tsx +181 -0
  4. package/src/brand/index.ts +2 -0
  5. package/src/brand/tilepaper-app-icon-geometry.ts +201 -0
  6. package/src/icons/WorkbenchIcon.tsx +57 -0
  7. package/src/icons/WorkbenchIconContext.tsx +25 -0
  8. package/src/icons/file-icon.ts +154 -0
  9. package/src/icons/index.ts +17 -0
  10. package/src/icons/resolveWorkbenchIcon.ts +48 -0
  11. package/src/icons/types.ts +28 -0
  12. package/src/index.ts +278 -88
  13. package/src/jdw/JdwPreview.tsx +165 -8
  14. package/src/jdw/JdwPreviewViewport.tsx +190 -0
  15. package/src/jdw/JsonCodeEditorPane.tsx +172 -21
  16. package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +101 -0
  17. package/src/jdw/createBuiltinJdwRegistry.ts +330 -5
  18. package/src/jdw/cssRenderBackend.tsx +96 -7
  19. package/src/jdw/document.ts +0 -3
  20. package/src/jdw/fixtures/jdw-sample-screens.ts +10 -8
  21. package/src/jdw/index.ts +9 -4
  22. package/src/jdw/jdw-preview-viewport.css +41 -0
  23. package/src/jdw/renderJdw.tsx +49 -8
  24. package/src/json-config/JsonConfigWorkbench.tsx +12 -15
  25. package/src/layout/ViewEmptyState.tsx +14 -0
  26. package/src/layout/WorkbenchCanvas.tsx +113 -6
  27. package/src/layout/WorkbenchLayout.tsx +3 -0
  28. package/src/layout/WorkbenchLayoutBase.tsx +43 -2
  29. package/src/layout/WorkbenchMediaPreviewViewport.tsx +122 -0
  30. package/src/layout/WorkbenchPropertyOverrideLabel.tsx +90 -0
  31. package/src/layout/WorkbenchPropertyPanel.tsx +153 -17
  32. package/src/layout/WorkbenchPropertySearch.tsx +51 -0
  33. package/src/layout/WorkbenchTree.tsx +9 -10
  34. package/src/layout/canvas/canvas-drag-ghost.css +21 -0
  35. package/src/layout/canvas/canvas-drag-preview-frame.css +15 -0
  36. package/src/layout/canvas/canvas-drop-indicator.css +16 -0
  37. package/src/layout/canvas/canvas-frame-handle.css +37 -0
  38. package/src/layout/canvas/canvas-frame-surface.css +24 -0
  39. package/src/layout/canvas/canvas-guide-block.css +17 -0
  40. package/src/layout/canvas/canvas-guide-layer.css +6 -0
  41. package/src/layout/canvas/canvas-guide-line.css +22 -0
  42. package/src/layout/canvas/canvas-item-badge.css +23 -0
  43. package/src/layout/canvas/canvas-item-frame.css +54 -0
  44. package/src/layout/canvas/canvas-pane-surface.css +9 -0
  45. package/src/layout/canvas/canvas-placeholder.css +21 -0
  46. package/src/layout/canvas/canvas-resize-frame.css +9 -0
  47. package/src/layout/canvas/canvas-resize-handle.css +74 -0
  48. package/src/layout/canvas/canvas-resize-preview.css +11 -0
  49. package/src/layout/canvas/canvas-selection-marquee.css +14 -0
  50. package/src/layout/canvas/canvas-viewport.css +18 -0
  51. package/src/layout/canvas/index.css +19 -0
  52. package/src/layout/canvas/preview-canvas.css +144 -0
  53. package/src/layout/editor/editor-body.css +9 -0
  54. package/src/layout/editor/editor-bottom-panel.css +44 -0
  55. package/src/layout/editor/editor-frame.css +14 -0
  56. package/src/layout/editor/editor-viewport.css +7 -0
  57. package/src/layout/editor/floating-menu.css +91 -0
  58. package/src/layout/editor/index.css +10 -0
  59. package/src/layout/editor/parse-error.css +9 -0
  60. package/src/layout/editor/problem-item.css +52 -0
  61. package/src/layout/editor/problem-list.css +7 -0
  62. package/src/layout/editor/render-surface.css +13 -0
  63. package/src/layout/fillScrollContract.ts +49 -0
  64. package/src/layout/fullscreen/fullscreen-backdrop.css +31 -0
  65. package/src/layout/fullscreen/fullscreen-button.css +44 -0
  66. package/src/layout/fullscreen/fullscreen-carousel.css +20 -0
  67. package/src/layout/fullscreen/fullscreen-content.css +8 -0
  68. package/src/layout/fullscreen/fullscreen-empty.css +16 -0
  69. package/src/layout/fullscreen/fullscreen-header.css +77 -0
  70. package/src/layout/fullscreen/fullscreen-hero.css +41 -0
  71. package/src/layout/fullscreen/fullscreen-nav-button.css +29 -0
  72. package/src/layout/fullscreen/fullscreen-option.css +83 -0
  73. package/src/layout/fullscreen/fullscreen-pill-row.css +6 -0
  74. package/src/layout/fullscreen/fullscreen-pill.css +10 -0
  75. package/src/layout/fullscreen/fullscreen-root.css +11 -0
  76. package/src/layout/fullscreen/index.css +13 -0
  77. package/src/layout/index.ts +156 -0
  78. package/src/layout/layout-base/banner.css +32 -0
  79. package/src/layout/layout-base/center.css +7 -0
  80. package/src/layout/layout-base/column.css +7 -0
  81. package/src/layout/layout-base/divider.css +5 -0
  82. package/src/layout/layout-base/empty.css +12 -0
  83. package/src/layout/layout-base/fill-scroll.css +36 -0
  84. package/src/layout/layout-base/fill.css +18 -0
  85. package/src/layout/layout-base/index.css +13 -0
  86. package/src/layout/layout-base/pane.css +6 -0
  87. package/src/layout/layout-base/panel-scroll.css +5 -0
  88. package/src/layout/layout-base/panel-surface.css +14 -0
  89. package/src/layout/layout-base/root.css +9 -0
  90. package/src/layout/layout-base/section-title.css +8 -0
  91. package/src/layout/layout.css +10 -0
  92. package/src/layout/layoutHelpers.ts +4 -2
  93. package/src/layout/media/index.css +2 -0
  94. package/src/layout/media/media-preview-viewport.css +69 -0
  95. package/src/layout/{Panel.tsx → panel/Panel.tsx} +29 -40
  96. package/src/layout/panel/TemplateGallery.tsx +90 -0
  97. package/src/layout/panel/WorkbenchAuthoringShell.tsx +57 -0
  98. package/src/layout/panel/WorkbenchLabeledPane.tsx +81 -0
  99. package/src/layout/panel/WorkbenchSidebarStack.tsx +15 -0
  100. package/src/layout/panel/filter-bar.css +59 -0
  101. package/src/layout/panel/index.css +7 -0
  102. package/src/layout/panel/index.ts +70 -0
  103. package/src/layout/panel/preview-pane.css +63 -0
  104. package/src/layout/panel/template-gallery.css +131 -0
  105. package/src/layout/panel/workbench-authoring-shell.css +48 -0
  106. package/src/layout/panel/workbench-labeled-pane.css +69 -0
  107. package/src/layout/panel/workbench-sidebar-stack.css +18 -0
  108. package/src/layout/property/color-input.css +8 -0
  109. package/src/layout/property/color-row.css +6 -0
  110. package/src/layout/property/index.css +15 -0
  111. package/src/layout/property/property-card.css +8 -0
  112. package/src/layout/property/property-grid.css +24 -0
  113. package/src/layout/property/property-hint.css +4 -0
  114. package/src/layout/property/property-inline.css +10 -0
  115. package/src/layout/property/property-key-value.css +29 -0
  116. package/src/layout/property/property-override-label.css +34 -0
  117. package/src/layout/property/property-panel.css +20 -0
  118. package/src/layout/property/property-row.css +17 -0
  119. package/src/layout/property/property-search.css +43 -0
  120. package/src/layout/property/property-section.css +97 -0
  121. package/src/layout/property/property-stack.css +11 -0
  122. package/src/layout/property/property-toggle.css +14 -0
  123. package/src/layout/propertyFieldFilter.ts +84 -0
  124. package/src/layout/sidebar/SideBarViewFrame.tsx +235 -0
  125. package/src/layout/sidebar/SideBarViewTabStrip.tsx +60 -0
  126. package/src/layout/sidebar/SideBarViewTitleMenu.tsx +75 -0
  127. package/src/layout/sidebar/SidebarActionIconBar.tsx +242 -0
  128. package/src/layout/sidebar/SidebarSectionNestingContext.tsx +21 -0
  129. package/src/layout/sidebar/SidebarSlotChrome.tsx +32 -0
  130. package/src/layout/sidebar/SidebarToolbar.tsx +10 -0
  131. package/src/layout/sidebar/WorkbenchActionSidebar.tsx +73 -0
  132. package/src/layout/{WorkbenchSidebarActions.tsx → sidebar/WorkbenchSidebarActions.tsx} +105 -51
  133. package/src/layout/sidebar/WorkbenchSidebarSectionStack.tsx +165 -0
  134. package/src/layout/sidebar/index.css +5 -0
  135. package/src/layout/sidebar/index.ts +55 -0
  136. package/src/layout/sidebar/sidebar-chrome.css +95 -0
  137. package/src/layout/sidebar/sidebar-section-stack.css +25 -0
  138. package/src/layout/sidebar/sidebar-section.css +124 -0
  139. package/src/layout/sidebar/sidebar-view.css +290 -0
  140. package/src/layout/tree/drag-preview.css +25 -0
  141. package/src/layout/tree/index.css +10 -0
  142. package/src/layout/tree/template-glyph.css +96 -0
  143. package/src/layout/tree/tree-action.css +20 -0
  144. package/src/layout/tree/tree-drag-overlay.css +13 -0
  145. package/src/layout/tree/tree-drop-line.css +17 -0
  146. package/src/layout/tree/tree-drop-zone.css +13 -0
  147. package/src/layout/tree/tree-expander.css +23 -0
  148. package/src/layout/tree/tree-item.css +93 -0
  149. package/src/layout/tree/tree.css +49 -0
  150. package/src/layout/usePreviewViewport.ts +428 -0
  151. package/src/modal/ConfirmDialog.tsx +1 -1
  152. package/src/modal/Modal.tsx +184 -311
  153. package/src/modal/ModalResizeHandles.tsx +40 -0
  154. package/src/modal/ModalTitlebar.tsx +86 -0
  155. package/src/modal/modal.css +291 -0
  156. package/src/modal/modalContainer.ts +36 -0
  157. package/src/modal/modalPosition.ts +36 -0
  158. package/src/modal/modalSize.ts +84 -0
  159. package/src/modal/modalTypes.ts +13 -0
  160. package/src/modal/useModalContainerViewport.ts +41 -0
  161. package/src/modal/useModalDrag.ts +118 -0
  162. package/src/modal/useModalFocusTrap.ts +142 -0
  163. package/src/modal/useModalResize.ts +122 -0
  164. package/src/modal/useModalWindowFrame.ts +122 -0
  165. package/src/overlay/ContextMenu.tsx +28 -50
  166. package/src/overlay/clampFixedOverlayPosition.ts +22 -0
  167. package/src/overlay/context-menu.css +127 -0
  168. package/src/overlay/index.ts +31 -0
  169. package/src/overlay/measureAnchoredOverlayPanel.ts +107 -0
  170. package/src/overlay/overlay.css +2 -0
  171. package/src/overlay/pointerPassthroughRegion.ts +83 -0
  172. package/src/overlay/useAnchoredOverlayPanel.ts +222 -0
  173. package/src/overlay/useClampedFixedOverlayPosition.ts +27 -0
  174. package/src/overlay/useContextMenuState.ts +59 -0
  175. package/src/overlay/useFixedOverlayDismiss.ts +49 -0
  176. package/src/overlay/usePointerPassthroughRegion.ts +87 -0
  177. package/src/primitives/{AbsoluteBox.tsx → absolute-box/AbsoluteBox.tsx} +5 -5
  178. package/src/primitives/absolute-box/index.ts +1 -0
  179. package/src/primitives/{Badge.tsx → badge/Badge.tsx} +4 -2
  180. package/src/primitives/badge/badge.css +20 -0
  181. package/src/primitives/badge/index.ts +1 -0
  182. package/src/primitives/{Button.tsx → button/Button.tsx} +7 -6
  183. package/src/primitives/button/button.css +76 -0
  184. package/src/primitives/button/index.ts +1 -0
  185. package/src/primitives/catalog-browse-card/CatalogBrowseCard.tsx +121 -0
  186. package/src/primitives/catalog-browse-card/catalog-browse-card.css +175 -0
  187. package/src/primitives/catalog-browse-card/index.ts +1 -0
  188. package/src/primitives/catalog-browse-pane/CatalogBrowseFacetChips.tsx +59 -0
  189. package/src/primitives/catalog-browse-pane/CatalogBrowsePane.tsx +360 -0
  190. package/src/primitives/catalog-browse-pane/catalog-browse-facet-chips.css +8 -0
  191. package/src/primitives/catalog-browse-pane/catalog-browse-pane.css +84 -0
  192. package/src/primitives/catalog-browse-pane/filterCatalogBrowseItems.ts +27 -0
  193. package/src/primitives/catalog-browse-pane/index.ts +3 -0
  194. package/src/primitives/catalog-filter-overlay/CatalogFilterOverlay.tsx +73 -0
  195. package/src/primitives/catalog-filter-overlay/catalog-filter-overlay.css +65 -0
  196. package/src/primitives/catalog-filter-overlay/index.ts +1 -0
  197. package/src/primitives/checkbox/Checkbox.tsx +40 -0
  198. package/src/primitives/checkbox/checkbox.css +81 -0
  199. package/src/primitives/checkbox/index.ts +1 -0
  200. package/src/primitives/chip/Chip.tsx +43 -0
  201. package/src/primitives/chip/chip.css +110 -0
  202. package/src/primitives/chip/index.ts +2 -0
  203. package/src/primitives/clearable-text-input/ClearableTextInput.tsx +78 -0
  204. package/src/primitives/clearable-text-input/clearable-text-input.css +15 -0
  205. package/src/primitives/clearable-text-input/index.ts +1 -0
  206. package/src/primitives/codicon/Codicon.tsx +20 -0
  207. package/src/primitives/codicon/index.ts +1 -0
  208. package/src/primitives/{EmptyState.tsx → empty-state/EmptyState.tsx} +9 -3
  209. package/src/primitives/empty-state/empty-state.css +20 -0
  210. package/src/primitives/empty-state/index.ts +1 -0
  211. package/src/primitives/external-link-button/ExternalLinkButton.tsx +56 -0
  212. package/src/primitives/external-link-button/index.ts +1 -0
  213. package/src/primitives/{Field.tsx → field/Field.tsx} +2 -1
  214. package/src/primitives/field/field.css +51 -0
  215. package/src/primitives/field/index.ts +1 -0
  216. package/src/primitives/file-icon/FileIcon.tsx +21 -0
  217. package/src/primitives/file-icon/index.ts +1 -0
  218. package/src/primitives/{IconButton.tsx → icon-button/IconButton.tsx} +7 -5
  219. package/src/primitives/icon-button/icon-button.css +46 -0
  220. package/src/primitives/icon-button/index.ts +1 -0
  221. package/src/primitives/index.ts +210 -50
  222. package/src/primitives/library-detail-layout/LibraryDetailLayout.tsx +135 -0
  223. package/src/primitives/library-detail-layout/index.ts +1 -0
  224. package/src/primitives/library-detail-layout/library-detail-layout.css +169 -0
  225. package/src/primitives/library-facet-filter-panel/LibraryFacetFilterPanel.tsx +454 -0
  226. package/src/primitives/library-facet-filter-panel/index.ts +1 -0
  227. package/src/primitives/library-facet-filter-panel/library-facet-filter-panel.css +205 -0
  228. package/src/primitives/library-facet-filter-strip/LibraryFacetFilterStrip.tsx +527 -0
  229. package/src/primitives/library-facet-filter-strip/index.ts +1 -0
  230. package/src/primitives/library-facet-filter-strip/library-facet-filter-strip.css +31 -0
  231. package/src/primitives/{List.tsx → list/List.tsx} +15 -6
  232. package/src/primitives/list/index.ts +1 -0
  233. package/src/primitives/list/list-empty-state.css +10 -0
  234. package/src/primitives/list/list-item.css +93 -0
  235. package/src/primitives/list/list.css +6 -0
  236. package/src/primitives/number-input/NumberInput.tsx +235 -0
  237. package/src/primitives/number-input/index.ts +1 -0
  238. package/src/primitives/number-input/number-input.css +105 -0
  239. package/src/primitives/panel-loading/PanelLoading.tsx +29 -0
  240. package/src/primitives/panel-loading/index.ts +1 -0
  241. package/src/primitives/panel-loading/panel-loading.css +16 -0
  242. package/src/primitives/panel-surface/panel-surface.css +77 -0
  243. package/src/primitives/primitives.css +36 -0
  244. package/src/primitives/record-media-hero/RecordMediaHero.tsx +81 -0
  245. package/src/primitives/record-media-hero/index.ts +1 -0
  246. package/src/primitives/record-media-hero/record-media-hero.css +84 -0
  247. package/src/primitives/scroll-area/ScrollArea.tsx +200 -0
  248. package/src/primitives/scroll-area/index.ts +1 -0
  249. package/src/primitives/scroll-area/scroll-area-overlay.css +69 -0
  250. package/src/primitives/scroll-area-infinite-load/ScrollAreaInfiniteSentinel.tsx +22 -0
  251. package/src/primitives/scroll-area-infinite-load/index.ts +2 -0
  252. package/src/primitives/scroll-area-infinite-load/scroll-area-infinite-sentinel.css +6 -0
  253. package/src/primitives/scroll-area-infinite-load/useScrollAreaInfiniteLoad.ts +84 -0
  254. package/src/primitives/searchable-multi-select/SearchableMultiSelect.tsx +378 -0
  255. package/src/primitives/searchable-multi-select/index.ts +9 -0
  256. package/src/primitives/searchable-multi-select/overlay.ts +125 -0
  257. package/src/primitives/searchable-multi-select/searchable-multi-select.css +129 -0
  258. package/src/primitives/select/Select.tsx +21 -3
  259. package/src/primitives/select/overlay.ts +23 -4
  260. package/src/primitives/select/select.app.css +5 -2
  261. package/src/primitives/select/select.css +49 -12
  262. package/src/primitives/styles.css +3 -952
  263. package/src/primitives/tabbed-panels/TabbedPanels.tsx +68 -0
  264. package/src/primitives/tabbed-panels/index.ts +2 -0
  265. package/src/primitives/tabbed-panels/tabbed-panels.css +58 -0
  266. package/src/primitives/{TextArea.tsx → text-area/TextArea.tsx} +3 -2
  267. package/src/primitives/text-area/index.ts +1 -0
  268. package/src/primitives/{TextInput.tsx → text-input/TextInput.tsx} +3 -2
  269. package/src/primitives/text-input/index.ts +1 -0
  270. package/src/primitives/text-input/input.css +54 -0
  271. package/src/primitives/{Toolbar.tsx → toolbar/Toolbar.tsx} +1 -1
  272. package/src/primitives/toolbar/index.ts +1 -0
  273. package/src/primitives/visually-hidden/visually-hidden.css +11 -0
  274. package/src/primitives/{WorkbenchEditor.tsx → workbench-editor/WorkbenchEditor.tsx} +81 -43
  275. package/src/primitives/workbench-editor/button-group.css +10 -0
  276. package/src/primitives/workbench-editor/editor-tabs.css +201 -0
  277. package/src/primitives/workbench-editor/index.ts +1 -0
  278. package/src/primitives/workbench-editor/resizable-panels.css +53 -0
  279. package/src/primitives/workbench-editor/segmented-control.css +98 -0
  280. package/src/primitives/workbench-media-slot/WorkbenchMediaPlaceholder.tsx +25 -0
  281. package/src/primitives/workbench-media-slot/WorkbenchMediaSlot.tsx +60 -0
  282. package/src/primitives/workbench-media-slot/index.ts +2 -0
  283. package/src/primitives/workbench-media-slot/media-slot.css +72 -0
  284. package/src/primitives/workbench-thumbnail/WorkbenchThumbnail.tsx +38 -0
  285. package/src/primitives/workbench-thumbnail/index.ts +1 -0
  286. package/src/primitives/workbench-thumbnail/thumbnail.css +69 -0
  287. package/src/scrollbars.css +77 -2
  288. package/src/styles.css +13 -7735
  289. package/src/test-utils/workbenchMonacoMock.tsx +37 -0
  290. package/src/utils/dragMime.ts +89 -0
  291. package/src/utils/useWorkbenchMediaImage.ts +37 -0
  292. package/src/widget-asset/WidgetAssetEditor.tsx +9 -7
  293. package/src/widget-asset/WidgetAssetModeControls.tsx +1 -1
  294. package/src/widget-asset/WidgetAssetWorkbench.tsx +5 -6
  295. package/src/widget-studio/create-widget-studio-workspace-editor.tsx +1 -2
  296. package/src/widget-studio/index.ts +4 -1
  297. package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +27 -10
  298. package/src/widget-tree/WidgetAssetPalette.tsx +35 -7
  299. package/src/widget-tree/WidgetInspectorPanel.tsx +53 -3
  300. package/src/widget-tree/WidgetSourceEditor.tsx +90 -3
  301. package/src/widget-tree/WidgetTreeCanvasPreview.tsx +875 -0
  302. package/src/widget-tree/WidgetTreeLab.tsx +411 -83
  303. package/src/widget-tree/WidgetTreeModeControls.tsx +30 -1
  304. package/src/widget-tree/WidgetTreeSidePanel.tsx +24 -34
  305. package/src/widget-tree/WidgetTreeView.tsx +711 -11
  306. package/src/widget-tree/WidgetTreeWorkbench.tsx +59 -15
  307. package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +28 -10
  308. package/src/widget-tree/index.ts +22 -4
  309. package/src/widget-tree/widget-placement-asset-dnd.ts +35 -0
  310. package/src/widget-tree/widget-tree-document.ts +3 -9
  311. package/src/widget-tree/widget-tree-editor-state.ts +40 -0
  312. package/src/widget-tree/widget-tree-layout.ts +48 -3
  313. package/src/widget-tree/widget-tree-play-helpers.ts +69 -58
  314. package/src/workbench/auth/WorkbenchLoginView.tsx +4 -6
  315. package/src/workbench/auth/auth-flows.css +440 -0
  316. package/src/workbench/auth/auth.css +3 -0
  317. package/src/workbench/auth/profile-modals.css +115 -0
  318. package/src/workbench/bootstrap/WorkbenchBootstrapGate.tsx +45 -0
  319. package/src/workbench/bootstrap/WorkbenchBootstrapView.tsx +100 -0
  320. package/src/workbench/bootstrap/index.ts +12 -0
  321. package/src/workbench/bootstrap/useWorkbenchBootstrap.ts +130 -0
  322. package/src/workbench/chat/ChatCommandProposalCard.tsx +115 -0
  323. package/src/workbench/chat/ChatComposer.tsx +32 -34
  324. package/src/workbench/chat/ChatConversationBar.tsx +134 -0
  325. package/src/workbench/chat/ChatHistoryMenu.tsx +171 -0
  326. package/src/workbench/chat/ChatHistoryMenuRow.tsx +74 -0
  327. package/src/workbench/chat/ChatMessageCollapsible.tsx +119 -0
  328. package/src/workbench/chat/ChatMessageItem.tsx +351 -19
  329. package/src/workbench/chat/ChatMessageList.tsx +109 -24
  330. package/src/workbench/chat/ChatPanel.tsx +141 -19
  331. package/src/workbench/chat/ChatPhasedRunProgress.tsx +275 -0
  332. package/src/workbench/chat/ChatRenameDialog.tsx +77 -0
  333. package/src/workbench/chat/chat-conversation.css +273 -0
  334. package/src/workbench/chat/chat-ui.css +1132 -0
  335. package/src/workbench/chat/chat.css +3 -0
  336. package/src/workbench/chat/chatConversation.ts +46 -0
  337. package/src/workbench/chat/chatHistoryRowMenuItems.ts +29 -0
  338. package/src/workbench/chat/chatMessageMeta.tsx +252 -0
  339. package/src/workbench/chat/chatScroll.ts +22 -0
  340. package/src/workbench/chat/index.ts +48 -1
  341. package/src/workbench/chat/slashCommand.ts +5 -7
  342. package/src/workbench/chat/types.ts +35 -0
  343. package/src/workbench/chat/useCancelRuntimeOnUnmount.ts +60 -0
  344. package/src/workbench/chat/useChatPrependPagination.ts +233 -0
  345. package/src/workbench/chat/useChatRuntimeState.ts +3 -15
  346. package/src/workbench/chat/useSlashCommandSuggest.ts +77 -24
  347. package/src/workbench/chrome/WorkbenchModalPortal.tsx +52 -0
  348. package/src/workbench/chrome/WorkbenchPlatformContext.tsx +31 -0
  349. package/src/workbench/chrome/index.css +6 -0
  350. package/src/workbench/chrome/workbench-chrome.css +4 -0
  351. package/src/workbench/chrome/workbench-desktop-titlebar.css +60 -0
  352. package/src/workbench/chrome/workbench-host.css +85 -0
  353. package/src/workbench/chrome/workbench-layout-regions.css +42 -0
  354. package/src/workbench/chrome/workbench-platform-chrome.css +142 -0
  355. package/src/workbench/chrome/workbench-shell-titlebar.css +124 -0
  356. package/src/workbench/chrome/workbenchModalViewState.ts +52 -0
  357. package/src/workbench/chrome/workbenchOverlaysContext.tsx +21 -0
  358. package/src/workbench/chrome/workbenchPlatformChrome.ts +40 -0
  359. package/src/workbench/command-palette/command-palette.css +156 -0
  360. package/src/workbench/commands/CommandGroupShell.tsx +131 -0
  361. package/src/workbench/commands/CommandList.tsx +167 -0
  362. package/src/workbench/commands/CommandPalette.tsx +391 -0
  363. package/src/workbench/{ConfirmationFlow.tsx → commands/ConfirmationFlow.tsx} +6 -8
  364. package/src/workbench/{ShortcutCommandBridge.tsx → commands/ShortcutCommandBridge.tsx} +1 -4
  365. package/src/workbench/commands/command-execution-policy.ts +61 -0
  366. package/src/workbench/commands/command-model.ts +279 -0
  367. package/src/workbench/{commands.ts → commands/commands.ts} +63 -7
  368. package/src/workbench/commands/workbenchContextMenu.ts +18 -0
  369. package/src/workbench/editor/WorkbenchEditorTabs.tsx +52 -0
  370. package/src/workbench/editor/editor-tabs-dnd.ts +162 -0
  371. package/src/workbench/editor/editorTabContextMenu.ts +111 -0
  372. package/src/workbench/editor/useEditorTabsStripDnd.ts +262 -0
  373. package/src/workbench/editor/useWorkbenchEditorTabContextMenu.tsx +66 -0
  374. package/src/workbench/editor-tabs/index.ts +22 -0
  375. package/src/workbench/index.ts +288 -37
  376. package/src/workbench/management/AccountManagementPanel.tsx +82 -0
  377. package/src/workbench/management/CommandInspectorPanel.tsx +127 -0
  378. package/src/workbench/management/CommandManagementPanel.tsx +129 -0
  379. package/src/workbench/management/CommandManagementSidebar.tsx +318 -0
  380. package/src/workbench/management/ExtensionManagementPanel.tsx +527 -0
  381. package/src/workbench/management/ExtensionManagementSidebar.tsx +509 -0
  382. package/src/workbench/management/IntegrationCommandActions.tsx +78 -0
  383. package/src/workbench/management/IntegrationSettingsSurface.tsx +290 -0
  384. package/src/workbench/management/IntegrationsShell.tsx +53 -0
  385. package/src/workbench/management/KeybindingCaptureField.tsx +142 -0
  386. package/src/workbench/management/KeybindingManagementPanel.tsx +120 -0
  387. package/src/workbench/management/LibraryCatalogPickerDialog.tsx +208 -0
  388. package/src/workbench/management/LibraryFacetFilterDialog.tsx +62 -0
  389. package/src/workbench/management/ManagementCard.tsx +89 -0
  390. package/src/workbench/management/ManagementFilterChips.tsx +41 -0
  391. package/src/workbench/management/ManagementGroup.tsx +56 -0
  392. package/src/workbench/management/ManagementPanelControls.tsx +43 -0
  393. package/src/workbench/management/ManagementPanelFrame.tsx +109 -0
  394. package/src/workbench/management/WorkbenchDialogFrame.tsx +148 -0
  395. package/src/workbench/management/WorkbenchNotice.tsx +211 -0
  396. package/src/workbench/management/build-command-management-groups.ts +157 -0
  397. package/src/workbench/management/command-inspector-uri.ts +26 -0
  398. package/src/workbench/management/extension-category-display.ts +42 -0
  399. package/src/workbench/management/extension-install-approval.ts +72 -0
  400. package/src/workbench/management/format-command-run-state.ts +19 -0
  401. package/src/workbench/management/index.ts +137 -0
  402. package/src/workbench/management/integration-command-action.ts +25 -0
  403. package/src/workbench/management/library-catalog-picker-dialog.css +56 -0
  404. package/src/workbench/management/library-facet-filter-dialog.css +8 -0
  405. package/src/workbench/management/management-panel.css +444 -0
  406. package/src/workbench/management/management.css +4 -0
  407. package/src/workbench/management/types.ts +139 -0
  408. package/src/workbench/{MarkdownPreview.tsx → markdown/MarkdownPreview.tsx} +26 -15
  409. package/src/workbench/markdown/markdownRemarkPlugins.ts +12 -0
  410. package/src/workbench/markdown/sanitizeMarkdownHref.ts +29 -0
  411. package/src/workbench/schema/index.ts +0 -1
  412. package/src/workbench/settings/NavigationPanel.tsx +41 -2
  413. package/src/workbench/settings/SchemaForm.tsx +20 -7
  414. package/src/workbench/settings/SectionTabPanel.tsx +172 -0
  415. package/src/workbench/settings/SectionedPanel.tsx +40 -286
  416. package/src/workbench/settings/StructuredDataForm.tsx +106 -26
  417. package/src/workbench/settings/StructuredDataSchemaPanel.tsx +345 -93
  418. package/src/workbench/settings/StructuredDataTableView.tsx +2 -2
  419. package/src/workbench/settings/WorkbenchPanelRegion.tsx +1 -1
  420. package/src/workbench/settings/WorkbenchSettingsModal.tsx +116 -62
  421. package/src/workbench/settings/WorkbenchSettingsNav.tsx +3 -3
  422. package/src/workbench/settings/extensionSettingsForm.ts +34 -0
  423. package/src/workbench/settings/index.ts +36 -1
  424. package/src/workbench/settings/navigation-panel.css +59 -0
  425. package/src/workbench/settings/panel-region.css +3 -2
  426. package/src/workbench/settings/schema-form.css +36 -0
  427. package/src/workbench/settings/schemaFormSettingSpec.ts +177 -0
  428. package/src/workbench/settings/schemaFormSettingsCategory.tsx +21 -0
  429. package/src/workbench/settings/section-tab-panel.css +157 -0
  430. package/src/workbench/settings/sectionScrollSpyDom.ts +139 -0
  431. package/src/workbench/settings/sectioned-panel.css +162 -0
  432. package/src/workbench/settings/sectionedPanelScrollSpy.ts +158 -28
  433. package/src/workbench/settings/settings-responsive.css +58 -0
  434. package/src/workbench/settings/settings.css +11 -0
  435. package/src/workbench/settings/settingsCommit.tsx +55 -0
  436. package/src/workbench/settings/structured-data-form.css +114 -0
  437. package/src/workbench/settings/structured-data-schema-panel.css +33 -19
  438. package/src/workbench/settings/structuredDataFormModel.ts +140 -0
  439. package/src/workbench/settings/structuredDataSchema.ts +111 -658
  440. package/src/workbench/settings/structuredDataSchemaDate.ts +197 -0
  441. package/src/workbench/settings/structuredDataSchemaField.ts +105 -0
  442. package/src/workbench/settings/structuredDataSchemaSection.ts +74 -0
  443. package/src/workbench/settings/structuredDataSchemaTable.ts +120 -0
  444. package/src/workbench/settings/structuredDataSchemaTypes.ts +308 -0
  445. package/src/workbench/settings/structuredDataSchemaValidation.ts +166 -0
  446. package/src/workbench/settings/useSectionScrollSpy.ts +420 -0
  447. package/src/workbench/settings/workbench-settings-modal.css +273 -0
  448. package/src/workbench/shell/ActivityBar.tsx +159 -0
  449. package/src/workbench/{ArtifactShell.tsx → shell/ArtifactShell.tsx} +30 -30
  450. package/src/workbench/shell/SplitView.tsx +485 -0
  451. package/src/workbench/{StatusBar.tsx → shell/StatusBar.tsx} +10 -8
  452. package/src/workbench/{StructuredArtifactEditor.tsx → shell/StructuredArtifactEditor.tsx} +9 -9
  453. package/src/workbench/{Timeline.tsx → shell/Timeline.tsx} +19 -24
  454. package/src/workbench/shell/WorkbenchCanvasShell.defaults.ts +106 -0
  455. package/src/workbench/shell/WorkbenchCanvasShell.model.ts +46 -0
  456. package/src/workbench/{WorkbenchCanvasShell.tsx → shell/WorkbenchCanvasShell.tsx} +34 -148
  457. package/src/workbench/shell/WorkbenchDesktopTitleBar.tsx +126 -0
  458. package/src/workbench/shell/WorkbenchShell.tsx +192 -0
  459. package/src/workbench/shell/WorkbenchShellTitleBarLayoutControls.tsx +80 -0
  460. package/src/workbench/shell/WorkbenchStandaloneShell.tsx +604 -0
  461. package/src/workbench/shell/WorkbenchViewEditor.tsx +75 -0
  462. package/src/workbench/shell/WorkbenchViewSidebar.tsx +85 -0
  463. package/src/workbench/shell/WorkbenchWindowChromeControls.tsx +293 -0
  464. package/src/workbench/shell/activity-bar.css +245 -0
  465. package/src/workbench/shell/activityBarOrder.ts +98 -0
  466. package/src/workbench/shell/appearanceLabels.ts +28 -0
  467. package/src/workbench/shell/confirmation-flow.css +87 -0
  468. package/src/workbench/shell/hardReset.ts +64 -0
  469. package/src/workbench/shell/index.css +5 -0
  470. package/src/workbench/shell/shell.ts +152 -0
  471. package/src/workbench/shell/shellPresets.ts +36 -0
  472. package/src/workbench/{shellState.ts → shell/shellState.ts} +16 -23
  473. package/src/workbench/shell/shellViewModel.ts +160 -0
  474. package/src/workbench/shell/sidebarViewPlacementDnd.ts +61 -0
  475. package/src/workbench/shell/split-view.css +188 -0
  476. package/src/workbench/{standalone.ts → shell/standalone.ts} +11 -11
  477. package/src/workbench/shell/status-bar.css +141 -0
  478. package/src/workbench/{status.ts → shell/status.ts} +10 -6
  479. package/src/workbench/shell/useDeferredWorkbenchMount.ts +71 -0
  480. package/src/workbench/shell/useWorkbenchAppearanceDocumentSync.tsx +17 -0
  481. package/src/workbench/shell/useWorkbenchSidebarActionBarDnd.ts +227 -0
  482. package/src/workbench/shell/useWorkbenchSidebarLayout.tsx +232 -0
  483. package/src/workbench/shell/useWorkbenchSidebarViewPlacementDropZone.ts +194 -0
  484. package/src/workbench/shell/useWorkbenchStandaloneShellStateSync.tsx +112 -0
  485. package/src/workbench/shell/workbenchSidebarLayoutContext.ts +46 -0
  486. package/src/workbench/shell/workbenchStandaloneShellReactContext.tsx +80 -0
  487. package/src/workbench/shell/workbenchViewRouteState.ts +151 -0
  488. package/src/workbench/theme/WorkbenchThemeProvider.tsx +142 -0
  489. package/src/workbench/{theme.ts → theme/theme.ts} +9 -3
  490. package/src/workbench/theme/themePresets.ts +191 -0
  491. package/src/workbench/views/action-list.css +144 -0
  492. package/src/workbench/views/artifact-preview.css +184 -0
  493. package/src/workbench/views/command-inspector.css +98 -0
  494. package/src/workbench/views/command-list.css +356 -0
  495. package/src/workbench/views/commands-sidebar.css +51 -0
  496. package/src/workbench/views/extensions-sidebar.css +175 -0
  497. package/src/workbench/views/multi-provider-explorer.css +182 -0
  498. package/src/workbench/views/search.css +10 -0
  499. package/src/workbench/views/timeline.css +239 -0
  500. package/src/workbench/views/view-hosts.css +37 -0
  501. package/src/workbench/views/view-sidebar.css +21 -0
  502. package/src/workbench/views/views.css +12 -0
  503. package/src/workbench/widgets/widget-tree.css +598 -0
  504. package/src/workbench/widgets/widgets.css +2 -0
  505. package/src/workbench/workspace/WorkspaceDraftsContext.tsx +59 -71
  506. package/src/workbench/workspace/WorkspaceEditor.tsx +27 -123
  507. package/src/workbench/workspace/WorkspaceEditorPanel.tsx +68 -9
  508. package/src/workbench/workspace/WorkspaceExplorer.tsx +149 -51
  509. package/src/workbench/workspace/WorkspaceExplorerPanel.tsx +73 -0
  510. package/src/workbench/workspace/WorkspaceFileIcon.tsx +4 -160
  511. package/src/workbench/workspace/WorkspacePathLabel.tsx +42 -0
  512. package/src/workbench/workspace/WorkspaceSearchPanel.tsx +18 -15
  513. package/src/workbench/workspace/WorkspaceSearchResults.tsx +6 -2
  514. package/src/workbench/workspace/build-workspace-explorer-nodes.ts +44 -0
  515. package/src/workbench/workspace/createVirtualWorkspaceExplorerPort.ts +141 -0
  516. package/src/workbench/workspace/explorer-tree-style.ts +18 -0
  517. package/src/workbench/workspace/index.ts +45 -32
  518. package/src/workbench/workspace/json-config-workbench.css +57 -0
  519. package/src/workbench/workspace/monaco-panel.css +71 -0
  520. package/src/workbench/workspace/path.ts +2 -0
  521. package/src/workbench/workspace/useWorkspaceExplorerController.ts +490 -0
  522. package/src/workbench/workspace/workspace-editor.css +235 -0
  523. package/src/workbench/workspace/workspace-explorer-panel.css +33 -0
  524. package/src/workbench/workspace/workspace.css +5 -0
  525. package/src/workbench/workspace/workspaceExplorerController.ts +193 -0
  526. package/src/workbench/workspace/workspaceJsonDiagnostics.ts +8 -7
  527. package/src/workbench-menu-surfaces.css +57 -0
  528. package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +0 -126
  529. package/src/layout/SideBarViewFrame.tsx +0 -367
  530. package/src/primitives/Checkbox.tsx +0 -21
  531. package/src/primitives/NumberInput.tsx +0 -38
  532. package/src/primitives/ScrollArea.tsx +0 -42
  533. package/src/primitives/Select.tsx +0 -1
  534. package/src/primitives/StatusBar.tsx +0 -46
  535. package/src/primitives/WorkbenchChrome.tsx +0 -424
  536. package/src/workbench/ActivityBar.tsx +0 -52
  537. package/src/workbench/CommandPalette.tsx +0 -819
  538. package/src/workbench/SplitView.tsx +0 -136
  539. package/src/workbench/WorkbenchShell.tsx +0 -74
  540. package/src/workbench/WorkbenchStandaloneShell.tsx +0 -318
  541. package/src/workbench/shell.ts +0 -15
  542. package/src/workbench/workspace/MultiProviderExplorer.tsx +0 -625
  543. /package/src/workbench/{keyboard.ts → commands/keyboard.ts} +0 -0
@@ -0,0 +1,139 @@
1
+ export type CommandManagementEntryStatus = 'available' | 'disabled' | 'no-handler';
2
+
3
+ export interface CommandManagementEntry {
4
+ readonly category?: string | undefined;
5
+ readonly description?: string | undefined;
6
+ readonly id: string;
7
+ readonly keybinding?: string | undefined;
8
+ readonly label: string;
9
+ readonly menuSurfaces?: readonly string[] | undefined;
10
+ readonly source: string;
11
+ readonly sourceLabel: string;
12
+ readonly status: CommandManagementEntryStatus;
13
+ }
14
+
15
+ export interface CommandManagementGroup {
16
+ readonly entries: readonly CommandManagementEntry[];
17
+ readonly id: string;
18
+ readonly label: string;
19
+ }
20
+
21
+ export interface CommandManagementRunState {
22
+ readonly commandId: string;
23
+ readonly message?: string | undefined;
24
+ readonly status: 'running' | 'success' | 'error';
25
+ readonly timestamp: number;
26
+ }
27
+
28
+ export type AccountManagementEntryStatus = 'active' | 'signed-out' | 'expired';
29
+
30
+ export interface AccountManagementEntry {
31
+ readonly displayName: string;
32
+ readonly email?: string | undefined;
33
+ readonly id: string;
34
+ readonly providerId: string;
35
+ readonly providerLabel?: string | undefined;
36
+ readonly status?: AccountManagementEntryStatus | undefined;
37
+ }
38
+
39
+ export interface AccountManagementPanelProps {
40
+ accounts: readonly AccountManagementEntry[];
41
+ activeAccountId?: string | undefined;
42
+ automationHint?: string | undefined;
43
+ className?: string | undefined;
44
+ emptyLabel?: string | undefined;
45
+ onSignOut?: ((accountId: string) => void) | undefined;
46
+ sessionLabel?: string | undefined;
47
+ }
48
+
49
+ export interface CommandManagementPanelProps {
50
+ className?: string | undefined;
51
+ emptyLabel?: string | undefined;
52
+ groups: readonly CommandManagementGroup[];
53
+ lastRun?: CommandManagementRunState | undefined;
54
+ onRunCommand?: ((commandId: string) => void | Promise<void>) | undefined;
55
+ query?: string | undefined;
56
+ summaryLabel?: string | undefined;
57
+ }
58
+
59
+ export type ExtensionManagementEntrySource = 'bundled' | 'installed';
60
+
61
+ export interface ExtensionManagementFeatureItem {
62
+ readonly description?: string | undefined;
63
+ readonly id: string;
64
+ readonly label: string;
65
+ }
66
+
67
+ export interface ExtensionManagementFeatureSummary {
68
+ readonly capabilities?: {
69
+ readonly provides: readonly string[];
70
+ readonly requires: readonly string[];
71
+ };
72
+ readonly commands?: readonly ExtensionManagementFeatureItem[] | undefined;
73
+ readonly documentViews?: readonly ExtensionManagementFeatureItem[] | undefined;
74
+ readonly menus?: readonly ExtensionManagementFeatureItem[] | undefined;
75
+ readonly permissions?: readonly string[] | undefined;
76
+ readonly settings?: readonly ExtensionManagementFeatureItem[] | undefined;
77
+ readonly views?: readonly ExtensionManagementFeatureItem[] | undefined;
78
+ }
79
+
80
+ export interface ExtensionManagementDiagnosticSummary {
81
+ readonly message: string;
82
+ readonly severity: 'error' | 'warning';
83
+ }
84
+
85
+ export interface ExtensionInstallPlanSummary {
86
+ readonly blocked: boolean;
87
+ readonly diagnostics?: readonly ExtensionManagementDiagnosticSummary[] | undefined;
88
+ readonly enableExtensionIds?: readonly string[] | undefined;
89
+ readonly installExtensionIds?: readonly string[] | undefined;
90
+ readonly permissions?: readonly string[] | undefined;
91
+ readonly requiresApproval: boolean;
92
+ }
93
+
94
+ export interface ExtensionManagementEntry {
95
+ readonly category: string;
96
+ readonly description?: string | undefined;
97
+ readonly diagnostics?: readonly ExtensionManagementDiagnosticSummary[] | undefined;
98
+ readonly displayName: string;
99
+ readonly enabled: boolean;
100
+ readonly features?: ExtensionManagementFeatureSummary | undefined;
101
+ readonly id: string;
102
+ readonly installedAt?: string | undefined;
103
+ readonly manifestUrl?: string | undefined;
104
+ readonly source: ExtensionManagementEntrySource;
105
+ }
106
+
107
+ export interface ExtensionCatalogBrowseEntry {
108
+ readonly category: string;
109
+ readonly description: string;
110
+ readonly displayName: string;
111
+ readonly icon?: string | undefined;
112
+ readonly id: string;
113
+ readonly installPlan?: ExtensionInstallPlanSummary | undefined;
114
+ readonly installed: boolean;
115
+ readonly manifestUrl: string;
116
+ }
117
+
118
+ export interface ExtensionInstallOptions {
119
+ /** Required when the install plan sets `requiresApproval`. */
120
+ readonly approved?: boolean | undefined;
121
+ }
122
+
123
+ export interface ExtensionManagementPanelProps {
124
+ browseEntries: readonly ExtensionCatalogBrowseEntry[];
125
+ catalogError?: string | undefined;
126
+ catalogLoading?: boolean | undefined;
127
+ className?: string | undefined;
128
+ installedEntries: readonly ExtensionManagementEntry[];
129
+ onInstall?:
130
+ ((entry: ExtensionCatalogBrowseEntry, options?: ExtensionInstallOptions) => void) | undefined;
131
+ onToggleEnabled?: ((entry: ExtensionManagementEntry, enabled: boolean) => void) | undefined;
132
+ /**
133
+ * Host-owned durable trust check. When true for an entry, the install confirm
134
+ * prompt is skipped and `{ approved: true }` is used.
135
+ */
136
+ isInstallTrusted?: ((entry: ExtensionCatalogBrowseEntry) => boolean) | undefined;
137
+ /** Persist trust after the user confirms a permissioned install. */
138
+ onRememberInstallTrust?: ((entry: ExtensionCatalogBrowseEntry) => void) | undefined;
139
+ }
@@ -1,6 +1,11 @@
1
1
  import Markdown from 'react-markdown';
2
2
  import { Children, isValidElement, type ComponentPropsWithoutRef, type ReactNode } from 'react';
3
- import { cx } from '../utils/cx';
3
+ import { cx } from '../../utils/cx';
4
+ import {
5
+ workbenchMarkdownRemarkPlugins,
6
+ workbenchMarkdownRehypePlugins,
7
+ } from './markdownRemarkPlugins';
8
+ import { sanitizeMarkdownHref } from './sanitizeMarkdownHref';
4
9
 
5
10
  export interface WorkbenchMarkdownPreviewProps extends ComponentPropsWithoutRef<'article'> {
6
11
  source: string;
@@ -14,22 +19,28 @@ export function WorkbenchMarkdownPreview({
14
19
  return (
15
20
  <article className={cx('ui-workbench-markdown-preview', className)} {...props}>
16
21
  <Markdown
22
+ remarkPlugins={workbenchMarkdownRemarkPlugins}
23
+ rehypePlugins={workbenchMarkdownRehypePlugins}
17
24
  components={{
18
- a: ({ children, href, ...anchorProps }) => (
19
- <a
20
- href={href}
21
- rel="noreferrer"
22
- target={href?.startsWith('#') ? undefined : '_blank'}
23
- {...anchorProps}
24
- >
25
+ a: ({ children, href }) => {
26
+ const safeHref = sanitizeMarkdownHref(href);
27
+ if (!safeHref) {
28
+ return <span>{children}</span>;
29
+ }
30
+ return (
31
+ <a
32
+ href={safeHref}
33
+ rel="noreferrer"
34
+ target={safeHref.startsWith('#') ? undefined : '_blank'}
35
+ >
36
+ {children}
37
+ </a>
38
+ );
39
+ },
40
+ code: ({ children, className: codeClassName }) => (
41
+ <code className={cx('ui-workbench-markdown-preview__code', codeClassName)}>
25
42
  {children}
26
- </a>
27
- ),
28
- code: ({ className: codeClassName, ...codeProps }) => (
29
- <code
30
- className={cx('ui-workbench-markdown-preview__code', codeClassName)}
31
- {...codeProps}
32
- />
43
+ </code>
33
44
  ),
34
45
  pre: ({ children }) => {
35
46
  const codeBlock = getMarkdownCodeBlock(children);
@@ -0,0 +1,12 @@
1
+ import remarkGfm from 'remark-gfm';
2
+ import rehypeSanitize from 'rehype-sanitize';
3
+
4
+ /** Shared remark plugins for workbench markdown surfaces (preview, chat, etc.). */
5
+ export const workbenchMarkdownRemarkPlugins = [remarkGfm];
6
+
7
+ /**
8
+ * Default rehype pipeline for untrusted markdown (chat / preview).
9
+ * Strips script/event handlers and dangerous URLs via rehype-sanitize.
10
+ * Hosts that need raw HTML must render outside these kit surfaces.
11
+ */
12
+ export const workbenchMarkdownRehypePlugins = [rehypeSanitize];
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Allowlist markdown link targets for safe preview rendering.
3
+ * Blocks javascript:/data:/vbscript: and other non-navigation schemes.
4
+ */
5
+ export function sanitizeMarkdownHref(href: string | undefined): string | undefined {
6
+ if (href == null || href.trim() === '') {
7
+ return undefined;
8
+ }
9
+
10
+ const trimmed = href.trim();
11
+ if (trimmed.startsWith('#')) {
12
+ return trimmed;
13
+ }
14
+
15
+ try {
16
+ const base =
17
+ typeof globalThis.location?.href === 'string' && globalThis.location.href.length > 0
18
+ ? globalThis.location.href
19
+ : 'https://workbench.local/';
20
+ const url = new URL(trimmed, base);
21
+ const protocol = url.protocol.toLowerCase();
22
+ if (protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:') {
23
+ return trimmed;
24
+ }
25
+ return undefined;
26
+ } catch {
27
+ return undefined;
28
+ }
29
+ }
@@ -45,4 +45,3 @@ export {
45
45
  initializeWorkbenchDocumentPatchHistory,
46
46
  } from './workbenchDocumentPatch';
47
47
  export { createPatchFromWorkbenchDocumentAction } from './workbenchDocumentActions';
48
- export type { WorkbenchDocument as JsonWorkbenchDocument } from './workbenchDocument';
@@ -1,4 +1,9 @@
1
1
  import type { ComponentPropsWithRef, ReactNode } from 'react';
2
+ import {
3
+ ScrollArea,
4
+ type ScrollAreaGutter,
5
+ type ScrollAreaScrollbarVisibility,
6
+ } from '../../primitives/scroll-area';
2
7
  import { cx } from '../../utils/cx';
3
8
 
4
9
  export interface WorkbenchNavigationPanelProps extends Omit<
@@ -8,9 +13,16 @@ export interface WorkbenchNavigationPanelProps extends Omit<
8
13
  content: ReactNode;
9
14
  contentClassName?: string | undefined;
10
15
  contentProps?: Omit<ComponentPropsWithRef<'div'>, 'children' | 'className'> | undefined;
16
+ contentScrollGutter?: ScrollAreaGutter | undefined;
17
+ contentScrollProps?: Omit<ComponentPropsWithRef<'div'>, 'children'> | undefined;
18
+ contentScrollbars?: ScrollAreaScrollbarVisibility | undefined;
11
19
  nav?: ReactNode | undefined;
12
20
  navClassName?: string | undefined;
21
+ navOrientation?: 'vertical' | 'horizontal' | undefined;
13
22
  navProps?: Omit<ComponentPropsWithRef<'nav'>, 'children' | 'className'> | undefined;
23
+ navScrollGutter?: ScrollAreaGutter | undefined;
24
+ navScrollProps?: Omit<ComponentPropsWithRef<'div'>, 'children'> | undefined;
25
+ navScrollbars?: ScrollAreaScrollbarVisibility | undefined;
14
26
  }
15
27
 
16
28
  export function WorkbenchNavigationPanel({
@@ -18,29 +30,56 @@ export function WorkbenchNavigationPanel({
18
30
  content,
19
31
  contentClassName,
20
32
  contentProps,
33
+ contentScrollGutter = 'stable',
34
+ contentScrollProps,
35
+ contentScrollbars = 'auto',
21
36
  nav,
22
37
  navClassName,
38
+ navOrientation = 'vertical',
23
39
  navProps,
40
+ navScrollGutter = 'stable',
41
+ navScrollProps,
42
+ navScrollbars = 'auto',
24
43
  ...props
25
44
  }: WorkbenchNavigationPanelProps) {
26
45
  const hasNav = nav !== undefined && nav !== null && nav !== false;
46
+ const { className: contentScrollClassName, ...resolvedContentScrollProps } =
47
+ contentScrollProps ?? {};
48
+ const { className: navScrollClassName, ...resolvedNavScrollProps } = navScrollProps ?? {};
27
49
 
28
50
  return (
29
51
  <div
30
52
  className={cx('ui-workbench-navigation-panel', className)}
31
53
  data-has-nav={hasNav ? 'true' : undefined}
54
+ data-nav-orientation={hasNav ? navOrientation : undefined}
32
55
  {...props}
33
56
  >
34
57
  {hasNav ? (
35
58
  <nav className={cx('ui-workbench-navigation-panel__nav', navClassName)} {...navProps}>
36
- {nav}
59
+ <ScrollArea
60
+ className={cx('ui-workbench-navigation-panel__nav-scroll', navScrollClassName)}
61
+ gutter={navScrollGutter}
62
+ orientation={navOrientation}
63
+ scrollbars={navScrollbars}
64
+ {...resolvedNavScrollProps}
65
+ >
66
+ {nav}
67
+ </ScrollArea>
37
68
  </nav>
38
69
  ) : null}
39
70
  <div
40
71
  className={cx('ui-workbench-navigation-panel__content', contentClassName)}
41
72
  {...contentProps}
42
73
  >
43
- {content}
74
+ <ScrollArea
75
+ className={cx('ui-workbench-navigation-panel__content-scroll', contentScrollClassName)}
76
+ gutter={contentScrollGutter}
77
+ orientation="vertical"
78
+ scrollbars={contentScrollbars}
79
+ {...resolvedContentScrollProps}
80
+ >
81
+ {content}
82
+ </ScrollArea>
44
83
  </div>
45
84
  </div>
46
85
  );
@@ -6,13 +6,14 @@ import {
6
6
  type FormEvent,
7
7
  type ReactNode,
8
8
  } from 'react';
9
- import { Button } from '../../primitives/Button';
10
- import { Checkbox } from '../../primitives/Checkbox';
11
- import { EmptyState } from '../../primitives/EmptyState';
12
- import { Field } from '../../primitives/Field';
13
- import { Select } from '../../primitives/Select';
14
- import { TextInput } from '../../primitives/TextInput';
9
+ import { Button } from '../../primitives/button';
10
+ import { Checkbox } from '../../primitives/checkbox';
11
+ import { EmptyState } from '../../primitives/empty-state';
12
+ import { Field } from '../../primitives/field';
13
+ import { Select } from '../../primitives/select';
14
+ import { TextInput } from '../../primitives/text-input';
15
15
  import { cx } from '../../utils/cx';
16
+ import { useWorkbenchSettingsCommit } from './settingsCommit';
16
17
 
17
18
  export type WorkbenchSchemaFormFieldType = 'checkbox' | 'number' | 'select' | 'text';
18
19
 
@@ -231,6 +232,9 @@ export function WorkbenchSchemaForm({
231
232
  values,
232
233
  ...props
233
234
  }: WorkbenchSchemaFormProps) {
235
+ const settingsCommit = useWorkbenchSettingsCommit();
236
+ const isImmediateSettingsCommit = settingsCommit?.commitMode === 'immediate';
237
+ const resolvedShowActions = isImmediateSettingsCommit ? false : showActions;
234
238
  const generatedId = useId().replace(/:/g, '');
235
239
  const [uncontrolledValues, setUncontrolledValues] = useState(() =>
236
240
  normalizeWorkbenchSchemaFormValues(fields, defaultValues),
@@ -273,6 +277,15 @@ export function WorkbenchSchemaForm({
273
277
 
274
278
  onFieldChange?.(context);
275
279
  onValuesChange?.(nextValues, context);
280
+
281
+ if (isImmediateSettingsCommit) {
282
+ settingsCommit?.onPreferenceChange?.({
283
+ categoryId: settingsCommit.categoryId,
284
+ key: field.id,
285
+ scopeId: settingsCommit.scopeId || undefined,
286
+ value: nextValues[field.id],
287
+ });
288
+ }
276
289
  };
277
290
 
278
291
  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
@@ -330,7 +343,7 @@ export function WorkbenchSchemaForm({
330
343
  })}
331
344
  </div>
332
345
  )}
333
- {showActions ? (
346
+ {resolvedShowActions ? (
334
347
  <div className="ui-workbench-schema-form__actions">
335
348
  <Button disabled={disabled} onClick={() => onCancel?.({ values: resolvedValues })}>
336
349
  {cancelLabel}
@@ -0,0 +1,172 @@
1
+ import { Fragment, useEffect, useRef, useState, type ComponentPropsWithRef } from 'react';
2
+ import { ScrollArea } from '../../primitives/scroll-area';
3
+ import { cx } from '../../utils/cx';
4
+ import type { WorkbenchSectionedPanelItem } from './SectionedPanel';
5
+ import { useSectionScrollSpy } from './useSectionScrollSpy';
6
+
7
+ const SCROLL_EDGE_THRESHOLD = 2;
8
+ const SECTION_TAB_PANEL_SCROLL_SPY_OFFSET = 80;
9
+
10
+ export type WorkbenchSectionTabPanelItem = WorkbenchSectionedPanelItem;
11
+
12
+ export interface WorkbenchSectionTabPanelProps extends Omit<
13
+ ComponentPropsWithRef<'div'>,
14
+ 'children'
15
+ > {
16
+ activeAnchorId?: string | undefined;
17
+ ariaLabel: string;
18
+ contentClassName?: string | undefined;
19
+ defaultActiveAnchorId?: string | undefined;
20
+ equalWidthTabs?: boolean | undefined;
21
+ items: readonly WorkbenchSectionTabPanelItem[];
22
+ navLinkClassName?: string | undefined;
23
+ onActiveAnchorChange?: ((anchorId: string | undefined) => void) | undefined;
24
+ readOnly?: boolean | undefined;
25
+ scrollSpy?: boolean | 'auto' | undefined;
26
+ scrollSpyOffset?: number | undefined;
27
+ scrollSpyScrollBehavior?: ScrollBehavior | undefined;
28
+ }
29
+
30
+ function useSectionTabPanelNavScrollEdges(enabled: boolean) {
31
+ const hostRef = useRef<HTMLDivElement | null>(null);
32
+ const [atStart, setAtStart] = useState(true);
33
+ const [atEnd, setAtEnd] = useState(true);
34
+
35
+ useEffect(() => {
36
+ if (!enabled) {
37
+ return;
38
+ }
39
+
40
+ const host = hostRef.current;
41
+ if (!host) {
42
+ return;
43
+ }
44
+
45
+ const scrollEl = host.querySelector(
46
+ '.ui-workbench-section-tab-panel__tabs-scroll',
47
+ ) as HTMLElement | null;
48
+
49
+ if (!scrollEl) {
50
+ return;
51
+ }
52
+
53
+ const update = () => {
54
+ const { clientWidth, scrollLeft, scrollWidth } = scrollEl;
55
+ const overflow = scrollWidth > clientWidth + SCROLL_EDGE_THRESHOLD;
56
+
57
+ setAtStart(!overflow || scrollLeft <= SCROLL_EDGE_THRESHOLD);
58
+ setAtEnd(!overflow || scrollLeft + clientWidth >= scrollWidth - SCROLL_EDGE_THRESHOLD);
59
+ };
60
+
61
+ update();
62
+
63
+ scrollEl.addEventListener('scroll', update, { passive: true });
64
+
65
+ const resizeObserver = new ResizeObserver(update);
66
+ resizeObserver.observe(scrollEl);
67
+
68
+ const tabs = scrollEl.querySelector('.ui-workbench-section-tab-panel__tabs');
69
+ if (tabs instanceof HTMLElement) {
70
+ resizeObserver.observe(tabs);
71
+ }
72
+
73
+ return () => {
74
+ scrollEl.removeEventListener('scroll', update);
75
+ resizeObserver.disconnect();
76
+ };
77
+ }, [enabled]);
78
+
79
+ return { hostRef, atStart, atEnd };
80
+ }
81
+
82
+ export function WorkbenchSectionTabPanel({
83
+ activeAnchorId,
84
+ ariaLabel,
85
+ className,
86
+ contentClassName,
87
+ defaultActiveAnchorId,
88
+ equalWidthTabs = true,
89
+ items,
90
+ navLinkClassName,
91
+ onActiveAnchorChange,
92
+ readOnly = false,
93
+ scrollSpy = true,
94
+ scrollSpyOffset = SECTION_TAB_PANEL_SCROLL_SPY_OFFSET,
95
+ scrollSpyScrollBehavior = 'smooth',
96
+ ...props
97
+ }: WorkbenchSectionTabPanelProps) {
98
+ const showSectionNav = items.length > 1;
99
+ const anchorOrder = items.map((item) => item.anchorId);
100
+ const navScrollEdges = useSectionTabPanelNavScrollEdges(showSectionNav);
101
+
102
+ const {
103
+ handleContentScroll,
104
+ resolvedActiveAnchorId,
105
+ scrollRef,
106
+ scrollSpyEnabled,
107
+ scrollToAnchor,
108
+ } = useSectionScrollSpy({
109
+ activeAnchorId,
110
+ anchorOrder,
111
+ axis: 'vertical',
112
+ defaultActiveAnchorId,
113
+ offset: scrollSpyOffset,
114
+ onActiveAnchorChange,
115
+ scrollBehavior: scrollSpyScrollBehavior,
116
+ scrollSpy,
117
+ });
118
+
119
+ const sectionNavLinks = items.map((item) => {
120
+ const active = resolvedActiveAnchorId === item.anchorId;
121
+
122
+ return (
123
+ <a
124
+ key={item.anchorId}
125
+ aria-current={active ? 'location' : undefined}
126
+ className={cx('ui-workbench-section-tab-panel__tab', navLinkClassName)}
127
+ data-active={active ? 'true' : undefined}
128
+ href={`#${item.anchorId}`}
129
+ onClick={(event) => {
130
+ event.preventDefault();
131
+ scrollToAnchor(item.anchorId);
132
+ }}
133
+ >
134
+ <span>{item.title}</span>
135
+ {item.count !== undefined ? <em>{item.count}</em> : null}
136
+ </a>
137
+ );
138
+ });
139
+
140
+ return (
141
+ <div
142
+ ref={navScrollEdges.hostRef}
143
+ className={cx('ui-workbench-section-tab-panel', className)}
144
+ data-equal-width-tabs={equalWidthTabs ? 'true' : undefined}
145
+ data-readonly={readOnly ? 'true' : undefined}
146
+ data-scroll-spy={scrollSpyEnabled ? 'true' : 'false'}
147
+ data-tab-scroll-at-end={showSectionNav && !navScrollEdges.atEnd ? 'false' : undefined}
148
+ data-tab-scroll-at-start={showSectionNav && !navScrollEdges.atStart ? 'false' : undefined}
149
+ {...props}
150
+ >
151
+ {showSectionNav ? (
152
+ <nav aria-label={ariaLabel} className="ui-workbench-section-tab-panel__bar">
153
+ <div className="ui-workbench-section-tab-panel__tabs-scroll">
154
+ <div className="ui-workbench-section-tab-panel__tabs">{sectionNavLinks}</div>
155
+ </div>
156
+ </nav>
157
+ ) : null}
158
+ <ScrollArea
159
+ ref={scrollRef}
160
+ className={cx('ui-workbench-section-tab-panel__scroll', contentClassName)}
161
+ gutter="auto"
162
+ orientation="vertical"
163
+ scrollbars="overlay"
164
+ onScroll={handleContentScroll}
165
+ >
166
+ {items.map((item) => (
167
+ <Fragment key={item.anchorId}>{item.render()}</Fragment>
168
+ ))}
169
+ </ScrollArea>
170
+ </div>
171
+ );
172
+ }