@joewinke/jatui 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/actions/collapse.js +15 -29
- package/dist/actions/listNav.js +108 -137
- package/dist/actions/railNav.js +72 -89
- package/dist/components/markup.js +59 -62
- package/dist/components/session-nav/transcriptModel.js +49 -66
- package/dist/data/emojis.js +4 -4
- package/dist/dnd/DropIndicator.svelte +119 -0
- package/dist/dnd/DropIndicator.svelte.d.ts +16 -0
- package/dist/dnd/announce.d.ts +1 -0
- package/dist/dnd/announce.js +1 -0
- package/dist/dnd/autoScroll.d.ts +7 -0
- package/dist/dnd/autoScroll.js +25 -0
- package/dist/dnd/createDndBoard.svelte.d.ts +43 -0
- package/dist/dnd/createDndBoard.svelte.js +183 -0
- package/dist/dnd/createDndBoard.test.d.ts +1 -0
- package/dist/dnd/createDndBoard.test.js +185 -0
- package/dist/dnd/draggable.d.ts +13 -0
- package/dist/dnd/draggable.js +42 -0
- package/dist/dnd/dropTarget.d.ts +14 -0
- package/dist/dnd/dropTarget.js +31 -0
- package/dist/dnd/index.d.ts +13 -0
- package/dist/dnd/index.js +9 -0
- package/dist/dnd/types.d.ts +41 -0
- package/dist/dnd/types.js +14 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/stores/confirmDialog.svelte.js +5 -5
- package/dist/stores/inputDialog.svelte.js +5 -5
- package/dist/types/booking.js +4 -4
- package/dist/types/comments.js +2 -2
- package/dist/types/messaging.js +3 -3
- package/dist/types/pipeline.js +2 -2
- package/dist/utils/currency.js +2 -4
- package/dist/utils/daisyuiColors.js +25 -27
- package/dist/utils/dateFormatters.js +44 -44
- package/dist/utils/googleMapsLoader.js +46 -100
- package/dist/utils/mentionParser.js +30 -30
- package/dist/utils/phone.js +21 -27
- package/dist/utils/phoneFormat.js +9 -9
- package/dist/utils/taskUtils.js +1 -1
- package/package.json +25 -3
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
/**
|
|
3
|
+
* Unit tests for createDndBoard internals.
|
|
4
|
+
*
|
|
5
|
+
* We can't exercise $effect/$state directly in vitest (no Svelte compiler context),
|
|
6
|
+
* so these tests validate the pure-logic layer: sequence-token rollback ordering
|
|
7
|
+
* and reseed suppression. They work by extracting the board logic functions
|
|
8
|
+
* that don't depend on runes and driving them directly.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
11
|
+
import { makeItemData, isItemData } from './types';
|
|
12
|
+
// ---- makeItemData / isItemData -------------------------------------------
|
|
13
|
+
describe('makeItemData / isItemData', () => {
|
|
14
|
+
it('round-trips through the Symbol brand', () => {
|
|
15
|
+
const data = makeItemData({ type: 'card', key: 'a', item: { id: 'a' }, container: 'col1', index: 0 });
|
|
16
|
+
expect(isItemData(data)).toBe(true);
|
|
17
|
+
expect(isItemData(data, 'card')).toBe(true);
|
|
18
|
+
expect(isItemData(data, 'other')).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it('rejects plain objects without the brand', () => {
|
|
21
|
+
expect(isItemData({ type: 'card', key: 'a' })).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
it('preserves all fields', () => {
|
|
24
|
+
const item = { id: 'x', name: 'Item X' };
|
|
25
|
+
const data = makeItemData({ type: 'board', key: 'x', item, container: 'c1', index: 2 });
|
|
26
|
+
expect(data.key).toBe('x');
|
|
27
|
+
expect(data.item).toBe(item);
|
|
28
|
+
expect(data.container).toBe('c1');
|
|
29
|
+
expect(data.index).toBe(2);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
function makeMirror(initial) {
|
|
33
|
+
const m = new Map();
|
|
34
|
+
for (const [k, v] of Object.entries(initial))
|
|
35
|
+
m.set(k, [...v]);
|
|
36
|
+
return m;
|
|
37
|
+
}
|
|
38
|
+
function applyToMirror(mirror, move, key) {
|
|
39
|
+
const fromList = [...(mirror.get(move.from.container) ?? [])];
|
|
40
|
+
const toList = move.from.container === move.to.container
|
|
41
|
+
? fromList
|
|
42
|
+
: [...(mirror.get(move.to.container) ?? [])];
|
|
43
|
+
const srcIdx = fromList.findIndex((it) => key(it) === key(move.item));
|
|
44
|
+
if (srcIdx === -1)
|
|
45
|
+
return;
|
|
46
|
+
fromList.splice(srcIdx, 1);
|
|
47
|
+
let destIdx = move.to.index;
|
|
48
|
+
if (move.from.container === move.to.container && move.to.index > move.from.index) {
|
|
49
|
+
destIdx = Math.max(0, destIdx - 1);
|
|
50
|
+
}
|
|
51
|
+
toList.splice(Math.min(destIdx, toList.length), 0, move.item);
|
|
52
|
+
mirror.set(move.from.container, fromList);
|
|
53
|
+
if (move.from.container !== move.to.container) {
|
|
54
|
+
mirror.set(move.to.container, toList);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function rollback(mirror, move, key) {
|
|
58
|
+
for (const [cid, list] of mirror) {
|
|
59
|
+
const idx = list.findIndex((it) => key(it) === key(move.item));
|
|
60
|
+
if (idx !== -1) {
|
|
61
|
+
list.splice(idx, 1);
|
|
62
|
+
mirror.set(cid, list);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const fromList = [...(mirror.get(move.from.container) ?? [])];
|
|
67
|
+
fromList.splice(Math.min(move.from.index, fromList.length), 0, move.item);
|
|
68
|
+
mirror.set(move.from.container, fromList);
|
|
69
|
+
}
|
|
70
|
+
const key = (i) => i.id;
|
|
71
|
+
const a = { id: 'a', name: 'A' };
|
|
72
|
+
const b = { id: 'b', name: 'B' };
|
|
73
|
+
const c = { id: 'c', name: 'C' };
|
|
74
|
+
describe('applyToMirror', () => {
|
|
75
|
+
it('moves item within same container (downward)', () => {
|
|
76
|
+
const mirror = makeMirror({ col: [a, b, c] });
|
|
77
|
+
applyToMirror(mirror, { item: a, from: { container: 'col', index: 0 }, to: { container: 'col', index: 2 } }, key);
|
|
78
|
+
expect(mirror.get('col')?.map(key)).toEqual(['b', 'a', 'c']);
|
|
79
|
+
});
|
|
80
|
+
it('moves item within same container (upward)', () => {
|
|
81
|
+
const mirror = makeMirror({ col: [a, b, c] });
|
|
82
|
+
applyToMirror(mirror, { item: c, from: { container: 'col', index: 2 }, to: { container: 'col', index: 0 } }, key);
|
|
83
|
+
expect(mirror.get('col')?.map(key)).toEqual(['c', 'a', 'b']);
|
|
84
|
+
});
|
|
85
|
+
it('moves item across containers', () => {
|
|
86
|
+
const mirror = makeMirror({ col1: [a, b], col2: [c] });
|
|
87
|
+
applyToMirror(mirror, { item: b, from: { container: 'col1', index: 1 }, to: { container: 'col2', index: 0 } }, key);
|
|
88
|
+
expect(mirror.get('col1')?.map(key)).toEqual(['a']);
|
|
89
|
+
expect(mirror.get('col2')?.map(key)).toEqual(['b', 'c']);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('rollback', () => {
|
|
93
|
+
it('restores item to its original position', () => {
|
|
94
|
+
const mirror = makeMirror({ col: [b, c, a] });
|
|
95
|
+
rollback(mirror, { item: a, from: { container: 'col', index: 0 } }, key);
|
|
96
|
+
expect(mirror.get('col')?.map(key)).toEqual(['a', 'b', 'c']);
|
|
97
|
+
});
|
|
98
|
+
it('restores item from a different container', () => {
|
|
99
|
+
const mirror = makeMirror({ col1: [b], col2: [a, c] });
|
|
100
|
+
rollback(mirror, { item: a, from: { container: 'col1', index: 0 } }, key);
|
|
101
|
+
expect(mirror.get('col1')?.map(key)).toEqual(['a', 'b']);
|
|
102
|
+
expect(mirror.get('col2')?.map(key)).toEqual(['c']);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('sequence-token rollback ordering', () => {
|
|
106
|
+
it('does not rollback when a newer commit has already completed', async () => {
|
|
107
|
+
const seq = new Map();
|
|
108
|
+
const mirror = makeMirror({ col1: [a, b], col2: [c] });
|
|
109
|
+
const move1 = { item: a, from: { container: 'col1', index: 0 }, to: { container: 'col2', index: 0 } };
|
|
110
|
+
const move2 = { item: a, from: { container: 'col2', index: 0 }, to: { container: 'col1', index: 0 } };
|
|
111
|
+
const token1 = (seq.get('a') ?? 0) + 1;
|
|
112
|
+
seq.set('a', token1);
|
|
113
|
+
applyToMirror(mirror, move1, key);
|
|
114
|
+
const token2 = (seq.get('a') ?? 0) + 1;
|
|
115
|
+
seq.set('a', token2);
|
|
116
|
+
applyToMirror(mirror, { ...move2, from: { container: 'col2', index: 0 } }, key);
|
|
117
|
+
const shouldRollbackMove1 = seq.get('a') === token1;
|
|
118
|
+
expect(shouldRollbackMove1).toBe(false);
|
|
119
|
+
const shouldRollbackMove2 = seq.get('a') === token2;
|
|
120
|
+
expect(shouldRollbackMove2).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
it('does rollback when this is the newest commit of the item', async () => {
|
|
123
|
+
const seq = new Map();
|
|
124
|
+
const mirror = makeMirror({ col1: [a, b], col2: [c] });
|
|
125
|
+
const move1 = { item: a, from: { container: 'col1', index: 0 }, to: { container: 'col2', index: 0 } };
|
|
126
|
+
const token1 = (seq.get('a') ?? 0) + 1;
|
|
127
|
+
seq.set('a', token1);
|
|
128
|
+
applyToMirror(mirror, move1, key);
|
|
129
|
+
const shouldRollback = seq.get('a') === token1;
|
|
130
|
+
expect(shouldRollback).toBe(true);
|
|
131
|
+
if (shouldRollback) {
|
|
132
|
+
rollback(mirror, move1, key);
|
|
133
|
+
}
|
|
134
|
+
expect(mirror.get('col1')?.map(key)).toContain('a');
|
|
135
|
+
expect(mirror.get('col2')?.map(key)).not.toContain('a');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe('reseed suppression', () => {
|
|
139
|
+
it('suppresses reseed while dragging and applies it after', () => {
|
|
140
|
+
let seedCalled = 0;
|
|
141
|
+
let dragging = true;
|
|
142
|
+
let inFlight = 0;
|
|
143
|
+
let seedQueued = false;
|
|
144
|
+
function maybeSeed() {
|
|
145
|
+
if (dragging || inFlight > 0) {
|
|
146
|
+
seedQueued = true;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
seedCalled++;
|
|
150
|
+
seedQueued = false;
|
|
151
|
+
}
|
|
152
|
+
maybeSeed();
|
|
153
|
+
expect(seedCalled).toBe(0);
|
|
154
|
+
expect(seedQueued).toBe(true);
|
|
155
|
+
dragging = false;
|
|
156
|
+
if (inFlight === 0 && seedQueued && !dragging) {
|
|
157
|
+
seedCalled++;
|
|
158
|
+
seedQueued = false;
|
|
159
|
+
}
|
|
160
|
+
expect(seedCalled).toBe(1);
|
|
161
|
+
expect(seedQueued).toBe(false);
|
|
162
|
+
});
|
|
163
|
+
it('suppresses reseed while commits in-flight and applies after all settle', () => {
|
|
164
|
+
let seedCalled = 0;
|
|
165
|
+
let dragging = false;
|
|
166
|
+
let inFlight = 2;
|
|
167
|
+
let seedQueued = false;
|
|
168
|
+
function tryFlush() {
|
|
169
|
+
if (inFlight === 0 && seedQueued && !dragging) {
|
|
170
|
+
seedCalled++;
|
|
171
|
+
seedQueued = false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (dragging || inFlight > 0) {
|
|
175
|
+
seedQueued = true;
|
|
176
|
+
}
|
|
177
|
+
expect(seedQueued).toBe(true);
|
|
178
|
+
inFlight--;
|
|
179
|
+
tryFlush();
|
|
180
|
+
expect(seedCalled).toBe(0);
|
|
181
|
+
inFlight--;
|
|
182
|
+
tryFlush();
|
|
183
|
+
expect(seedCalled).toBe(1);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DragData } from './types';
|
|
2
|
+
export interface DraggableParams<TData extends DragData = DragData> {
|
|
3
|
+
data: () => TData;
|
|
4
|
+
disabled?: () => boolean;
|
|
5
|
+
dragHandle?: Element;
|
|
6
|
+
preview?: (container: HTMLElement, data: TData) => () => void;
|
|
7
|
+
onDragStart?: (data: TData) => void;
|
|
8
|
+
onDrop?: (data: TData) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const draggable: <TData extends DragData>(node: HTMLElement, params: DraggableParams<TData>) => {
|
|
11
|
+
update(next: DraggableParams<TData>): void;
|
|
12
|
+
destroy: () => void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { draggable as registerDraggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
2
|
+
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
3
|
+
export const draggable = ((node, params) => {
|
|
4
|
+
let current = params;
|
|
5
|
+
let cleanup;
|
|
6
|
+
function register() {
|
|
7
|
+
cleanup = registerDraggable({
|
|
8
|
+
element: node,
|
|
9
|
+
dragHandle: current.dragHandle,
|
|
10
|
+
canDrag: () => !(current.disabled?.() ?? false),
|
|
11
|
+
getInitialData: () => current.data(),
|
|
12
|
+
onGenerateDragPreview({ source, nativeSetDragImage }) {
|
|
13
|
+
if (!current.preview)
|
|
14
|
+
return;
|
|
15
|
+
setCustomNativeDragPreview({
|
|
16
|
+
render: ({ container }) => current.preview(container, source.data),
|
|
17
|
+
nativeSetDragImage,
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
onDragStart({ source }) {
|
|
21
|
+
node.dataset.dragging = 'true';
|
|
22
|
+
current.onDragStart?.(source.data);
|
|
23
|
+
},
|
|
24
|
+
onDrop({ source }) {
|
|
25
|
+
delete node.dataset.dragging;
|
|
26
|
+
current.onDrop?.(source.data);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
register();
|
|
31
|
+
return {
|
|
32
|
+
update(next) {
|
|
33
|
+
const handleChanged = next.dragHandle !== current.dragHandle;
|
|
34
|
+
current = next;
|
|
35
|
+
if (handleChanged) {
|
|
36
|
+
cleanup();
|
|
37
|
+
register();
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
destroy: () => cleanup(),
|
|
41
|
+
};
|
|
42
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DragData, TargetFeedback } from './types';
|
|
2
|
+
export interface DropTargetParams<TSelf extends DragData = DragData> {
|
|
3
|
+
data: (feedback: TargetFeedback) => TSelf;
|
|
4
|
+
accepts?: (source: Record<string | symbol, unknown>) => boolean;
|
|
5
|
+
sticky?: boolean;
|
|
6
|
+
onEnter?: (source: Record<string | symbol, unknown>) => void;
|
|
7
|
+
onLeave?: () => void;
|
|
8
|
+
onMove?: (self: TSelf, source: Record<string | symbol, unknown>) => void;
|
|
9
|
+
onDropped?: (self: TSelf, source: Record<string | symbol, unknown>) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const dropTarget: <TSelf extends DragData>(node: HTMLElement, params: DropTargetParams<TSelf>) => {
|
|
12
|
+
update(next: DropTargetParams<TSelf>): void;
|
|
13
|
+
destroy: import("@atlaskit/pragmatic-drag-and-drop/dist/types/internal-types").CleanupFn;
|
|
14
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
2
|
+
export const dropTarget = ((node, params) => {
|
|
3
|
+
let current = params;
|
|
4
|
+
const cleanup = dropTargetForElements({
|
|
5
|
+
element: node,
|
|
6
|
+
getData: ({ input, element, source }) => current.data({ input, element, source }),
|
|
7
|
+
canDrop: ({ source }) => current.accepts?.(source.data) ?? true,
|
|
8
|
+
getIsSticky: () => current.sticky ?? false,
|
|
9
|
+
onDragEnter({ source }) {
|
|
10
|
+
node.dataset.dropOver = 'true';
|
|
11
|
+
current.onEnter?.(source.data);
|
|
12
|
+
},
|
|
13
|
+
onDragLeave() {
|
|
14
|
+
delete node.dataset.dropOver;
|
|
15
|
+
current.onLeave?.();
|
|
16
|
+
},
|
|
17
|
+
onDrag({ self, source }) {
|
|
18
|
+
current.onMove?.(self.data, source.data);
|
|
19
|
+
},
|
|
20
|
+
onDrop({ self, source }) {
|
|
21
|
+
delete node.dataset.dropOver;
|
|
22
|
+
current.onDropped?.(self.data, source.data);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
update(next) {
|
|
27
|
+
current = next;
|
|
28
|
+
},
|
|
29
|
+
destroy: cleanup,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { draggable } from './draggable';
|
|
2
|
+
export type { DraggableParams } from './draggable';
|
|
3
|
+
export { dropTarget } from './dropTarget';
|
|
4
|
+
export type { DropTargetParams } from './dropTarget';
|
|
5
|
+
export { createDndBoard } from './createDndBoard.svelte';
|
|
6
|
+
export type { BoardMove, DndBoardOptions } from './createDndBoard.svelte';
|
|
7
|
+
export { default as DropIndicator } from './DropIndicator.svelte';
|
|
8
|
+
export { autoScroll } from './autoScroll';
|
|
9
|
+
export type { AutoScrollParams } from './autoScroll';
|
|
10
|
+
export { announce, cleanupAnnouncements } from './announce';
|
|
11
|
+
export { makeItemData, isItemData } from './types';
|
|
12
|
+
export type { DragData, ItemDragData, ContainerDropData, TargetFeedback, Edge } from './types';
|
|
13
|
+
export { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { draggable } from './draggable';
|
|
2
|
+
export { dropTarget } from './dropTarget';
|
|
3
|
+
export { createDndBoard } from './createDndBoard.svelte';
|
|
4
|
+
export { default as DropIndicator } from './DropIndicator.svelte';
|
|
5
|
+
export { autoScroll } from './autoScroll';
|
|
6
|
+
export { announce, cleanupAnnouncements } from './announce';
|
|
7
|
+
export { makeItemData, isItemData } from './types';
|
|
8
|
+
// Low-level pdnd primitives re-exported to let host code avoid direct @atlaskit imports
|
|
9
|
+
export { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Input } from '@atlaskit/pragmatic-drag-and-drop/types';
|
|
2
|
+
export interface DragData extends Record<string | symbol, unknown> {
|
|
3
|
+
readonly type: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Module-scoped Symbol brand for board-managed items.
|
|
7
|
+
* ⚠ Symbol identity = module identity. Two copies of this module on one page makes
|
|
8
|
+
* isItemData() return false across the boundary — dnd/ must exist EXACTLY ONCE.
|
|
9
|
+
* Declare all @atlaskit/pragmatic-drag-and-drop* packages as peerDependencies in
|
|
10
|
+
* the host app (host owns the single instance).
|
|
11
|
+
*/
|
|
12
|
+
declare const ITEM: unique symbol;
|
|
13
|
+
export interface ItemDragData<TItem = unknown> extends DragData {
|
|
14
|
+
readonly [ITEM]: true;
|
|
15
|
+
readonly key: string;
|
|
16
|
+
readonly item: TItem;
|
|
17
|
+
readonly container: string;
|
|
18
|
+
readonly index: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ItemDragDataInput<TItem = unknown> {
|
|
21
|
+
type: string;
|
|
22
|
+
key: string;
|
|
23
|
+
item: TItem;
|
|
24
|
+
container: string;
|
|
25
|
+
index: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function makeItemData<TItem>(args: ItemDragDataInput<TItem>): ItemDragData<TItem>;
|
|
28
|
+
export declare function isItemData<TItem = unknown>(data: Record<string | symbol, unknown>, type?: string): data is ItemDragData<TItem>;
|
|
29
|
+
export interface ContainerDropData extends DragData {
|
|
30
|
+
readonly container: string;
|
|
31
|
+
readonly index?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface TargetFeedback {
|
|
34
|
+
input: Input;
|
|
35
|
+
element: Element;
|
|
36
|
+
source: {
|
|
37
|
+
element: HTMLElement;
|
|
38
|
+
data: Record<string | symbol, unknown>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-scoped Symbol brand for board-managed items.
|
|
3
|
+
* ⚠ Symbol identity = module identity. Two copies of this module on one page makes
|
|
4
|
+
* isItemData() return false across the boundary — dnd/ must exist EXACTLY ONCE.
|
|
5
|
+
* Declare all @atlaskit/pragmatic-drag-and-drop* packages as peerDependencies in
|
|
6
|
+
* the host app (host owns the single instance).
|
|
7
|
+
*/
|
|
8
|
+
const ITEM = Symbol('jatui-dnd-item');
|
|
9
|
+
export function makeItemData(args) {
|
|
10
|
+
return { ...args, [ITEM]: true };
|
|
11
|
+
}
|
|
12
|
+
export function isItemData(data, type) {
|
|
13
|
+
return data[ITEM] === true && (type === undefined || data.type === type);
|
|
14
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -142,3 +142,8 @@ export { default as LocationMap } from './components/LocationMap.svelte';
|
|
|
142
142
|
export { default as GPSTracker } from './components/GPSTracker.svelte';
|
|
143
143
|
export type { MapJob, MapAgent } from './types/maps';
|
|
144
144
|
export { loadGoogleMapsAPI, isGoogleMapsLoaded, isPlacesLoaded, isGeometryLoaded, } from './utils/googleMapsLoader';
|
|
145
|
+
export { draggable, dropTarget, autoScroll, announce, cleanupAnnouncements, monitorForElements, } from './dnd/index';
|
|
146
|
+
export { createDndBoard } from './dnd/createDndBoard.svelte';
|
|
147
|
+
export { default as DropIndicator } from './dnd/DropIndicator.svelte';
|
|
148
|
+
export { makeItemData, isItemData } from './dnd/types';
|
|
149
|
+
export type { DragData, ItemDragData, ContainerDropData, TargetFeedback, Edge, DraggableParams, DropTargetParams, AutoScrollParams, BoardMove, DndBoardOptions, } from './dnd/index';
|
package/dist/index.js
CHANGED
|
@@ -141,3 +141,8 @@ export { default as LocationMap } from './components/LocationMap.svelte';
|
|
|
141
141
|
export { default as GPSTracker } from './components/GPSTracker.svelte';
|
|
142
142
|
// Utilities — Google Maps loader
|
|
143
143
|
export { loadGoogleMapsAPI, isGoogleMapsLoaded, isPlacesLoaded, isGeometryLoaded, } from './utils/googleMapsLoader';
|
|
144
|
+
// DnD — pragmatic-drag-and-drop wrappers (peerDep: @atlaskit/pragmatic-drag-and-drop*)
|
|
145
|
+
export { draggable, dropTarget, autoScroll, announce, cleanupAnnouncements, monitorForElements, } from './dnd/index';
|
|
146
|
+
export { createDndBoard } from './dnd/createDndBoard.svelte';
|
|
147
|
+
export { default as DropIndicator } from './dnd/DropIndicator.svelte';
|
|
148
|
+
export { makeItemData, isItemData } from './dnd/types';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Global promise-based confirm dialog.
|
|
3
3
|
* Usage: const ok = await showConfirm({ title: '...', body: '...' })
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
let pending = $state(null);
|
|
6
6
|
export function getPending() {
|
|
7
7
|
return pending;
|
|
8
8
|
}
|
|
@@ -11,21 +11,21 @@ export function showConfirm(options) {
|
|
|
11
11
|
if (pending) {
|
|
12
12
|
pending.resolve(false);
|
|
13
13
|
}
|
|
14
|
-
return new Promise(
|
|
15
|
-
pending = { options
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
pending = { options, resolve };
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
export function confirmDialog() {
|
|
19
19
|
if (!pending)
|
|
20
20
|
return;
|
|
21
|
-
|
|
21
|
+
const p = pending;
|
|
22
22
|
pending = null;
|
|
23
23
|
p.resolve(true);
|
|
24
24
|
}
|
|
25
25
|
export function cancelDialog() {
|
|
26
26
|
if (!pending)
|
|
27
27
|
return;
|
|
28
|
-
|
|
28
|
+
const p = pending;
|
|
29
29
|
pending = null;
|
|
30
30
|
p.resolve(false);
|
|
31
31
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Usage: const value = await showInput({ title: '...', placeholder: '...' })
|
|
4
4
|
* Returns the typed string if confirmed, null if cancelled.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
let pending = $state(null);
|
|
7
7
|
export function getPendingInput() {
|
|
8
8
|
return pending;
|
|
9
9
|
}
|
|
@@ -12,21 +12,21 @@ export function showInput(options) {
|
|
|
12
12
|
if (pending) {
|
|
13
13
|
pending.resolve(null);
|
|
14
14
|
}
|
|
15
|
-
return new Promise(
|
|
16
|
-
pending = { options
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
pending = { options, resolve };
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
export function submitInput(value) {
|
|
20
20
|
if (!pending)
|
|
21
21
|
return;
|
|
22
|
-
|
|
22
|
+
const p = pending;
|
|
23
23
|
pending = null;
|
|
24
24
|
p.resolve(value);
|
|
25
25
|
}
|
|
26
26
|
export function cancelInput() {
|
|
27
27
|
if (!pending)
|
|
28
28
|
return;
|
|
29
|
-
|
|
29
|
+
const p = pending;
|
|
30
30
|
pending = null;
|
|
31
31
|
p.resolve(null);
|
|
32
32
|
}
|
package/dist/types/booking.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Booking System Types
|
|
2
2
|
// Generic types for scheduling/booking UI components
|
|
3
3
|
// Day of week helpers
|
|
4
|
-
export
|
|
4
|
+
export const DAYS_OF_WEEK = [
|
|
5
5
|
'Sunday',
|
|
6
6
|
'Monday',
|
|
7
7
|
'Tuesday',
|
|
@@ -10,14 +10,14 @@ export var DAYS_OF_WEEK = [
|
|
|
10
10
|
'Friday',
|
|
11
11
|
'Saturday'
|
|
12
12
|
];
|
|
13
|
-
export
|
|
13
|
+
export const DAYS_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
14
14
|
// Location type display
|
|
15
|
-
export
|
|
15
|
+
export const LOCATION_LABELS = {
|
|
16
16
|
remote: 'Video Call',
|
|
17
17
|
phone: 'Phone Call',
|
|
18
18
|
in_person: 'In Person'
|
|
19
19
|
};
|
|
20
|
-
export
|
|
20
|
+
export const LOCATION_ICONS = {
|
|
21
21
|
remote: 'video',
|
|
22
22
|
phone: 'phone',
|
|
23
23
|
in_person: 'map-pin'
|
package/dist/types/comments.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// Threading is ONE level deep on the data side: a comment is either
|
|
7
7
|
// top-level (`parent_id === null`) or a single-level reply. The UI renders
|
|
8
8
|
// this as two visual levels (a comment and its replies).
|
|
9
|
-
export
|
|
9
|
+
export const COMMENT_ENTITY_TYPES = [
|
|
10
10
|
'project',
|
|
11
11
|
'invoice',
|
|
12
12
|
'contract',
|
|
@@ -16,7 +16,7 @@ export var COMMENT_ENTITY_TYPES = [
|
|
|
16
16
|
'milestone',
|
|
17
17
|
'contract_term'
|
|
18
18
|
];
|
|
19
|
-
export
|
|
19
|
+
export const COMMENT_VISIBILITIES = [
|
|
20
20
|
'internal',
|
|
21
21
|
'client'
|
|
22
22
|
];
|
package/dist/types/messaging.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Messaging System Types
|
|
2
2
|
// Generic types for messaging UI components — no framework or backend dependencies
|
|
3
3
|
// ─── Emoji Data Constants ─────────────────────────────────────────────
|
|
4
|
-
export
|
|
4
|
+
export const EMOJI_CATEGORIES = [
|
|
5
5
|
{ id: 'search', name: 'Search', icon: '🔍', description: 'Search results' },
|
|
6
6
|
{
|
|
7
7
|
id: 'frequently_used',
|
|
@@ -59,7 +59,7 @@ export var EMOJI_CATEGORIES = [
|
|
|
59
59
|
description: 'Organization custom emojis'
|
|
60
60
|
}
|
|
61
61
|
];
|
|
62
|
-
export
|
|
62
|
+
export const SKIN_TONES = [
|
|
63
63
|
{ id: 'default', name: 'Default', unicode: '', preview: '👋' },
|
|
64
64
|
{ id: 'light', name: 'Light', unicode: '🏻', preview: '👋🏻' },
|
|
65
65
|
{ id: 'medium-light', name: 'Medium Light', unicode: '🏼', preview: '👋🏼' },
|
|
@@ -68,7 +68,7 @@ export var SKIN_TONES = [
|
|
|
68
68
|
{ id: 'dark', name: 'Dark', unicode: '🏿', preview: '👋🏿' }
|
|
69
69
|
];
|
|
70
70
|
// Default quick-reaction emojis (used when no user preferences available)
|
|
71
|
-
export
|
|
71
|
+
export const DEFAULT_QUICK_REACTIONS = [
|
|
72
72
|
{
|
|
73
73
|
unicode: '👍',
|
|
74
74
|
name: 'Thumbs Up',
|
package/dist/types/pipeline.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// ─── Core Stage/Column Types ───
|
|
2
2
|
// ─── Defaults ───
|
|
3
|
-
export
|
|
3
|
+
export const DEFAULT_DRAG_CONFIG = {
|
|
4
4
|
enabled: true,
|
|
5
5
|
flipDurationMs: 200,
|
|
6
6
|
dropTargetClass: 'outline-dashed outline-2 outline-base-content/20'
|
|
7
7
|
};
|
|
8
|
-
export
|
|
8
|
+
export const DEFAULT_PIPELINE_CONFIG = {
|
|
9
9
|
views: ['kanban'],
|
|
10
10
|
defaultView: 'kanban',
|
|
11
11
|
drag: DEFAULT_DRAG_CONFIG,
|
package/dist/utils/currency.js
CHANGED
|
@@ -5,12 +5,10 @@
|
|
|
5
5
|
* Format a number as USD currency string.
|
|
6
6
|
* Override locale/currency by passing options.
|
|
7
7
|
*/
|
|
8
|
-
export function formatCurrency(amount, locale, currency) {
|
|
9
|
-
if (locale === void 0) { locale = 'en-US'; }
|
|
10
|
-
if (currency === void 0) { currency = 'USD'; }
|
|
8
|
+
export function formatCurrency(amount, locale = 'en-US', currency = 'USD') {
|
|
11
9
|
return new Intl.NumberFormat(locale, {
|
|
12
10
|
style: 'currency',
|
|
13
|
-
currency
|
|
11
|
+
currency,
|
|
14
12
|
minimumFractionDigits: 2,
|
|
15
13
|
maximumFractionDigits: 2
|
|
16
14
|
}).format(amount);
|