@stephen-netu/design-system 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/dist/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +10 -2
  2. package/dist/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte.d.ts.map +1 -1
  3. package/dist/b0-app-shell/{command-bar/CommandBar.svelte → global-command-bar/GlobalCommandBar.svelte} +75 -75
  4. package/dist/b0-app-shell/{command-bar/CommandBar.svelte.d.ts → global-command-bar/GlobalCommandBar.svelte.d.ts} +6 -6
  5. package/dist/b0-app-shell/global-command-bar/GlobalCommandBar.svelte.d.ts.map +1 -0
  6. package/dist/b0-app-shell/index.d.ts +1 -1
  7. package/dist/b0-app-shell/index.d.ts.map +1 -1
  8. package/dist/b0-app-shell/index.js +1 -1
  9. package/dist/d0-data-viz/CheckpointPill.svelte +7 -2
  10. package/dist/d0-data-viz/CheckpointPill.svelte.d.ts.map +1 -1
  11. package/dist/d0-data-viz/theme-integration.d.ts +3 -3
  12. package/dist/d0-data-viz/theme-integration.js +3 -3
  13. package/dist/d0-data-viz/theme-integration.test.js +41 -0
  14. package/dist/demos/BspSizingInfographic.svelte +3 -32
  15. package/dist/editor/CodeEditor.test.js +38 -0
  16. package/dist/editor/FindReplaceDialog.svelte +32 -32
  17. package/dist/editor/MarkdownEditor.svelte +71 -58
  18. package/dist/editor/MarkdownEditor.svelte.d.ts.map +1 -1
  19. package/dist/editor/MarkdownEditor.test.js +38 -0
  20. package/dist/editor/components/CorrectionTooltip.svelte +0 -1
  21. package/dist/editor/extensions/expansion.d.ts.map +1 -1
  22. package/dist/editor/extensions/expansion.js +16 -10
  23. package/dist/entity-graph-view/WorldView.svelte +1 -1
  24. package/dist/fabric/ai/ChatPanel.svelte +31 -31
  25. package/dist/fabric/ai/ResearchPanel.svelte +6 -3
  26. package/dist/fabric/ai/ResearchPanel.svelte.d.ts.map +1 -1
  27. package/dist/fabric/index.d.ts +4 -5
  28. package/dist/fabric/index.d.ts.map +1 -1
  29. package/dist/fabric/index.js +3 -3
  30. package/dist/fabric/input/{CommandBar.svelte → AppHeaderBar.svelte} +13 -13
  31. package/dist/fabric/input/{CommandBar.svelte.d.ts → AppHeaderBar.svelte.d.ts} +5 -5
  32. package/dist/fabric/input/AppHeaderBar.svelte.d.ts.map +1 -0
  33. package/dist/fabric/input/{CommandBar.test.js → AppHeaderBar.test.js} +9 -9
  34. package/dist/fabric/input/index.d.ts +2 -2
  35. package/dist/fabric/input/index.d.ts.map +1 -1
  36. package/dist/fabric/input/index.js +1 -1
  37. package/dist/fabric/layout/KanbanBoard.svelte +25 -155
  38. package/dist/fabric/layout/KanbanBoard.svelte.d.ts +2 -26
  39. package/dist/fabric/layout/KanbanBoard.svelte.d.ts.map +1 -1
  40. package/dist/fabric/layout/KanbanBoard.test.js +125 -10
  41. package/dist/fabric/layout/KanbanCard.svelte +27 -223
  42. package/dist/fabric/layout/KanbanCard.svelte.d.ts +2 -19
  43. package/dist/fabric/layout/KanbanCard.svelte.d.ts.map +1 -1
  44. package/dist/fabric/layout/KanbanColumn.svelte +41 -275
  45. package/dist/fabric/layout/KanbanColumn.svelte.d.ts +2 -22
  46. package/dist/fabric/layout/KanbanColumn.svelte.d.ts.map +1 -1
  47. package/dist/fabric/layout/index.d.ts +2 -5
  48. package/dist/fabric/layout/index.d.ts.map +1 -1
  49. package/dist/fabric/layout/index.js +1 -1
  50. package/dist/g0-generative/renderer/OpenUIRenderer.svelte +3 -3
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +4 -2
  53. package/dist/l0-layout/SectionSplitter.svelte +5 -5
  54. package/dist/l0-layout/block-writer/BlockItem.svelte +6 -4
  55. package/dist/l0-layout/card/CompactCard.svelte +4 -3
  56. package/dist/l0-layout/grant/GrantCard.svelte +15 -5
  57. package/dist/l0-layout/grant/GrantCard.svelte.d.ts.map +1 -1
  58. package/dist/l0-layout/index.d.ts +2 -0
  59. package/dist/l0-layout/index.d.ts.map +1 -1
  60. package/dist/l0-layout/index.js +1 -0
  61. package/dist/l0-layout/kanban/KanbanBoard.svelte +246 -29
  62. package/dist/l0-layout/kanban/KanbanBoard.svelte.d.ts +28 -2
  63. package/dist/l0-layout/kanban/KanbanBoard.svelte.d.ts.map +1 -1
  64. package/dist/l0-layout/kanban/KanbanCard.svelte +175 -150
  65. package/dist/l0-layout/kanban/KanbanCard.svelte.d.ts +16 -18
  66. package/dist/l0-layout/kanban/KanbanCard.svelte.d.ts.map +1 -1
  67. package/dist/l0-layout/kanban/KanbanColumn.svelte +152 -78
  68. package/dist/l0-layout/kanban/KanbanColumn.svelte.d.ts +28 -7
  69. package/dist/l0-layout/kanban/KanbanColumn.svelte.d.ts.map +1 -1
  70. package/dist/l0-layout/kanban/index.d.ts +6 -0
  71. package/dist/l0-layout/kanban/index.d.ts.map +1 -0
  72. package/dist/l0-layout/kanban/index.js +3 -0
  73. package/dist/n0-node-graph/Node.svelte +2 -2
  74. package/dist/n0-node-graph/NodePalette.svelte +2 -2
  75. package/dist/n1-flow-canvas/graph-state.test.js +69 -0
  76. package/dist/n1-flow-canvas/utils.test.js +116 -0
  77. package/dist/n3-force-graph/GraphTooltip.svelte +2 -2
  78. package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte +12 -11
  79. package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte.d.ts.map +1 -1
  80. package/dist/n4-adaptive-manifold/classifier.test.js +104 -0
  81. package/dist/n4-adaptive-manifold/n4-tokens.css +2 -2
  82. package/dist/p0-primitives/ThemeProvider.svelte +10 -11
  83. package/dist/p0-primitives/ThemeProvider.svelte.d.ts +1 -1
  84. package/dist/p0-primitives/ThemeProvider.svelte.d.ts.map +1 -1
  85. package/dist/p0-primitives/canvas-theme.d.ts +12 -0
  86. package/dist/p0-primitives/canvas-theme.d.ts.map +1 -1
  87. package/dist/p0-primitives/canvas-theme.js +10 -0
  88. package/dist/p0-primitives/index.d.ts +2 -1
  89. package/dist/p0-primitives/index.d.ts.map +1 -1
  90. package/dist/p0-primitives/index.js +1 -0
  91. package/dist/p0-primitives/theme-context.d.ts +9 -0
  92. package/dist/p0-primitives/theme-context.d.ts.map +1 -0
  93. package/dist/p0-primitives/theme-context.js +8 -0
  94. package/dist/p0-primitives/tokens/tokens.css +22 -11
  95. package/dist/p0-primitives/utils/index.d.ts +2 -2
  96. package/dist/p0-primitives/utils/index.d.ts.map +1 -1
  97. package/dist/s0-state/SyncStatus.svelte +1 -1
  98. package/dist/s0-state/ThemeStore.svelte.d.ts +3 -2
  99. package/dist/s0-state/ThemeStore.svelte.d.ts.map +1 -1
  100. package/dist/s0-state/ThemeStore.svelte.js +20 -1
  101. package/dist/s0-state/index.d.ts +0 -1
  102. package/dist/s0-state/index.d.ts.map +1 -1
  103. package/dist/s0-state/index.js +1 -0
  104. package/dist/s0-state/modal-stack-store.svelte.d.ts +25 -0
  105. package/dist/s0-state/modal-stack-store.svelte.d.ts.map +1 -1
  106. package/dist/s0-state/modal-stack-store.svelte.js +19 -0
  107. package/dist/showcase/Showcase.svelte +43 -34
  108. package/dist/showcase/Showcase.svelte.d.ts.map +1 -1
  109. package/dist/spatial/BspTilingCanvas.svelte +7 -5
  110. package/dist/spatial/BspTilingCanvas.svelte.d.ts +1 -0
  111. package/dist/spatial/BspTilingCanvas.svelte.d.ts.map +1 -1
  112. package/dist/spatial/BspTilingSimulation.test.js +88 -0
  113. package/dist/spatial/CameraController.test.js +120 -0
  114. package/dist/spatial/ForceCanvas.svelte +20 -13
  115. package/dist/spatial/ForceCanvas.svelte.d.ts +1 -0
  116. package/dist/spatial/ForceCanvas.svelte.d.ts.map +1 -1
  117. package/dist/spatial/ForceSimulation.svelte.d.ts.map +1 -1
  118. package/dist/spatial/ForceSimulation.svelte.js +32 -21
  119. package/dist/spatial/LodRenderer.svelte +16 -1
  120. package/dist/spatial/LodRenderer.svelte.d.ts +1 -0
  121. package/dist/spatial/LodRenderer.svelte.d.ts.map +1 -1
  122. package/dist/spatial/SnapZoomCamera.svelte +25 -13
  123. package/dist/spatial/SnapZoomCamera.svelte.d.ts +1 -0
  124. package/dist/spatial/SnapZoomCamera.svelte.d.ts.map +1 -1
  125. package/dist/spatial/ZoneTiler.svelte +5 -2
  126. package/dist/spatial/ZoneTiler.svelte.d.ts +1 -0
  127. package/dist/spatial/ZoneTiler.svelte.d.ts.map +1 -1
  128. package/dist/spatial/d3-types.d.ts +31 -0
  129. package/dist/spatial/d3-types.d.ts.map +1 -0
  130. package/dist/spatial/d3-types.js +19 -0
  131. package/dist/ssr-import-clean.test.js +37 -0
  132. package/dist/t0-transport/fs.d.ts +12 -0
  133. package/dist/t0-transport/fs.d.ts.map +1 -0
  134. package/dist/t0-transport/fs.js +55 -0
  135. package/dist/t0-transport/index.d.ts +1 -0
  136. package/dist/t0-transport/index.d.ts.map +1 -1
  137. package/dist/t0-transport/index.js +1 -0
  138. package/dist/t0-transport/invoke.d.ts.map +1 -1
  139. package/dist/t0-transport/invoke.js +5 -2
  140. package/dist/t0-transport/quality.d.ts +12 -3
  141. package/dist/t0-transport/quality.d.ts.map +1 -1
  142. package/dist/t0-transport/quality.js +17 -4
  143. package/dist/t0-transport/substrate.svelte.d.ts +27 -0
  144. package/dist/t0-transport/substrate.svelte.d.ts.map +1 -0
  145. package/dist/t0-transport/substrate.svelte.js +49 -0
  146. package/dist/u0-primitives/LockIndicator.svelte +1 -1
  147. package/dist/u0-primitives/VerticalToolbar.svelte +1 -1
  148. package/dist/u0-primitives/accordion/Accordion.svelte +10 -9
  149. package/dist/u0-primitives/accordion/Accordion.svelte.d.ts +0 -7
  150. package/dist/u0-primitives/accordion/Accordion.svelte.d.ts.map +1 -1
  151. package/dist/u0-primitives/accordion/Accordion.test.js +5 -5
  152. package/dist/u0-primitives/badge/Badge.test.js +10 -10
  153. package/dist/u0-primitives/badge/ValidityBadge.test.js +9 -9
  154. package/dist/u0-primitives/button/Button.svelte +3 -1
  155. package/dist/u0-primitives/button/Button.svelte.d.ts +1 -0
  156. package/dist/u0-primitives/button/Button.svelte.d.ts.map +1 -1
  157. package/dist/u0-primitives/button/Button.test.js +11 -11
  158. package/dist/u0-primitives/card/Card.svelte +26 -20
  159. package/dist/u0-primitives/card/Card.svelte.d.ts.map +1 -1
  160. package/dist/u0-primitives/command-palette/CommandPalette.svelte +27 -0
  161. package/dist/u0-primitives/command-palette/CommandPalette.svelte.d.ts.map +1 -1
  162. package/dist/u0-primitives/command-palette/commandStore.svelte.d.ts.map +1 -1
  163. package/dist/u0-primitives/command-palette/commandStore.svelte.js +2 -1
  164. package/dist/u0-primitives/dropdown/Dropdown.test.js +1 -1
  165. package/dist/u0-primitives/index.d.ts +2 -0
  166. package/dist/u0-primitives/index.d.ts.map +1 -1
  167. package/dist/u0-primitives/index.js +1 -0
  168. package/dist/u0-primitives/input/Input.svelte +9 -0
  169. package/dist/u0-primitives/input/Input.svelte.d.ts.map +1 -1
  170. package/dist/u0-primitives/input/Input.test.js +1 -1
  171. package/dist/u0-primitives/modal/Modal.svelte +46 -23
  172. package/dist/u0-primitives/modal/Modal.svelte.d.ts.map +1 -1
  173. package/dist/u0-primitives/modal/Modal.test.js +63 -15
  174. package/dist/u0-primitives/rsvp/RsvpReader.svelte +8 -8
  175. package/dist/u0-primitives/rsvp/RsvpReader.svelte.d.ts.map +1 -1
  176. package/dist/u0-primitives/steps/Steps.svelte +2 -2
  177. package/dist/u0-primitives/surface-state/SurfaceState.svelte +190 -0
  178. package/dist/u0-primitives/surface-state/SurfaceState.svelte.d.ts +15 -0
  179. package/dist/u0-primitives/surface-state/SurfaceState.svelte.d.ts.map +1 -0
  180. package/dist/u0-primitives/toggle/Toggle.svelte +12 -2
  181. package/dist/u0-primitives/tooltip/Tooltip.test.js +12 -12
  182. package/dist/v0-diagrams/MarkmapDiagram.test.js +49 -0
  183. package/dist/v0-diagrams/MermaidDiagram.svelte +21 -9
  184. package/dist/v0-diagrams/MermaidDiagram.svelte.d.ts.map +1 -1
  185. package/dist/v0-diagrams/MermaidDiagram.test.js +40 -0
  186. package/package.json +51 -24
  187. package/src/n4-adaptive-manifold/n4-tokens.css +2 -2
  188. package/src/p0-primitives/tokens/tokens.css +22 -11
  189. package/src/p0-primitives/tokens/tokens.json +13 -2
  190. package/dist/b0-app-shell/command-bar/CommandBar.svelte.d.ts.map +0 -1
  191. package/dist/fabric/input/CommandBar.svelte.d.ts.map +0 -1
  192. package/dist/stores/vaultStore.svelte +0 -14
  193. package/dist/stores/vaultStore.svelte.d.ts +0 -24
  194. package/dist/stores/vaultStore.svelte.d.ts.map +0 -1
  195. package/dist/tauri/index.d.ts +0 -3
  196. package/dist/tauri/index.d.ts.map +0 -1
  197. package/dist/tauri/index.js +0 -11
  198. package/dist/types/tauri.d.ts +0 -18
