@awesome-markdown/board-ui 0.0.0-stage → 1.6.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 (184) hide show
  1. package/README.md +76 -2
  2. package/dist/board/Board.d.ts +24 -0
  3. package/dist/board/Board.d.ts.map +1 -0
  4. package/dist/board/Board.js +166 -0
  5. package/dist/board/Board.js.map +1 -0
  6. package/dist/board/Cell.d.ts +23 -0
  7. package/dist/board/Cell.d.ts.map +1 -0
  8. package/dist/board/Cell.js +145 -0
  9. package/dist/board/Cell.js.map +1 -0
  10. package/dist/board/ColumnHeader.d.ts +18 -0
  11. package/dist/board/ColumnHeader.d.ts.map +1 -0
  12. package/dist/board/ColumnHeader.js +31 -0
  13. package/dist/board/ColumnHeader.js.map +1 -0
  14. package/dist/board/HomelessItemCard.d.ts +15 -0
  15. package/dist/board/HomelessItemCard.d.ts.map +1 -0
  16. package/dist/board/HomelessItemCard.js +36 -0
  17. package/dist/board/HomelessItemCard.js.map +1 -0
  18. package/dist/board/HomelessPanel.d.ts +17 -0
  19. package/dist/board/HomelessPanel.d.ts.map +1 -0
  20. package/dist/board/HomelessPanel.js +26 -0
  21. package/dist/board/HomelessPanel.js.map +1 -0
  22. package/dist/board/ItemCard.d.ts +21 -0
  23. package/dist/board/ItemCard.d.ts.map +1 -0
  24. package/dist/board/ItemCard.js +104 -0
  25. package/dist/board/ItemCard.js.map +1 -0
  26. package/dist/board/SwimlaneRow.d.ts +23 -0
  27. package/dist/board/SwimlaneRow.d.ts.map +1 -0
  28. package/dist/board/SwimlaneRow.js +30 -0
  29. package/dist/board/SwimlaneRow.js.map +1 -0
  30. package/dist/board/dnd/boardDnd.d.ts +15 -0
  31. package/dist/board/dnd/boardDnd.d.ts.map +1 -0
  32. package/dist/board/dnd/boardDnd.js +69 -0
  33. package/dist/board/dnd/boardDnd.js.map +1 -0
  34. package/dist/board/dnd/dragTypes.d.ts +24 -0
  35. package/dist/board/dnd/dragTypes.d.ts.map +1 -0
  36. package/dist/board/dnd/dragTypes.js +22 -0
  37. package/dist/board/dnd/dragTypes.js.map +1 -0
  38. package/dist/board/dnd/mutateDragDrop.d.ts +37 -0
  39. package/dist/board/dnd/mutateDragDrop.d.ts.map +1 -0
  40. package/dist/board/dnd/mutateDragDrop.js +116 -0
  41. package/dist/board/dnd/mutateDragDrop.js.map +1 -0
  42. package/dist/board/dnd/onDragEnd.d.ts +24 -0
  43. package/dist/board/dnd/onDragEnd.d.ts.map +1 -0
  44. package/dist/board/dnd/onDragEnd.js +47 -0
  45. package/dist/board/dnd/onDragEnd.js.map +1 -0
  46. package/dist/board/layout/AxisBehavior.d.ts +35 -0
  47. package/dist/board/layout/AxisBehavior.d.ts.map +1 -0
  48. package/dist/board/layout/AxisBehavior.js +82 -0
  49. package/dist/board/layout/AxisBehavior.js.map +1 -0
  50. package/dist/board/layout/AxisDrawer.d.ts +17 -0
  51. package/dist/board/layout/AxisDrawer.d.ts.map +1 -0
  52. package/dist/board/layout/AxisDrawer.js +40 -0
  53. package/dist/board/layout/AxisDrawer.js.map +1 -0
  54. package/dist/board/layout/BoardDrawer.d.ts +11 -0
  55. package/dist/board/layout/BoardDrawer.d.ts.map +1 -0
  56. package/dist/board/layout/BoardDrawer.js +27 -0
  57. package/dist/board/layout/BoardDrawer.js.map +1 -0
  58. package/dist/board/layout/Drawer.d.ts +19 -0
  59. package/dist/board/layout/Drawer.d.ts.map +1 -0
  60. package/dist/board/layout/Drawer.js +18 -0
  61. package/dist/board/layout/Drawer.js.map +1 -0
  62. package/dist/board/layout/FilterEditor.d.ts +12 -0
  63. package/dist/board/layout/FilterEditor.d.ts.map +1 -0
  64. package/dist/board/layout/FilterEditor.js +11 -0
  65. package/dist/board/layout/FilterEditor.js.map +1 -0
  66. package/dist/board/layout/InlineControls.d.ts +22 -0
  67. package/dist/board/layout/InlineControls.d.ts.map +1 -0
  68. package/dist/board/layout/InlineControls.js +39 -0
  69. package/dist/board/layout/InlineControls.js.map +1 -0
  70. package/dist/board/layout/SortableAxis.d.ts +28 -0
  71. package/dist/board/layout/SortableAxis.d.ts.map +1 -0
  72. package/dist/board/layout/SortableAxis.js +39 -0
  73. package/dist/board/layout/SortableAxis.js.map +1 -0
  74. package/dist/board/layout/axis-defaults.d.ts +22 -0
  75. package/dist/board/layout/axis-defaults.d.ts.map +1 -0
  76. package/dist/board/layout/axis-defaults.js +37 -0
  77. package/dist/board/layout/axis-defaults.js.map +1 -0
  78. package/dist/board/layout/filter-draft.d.ts +21 -0
  79. package/dist/board/layout/filter-draft.d.ts.map +1 -0
  80. package/dist/board/layout/filter-draft.js +110 -0
  81. package/dist/board/layout/filter-draft.js.map +1 -0
  82. package/dist/board/layout/useBoardLayout.d.ts +27 -0
  83. package/dist/board/layout/useBoardLayout.d.ts.map +1 -0
  84. package/dist/board/layout/useBoardLayout.js +92 -0
  85. package/dist/board/layout/useBoardLayout.js.map +1 -0
  86. package/dist/breadcrumb.d.ts +22 -0
  87. package/dist/breadcrumb.d.ts.map +1 -0
  88. package/dist/breadcrumb.js +15 -0
  89. package/dist/breadcrumb.js.map +1 -0
  90. package/dist/components/BoardAssigneeField.d.ts +10 -0
  91. package/dist/components/BoardAssigneeField.d.ts.map +1 -0
  92. package/dist/components/BoardAssigneeField.js +37 -0
  93. package/dist/components/BoardAssigneeField.js.map +1 -0
  94. package/dist/components/ConflictBanner.d.ts +12 -0
  95. package/dist/components/ConflictBanner.d.ts.map +1 -0
  96. package/dist/components/ConflictBanner.js +47 -0
  97. package/dist/components/ConflictBanner.js.map +1 -0
  98. package/dist/components/ConflictDiff.d.ts +13 -0
  99. package/dist/components/ConflictDiff.d.ts.map +1 -0
  100. package/dist/components/ConflictDiff.js +97 -0
  101. package/dist/components/ConflictDiff.js.map +1 -0
  102. package/dist/components/ConflictPanel.d.ts +16 -0
  103. package/dist/components/ConflictPanel.d.ts.map +1 -0
  104. package/dist/components/ConflictPanel.js +53 -0
  105. package/dist/components/ConflictPanel.js.map +1 -0
  106. package/dist/components/DeleteItemConfirmDialog.d.ts +14 -0
  107. package/dist/components/DeleteItemConfirmDialog.d.ts.map +1 -0
  108. package/dist/components/DeleteItemConfirmDialog.js +46 -0
  109. package/dist/components/DeleteItemConfirmDialog.js.map +1 -0
  110. package/dist/components/ItemEditorActions.d.ts +15 -0
  111. package/dist/components/ItemEditorActions.d.ts.map +1 -0
  112. package/dist/components/ItemEditorActions.js +48 -0
  113. package/dist/components/ItemEditorActions.js.map +1 -0
  114. package/dist/index.d.ts +32 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.js +37 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/lib/derive-summary.d.ts +9 -0
  119. package/dist/lib/derive-summary.d.ts.map +1 -0
  120. package/dist/lib/derive-summary.js +27 -0
  121. package/dist/lib/derive-summary.js.map +1 -0
  122. package/dist/lib/item-board.d.ts +5 -0
  123. package/dist/lib/item-board.d.ts.map +1 -0
  124. package/dist/lib/item-board.js +14 -0
  125. package/dist/lib/item-board.js.map +1 -0
  126. package/dist/lib/property-display.d.ts +18 -0
  127. package/dist/lib/property-display.d.ts.map +1 -0
  128. package/dist/lib/property-display.js +81 -0
  129. package/dist/lib/property-display.js.map +1 -0
  130. package/dist/pages/BoardListPage.d.ts +9 -0
  131. package/dist/pages/BoardListPage.d.ts.map +1 -0
  132. package/dist/pages/BoardListPage.js +113 -0
  133. package/dist/pages/BoardListPage.js.map +1 -0
  134. package/dist/pages/BoardPage.d.ts +7 -0
  135. package/dist/pages/BoardPage.d.ts.map +1 -0
  136. package/dist/pages/BoardPage.js +37 -0
  137. package/dist/pages/BoardPage.js.map +1 -0
  138. package/dist/pages/ItemEditorPage.d.ts +3 -0
  139. package/dist/pages/ItemEditorPage.d.ts.map +1 -0
  140. package/dist/pages/ItemEditorPage.js +255 -0
  141. package/dist/pages/ItemEditorPage.js.map +1 -0
  142. package/dist/provider/ProviderContext.d.ts +17 -0
  143. package/dist/provider/ProviderContext.d.ts.map +1 -0
  144. package/dist/provider/ProviderContext.js +21 -0
  145. package/dist/provider/ProviderContext.js.map +1 -0
  146. package/dist/router/RouterAdapter.d.ts +43 -0
  147. package/dist/router/RouterAdapter.d.ts.map +1 -0
  148. package/dist/router/RouterAdapter.js +21 -0
  149. package/dist/router/RouterAdapter.js.map +1 -0
  150. package/dist/shell/SyncStatusDot.d.ts +8 -0
  151. package/dist/shell/SyncStatusDot.d.ts.map +1 -0
  152. package/dist/shell/SyncStatusDot.js +58 -0
  153. package/dist/shell/SyncStatusDot.js.map +1 -0
  154. package/dist/shell/ThemeToggle.d.ts +8 -0
  155. package/dist/shell/ThemeToggle.d.ts.map +1 -0
  156. package/dist/shell/ThemeToggle.js +21 -0
  157. package/dist/shell/ThemeToggle.js.map +1 -0
  158. package/dist/state/theme-store.d.ts +17 -0
  159. package/dist/state/theme-store.d.ts.map +1 -0
  160. package/dist/state/theme-store.js +58 -0
  161. package/dist/state/theme-store.js.map +1 -0
  162. package/dist/state/useBoardRender.d.ts +16 -0
  163. package/dist/state/useBoardRender.d.ts.map +1 -0
  164. package/dist/state/useBoardRender.js +53 -0
  165. package/dist/state/useBoardRender.js.map +1 -0
  166. package/dist/state/useProviderSubscribe.d.ts +22 -0
  167. package/dist/state/useProviderSubscribe.d.ts.map +1 -0
  168. package/dist/state/useProviderSubscribe.js +48 -0
  169. package/dist/state/useProviderSubscribe.js.map +1 -0
  170. package/dist/sync/conflict-api.d.ts +16 -0
  171. package/dist/sync/conflict-api.d.ts.map +1 -0
  172. package/dist/sync/conflict-api.js +35 -0
  173. package/dist/sync/conflict-api.js.map +1 -0
  174. package/dist/sync/conflict-store.d.ts +44 -0
  175. package/dist/sync/conflict-store.d.ts.map +1 -0
  176. package/dist/sync/conflict-store.js +159 -0
  177. package/dist/sync/conflict-store.js.map +1 -0
  178. package/fonts/InterTight-Medium.woff2 +0 -0
  179. package/fonts/InterTight-Regular.woff2 +0 -0
  180. package/fonts/JetBrainsMono-Medium.woff2 +0 -0
  181. package/fonts/JetBrainsMono-Regular.woff2 +0 -0
  182. package/fonts/LICENSE +14 -0
  183. package/package.json +58 -3
  184. package/styles.css +232 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HomelessPanel.d.ts","sourceRoot":"","sources":["../../src/board/HomelessPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAGlE,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAkDpG"}
