@dxos/plugin-kanban 0.8.4-main.fd6878d → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/LICENSE +102 -5
  2. package/PLUGIN.mdl +398 -0
  3. package/README.md +1 -1
  4. package/dist/lib/neutral/KanbanArticle-T4CPKAZH.mjs +132 -0
  5. package/dist/lib/neutral/KanbanArticle-T4CPKAZH.mjs.map +7 -0
  6. package/dist/lib/neutral/KanbanPlugin.mjs +44 -0
  7. package/dist/lib/neutral/KanbanPlugin.mjs.map +7 -0
  8. package/dist/lib/neutral/KanbanPlugin.node.mjs +27 -0
  9. package/dist/lib/neutral/KanbanPlugin.node.mjs.map +7 -0
  10. package/dist/lib/neutral/KanbanPlugin.workerd.mjs +21 -0
  11. package/dist/lib/neutral/KanbanPlugin.workerd.mjs.map +7 -0
  12. package/dist/lib/neutral/KanbanSettings-5WOS4CUE.mjs +83 -0
  13. package/dist/lib/neutral/KanbanSettings-5WOS4CUE.mjs.map +7 -0
  14. package/dist/lib/neutral/blueprint-definition-6DV3Q5MC.mjs +15 -0
  15. package/dist/lib/neutral/blueprint-definition-6DV3Q5MC.mjs.map +7 -0
  16. package/dist/lib/neutral/blueprints/index.mjs +8 -0
  17. package/dist/lib/neutral/capabilities/index.mjs +17 -0
  18. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  19. package/dist/lib/neutral/chunk-6ZHHQWO5.mjs +39 -0
  20. package/dist/lib/neutral/chunk-6ZHHQWO5.mjs.map +7 -0
  21. package/dist/lib/neutral/chunk-DAKIZO46.mjs +246 -0
  22. package/dist/lib/neutral/chunk-DAKIZO46.mjs.map +7 -0
  23. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  24. package/dist/lib/neutral/chunk-M5ISZWZU.mjs +8 -0
  25. package/dist/lib/neutral/chunk-M5ISZWZU.mjs.map +7 -0
  26. package/dist/lib/neutral/chunk-ZTQW5KQS.mjs +26 -0
  27. package/dist/lib/neutral/chunk-ZTQW5KQS.mjs.map +7 -0
  28. package/dist/lib/neutral/components/index.mjs +243 -0
  29. package/dist/lib/neutral/components/index.mjs.map +7 -0
  30. package/dist/lib/neutral/containers/index.mjs +11 -0
  31. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  32. package/dist/lib/neutral/create-object-DKBSI46K.mjs +40 -0
  33. package/dist/lib/neutral/create-object-DKBSI46K.mjs.map +7 -0
  34. package/dist/lib/neutral/delete-card-VNAV3CZV.mjs +24 -0
  35. package/dist/lib/neutral/delete-card-VNAV3CZV.mjs.map +7 -0
  36. package/dist/lib/neutral/delete-card-field-XHOLGS6L.mjs +39 -0
  37. package/dist/lib/neutral/delete-card-field-XHOLGS6L.mjs.map +7 -0
  38. package/dist/lib/neutral/hooks/index.mjs +431 -0
  39. package/dist/lib/neutral/hooks/index.mjs.map +7 -0
  40. package/dist/lib/neutral/index.mjs +34 -0
  41. package/dist/lib/neutral/index.mjs.map +7 -0
  42. package/dist/lib/neutral/meta.json +1 -0
  43. package/dist/lib/neutral/meta.mjs +8 -0
  44. package/dist/lib/neutral/meta.mjs.map +7 -0
  45. package/dist/lib/neutral/operation-handler-B7IW6MXU.mjs +13 -0
  46. package/dist/lib/neutral/operation-handler-B7IW6MXU.mjs.map +7 -0
  47. package/dist/lib/neutral/operations/index.mjs +8 -0
  48. package/dist/lib/neutral/operations/index.mjs.map +7 -0
  49. package/dist/lib/neutral/plugin.mjs +16 -0
  50. package/dist/lib/neutral/plugin.mjs.map +7 -0
  51. package/dist/lib/neutral/react-surface-VZEVEJL5.mjs +91 -0
  52. package/dist/lib/neutral/react-surface-VZEVEJL5.mjs.map +7 -0
  53. package/dist/lib/neutral/restore-card-EKVEPATL.mjs +21 -0
  54. package/dist/lib/neutral/restore-card-EKVEPATL.mjs.map +7 -0
  55. package/dist/lib/neutral/restore-card-field-TQCTGGNO.mjs +37 -0
  56. package/dist/lib/neutral/restore-card-field-TQCTGGNO.mjs.map +7 -0
  57. package/dist/lib/neutral/testing/index.mjs +62 -0
  58. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  59. package/dist/lib/neutral/translations.mjs +44 -0
  60. package/dist/lib/neutral/translations.mjs.map +7 -0
  61. package/dist/lib/neutral/types/index.mjs +22 -0
  62. package/dist/lib/neutral/types/index.mjs.map +7 -0
  63. package/dist/lib/neutral/undo-mappings-6CHW6BOF.mjs +42 -0
  64. package/dist/lib/neutral/undo-mappings-6CHW6BOF.mjs.map +7 -0
  65. package/dist/types/src/KanbanPlugin.d.ts +3 -1
  66. package/dist/types/src/KanbanPlugin.d.ts.map +1 -1
  67. package/dist/types/src/KanbanPlugin.node.d.ts +4 -0
  68. package/dist/types/src/KanbanPlugin.node.d.ts.map +1 -0
  69. package/dist/types/src/KanbanPlugin.test.d.ts +2 -0
  70. package/dist/types/src/KanbanPlugin.test.d.ts.map +1 -0
  71. package/dist/types/src/KanbanPlugin.workerd.d.ts +4 -0
  72. package/dist/types/src/KanbanPlugin.workerd.d.ts.map +1 -0
  73. package/dist/types/src/blueprints/index.d.ts +2 -0
  74. package/dist/types/src/blueprints/index.d.ts.map +1 -0
  75. package/dist/types/src/blueprints/kanban-blueprint.d.ts +4 -0
  76. package/dist/types/src/blueprints/kanban-blueprint.d.ts.map +1 -0
  77. package/dist/types/src/capabilities/artifact-definition.d.ts +3 -2
  78. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  79. package/dist/types/src/capabilities/blueprint-definition.d.ts +6 -0
  80. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
  81. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  82. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  83. package/dist/types/src/capabilities/index.d.ts +13 -2
  84. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  85. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  86. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  87. package/dist/types/src/capabilities/react-surface.d.ts +3 -2
  88. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/undo-mappings.d.ts +5 -0
  90. package/dist/types/src/capabilities/undo-mappings.d.ts.map +1 -0
  91. package/dist/types/src/components/KanbanBoard/KanbanBoard.d.ts +37 -0
  92. package/dist/types/src/components/KanbanBoard/KanbanBoard.d.ts.map +1 -0
  93. package/dist/types/src/components/KanbanBoard/KanbanBoard.stories.d.ts +72 -0
  94. package/dist/types/src/components/KanbanBoard/KanbanBoard.stories.d.ts.map +1 -0
  95. package/dist/types/src/components/KanbanBoard/KanbanCard.d.ts +9 -0
  96. package/dist/types/src/components/KanbanBoard/KanbanCard.d.ts.map +1 -0
  97. package/dist/types/src/components/KanbanBoard/KanbanColumn.d.ts +8 -0
  98. package/dist/types/src/components/KanbanBoard/KanbanColumn.d.ts.map +1 -0
  99. package/dist/types/src/components/KanbanBoard/context.d.ts +38 -0
  100. package/dist/types/src/components/KanbanBoard/context.d.ts.map +1 -0
  101. package/dist/types/src/components/KanbanBoard/index.d.ts +2 -0
  102. package/dist/types/src/components/KanbanBoard/index.d.ts.map +1 -0
  103. package/dist/types/src/components/index.d.ts +1 -2
  104. package/dist/types/src/components/index.d.ts.map +1 -1
  105. package/dist/types/src/containers/KanbanArticle/KanbanArticle.d.ts +6 -0
  106. package/dist/types/src/containers/KanbanArticle/KanbanArticle.d.ts.map +1 -0
  107. package/dist/types/src/containers/KanbanArticle/KanbanArticle.stories.d.ts +79 -0
  108. package/dist/types/src/containers/KanbanArticle/KanbanArticle.stories.d.ts.map +1 -0
  109. package/dist/types/src/containers/KanbanArticle/index.d.ts +2 -0
  110. package/dist/types/src/containers/KanbanArticle/index.d.ts.map +1 -0
  111. package/dist/types/src/containers/KanbanSettings/KanbanSettings.d.ts +13 -0
  112. package/dist/types/src/containers/KanbanSettings/KanbanSettings.d.ts.map +1 -0
  113. package/dist/types/src/containers/KanbanSettings/index.d.ts +2 -0
  114. package/dist/types/src/containers/KanbanSettings/index.d.ts.map +1 -0
  115. package/dist/types/src/containers/index.d.ts +4 -0
  116. package/dist/types/src/containers/index.d.ts.map +1 -0
  117. package/dist/types/src/hooks/index.d.ts +7 -0
  118. package/dist/types/src/hooks/index.d.ts.map +1 -0
  119. package/dist/types/src/hooks/useEchoChangeCallback.d.ts +13 -0
  120. package/dist/types/src/hooks/useEchoChangeCallback.d.ts.map +1 -0
  121. package/dist/types/src/hooks/useItemsProjection.d.ts +10 -0
  122. package/dist/types/src/hooks/useItemsProjection.d.ts.map +1 -0
  123. package/dist/types/src/hooks/useKanbanBoardModel.browser.test.d.ts +2 -0
  124. package/dist/types/src/hooks/useKanbanBoardModel.browser.test.d.ts.map +1 -0
  125. package/dist/types/src/hooks/useKanbanBoardModel.d.ts +16 -0
  126. package/dist/types/src/hooks/useKanbanBoardModel.d.ts.map +1 -0
  127. package/dist/types/src/hooks/useKanbanColumnEventHandler.d.ts +22 -0
  128. package/dist/types/src/hooks/useKanbanColumnEventHandler.d.ts.map +1 -0
  129. package/dist/types/src/hooks/useKanbanItemEventHandler.d.ts +19 -0
  130. package/dist/types/src/hooks/useKanbanItemEventHandler.d.ts.map +1 -0
  131. package/dist/types/src/hooks/useProjectionModel.d.ts +15 -0
  132. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
  133. package/dist/types/src/index.d.ts +3 -1
  134. package/dist/types/src/index.d.ts.map +1 -1
  135. package/dist/types/src/meta.d.ts +2 -3
  136. package/dist/types/src/meta.d.ts.map +1 -1
  137. package/dist/types/src/operations/delete-card-field.d.ts +5 -0
  138. package/dist/types/src/operations/delete-card-field.d.ts.map +1 -0
  139. package/dist/types/src/operations/delete-card.d.ts +5 -0
  140. package/dist/types/src/operations/delete-card.d.ts.map +1 -0
  141. package/dist/types/src/operations/index.d.ts +3 -0
  142. package/dist/types/src/operations/index.d.ts.map +1 -0
  143. package/dist/types/src/operations/restore-card-field.d.ts +5 -0
  144. package/dist/types/src/operations/restore-card-field.d.ts.map +1 -0
  145. package/dist/types/src/operations/restore-card.d.ts +5 -0
  146. package/dist/types/src/operations/restore-card.d.ts.map +1 -0
  147. package/dist/types/src/playwright/board-manager.d.ts +5 -0
  148. package/dist/types/src/playwright/board-manager.d.ts.map +1 -0
  149. package/dist/types/src/playwright/playwright.config.d.ts +3 -0
  150. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -0
  151. package/dist/types/src/playwright/smoke.spec.d.ts +2 -0
  152. package/dist/types/src/playwright/smoke.spec.d.ts.map +1 -0
  153. package/dist/types/src/plugin.d.ts +4 -0
  154. package/dist/types/src/plugin.d.ts.map +1 -0
  155. package/dist/types/src/testing/KanbanCardTileSimple.d.ts +7 -0
  156. package/dist/types/src/testing/KanbanCardTileSimple.d.ts.map +1 -0
  157. package/dist/types/src/testing/index.d.ts +2 -0
  158. package/dist/types/src/testing/index.d.ts.map +1 -0
  159. package/dist/types/src/translations.d.ts +50 -22
  160. package/dist/types/src/translations.d.ts.map +1 -1
  161. package/dist/types/src/types/Kanban.d.ts +94 -0
  162. package/dist/types/src/types/Kanban.d.ts.map +1 -0
  163. package/dist/types/src/types/KanbanOperation.d.ts +52 -0
  164. package/dist/types/src/types/KanbanOperation.d.ts.map +1 -0
  165. package/dist/types/src/types/constants.d.ts +6 -0
  166. package/dist/types/src/types/constants.d.ts.map +1 -0
  167. package/dist/types/src/types/index.d.ts +3 -1
  168. package/dist/types/src/types/index.d.ts.map +1 -1
  169. package/dist/types/src/types/schema.d.ts +18 -95
  170. package/dist/types/src/types/schema.d.ts.map +1 -1
  171. package/dist/types/src/types/types.d.ts +28 -0
  172. package/dist/types/src/types/types.d.ts.map +1 -1
  173. package/dist/types/src/util/arrangement.d.ts +72 -0
  174. package/dist/types/src/util/arrangement.d.ts.map +1 -0
  175. package/dist/types/src/util/arrangement.test.d.ts +2 -0
  176. package/dist/types/src/util/arrangement.test.d.ts.map +1 -0
  177. package/dist/types/src/util/index.d.ts +2 -0
  178. package/dist/types/src/util/index.d.ts.map +1 -0
  179. package/dist/types/tsconfig.tsbuildinfo +1 -1
  180. package/package.json +127 -55
  181. package/src/KanbanPlugin.node.ts +21 -0
  182. package/src/KanbanPlugin.test.ts +31 -0
  183. package/src/KanbanPlugin.tsx +24 -52
  184. package/src/KanbanPlugin.workerd.ts +18 -0
  185. package/src/blueprints/index.ts +5 -0
  186. package/src/blueprints/kanban-blueprint.ts +27 -0
  187. package/src/capabilities/artifact-definition.ts +119 -114
  188. package/src/capabilities/blueprint-definition.ts +19 -0
  189. package/src/capabilities/create-object.ts +40 -0
  190. package/src/capabilities/index.ts +16 -3
  191. package/src/capabilities/operation-handler.ts +14 -0
  192. package/src/capabilities/react-surface.tsx +90 -69
  193. package/src/capabilities/undo-mappings.ts +34 -0
  194. package/src/components/KanbanBoard/KanbanBoard.stories.tsx +145 -0
  195. package/src/components/KanbanBoard/KanbanBoard.tsx +164 -0
  196. package/src/components/KanbanBoard/KanbanCard.tsx +101 -0
  197. package/src/components/KanbanBoard/KanbanColumn.tsx +72 -0
  198. package/src/components/KanbanBoard/context.ts +54 -0
  199. package/src/components/KanbanBoard/index.ts +5 -0
  200. package/src/components/index.ts +1 -2
  201. package/src/containers/KanbanArticle/KanbanArticle.stories.tsx +277 -0
  202. package/src/containers/KanbanArticle/KanbanArticle.tsx +179 -0
  203. package/src/containers/KanbanArticle/index.ts +5 -0
  204. package/src/containers/KanbanSettings/KanbanSettings.tsx +94 -0
  205. package/src/containers/KanbanSettings/index.ts +5 -0
  206. package/src/containers/index.ts +8 -0
  207. package/src/hooks/index.ts +10 -0
  208. package/src/hooks/useEchoChangeCallback.ts +30 -0
  209. package/src/hooks/useItemsProjection.ts +44 -0
  210. package/src/hooks/useKanbanBoardModel.browser.test.ts +230 -0
  211. package/src/hooks/useKanbanBoardModel.ts +156 -0
  212. package/src/hooks/useKanbanColumnEventHandler.ts +106 -0
  213. package/src/hooks/useKanbanItemEventHandler.ts +133 -0
  214. package/src/hooks/useProjectionModel.ts +58 -0
  215. package/src/index.ts +3 -2
  216. package/src/meta.ts +27 -8
  217. package/src/operations/delete-card-field.ts +42 -0
  218. package/src/operations/delete-card.ts +23 -0
  219. package/src/operations/index.ts +10 -0
  220. package/src/operations/restore-card-field.ts +36 -0
  221. package/src/operations/restore-card.ts +21 -0
  222. package/src/playwright/board-manager.ts +13 -0
  223. package/src/playwright/playwright.config.ts +19 -0
  224. package/src/playwright/smoke.spec.ts +107 -0
  225. package/src/plugin.ts +11 -0
  226. package/src/testing/KanbanCardTileSimple.tsx +82 -0
  227. package/src/testing/index.ts +5 -0
  228. package/src/translations.ts +28 -20
  229. package/src/types/Kanban.ts +134 -0
  230. package/src/types/KanbanOperation.ts +79 -0
  231. package/src/types/constants.ts +9 -0
  232. package/src/types/index.ts +4 -1
  233. package/src/types/schema.ts +33 -45
  234. package/src/types/types.ts +35 -0
  235. package/src/util/arrangement.test.ts +217 -0
  236. package/src/util/arrangement.ts +177 -0
  237. package/src/util/index.ts +5 -0
  238. package/src/vite-env.d.ts +10 -0
  239. package/dist/lib/browser/chunk-5BR6HNHI.mjs +0 -108
  240. package/dist/lib/browser/chunk-5BR6HNHI.mjs.map +0 -7
  241. package/dist/lib/browser/index.mjs +0 -99
  242. package/dist/lib/browser/index.mjs.map +0 -7
  243. package/dist/lib/browser/intent-resolver-65UVYRI2.mjs +0 -111
  244. package/dist/lib/browser/intent-resolver-65UVYRI2.mjs.map +0 -7
  245. package/dist/lib/browser/meta.json +0 -1
  246. package/dist/lib/browser/react-surface-KX5U6PJ2.mjs +0 -256
  247. package/dist/lib/browser/react-surface-KX5U6PJ2.mjs.map +0 -7
  248. package/dist/lib/browser/types/index.mjs +0 -13
  249. package/dist/lib/node-esm/chunk-WLFZKRIJ.mjs +0 -110
  250. package/dist/lib/node-esm/chunk-WLFZKRIJ.mjs.map +0 -7
  251. package/dist/lib/node-esm/index.mjs +0 -100
  252. package/dist/lib/node-esm/index.mjs.map +0 -7
  253. package/dist/lib/node-esm/intent-resolver-R3MYQATZ.mjs +0 -112
  254. package/dist/lib/node-esm/intent-resolver-R3MYQATZ.mjs.map +0 -7
  255. package/dist/lib/node-esm/meta.json +0 -1
  256. package/dist/lib/node-esm/react-surface-BAMERRU5.mjs +0 -257
  257. package/dist/lib/node-esm/react-surface-BAMERRU5.mjs.map +0 -7
  258. package/dist/lib/node-esm/types/index.mjs +0 -14
  259. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  260. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  261. package/dist/types/src/components/KanbanContainer.d.ts +0 -7
  262. package/dist/types/src/components/KanbanContainer.d.ts.map +0 -1
  263. package/dist/types/src/components/KanbanContainer.stories.d.ts +0 -10
  264. package/dist/types/src/components/KanbanContainer.stories.d.ts.map +0 -1
  265. package/dist/types/src/components/KanbanViewEditor.d.ts +0 -8
  266. package/dist/types/src/components/KanbanViewEditor.d.ts.map +0 -1
  267. package/dist/types/src/types/kanban.d.ts +0 -11
  268. package/dist/types/src/types/kanban.d.ts.map +0 -1
  269. package/src/capabilities/intent-resolver.ts +0 -70
  270. package/src/components/KanbanContainer.stories.tsx +0 -189
  271. package/src/components/KanbanContainer.tsx +0 -95
  272. package/src/components/KanbanViewEditor.tsx +0 -60
  273. package/src/types/kanban.ts +0 -29
  274. /package/dist/lib/{browser/types → neutral/blueprints}/index.mjs.map +0 -0
  275. /package/dist/lib/{node-esm/types/index.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
@@ -5,22 +5,22 @@
5
5
  // ISSUE(burdon): defineArtifact
6
6
  // @ts-nocheck
7
7
 
8
- import { Schema, pipe } from 'effect';
8
+ import * as Effect from 'effect/Effect';
9
+ import * as Schema from 'effect/Schema';
9
10
 
10
11
  import { ToolResult, createTool } from '@dxos/ai';
11
- import { Capabilities, type PromiseIntentDispatcher, chain, contributes, createIntent } from '@dxos/app-framework';
12
+ import { Capabilities, Capability, type PromiseIntentDispatcher } from '@dxos/app-framework';
12
13
  import { createArtifactElement } from '@dxos/assistant';
13
- import { defineArtifact } from '@dxos/blueprints';
14
- import { Obj, Query } from '@dxos/echo';
14
+ import { defineArtifact } from '@dxos/compute';
15
+ import { Filter, Obj, Query, Type, View } from '@dxos/echo';
15
16
  import { invariant } from '@dxos/invariant';
16
- import { SpaceAction } from '@dxos/plugin-space/types';
17
- import { Filter, type Space, fullyQualifiedId } from '@dxos/react-client/echo';
18
- import { KanbanView } from '@dxos/react-ui-kanban';
19
- import { DataType } from '@dxos/schema';
17
+ import { SpaceOperation } from '@dxos/plugin-space';
18
+ import { type Space } from '@dxos/react-client/echo';
19
+ import { ViewModel } from '@dxos/schema';
20
20
  import { isNonNullable } from '@dxos/util';
21
21
 
22
- import { meta } from '../meta';
23
- import { KanbanAction } from '../types';
22
+ import { meta } from '#meta';
23
+ import { Kanban } from '#types';
24
24
 
25
25
  const QualifiedId = Schema.String.annotations({
26
26
  description: 'The fully qualified ID of the kanban `spaceID:objectID`',
@@ -33,115 +33,120 @@ declare global {
33
33
  }
34
34
  }
35
35
 
36
- export default () => {
37
- const definition = defineArtifact({
38
- id: `artifact:${meta.id}`,
39
- name: meta.name,
40
- instructions: `
36
+ export default Capability.makeModule(() =>
37
+ Effect.sync(() => {
38
+ const definition = defineArtifact({
39
+ id: `artifact:${meta.id}`,
40
+ name: meta.name,
41
+ instructions: `
41
42
  - Before adding items to a kanban board, inspect the board to see its schema
42
43
  - When adding items, you must not include the 'id' field -- it is automatically generated
43
44
  - BEFORE adding items, always make sure the board has been shown to the user!
44
45
  `,
45
- schema: KanbanView,
46
- tools: [
47
- createTool(meta.id, {
48
- name: 'create',
49
- description: `
46
+ schema: Kanban.Kanban,
47
+ tools: [
48
+ createTool(meta.id, {
49
+ name: 'create',
50
+ description: `
50
51
  Create a new kanban board using an existing schema.
51
52
  Use schema_create first to create a schema, or schema_list to choose an existing one.`,
52
- caption: 'Creating kanban board...',
53
- schema: Schema.Struct({
54
- typename: Schema.String.annotations({
55
- description: 'The fully qualified name of the record type to use for the kanban cards.',
56
- }),
57
- pivotColumn: Schema.optional(Schema.String).annotations({
58
- description: 'Optional field name to use as the column pivot.',
59
- }),
60
- }),
61
- execute: async ({ typename, pivotColumn }, { extensions }) => {
62
- invariant(extensions?.space, 'No space');
63
- invariant(extensions?.dispatch, 'No intent dispatcher');
64
-
65
- // Validate schema exists first
66
- const schema = await extensions.space.db.schemaRegistry.query({ typename }).firstOrUndefined();
67
- if (!schema) {
68
- return ToolResult.Error(`Schema not found: ${typename}`);
69
- }
70
-
71
- const intent = pipe(
72
- createIntent(KanbanAction.Create, {
73
- space: extensions.space,
74
- typename,
75
- initialPivotColumn: pivotColumn,
53
+ caption: 'Creating kanban board...',
54
+ schema: Schema.Struct({
55
+ typename: Schema.String.annotations({
56
+ description: 'The fully qualified name of the record type to use for the kanban cards.',
76
57
  }),
77
- chain(SpaceAction.AddObject, { target: extensions.space }),
78
- );
79
-
80
- const { data, error } = await extensions.dispatch(intent);
81
- if (!data || error) {
82
- return ToolResult.Error(error?.message ?? 'Failed to create kanban board');
83
- }
84
-
85
- return ToolResult.Success(createArtifactElement(data.id));
86
- },
87
- }),
88
- createTool(meta.id, {
89
- name: 'list',
90
- description: 'List all kanban boards in the current space.',
91
- caption: 'Listing kanban boards...',
92
- schema: Schema.Struct({}),
93
- execute: async (_input, { extensions }) => {
94
- invariant(extensions?.space, 'No space');
95
- const space = extensions.space;
96
- const { objects } = await space.db.query(Filter.type(DataType.View)).run();
97
-
98
- const boardInfo = await Promise.all(
99
- objects.map(async (view) => {
100
- const kanban = await view.presentation.load();
101
- if (!Obj.instanceOf(KanbanView, kanban)) {
102
- return null;
103
- }
104
-
105
- return {
106
- id: fullyQualifiedId(view),
107
- name: view.name ?? 'Unnamed Kanban',
108
- typename: view.query.typename,
109
- };
58
+ pivotColumn: Schema.optional(Schema.String).annotations({
59
+ description: 'Optional field name to use as the column pivot.',
110
60
  }),
111
- );
112
-
113
- return ToolResult.Success(boardInfo.filter(isNonNullable));
114
- },
115
- }),
116
- createTool(meta.id, {
117
- name: 'inspect',
118
- description: 'Get details about a specific kanban board.',
119
- caption: 'Inspecting kanban board...',
120
- schema: Schema.Struct({ id: QualifiedId }),
121
- execute: async ({ id }, { extensions }) => {
122
- invariant(extensions?.space, 'No space');
123
- const space = extensions.space;
124
- const view = (await space.db
125
- // TODO(wittjosiah): Filter.and should aggregate type
126
- .query(Query.select(Filter.and(Filter.type(DataType.View), Filter.ids(id))))
127
- .first()) as DataType.View;
128
-
129
- const kanban = await view.presentation.load();
130
- invariant(Obj.instanceOf(KanbanView, kanban));
131
-
132
- const typename = view.query.typename;
133
- const schema = await space.db.schemaRegistry.query({ typename }).firstOrUndefined();
134
- invariant(schema);
135
-
136
- return ToolResult.Success({
137
- schema,
138
- columnField: kanban.columnFieldId,
139
- viewFields: view.projection.fields,
140
- });
141
- },
142
- }),
143
- ],
144
- });
145
-
146
- return contributes(Capabilities.ArtifactDefinition, definition);
147
- };
61
+ }),
62
+ execute: async ({ typename, pivotColumn }, { extensions }) => {
63
+ invariant(extensions?.space, 'No space');
64
+ invariant(extensions?.invoke, 'No operation invoker');
65
+
66
+ // Validate schema exists first.
67
+ const types = extensions.space.db.graph.registry.list().filter(Type.isType);
68
+ const schema = types.find((t) => Type.getTypename(t) === typename);
69
+ if (!schema) {
70
+ return ToolResult.Error(`Schema not found: ${typename}`);
71
+ }
72
+
73
+ const { view } = await ViewModel.makeFromDatabase({
74
+ db: extensions.space.db,
75
+ typename,
76
+ pivotFieldName: pivotColumn,
77
+ });
78
+ const kanban = Kanban.make({ view });
79
+
80
+ const { error } = await extensions.invoke(SpaceOperation.AddObject, {
81
+ target: extensions.space,
82
+ object: kanban,
83
+ });
84
+ if (error) {
85
+ return ToolResult.Error(error?.message ?? 'Failed to add kanban board to space');
86
+ }
87
+
88
+ return ToolResult.Success(createArtifactElement(kanban.id));
89
+ },
90
+ }),
91
+ createTool(meta.id, {
92
+ name: 'list',
93
+ description: 'List all kanban boards in the current space.',
94
+ caption: 'Listing kanban boards...',
95
+ schema: Schema.Struct({}),
96
+ execute: async (_input, { extensions }) => {
97
+ invariant(extensions?.space, 'No space');
98
+ const space = extensions.space;
99
+ const { objects } = await space.db.query(Filter.type(View.View)).run();
100
+
101
+ const boardInfo = await Promise.all(
102
+ objects.map(async (view) => {
103
+ const kanban = await view.presentation.load();
104
+ if (!Obj.instanceOf(Kanban.Kanban, kanban)) {
105
+ return null;
106
+ }
107
+
108
+ return {
109
+ id: Obj.getURI(view),
110
+ name: view.name ?? 'Unnamed Kanban',
111
+ typename: view.query.typename,
112
+ };
113
+ }),
114
+ );
115
+
116
+ return ToolResult.Success(boardInfo.filter(isNonNullable));
117
+ },
118
+ }),
119
+ createTool(meta.id, {
120
+ name: 'inspect',
121
+ description: 'Get details about a specific kanban board.',
122
+ caption: 'Inspecting kanban board...',
123
+ schema: Schema.Struct({ id: QualifiedId }),
124
+ execute: async ({ id }, { extensions }) => {
125
+ invariant(extensions?.space, 'No space');
126
+ const space = extensions.space;
127
+ const view = (await space.db
128
+ // TODO(wittjosiah): Filter.and should aggregate type
129
+ .query(Query.select(Filter.and(Filter.type(View.View), Filter.id(id))))
130
+ .first()) as View.View;
131
+
132
+ const kanban = await view.presentation.load();
133
+ invariant(Obj.instanceOf(Kanban.Kanban, kanban));
134
+
135
+ const typename = view.query.typename;
136
+ const types = space.db.graph.registry.list().filter(Type.isType);
137
+ const schema = types.find((t) => Type.getTypename(t) === typename);
138
+ invariant(schema);
139
+
140
+ return ToolResult.Success({
141
+ schema,
142
+ columnField: view.projection.pivotFieldId,
143
+ viewFields: view.projection.fields,
144
+ });
145
+ },
146
+ }),
147
+ ],
148
+ });
149
+
150
+ return Capability.contributes(Capabilities.ArtifactDefinition, definition);
151
+ }),
152
+ );
@@ -0,0 +1,19 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities } from '@dxos/app-toolkit';
9
+
10
+ import { KanbanBlueprint } from '#blueprints';
11
+
12
+ // NOTE: Explicit annotation required: d.ts emit cannot portably name the inferred @dxos/compute types (TS2883).
13
+ const blueprintDefinition: () => Effect.Effect<
14
+ Capability.Capability<typeof AppCapabilities.BlueprintDefinition>[],
15
+ never,
16
+ Capability.Service
17
+ > = () => Effect.succeed([Capability.contributes(AppCapabilities.BlueprintDefinition, KanbanBlueprint)]);
18
+
19
+ export default blueprintDefinition;
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { Operation } from '@dxos/compute';
9
+ import { Type } from '@dxos/echo';
10
+ import { SpaceOperation } from '@dxos/plugin-space';
11
+ import { SpaceCapabilities } from '@dxos/plugin-space';
12
+ import { ViewModel } from '@dxos/schema';
13
+
14
+ import { CreateKanbanSchema, Kanban } from '#types';
15
+
16
+ export default Capability.makeModule(
17
+ Effect.fnUntraced(function* () {
18
+ return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {
19
+ id: Type.getTypename(Kanban.Kanban),
20
+ inputSchema: CreateKanbanSchema,
21
+ createObject: (props, options) =>
22
+ Effect.gen(function* () {
23
+ const object = yield* Effect.promise(async () => {
24
+ const { view } = await ViewModel.makeFromDatabase({
25
+ db: options.db,
26
+ typename: props.typename,
27
+ pivotFieldName: props.initialPivotColumn,
28
+ });
29
+ return Kanban.make({ name: props.name, view });
30
+ });
31
+ return yield* Operation.invoke(SpaceOperation.AddObject, {
32
+ object,
33
+ target: options.target,
34
+ hidden: true,
35
+ targetNodeId: options.targetNodeId,
36
+ });
37
+ }),
38
+ });
39
+ }),
40
+ );
@@ -2,7 +2,20 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { lazy } from '@dxos/app-framework';
5
+ import { Capability } from '@dxos/app-framework';
6
+ import { type AppCapabilities } from '@dxos/app-toolkit';
7
+ import type { OperationHandlerSet } from '@dxos/compute';
6
8
 
