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

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 (534) hide show
  1. package/package.json +31 -23
  2. package/src/brand/TilepaperAppIcon.tsx +181 -0
  3. package/src/brand/index.ts +2 -0
  4. package/src/brand/tilepaper-app-icon-geometry.ts +201 -0
  5. package/src/icons/WorkbenchIcon.tsx +57 -0
  6. package/src/icons/WorkbenchIconContext.tsx +25 -0
  7. package/src/icons/file-icon.ts +154 -0
  8. package/src/icons/index.ts +17 -0
  9. package/src/icons/resolveWorkbenchIcon.ts +48 -0
  10. package/src/icons/types.ts +28 -0
  11. package/src/index.ts +261 -71
  12. package/src/jdw/JdwPreview.tsx +165 -8
  13. package/src/jdw/JdwPreviewViewport.tsx +190 -0
  14. package/src/jdw/JsonCodeEditorPane.tsx +165 -15
  15. package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +101 -0
  16. package/src/jdw/createBuiltinJdwRegistry.ts +330 -5
  17. package/src/jdw/cssRenderBackend.tsx +96 -7
  18. package/src/jdw/document.ts +0 -3
  19. package/src/jdw/fixtures/jdw-sample-screens.ts +10 -8
  20. package/src/jdw/index.ts +9 -4
  21. package/src/jdw/jdw-preview-viewport.css +41 -0
  22. package/src/jdw/renderJdw.tsx +49 -8
  23. package/src/json-config/JsonConfigWorkbench.tsx +11 -14
  24. package/src/layout/ViewEmptyState.tsx +14 -0
  25. package/src/layout/WorkbenchCanvas.tsx +113 -6
  26. package/src/layout/WorkbenchLayout.tsx +3 -0
  27. package/src/layout/WorkbenchLayoutBase.tsx +43 -2
  28. package/src/layout/WorkbenchMediaPreviewViewport.tsx +122 -0
  29. package/src/layout/WorkbenchPropertyOverrideLabel.tsx +90 -0
  30. package/src/layout/WorkbenchPropertyPanel.tsx +153 -17
  31. package/src/layout/WorkbenchPropertySearch.tsx +51 -0
  32. package/src/layout/WorkbenchTree.tsx +9 -10
  33. package/src/layout/canvas/canvas-drag-ghost.css +21 -0
  34. package/src/layout/canvas/canvas-drag-preview-frame.css +15 -0
  35. package/src/layout/canvas/canvas-drop-indicator.css +16 -0
  36. package/src/layout/canvas/canvas-frame-handle.css +37 -0
  37. package/src/layout/canvas/canvas-frame-surface.css +24 -0
  38. package/src/layout/canvas/canvas-guide-block.css +17 -0
  39. package/src/layout/canvas/canvas-guide-layer.css +6 -0
  40. package/src/layout/canvas/canvas-guide-line.css +22 -0
  41. package/src/layout/canvas/canvas-item-badge.css +23 -0
  42. package/src/layout/canvas/canvas-item-frame.css +54 -0
  43. package/src/layout/canvas/canvas-pane-surface.css +9 -0
  44. package/src/layout/canvas/canvas-placeholder.css +21 -0
  45. package/src/layout/canvas/canvas-resize-frame.css +9 -0
  46. package/src/layout/canvas/canvas-resize-handle.css +74 -0
  47. package/src/layout/canvas/canvas-resize-preview.css +11 -0
  48. package/src/layout/canvas/canvas-selection-marquee.css +14 -0
  49. package/src/layout/canvas/canvas-viewport.css +18 -0
  50. package/src/layout/canvas/index.css +19 -0
  51. package/src/layout/canvas/preview-canvas.css +144 -0
  52. package/src/layout/editor/editor-body.css +9 -0
  53. package/src/layout/editor/editor-bottom-panel.css +44 -0
  54. package/src/layout/editor/editor-frame.css +14 -0
  55. package/src/layout/editor/editor-viewport.css +7 -0
  56. package/src/layout/editor/floating-menu.css +91 -0
  57. package/src/layout/editor/index.css +10 -0
  58. package/src/layout/editor/parse-error.css +9 -0
  59. package/src/layout/editor/problem-item.css +52 -0
  60. package/src/layout/editor/problem-list.css +7 -0
  61. package/src/layout/editor/render-surface.css +13 -0
  62. package/src/layout/fillScrollContract.ts +49 -0
  63. package/src/layout/fullscreen/fullscreen-backdrop.css +31 -0
  64. package/src/layout/fullscreen/fullscreen-button.css +44 -0
  65. package/src/layout/fullscreen/fullscreen-carousel.css +20 -0
  66. package/src/layout/fullscreen/fullscreen-content.css +8 -0
  67. package/src/layout/fullscreen/fullscreen-empty.css +16 -0
  68. package/src/layout/fullscreen/fullscreen-header.css +77 -0
  69. package/src/layout/fullscreen/fullscreen-hero.css +41 -0
  70. package/src/layout/fullscreen/fullscreen-nav-button.css +29 -0
  71. package/src/layout/fullscreen/fullscreen-option.css +83 -0
  72. package/src/layout/fullscreen/fullscreen-pill-row.css +6 -0
  73. package/src/layout/fullscreen/fullscreen-pill.css +10 -0
  74. package/src/layout/fullscreen/fullscreen-root.css +11 -0
  75. package/src/layout/fullscreen/index.css +13 -0
  76. package/src/layout/index.ts +156 -0
  77. package/src/layout/layout-base/banner.css +32 -0
  78. package/src/layout/layout-base/center.css +7 -0
  79. package/src/layout/layout-base/column.css +7 -0
  80. package/src/layout/layout-base/divider.css +5 -0
  81. package/src/layout/layout-base/empty.css +12 -0
  82. package/src/layout/layout-base/fill-scroll.css +36 -0
  83. package/src/layout/layout-base/fill.css +18 -0
  84. package/src/layout/layout-base/index.css +13 -0
  85. package/src/layout/layout-base/pane.css +6 -0
  86. package/src/layout/layout-base/panel-scroll.css +5 -0
  87. package/src/layout/layout-base/panel-surface.css +14 -0
  88. package/src/layout/layout-base/root.css +9 -0
  89. package/src/layout/layout-base/section-title.css +8 -0
  90. package/src/layout/layout.css +10 -0
  91. package/src/layout/layoutHelpers.ts +4 -2
  92. package/src/layout/media/index.css +2 -0
  93. package/src/layout/media/media-preview-viewport.css +69 -0
  94. package/src/layout/{Panel.tsx → panel/Panel.tsx} +29 -40
  95. package/src/layout/panel/TemplateGallery.tsx +90 -0
  96. package/src/layout/panel/WorkbenchAuthoringShell.tsx +57 -0
  97. package/src/layout/panel/WorkbenchLabeledPane.tsx +81 -0
  98. package/src/layout/panel/WorkbenchSidebarStack.tsx +15 -0
  99. package/src/layout/panel/filter-bar.css +59 -0
  100. package/src/layout/panel/index.css +7 -0
  101. package/src/layout/panel/index.ts +70 -0
  102. package/src/layout/panel/preview-pane.css +63 -0
  103. package/src/layout/panel/template-gallery.css +131 -0
  104. package/src/layout/panel/workbench-authoring-shell.css +48 -0
  105. package/src/layout/panel/workbench-labeled-pane.css +69 -0
  106. package/src/layout/panel/workbench-sidebar-stack.css +18 -0
  107. package/src/layout/property/color-input.css +8 -0
  108. package/src/layout/property/color-row.css +6 -0
  109. package/src/layout/property/index.css +15 -0
  110. package/src/layout/property/property-card.css +8 -0
  111. package/src/layout/property/property-grid.css +24 -0
  112. package/src/layout/property/property-hint.css +4 -0
  113. package/src/layout/property/property-inline.css +10 -0
  114. package/src/layout/property/property-key-value.css +29 -0
  115. package/src/layout/property/property-override-label.css +34 -0
  116. package/src/layout/property/property-panel.css +20 -0
  117. package/src/layout/property/property-row.css +17 -0
  118. package/src/layout/property/property-search.css +43 -0
  119. package/src/layout/property/property-section.css +97 -0
  120. package/src/layout/property/property-stack.css +11 -0
  121. package/src/layout/property/property-toggle.css +14 -0
  122. package/src/layout/propertyFieldFilter.ts +84 -0
  123. package/src/layout/sidebar/SideBarViewFrame.tsx +235 -0
  124. package/src/layout/sidebar/SideBarViewTabStrip.tsx +60 -0
  125. package/src/layout/sidebar/SideBarViewTitleMenu.tsx +75 -0
  126. package/src/layout/sidebar/SidebarActionIconBar.tsx +242 -0
  127. package/src/layout/sidebar/SidebarSectionNestingContext.tsx +21 -0
  128. package/src/layout/sidebar/SidebarSlotChrome.tsx +32 -0
  129. package/src/layout/sidebar/SidebarToolbar.tsx +10 -0
  130. package/src/layout/sidebar/WorkbenchActionSidebar.tsx +73 -0
  131. package/src/layout/{WorkbenchSidebarActions.tsx → sidebar/WorkbenchSidebarActions.tsx} +105 -51
  132. package/src/layout/sidebar/WorkbenchSidebarSectionStack.tsx +165 -0
  133. package/src/layout/sidebar/index.css +5 -0
  134. package/src/layout/sidebar/index.ts +55 -0
  135. package/src/layout/sidebar/sidebar-chrome.css +95 -0
  136. package/src/layout/sidebar/sidebar-section-stack.css +25 -0
  137. package/src/layout/sidebar/sidebar-section.css +124 -0
  138. package/src/layout/sidebar/sidebar-view.css +290 -0
  139. package/src/layout/tree/drag-preview.css +25 -0
  140. package/src/layout/tree/index.css +10 -0
  141. package/src/layout/tree/template-glyph.css +96 -0
  142. package/src/layout/tree/tree-action.css +20 -0
  143. package/src/layout/tree/tree-drag-overlay.css +13 -0
  144. package/src/layout/tree/tree-drop-line.css +17 -0
  145. package/src/layout/tree/tree-drop-zone.css +13 -0
  146. package/src/layout/tree/tree-expander.css +23 -0
  147. package/src/layout/tree/tree-item.css +93 -0
  148. package/src/layout/tree/tree.css +49 -0
  149. package/src/layout/usePreviewViewport.ts +428 -0
  150. package/src/modal/ConfirmDialog.tsx +1 -1
  151. package/src/modal/Modal.tsx +148 -305
  152. package/src/modal/ModalResizeHandles.tsx +40 -0
  153. package/src/modal/ModalTitlebar.tsx +86 -0
  154. package/src/modal/modal.css +291 -0
  155. package/src/modal/modalContainer.ts +36 -0
  156. package/src/modal/modalPosition.ts +36 -0
  157. package/src/modal/modalSize.ts +84 -0
  158. package/src/modal/modalTypes.ts +13 -0
  159. package/src/modal/useModalContainerViewport.ts +41 -0
  160. package/src/modal/useModalDrag.ts +118 -0
  161. package/src/modal/useModalResize.ts +122 -0
  162. package/src/modal/useModalWindowFrame.ts +122 -0
  163. package/src/overlay/ContextMenu.tsx +28 -50
  164. package/src/overlay/clampFixedOverlayPosition.ts +22 -0
  165. package/src/overlay/context-menu.css +127 -0
  166. package/src/overlay/index.ts +31 -0
  167. package/src/overlay/measureAnchoredOverlayPanel.ts +107 -0
  168. package/src/overlay/overlay.css +2 -0
  169. package/src/overlay/pointerPassthroughRegion.ts +83 -0
  170. package/src/overlay/useAnchoredOverlayPanel.ts +222 -0
  171. package/src/overlay/useClampedFixedOverlayPosition.ts +27 -0
  172. package/src/overlay/useContextMenuState.ts +59 -0
  173. package/src/overlay/useFixedOverlayDismiss.ts +49 -0
  174. package/src/overlay/usePointerPassthroughRegion.ts +85 -0
  175. package/src/primitives/{AbsoluteBox.tsx → absolute-box/AbsoluteBox.tsx} +1 -1
  176. package/src/primitives/absolute-box/index.ts +1 -0
  177. package/src/primitives/{Badge.tsx → badge/Badge.tsx} +4 -2
  178. package/src/primitives/badge/badge.css +20 -0
  179. package/src/primitives/badge/index.ts +1 -0
  180. package/src/primitives/{Button.tsx → button/Button.tsx} +3 -2
  181. package/src/primitives/button/button.css +76 -0
  182. package/src/primitives/button/index.ts +1 -0
  183. package/src/primitives/catalog-browse-card/CatalogBrowseCard.tsx +121 -0
  184. package/src/primitives/catalog-browse-card/catalog-browse-card.css +175 -0
  185. package/src/primitives/catalog-browse-card/index.ts +1 -0
  186. package/src/primitives/catalog-browse-pane/CatalogBrowseFacetChips.tsx +59 -0
  187. package/src/primitives/catalog-browse-pane/CatalogBrowsePane.tsx +360 -0
  188. package/src/primitives/catalog-browse-pane/catalog-browse-facet-chips.css +8 -0
  189. package/src/primitives/catalog-browse-pane/catalog-browse-pane.css +84 -0
  190. package/src/primitives/catalog-browse-pane/filterCatalogBrowseItems.ts +27 -0
  191. package/src/primitives/catalog-browse-pane/index.ts +3 -0
  192. package/src/primitives/catalog-filter-overlay/CatalogFilterOverlay.tsx +73 -0
  193. package/src/primitives/catalog-filter-overlay/catalog-filter-overlay.css +65 -0
  194. package/src/primitives/catalog-filter-overlay/index.ts +1 -0
  195. package/src/primitives/checkbox/Checkbox.tsx +40 -0
  196. package/src/primitives/checkbox/checkbox.css +81 -0
  197. package/src/primitives/checkbox/index.ts +1 -0
  198. package/src/primitives/chip/Chip.tsx +43 -0
  199. package/src/primitives/chip/chip.css +110 -0
  200. package/src/primitives/chip/index.ts +2 -0
  201. package/src/primitives/clearable-text-input/ClearableTextInput.tsx +78 -0
  202. package/src/primitives/clearable-text-input/clearable-text-input.css +15 -0
  203. package/src/primitives/clearable-text-input/index.ts +1 -0
  204. package/src/primitives/codicon/Codicon.tsx +20 -0
  205. package/src/primitives/codicon/index.ts +1 -0
  206. package/src/primitives/{EmptyState.tsx → empty-state/EmptyState.tsx} +9 -3
  207. package/src/primitives/empty-state/empty-state.css +20 -0
  208. package/src/primitives/empty-state/index.ts +1 -0
  209. package/src/primitives/external-link-button/ExternalLinkButton.tsx +56 -0
  210. package/src/primitives/external-link-button/index.ts +1 -0
  211. package/src/primitives/{Field.tsx → field/Field.tsx} +2 -1
  212. package/src/primitives/field/field.css +51 -0
  213. package/src/primitives/field/index.ts +1 -0
  214. package/src/primitives/file-icon/FileIcon.tsx +21 -0
  215. package/src/primitives/file-icon/index.ts +1 -0
  216. package/src/primitives/{IconButton.tsx → icon-button/IconButton.tsx} +6 -4
  217. package/src/primitives/icon-button/icon-button.css +46 -0
  218. package/src/primitives/icon-button/index.ts +1 -0
  219. package/src/primitives/index.ts +210 -50
  220. package/src/primitives/library-detail-layout/LibraryDetailLayout.tsx +135 -0
  221. package/src/primitives/library-detail-layout/index.ts +1 -0
  222. package/src/primitives/library-detail-layout/library-detail-layout.css +169 -0
  223. package/src/primitives/library-facet-filter-panel/LibraryFacetFilterPanel.tsx +454 -0
  224. package/src/primitives/library-facet-filter-panel/index.ts +1 -0
  225. package/src/primitives/library-facet-filter-panel/library-facet-filter-panel.css +205 -0
  226. package/src/primitives/library-facet-filter-strip/LibraryFacetFilterStrip.tsx +527 -0
  227. package/src/primitives/library-facet-filter-strip/index.ts +1 -0
  228. package/src/primitives/library-facet-filter-strip/library-facet-filter-strip.css +31 -0
  229. package/src/primitives/{List.tsx → list/List.tsx} +15 -6
  230. package/src/primitives/list/index.ts +1 -0
  231. package/src/primitives/list/list-empty-state.css +10 -0
  232. package/src/primitives/list/list-item.css +93 -0
  233. package/src/primitives/list/list.css +6 -0
  234. package/src/primitives/number-input/NumberInput.tsx +235 -0
  235. package/src/primitives/number-input/index.ts +1 -0
  236. package/src/primitives/number-input/number-input.css +105 -0
  237. package/src/primitives/panel-loading/PanelLoading.tsx +29 -0
  238. package/src/primitives/panel-loading/index.ts +1 -0
  239. package/src/primitives/panel-loading/panel-loading.css +16 -0
  240. package/src/primitives/panel-surface/panel-surface.css +77 -0
  241. package/src/primitives/primitives.css +36 -0
  242. package/src/primitives/record-media-hero/RecordMediaHero.tsx +81 -0
  243. package/src/primitives/record-media-hero/index.ts +1 -0
  244. package/src/primitives/record-media-hero/record-media-hero.css +84 -0
  245. package/src/primitives/scroll-area/ScrollArea.tsx +200 -0
  246. package/src/primitives/scroll-area/index.ts +1 -0
  247. package/src/primitives/scroll-area/scroll-area-overlay.css +69 -0
  248. package/src/primitives/scroll-area-infinite-load/ScrollAreaInfiniteSentinel.tsx +22 -0
  249. package/src/primitives/scroll-area-infinite-load/index.ts +2 -0
  250. package/src/primitives/scroll-area-infinite-load/scroll-area-infinite-sentinel.css +6 -0
  251. package/src/primitives/scroll-area-infinite-load/useScrollAreaInfiniteLoad.ts +84 -0
  252. package/src/primitives/searchable-multi-select/SearchableMultiSelect.tsx +378 -0
  253. package/src/primitives/searchable-multi-select/index.ts +9 -0
  254. package/src/primitives/searchable-multi-select/overlay.ts +125 -0
  255. package/src/primitives/searchable-multi-select/searchable-multi-select.css +129 -0
  256. package/src/primitives/select/Select.tsx +21 -3
  257. package/src/primitives/select/overlay.ts +23 -4
  258. package/src/primitives/select/select.app.css +5 -2
  259. package/src/primitives/select/select.css +49 -12
  260. package/src/primitives/styles.css +3 -952
  261. package/src/primitives/tabbed-panels/TabbedPanels.tsx +68 -0
  262. package/src/primitives/tabbed-panels/index.ts +2 -0
  263. package/src/primitives/tabbed-panels/tabbed-panels.css +58 -0
  264. package/src/primitives/{TextArea.tsx → text-area/TextArea.tsx} +2 -1
  265. package/src/primitives/text-area/index.ts +1 -0
  266. package/src/primitives/{TextInput.tsx → text-input/TextInput.tsx} +2 -1
  267. package/src/primitives/text-input/index.ts +1 -0
  268. package/src/primitives/text-input/input.css +54 -0
  269. package/src/primitives/{Toolbar.tsx → toolbar/Toolbar.tsx} +1 -1
  270. package/src/primitives/toolbar/index.ts +1 -0
  271. package/src/primitives/visually-hidden/visually-hidden.css +11 -0
  272. package/src/primitives/{WorkbenchEditor.tsx → workbench-editor/WorkbenchEditor.tsx} +81 -43
  273. package/src/primitives/workbench-editor/button-group.css +10 -0
  274. package/src/primitives/workbench-editor/editor-tabs.css +201 -0
  275. package/src/primitives/workbench-editor/index.ts +1 -0
  276. package/src/primitives/workbench-editor/resizable-panels.css +53 -0
  277. package/src/primitives/workbench-editor/segmented-control.css +98 -0
  278. package/src/primitives/workbench-media-slot/WorkbenchMediaPlaceholder.tsx +25 -0
  279. package/src/primitives/workbench-media-slot/WorkbenchMediaSlot.tsx +60 -0
  280. package/src/primitives/workbench-media-slot/index.ts +2 -0
  281. package/src/primitives/workbench-media-slot/media-slot.css +72 -0
  282. package/src/primitives/workbench-thumbnail/WorkbenchThumbnail.tsx +38 -0
  283. package/src/primitives/workbench-thumbnail/index.ts +1 -0
  284. package/src/primitives/workbench-thumbnail/thumbnail.css +69 -0
  285. package/src/scrollbars.css +77 -2
  286. package/src/styles.css +14 -7735
  287. package/src/test-utils/workbenchMonacoMock.tsx +37 -0
  288. package/src/utils/dragMime.ts +89 -0
  289. package/src/utils/useWorkbenchMediaImage.ts +37 -0
  290. package/src/widget-asset/WidgetAssetEditor.tsx +9 -7
  291. package/src/widget-asset/WidgetAssetModeControls.tsx +1 -1
  292. package/src/widget-asset/WidgetAssetWorkbench.tsx +5 -6
  293. package/src/widget-studio/create-widget-studio-workspace-editor.tsx +1 -2
  294. package/src/widget-studio/index.ts +4 -1
  295. package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +27 -10
  296. package/src/widget-tree/WidgetAssetPalette.tsx +35 -7
  297. package/src/widget-tree/WidgetInspectorPanel.tsx +53 -3
  298. package/src/widget-tree/WidgetSourceEditor.tsx +90 -3
  299. package/src/widget-tree/WidgetTreeCanvasPreview.tsx +875 -0
  300. package/src/widget-tree/WidgetTreeLab.tsx +411 -83
  301. package/src/widget-tree/WidgetTreeModeControls.tsx +30 -1
  302. package/src/widget-tree/WidgetTreeSidePanel.tsx +24 -34
  303. package/src/widget-tree/WidgetTreeView.tsx +711 -11
  304. package/src/widget-tree/WidgetTreeWorkbench.tsx +59 -15
  305. package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +26 -8
  306. package/src/widget-tree/index.ts +22 -4
  307. package/src/widget-tree/widget-placement-asset-dnd.ts +35 -0
  308. package/src/widget-tree/widget-tree-document.ts +3 -9
  309. package/src/widget-tree/widget-tree-editor-state.ts +40 -0
  310. package/src/widget-tree/widget-tree-layout.ts +48 -3
  311. package/src/widget-tree/widget-tree-play-helpers.ts +69 -58
  312. package/src/workbench/ActivityBar.tsx +128 -21
  313. package/src/workbench/ArtifactShell.tsx +8 -8
  314. package/src/workbench/CommandGroupShell.tsx +131 -0
  315. package/src/workbench/CommandList.tsx +167 -0
  316. package/src/workbench/CommandPalette.tsx +194 -596
  317. package/src/workbench/ConfirmationFlow.tsx +3 -5
  318. package/src/workbench/MarkdownPreview.tsx +8 -12
  319. package/src/workbench/ShortcutCommandBridge.tsx +1 -4
  320. package/src/workbench/SplitView.tsx +385 -36
  321. package/src/workbench/StatusBar.tsx +4 -2
  322. package/src/workbench/StructuredArtifactEditor.tsx +3 -3
  323. package/src/workbench/Timeline.tsx +2 -7
  324. package/src/workbench/WorkbenchCanvasShell.defaults.ts +106 -0
  325. package/src/workbench/WorkbenchCanvasShell.model.ts +46 -0
  326. package/src/workbench/WorkbenchCanvasShell.tsx +32 -146
  327. package/src/workbench/WorkbenchDesktopTitleBar.tsx +126 -0
  328. package/src/workbench/WorkbenchEditorTabs.tsx +52 -0
  329. package/src/workbench/WorkbenchModalPortal.tsx +52 -0
  330. package/src/workbench/WorkbenchPlatformContext.tsx +31 -0
  331. package/src/workbench/WorkbenchShell.tsx +144 -26
  332. package/src/workbench/WorkbenchShellTitleBarLayoutControls.tsx +80 -0
  333. package/src/workbench/WorkbenchStandaloneShell.tsx +327 -41
  334. package/src/workbench/WorkbenchThemeProvider.tsx +142 -0
  335. package/src/workbench/WorkbenchViewEditor.tsx +75 -0
  336. package/src/workbench/WorkbenchViewSidebar.tsx +85 -0
  337. package/src/workbench/WorkbenchWindowChromeControls.tsx +290 -0
  338. package/src/workbench/activityBarOrder.ts +98 -0
  339. package/src/workbench/appearanceLabels.ts +28 -0
  340. package/src/workbench/auth/WorkbenchLoginView.tsx +4 -6
  341. package/src/workbench/auth/auth-flows.css +440 -0
  342. package/src/workbench/auth/auth.css +3 -0
  343. package/src/workbench/auth/profile-modals.css +115 -0
  344. package/src/workbench/bootstrap/WorkbenchBootstrapGate.tsx +45 -0
  345. package/src/workbench/bootstrap/WorkbenchBootstrapView.tsx +100 -0
  346. package/src/workbench/bootstrap/index.ts +12 -0
  347. package/src/workbench/bootstrap/useWorkbenchBootstrap.ts +130 -0
  348. package/src/workbench/chat/ChatCommandProposalCard.tsx +115 -0
  349. package/src/workbench/chat/ChatComposer.tsx +32 -34
  350. package/src/workbench/chat/ChatConversationBar.tsx +134 -0
  351. package/src/workbench/chat/ChatHistoryMenu.tsx +171 -0
  352. package/src/workbench/chat/ChatHistoryMenuRow.tsx +74 -0
  353. package/src/workbench/chat/ChatMessageCollapsible.tsx +115 -0
  354. package/src/workbench/chat/ChatMessageItem.tsx +293 -19
  355. package/src/workbench/chat/ChatMessageList.tsx +109 -24
  356. package/src/workbench/chat/ChatPanel.tsx +132 -19
  357. package/src/workbench/chat/ChatPhasedRunProgress.tsx +202 -0
  358. package/src/workbench/chat/ChatRenameDialog.tsx +77 -0
  359. package/src/workbench/chat/chat-conversation.css +273 -0
  360. package/src/workbench/chat/chat-ui.css +1124 -0
  361. package/src/workbench/chat/chat.css +3 -0
  362. package/src/workbench/chat/chatConversation.ts +46 -0
  363. package/src/workbench/chat/chatHistoryRowMenuItems.ts +29 -0
  364. package/src/workbench/chat/chatMessageMeta.tsx +252 -0
  365. package/src/workbench/chat/chatScroll.ts +22 -0
  366. package/src/workbench/chat/index.ts +47 -1
  367. package/src/workbench/chat/slashCommand.ts +5 -7
  368. package/src/workbench/chat/types.ts +35 -0
  369. package/src/workbench/chat/useCancelRuntimeOnUnmount.ts +60 -0
  370. package/src/workbench/chat/useChatPrependPagination.ts +233 -0
  371. package/src/workbench/chat/useChatRuntimeState.ts +3 -15
  372. package/src/workbench/chat/useSlashCommandSuggest.ts +76 -23
  373. package/src/workbench/chrome/index.css +6 -0
  374. package/src/workbench/chrome/workbench-desktop-titlebar.css +60 -0
  375. package/src/workbench/chrome/workbench-host.css +85 -0
  376. package/src/workbench/chrome/workbench-layout-regions.css +42 -0
  377. package/src/workbench/chrome/workbench-platform-chrome.css +142 -0
  378. package/src/workbench/chrome/workbench-shell-titlebar.css +124 -0
  379. package/src/workbench/command-execution-policy.ts +61 -0
  380. package/src/workbench/command-model.ts +275 -0
  381. package/src/workbench/command-palette/command-palette.css +156 -0
  382. package/src/workbench/commands.ts +62 -6
  383. package/src/workbench/editor-tabs/index.ts +22 -0
  384. package/src/workbench/editor-tabs-dnd.ts +162 -0
  385. package/src/workbench/editorTabContextMenu.ts +111 -0
  386. package/src/workbench/hardReset.ts +64 -0
  387. package/src/workbench/index.ts +234 -2
  388. package/src/workbench/jdw/jdw-editors.css +4 -0
  389. package/src/workbench/jdw/jdw.css +2 -0
  390. package/src/workbench/management/AccountManagementPanel.tsx +82 -0
  391. package/src/workbench/management/CommandInspectorPanel.tsx +127 -0
  392. package/src/workbench/management/CommandManagementPanel.tsx +129 -0
  393. package/src/workbench/management/CommandManagementSidebar.tsx +318 -0
  394. package/src/workbench/management/ExtensionManagementPanel.tsx +498 -0
  395. package/src/workbench/management/ExtensionManagementSidebar.tsx +492 -0
  396. package/src/workbench/management/IntegrationCommandActions.tsx +78 -0
  397. package/src/workbench/management/IntegrationSettingsSurface.tsx +290 -0
  398. package/src/workbench/management/IntegrationsShell.tsx +53 -0
  399. package/src/workbench/management/KeybindingCaptureField.tsx +142 -0
  400. package/src/workbench/management/KeybindingManagementPanel.tsx +120 -0
  401. package/src/workbench/management/LibraryCatalogPickerDialog.tsx +208 -0
  402. package/src/workbench/management/LibraryFacetFilterDialog.tsx +62 -0
  403. package/src/workbench/management/ManagementCard.tsx +89 -0
  404. package/src/workbench/management/ManagementFilterChips.tsx +41 -0
  405. package/src/workbench/management/ManagementGroup.tsx +56 -0
  406. package/src/workbench/management/ManagementPanelControls.tsx +43 -0
  407. package/src/workbench/management/ManagementPanelFrame.tsx +109 -0
  408. package/src/workbench/management/WorkbenchDialogFrame.tsx +148 -0
  409. package/src/workbench/management/WorkbenchNotice.tsx +211 -0
  410. package/src/workbench/management/build-command-management-groups.ts +157 -0
  411. package/src/workbench/management/command-inspector-uri.ts +26 -0
  412. package/src/workbench/management/extension-category-display.ts +42 -0
  413. package/src/workbench/management/format-command-run-state.ts +19 -0
  414. package/src/workbench/management/index.ts +130 -0
  415. package/src/workbench/management/integration-command-action.ts +25 -0
  416. package/src/workbench/management/library-catalog-picker-dialog.css +56 -0
  417. package/src/workbench/management/library-facet-filter-dialog.css +8 -0
  418. package/src/workbench/management/management-panel.css +444 -0
  419. package/src/workbench/management/management.css +4 -0
  420. package/src/workbench/management/types.ts +126 -0
  421. package/src/workbench/markdownRemarkPlugins.ts +4 -0
  422. package/src/workbench/schema/index.ts +0 -1
  423. package/src/workbench/settings/NavigationPanel.tsx +41 -2
  424. package/src/workbench/settings/SchemaForm.tsx +20 -7
  425. package/src/workbench/settings/SectionTabPanel.tsx +172 -0
  426. package/src/workbench/settings/SectionedPanel.tsx +40 -286
  427. package/src/workbench/settings/StructuredDataForm.tsx +106 -26
  428. package/src/workbench/settings/StructuredDataSchemaPanel.tsx +345 -93
  429. package/src/workbench/settings/StructuredDataTableView.tsx +2 -2
  430. package/src/workbench/settings/WorkbenchPanelRegion.tsx +1 -1
  431. package/src/workbench/settings/WorkbenchSettingsModal.tsx +116 -62
  432. package/src/workbench/settings/WorkbenchSettingsNav.tsx +3 -3
  433. package/src/workbench/settings/extensionSettingsForm.ts +34 -0
  434. package/src/workbench/settings/index.ts +36 -1
  435. package/src/workbench/settings/navigation-panel.css +59 -0
  436. package/src/workbench/settings/panel-region.css +3 -2
  437. package/src/workbench/settings/schema-form.css +36 -0
  438. package/src/workbench/settings/schemaFormSettingSpec.ts +177 -0
  439. package/src/workbench/settings/schemaFormSettingsCategory.tsx +21 -0
  440. package/src/workbench/settings/section-tab-panel.css +157 -0
  441. package/src/workbench/settings/sectionScrollSpyDom.ts +139 -0
  442. package/src/workbench/settings/sectioned-panel.css +162 -0
  443. package/src/workbench/settings/sectionedPanelScrollSpy.ts +158 -28
  444. package/src/workbench/settings/settings-responsive.css +58 -0
  445. package/src/workbench/settings/settings.css +11 -0
  446. package/src/workbench/settings/settingsCommit.tsx +55 -0
  447. package/src/workbench/settings/structured-data-form.css +114 -0
  448. package/src/workbench/settings/structured-data-schema-panel.css +33 -19
  449. package/src/workbench/settings/structuredDataFormModel.ts +140 -0
  450. package/src/workbench/settings/structuredDataSchema.ts +111 -658
  451. package/src/workbench/settings/structuredDataSchemaDate.ts +197 -0
  452. package/src/workbench/settings/structuredDataSchemaField.ts +105 -0
  453. package/src/workbench/settings/structuredDataSchemaSection.ts +74 -0
  454. package/src/workbench/settings/structuredDataSchemaTable.ts +120 -0
  455. package/src/workbench/settings/structuredDataSchemaTypes.ts +308 -0
  456. package/src/workbench/settings/structuredDataSchemaValidation.ts +166 -0
  457. package/src/workbench/settings/useSectionScrollSpy.ts +420 -0
  458. package/src/workbench/settings/workbench-settings-modal.css +273 -0
  459. package/src/workbench/shell/activity-bar.css +245 -0
  460. package/src/workbench/shell/confirmation-flow.css +87 -0
  461. package/src/workbench/shell/index.css +5 -0
  462. package/src/workbench/shell/split-view.css +188 -0
  463. package/src/workbench/shell/status-bar.css +141 -0
  464. package/src/workbench/shell.ts +133 -2
  465. package/src/workbench/shellPresets.ts +36 -0
  466. package/src/workbench/shellState.ts +16 -23
  467. package/src/workbench/shellViewModel.ts +160 -0
  468. package/src/workbench/sidebarViewPlacementDnd.ts +61 -0
  469. package/src/workbench/standalone.ts +9 -9
  470. package/src/workbench/status.ts +10 -6
  471. package/src/workbench/theme.ts +8 -2
  472. package/src/workbench/themePresets.ts +191 -0
  473. package/src/workbench/useDeferredWorkbenchMount.ts +71 -0
  474. package/src/workbench/useEditorTabsStripDnd.ts +262 -0
  475. package/src/workbench/useWorkbenchAppearanceDocumentSync.tsx +17 -0
  476. package/src/workbench/useWorkbenchEditorTabContextMenu.tsx +66 -0
  477. package/src/workbench/useWorkbenchSidebarActionBarDnd.ts +227 -0
  478. package/src/workbench/useWorkbenchSidebarLayout.tsx +232 -0
  479. package/src/workbench/useWorkbenchSidebarViewPlacementDropZone.ts +194 -0
  480. package/src/workbench/useWorkbenchStandaloneShellStateSync.tsx +112 -0
  481. package/src/workbench/views/action-list.css +144 -0
  482. package/src/workbench/views/artifact-preview.css +184 -0
  483. package/src/workbench/views/command-inspector.css +98 -0
  484. package/src/workbench/views/command-list.css +356 -0
  485. package/src/workbench/views/commands-sidebar.css +51 -0
  486. package/src/workbench/views/extensions-sidebar.css +175 -0
  487. package/src/workbench/views/multi-provider-explorer.css +182 -0
  488. package/src/workbench/views/search.css +10 -0
  489. package/src/workbench/views/timeline.css +239 -0
  490. package/src/workbench/views/view-hosts.css +37 -0
  491. package/src/workbench/views/view-sidebar.css +21 -0
  492. package/src/workbench/views/views.css +12 -0
  493. package/src/workbench/widgets/widget-tree.css +598 -0
  494. package/src/workbench/widgets/widgets.css +2 -0
  495. package/src/workbench/workbench-chrome.css +4 -0
  496. package/src/workbench/workbenchContextMenu.ts +18 -0
  497. package/src/workbench/workbenchModalViewState.ts +52 -0
  498. package/src/workbench/workbenchOverlaysContext.tsx +21 -0
  499. package/src/workbench/workbenchPlatformChrome.ts +40 -0
  500. package/src/workbench/workbenchSidebarLayoutContext.ts +46 -0
  501. package/src/workbench/workbenchStandaloneShellReactContext.tsx +80 -0
  502. package/src/workbench/workbenchViewRouteState.ts +151 -0
  503. package/src/workbench/workspace/WorkspaceDraftsContext.tsx +59 -71
  504. package/src/workbench/workspace/WorkspaceEditor.tsx +27 -123
  505. package/src/workbench/workspace/WorkspaceEditorPanel.tsx +67 -8
  506. package/src/workbench/workspace/WorkspaceExplorer.tsx +149 -51
  507. package/src/workbench/workspace/WorkspaceExplorerPanel.tsx +73 -0
  508. package/src/workbench/workspace/WorkspaceFileIcon.tsx +4 -160
  509. package/src/workbench/workspace/WorkspacePathLabel.tsx +42 -0
  510. package/src/workbench/workspace/WorkspaceSearchPanel.tsx +18 -15
  511. package/src/workbench/workspace/WorkspaceSearchResults.tsx +6 -2
  512. package/src/workbench/workspace/build-workspace-explorer-nodes.ts +44 -0
  513. package/src/workbench/workspace/createVirtualWorkspaceExplorerPort.ts +141 -0
  514. package/src/workbench/workspace/explorer-tree-style.ts +18 -0
  515. package/src/workbench/workspace/index.ts +45 -32
  516. package/src/workbench/workspace/json-config-workbench.css +57 -0
  517. package/src/workbench/workspace/monaco-panel.css +71 -0
  518. package/src/workbench/workspace/path.ts +2 -0
  519. package/src/workbench/workspace/useWorkspaceExplorerController.ts +490 -0
  520. package/src/workbench/workspace/workspace-editor.css +235 -0
  521. package/src/workbench/workspace/workspace-explorer-panel.css +33 -0
  522. package/src/workbench/workspace/workspace.css +5 -0
  523. package/src/workbench/workspace/workspaceExplorerController.ts +193 -0
  524. package/src/workbench/workspace/workspaceJsonDiagnostics.ts +2 -2
  525. package/src/workbench-menu-surfaces.css +57 -0
  526. package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +0 -126
  527. package/src/layout/SideBarViewFrame.tsx +0 -367
  528. package/src/primitives/Checkbox.tsx +0 -21
  529. package/src/primitives/NumberInput.tsx +0 -38
  530. package/src/primitives/ScrollArea.tsx +0 -42
  531. package/src/primitives/Select.tsx +0 -1
  532. package/src/primitives/StatusBar.tsx +0 -46
  533. package/src/primitives/WorkbenchChrome.tsx +0 -424
  534. package/src/workbench/workspace/MultiProviderExplorer.tsx +0 -625