@@ -1,29 +1,5 @@
1
- /**
2
- * KanbanBoard - Fabric Component
3
- *
4
- * Multi-column kanban board with drag-drop support.
5
- * Decoupled from shell stores - uses props/callbacks for all state.
6
- *
7
- * @package @kos/design-system/fabric/layout
8
- * @adr 2026-04-12-leap-substrate-refactor-001
9
- */
10
- import type { ColumnData } from './KanbanColumn.svelte';
11
- import type { CardData } from './KanbanCard.svelte';
12
- interface ColumnState {
13
- column: ColumnData;
14
- cards: CardData[];
15
- isDropTarget?: boolean;
16
- isCollapsed?: boolean;
17
- }
18
- export interface Props {
19
- columns: ColumnState[];
20
- onCardMove?: (cardId: string, sourceColumnId: string, targetColumnId: string) => void;
21
- onCardClick?: (card: CardData) => void;
22
- onAddCard?: (columnId: string) => void;
23
- onAddColumn?: () => void;
24
- onColumnMenuClick?: (columnId: string) => void;
25
- title?: string;
26
- }
1
+ import KanbanBoard from '../../l0-layout/kanban/KanbanBoard.svelte';
2
+ import type { Props } from '../../l0-layout/kanban/KanbanBoard.svelte';
27
3
  declare const KanbanBoard: import("svelte").Component<Props, {}, "">;
