@svar-ui/svelte-kanban 2.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 (58) hide show
  1. package/dist/components/Avatar.svelte +87 -0
  2. package/dist/components/Avatar.svelte.d.ts +17 -0
  3. package/dist/components/Card.svelte +346 -0
  4. package/dist/components/Card.svelte.d.ts +9 -0
  5. package/dist/components/CardList.svelte +343 -0
  6. package/dist/components/CardList.svelte.d.ts +21 -0
  7. package/dist/components/CardWrapper.svelte +49 -0
  8. package/dist/components/CardWrapper.svelte.d.ts +15 -0
  9. package/dist/components/Column.svelte +230 -0
  10. package/dist/components/Column.svelte.d.ts +24 -0
  11. package/dist/components/ContextMenu.svelte +111 -0
  12. package/dist/components/ContextMenu.svelte.d.ts +18 -0
  13. package/dist/components/DragGhost.svelte +57 -0
  14. package/dist/components/DragGhost.svelte.d.ts +14 -0
  15. package/dist/components/Editor.svelte +108 -0
  16. package/dist/components/Editor.svelte.d.ts +10 -0
  17. package/dist/components/ExportLayout.svelte +52 -0
  18. package/dist/components/ExportLayout.svelte.d.ts +15 -0
  19. package/dist/components/Kanban.svelte +100 -0
  20. package/dist/components/Kanban.svelte.d.ts +186 -0
  21. package/dist/components/Layout.svelte +362 -0
  22. package/dist/components/Layout.svelte.d.ts +19 -0
  23. package/dist/components/Toolbar.svelte +97 -0
  24. package/dist/components/Toolbar.svelte.d.ts +12 -0
  25. package/dist/components/useCardOverlay.svelte.d.ts +24 -0
  26. package/dist/components/useCardOverlay.svelte.js +60 -0
  27. package/dist/components/useDrag.svelte.d.ts +22 -0
  28. package/dist/components/useDrag.svelte.js +16 -0
  29. package/dist/context.d.ts +3 -0
  30. package/dist/context.js +3 -0
  31. package/dist/defaults.d.ts +8 -0
  32. package/dist/defaults.js +85 -0
  33. package/dist/directives/dblclick.d.ts +13 -0
  34. package/dist/directives/dblclick.js +26 -0
  35. package/dist/directives/drag.d.ts +11 -0
  36. package/dist/directives/drag.js +183 -0
  37. package/dist/env.d.ts +9 -0
  38. package/dist/export/Card.svelte +5 -0
  39. package/dist/export/Card.svelte.d.ts +11 -0
  40. package/dist/export/Kanban.svelte +30 -0
  41. package/dist/export/Kanban.svelte.d.ts +16 -0
  42. package/dist/export.d.ts +3 -0
  43. package/dist/export.js +15 -0
  44. package/dist/index.d.ts +15 -0
  45. package/dist/index.js +15 -0
  46. package/dist/themes/Print.svelte +126 -0
  47. package/dist/themes/Print.svelte.d.ts +13 -0
  48. package/dist/themes/PrintBW.svelte +153 -0
  49. package/dist/themes/PrintBW.svelte.d.ts +13 -0
  50. package/dist/themes/Willow.svelte +45 -0
  51. package/dist/themes/Willow.svelte.d.ts +7 -0
  52. package/dist/themes/WillowDark.svelte +49 -0
  53. package/dist/themes/WillowDark.svelte.d.ts +7 -0
  54. package/dist/types.d.ts +86 -0
  55. package/dist/types.js +1 -0
  56. package/license.txt +21 -0
  57. package/package.json +59 -0
  58. package/readme.md +100 -0
