@joewinke/jatui 0.1.11 → 0.1.20
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/README.md +123 -0
- package/package.json +2 -1
- package/src/lib/actions/railNav.ts +473 -0
- package/src/lib/components/AnnotationLayer.svelte +108 -0
- package/src/lib/components/AnnotationPanel.svelte +319 -0
- package/src/lib/components/AudioWaveform.svelte +9 -5
- package/src/lib/components/AvailabilityModal.svelte +7 -3
- package/src/lib/components/AvatarUpload.svelte +27 -4
- package/src/lib/components/BookingForm.svelte +11 -9
- package/src/lib/components/BurndownChart.svelte +778 -0
- package/src/lib/components/Button.svelte +10 -1
- package/src/lib/components/CalendarPicker.svelte +3 -3
- package/src/lib/components/Card.svelte +2 -2
- package/src/lib/components/ChipInput.svelte +8 -3
- package/src/lib/components/ColorSelector.svelte +17 -13
- package/src/lib/components/CommentThread.svelte +773 -0
- package/src/lib/components/ConfirmDialog.svelte +348 -0
- package/src/lib/components/ConfirmModal.svelte +78 -11
- package/src/lib/components/ContextMenu.svelte +59 -19
- package/src/lib/components/CountdownTimer.svelte +1 -1
- package/src/lib/components/DateRangePicker.svelte +6 -4
- package/src/lib/components/Drawer.svelte +36 -3
- package/src/lib/components/EntityPreviewCard.svelte +104 -0
- package/src/lib/components/FileDropzone.svelte +493 -0
- package/src/lib/components/FilePicker.svelte +83 -14
- package/src/lib/components/FileThumbnail.svelte +80 -0
- package/src/lib/components/FilterDropdown.svelte +11 -11
- package/src/lib/components/GPSTracker.svelte +202 -0
- package/src/lib/components/HunkDiffView.svelte +348 -0
- package/src/lib/components/ImageLightbox.svelte +274 -0
- package/src/lib/components/ImageUpload.svelte +58 -9
- package/src/lib/components/InlineEdit.svelte +6 -2
- package/src/lib/components/InputDialog.svelte +327 -0
- package/src/lib/components/KeyboardShortcutsOverlay.svelte +296 -0
- package/src/lib/components/LazyImage.svelte +1 -0
- package/src/lib/components/LinkShortener.svelte +1 -1
- package/src/lib/components/LoadingSpinner.svelte +6 -2
- package/src/lib/components/LocationMap.svelte +186 -0
- package/src/lib/components/MapView.svelte +341 -0
- package/src/lib/components/MarkupEditor.svelte +485 -0
- package/src/lib/components/MarkupOverlay.svelte +55 -0
- package/src/lib/components/MediaWorkbench.svelte +871 -0
- package/src/lib/components/MilestoneCard.svelte +1 -1
- package/src/lib/components/MilestoneTimeline.svelte +1 -1
- package/src/lib/components/Modal.svelte +39 -4
- package/src/lib/components/PDFViewer.svelte +105 -0
- package/src/lib/components/PdfThumbnail.svelte +3 -1
- package/src/lib/components/PhoneInput.svelte +1 -1
- package/src/lib/components/ResizablePanel.svelte +4 -4
- package/src/lib/components/SearchDropdown.svelte +26 -13
- package/src/lib/components/SelectInput.svelte +26 -4
- package/src/lib/components/SidebarUserFooter.svelte +1 -1
- package/src/lib/components/SignaturePad.svelte +8 -4
- package/src/lib/components/SmartImageEditor.svelte +720 -0
- package/src/lib/components/SortDropdown.svelte +9 -3
- package/src/lib/components/Sparkline.svelte +9 -0
- package/src/lib/components/StatusBadge.svelte +20 -18
- package/src/lib/components/TextArea.svelte +24 -5
- package/src/lib/components/TextInput.svelte +29 -6
- package/src/lib/components/ThemeSelector.svelte +15 -4
- package/src/lib/components/TimeSlotPicker.svelte +7 -7
- package/src/lib/components/UserAvatar.svelte +14 -1
- package/src/lib/components/VariablePicker.svelte +170 -0
- package/src/lib/components/VoicePlayer.svelte +4 -3
- package/src/lib/components/linked-columns/LinkedColumns.svelte +520 -0
- package/src/lib/components/markup.ts +287 -0
- package/src/lib/components/messaging/ChannelInfoModal.svelte +9 -9
- package/src/lib/components/messaging/ChannelList.svelte +1 -1
- package/src/lib/components/messaging/ChannelMembersModal.svelte +1 -1
- package/src/lib/components/messaging/CreateChannelModal.svelte +1 -1
- package/src/lib/components/messaging/DirectMessageList.svelte +1 -1
- package/src/lib/components/messaging/EmojiSelector.svelte +2 -1
- package/src/lib/components/messaging/MentionAutocomplete.svelte +1 -1
- package/src/lib/components/messaging/MessageAttachment.svelte +3 -3
- package/src/lib/components/messaging/MessageAttachmentUpload.svelte +3 -3
- package/src/lib/components/messaging/MessageInput.svelte +1 -1
- package/src/lib/components/messaging/MessageItem.svelte +6 -3
- package/src/lib/components/messaging/NotificationSettingsModal.svelte +1 -1
- package/src/lib/components/messaging/QuotedMessageDisplay.svelte +6 -1
- package/src/lib/components/messaging/StartDMModal.svelte +1 -1
- package/src/lib/components/pipeline/Pipeline.svelte +4 -4
- package/src/lib/components/pipeline/PipelineCard.svelte +1 -1
- package/src/lib/components/pipeline/PipelineColumn.svelte +8 -3
- package/src/lib/components/replay/ChapterTimeline.svelte +326 -0
- package/src/lib/components/session-nav/transcriptModel.ts +352 -0
- package/src/lib/index.ts +138 -0
- package/src/lib/stores/confirmDialog.svelte.ts +48 -0
- package/src/lib/stores/inputDialog.svelte.ts +51 -0
- package/src/lib/styles/rail.css +63 -0
- package/src/lib/types/annotation.ts +38 -0
- package/src/lib/types/comments.ts +97 -0
- package/src/lib/types/entityPreview.ts +45 -0
- package/src/lib/types/filePicker.ts +2 -0
- package/src/lib/types/googleMaps.d.ts +51 -0
- package/src/lib/types/maps.ts +43 -0
- package/src/lib/types/smartImageEditor.ts +39 -0
- package/src/lib/types/templateVars.ts +36 -0
- package/src/lib/utils/dateFormatters.ts +12 -10
- package/src/lib/utils/googleMapsLoader.ts +84 -0
- package/src/lib/utils/taskUtils.ts +21 -7
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template variable types — shared shape between the JST server-side registry
|
|
3
|
+
* (`src/lib/server/template-vars.ts`, `getVarsForCategory`) and the
|
|
4
|
+
* VariablePicker component.
|
|
5
|
+
*
|
|
6
|
+
* jatui cannot import the host app's `$lib/server` module (server-only), so
|
|
7
|
+
* these types are mirrored here. They are kept structurally identical to the
|
|
8
|
+
* registry's output so `getVarsForCategory(category, availableVars)` can be
|
|
9
|
+
* passed straight into `<VariablePicker groups={...} />` with no mapping —
|
|
10
|
+
* same jst↔jatui structural-compatibility pattern used by CommentThread.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** A single insertable merge variable. */
|
|
14
|
+
export interface TemplateVar {
|
|
15
|
+
/**
|
|
16
|
+
* Dotted variable path inserted into the template as `{{name}}`.
|
|
17
|
+
* e.g. `contact.name`, `org.logo_url`, `total`.
|
|
18
|
+
*/
|
|
19
|
+
name: string
|
|
20
|
+
/** Human label shown in the picker, e.g. "Contact name". */
|
|
21
|
+
label: string
|
|
22
|
+
/** Optional one-line help text describing the value. */
|
|
23
|
+
description?: string
|
|
24
|
+
/** Optional sample value shown as a hint, e.g. "Acme Inc.". */
|
|
25
|
+
example?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Variable context group, e.g. all client/org/financial/custom vars. */
|
|
29
|
+
export interface TemplateVarGroup {
|
|
30
|
+
/** Stable group id — matches VarGroupId in the host app's template-vars registry. */
|
|
31
|
+
id: string
|
|
32
|
+
/** Group heading shown in the picker, e.g. "Client". */
|
|
33
|
+
label: string
|
|
34
|
+
/** Variables in this group (never empty — empty groups are omitted). */
|
|
35
|
+
vars: TemplateVar[]
|
|
36
|
+
}
|
|
@@ -24,9 +24,11 @@ export function normalizeTimestamp(timestamp: string): string {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Parse a potentially non-standard timestamp into a Date object.
|
|
27
|
+
* Accepts a Date (returned by postgres.js), ISO string, or null/undefined.
|
|
27
28
|
*/
|
|
28
|
-
export function parseTimestamp(timestamp: string | null | undefined): Date | null {
|
|
29
|
+
export function parseTimestamp(timestamp: Date | string | null | undefined): Date | null {
|
|
29
30
|
if (!timestamp) return null;
|
|
31
|
+
if (timestamp instanceof Date) return isNaN(timestamp.getTime()) ? null : timestamp;
|
|
30
32
|
|
|
31
33
|
const normalized = normalizeTimestamp(timestamp);
|
|
32
34
|
const date = new Date(normalized);
|
|
@@ -38,7 +40,7 @@ export function parseTimestamp(timestamp: string | null | undefined): Date | nul
|
|
|
38
40
|
* Format relative time (e.g., "2d", "3mo", "1y").
|
|
39
41
|
* Compact format suitable for tables and compact UIs.
|
|
40
42
|
*/
|
|
41
|
-
export function formatRelativeTime(dateStr: string | null | undefined): string {
|
|
43
|
+
export function formatRelativeTime(dateStr: Date | string | null | undefined): string {
|
|
42
44
|
if (!dateStr) return '-';
|
|
43
45
|
|
|
44
46
|
const date = parseTimestamp(dateStr);
|
|
@@ -65,7 +67,7 @@ export function formatRelativeTime(dateStr: string | null | undefined): string {
|
|
|
65
67
|
/**
|
|
66
68
|
* Format full date and time for tooltips and detailed views.
|
|
67
69
|
*/
|
|
68
|
-
export function formatFullDate(dateStr: string | null | undefined): string {
|
|
70
|
+
export function formatFullDate(dateStr: Date | string | null | undefined): string {
|
|
69
71
|
if (!dateStr) return '';
|
|
70
72
|
|
|
71
73
|
const date = parseTimestamp(dateStr);
|
|
@@ -83,7 +85,7 @@ export function formatFullDate(dateStr: string | null | undefined): string {
|
|
|
83
85
|
/**
|
|
84
86
|
* Format short date for compact displays (e.g., date range picker).
|
|
85
87
|
*/
|
|
86
|
-
export function formatShortDate(dateStr: string | null | undefined): string {
|
|
88
|
+
export function formatShortDate(dateStr: Date | string | null | undefined): string {
|
|
87
89
|
if (!dateStr) return '';
|
|
88
90
|
|
|
89
91
|
const date = parseTimestamp(dateStr);
|
|
@@ -96,7 +98,7 @@ export function formatShortDate(dateStr: string | null | undefined): string {
|
|
|
96
98
|
* Format last activity time for agent cards.
|
|
97
99
|
* Shows "Just now", "Xm ago", "Xh ago", or "Xd ago".
|
|
98
100
|
*/
|
|
99
|
-
export function formatLastActivity(timestamp: string | null | undefined): string {
|
|
101
|
+
export function formatLastActivity(timestamp: Date | string | null | undefined): string {
|
|
100
102
|
if (!timestamp) return 'Never';
|
|
101
103
|
|
|
102
104
|
const date = parseTimestamp(timestamp);
|
|
@@ -117,7 +119,7 @@ export function formatLastActivity(timestamp: string | null | undefined): string
|
|
|
117
119
|
/**
|
|
118
120
|
* Format date for display (simple locale string).
|
|
119
121
|
*/
|
|
120
|
-
export function formatDate(dateString: string | null | undefined): string {
|
|
122
|
+
export function formatDate(dateString: Date | string | null | undefined): string {
|
|
121
123
|
if (!dateString) return 'N/A';
|
|
122
124
|
|
|
123
125
|
const date = parseTimestamp(dateString);
|
|
@@ -129,7 +131,7 @@ export function formatDate(dateString: string | null | undefined): string {
|
|
|
129
131
|
/**
|
|
130
132
|
* Get milliseconds since timestamp (for calculations).
|
|
131
133
|
*/
|
|
132
|
-
export function getTimeSinceMs(timestamp: string | null | undefined): number {
|
|
134
|
+
export function getTimeSinceMs(timestamp: Date | string | null | undefined): number {
|
|
133
135
|
if (!timestamp) return Infinity;
|
|
134
136
|
|
|
135
137
|
const date = parseTimestamp(timestamp);
|
|
@@ -141,14 +143,14 @@ export function getTimeSinceMs(timestamp: string | null | undefined): number {
|
|
|
141
143
|
/**
|
|
142
144
|
* Get minutes since timestamp.
|
|
143
145
|
*/
|
|
144
|
-
export function getTimeSinceMinutes(timestamp: string | null | undefined): number {
|
|
146
|
+
export function getTimeSinceMinutes(timestamp: Date | string | null | undefined): number {
|
|
145
147
|
return getTimeSinceMs(timestamp) / 60000;
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
/**
|
|
149
151
|
* Check if timestamp is within a given number of minutes.
|
|
150
152
|
*/
|
|
151
|
-
export function isWithinMinutes(timestamp: string | null | undefined, minutes: number): boolean {
|
|
153
|
+
export function isWithinMinutes(timestamp: Date | string | null | undefined, minutes: number): boolean {
|
|
152
154
|
return getTimeSinceMinutes(timestamp) < minutes;
|
|
153
155
|
}
|
|
154
156
|
|
|
@@ -156,7 +158,7 @@ export function isWithinMinutes(timestamp: string | null | undefined, minutes: n
|
|
|
156
158
|
* Format date + time for detail views (e.g. "Jan 5, 2:30 PM").
|
|
157
159
|
* No year — use formatFullDate when year is needed.
|
|
158
160
|
*/
|
|
159
|
-
export function formatDateTime(dateStr: string | null | undefined): string {
|
|
161
|
+
export function formatDateTime(dateStr: Date | string | null | undefined): string {
|
|
160
162
|
if (!dateStr) return '';
|
|
161
163
|
const date = parseTimestamp(dateStr);
|
|
162
164
|
if (!date) return '';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized Google Maps API loader for jatui.
|
|
3
|
+
*
|
|
4
|
+
* Prevents multiple script loads and ensures all required libraries are available.
|
|
5
|
+
* Pass the API key explicitly — jatui is SvelteKit-agnostic (no $env imports).
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* await loadGoogleMapsAPI({ apiKey: 'YOUR_KEY', libraries: ['marker', 'geometry'] })
|
|
9
|
+
* if (isGoogleMapsLoaded()) { ... }
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
interface LoadOptions {
|
|
13
|
+
apiKey: string;
|
|
14
|
+
libraries?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let loadPromise: Promise<void> | null = null;
|
|
18
|
+
let isLoaded = false;
|
|
19
|
+
|
|
20
|
+
export async function loadGoogleMapsAPI(options: LoadOptions): Promise<void> {
|
|
21
|
+
if (typeof window === 'undefined') return;
|
|
22
|
+
|
|
23
|
+
const { apiKey, libraries = [] } = options;
|
|
24
|
+
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
console.warn('googleMapsLoader: No API key provided');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If already loaded and all required libraries are available, return
|
|
31
|
+
if (isLoaded && window.google?.maps) {
|
|
32
|
+
const allLibrariesAvailable = libraries.every((lib) => {
|
|
33
|
+
switch (lib) {
|
|
34
|
+
case 'places':
|
|
35
|
+
return window.google?.maps?.places;
|
|
36
|
+
case 'geometry':
|
|
37
|
+
return window.google?.maps?.geometry;
|
|
38
|
+
default:
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (allLibrariesAvailable) return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// If already loading, return the existing promise
|
|
46
|
+
if (loadPromise) return loadPromise;
|
|
47
|
+
|
|
48
|
+
// Combine default libraries with requested ones
|
|
49
|
+
const allLibraries = Array.from(new Set(['geometry', 'places', 'marker', ...libraries]));
|
|
50
|
+
|
|
51
|
+
loadPromise = new Promise<void>((resolve, reject) => {
|
|
52
|
+
const script = document.createElement('script');
|
|
53
|
+
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=${allLibraries.join(',')}`;
|
|
54
|
+
script.async = true;
|
|
55
|
+
script.defer = true;
|
|
56
|
+
|
|
57
|
+
script.onload = () => {
|
|
58
|
+
isLoaded = true;
|
|
59
|
+
loadPromise = null;
|
|
60
|
+
resolve();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
script.onerror = (error) => {
|
|
64
|
+
loadPromise = null;
|
|
65
|
+
reject(error);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
document.head.appendChild(script);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return loadPromise;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function isGoogleMapsLoaded(): boolean {
|
|
75
|
+
return isLoaded && !!window.google?.maps;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function isPlacesLoaded(): boolean {
|
|
79
|
+
return isGoogleMapsLoaded() && !!window.google?.maps?.places;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function isGeometryLoaded(): boolean {
|
|
83
|
+
return isGoogleMapsLoaded() && !!window.google?.maps?.geometry;
|
|
84
|
+
}
|
|
@@ -6,17 +6,31 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* DaisyUI badge class for a task status value.
|
|
8
8
|
* Usage: <span class="badge {statusColor(task.status)}">...</span>
|
|
9
|
+
*
|
|
10
|
+
* Aligned to the canonical JAT TASK_STATUS palette
|
|
11
|
+
* (jat/ide/src/lib/config/statusColors.ts → TASK_STATUS_VISUALS) and the
|
|
12
|
+
* committed JST portal palette (jst/src/lib/components/portal/portalStatus.ts
|
|
13
|
+
* → TASK_BADGE) so a task renders the same semantics in JAT-style admin
|
|
14
|
+
* surfaces, the JST portal, and the JAT IDE:
|
|
15
|
+
* open=ghost(neutral) · in_progress=info(blue) · blocked=warning(amber) ·
|
|
16
|
+
* closed=success(green). Paused / mid-flight states (waiting, review) and
|
|
17
|
+
* post-completion states (submitted, accepted, deployed) use the outline
|
|
18
|
+
* variants JAT applies. Where JAT and JST agree (open/in_progress/closed/
|
|
19
|
+
* waiting), this matches both; JAT's statusColors.ts is canonical otherwise.
|
|
9
20
|
*/
|
|
10
21
|
export function statusColor(status: string): string {
|
|
11
22
|
switch (status) {
|
|
12
23
|
case 'open': return 'badge-ghost';
|
|
13
|
-
case 'in_progress': return 'badge-
|
|
14
|
-
case 'waiting': return 'badge-
|
|
15
|
-
case '
|
|
16
|
-
case '
|
|
17
|
-
case '
|
|
18
|
-
case '
|
|
19
|
-
case '
|
|
24
|
+
case 'in_progress': return 'badge-info';
|
|
25
|
+
case 'waiting': return 'badge-info badge-outline';
|
|
26
|
+
case 'review': return 'badge-info badge-outline';
|
|
27
|
+
case 'blocked': return 'badge-warning';
|
|
28
|
+
case 'submitted': return 'badge-secondary badge-outline';
|
|
29
|
+
case 'accepted': return 'badge-success badge-outline';
|
|
30
|
+
case 'deployed': return 'badge-primary badge-outline';
|
|
31
|
+
case 'rejected': return 'badge-warning badge-outline';
|
|
32
|
+
case 'reopened': return 'badge-warning badge-outline';
|
|
33
|
+
case 'closed': return 'badge-success';
|
|
20
34
|
case 'dev': return 'badge-ghost badge-outline';
|
|
21
35
|
default: return 'badge-ghost';
|
|
22
36
|
}
|