28
4
  type KanbanBoard = ReturnType<typeof KanbanBoard>;
29
5
  export default KanbanBoard;
@@ -1 +1 @@
1
- {"version":3,"file":"KanbanBoard.svelte.d.ts","sourceRoot":"","sources":["../../../src/fabric/layout/KanbanBoard.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;KAQK;AACL,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGlD,UAAU,WAAW;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACtF,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAyEH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"KanbanBoard.svelte.d.ts","sourceRoot":"","sources":["../../../src/fabric/layout/KanbanBoard.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,2CAA2C,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAuBvE,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -1,25 +1,140 @@
1
- import { afterEach, describe, it, expect } from 'vitest';
2
- import { cleanup, render } from '@testing-library/svelte';
1
+ import { cleanup, fireEvent, render } from '@testing-library/svelte';
2
+ import { afterEach, describe, it, expect, vi } from 'vitest';
3
3
  import KanbanBoard from './KanbanBoard.svelte';
4
- // This component uses `{#await import('./KanbanColumn.svelte')}` for lazy loading.
5
- // In tests the dynamic import doesn't resolve in jsdom, so we test what renders
6
- // synchronously: an error boundary slot. When that's absent the component renders
7
- // nothing until the promise resolves.
8
4
  describe('KanbanBoard', () => {
9
5
  afterEach(() => cleanup());
10
6
  it('exports a valid Svelte component', () => {
11
7
  expect(KanbanBoard).toBeDefined();
12
8
  expect(typeof KanbanBoard).toBe('function');
13
9
  });
14
- it('initializes draggedCardId and activeDropColumn state', async () => {
15
- const { component } = render(KanbanBoard, {
10
+ it('renders columns with title', async () => {
11
+ const { container } = render(KanbanBoard, {
16
12
  props: {
17
13
  columns: [
18
14
  { column: { id: 'c1', title: 'Backlog' }, cards: [{ id: 'card1', title: 'Task 1' }] },
15
+ { column: { id: 'c2', title: 'In Progress' }, cards: [] },
19
16
  ],
20
17
  },
21
18
  });
22
- // Component mounted without crashing — even if {#await} hasn't resolved yet
23
- expect(component).toBeDefined();
19
+ expect(container.querySelector('.ds-kanban-board')).not.toBeNull();
20
+ expect(container.querySelectorAll('.ds-kanban-column').length).toBe(2);
21
+ expect(container.querySelector('.ds-kanban-column-title')?.textContent).toBe('Backlog');
22
+ });
23
+ it('renders board title when provided', () => {
24
+ const { container } = render(KanbanBoard, {
25
+ props: {
26
+ title: 'My Board',
27
+ columns: [],
28
+ },
29
+ });
30
+ expect(container.querySelector('.ds-kanban-board-title')?.textContent).toBe('My Board');
31
+ });
32
+ it('renders cards within columns', () => {
33
+ const { container } = render(KanbanBoard, {
34
+ props: {
35
+ columns: [
36
+ {
37
+ column: { id: 'c1', title: 'Todo' },
38
+ cards: [
39
+ { id: 'card1', title: 'First Task', priority: 'high' },
40
+ { id: 'card2', title: 'Second Task', priority: 'low' },
41
+ ],
42
+ },
43
+ ],
44
+ },
45
+ });
46
+ const titles = container.querySelectorAll('.ds-kanban-card-title');
47
+ expect(titles.length).toBe(2);
48
+ expect(titles[0]?.textContent).toBe('First Task');
49
+ expect(titles[1]?.textContent).toBe('Second Task');
50
+ });
51
+ it('renders priority indicator bars', () => {
52
+ const { container } = render(KanbanBoard, {
53
+ props: {
54
+ columns: [
55
+ {
56
+ column: { id: 'c1', title: 'Todo' },
57
+ cards: [{ id: 'card1', title: 'Urgent Task', priority: 'urgent' }],
58
+ },
59
+ ],
60
+ },
61
+ });
62
+ expect(container.querySelector('.ds-kanban-priority-bar')).not.toBeNull();
63
+ });
64
+ it('renders tags when provided', () => {
65
+ const { container } = render(KanbanBoard, {
66
+ props: {
67
+ columns: [
68
+ {
69
+ column: { id: 'c1', title: 'Todo' },
70
+ cards: [{ id: 'card1', title: 'Tagged', tags: ['alpha', 'beta', 'gamma', 'delta'] }],
71
+ },
72
+ ],
73
+ },
74
+ });
75
+ const tags = container.querySelectorAll('.ds-kanban-card-tag');
76
+ expect(tags.length).toBe(3); // max 3 shown
77
+ expect(container.querySelector('.ds-kanban-card-tag-more')?.textContent).toBe('+1');
78
+ });
79
+ it('moves a card with keyboard move mode', async () => {
80
+ const onCardMove = vi.fn();
81
+ const onCardClick = vi.fn();
82
+ const { container } = render(KanbanBoard, {
83
+ props: {
84
+ columns: [
85
+ { column: { id: 'todo', title: 'Todo' }, cards: [{ id: 'task-1', title: 'Task 1' }] },
86
+ { column: { id: 'doing', title: 'In Progress' }, cards: [] },
87
+ ],
88
+ onCardMove,
89
+ onCardClick,
90
+ },
91
+ });
92
+ const card = container.querySelector('.ds-kanban-card');
93
+ const interactiveCard = container.querySelector('.ds-card');
94
+ expect(card).not.toBeNull();
95
+ expect(interactiveCard).not.toBeNull();
96
+ await fireEvent.keyDown(interactiveCard, { key: ' ' });
97
+ expect(container.querySelector('.ds-kanban-move-toast')).not.toBeNull();
98
+ expect(card.classList.contains('is-selected')).toBe(true);
99
+ await fireEvent.keyDown(interactiveCard, { key: 'ArrowRight' });
100
+ expect(container.querySelector('.ds-kanban-move-target')?.textContent).toBe('→ In Progress');
101
+ await fireEvent.keyDown(interactiveCard, { key: 'Enter' });
102
+ expect(onCardMove).toHaveBeenCalledWith('task-1', 'todo', 'doing');
103
+ expect(onCardClick).not.toHaveBeenCalled();
104
+ expect(container.querySelector('.ds-kanban-move-toast')).toBeNull();
105
+ });
106
+ it('cancels keyboard move mode with Escape', async () => {
107
+ const onCardMove = vi.fn();
108
+ const { container } = render(KanbanBoard, {
109
+ props: {
110
+ columns: [
111
+ { column: { id: 'todo', title: 'Todo' }, cards: [{ id: 'task-1', title: 'Task 1' }] },
112
+ { column: { id: 'doing', title: 'In Progress' }, cards: [] },
113
+ ],
114
+ onCardMove,
115
+ },
116
+ });
117
+ const card = container.querySelector('.ds-kanban-card');
118
+ const interactiveCard = container.querySelector('.ds-card');
119
+ expect(card).not.toBeNull();
120
+ expect(interactiveCard).not.toBeNull();
121
+ await fireEvent.keyDown(interactiveCard, { key: ' ' });
122
+ await fireEvent.keyDown(interactiveCard, { key: 'ArrowRight' });
123
+ await fireEvent.keyDown(interactiveCard, { key: 'Escape' });
124
+ expect(onCardMove).not.toHaveBeenCalled();
125
+ expect(container.querySelector('.ds-kanban-move-toast')).toBeNull();
126
+ });
127
+ it('renders move-toast in keyboard move mode', () => {
128
+ // Move mode is internal state — verify the toast element exists in DOM when triggered
129
+ // This is tested via the board's reactive rendering; we verify the CSS class exists
130
+ const { container } = render(KanbanBoard, {
131
+ props: {
132
+ columns: [
133
+ { column: { id: 'c1', title: 'Todo' }, cards: [{ id: 'card1', title: 'Task' }] },
134
+ ],
135
+ },
136
+ });
137
+ // Toast should not be visible initially
138
+ expect(container.querySelector('.ds-kanban-move-toast')).toBeNull();
24
139
  });
25
140
  });
@@ -1,226 +1,30 @@
1
1
  <script lang="ts">
2
- /**
3
- * KanbanCard - Fabric Component
4
- *
5
- * Draggable kanban card with metadata display.
6
- * Decoupled from shell stores - uses props/callbacks for all state.
7
- *
8
- * @package @kos/design-system/fabric/layout
9
- * @adr 2026-04-12-leap-substrate-refactor-001
10
- */
11
- import { GripVertical, Clock, Tag } from '@lucide/svelte';
12
-
13
- export interface CardData {
14
- id: string;
15
- title: string;
16
- description?: string;
17
- priority?: 'low' | 'medium' | 'high';
18
- tags?: string[];
19
- dueDate?: Date;
20
- assignee?: string;
21
- metadata?: Record<string, unknown>;
22
- }
23
-
24
- export interface Props {
25
- card: CardData;
26
- isDragging?: boolean;
27
- isSelected?: boolean;
28
- disabled?: boolean;
29
- onClick?: (card: CardData) => void;
30
- onDragStart?: (card: CardData) => void;
31
- onDragEnd?: (card: CardData) => void;
32
- }
33
-
34
- let { card, isDragging, isSelected, disabled, onClick, onDragStart, onDragEnd }: Props = $props();
35
-
36
- function priorityColor(p: string | undefined): string {
37
- switch (p) {
38
- case 'high': return 'var(--color-error, #c0392b)';
39
- case 'medium': return 'var(--color-warning, #f39c12)';
40
- case 'low': return 'var(--color-success, #27ae60)';
41
- default: return 'var(--color-text-tertiary, #706858)';
42
- }
43
- }
44
-
45
- function formatDate(date: Date | undefined): string {
46
- if (!date) return '';
47
- return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
48
- }
2
+ import KanbanCard from '../../l0-layout/kanban/KanbanCard.svelte';
3
+ import type { Props } from '../../l0-layout/kanban/KanbanCard.svelte';
4
+
5
+ let {
6
+ card,
7
+ isDragging = false,
8
+ isSelected = false,
9
+ disabled = false,
10
+ onClick,
11
+ onDragStart,
12
+ onDragEnd,
13
+ onKeyDown,
14
+ moveMode = false,
15
+ children,
16
+ }: Props = $props();
49
17
  </script>
50
18
 
51
- <div
52
- class="kanban-card"
53
- class:dragging={isDragging}
54
- class:selected={isSelected}
55
- class:disabled={disabled}
56
- role="button"
57
- tabindex="0"
58
- aria-grabbed={isDragging}
59
- onclick={() => onClick?.(card)}
60
- onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') onClick?.(card); }}
61
- ondragstart={() => onDragStart?.(card)}
62
- ondragend={() => onDragEnd?.(card)}
63
- draggable={!disabled}
64
- >
65
- <div class="card-header">
66
- {#if card.priority}
67
- <span
68
- class="priority-indicator"
69
- style="background: {priorityColor(card.priority)}"
70
- title="Priority: {card.priority}"
71
- ></span>
72
- {/if}
73
- <span class="card-title">{card.title}</span>
74
- <GripVertical size={14} class="drag-handle" />
75
- </div>
76
-
77
- {#if card.description}
78
- <p class="card-description">{card.description}</p>
79
- {/if}
80
-
81
- <div class="card-footer">
82
- {#if card.tags && card.tags.length > 0}
83
- <div class="tags">
84
- {#each card.tags.slice(0, 3) as tag}
85
- <span class="tag">
86
- <Tag size={10} />
87
- {tag}
88
- </span>
89
- {/each}
90
- {#if card.tags.length > 3}
91
- <span class="tag-more">+{card.tags.length - 3}</span>
92
- {/if}
93
- </div>
94
- {/if}
95
-
96
- {#if card.dueDate}
97
- <span class="due-date" class:overdue={card.dueDate < new Date()}>
98
- <Clock size={12} />
99
- {formatDate(card.dueDate)}
100
- </span>
101
- {/if}
102
- </div>
103
- </div>
104
-
105
- <style>
106
- .kanban-card {
107
- background: var(--color-bg-panel, #222222);
108
- border: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
109
- border-radius: var(--radius-md, 0.375rem);
110
- padding: 12px;
111
- cursor: grab;
112
- transition: box-shadow 0.15s, transform 0.15s, border-color 0.15s;
113
- user-select: none;
114
- }
115
-
116
- .kanban-card:hover {
117
- border-color: var(--border-default, #333333);
118
- box-shadow: var(--shadow-sm, 0 2px 4px rgba(0,0,0,0.2));
119
- }
120
-
121
- .kanban-card.dragging {
122
- opacity: 0.5;
123
- transform: rotate(2deg);
124
- box-shadow: var(--shadow-lg, 0 4px 12px rgba(0,0,0,0.3));
125
- }
126
-
127
- .kanban-card.selected {
128
- border-color: var(--color-accent, var(--color-accent));
129
- box-shadow: 0 0 0 2px var(--color-accent-muted);
130
- }
131
-
132
- .kanban-card.disabled {
133
- opacity: 0.5;
134
- cursor: not-allowed;
135
- pointer-events: none;
136
- }
137
-
138
- .card-header {
139
- display: flex;
140
- align-items: center;
141
- gap: var(--space-2);
142
- margin-bottom: 8px;
143
- }
144
-
145
- .priority-indicator {
146
- width: 8px;
147
- height: 8px;
148
- border-radius: 50%;
149
- flex-shrink: 0;
150
- }
151
-
152
- .card-title {
153
- flex: 1;
154
- font-size: 13px;
155
- font-weight: 500;
156
- color: var(--color-text-primary, #f2efe9);
157
- overflow: hidden;
158
- text-overflow: ellipsis;
159
- white-space: nowrap;
160
- }
161
-
162
- :global(.drag-handle) {
163
- color: var(--color-text-tertiary, #706858);
164
- opacity: 0;
165
- transition: opacity 0.15s;
166
- }
167
-
168
- .kanban-card:hover :global(.drag-handle) {
169
- opacity: 1;
170
- }
171
-
172
- .card-description {
173
- font-size: 12px;
174
- color: var(--color-text-secondary, #a09880);
175
- line-height: 1.4;
176
- margin: 0 0 12px 0;
177
- display: -webkit-box;
178
- -webkit-line-clamp: 3;
179
- line-clamp: 3;
180
- -webkit-box-orient: vertical;
181
- box-orient: vertical;
182
- overflow: hidden;
183
- }
184
-
185
- .card-footer {
186
- display: flex;
187
- align-items: center;
188
- justify-content: space-between;
189
- gap: var(--space-2);
190
- }
191
-
192
- .tags {
193
- display: flex;
194
- align-items: center;
195
- gap: var(--space-2);
196
- flex-wrap: wrap;
197
- }
198
-
199
- .tag {
200
- display: inline-flex;
201
- align-items: center;
202
- gap: 3px;
203
- font-size: 10px;
204
- padding: 2px 6px;
205
- background: var(--color-bg-canvas, #1a1a1a);
206
- border-radius: var(--radius-sm, 0.25rem);
207
- color: var(--color-text-tertiary, #706858);
208
- }
209
-
210
- .tag-more {
211
- font-size: 10px;
212
- color: var(--color-text-tertiary, #706858);
213
- }
214
-
215
- .due-date {
216
- display: inline-flex;
217
- align-items: center;
218
- gap: var(--space-1);
219
- font-size: 11px;
220
- color: var(--color-text-tertiary, #706858);
221
- }
222
-
223
- .due-date.overdue {
224
- color: var(--color-error, #c0392b);
225
- }
226
- </style>
19
+ <KanbanCard
20
+ {card}
21
+ {isDragging}
22
+ {isSelected}
23
+ {disabled}
24
+ {onClick}
25
+ {onDragStart}
26
+ {onDragEnd}
27
+ {onKeyDown}
28
+ {moveMode}
29
+ {children}
30
+ />
@@ -1,22 +1,5 @@
1
- export interface CardData {
2
- id: string;
3
- title: string;
4
- description?: string;
5
- priority?: 'low' | 'medium' | 'high';
6
- tags?: string[];
7
- dueDate?: Date;
8
- assignee?: string;
9
- metadata?: Record<string, unknown>;
10
- }
11
- export interface Props {
12
- card: CardData;
13
- isDragging?: boolean;
14
- isSelected?: boolean;
15
- disabled?: boolean;
16
- onClick?: (card: CardData) => void;
17
- onDragStart?: (card: CardData) => void;
18
- onDragEnd?: (card: CardData) => void;
19
- }
1
+ import KanbanCard from '../../l0-layout/kanban/KanbanCard.svelte';
2
+ import type { Props } from '../../l0-layout/kanban/KanbanCard.svelte';
20
3
  declare const KanbanCard: import("svelte").Component<Props, {}, "">;
21
4
  type KanbanCard = ReturnType<typeof KanbanCard>;
22
5
  export default KanbanCard;
@@ -1 +1 @@
1
- {"version":3,"file":"KanbanCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/fabric/layout/KanbanCard.svelte.ts"],"names":[],"mappings":"AAeE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;CACtC;AAiEH,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"KanbanCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/fabric/layout/KanbanCard.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,UAAU,MAAM,0CAA0C,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAwBtE,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}