@@ -0,0 +1,26 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState } from 'react';
3
+ import { HomelessItemCard } from './HomelessItemCard.js';
4
+ /**
5
+ * Collapsible panel listing items that belong to this board but no longer
6
+ * match any column filter. Populated from GET /boards/:slug/homeless.
7
+ */
8
+ export function HomelessPanel({ homeless, items: itemsProp }) {
9
+ const [open, setOpen] = useState(true);
10
+ const items = itemsProp ?? homeless.items;
11
+ if (items.length === 0)
12
+ return _jsx(_Fragment, {});
13
+ return (_jsxs("div", { style: { borderTop: '1px solid var(--border)' }, "data-testid": "homeless-panel", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-2", style: {
14
+ fontFamily: 'var(--font-mono)',
15
+ fontSize: '11px',
16
+ fontWeight: 500,
17
+ color: 'var(--ink-muted)',
18
+ textTransform: 'uppercase',
19
+ letterSpacing: '0.06em',
20
+ background: 'var(--bg)',
21
+ border: 'none',
22
+ cursor: 'pointer',
23
+ borderBottom: open ? '1px solid var(--border)' : 'none',
24
+ }, "data-testid": "homeless-panel-toggle", "aria-expanded": open, children: [_jsxs("span", { children: ["\u26A0 ", items.length, " homeless item", items.length !== 1 ? 's' : '', " \u2014 \"", homeless.board.title, "\""] }), _jsx("span", { "aria-hidden": "true", children: open ? '▲' : '▼' })] }), open && (_jsx("ul", { className: "px-4 pb-3 flex flex-wrap gap-2", style: { paddingTop: '8px' }, "data-testid": "homeless-item-list", children: items.map((item) => (_jsx(HomelessItemCard, { item: item }, item.slug))) }))] }));
25
+ }
26
+ //# sourceMappingURL=HomelessPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HomelessPanel.js","sourceRoot":"","sources":["../../src/board/HomelessPanel.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAWzD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAsB;IAC9E,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC;IAE1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,mBAAK,CAAC;IAErC,OAAO,CACL,eACE,KAAK,EAAE,EAAE,SAAS,EAAE,yBAAyB,EAAE,iBACnC,gBAAgB,aAE5B,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EACjC,SAAS,EAAC,oDAAoD,EAC9D,KAAK,EAAE;oBACL,UAAU,EAAE,kBAAkB;oBAC9B,QAAQ,EAAE,MAAM;oBAChB,UAAU,EAAE,GAAG;oBACf,KAAK,EAAE,kBAAkB;oBACzB,aAAa,EAAE,WAAW;oBAC1B,aAAa,EAAE,QAAQ;oBACvB,UAAU,EAAE,WAAW;oBACvB,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,SAAS;oBACjB,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,MAAM;iBACxD,iBACW,uBAAuB,mBACpB,IAAI,aAEnB,sCACK,KAAK,CAAC,MAAM,oBAAgB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,gBAC3D,QAAQ,CAAC,KAAK,CAAC,KAAK,UAChB,EACP,8BAAkB,MAAM,YAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAQ,IAC3C,EAER,IAAI,IAAI,CACP,aACE,SAAS,EAAC,gCAAgC,EAC1C,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,iBAChB,oBAAoB,YAE/B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,KAAC,gBAAgB,IAAiB,IAAI,EAAE,IAAI,IAArB,IAAI,CAAC,IAAI,CAAgB,CACjD,CAAC,GACC,CACN,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import type { Board, Item } from '@awesome-markdown/contracts';
3
+ interface ItemCardProps {
4
+ item: Item;
5
+ columnSlug: string;
6
+ swimlaneSlug: string;
7
+ boardSlug: string;
8
+ board: Board;
9
+ }
10
+ /**
11
+ * A draggable item card with three-layer layout:
12
+ * 1. Title (Inter Tight 14px/500)
13
+ * 2. Summary (first prose line from body, 12.5px/400, muted)
14
+ * 3. Tags row (mono uppercase, dot-separated, muted)
15
+ *
16
+ * Clicking the card navigates to /items/:slug (full-page editor).
17
+ * When conflicted: drag disabled, dashed ink-muted border, 🔒 indicator.
18
+ */
19
+ export declare function ItemCard({ item, columnSlug, swimlaneSlug, boardSlug, board, }: ItemCardProps): React.ReactElement;
20
+ export {};
21
+ //# sourceMappingURL=ItemCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ItemCard.d.ts","sourceRoot":"","sources":["../../src/board/ItemCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAQ/D,UAAU,aAAa;IACrB,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,SAAS,EACT,KAAK,GACN,EAAE,aAAa,GAAG,KAAK,CAAC,YAAY,CA2KpC"}
@@ -0,0 +1,104 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState } from 'react';
3
+ import { useSortable } from '@dnd-kit/sortable';
4
+ import { CSS } from '@dnd-kit/utilities';
5
+ import { useOptionalConflict } from '../sync/conflict-store.js';
6
+ import { deriveSummary } from '../lib/derive-summary.js';
7
+ import { buildItemEditorHref, getBoardScopedString } from '../lib/item-board.js';
8
+ import { PropertyValueDisplay } from '../lib/property-display.js';
9
+ import { useRouterAdapter } from '../router/RouterAdapter.js';
10
+ /**
11
+ * A draggable item card with three-layer layout:
12
+ * 1. Title (Inter Tight 14px/500)
13
+ * 2. Summary (first prose line from body, 12.5px/400, muted)
14
+ * 3. Tags row (mono uppercase, dot-separated, muted)
15
+ *
16
+ * Clicking the card navigates to /items/:slug (full-page editor).
17
+ * When conflicted: drag disabled, dashed ink-muted border, 🔒 indicator.
18
+ */
19
+ export function ItemCard({ item, columnSlug, swimlaneSlug, boardSlug, board, }) {
20
+ const { navigate } = useRouterAdapter();
21
+ const conflict = useOptionalConflict();
22
+ const isConflicted = conflict?.isItemAffected(item.slug) ?? false;
23
+ const dragData = {
24
+ type: 'item',
25
+ itemSlug: item.slug,
26
+ columnSlug,
27
+ swimlaneSlug,
28
+ };
29
+ const [isHovered, setIsHovered] = useState(false);
30
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({
31
+ id: item.slug,
32
+ data: dragData,
33
+ disabled: isConflicted,
34
+ });
35
+ const borderStyle = isConflicted
36
+ ? '1px dashed var(--ink-muted)'
37
+ : isHovered && !isDragging
38
+ ? '1px solid var(--accent)'
39
+ : '1px solid var(--border)';
40
+ const style = {
41
+ transform: CSS.Transform.toString(transform),
42
+ transition: transition ?? undefined,
43
+ opacity: isDragging ? 0.4 : 1,
44
+ padding: '10px 12px',
45
+ border: borderStyle,
46
+ borderRadius: 0,
47
+ boxShadow: 'none',
48
+ background: 'transparent',
49
+ cursor: isConflicted ? 'not-allowed' : isDragging ? 'grabbing' : 'grab',
50
+ userSelect: 'none',
51
+ };
52
+ const itemAsMap = item;
53
+ const tags = Array.isArray(itemAsMap['tags']) ? itemAsMap['tags'] : [];
54
+ const summary = item.body !== undefined && item.body.trim() !== ''
55
+ ? deriveSummary(item.body)
56
+ : '';
57
+ const assignee = getBoardScopedString(item, boardSlug, 'assignee').trim();
58
+ const showsAssigneeInLayout = board.cardLayout?.some((layout) => layout.property === 'assignee') ?? false;
59
+ const handleClick = (e) => {
60
+ // Don't navigate if the user is dragging
61
+ if (isDragging)
62
+ return;
63
+ e.stopPropagation();
64
+ navigate(buildItemEditorHref(item.slug, boardSlug));
65
+ };
66
+ return (_jsxs("div", { ref: setNodeRef, style: style, onClick: isConflicted ? undefined : handleClick, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), "data-testid": `item-card-${item.slug}`, "data-item-slug": item.slug, "data-conflict": isConflicted ? 'true' : undefined, ...attributes, ...(isConflicted ? {} : listeners), children: [_jsxs("div", { className: "flex items-start justify-between gap-1", children: [_jsx("span", { style: {
67
+ fontFamily: 'var(--font-sans)',
68
+ fontSize: '14px',
69
+ fontWeight: 500,
70
+ color: 'var(--ink)',
71
+ lineHeight: 1.3,
72
+ flex: 1,
73
+ minWidth: 0,
74
+ overflow: 'hidden',
75
+ textOverflow: 'ellipsis',
76
+ whiteSpace: 'nowrap',
77
+ }, "data-testid": `item-title-${item.slug}`, children: item.title }), isConflicted && (_jsx("span", { style: { flexShrink: 0, fontSize: '12px' }, title: "This item is locked while a merge conflict is being resolved", "aria-label": "Conflict lock", "data-testid": `conflict-lock-${item.slug}`, children: "\uD83D\uDD12" }))] }), summary !== '' && (_jsx("p", { style: {
78
+ fontFamily: 'var(--font-sans)',
79
+ fontSize: '12.5px',
80
+ fontWeight: 400,
81
+ color: 'var(--ink-muted)',
82
+ lineHeight: 1.4,
83
+ marginTop: '4px',
84
+ overflow: 'hidden',
85
+ display: '-webkit-box',
86
+ WebkitLineClamp: 2,
87
+ WebkitBoxOrient: 'vertical',
88
+ }, children: summary })), tags.length > 0 && (_jsx("p", { style: {
89
+ fontFamily: 'var(--font-mono)',
90
+ fontSize: '10.5px',
91
+ fontWeight: 400,
92
+ color: 'var(--ink-muted)',
93
+ textTransform: 'uppercase',
94
+ letterSpacing: '0.06em',
95
+ marginTop: '6px',
96
+ }, children: tags.join(' · ') })), assignee !== '' && !showsAssigneeInLayout && (_jsxs("div", { style: {
97
+ fontFamily: 'var(--font-mono)',
98
+ fontSize: '10.5px',
99
+ fontWeight: 400,
100
+ color: 'var(--ink-muted)',
101
+ marginTop: '6px',
102
+ }, "data-testid": `item-assignee-${item.slug}`, children: ["assigned \u2192 ", assignee] })), board.cardLayout && board.cardLayout.length > 0 && (_jsx("div", { className: "flex items-center flex-wrap gap-1", style: { marginTop: '6px' }, children: board.cardLayout.map((layout) => (_jsx(PropertyValueDisplay, { item: item, boardSlug: boardSlug, layout: layout }, layout.property))) }))] }));
103
+ }
104
+ //# sourceMappingURL=ItemCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ItemCard.js","sourceRoot":"","sources":["../../src/board/ItemCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import type { Axis, Cell as CellData, Board } from '@awesome-markdown/contracts';
3
+ interface SwimlaneRowProps {
4
+ swimlane: Axis;
5
+ columns: Axis[];
6
+ cells: CellData[];
7
+ board: Board;
8
+ /** False for the implicit swimlane of a board that declares none. */
9
+ editable: boolean;
10
+ selected: boolean;
11
+ onEdit: () => void;
12
+ onRename: (title: string) => void;
13
+ onError: (msg: string) => void;
14
+ onCreated: () => void;
15
+ }
16
+ /**
17
+ * A horizontal row representing one swimlane axis.
18
+ * Renders a label cell followed by one Cell per column. The label is the
19
+ * drag handle for reordering rows.
20
+ */
21
+ export declare function SwimlaneRow({ swimlane, columns, cells, board, editable, selected, onEdit, onRename, onError, onCreated, }: SwimlaneRowProps): React.ReactElement;
22
+ export {};
23
+ //# sourceMappingURL=SwimlaneRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwimlaneRow.d.ts","sourceRoot":"","sources":["../../src/board/SwimlaneRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,QAAQ,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAKjF,UAAU,gBAAgB;IACxB,QAAQ,EAAE,IAAI,CAAC;IACf,OAAO,EAAE,IAAI,EAAE,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAO,EACP,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,SAAS,GACV,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAqEvC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { Cell } from './Cell.js';
4
+ import { SortableAxis } from './layout/SortableAxis.js';
5
+ import { filterSummary } from './layout/filter-draft.js';
6
+ /**
7
+ * A horizontal row representing one swimlane axis.
8
+ * Renders a label cell followed by one Cell per column. The label is the
9
+ * drag handle for reordering rows.
10
+ */
11
+ export function SwimlaneRow({ swimlane, columns, cells, board, editable, selected, onEdit, onRename, onError, onCreated, }) {
12
+ return (_jsx(SortableAxis, { dim: "swimlanes", axis: swimlane, editable: editable, selected: selected, label: editable ? swimlane.title : '', subtitle: editable ? filterSummary(swimlane.filter) : undefined, onEdit: onEdit, onRename: onRename, children: ({ setNodeRef, style, handleProps, handleClassName, title }) => (_jsxs("div", { ref: setNodeRef, className: "flex", style: { ...style, background: 'var(--bg)' }, "data-testid": `swimlane-row-${swimlane.slug}`, "data-swimlane-slug": swimlane.slug, children: [_jsx("div", { ...handleProps, className: `w-28 flex-shrink-0 px-2 py-2 ${handleClassName}`, style: {
13
+ borderRight: '1px solid var(--border)',
14
+ borderBottom: '1px solid var(--border)',
15
+ boxShadow: selected ? 'inset 3px 0 0 var(--accent)' : undefined,
16
+ }, "data-testid": `swimlane-label-${swimlane.slug}`, "data-synthetic": swimlane.synthetic ? 'true' : undefined, children: _jsx("span", { className: "block", style: {
17
+ fontFamily: 'var(--font-mono)',
18
+ fontSize: '10.5px',
19
+ fontWeight: 500,
20
+ color: 'var(--ink-muted)',
21
+ textTransform: 'uppercase',
22
+ letterSpacing: '0.06em',
23
+ }, children: title }) }), columns.map((column) => {
24
+ const cell = cells.find((c) => c.columnSlug === column.slug && c.swimlaneSlug === swimlane.slug);
25
+ if (!cell)
26
+ return null;
27
+ return (_jsx(Cell, { cell: cell, columnAxis: column, swimlaneAxis: swimlane, board: board, onError: onError, onCreated: onCreated }, `${column.slug}-${swimlane.slug}`));
28
+ })] })) }));
29
+ }
30
+ //# sourceMappingURL=SwimlaneRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwimlaneRow.js","sourceRoot":"","sources":["../../src/board/SwimlaneRow.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAgBzD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAO,EACP,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,SAAS,GACQ;IACjB,OAAO,CACL,KAAC,YAAY,IACX,GAAG,EAAC,WAAW,EACf,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EACrC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,EAC/D,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,YAEjB,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAC/D,eACE,GAAG,EAAE,UAAU,EACf,SAAS,EAAC,MAAM,EAChB,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,iBAC/B,gBAAgB,QAAQ,CAAC,IAAI,EAAE,wBACxB,QAAQ,CAAC,IAAI,aAGjC,iBACM,WAAW,EACf,SAAS,EAAE,gCAAgC,eAAe,EAAE,EAC5D,KAAK,EAAE;wBACL,WAAW,EAAE,yBAAyB;wBACtC,YAAY,EAAE,yBAAyB;wBACvC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,SAAS;qBAChE,iBACY,kBAAkB,QAAQ,CAAC,IAAI,EAAE,oBAC9B,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,YAEvD,eACE,SAAS,EAAC,OAAO,EACjB,KAAK,EAAE;4BACL,UAAU,EAAE,kBAAkB;4BAC9B,QAAQ,EAAE,QAAQ;4BAClB,UAAU,EAAE,GAAG;4BACf,KAAK,EAAE,kBAAkB;4BACzB,aAAa,EAAE,WAAW;4BAC1B,aAAa,EAAE,QAAQ;yBACxB,YAEA,KAAK,GACD,GACH,EAGL,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;oBACtB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,CACxE,CAAC;oBACF,IAAI,CAAC,IAAI;wBAAE,OAAO,IAAI,CAAC;oBACvB,OAAO,CACL,KAAC,IAAI,IAEH,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,QAAQ,EACtB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,IANf,GAAG,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,CAOtC,CACH,CAAC;gBACJ,CAAC,CAAC,IACE,CACP,GACY,CAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { CollisionDetection, DragEndEvent } from '@dnd-kit/core';
2
+ import type { BoardRender, Cell, Homeless, Mutation } from '@awesome-markdown/contracts';
3
+ /**
4
+ * Items only collide with cells/items; axis headers only with headers of the
5
+ * same dimension — so reordering columns never targets a cell and vice versa.
6
+ */
7
+ export declare const layoutAwareCollision: CollisionDetection;
8
+ export interface HomelessDropPlan {
9
+ itemSlug: string;
10
+ mutations: Mutation[];
11
+ newCells: Cell[];
12
+ }
13
+ /** Resolve a homeless-item drop into its PATCH mutations and optimistic cells. */
14
+ export declare function planHomelessDrop(event: DragEndEvent, cells: Cell[], render: BoardRender, homeless: Homeless): HomelessDropPlan | null;
15
+ //# sourceMappingURL=boardDnd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boardDnd.d.ts","sourceRoot":"","sources":["../../../src/board/dnd/boardDnd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAQ,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAM/F;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,kBAQlC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,QAAQ,EAAE,IAAI,EAAE,CAAC;CAClB;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,QAAQ,GACjB,gBAAgB,GAAG,IAAI,CAuDzB"}
@@ -0,0 +1,69 @@
1
+ import { closestCenter } from '@dnd-kit/core';
2
+ import { deriveMutations } from '@awesome-markdown/filter-engine';
3
+ import { buildCellFilter } from './mutateDragDrop.js';
4
+ import { decodeCellId } from './dragTypes.js';
5
+ /**
6
+ * Items only collide with cells/items; axis headers only with headers of the
7
+ * same dimension — so reordering columns never targets a cell and vice versa.
8
+ */
9
+ export const layoutAwareCollision = (args) => {
10
+ const active = args.active.data.current;
11
+ const droppableContainers = args.droppableContainers.filter((c) => {
12
+ const data = c.data.current;
13
+ if (active?.type === 'axis')
14
+ return data?.type === 'axis' && data.dim === active.dim;
15
+ return data?.type !== 'axis';
16
+ });
17
+ return closestCenter({ ...args, droppableContainers });
18
+ };
19
+ /** Resolve a homeless-item drop into its PATCH mutations and optimistic cells. */
20
+ export function planHomelessDrop(event, cells, render, homeless) {
21
+ if (!event.over)
22
+ return null;
23
+ const { itemSlug } = event.active.data.current;
24
+ const overId = String(event.over.id);
25
+ let dstColumnSlug;
26
+ let dstSwimlaneSlug;
27
+ let insertBeforeSlug;
28
+ const cellDecoded = decodeCellId(overId);
29
+ if (cellDecoded) {
30
+ dstColumnSlug = cellDecoded.columnSlug;
31
+ dstSwimlaneSlug = cellDecoded.swimlaneSlug;
32
+ insertBeforeSlug = null;
33
+ }
34
+ else {
35
+ const overCell = cells.find((c) => c.items.some((i) => i.slug === overId));
36
+ if (!overCell)
37
+ return null;
38
+ dstColumnSlug = overCell.columnSlug;
39
+ dstSwimlaneSlug = overCell.swimlaneSlug;
40
+ insertBeforeSlug = overId;
41
+ }
42
+ const dstCell = cells.find((c) => c.columnSlug === dstColumnSlug && c.swimlaneSlug === dstSwimlaneSlug);
43
+ if (!dstCell || dstCell.readOnly)
44
+ return null;
45
+ const colAxis = render.axes.columns.find((a) => a.slug === dstColumnSlug);
46
+ const slAxis = render.axes.swimlanes.find((a) => a.slug === dstSwimlaneSlug);
47
+ if (!colAxis || !slAxis)
48
+ return null;
49
+ const filter = buildCellFilter(render.board, colAxis, slAxis);
50
+ const mutations = deriveMutations(filter, { board: render.board.slug }, colAxis.writeOnDrop ?? slAxis.writeOnDrop);
51
+ if (!Array.isArray(mutations))
52
+ return null;
53
+ const movingItem = homeless.items.find((i) => i.slug === itemSlug);
54
+ if (!movingItem)
55
+ return null;
56
+ const newCells = cells.map((cell) => {
57
+ if (cell.columnSlug !== dstColumnSlug || cell.swimlaneSlug !== dstSwimlaneSlug)
58
+ return cell;
59
+ const withoutItem = cell.items.filter((i) => i.slug !== itemSlug);
60
+ const idx = insertBeforeSlug === null ? -1 : withoutItem.findIndex((i) => i.slug === insertBeforeSlug);
61
+ const insertAt = idx >= 0 ? idx : withoutItem.length;
62
+ return {
63
+ ...cell,
64
+ items: [...withoutItem.slice(0, insertAt), movingItem, ...withoutItem.slice(insertAt)],
65
+ };
66
+ });
67
+ return { itemSlug, mutations, newCells };
68
+ }
69
+ //# sourceMappingURL=boardDnd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boardDnd.js","sourceRoot":"","sources":["../../../src/board/dnd/boardDnd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface ItemDragData {
2
+ type: 'item';
3
+ itemSlug: string;
4
+ columnSlug: string;
5
+ swimlaneSlug: string;
6
+ }
7
+ /** Drag payload for items dragged from the HomelessPanel. */
8
+ export interface HomelessItemDragData {
9
+ type: 'homeless-item';
10
+ itemSlug: string;
11
+ }
12
+ /** Discriminated union of all drag data shapes in this app. */
13
+ export type DragData = ItemDragData | HomelessItemDragData;
14
+ /**
15
+ * Cell drop-target IDs are encoded as `${columnSlug}::${swimlaneSlug}`.
16
+ * This format must not appear in item slugs.
17
+ */
18
+ export declare const CELL_ID_SEPARATOR = "::";
19
+ export declare function encodeCellId(columnSlug: string, swimlaneSlug: string): string;
20
+ export declare function decodeCellId(cellId: string): {
21
+ columnSlug: string;
22
+ swimlaneSlug: string;
23
+ } | null;
24
+ //# sourceMappingURL=dragTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dragTypes.d.ts","sourceRoot":"","sources":["../../../src/board/dnd/dragTypes.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,6DAA6D;AAC7D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,+DAA+D;AAC/D,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,oBAAoB,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GACb;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAOrD"}
@@ -0,0 +1,22 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Drag payload attached to each draggable ItemCard via useSortable data
3
+ // ---------------------------------------------------------------------------
4
+ /**
5
+ * Cell drop-target IDs are encoded as `${columnSlug}::${swimlaneSlug}`.
6
+ * This format must not appear in item slugs.
7
+ */
8
+ export const CELL_ID_SEPARATOR = '::';
9
+ export function encodeCellId(columnSlug, swimlaneSlug) {
10
+ return `${columnSlug}${CELL_ID_SEPARATOR}${swimlaneSlug}`;
11
+ }
12
+ export function decodeCellId(cellId) {
13
+ const idx = cellId.indexOf(CELL_ID_SEPARATOR);
14
+ if (idx === -1)
15
+ return null;
16
+ const columnSlug = cellId.slice(0, idx);
17
+ const swimlaneSlug = cellId.slice(idx + CELL_ID_SEPARATOR.length);
18
+ if (!columnSlug || !swimlaneSlug)
19
+ return null;
20
+ return { columnSlug, swimlaneSlug };
21
+ }
22
+ //# sourceMappingURL=dragTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dragTypes.js","sourceRoot":"","sources":["../../../src/board/dnd/dragTypes.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,8EAA8E;AAkB9E;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,YAAoB;IACnE,OAAO,GAAG,UAAU,GAAG,iBAAiB,GAAG,YAAY,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAc;IAEd,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9C,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAClE,IAAI,CAAC,UAAU,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { Board, Axis, Cell, FilterRule, Mutation, Item } from '@awesome-markdown/contracts';
2
+ /**
3
+ * Build the combined cell filter (board ∧ column ∧ swimlane).
4
+ * Returns undefined when all three are absent (match-all).
5
+ */
6
+ export declare function buildCellFilter(board: Board, col: Axis, sl: Axis): FilterRule | undefined;
7
+ /** Read the per-board `order` string for an item, if present. */
8
+ export declare function getItemBoardOrder(item: Item, boardSlug: string): string | undefined;
9
+ /**
10
+ * Apply a drag-drop move to a local copy of the cells array.
11
+ * Handles both cross-cell moves and same-cell reorders.
12
+ */
13
+ export declare function applyOptimisticMove(cells: Cell[], item: Item, srcColumnSlug: string, srcSwimlaneSlug: string, dstColumnSlug: string, dstSwimlaneSlug: string, insertBeforeSlug: string | null): Cell[];
14
+ export interface DropMutations {
15
+ mutations: Mutation[];
16
+ type: 'move' | 'reorder';
17
+ }
18
+ /**
19
+ * Compute the mutation list for a drag-drop action.
20
+ *
21
+ * Returns null when the destination cell is read-only or when
22
+ * deriveMutations returns `{ readonly: true }` as a belt-and-suspenders check.
23
+ *
24
+ * One drop = exactly one PATCH. The returned mutation list includes:
25
+ * 1. Cell-placement mutations derived from the destination cell's filter.
26
+ * 2. One `set boards.<boardSlug>.order = <fractional-key>` mutation for ordering.
27
+ */
28
+ export declare function computeDropMutations(params: {
29
+ itemSlug: string;
30
+ srcCell: Cell;
31
+ dstCell: Cell;
32
+ colAxis: Axis;
33
+ slAxis: Axis;
34
+ board: Board;
35
+ insertBeforeSlug: string | null;
36
+ }): DropMutations | null;
37
+ //# sourceMappingURL=mutateDragDrop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutateDragDrop.d.ts","sourceRoot":"","sources":["../../../src/board/dnd/mutateDragDrop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,QAAQ,EAER,IAAI,EACL,MAAM,6BAA6B,CAAC;AAOrC;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,IAAI,EACT,EAAE,EAAE,IAAI,GACP,UAAU,GAAG,SAAS,CAOxB;AAkBD,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQnF;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAC9B,IAAI,EAAE,CA+BR;AAMD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,GAAG,aAAa,GAAG,IAAI,CAyCvB"}
@@ -0,0 +1,116 @@
1
+ import { deriveMutations, keyBetween } from '@awesome-markdown/filter-engine';
2
+ // ---------------------------------------------------------------------------
3
+ // Filter composition
4
+ // ---------------------------------------------------------------------------
5
+ /**
6
+ * Build the combined cell filter (board ∧ column ∧ swimlane).
7
+ * Returns undefined when all three are absent (match-all).
8
+ */
9
+ export function buildCellFilter(board, col, sl) {
10
+ const rules = [board.filter, col.filter, sl.filter].filter((f) => f !== undefined);
11
+ if (rules.length === 0)
12
+ return undefined;
13
+ if (rules.length === 1)
14
+ return rules[0];
15
+ return { all: rules };
16
+ }
17
+ // ---------------------------------------------------------------------------
18
+ // writeOnDrop resolution
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Column writeOnDrop takes precedence over swimlane writeOnDrop.
22
+ */
23
+ function getWriteOnDropOverride(col, sl) {
24
+ if (col.writeOnDrop !== undefined)
25
+ return col.writeOnDrop;
26
+ return sl.writeOnDrop;
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Per-board order key helper
30
+ // ---------------------------------------------------------------------------
31
+ /** Read the per-board `order` string for an item, if present. */
32
+ export function getItemBoardOrder(item, boardSlug) {
33
+ const boards = item.boards;
34
+ if (!Array.isArray(boards))
35
+ return undefined;
36
+ const entry = boards.find((e) => e['board'] === boardSlug);
37
+ const o = entry?.['order'];
38
+ return typeof o === 'string' ? o : undefined;
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Optimistic cell reordering helper
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * Apply a drag-drop move to a local copy of the cells array.
45
+ * Handles both cross-cell moves and same-cell reorders.
46
+ */
47
+ export function applyOptimisticMove(cells, item, srcColumnSlug, srcSwimlaneSlug, dstColumnSlug, dstSwimlaneSlug, insertBeforeSlug) {
48
+ return cells.map((cell) => {
49
+ const isDst = cell.columnSlug === dstColumnSlug && cell.swimlaneSlug === dstSwimlaneSlug;
50
+ const isSrc = cell.columnSlug === srcColumnSlug && cell.swimlaneSlug === srcSwimlaneSlug;
51
+ if (!isDst && !isSrc)
52
+ return cell;
53
+ // Remove item from its current position (handles both src and dst sides)
54
+ const withoutItem = cell.items.filter((i) => i.slug !== item.slug);
55
+ if (isDst) {
56
+ if (insertBeforeSlug === null) {
57
+ return { ...cell, items: [...withoutItem, item] };
58
+ }
59
+ const idx = withoutItem.findIndex((i) => i.slug === insertBeforeSlug);
60
+ const insertAt = idx >= 0 ? idx : withoutItem.length;
61
+ return {
62
+ ...cell,
63
+ items: [
64
+ ...withoutItem.slice(0, insertAt),
65
+ item,
66
+ ...withoutItem.slice(insertAt),
67
+ ],
68
+ };
69
+ }
70
+ // isSrc only (cross-cell move source cleanup)
71
+ return { ...cell, items: withoutItem };
72
+ });
73
+ }
74
+ /**
75
+ * Compute the mutation list for a drag-drop action.
76
+ *
77
+ * Returns null when the destination cell is read-only or when
78
+ * deriveMutations returns `{ readonly: true }` as a belt-and-suspenders check.
79
+ *
80
+ * One drop = exactly one PATCH. The returned mutation list includes:
81
+ * 1. Cell-placement mutations derived from the destination cell's filter.
82
+ * 2. One `set boards.<boardSlug>.order = <fractional-key>` mutation for ordering.
83
+ */
84
+ export function computeDropMutations(params) {
85
+ const { itemSlug, srcCell, dstCell, colAxis, slAxis, board, insertBeforeSlug } = params;
86
+ if (dstCell.readOnly)
87
+ return null;
88
+ const filter = buildCellFilter(board, colAxis, slAxis);
89
+ const override = getWriteOnDropOverride(colAxis, slAxis);
90
+ const result = deriveMutations(filter, { board: board.slug }, override);
91
+ if (!Array.isArray(result))
92
+ return null; // ReadOnly from deriveMutations
93
+ // Determine insert position in the destination cell (excluding the moved item)
94
+ const dstItemsWithoutMoved = dstCell.items.filter((i) => i.slug !== itemSlug);
95
+ const rawIdx = insertBeforeSlug === null
96
+ ? -1
97
+ : dstItemsWithoutMoved.findIndex((i) => i.slug === insertBeforeSlug);
98
+ const insertAt = rawIdx >= 0 ? rawIdx : dstItemsWithoutMoved.length;
99
+ const prevItem = dstItemsWithoutMoved[insertAt - 1] ?? null;
100
+ const nextItem = dstItemsWithoutMoved[insertAt] ?? null;
101
+ const prevOrder = prevItem !== null ? getItemBoardOrder(prevItem, board.slug) : undefined;
102
+ const nextOrder = nextItem !== null ? getItemBoardOrder(nextItem, board.slug) : undefined;
103
+ const newOrderKey = keyBetween(prevOrder, nextOrder);
104
+ const orderMutation = {
105
+ op: 'set',
106
+ path: `boards.${board.slug}.order`,
107
+ value: newOrderKey,
108
+ };
109
+ const isReorder = srcCell.columnSlug === dstCell.columnSlug &&
110
+ srcCell.swimlaneSlug === dstCell.swimlaneSlug;
111
+ return {
112
+ mutations: [...result, orderMutation],
113
+ type: isReorder ? 'reorder' : 'move',
114
+ };
115
+ }
116
+ //# sourceMappingURL=mutateDragDrop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutateDragDrop.js","sourceRoot":"","sources":["../../../src/board/dnd/mutateDragDrop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { DragEndEvent } from '@dnd-kit/core';
2
+ import type { Cell } from '@awesome-markdown/contracts';
3
+ export type DropAction = {
4
+ type: 'noop';
5
+ } | {
6
+ type: 'drop';
7
+ itemSlug: string;
8
+ srcColumnSlug: string;
9
+ srcSwimlaneSlug: string;
10
+ dstColumnSlug: string;
11
+ dstSwimlaneSlug: string;
12
+ /**
13
+ * Slug of the item to insert before, or null to insert at end of cell.
14
+ * When src === dst this is a same-cell reorder.
15
+ */
16
+ insertBeforeSlug: string | null;
17
+ };
18
+ /**
19
+ * Pure function: translates a @dnd-kit DragEndEvent into a drop action.
20
+ * Uses `cells` to locate which cell an item belongs to.
21
+ * No React, no provider calls — fully testable in isolation.
22
+ */
23
+ export declare function onDragEnd(event: DragEndEvent, cells: Cell[]): DropAction;
24
+ //# sourceMappingURL=onDragEnd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onDragEnd.d.ts","sourceRoot":"","sources":["../../../src/board/dnd/onDragEnd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAQxD,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEN;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,CAwCxE"}