7
- export const IntentResolver = lazy(() => import('./intent-resolver'));
8
- export const ReactSurface = lazy(() => import('./react-surface'));
9
+ // The contributed capability type references Blueprint types from @dxos/compute, so the lazy
10
+ // wrapper needs an explicit annotation to keep the inferred type portable (TS2883).
11
+ export const BlueprintDefinition: Capability.LazyCapability<
12
+ void,
13
+ Capability.Capability<typeof AppCapabilities.BlueprintDefinition>[]
14
+ > = Capability.lazy('BlueprintDefinition', () => import('./blueprint-definition'));
15
+ export const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));
16
+ export const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(
17
+ 'OperationHandler',
18
+ () => import('./operation-handler'),
19
+ );
20
+ export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
21
+ export const UndoMappings = Capability.lazy('UndoMappings', () => import('./undo-mappings'));
@@ -0,0 +1,14 @@
1
+ // Copyright 2025 DXOS.org
2
+
3
+ import * as Effect from 'effect/Effect';
4
+
5
+ import { Capabilities, Capability } from '@dxos/app-framework';
6
+ import type { OperationHandlerSet } from '@dxos/compute';
7
+
8
+ import { KanbanOperationHandlerSet } from '#operations';
9
+
10
+ export default Capability.makeModule<OperationHandlerSet.OperationHandlerSet>(
11
+ Effect.fnUntraced(function* () {
12
+ return Capability.contributes(Capabilities.OperationHandler, KanbanOperationHandlerSet);
13
+ }),
14
+ );
@@ -2,83 +2,104 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect';
5
+ import * as Effect from 'effect/Effect';
6
+ import type * as Schema from 'effect/Schema';
7
+ import * as SchemaAST from 'effect/SchemaAST';
6
8
  import React, { useMemo } from 'react';