@@ -0,0 +1,362 @@
1
+ <script lang="ts">import { getContext, onDestroy, setContext } from "svelte";
2
+ import { delegateClick, hotkeys, locate, locateID } from "@svar-ui/lib-dom";
3
+ import { Popup } from "@svar-ui/svelte-core";
4
+ import Column from "./Column.svelte";
5
+ import ContextMenu from "./ContextMenu.svelte";
6
+ import DragGhost from "./DragGhost.svelte";
7
+ import { cardDrag } from "../directives/drag.js";
8
+ import { KANBAN_API_CONTEXT, SCROLL_CONTAINER_CONTEXT, DND_CONTEXT } from "../context.js";
9
+ import { useCardOverlay } from "./useCardOverlay.svelte.js";
10
+ let { readonly = false, render, cardContent, cardShape, tooltip, cardPopup, cardCss, columnCss } = $props();
11
+ const columnScroll = $derived(render?.columnScroll ?? true);
12
+ const fixedColumnWidth = $derived(render?.fixedColumnWidth ?? true);
13
+ const virtualizeCards = $derived(render?.virtualizeCards ?? false);
14
+ const virtualizeColumns = $derived(render?.virtualizeColumns ?? false);
15
+ const estimatedCardHeight = $derived(render?.estimatedCardHeight ?? 80);
16
+ const cardOverscan = $derived(render?.cardOverscan ?? 5);
17
+ const columnOverscan = $derived(render?.columnOverscan ?? 1);
18
+ const store = getContext(KANBAN_API_CONTEXT);
19
+ const { viewData } = store.getReactiveState();
20
+ const brandmark = store.getBrandmark();
21
+ const _ = getContext("wx-i18n").getGroup("kanban");
22
+ const dnd = getContext(DND_CONTEXT);
23
+ let root = $state();
24
+ let scroll = $state();
25
+ let visibleColumnIds = $state(new Set());
26
+ let visibilityFrame = 0;
27
+ const columnElements = new Map();
28
+ setContext(SCROLL_CONTAINER_CONTEXT, () => columnScroll ? null : scroll ?? null);
29
+ function sameSet(a, b) {
30
+ if (a.size !== b.size) return false;
31
+ for (const value of a) {
32
+ if (!b.has(value)) return false;
33
+ }
34
+ return true;
35
+ }
36
+ function setVisibleColumns(next) {
37
+ if (!sameSet(visibleColumnIds, next)) {
38
+ visibleColumnIds = next;
39
+ }
40
+ }
41
+ function updateColumnVisibility() {
42
+ if (!virtualizeColumns || !scroll) {
43
+ setVisibleColumns(new Set());
44
+ return;
45
+ }
46
+ const columns = $viewData.columns;
47
+ if (!columns.length) {
48
+ setVisibleColumns(new Set());
49
+ return;
50
+ }
51
+ const scrollRect = scroll.getBoundingClientRect();
52
+ let first = -1;
53
+ let last = -1;
54
+ for (let i = 0; i < columns.length; i++) {
55
+ const element = columnElements.get(columns[i].id);
56
+ if (!element) continue;
57
+ const rect = element.getBoundingClientRect();
58
+ if (rect.right >= scrollRect.left && rect.left <= scrollRect.right) {
59
+ if (first === -1) first = i;
60
+ last = i;
61
+ }
62
+ }
63
+ if (first === -1 || last === -1) {
64
+ setVisibleColumns(new Set());
65
+ return;
66
+ }
67
+ const overscan = Math.max(0, Math.floor(columnOverscan || 0));
68
+ first = Math.max(0, first - overscan);
69
+ last = Math.min(columns.length - 1, last + overscan);
70
+ const next = new Set();
71
+ for (let i = first; i <= last; i++) {
72
+ next.add(columns[i].id);
73
+ }
74
+ setVisibleColumns(next);
75
+ }
76
+ function scheduleColumnVisibility(..._tracked) {
77
+ if (visibilityFrame) return;
78
+ visibilityFrame = requestAnimationFrame(() => {
79
+ visibilityFrame = 0;
80
+ updateColumnVisibility();
81
+ });
82
+ }
83
+ function registerColumn(id, element) {
84
+ if (element) columnElements.set(id, element);
85
+ else columnElements.delete(id);
86
+ scheduleColumnVisibility();
87
+ }
88
+ function updateScrollHeightVar() {
89
+ if (!scroll) return;
90
+ scroll.style.setProperty("--wx-kanban-scroll-height", `${scroll.clientHeight}px`);
91
+ }
92
+ function isColumnContentVisible(id) {
93
+ return !virtualizeColumns || visibleColumnIds.size === 0 || visibleColumnIds.has(id);
94
+ }
95
+ function isColumnRequestVisible(id) {
96
+ return !virtualizeColumns || visibleColumnIds.has(id);
97
+ }
98
+ function getCard(id) {
99
+ return store.getState().cards.getById(id);
100
+ }
101
+ const overlay = useCardOverlay(getCard, "right-start");
102
+ const popupExtra = { trackScroll: true };
103
+ function selectCard(id) {
104
+ if (!readonly && id != null) {
105
+ store.exec("select-card", { id });
106
+ }
107
+ }
108
+ function handleCardClick(id, ev) {
109
+ // suppress the click that fires right after a pointerup ends a drag
110
+ if (readonly || dnd?.active) return;
111
+ if (cardPopup && id != null) {
112
+ const target = ev?.target;
113
+ const el = target ? locate(target) : null;
114
+ if (el) {
115
+ overlay.handleCardPopup({
116
+ cardId: id,
117
+ element: el
118
+ });
119
+ return;
120
+ }
121
+ }
122
+ selectCard(id);
123
+ }
124
+ function handleCardKey(e) {
125
+ if (readonly) return;
126
+ e?.preventDefault();
127
+ const active = document.activeElement;
128
+ const id = active ? locateID(active) : null;
129
+ if (cardPopup && id != null && active) {
130
+ overlay.handleCardPopup({
131
+ cardId: id,
132
+ element: active
133
+ });
134
+ return;
135
+ }
136
+ selectCard(id);
137
+ }
138
+ const cardMenuConfig = $derived(cardShape?.menu ? typeof cardShape.menu === "object" ? cardShape.menu : {} : null);
139
+ let cardMenu = $state();
140
+ function handleCardMenu(id, ev) {
141
+ if (readonly || id == null || !cardMenu) return;
142
+ ev.stopPropagation();
143
+ cardMenu.show(ev, id);
144
+ }
145
+ function delegateCardClick(node) {
146
+ delegateClick(node, {
147
+ click: handleCardClick,
148
+ menu: handleCardMenu
149
+ });
150
+ }
151
+ function cardHotkeys(node) {
152
+ const destroy = hotkeys.subscribe((keys) => {
153
+ keys.configure({
154
+ enter: handleCardKey,
155
+ space: handleCardKey
156
+ }, node);
157
+ });
158
+ return { destroy };
159
+ }
160
+ $effect(() => {
161
+ scheduleColumnVisibility(virtualizeColumns, columnOverscan, fixedColumnWidth, $viewData.columns);
162
+ });
163
+ $effect(() => {
164
+ if (!scroll || !virtualizeColumns || typeof ResizeObserver === "undefined") return;
165
+ const observer = new ResizeObserver(() => scheduleColumnVisibility());
166
+ observer.observe(scroll);
167
+ return () => observer.disconnect();
168
+ });
169
+ $effect(() => {
170
+ if (!scroll) return;
171
+ updateScrollHeightVar();
172
+ window.addEventListener("resize", updateScrollHeightVar);
173
+ if (typeof ResizeObserver === "undefined") {
174
+ return () => window.removeEventListener("resize", updateScrollHeightVar);
175
+ }
176
+ const observer = new ResizeObserver(updateScrollHeightVar);
177
+ observer.observe(scroll);
178
+ return () => {
179
+ observer.disconnect();
180
+ window.removeEventListener("resize", updateScrollHeightVar);
181
+ };
182
+ });
183
+ onDestroy(() => {
184
+ if (visibilityFrame) cancelAnimationFrame(visibilityFrame);
185
+ });
186
+ </script>
187
+
188
+ <div
189
+ class="wx-kanban"
190
+ role="region"
191
+ aria-label={_("Kanban board")}
192
+ bind:this={root}
193
+ >
194
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
195
+ <div
196
+ class="wx-board"
197
+ class:wx-scroll-board={!columnScroll}
198
+ class:wx-layout-flex={!fixedColumnWidth}
199
+ use:cardDrag={{ dnd, store, readonly }}
200
+ use:delegateCardClick
201
+ use:cardHotkeys
202
+ onmousemove={tooltip ? overlay.handleTooltipMove : undefined}
203
+ onmouseleave={tooltip ? overlay.handleTooltipLeave : undefined}
204
+ >
205
+ <div
206
+ class="wx-scroll"
207
+ bind:this={scroll}
208
+ onscroll={scheduleColumnVisibility}
209
+ >
210
+ <div class="wx-content">
211
+ {#each $viewData.columns as column (column.id)}
212
+ <Column
213
+ {column}
214
+ {readonly}
215
+ {cardContent}
216
+ {cardShape}
217
+ contentVisible={isColumnContentVisible(column.id)}
218
+ requestVisible={isColumnRequestVisible(column.id)}
219
+ {virtualizeCards}
220
+ {estimatedCardHeight}
221
+ {cardOverscan}
222
+ {fixedColumnWidth}
223
+ {registerColumn}
224
+ {cardCss}
225
+ {columnCss}
226
+ />
227
+ {/each}
228
+ </div>
229
+ </div>
230
+ </div>
231
+ {#if brandmark}
232
+ <a style={brandmark.style} href={brandmark.link} target="_blank">
233
+ {brandmark.text}
234
+ </a>
235
+ {/if}
236
+ <DragGhost {root} {cardContent} {cardShape} />
237
+
238
+ {#if cardMenuConfig}
239
+ <ContextMenu
240
+ options={cardMenuConfig.options}
241
+ filter={cardMenuConfig.filter}
242
+ onclick={cardMenuConfig.onclick}
243
+ bind:this={cardMenu}
244
+ />
245
+ {/if}
246
+
247
+ {#if overlay.tooltipState && tooltip}
248
+ {@const TooltipCmp = tooltip}
249
+ <div
250
+ class="wx-tooltip"
251
+ style="position:fixed;left:{overlay.mousePos.x +
252
+ 12}px;top:{overlay.mousePos.y +
253
+ 16}px;z-index:10000;pointer-events:none"
254
+ aria-hidden="true"
255
+ >
256
+ <TooltipCmp card={overlay.tooltipState.card} />
257
+ </div>
258
+ {/if}
259
+
260
+ {#if overlay.cardPopupState && cardPopup}
261
+ {@const CardPopupCmp = cardPopup}
262
+ <Popup
263
+ at={overlay.cardPopupState.at}
264
+ parent={overlay.cardPopupState.element}
265
+ oncancel={overlay.hideCardPopup}
266
+ {...popupExtra}
267
+ >
268
+ <CardPopupCmp
269
+ card={overlay.cardPopupState.card}
270
+ close={overlay.hideCardPopup}
271
+ />
272
+ </Popup>
273
+ {/if}
274
+ </div>
275
+
276
+ <style>
277
+ .wx-kanban {
278
+ display: flex;
279
+ flex-direction: column;
280
+ height: 100%;
281
+ width: 100%;
282
+ position: relative;
283
+ background: var(--wx-kanban-bg);
284
+ overflow: hidden;
285
+ }
286
+
287
+ .wx-board {
288
+ flex: 1;
289
+ padding: 12px;
290
+ box-sizing: border-box;
291
+ min-height: 0;
292
+ }
293
+
294
+ /* the scroll wrapper sits inside the padded board, so the
295
+ padding stays at the edges and never scrolls away */
296
+ .wx-scroll {
297
+ height: 100%;
298
+ overflow-x: auto;
299
+ overflow-y: hidden;
300
+ }
301
+
302
+ .wx-content {
303
+ display: flex;
304
+ gap: 12px;
305
+ align-items: stretch;
306
+ min-height: 100%;
307
+ box-sizing: border-box;
308
+ }
309
+
310
+ .wx-board:not(.wx-scroll-board) .wx-content {
311
+ height: 100%;
312
+ min-height: 0;
313
+ }
314
+
315
+ .wx-board:not(.wx-scroll-board) :global(.wx-column:not(.wx-collapsed)) {
316
+ height: 100%;
317
+ min-height: 0;
318
+ }
319
+
320
+ .wx-board:not(.wx-scroll-board) :global(.wx-column.wx-collapsed) {
321
+ height: 100%;
322
+ min-height: 0;
323
+ }
324
+
325
+ /* board-wide vertical scroll (columnScroll: false) */
326
+ .wx-scroll-board .wx-scroll {
327
+ overflow-y: auto;
328
+ }
329
+
330
+ .wx-scroll-board :global(.wx-column) {
331
+ max-height: none;
332
+ overflow: visible;
333
+ }
334
+
335
+ .wx-scroll-board :global(.wx-column.wx-collapsed) {
336
+ position: sticky;
337
+ top: 0;
338
+ z-index: 1;
339
+ align-self: flex-start;
340
+ height: var(--wx-kanban-scroll-height, 100%);
341
+ max-height: var(--wx-kanban-scroll-height, 100%);
342
+ overflow: hidden;
343
+ }
344
+
345
+ .wx-scroll-board :global(.wx-column-cards) {
346
+ overflow: visible;
347
+ flex: none;
348
+ }
349
+
350
+ .wx-scroll-board :global(.wx-column-header) {
351
+ position: sticky;
352
+ top: 0;
353
+ z-index: 1;
354
+ background: var(--wx-kanban-column-bg);
355
+ }
356
+
357
+ /* flexible columns sharing viewport width (fixedColumnWidth: false) */
358
+ .wx-layout-flex :global(.wx-column:not(.wx-collapsed)) {
359
+ flex: 1 1 0;
360
+ min-width: 240px;
361
+ }
362
+ </style>
@@ -0,0 +1,19 @@
1
+ import type { Component } from "svelte";
2
+ import type { KanbanCard } from "@svar-ui/kanban-store";
3
+ import type { CardShape, RenderConfig, CardCssFn, ColumnCssFn } from "../types.js";
4
+ type Props = {
5
+ cardShape: CardShape;
6
+ readonly?: boolean;
7
+ render?: RenderConfig;
8
+ cardContent?: Component<{
9
+ card: KanbanCard;
10
+ cardShape: CardShape;
11
+ }>;
12
+ tooltip?: any;
13
+ cardPopup?: any;
14
+ cardCss?: CardCssFn;
15
+ columnCss?: ColumnCssFn;
16
+ };
17
+ declare const Layout: Component<Props, {}, "">;
18
+ type Layout = ReturnType<typeof Layout>;
19
+ export default Layout;
@@ -0,0 +1,97 @@
1
+ <script lang="ts">import { getContext, setContext } from "svelte";
2
+ import { readable } from "svelte/store";
3
+ import { Toolbar } from "@svar-ui/svelte-toolbar";
4
+ import { locale } from "@svar-ui/lib-dom";
5
+ import { en } from "@svar-ui/kanban-locales";
6
+ import { en as coreEn } from "@svar-ui/core-locales";
7
+ import { getToolbarItems } from "@svar-ui/kanban-store";
8
+ const sortOptions = {
9
+ "sort-label-asc": {
10
+ field: "label",
11
+ dir: "asc"
12
+ },
13
+ "sort-label-desc": {
14
+ field: "label",
15
+ dir: "desc"
16
+ },
17
+ "sort-priority-asc": {
18
+ field: "priority",
19
+ dir: "asc"
20
+ },
21
+ "sort-priority-desc": {
22
+ field: "priority",
23
+ dir: "desc"
24
+ }
25
+ };
26
+ let { api = null, items = [], undo = false, sort = false, add = true } = $props();
27
+ let l = getContext("wx-i18n");
28
+ if (!l) {
29
+ l = locale({
30
+ ...en,
31
+ ...coreEn
32
+ });
33
+ setContext("wx-i18n", l);
34
+ }
35
+ const _ = l.getGroup("kanban");
36
+ const emptyHistory = readable({
37
+ undo: 0,
38
+ redo: 0
39
+ });
40
+ let history = $derived(api ? api.getReactiveState().history : emptyHistory);
41
+ const historyActions = ["undo", "redo"];
42
+ function defaultHandler(id) {
43
+ if (!api) return;
44
+ if (id === "add-card") {
45
+ api.exec("add-card", {
46
+ card: {},
47
+ edit: true
48
+ });
49
+ } else if (id === "undo" || id === "redo") {
50
+ api.exec(id, {});
51
+ } else if (id === "sort-clear") {
52
+ api.exec("sort-cards", { sort: null });
53
+ } else if (id in sortOptions) {
54
+ api.exec("sort-cards", { sort: sortOptions[id] });
55
+ }
56
+ }
57
+ function prepareItem(item) {
58
+ const next = { ...item };
59
+ const id = typeof next.id === "string" ? next.id : "";
60
+ if (next.items) {
61
+ next.items = next.items.map(prepareItem);
62
+ }
63
+ if (next.text) next.text = _(next.text);
64
+ if (next.menuText) next.menuText = _(next.menuText);
65
+ if (next.title) next.title = _(next.title);
66
+ if (historyActions.includes(id)) {
67
+ next.disabled = id === "undo" ? !$history?.undo : !$history?.redo;
68
+ }
69
+ if (!next.handler && id) {
70
+ next.handler = () => defaultHandler(id);
71
+ }
72
+ return next;
73
+ }
74
+ const finalItems = $derived.by(() => {
75
+ const buttons = items.length ? items : getToolbarItems({
76
+ undo,
77
+ sort,
78
+ add
79
+ });
80
+ return buttons.map(prepareItem);
81
+ });
82
+ </script>
83
+
84
+ <div class="wx-root">
85
+ <Toolbar items={finalItems} />
86
+ </div>
87
+
88
+ <style>
89
+ .wx-root {
90
+ display: contents;
91
+ }
92
+
93
+ /* FIXME: separator styles are broken somehow */
94
+ .wx-root :global(.wx-toolbar > div.wx-separator) {
95
+ min-height: auto;
96
+ }
97
+ </style>
@@ -0,0 +1,12 @@
1
+ import { Toolbar } from "@svar-ui/svelte-toolbar";
2
+ import type { KanbanInstanceApi } from "../types.js";
3
+ type Props = {
4
+ api?: KanbanInstanceApi | null;
5
+ items?: any[];
6
+ add?: boolean;
7
+ undo?: boolean;
8
+ sort?: boolean;
9
+ };
10
+ declare const Toolbar: import("svelte").Component<Props, {}, "">;
11
+ type Toolbar = ReturnType<typeof Toolbar>;
12
+ export default Toolbar;
@@ -0,0 +1,24 @@
1
+ import type { TPosition } from "@svar-ui/lib-dom";
2
+ import type { CardID, KanbanCard } from "@svar-ui/kanban-store";
3
+ export type CardPopupInfo = {
4
+ cardId: CardID;
5
+ element: HTMLElement;
6
+ };
7
+ export declare function useCardOverlay(getCard: (id: CardID) => KanbanCard | undefined, popupAt?: TPosition): {
8
+ readonly tooltipState: {
9
+ card: KanbanCard;
10
+ } | null;
11
+ readonly mousePos: {
12
+ x: number;
13
+ y: number;
14
+ };
15
+ readonly cardPopupState: {
16
+ card: KanbanCard;
17
+ element: HTMLElement;
18
+ at: TPosition;
19
+ } | null;
20
+ handleTooltipMove: (e: MouseEvent) => void;
21
+ handleTooltipLeave: () => void;
22
+ handleCardPopup: (info: CardPopupInfo | null) => void;
23
+ hideCardPopup: () => void;
24
+ };
@@ -0,0 +1,60 @@
1
+ import { getID, locate } from "@svar-ui/lib-dom";
2
+ export function useCardOverlay(getCard, popupAt = "right-start") {
3
+ let _tooltipTarget = null;
4
+ let tooltipState = $state(null);
5
+ let mousePos = $state({ x: 0, y: 0 });
6
+ let cardPopupState = $state(null);
7
+ function handleTooltipMove(e) {
8
+ mousePos = { x: e.clientX, y: e.clientY };
9
+ if (cardPopupState || !e.target)
10
+ return;
11
+ const el = locate(e.target) ?? null;
12
+ if (el === _tooltipTarget)
13
+ return;
14
+ _tooltipTarget = el;
15
+ if (!el) {
16
+ tooltipState = null;
17
+ return;
18
+ }
19
+ const card = getCard(getID(el));
20
+ tooltipState = card ? { card } : null;
21
+ }
22
+ function handleTooltipLeave() {
23
+ _tooltipTarget = null;
24
+ tooltipState = null;
25
+ }
26
+ function handleCardPopup(info) {
27
+ tooltipState = null;
28
+ _tooltipTarget = null;
29
+ if (!info) {
30
+ cardPopupState = null;
31
+ return;
32
+ }
33
+ const card = getCard(info.cardId);
34
+ if (card) {
35
+ cardPopupState = {
36
+ card,
37
+ element: info.element,
38
+ at: popupAt,
39
+ };
40
+ }
41
+ }
42
+ function hideCardPopup() {
43
+ cardPopupState = null;
44
+ }
45
+ return {
46
+ get tooltipState() {
47
+ return tooltipState;
48
+ },
49
+ get mousePos() {
50
+ return mousePos;
51
+ },
52
+ get cardPopupState() {
53
+ return cardPopupState;
54
+ },
55
+ handleTooltipMove,
56
+ handleTooltipLeave,
57
+ handleCardPopup,
58
+ hideCardPopup,
59
+ };
60
+ }
@@ -0,0 +1,22 @@
1
+ import type { CardID, ColumnID } from "@svar-ui/kanban-store";
2
+ export type DndTarget = {
3
+ column: ColumnID;
4
+ beforeId: CardID | null;
5
+ };
6
+ export declare class DndState {
7
+ active: boolean;
8
+ cardId: CardID | null;
9
+ sourceColumn: ColumnID | null;
10
+ width: number;
11
+ height: number;
12
+ pointer: {
13
+ x: number;
14
+ y: number;
15
+ };
16
+ offset: {
17
+ x: number;
18
+ y: number;
19
+ };
20
+ target: DndTarget | null;
21
+ reset(): void;
22
+ }
@@ -0,0 +1,16 @@
1
+ export class DndState {
2
+ active = $state(false);
3
+ cardId = $state(null);
4
+ sourceColumn = $state(null);
5
+ width = $state(0);
6
+ height = $state(0);
7
+ pointer = $state({ x: 0, y: 0 });
8
+ offset = $state({ x: 0, y: 0 });
9
+ target = $state(null);
10
+ reset() {
11
+ this.active = false;
12
+ this.cardId = null;
13
+ this.sourceColumn = null;
14
+ this.target = null;
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ export declare const SCROLL_CONTAINER_CONTEXT: unique symbol;
2
+ export declare const KANBAN_API_CONTEXT: unique symbol;
3
+ export declare const DND_CONTEXT: unique symbol;
@@ -0,0 +1,3 @@
1
+ export const SCROLL_CONTAINER_CONTEXT = Symbol("wx/kanban-scroll-container");
2
+ export const KANBAN_API_CONTEXT = Symbol("kanban-api");
3
+ export const DND_CONTEXT = Symbol("wx/kanban-dnd");
@@ -0,0 +1,8 @@
1
+ import type { CardShape, EditorShape } from "./types.js";
2
+ export declare function getCardShape(): CardShape;
3
+ export declare function getPriorityOptions(): {
4
+ id: number;
5
+ label: string;
6
+ css: string;
7
+ }[];
8
+ export declare function getEditorItems(shape?: EditorShape | CardShape): any[];