@dxos/plugin-kanban 0.8.4-main.abd8ff62ef → 0.8.4-main.bc2380dfbc
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.
- package/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/neutral/KanbanArticle-NEJ3LNBO.mjs +132 -0
- package/dist/lib/neutral/KanbanArticle-NEJ3LNBO.mjs.map +7 -0
- package/dist/lib/neutral/KanbanPlugin.mjs +36 -0
- package/dist/lib/neutral/KanbanPlugin.mjs.map +7 -0
- package/dist/lib/neutral/KanbanPlugin.node.mjs +27 -0
- package/dist/lib/neutral/KanbanPlugin.node.mjs.map +7 -0
- package/dist/lib/neutral/KanbanPlugin.workerd.mjs +21 -0
- package/dist/lib/neutral/KanbanPlugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/KanbanSettings-G6M47NSK.mjs +83 -0
- package/dist/lib/neutral/KanbanSettings-G6M47NSK.mjs.map +7 -0
- package/dist/lib/neutral/blueprint-definition-FHVIEKTQ.mjs +15 -0
- package/dist/lib/neutral/blueprint-definition-FHVIEKTQ.mjs.map +7 -0
- package/dist/lib/neutral/blueprints/index.mjs +8 -0
- package/dist/lib/neutral/capabilities/index.mjs +19 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/chunk-6FPBLOS3.mjs +8 -0
- package/dist/lib/neutral/chunk-6FPBLOS3.mjs.map +7 -0
- package/dist/lib/{browser/index.mjs → neutral/chunk-KDPM77BD.mjs} +1 -9
- package/dist/lib/neutral/chunk-KDPM77BD.mjs.map +7 -0
- package/dist/lib/neutral/chunk-OQ72EEGU.mjs +254 -0
- package/dist/lib/neutral/chunk-OQ72EEGU.mjs.map +7 -0
- package/dist/lib/{browser/blueprints/index.mjs → neutral/chunk-ZTQW5KQS.mjs} +3 -4
- package/dist/lib/{browser/blueprints/index.mjs.map → neutral/chunk-ZTQW5KQS.mjs.map} +2 -2
- package/dist/lib/neutral/components/index.mjs +243 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +11 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-object-DKBSI46K.mjs +40 -0
- package/dist/lib/neutral/create-object-DKBSI46K.mjs.map +7 -0
- package/dist/lib/{browser/delete-card-7OSCNCW2.mjs → neutral/delete-card-356CBACE.mjs} +4 -4
- package/dist/lib/neutral/delete-card-356CBACE.mjs.map +7 -0
- package/dist/lib/{browser/delete-card-field-NSB2RE3Z.mjs → neutral/delete-card-field-IRCZL2BR.mjs} +4 -4
- package/dist/lib/neutral/delete-card-field-IRCZL2BR.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +432 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +34 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +8 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/migrations-IWBT35UT.mjs +31 -0
- package/dist/lib/neutral/migrations-IWBT35UT.mjs.map +7 -0
- package/dist/lib/neutral/operation-handler-B7IW6MXU.mjs +13 -0
- package/dist/lib/neutral/operation-handler-B7IW6MXU.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +16 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-QROEHBRW.mjs +93 -0
- package/dist/lib/neutral/react-surface-QROEHBRW.mjs.map +7 -0
- package/dist/lib/{browser/restore-card-FO3WERIE.mjs → neutral/restore-card-P25Y4YSE.mjs} +4 -4
- package/dist/lib/neutral/restore-card-P25Y4YSE.mjs.map +7 -0
- package/dist/lib/{browser/restore-card-field-U5XYEEOW.mjs → neutral/restore-card-field-NHR3R4XI.mjs} +4 -4
- package/dist/lib/neutral/restore-card-field-NHR3R4XI.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +60 -0
- package/dist/lib/neutral/testing/index.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs +22 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/lib/neutral/undo-mappings-6CHW6BOF.mjs +42 -0
- package/dist/lib/neutral/undo-mappings-6CHW6BOF.mjs.map +7 -0
- package/dist/types/src/KanbanPlugin.d.ts.map +1 -1
- package/dist/types/src/KanbanPlugin.node.d.ts.map +1 -1
- package/dist/types/src/KanbanPlugin.workerd.d.ts +4 -0
- package/dist/types/src/KanbanPlugin.workerd.d.ts.map +1 -0
- package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +11 -0
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +6 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/migrations.d.ts +2 -1
- package/dist/types/src/capabilities/migrations.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanBoard.d.ts +3 -23
- package/dist/types/src/components/KanbanBoard/KanbanBoard.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanBoard.stories.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanCard.d.ts +2 -3
- package/dist/types/src/components/KanbanBoard/KanbanCard.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanColumn.d.ts +2 -3
- package/dist/types/src/components/KanbanBoard/KanbanColumn.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/context.d.ts +38 -0
- package/dist/types/src/components/KanbanBoard/context.d.ts.map +1 -0
- package/dist/types/src/containers/KanbanArticle/KanbanArticle.d.ts +6 -0
- package/dist/types/src/containers/KanbanArticle/KanbanArticle.d.ts.map +1 -0
- package/dist/types/src/containers/{KanbanContainer/KanbanContainer.stories.d.ts → KanbanArticle/KanbanArticle.stories.d.ts} +1 -1
- package/dist/types/src/containers/KanbanArticle/KanbanArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/KanbanArticle/index.d.ts +2 -0
- package/dist/types/src/containers/KanbanArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +1 -1
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/delete-card-field.d.ts +2 -2
- package/dist/types/src/operations/delete-card-field.d.ts.map +1 -1
- package/dist/types/src/operations/delete-card.d.ts +2 -2
- package/dist/types/src/operations/delete-card.d.ts.map +1 -1
- package/dist/types/src/operations/index.d.ts +0 -1
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/operations/restore-card-field.d.ts +2 -2
- package/dist/types/src/operations/restore-card-field.d.ts.map +1 -1
- package/dist/types/src/operations/restore-card.d.ts +2 -2
- package/dist/types/src/operations/restore-card.d.ts.map +1 -1
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/types/Kanban.d.ts +1 -2
- package/dist/types/src/types/Kanban.d.ts.map +1 -1
- package/dist/types/src/{operations/definitions.d.ts → types/KanbanOperation.d.ts} +1 -1
- package/dist/types/src/types/KanbanOperation.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +2 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +101 -73
- package/src/KanbanPlugin.node.ts +3 -37
- package/src/KanbanPlugin.tsx +11 -38
- package/src/KanbanPlugin.workerd.ts +18 -0
- package/src/capabilities/artifact-definition.ts +3 -4
- package/src/capabilities/create-object.ts +40 -0
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/migrations.ts +3 -3
- package/src/capabilities/react-surface.tsx +3 -4
- package/src/capabilities/undo-mappings.ts +1 -1
- package/src/components/KanbanBoard/KanbanBoard.stories.tsx +1 -2
- package/src/components/KanbanBoard/KanbanBoard.tsx +13 -47
- package/src/components/KanbanBoard/KanbanCard.tsx +75 -72
- package/src/components/KanbanBoard/KanbanColumn.tsx +9 -8
- package/src/components/KanbanBoard/context.ts +54 -0
- package/src/containers/{KanbanContainer/KanbanContainer.stories.tsx → KanbanArticle/KanbanArticle.stories.tsx} +9 -8
- package/src/containers/{KanbanContainer/KanbanContainer.tsx → KanbanArticle/KanbanArticle.tsx} +8 -8
- package/src/containers/KanbanArticle/index.ts +5 -0
- package/src/containers/index.ts +1 -1
- package/src/hooks/useKanbanBoardModel.browser.test.ts +1 -2
- package/src/index.ts +3 -6
- package/src/operations/delete-card-field.ts +2 -2
- package/src/operations/delete-card.ts +2 -2
- package/src/operations/index.ts +0 -2
- package/src/operations/restore-card-field.ts +2 -2
- package/src/operations/restore-card.ts +2 -2
- package/src/playwright/smoke.spec.ts +3 -3
- package/src/plugin.ts +11 -0
- package/src/types/Kanban.ts +1 -2
- package/src/{operations/definitions.ts → types/KanbanOperation.ts} +4 -0
- package/src/types/index.ts +3 -1
- package/src/types/migrations.test.ts +2 -3
- package/src/types/schema.ts +1 -1
- package/src/util/arrangement.test.ts +1 -2
- package/dist/lib/browser/chunk-T32TEM55.mjs +0 -105
- package/dist/lib/browser/chunk-T32TEM55.mjs.map +0 -7
- package/dist/lib/browser/delete-card-7OSCNCW2.mjs.map +0 -7
- package/dist/lib/browser/delete-card-field-NSB2RE3Z.mjs.map +0 -7
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/operations/index.mjs +0 -13
- package/dist/lib/browser/operations/index.mjs.map +0 -7
- package/dist/lib/browser/restore-card-FO3WERIE.mjs.map +0 -7
- package/dist/lib/browser/restore-card-field-U5XYEEOW.mjs.map +0 -7
- package/dist/lib/browser/types/index.mjs +0 -160
- package/dist/lib/browser/types/index.mjs.map +0 -7
- package/dist/lib/node-esm/blueprints/index.mjs +0 -28
- package/dist/lib/node-esm/blueprints/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-W2RNFBMZ.mjs +0 -106
- package/dist/lib/node-esm/chunk-W2RNFBMZ.mjs.map +0 -7
- package/dist/lib/node-esm/delete-card-ZIREL6HN.mjs +0 -25
- package/dist/lib/node-esm/delete-card-ZIREL6HN.mjs.map +0 -7
- package/dist/lib/node-esm/delete-card-field-IPTEGVPP.mjs +0 -43
- package/dist/lib/node-esm/delete-card-field-IPTEGVPP.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -30
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/operations/index.mjs +0 -14
- package/dist/lib/node-esm/operations/index.mjs.map +0 -7
- package/dist/lib/node-esm/restore-card-WJJ4YB7K.mjs +0 -22
- package/dist/lib/node-esm/restore-card-WJJ4YB7K.mjs.map +0 -7
- package/dist/lib/node-esm/restore-card-field-L24WJXAW.mjs +0 -41
- package/dist/lib/node-esm/restore-card-field-L24WJXAW.mjs.map +0 -7
- package/dist/lib/node-esm/translations.mjs +0 -45
- package/dist/lib/node-esm/translations.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -161
- package/dist/lib/node-esm/types/index.mjs.map +0 -7
- package/dist/types/src/containers/KanbanContainer/KanbanContainer.d.ts +0 -6
- package/dist/types/src/containers/KanbanContainer/KanbanContainer.d.ts.map +0 -1
- package/dist/types/src/containers/KanbanContainer/KanbanContainer.stories.d.ts.map +0 -1
- package/dist/types/src/containers/KanbanContainer/index.d.ts +0 -2
- package/dist/types/src/containers/KanbanContainer/index.d.ts.map +0 -1
- package/dist/types/src/operations/definitions.d.ts.map +0 -1
- package/src/containers/KanbanContainer/index.ts +0 -5
- /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/blueprints/index.mjs.map} +0 -0
- /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
- /package/dist/lib/{node-esm/chunk-HSLMI22Q.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/lib/{browser → neutral}/translations.mjs +0 -0
- /package/dist/lib/{browser → neutral}/translations.mjs.map +0 -0
|
@@ -9,90 +9,93 @@ import { AppSurface, useObjectMenuItems } from '@dxos/app-toolkit/ui';
|
|
|
9
9
|
import { Obj } from '@dxos/echo';
|
|
10
10
|
import { Card, Toolbar, useTranslation } from '@dxos/react-ui';
|
|
11
11
|
import { Menu, createMenuAction } from '@dxos/react-ui-menu';
|
|
12
|
-
import { Focus, Mosaic,
|
|
12
|
+
import { Focus, Mosaic, useBoard } from '@dxos/react-ui-mosaic';
|
|
13
13
|
|
|
14
14
|
import { meta } from '#meta';
|
|
15
15
|
|
|
16
|
-
import { useKanbanBoard } from './
|
|
16
|
+
import { type KanbanCardProps, useKanbanBoard } from './context';
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
export { type KanbanCardProps };
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const KANBAN_CARD_TILE_NAME = 'KanbanBoard.Card';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Mosaic Tile for Kanban card.
|
|
24
24
|
* Uses Surface for content; requires plugin manager context.
|
|
25
25
|
*/
|
|
26
|
-
export const KanbanCard = forwardRef<HTMLDivElement, KanbanCardProps>(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
export const KanbanCard = forwardRef<HTMLDivElement, KanbanCardProps>(
|
|
27
|
+
({ data, location, debug, draggable }, forwardedRef) => {
|
|
28
|
+
const { t } = useTranslation(meta.id);
|
|
29
|
+
const { model } = useBoard(KANBAN_CARD_TILE_NAME);
|
|
30
|
+
const { projection, columnFieldPath, onCardRemove } = useKanbanBoard(KANBAN_CARD_TILE_NAME);
|
|
31
|
+
const [dragHandle, setDragHandle] = useState<HTMLButtonElement | null>(null);
|
|
32
|
+
const dragHandleRef = useCallback((el: HTMLButtonElement | null) => setDragHandle(el), []);
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
const objectMenuItems = useObjectMenuItems(data);
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
const menuItems = useMemo(
|
|
37
|
+
() => [
|
|
38
|
+
...objectMenuItems,
|
|
39
|
+
...(onCardRemove
|
|
40
|
+
? [
|
|
41
|
+
createMenuAction('remove', () => onCardRemove(data), {
|
|
42
|
+
label: t('remove-card.label'),
|
|
43
|
+
icon: 'ph--trash--regular',
|
|
44
|
+
}),
|
|
45
|
+
]
|
|
46
|
+
: []),
|
|
47
|
+
],
|
|
48
|
+
[objectMenuItems, onCardRemove, data, t],
|
|
49
|
+
);
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
<Card.
|
|
63
|
-
<Card.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
51
|
+
return (
|
|
52
|
+
<Menu.Root>
|
|
53
|
+
<Mosaic.Tile
|
|
54
|
+
asChild
|
|
55
|
+
id={model.getItemId(data)}
|
|
56
|
+
data={data}
|
|
57
|
+
location={location}
|
|
58
|
+
debug={debug}
|
|
59
|
+
draggable={draggable}
|
|
60
|
+
dragHandle={dragHandle}
|
|
61
|
+
>
|
|
62
|
+
<Focus.Item asChild>
|
|
63
|
+
<Card.Root ref={forwardedRef} data-testid='board-item'>
|
|
64
|
+
<Card.Toolbar>
|
|
65
|
+
<Card.DragHandle ref={dragHandleRef} testId='mosaicBoard.cardDragHandle' />
|
|
66
|
+
<Card.Title data-testid='mosaicBoard.cardTitle'>{Obj.getLabel(data)}</Card.Title>
|
|
67
|
+
{/* TODO(wittjosiah): Reconcile with Card.Menu. */}
|
|
68
|
+
<Menu.Trigger asChild disabled={!menuItems?.length}>
|
|
69
|
+
<Toolbar.IconButton
|
|
70
|
+
iconOnly
|
|
71
|
+
variant='ghost'
|
|
72
|
+
icon='ph--dots-three-vertical--regular'
|
|
73
|
+
label={t('action-menu.label')}
|
|
74
|
+
/>
|
|
75
|
+
</Menu.Trigger>
|
|
76
|
+
<Menu.Content items={menuItems} />
|
|
77
|
+
</Card.Toolbar>
|
|
78
|
+
<Card.Content>
|
|
79
|
+
{projection && (
|
|
80
|
+
<Surface.Surface
|
|
81
|
+
type={AppSurface.Card}
|
|
82
|
+
limit={1}
|
|
83
|
+
data={{
|
|
84
|
+
subject: data,
|
|
85
|
+
projection,
|
|
86
|
+
// Hide the pivot field: its value is already conveyed by
|
|
87
|
+
// which column the card sits in.
|
|
88
|
+
ignorePaths: columnFieldPath ? [columnFieldPath] : undefined,
|
|
89
|
+
}}
|
|
90
|
+
/>
|
|
91
|
+
)}
|
|
92
|
+
</Card.Content>
|
|
93
|
+
</Card.Root>
|
|
94
|
+
</Focus.Item>
|
|
95
|
+
</Mosaic.Tile>
|
|
96
|
+
</Menu.Root>
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
);
|
|
97
100
|
|
|
98
101
|
KanbanCard.displayName = KANBAN_CARD_TILE_NAME;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { FC, forwardRef,
|
|
5
|
+
import React, { FC, forwardRef, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import type { Obj } from '@dxos/echo';
|
|
8
8
|
import { Board, type MosaicTileProps, useBoard } from '@dxos/react-ui-mosaic';
|
|
@@ -10,23 +10,23 @@ import { Board, type MosaicTileProps, useBoard } from '@dxos/react-ui-mosaic';
|
|
|
10
10
|
import { useKanbanItemEventHandler } from '#hooks';
|
|
11
11
|
import { type ColumnStructure, UNCATEGORIZED_VALUE } from '#types';
|
|
12
12
|
|
|
13
|
-
import { useKanbanBoard } from './
|
|
13
|
+
import { type KanbanColumnProps, useKanbanBoard } from './context';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
export { type KanbanColumnProps };
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const KANBAN_COLUMN_NAME = 'KanbanBoard.Column';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Mosaic Tile for Kanban column.
|
|
21
21
|
*/
|
|
22
22
|
export const KanbanColumn = forwardRef<HTMLDivElement, KanbanColumnProps>(
|
|
23
|
-
({ data: column, location, debug }, forwardedRef) => {
|
|
23
|
+
({ data: column, location, debug, draggable }, forwardedRef) => {
|
|
24
24
|
const { model } = useBoard<ColumnStructure, Obj.Unknown>(KANBAN_COLUMN_NAME);
|
|
25
25
|
const { columnFieldPath, change, onCardAdd, getPivotAttributes, itemTile } = useKanbanBoard(KANBAN_COLUMN_NAME);
|
|
26
26
|
|
|
27
27
|
const { title } = getPivotAttributes(column.columnValue);
|
|
28
28
|
const uncategorized = column.columnValue === UNCATEGORIZED_VALUE;
|
|
29
|
-
const
|
|
29
|
+
const [dragHandle, setDragHandle] = useState<HTMLButtonElement | null>(null);
|
|
30
30
|
|
|
31
31
|
const eventHandler = useKanbanItemEventHandler({
|
|
32
32
|
column,
|
|
@@ -41,7 +41,8 @@ export const KanbanColumn = forwardRef<HTMLDivElement, KanbanColumnProps>(
|
|
|
41
41
|
location={location}
|
|
42
42
|
classNames='grid grid-rows-[var(--dx-rail-action)_1fr_var(--dx-rail-action)]'
|
|
43
43
|
debug={debug}
|
|
44
|
-
|
|
44
|
+
draggable={draggable}
|
|
45
|
+
dragHandle={dragHandle}
|
|
45
46
|
ref={forwardedRef}
|
|
46
47
|
>
|
|
47
48
|
{uncategorized ? (
|
|
@@ -49,7 +50,7 @@ export const KanbanColumn = forwardRef<HTMLDivElement, KanbanColumnProps>(
|
|
|
49
50
|
<span className='font-medium'>{title}</span>
|
|
50
51
|
</div>
|
|
51
52
|
) : (
|
|
52
|
-
<Board.Column.Header label={title} dragHandleRef={
|
|
53
|
+
<Board.Column.Header label={title} dragHandleRef={setDragHandle} />
|
|
53
54
|
)}
|
|
54
55
|
<Board.Column.Body
|
|
55
56
|
data={column}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { createContext } from '@radix-ui/react-context';
|
|
6
|
+
import { type ComponentType } from 'react';
|
|
7
|
+
|
|
8
|
+
import { type Obj } from '@dxos/echo';
|
|
9
|
+
import { type MosaicTileProps } from '@dxos/react-ui-mosaic';
|
|
10
|
+
import { type ProjectionModel } from '@dxos/schema';
|
|
11
|
+
|
|
12
|
+
import { type ColumnStructure, type KanbanChangeCallback, UNCATEGORIZED_ATTRIBUTES, UNCATEGORIZED_VALUE } from '#types';
|
|
13
|
+
|
|
14
|
+
const KANBAN_BOARD_NAME = 'KanbanBoard.Context';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Card tile props. Defined here (rather than in `KanbanCard.tsx`) so the
|
|
18
|
+
* context type can reference it without forming a cycle through that
|
|
19
|
+
* module's runtime exports — webkit treats the resulting TDZ as a hard
|
|
20
|
+
* error while other engines are lenient.
|
|
21
|
+
*/
|
|
22
|
+
export type KanbanCardProps = Pick<MosaicTileProps<Obj.Unknown>, 'location' | 'data' | 'debug' | 'draggable'>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Column tile props. See note on {@link KanbanCardProps}.
|
|
26
|
+
*/
|
|
27
|
+
export type KanbanColumnProps = Pick<MosaicTileProps<ColumnStructure>, 'location' | 'data' | 'debug' | 'draggable'>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Context value for the Kanban board.
|
|
31
|
+
* Items are Echo objects (Obj.Unknown).
|
|
32
|
+
*/
|
|
33
|
+
export type KanbanBoardContextValue = {
|
|
34
|
+
kanbanId: string;
|
|
35
|
+
projection: ProjectionModel | undefined;
|
|
36
|
+
columnFieldPath: string | undefined;
|
|
37
|
+
change: KanbanChangeCallback<Obj.Unknown>;
|
|
38
|
+
pivotFieldId: string | undefined;
|
|
39
|
+
getPivotAttributes: (columnValue: string) => { title: string; color: string };
|
|
40
|
+
itemTile?: ComponentType<KanbanCardProps>; // TODO(burdon): Prop.
|
|
41
|
+
onCardAdd?: (columnValue: string | undefined) => string | undefined;
|
|
42
|
+
onCardRemove?: (card: Obj.Unknown) => void;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const [KanbanBoardContext, useKanbanBoard] = createContext<KanbanBoardContextValue>(KANBAN_BOARD_NAME, {
|
|
46
|
+
kanbanId: 'never',
|
|
47
|
+
projection: undefined,
|
|
48
|
+
columnFieldPath: undefined,
|
|
49
|
+
change: { kanban: () => {}, setItemField: () => {} },
|
|
50
|
+
pivotFieldId: undefined,
|
|
51
|
+
getPivotAttributes: (id: string) =>
|
|
52
|
+
id === UNCATEGORIZED_VALUE ? UNCATEGORIZED_ATTRIBUTES : { title: id, color: 'neutral' },
|
|
53
|
+
itemTile: (() => null) as ComponentType<KanbanCardProps>,
|
|
54
|
+
});
|
|
@@ -11,17 +11,18 @@ import { expect, waitFor, within } from 'storybook/test';
|
|
|
11
11
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
12
|
import { Surface } from '@dxos/app-framework/ui';
|
|
13
13
|
import { AppSurface } from '@dxos/app-toolkit/ui';
|
|
14
|
-
import { Obj, type QueryAST, Type } from '@dxos/echo';
|
|
15
|
-
import { View } from '@dxos/echo';
|
|
14
|
+
import { Filter, Obj, type QueryAST, Type, View } from '@dxos/echo';
|
|
16
15
|
import { type Mutable } from '@dxos/echo/internal';
|
|
17
16
|
import { invariant } from '@dxos/invariant';
|
|
18
|
-
|
|
17
|
+
// `/plugin` entrypoints used here for the same reason as `corePlugins()` —
|
|
18
|
+
// see `@dxos/plugin-testing/src/core.ts` for the rationale.
|
|
19
|
+
import { ClientPlugin } from '@dxos/plugin-client/testing';
|
|
19
20
|
import { initializeIdentity } from '@dxos/plugin-client/testing';
|
|
20
|
-
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
21
|
-
import { SpacePlugin } from '@dxos/plugin-space';
|
|
21
|
+
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
22
|
+
import { SpacePlugin } from '@dxos/plugin-space/testing';
|
|
22
23
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
23
24
|
import { random } from '@dxos/random';
|
|
24
|
-
import {
|
|
25
|
+
import { type Space, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
|
|
25
26
|
import { ViewEditor } from '@dxos/react-ui-form';
|
|
26
27
|
import { Syntax } from '@dxos/react-ui-syntax-highlighter';
|
|
27
28
|
import { withLayout } from '@dxos/react-ui/testing';
|
|
@@ -56,7 +57,7 @@ type ClientSetupOptions = {
|
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* Creates the standard plugin manager decorator with client configuration.
|
|
59
|
-
* Includes KanbanPlugin so the Surface resolves to
|
|
60
|
+
* Includes KanbanPlugin so the Surface resolves to KanbanArticle.
|
|
60
61
|
*/
|
|
61
62
|
const withKanbanPlugins = ({ types = [], onSpaceCreated }: ClientSetupOptions): Decorator =>
|
|
62
63
|
withPluginManager({
|
|
@@ -80,7 +81,7 @@ const withKanbanPlugins = ({ types = [], onSpaceCreated }: ClientSetupOptions):
|
|
|
80
81
|
});
|
|
81
82
|
|
|
82
83
|
/**
|
|
83
|
-
* Renders the first Kanban in the space via Surface (resolves to
|
|
84
|
+
* Renders the first Kanban in the space via Surface (resolves to KanbanArticle),
|
|
84
85
|
* with a sidebar containing ViewEditor and Json filter.
|
|
85
86
|
*/
|
|
86
87
|
const DefaultComponent = () => {
|
package/src/containers/{KanbanContainer/KanbanContainer.tsx → KanbanArticle/KanbanArticle.tsx}
RENAMED
|
@@ -16,23 +16,23 @@ import { getTagFromQuery, getTypenameFromQuery } from '@dxos/schema';
|
|
|
16
16
|
|
|
17
17
|
import { KanbanBoard } from '#components';
|
|
18
18
|
import { useEchoChangeCallback, useItemsProjection, useProjectionModel } from '#hooks';
|
|
19
|
-
import { KanbanOperation } from '#
|
|
19
|
+
import { KanbanOperation } from '#types';
|
|
20
20
|
import { Kanban } from '#types';
|
|
21
21
|
|
|
22
|
-
export type
|
|
22
|
+
export type KanbanArticleProps = AppSurface.ObjectArticleProps<Kanban.Kanban>;
|
|
23
23
|
|
|
24
|
-
export const
|
|
24
|
+
export const KanbanArticle = (props: KanbanArticleProps) => {
|
|
25
25
|
// Branch on `kanban.spec.kind`: view-variant runs a typename query through
|
|
26
26
|
// `useProjectionModel`; items-variant dereferences `kanban.spec.items` and
|
|
27
27
|
// uses a stub projection from `useItemsProjection`.
|
|
28
28
|
return Kanban.isKanbanItems(props.subject) ? (
|
|
29
|
-
<
|
|
29
|
+
<ItemsKanbanArticle {...props} subject={props.subject} />
|
|
30
30
|
) : (
|
|
31
|
-
<
|
|
31
|
+
<ViewKanbanArticle {...props} />
|
|
32
32
|
);
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
const
|
|
35
|
+
const ViewKanbanArticle = ({ role, subject: object }: KanbanArticleProps) => {
|
|
36
36
|
const registry = useContext(RegistryContext);
|
|
37
37
|
const schemas = useCapabilities(AppCapabilities.Schema);
|
|
38
38
|
const db = Obj.getDatabase(object);
|
|
@@ -106,9 +106,9 @@ const ViewKanbanContainer = ({ role, subject: object }: KanbanContainerProps) =>
|
|
|
106
106
|
);
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
type
|
|
109
|
+
type ItemsKanbanArticleProps = Omit<KanbanArticleProps, 'subject'> & { subject: Kanban.KanbanItems };
|
|
110
110
|
|
|
111
|
-
const
|
|
111
|
+
const ItemsKanbanArticle = ({ role, subject: object }: ItemsKanbanArticleProps) => {
|
|
112
112
|
const db = Obj.getDatabase(object);
|
|
113
113
|
const projection = useItemsProjection(object);
|
|
114
114
|
const change = useEchoChangeCallback(object);
|
package/src/containers/index.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentType, lazy } from 'react';
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const KanbanArticle: ComponentType<any> = lazy(() => import('./KanbanArticle'));
|
|
8
8
|
export const KanbanSettings: ComponentType<any> = lazy(() => import('./KanbanSettings'));
|
|
@@ -7,8 +7,7 @@ import { act, renderHook } from '@testing-library/react';
|
|
|
7
7
|
import * as Schema from 'effect/Schema';
|
|
8
8
|
import { beforeEach, describe, test } from 'vitest';
|
|
9
9
|
|
|
10
|
-
import { Filter, JsonSchema, Obj, Query, Type } from '@dxos/echo';
|
|
11
|
-
import { type View } from '@dxos/echo';
|
|
10
|
+
import { Filter, JsonSchema, Obj, Query, Type, type View } from '@dxos/echo';
|
|
12
11
|
import { Format, FormatAnnotation, PropertyMetaAnnotationId } from '@dxos/echo/internal';
|
|
13
12
|
import { ObjectId } from '@dxos/keys';
|
|
14
13
|
import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
|
package/src/index.ts
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { meta } from './meta';
|
|
8
|
-
|
|
9
|
-
export const KanbanPlugin = Plugin.lazy(meta, () => import('#plugin'));
|
|
10
|
-
|
|
5
|
+
export * from './blueprints';
|
|
11
6
|
export * from './meta';
|
|
7
|
+
export * from './operations';
|
|
8
|
+
export * from './types';
|
|
@@ -9,9 +9,9 @@ import { type EchoSchema } from '@dxos/echo/internal';
|
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
10
|
import { ProjectionModel, createEchoChangeCallback, getTypenameFromQuery } from '@dxos/schema';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { KanbanOperation } from '../types';
|
|
13
13
|
|
|
14
|
-
const handler: Operation.WithHandler<typeof DeleteCardField> = DeleteCardField.pipe(
|
|
14
|
+
const handler: Operation.WithHandler<typeof KanbanOperation.DeleteCardField> = KanbanOperation.DeleteCardField.pipe(
|
|
15
15
|
Operation.withHandler(
|
|
16
16
|
Effect.fnUntraced(function* ({ view, fieldId }) {
|
|
17
17
|
const registry = yield* Capability.get(Capabilities.AtomRegistry);
|
|
@@ -6,9 +6,9 @@ import { Operation } from '@dxos/compute';
|
|
|
6
6
|
import { Obj } from '@dxos/echo';
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { KanbanOperation } from '../types';
|
|
10
10
|
|
|
11
|
-
const handler: Operation.WithHandler<typeof DeleteCard> = DeleteCard.pipe(
|
|
11
|
+
const handler: Operation.WithHandler<typeof KanbanOperation.DeleteCard> = KanbanOperation.DeleteCard.pipe(
|
|
12
12
|
Operation.withHandler(({ card }) =>
|
|
13
13
|
Effect.sync(() => {
|
|
14
14
|
const db = Obj.getDatabase(card);
|
package/src/operations/index.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { type EchoSchema } from '@dxos/echo/internal';
|
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
10
|
import { ProjectionModel, createEchoChangeCallback, getTypenameFromQuery } from '@dxos/schema';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { KanbanOperation } from '../types';
|
|
13
13
|
|
|
14
|
-
const handler: Operation.WithHandler<typeof RestoreCardField> = RestoreCardField.pipe(
|
|
14
|
+
const handler: Operation.WithHandler<typeof KanbanOperation.RestoreCardField> = KanbanOperation.RestoreCardField.pipe(
|
|
15
15
|
Operation.withHandler(
|
|
16
16
|
Effect.fnUntraced(function* ({ view, field, props, index }) {
|
|
17
17
|
const registry = yield* Capability.get(Capabilities.AtomRegistry);
|
|
@@ -6,9 +6,9 @@ import { Operation } from '@dxos/compute';
|
|
|
6
6
|
import { Obj } from '@dxos/echo';
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { KanbanOperation } from '../types';
|
|
10
10
|
|
|
11
|
-
const handler: Operation.WithHandler<typeof RestoreCard> = RestoreCard.pipe(
|
|
11
|
+
const handler: Operation.WithHandler<typeof KanbanOperation.RestoreCard> = KanbanOperation.RestoreCard.pipe(
|
|
12
12
|
Operation.withHandler(({ card }) =>
|
|
13
13
|
Effect.sync(() => {
|
|
14
14
|
const db = Obj.getDatabase(card);
|
|
@@ -49,7 +49,7 @@ test.describe('Kanban MutableSchema', () => {
|
|
|
49
49
|
expect(secondLabel).not.toBeNull();
|
|
50
50
|
|
|
51
51
|
// Drag first item below the second item.
|
|
52
|
-
await column.item(0).dragTo(column.item(1).locator, { x: 0, y: 200 });
|
|
52
|
+
await column.item(0).dragTo(column.item(1).locator, { x: 0, y: 200 }, 'bottom');
|
|
53
53
|
|
|
54
54
|
// Item count should stay the same.
|
|
55
55
|
await expect(column.items()).toHaveCount(countBefore);
|
|
@@ -71,8 +71,8 @@ test.describe('Kanban MutableSchema', () => {
|
|
|
71
71
|
const draggedLabel = await col1.item(0).title().textContent();
|
|
72
72
|
expect(draggedLabel).not.toBeNull();
|
|
73
73
|
|
|
74
|
-
// Drop above first item.
|
|
75
|
-
await col1.item(0).dragTo(col2.item(0).locator, { x: 0, y: -30 });
|
|
74
|
+
// Drop above first item.
|
|
75
|
+
await col1.item(0).dragTo(col2.item(0).locator, { x: 0, y: -30 }, 'top');
|
|
76
76
|
|
|
77
77
|
await expect(col1.items()).toHaveCount(col1CountBefore - 1);
|
|
78
78
|
await expect(col2.items()).toHaveCount(col2CountBefore + 1);
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Plugin } from '@dxos/app-framework';
|
|
6
|
+
|
|
7
|
+
import { meta } from './meta';
|
|
8
|
+
|
|
9
|
+
export const KanbanPlugin = Plugin.lazy(meta, () => import('#plugin'));
|
|
10
|
+
|
|
11
|
+
export { KanbanOperationHandlerSet } from './operations';
|
package/src/types/Kanban.ts
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import { Annotation, Obj, Ref, Type } from '@dxos/echo';
|
|
8
|
-
import { View } from '@dxos/echo';
|
|
7
|
+
import { Annotation, Obj, Ref, Type, View } from '@dxos/echo';
|
|
9
8
|
import { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/internal';
|
|
10
9
|
import { ViewAnnotation } from '@dxos/schema';
|
|
11
10
|
|
package/src/types/index.ts
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
import { afterEach, beforeEach, describe, test } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import { Filter, JsonSchema, Obj, Query, Ref, Type, View } from '@dxos/echo';
|
|
8
|
+
import { Filter, JsonSchema, Migration, Obj, Query, Ref, Type, View } from '@dxos/echo';
|
|
10
9
|
import { EchoTestBuilder } from '@dxos/echo-db/testing';
|
|
11
10
|
import { ViewModel } from '@dxos/schema';
|
|
12
11
|
|
|
@@ -35,7 +34,7 @@ describe('Kanban migration v1 → v2', () => {
|
|
|
35
34
|
await builder.close();
|
|
36
35
|
});
|
|
37
36
|
|
|
38
|
-
const migration =
|
|
37
|
+
const migration = Migration.define({
|
|
39
38
|
from: KanbanV1,
|
|
40
39
|
to: Kanban,
|
|
41
40
|
transform: async (from) => ({
|
package/src/types/schema.ts
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
import { beforeEach, describe, test } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
9
|
-
import { type View } from '@dxos/echo';
|
|
8
|
+
import { Filter, JsonSchema, Query, Type, type View } from '@dxos/echo';
|
|
10
9
|
import { ObjectId } from '@dxos/keys';
|
|
11
10
|
import { ViewModel } from '@dxos/schema';
|
|
12
11
|
|