7
9
 
8
- import { Capabilities, contributes, createSurface, useCapabilities } from '@dxos/app-framework';
9
- import { Obj, Type } from '@dxos/echo';
10
- import { findAnnotation } from '@dxos/effect';
11
- import { ClientCapabilities } from '@dxos/plugin-client';
12
- import { type Space, getSpace, isSpace } from '@dxos/react-client/echo';
13
- import { type InputProps, SelectInput, useFormValues } from '@dxos/react-ui-form';
14
- import { KanbanView } from '@dxos/react-ui-kanban';
15
- import { DataType } from '@dxos/schema';
10
+ import { Capabilities, Capability } from '@dxos/app-framework';
11
+ import { Surface } from '@dxos/app-framework/ui';
12
+ import { AppSurface } from '@dxos/app-toolkit/ui';
13
+ import { type Collection, Database, Obj, Type } from '@dxos/echo';
14
+ import { SchemaEx } from '@dxos/effect';
15
+ import { type FormFieldComponentProps, SelectField, useFormValues } from '@dxos/react-ui-form';
16
16
 
17
- import { KanbanContainer, KanbanViewEditor } from '../components';
18
- import { meta } from '../meta';
19
- import { PivotColumnAnnotationId } from '../types';
17
+ import { KanbanArticle, KanbanSettings } from '#containers';
18
+ import { Kanban, PivotColumnAnnotationId } from '#types';
20
19
 