@@ -0,0 +1,37 @@
1
+ import type { ReactNode } from 'react';
2
+ import { createElement } from 'react';
3
+
4
+ export interface MockWorkbenchMonacoEditorProps {
5
+ language?: string;
6
+ onChange?: (value?: string) => void;
7
+ path?: string;
8
+ theme?: string;
9
+ value?: string;
10
+ }
11
+
12
+ export function createWorkbenchMonacoMockModule(
13
+ renderEditor?: (props: MockWorkbenchMonacoEditorProps) => ReactNode,
14
+ ) {
15
+ const defaultRender = ({ value }: MockWorkbenchMonacoEditorProps) =>
16
+ createElement('div', { 'data-testid': 'monaco-editor' }, value ?? 'Mocked Monaco Editor');
17
+
18
+ return {
19
+ WorkbenchMonacoEditor: renderEditor ?? defaultRender,
20
+ useMonacoWorkbenchThemeSync: () => undefined,
21
+ prepareMonacoWorkbenchEditor: () => undefined,
22
+ monacoThemeForWorkspaceTheme: (theme: string) =>
23
+ theme === 'light' ? 'workbench-kit-light' : 'workbench-kit-dark',
24
+ MONACO_DARK_THEME_ID: 'workbench-kit-dark',
25
+ MONACO_LIGHT_THEME_ID: 'workbench-kit-light',
26
+ monaco: {
27
+ KeyMod: { CtrlCmd: 1 },
28
+ KeyCode: { KeyS: 1 },
29
+ editor: {
30
+ defineTheme: () => undefined,
31
+ setTheme: () => undefined,
32
+ onDidChangeMarkers: () => ({ dispose: () => undefined }),
33
+ getModelMarkers: () => [],
34
+ },
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,89 @@
1
+ export interface TypedDragMimeOptions<T> {
2
+ readonly mimeType: string;
3
+ readonly serialize: (value: T) => string;
4
+ readonly deserialize: (raw: string) => T | null;
5
+ /** When true, also write/read `text/plain`. Default: false. */
6
+ readonly textPlainFallback?: boolean;
7
+ /** Default: `'copyMove'`. */
8
+ readonly effectAllowed?: DataTransfer['effectAllowed'];
9
+ }
10
+
11
+ export interface TypedDragMime<T> {
12
+ write(dataTransfer: DataTransfer, value: T): void;
13
+ read(dataTransfer: DataTransfer | null): T | null;
14
+ has(dataTransfer: DataTransfer | null): boolean;
15
+ }
16
+
17
+ /**
18
+ * Host-supplied MIME + codecs for `DataTransfer` write/read/has.
19
+ *
20
+ * Prefer the custom MIME for privileged drop decisions; treat `text/plain`
21
+ * fallback as interoperability only (some environments strip custom types).
22
+ * Plaintext alone never satisfies `has()`.
23
+ */
24
+ export function createTypedDragMime<T>(options: TypedDragMimeOptions<T>): TypedDragMime<T> {
25
+ const {
26
+ mimeType,
27
+ serialize,
28
+ deserialize,
29
+ textPlainFallback = false,
30
+ effectAllowed = 'copyMove',
31
+ } = options;
32
+
33
+ return {
34
+ write(dataTransfer, value) {
35
+ const payload = serialize(value);
36
+ dataTransfer.setData(mimeType, payload);
37
+ if (textPlainFallback) {
38
+ dataTransfer.setData('text/plain', payload);
39
+ }
40
+ dataTransfer.effectAllowed = effectAllowed;
41
+ },
42
+ read(dataTransfer) {
43
+ if (dataTransfer == null) {
44
+ return null;
45
+ }
46
+
47
+ const custom = dataTransfer.getData(mimeType).trim();
48
+ if (custom.length > 0) {
49
+ return deserialize(custom);
50
+ }
51
+
52
+ if (textPlainFallback) {
53
+ const plain = dataTransfer.getData('text/plain').trim();
54
+ if (plain.length > 0) {
55
+ return deserialize(plain);
56
+ }
57
+ }
58
+
59
+ return null;
60
+ },
61
+ has(dataTransfer) {
62
+ if (dataTransfer == null) {
63
+ return false;
64
+ }
65
+
66
+ return Array.from(dataTransfer.types).includes(mimeType);
67
+ },
68
+ };
69
+ }
70
+
71
+ /** Convenience factory for string id / label payloads. */
72
+ export function createStringDragMime(options: {
73
+ mimeType: string;
74
+ textPlainFallback?: boolean;
75
+ effectAllowed?: DataTransfer['effectAllowed'];
76
+ }): TypedDragMime<string> {
77
+ return createTypedDragMime({
78
+ mimeType: options.mimeType,
79
+ // Pass concrete defaults so linked consumers with
80
+ // `exactOptionalPropertyTypes` can typecheck the source file.
81
+ textPlainFallback: options.textPlainFallback ?? false,
82
+ effectAllowed: options.effectAllowed ?? 'copyMove',
83
+ serialize: (value) => value,
84
+ deserialize: (raw) => {
85
+ const trimmed = raw.trim();
86
+ return trimmed.length === 0 ? null : trimmed;
87
+ },
88
+ });
89
+ }
@@ -0,0 +1,37 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+
3
+ export function hasWorkbenchMediaImageSource(
4
+ imageUrl: string | null | undefined,
5
+ ): imageUrl is string {
6
+ return imageUrl !== null && imageUrl !== undefined && imageUrl.trim() !== '';
7
+ }
8
+
9
+ export interface UseWorkbenchMediaImageResult {
10
+ readonly hasSource: boolean;
11
+ readonly imageSrc: string | undefined;
12
+ readonly onImageError: () => void;
13
+ readonly shouldShowImage: boolean;
14
+ }
15
+
16
+ export function useWorkbenchMediaImage(
17
+ imageUrl: string | null | undefined,
18
+ ): UseWorkbenchMediaImageResult {
19
+ const [failed, setFailed] = useState(false);
20
+
21
+ useEffect(() => {
22
+ setFailed(false);
23
+ }, [imageUrl]);
24
+
25
+ const onImageError = useCallback(() => {
26
+ setFailed(true);
27
+ }, []);
28
+
29
+ const hasSource = hasWorkbenchMediaImageSource(imageUrl);
30
+
31
+ return {
32
+ hasSource,
33
+ imageSrc: hasSource ? imageUrl : undefined,
34
+ onImageError,
35
+ shouldShowImage: hasSource && !failed,
36
+ };
37
+ }
@@ -11,7 +11,8 @@ import {
11
11
  type WorkspaceAssetFileRef,
12
12
  } from '@workbench-kit/jdw';
13
13
 
14
- import { JdwPreview } from '../jdw/JdwPreview.js';
14
+ import { JdwPreviewViewport } from '../jdw/JdwPreviewViewport.js';
15
+ import { WorkbenchLabeledPane } from '../layout/panel';
15
16
  import { WidgetAssetSourceEditor } from './WidgetAssetSourceEditor.js';
16
17
  import type { WorkspaceEditorTheme } from '../workbench/workspace/WorkspaceEditor.js';
17
18
  import { WorkbenchPropertyHint, WorkbenchPropertyPanel } from '../layout/WorkbenchPropertyPanel';
@@ -128,12 +129,13 @@ export function WidgetAssetEditor({
128
129
  />
129
130
  </section>
130
131
  ) : null}
131
- <section aria-label="Asset preview" className="widget-asset-editor__preview">
132
- <header className="widget-asset-editor__preview-header">Placement preview</header>
133
- <div className="widget-asset-editor__preview-body">
134
- <JdwPreview json={previewJson} registry={registry} />
135
- </div>
136
- </section>
132
+ <WorkbenchLabeledPane
133
+ aria-label="Asset preview"
134
+ className="widget-asset-editor__preview"
135
+ title="Placement preview"
136
+ >
137
+ <JdwPreviewViewport json={previewJson} registry={registry} />
138
+ </WorkbenchLabeledPane>
137
139
  </div>
138
140
  </div>
139
141
  );
@@ -1,4 +1,4 @@
1
- import { IconButton } from '../primitives/IconButton';
1
+ import { IconButton } from '../primitives/icon-button';
2
2
  import { cx } from '../utils/cx';
3
3
  import type { WidgetAssetViewMode } from './widget-asset-mode.js';
4
4
 
@@ -1,11 +1,12 @@
1
1
  import { useState, type ReactNode } from 'react';
2
2
  import type { WidgetRegistryContract } from '@workbench-kit/contracts';
3
3
 
4
- import { Panel, PanelBody, PanelHeader } from '../layout/Panel';
5
- import { Button } from '../primitives/Button';
6
- import { Toolbar } from '../primitives/Toolbar';
4
+ import { Panel, PanelBody, PanelHeader } from '../layout/panel';
5
+ import { Button } from '../primitives/button';
6
+ import { Toolbar } from '../primitives/toolbar';
7
7
  import type { WorkspaceEditorTheme } from '../workbench/workspace/WorkspaceEditor.js';
8
8
  import { fileNameOfPath } from '../workbench/workspace/path';
9
+ import { WorkspacePathLabel } from '../workbench/workspace/WorkspacePathLabel';
9
10
  import type { WorkspaceFile } from '../workbench/workspace/types.js';
10
11
  import { WidgetAssetEditor } from './WidgetAssetEditor.js';
11
12
  import { WidgetAssetModeControls } from './WidgetAssetModeControls.js';
@@ -83,9 +84,7 @@ export function WidgetAssetWorkbench({
83
84
  <span className="widget-asset-workbench__title">
84
85
  {resolvedTitle}
85
86
  {path ? (
86
- <span className="widget-asset-workbench__path" title={path}>
87
- {path}
88
- </span>
87
+ <WorkspacePathLabel className="widget-asset-workbench__path" path={path} />
89
88
  ) : null}
90
89
  {dirty ? (
91
90
  <span className="widget-asset-workbench__dirty-indicator" title="Unsaved changes">
@@ -16,8 +16,7 @@ export interface WidgetStudioRenderContext extends WorkspaceEditorPanelRenderEdi
16
16
  export interface CreateWidgetStudioWorkspaceEditorOptions {
17
17
  readonly registry?: WidgetRegistryContract<unknown> | undefined;
18
18
  readonly resolveAssetCatalog?:
19
- | ((files: readonly WorkspaceFile[]) => WidgetAssetCatalogContract)
20
- | undefined;
19
+ ((files: readonly WorkspaceFile[]) => WidgetAssetCatalogContract) | undefined;
21
20
  }
22
21
 
23
22
  export function createWidgetStudioWorkspaceEditorRenderer(
@@ -4,4 +4,7 @@ export type {
4
4
  WidgetStudioRenderContext,
5
5
  } from './create-widget-studio-workspace-editor.js';
6
6
  export { createBuiltinWidgetAssetCatalog } from './builtin-widget-asset-catalog.js';
7
- export { resolveWidgetStudioAssetCatalog } from './resolve-widget-studio-asset-catalog.js';
7
+ export {
8
+ resolveWidgetStudioAssetCatalog,
9
+ type ResolveWidgetStudioAssetCatalogOptions,
10
+ } from './resolve-widget-studio-asset-catalog.js';
@@ -1,5 +1,6 @@
1
1
  import type { WidgetAssetCatalogContract } from '@workbench-kit/contracts';
2
2
  import {
3
+ createWidgetAssetCatalogFromJdwDocuments,
3
4
  createWidgetAssetCatalogFromWorkspaceFiles,
4
5
  mergeWidgetAssetCatalogs,
5
6
  } from '@workbench-kit/jdw';
@@ -7,20 +8,36 @@ import {
7
8
  import type { WorkspaceFile } from '../workbench/workspace/types.js';
8
9
  import { createBuiltinWidgetAssetCatalog } from './builtin-widget-asset-catalog.js';
9
10
 
11
+ export interface ResolveWidgetStudioAssetCatalogOptions {
12
+ /** Paths to omit from the JDW-document catalog (usually the active editor file). */
13
+ readonly excludeDocumentPaths?: readonly string[] | undefined;
14
+ }
15
+
10
16
  /**
11
- * Resolves the widget studio palette from built-in assets plus workspace asset packages
12
- * (`<slug>/manifest.json` + `content.json`). Workspace assets override built-ins when they
13
- * share the same `name`.
17
+ * Resolves the widget studio / Form palette from:
18
+ * 1. built-in assets
19
+ * 2. workspace asset packages (`manifest.json` + `content.json`)
20
+ * 3. workspace `*.jdw.json` documents (for example `jdw/parts/*`)
21
+ *
22
+ * Later catalogs override earlier entries when they share the same `id`.
14
23
  */
15
24
  export function resolveWidgetStudioAssetCatalog(
16
25
  files: readonly WorkspaceFile[],
26
+ options: ResolveWidgetStudioAssetCatalogOptions = {},
17
27
  ): WidgetAssetCatalogContract {
18
- const workspaceCatalog = createWidgetAssetCatalogFromWorkspaceFiles(
19
- files.map((file) => ({
20
- path: file.path,
21
- content: file.content,
22
- })),
23
- );
28
+ const workspaceFiles = files.map((file) => ({
29
+ path: file.path,
30
+ content: file.content,
31
+ }));
24
32
 
25
- return mergeWidgetAssetCatalogs(createBuiltinWidgetAssetCatalog(), workspaceCatalog);
33
+ const packageCatalog = createWidgetAssetCatalogFromWorkspaceFiles(workspaceFiles);
34
+ const documentCatalog = createWidgetAssetCatalogFromJdwDocuments(workspaceFiles, {
35
+ excludePaths: options.excludeDocumentPaths,
36
+ });
37
+
38
+ return mergeWidgetAssetCatalogs(
39
+ createBuiltinWidgetAssetCatalog(),
40
+ packageCatalog,
41
+ documentCatalog,
42
+ );
26
43
  }
@@ -1,15 +1,20 @@
1
+ import type { DragEvent } from 'react';
1
2
  import type { WidgetPlacementAsset } from '@workbench-kit/contracts';
2
3
  import type { GenericWidget } from '@workbench-kit/jdw';
3
4
 
4
5
  import { WorkbenchPropertyHint } from '../layout/WorkbenchPropertyPanel';
5
6
  import { cxCodicon } from '../utils/codicon';
6
7
  import { cx } from '../utils/cx';
8
+ import { writeWidgetPlacementAssetDragData } from './widget-placement-asset-dnd.js';
7
9
  import { canAddChildren } from './widget-tree-layout.js';
8
10
 
9
11
  const CATEGORY_LABELS: Record<string, string> = {
10
12
  content: 'Content',
11
13
  layout: 'Layout',
12
14
  template: 'Templates',
15
+ parts: 'Parts',
16
+ composed: 'Composed',
17
+ documents: 'Documents',
13
18
  };
14
19
 
15
20
  export interface WidgetAssetPaletteProps {
@@ -25,18 +30,36 @@ export function WidgetAssetPalette({
25
30
  readOnly = false,
26
31
  selectedContainer,
27
32
  }: WidgetAssetPaletteProps) {
28
- const canPlace = canAddChildren(selectedContainer) && !readOnly;
33
+ const canClickPlace = canAddChildren(selectedContainer) && !readOnly;
34
+ const canDrag = !readOnly;
29
35
  const categories = Object.keys(assetsByCategory);
30
36
 
37
+ const handleAssetClick = (asset: WidgetPlacementAsset): void => {
38
+ if (!canClickPlace) return;
39
+ onPlaceAsset(asset);
40
+ };
41
+
42
+ const handleAssetDragStart = (
43
+ event: DragEvent<HTMLButtonElement>,
44
+ asset: WidgetPlacementAsset,
45
+ ): void => {
46
+ if (!canDrag) return;
47
+ writeWidgetPlacementAssetDragData(event.dataTransfer, asset);
48
+ };
49
+
31
50
  return (
32
51
  <div className="widget-tree-asset-palette" data-testid="widget-tree-asset-palette">
33
- {!canPlace ? (
52
+ {readOnly ? (
53
+ <WorkbenchPropertyHint>Widget assets are read-only in this editor.</WorkbenchPropertyHint>
54
+ ) : !canClickPlace ? (
34
55
  <WorkbenchPropertyHint>
35
- Select a container node in Outline to place an asset.
56
+ Select a container node in Outline to click-add, or drag an asset onto the outline or
57
+ preview.
36
58
  </WorkbenchPropertyHint>
37
59
  ) : (
38
60
  <WorkbenchPropertyHint>
39
- Click an asset to add it to <strong>{selectedContainer?.type ?? 'container'}</strong>.
61
+ Click an asset to add it to <strong>{selectedContainer?.type ?? 'container'}</strong>, or
62
+ drag it onto the outline or preview.
40
63
  </WorkbenchPropertyHint>
41
64
  )}
42
65
 
@@ -49,15 +72,20 @@ export function WidgetAssetPalette({
49
72
  {assetsByCategory[category]?.map((asset) => (
50
73
  <button
51
74
  key={asset.id}
75
+ aria-disabled={!canClickPlace}
52
76
  className={cx(
53
77
  'widget-tree-asset-palette__card',
54
- !canPlace && 'widget-tree-asset-palette__card--disabled',
78
+ canDrag && 'widget-tree-asset-palette__card--draggable',
79
+ !canClickPlace && !readOnly && 'widget-tree-asset-palette__card--drop-only',
80
+ readOnly && 'widget-tree-asset-palette__card--disabled',
55
81
  )}
56
82
  data-testid={`widget-asset-${asset.id}`}
57
- disabled={!canPlace}
83
+ disabled={readOnly}
84
+ draggable={canDrag}
58
85
  title={asset.description ?? asset.label}
59
86
  type="button"
60
- onClick={() => onPlaceAsset(asset)}
87
+ onClick={() => handleAssetClick(asset)}
88
+ onDragStart={(event) => handleAssetDragStart(event, asset)}
61
89
  >
62
90
  {asset.icon ? (
63
91
  <i aria-hidden className={cxCodicon(asset.icon)} />
@@ -1,3 +1,4 @@
1
+ import type { Ref } from 'react';
1
2
  import type {
2
3
  WidgetInspectorField,
3
4
  WidgetInspectorSection,
@@ -5,8 +6,8 @@ import type {
5
6
  } from '@workbench-kit/contracts';
6
7
  import type { GenericWidget, WidgetPath } from '@workbench-kit/jdw';
7
8
 
8
- import { Badge } from '../primitives/Badge';
9
- import { Button } from '../primitives/Button';
9
+ import { Badge } from '../primitives/badge';
10
+ import { Button } from '../primitives/button';
10
11
  import {
11
12
  WorkbenchPropertyCheckboxRow,
12
13
  WorkbenchPropertyColorRow,
@@ -24,6 +25,7 @@ export interface WidgetInspectorPanelProps {
24
25
  readonly path: WidgetPath | null;
25
26
  readonly parentWidget?: GenericWidget | null | undefined;
26
27
  readonly widgetRegistry?: WidgetRegistryContract<unknown> | undefined;
28
+ readonly panelRef?: Ref<HTMLDivElement> | undefined;
27
29
  readonly readOnly?: boolean | undefined;
28
30
  readonly onPatch?: ((next: GenericWidget) => void) | undefined;
29
31
  readonly onRemove?: (() => void) | undefined;
@@ -33,6 +35,7 @@ export function WidgetInspectorPanel({
33
35
  widget,
34
36
  path,
35
37
  parentWidget = null,
38
+ panelRef,
36
39
  widgetRegistry,
37
40
  readOnly = false,
38
41
  onPatch,
@@ -43,7 +46,10 @@ export function WidgetInspectorPanel({
43
46
  const showPlacement =
44
47
  widget &&
45
48
  parentType &&
46
- (parentType === 'grid' || parentType === 'row' || parentType === 'column');
49
+ (parentType === 'grid' ||
50
+ parentType === 'row' ||
51
+ parentType === 'column' ||
52
+ parentType === 'stack');
47
53
 
48
54
  const updateProp = (prop: string, value: unknown) => {
49
55
  if (!widget || !path || !onPatch || readOnly) return;
@@ -54,6 +60,8 @@ export function WidgetInspectorPanel({
54
60
  <WorkbenchPropertyPanel
55
61
  className="widget-tree-inspector"
56
62
  data-testid="widget-tree-inspector-panel"
63
+ ref={panelRef}
64
+ tabIndex={-1}
57
65
  >
58
66
  {!widget ? (
59
67
  <WorkbenchPropertyHint>Select a node in the outline.</WorkbenchPropertyHint>
@@ -150,6 +158,37 @@ function PlacementSection({
150
158
  );
151
159
  }
152
160
 
161
+ if (parentType === 'stack') {
162
+ return (
163
+ <WorkbenchPropertySection title="Stack placement">
164
+ <WorkbenchPropertyNumberRow
165
+ label="Left"
166
+ disabled={readOnly}
167
+ value={typeof values.left === 'number' ? values.left : undefined}
168
+ onValueChange={(next) => onValueChange('left', next)}
169
+ />
170
+ <WorkbenchPropertyNumberRow
171
+ label="Top"
172
+ disabled={readOnly}
173
+ value={typeof values.top === 'number' ? values.top : undefined}
174
+ onValueChange={(next) => onValueChange('top', next)}
175
+ />
176
+ <WorkbenchPropertyNumberRow
177
+ label="Right"
178
+ disabled={readOnly}
179
+ value={typeof values.right === 'number' ? values.right : undefined}
180
+ onValueChange={(next) => onValueChange('right', next)}
181
+ />
182
+ <WorkbenchPropertyNumberRow
183
+ label="Bottom"
184
+ disabled={readOnly}
185
+ value={typeof values.bottom === 'number' ? values.bottom : undefined}
186
+ onValueChange={(next) => onValueChange('bottom', next)}
187
+ />
188
+ </WorkbenchPropertySection>
189
+ );
190
+ }
191
+
153
192
  return (
154
193
  <WorkbenchPropertySection title="Flex placement">
155
194
  <WorkbenchPropertyNumberRow
@@ -160,6 +199,17 @@ function PlacementSection({
160
199
  value={typeof values.flex === 'number' ? values.flex : undefined}
161
200
  onValueChange={(next) => onValueChange('flex', next)}
162
201
  />
202
+ <WorkbenchPropertySelectRow
203
+ label="Fit"
204
+ disabled={readOnly}
205
+ options={[
206
+ { label: 'Auto', value: '' },
207
+ { label: 'Tight', value: 'tight' },
208
+ { label: 'Loose', value: 'loose' },
209
+ ]}
210
+ value={typeof values.flexFit === 'string' ? values.flexFit : ''}
211
+ onValueChange={(next) => onValueChange('flexFit', next.length > 0 ? next : undefined)}
212
+ />
163
213
  <WorkbenchPropertySelectRow
164
214
  label="Align"
165
215
  disabled={readOnly}
@@ -1,10 +1,22 @@
1
1
  import { useMemo } from 'react';
2
2
  import type { WidgetJsonSchema } from '@workbench-kit/contracts';
3
+ import {
4
+ findPathForLineAndColumn,
5
+ findSourceRangeForPath,
6
+ getWidgetAtPath,
7
+ type GenericWidget,
8
+ type WidgetPath,
9
+ } from '@workbench-kit/jdw';
3
10
 
4
- import { JsonCodeEditorPane } from '../jdw/JsonCodeEditorPane.js';
11
+ import {
12
+ JsonCodeEditorPane,
13
+ type JsonEditorRange,
14
+ type JsonEditorPosition,
15
+ type JsonEditorProblem,
16
+ } from '../jdw/JsonCodeEditorPane.js';
17
+ import { JDW_WIDGET_DOCUMENT_MIME } from '../jdw/document.js';
5
18
  import type { WorkspaceEditorTheme } from '../workbench/workspace/WorkspaceEditor.js';
6
19
  import type { WorkspaceFile } from '../workbench/workspace/types.js';
7
- import { WIDGET_TREE_DOCUMENT_MIME } from './widget-tree-document.js';
8
20
 
9
21
  export interface WidgetSourceEditorProps {
10
22
  readonly path?: string | undefined;
@@ -12,10 +24,49 @@ export interface WidgetSourceEditorProps {
12
24
  readonly onChange: (value: string) => void;
13
25
  readonly onSave?: (() => void) | undefined;
14
26
  readonly parseError?: string | null | undefined;
27
+ readonly problems?: readonly JsonEditorProblem[] | undefined;
15
28
  readonly jsonSchema?: WidgetJsonSchema | null | undefined;
16
29
  readonly readOnly?: boolean | undefined;
30
+ readonly root?: GenericWidget | null | undefined;
31
+ readonly selectedPath?: WidgetPath | null | undefined;
17
32
  readonly showProblemsPanel?: boolean | undefined;
18
33
  readonly theme?: WorkspaceEditorTheme | undefined;
34
+ readonly onSelectPath?: ((path: WidgetPath) => void) | undefined;
35
+ }
36
+
37
+ export function resolveWidgetSourceRevealPosition(
38
+ source: string,
39
+ path: WidgetPath | null | undefined,
40
+ ): JsonEditorPosition | null {
41
+ const position = resolveWidgetSourceActiveRange(source, path);
42
+ if (!position) return null;
43
+
44
+ return {
45
+ column: position.startColumn,
46
+ lineNumber: position.startLineNumber,
47
+ };
48
+ }
49
+
50
+ export function resolveWidgetSourceActiveRange(
51
+ source: string,
52
+ path: WidgetPath | null | undefined,
53
+ ): JsonEditorRange | null {
54
+ if (!path) return null;
55
+ return findSourceRangeForPath(source, path);
56
+ }
57
+
58
+ export function resolveWidgetPathForEditorPosition(
59
+ source: string,
60
+ root: GenericWidget | null | undefined,
61
+ lineNumber: number,
62
+ column: number,
63
+ ): WidgetPath | null {
64
+ if (!root) return null;
65
+
66
+ const pathAtCursor = findPathForLineAndColumn(source, lineNumber, column);
67
+ if (!pathAtCursor || !getWidgetAtPath(root, pathAtCursor)) return null;
68
+
69
+ return pathAtCursor;
19
70
  }
20
71
 
21
72
  export function WidgetSourceEditor({
@@ -24,31 +75,67 @@ export function WidgetSourceEditor({
24
75
  onChange,
25
76
  onSave,
26
77
  parseError = null,
78
+ problems = [],
27
79
  jsonSchema = null,
28
80
  readOnly = false,
81
+ selectedPath = null,
29
82
  showProblemsPanel = false,
30
83
  theme = 'dark',
84
+ root = null,
85
+ onSelectPath,
31
86
  }: WidgetSourceEditorProps) {
32
87
  const file = useMemo<WorkspaceFile>(
33
88
  () => ({
34
89
  content: value,
35
- mimeType: WIDGET_TREE_DOCUMENT_MIME,
90
+ mimeType: JDW_WIDGET_DOCUMENT_MIME,
36
91
  path,
37
92
  }),
38
93
  [path, value],
39
94
  );
95
+ const activeSourceRange = useMemo(
96
+ () => resolveWidgetSourceActiveRange(value, selectedPath),
97
+ [selectedPath, value],
98
+ );
99
+ const revealPosition = useMemo(
100
+ () =>
101
+ activeSourceRange
102
+ ? {
103
+ column: activeSourceRange.startColumn,
104
+ lineNumber: activeSourceRange.startLineNumber,
105
+ }
106
+ : null,
107
+ [activeSourceRange?.startColumn, activeSourceRange?.startLineNumber],
108
+ );
109
+
110
+ const handleCursorPositionChange = ({
111
+ lineNumber,
112
+ column,
113
+ }: {
114
+ lineNumber: number;
115
+ column: number;
116
+ }) => {
117
+ if (!onSelectPath) return;
118
+
119
+ const pathAtCursor = resolveWidgetPathForEditorPosition(value, root, lineNumber, column);
120
+ if (!pathAtCursor) return;
121
+ onSelectPath(pathAtCursor);
122
+ };
40
123
 
41
124
  return (
42
125
  <div className="widget-tree-source" data-testid="widget-tree-source">
43
126
  <JsonCodeEditorPane
127
+ activeSourceRange={activeSourceRange}
44
128
  documentParseError={parseError}
45
129
  file={file}
46
130
  jsonSchema={jsonSchema}
131
+ problems={problems}
47
132
  readOnly={readOnly}
133
+ revealPosition={revealPosition}
48
134
  showProblemsPanel={showProblemsPanel}
49
135
  theme={theme}
50
136
  value={value}
51
137
  onChange={onChange}
138
+ onCursorPositionChange={handleCursorPositionChange}
52
139
  onSave={onSave}
53
140
  />
54
141
  </div>