21
- export default () =>
22
- contributes(Capabilities.ReactSurface, [
23
- createSurface({
24
- id: meta.id,
25
- role: ['article', 'section'],
26
- filter: (data): data is { subject: DataType.View } =>
27
- Obj.instanceOf(DataType.View, data.subject) && Obj.instanceOf(KanbanView, data.subject.presentation.target),
28
- component: ({ data, role }) => <KanbanContainer view={data.subject} role={role} />,
29
- }),
30
- createSurface({
31
- id: `${meta.id}/object-settings`,
32
- role: 'object-settings',
33
- position: 'hoist',
34
- filter: (data): data is { subject: DataType.View } =>
35
- Obj.instanceOf(DataType.View, data.subject) && Obj.instanceOf(KanbanView, data.subject.presentation.target),
36
- component: ({ data }) => <KanbanViewEditor view={data.subject} />,
37
- }),
38
- createSurface({
39
- id: `${meta.id}/create-initial-schema-form-[pivot-column]`,
40
- role: 'form-input',
41
- filter: (
42
- data,
43
- ): data is { prop: string; schema: Schema.Schema<any>; target: Space | DataType.Collection | undefined } => {
44
- const annotation = findAnnotation<boolean>((data.schema as Schema.Schema.All).ast, PivotColumnAnnotationId);
45
- return !!annotation;
46
- },
47
- component: ({ data: { target }, ...inputProps }) => {
48
- const props = inputProps as any as InputProps;
49
- const space = isSpace(target) ? target : getSpace(target);
50
- if (!space) {
51
- return null;
52
- }
53
- const { typename } = useFormValues();
54
- // TODO(wittjosiah): Unify this schema lookup.
55
- const schemaWhitelists = useCapabilities(ClientCapabilities.SchemaWhiteList);
56
- const staticSchema = schemaWhitelists.flat().find((schema) => Type.getTypename(schema) === typename);
57
- const [selectedSchema] = space?.db.schemaRegistry.query({ typename }).runSync();
20
+ export default Capability.makeModule(() =>
21
+ Effect.succeed(
22
+ Capability.contributes(Capabilities.ReactSurface, [
23
+ Surface.create({
24
+ id: 'root',
25
+ // TODO(wittjosiah): Split into multiple surfaces if this filter proves too strict for non-article roles.
26
+ filter: AppSurface.oneOf(
27
+ AppSurface.object(AppSurface.Article, Kanban.Kanban),
28
+ AppSurface.object(AppSurface.Section, Kanban.Kanban),
29
+ ),
30
+ component: ({ data, role }) => <KanbanArticle role={role} subject={data.subject} />,
31
+ }),
32
+ Surface.create({
33
+ id: 'objectProperties',
34
+ position: 'first',
35
+ filter: AppSurface.object(AppSurface.ObjectProperties, Kanban.Kanban),
36
+ component: ({ data }) => <KanbanSettings subject={data.subject} />,
37
+ }),
38
+ Surface.create({
39
+ id: 'createInitialSchemaForm',
40
+ role: 'form-input',
41
+ filter: (
42
+ data,
43
+ ): data is {
44
+ prop: string;
45
+ schema: Schema.Schema<any>;
46
+ target: Database.Database | Collection.Collection | undefined;
47
+ fieldPropertyAst?: SchemaAST.AST;
48
+ } => {
49
+ const annotation = SchemaEx.findAnnotation<boolean>(
50
+ (data.schema as Schema.Schema.All).ast,
51
+ PivotColumnAnnotationId,
52
+ );
53
+ return !!annotation;
54
+ },
55
+ component: ({ data: { target, fieldPropertyAst }, ...inputProps }) => {
56
+ const ast = fieldPropertyAst;
57
+ if (!ast) {
58
+ return null;
59
+ }
58
60
 
59
- const singleSelectColumns = useMemo(() => {
60
- const properties = staticSchema
61
- ? Type.toJsonSchema(staticSchema).properties
62
- : selectedSchema?.jsonSchema?.properties;
63
- if (!properties) {
64
- return [];
61
+ const props = { ...inputProps, type: ast } as any as FormFieldComponentProps;
62
+ const db = Database.isDatabase(target) ? target : target && Obj.getDatabase(target);
63
+ if (!db) {
64
+ return null;
65
65
  }
66
66
 
67
- const columns = Object.entries(properties).reduce<string[]>((acc, [key, value]) => {
68
- if (typeof value === 'object' && value?.format === 'single-select') {
69
- acc.push(key);
67
+ const { typename } = useFormValues('KanbanForm');
68
+ const [selectedSchema] = useMemo(
69
+ () =>
70
+ db.graph.registry
71
+ .list()
72
+ .filter(Type.isType)
73
+ .filter((t) => Type.getTypename(t) === typename),
74
+ [db, typename],
75
+ );
76
+ const singleSelectColumns = useMemo(() => {
77
+ if (!selectedSchema) {
78
+ return [];
79
+ }
80
+ const jsonSchema = selectedSchema.jsonSchema;
81
+ const properties = jsonSchema.properties;
82
+ if (!properties) {
83
+ return [];
70
84
  }
71
- return acc;
72
- }, []);
73
85
 
74
- return columns;
75
- }, [selectedSchema?.jsonSchema, staticSchema]);
86
+ const columns = Object.entries(properties).reduce<string[]>((acc, [key, value]) => {
87
+ if (typeof value === 'object' && value?.format === 'single-select') {
88
+ acc.push(key);
89
+ }
90
+ return acc;
91
+ }, []);
76
92
 
77
- if (!typename) {
78
- return null;
79
- }
93
+ return columns;
94
+ }, [selectedSchema]);
95
+
96
+ if (!typename) {
97
+ return null;
98
+ }
80
99
 
81
- return <SelectInput {...props} options={singleSelectColumns.map((column) => ({ value: column }))} />;
82
- },
83
- }),
84
- ]);
100
+ return <SelectField {...props} options={singleSelectColumns.map((column) => ({ value: column }))} />;
101
+ },
102
+ }),
103
+ ]),
104
+ ),
105
+ );
@@ -0,0 +1,34 @@
1
+ // Copyright 2025 DXOS.org
2
+
3
+ import * as Effect from 'effect/Effect';
4
+
5
+ import { Capabilities, Capability, UndoMapping } from '@dxos/app-framework';
6
+
7
+ import { meta } from '#meta';
8
+ import { KanbanOperation } from '#types';
9
+
10
+ export default Capability.makeModule(() =>
11
+ Effect.succeed(
12
+ Capability.contributes(Capabilities.UndoMapping, [
13
+ UndoMapping.make({
14
+ operation: KanbanOperation.DeleteCardField,
15
+ inverse: KanbanOperation.RestoreCardField,
16
+ deriveContext: (input, output) => ({
17
+ view: input.view,
18
+ field: output.field,
19
+ props: output.props,
20
+ index: output.index,
21
+ }),
22
+ message: ['card-field-deleted.label', { ns: meta.id }],
23
+ }),
24
+ UndoMapping.make({
25
+ operation: KanbanOperation.DeleteCard,
26
+ inverse: KanbanOperation.RestoreCard,
27
+ deriveContext: (_input, output) => ({
28
+ card: output.card,
29
+ }),
30
+ message: ['card-deleted.label', { ns: meta.id }],
31
+ }),
32
+ ]),
33
+ ),
34
+ );