@joewinke/jatui 0.1.23 → 0.1.24

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 (124) hide show
  1. package/CLAUDE.md +244 -0
  2. package/package.json +23 -10
  3. package/src/lib/actions/collapse.ts +0 -136
  4. package/src/lib/actions/railNav.ts +0 -473
  5. package/src/lib/components/AnnotationLayer.svelte +0 -108
  6. package/src/lib/components/AnnotationPanel.svelte +0 -319
  7. package/src/lib/components/AudioWaveform.svelte +0 -698
  8. package/src/lib/components/AvailabilityModal.svelte +0 -177
  9. package/src/lib/components/AvatarUpload.svelte +0 -234
  10. package/src/lib/components/Badge.svelte +0 -38
  11. package/src/lib/components/BookingForm.svelte +0 -278
  12. package/src/lib/components/BurndownChart.svelte +0 -778
  13. package/src/lib/components/Button.svelte +0 -81
  14. package/src/lib/components/CalendarPicker.svelte +0 -284
  15. package/src/lib/components/Card.svelte +0 -67
  16. package/src/lib/components/CharacterCounter.svelte +0 -82
  17. package/src/lib/components/ChipInput.svelte +0 -609
  18. package/src/lib/components/Collapse.svelte +0 -82
  19. package/src/lib/components/ColorSelector.svelte +0 -167
  20. package/src/lib/components/CommentThread.svelte +0 -773
  21. package/src/lib/components/ConfirmDialog.svelte +0 -348
  22. package/src/lib/components/ConfirmModal.svelte +0 -142
  23. package/src/lib/components/ContextMenu.svelte +0 -188
  24. package/src/lib/components/CountdownTimer.svelte +0 -94
  25. package/src/lib/components/DateRangePicker.svelte +0 -194
  26. package/src/lib/components/Drawer.svelte +0 -143
  27. package/src/lib/components/EmojiPicker.svelte +0 -159
  28. package/src/lib/components/EntityPreviewCard.svelte +0 -104
  29. package/src/lib/components/FileDropzone.svelte +0 -493
  30. package/src/lib/components/FilePicker.svelte +0 -488
  31. package/src/lib/components/FileThumbnail.svelte +0 -80
  32. package/src/lib/components/FilterDropdown.svelte +0 -203
  33. package/src/lib/components/FloatingActionBar.svelte +0 -354
  34. package/src/lib/components/GPSTracker.svelte +0 -202
  35. package/src/lib/components/HunkDiffView.svelte +0 -348
  36. package/src/lib/components/ImageLightbox.svelte +0 -274
  37. package/src/lib/components/ImageUpload.svelte +0 -147
  38. package/src/lib/components/InlineEdit.svelte +0 -291
  39. package/src/lib/components/InputDialog.svelte +0 -327
  40. package/src/lib/components/KeyboardShortcutsOverlay.svelte +0 -296
  41. package/src/lib/components/LazyImage.svelte +0 -123
  42. package/src/lib/components/LinkShortener.svelte +0 -274
  43. package/src/lib/components/LoadingSpinner.svelte +0 -106
  44. package/src/lib/components/LocationMap.svelte +0 -186
  45. package/src/lib/components/MapView.svelte +0 -341
  46. package/src/lib/components/MarkupEditor.svelte +0 -485
  47. package/src/lib/components/MarkupOverlay.svelte +0 -55
  48. package/src/lib/components/MediaWorkbench.svelte +0 -871
  49. package/src/lib/components/MilestoneCard.svelte +0 -98
  50. package/src/lib/components/MilestoneTimeline.svelte +0 -91
  51. package/src/lib/components/Modal.svelte +0 -244
  52. package/src/lib/components/PDFViewer.svelte +0 -105
  53. package/src/lib/components/PdfThumbnail.svelte +0 -63
  54. package/src/lib/components/PhoneInput.svelte +0 -212
  55. package/src/lib/components/ResizableDivider.svelte +0 -307
  56. package/src/lib/components/ResizablePanel.svelte +0 -305
  57. package/src/lib/components/SearchDropdown.svelte +0 -421
  58. package/src/lib/components/SelectInput.svelte +0 -237
  59. package/src/lib/components/SidebarUserFooter.svelte +0 -34
  60. package/src/lib/components/SignaturePad.svelte +0 -175
  61. package/src/lib/components/SmartImageEditor.svelte +0 -720
  62. package/src/lib/components/SortDropdown.svelte +0 -156
  63. package/src/lib/components/Sparkline.svelte +0 -116
  64. package/src/lib/components/SpeechForm.svelte +0 -114
  65. package/src/lib/components/StatusBadge.svelte +0 -157
  66. package/src/lib/components/TaskTypeIcon.svelte +0 -54
  67. package/src/lib/components/TextArea.svelte +0 -162
  68. package/src/lib/components/TextInput.svelte +0 -131
  69. package/src/lib/components/ThemeSelector.svelte +0 -206
  70. package/src/lib/components/TimeSlotPicker.svelte +0 -162
  71. package/src/lib/components/UserAvatar.svelte +0 -72
  72. package/src/lib/components/VariablePicker.svelte +0 -170
  73. package/src/lib/components/VoicePlayer.svelte +0 -422
  74. package/src/lib/components/linked-columns/LinkedColumns.svelte +0 -526
  75. package/src/lib/components/markup.ts +0 -287
  76. package/src/lib/components/messaging/Avatar.svelte +0 -81
  77. package/src/lib/components/messaging/ChannelInfoModal.svelte +0 -163
  78. package/src/lib/components/messaging/ChannelList.svelte +0 -107
  79. package/src/lib/components/messaging/ChannelMemberAvatarStack.svelte +0 -69
  80. package/src/lib/components/messaging/ChannelMembersModal.svelte +0 -182
  81. package/src/lib/components/messaging/CreateChannelModal.svelte +0 -190
  82. package/src/lib/components/messaging/DirectMessageList.svelte +0 -145
  83. package/src/lib/components/messaging/EmojiSelector.svelte +0 -261
  84. package/src/lib/components/messaging/MentionAutocomplete.svelte +0 -193
  85. package/src/lib/components/messaging/MessageAttachment.svelte +0 -273
  86. package/src/lib/components/messaging/MessageAttachmentUpload.svelte +0 -243
  87. package/src/lib/components/messaging/MessageInput.svelte +0 -452
  88. package/src/lib/components/messaging/MessageItem.svelte +0 -341
  89. package/src/lib/components/messaging/MessageThread.svelte +0 -306
  90. package/src/lib/components/messaging/NotificationSettingsModal.svelte +0 -234
  91. package/src/lib/components/messaging/QuotedMessageDisplay.svelte +0 -123
  92. package/src/lib/components/messaging/StartDMModal.svelte +0 -100
  93. package/src/lib/components/messaging/ThreadPanel.svelte +0 -153
  94. package/src/lib/components/pipeline/DESIGN.md +0 -361
  95. package/src/lib/components/pipeline/Pipeline.svelte +0 -391
  96. package/src/lib/components/pipeline/PipelineCard.svelte +0 -94
  97. package/src/lib/components/pipeline/PipelineColumn.svelte +0 -163
  98. package/src/lib/components/replay/ChapterTimeline.svelte +0 -326
  99. package/src/lib/components/session-nav/transcriptModel.ts +0 -352
  100. package/src/lib/data/emojis.ts +0 -1208
  101. package/src/lib/index.ts +0 -405
  102. package/src/lib/stores/confirmDialog.svelte.ts +0 -48
  103. package/src/lib/stores/inputDialog.svelte.ts +0 -51
  104. package/src/lib/styles/rail.css +0 -63
  105. package/src/lib/types/annotation.ts +0 -38
  106. package/src/lib/types/booking.ts +0 -143
  107. package/src/lib/types/comments.ts +0 -97
  108. package/src/lib/types/entityPreview.ts +0 -45
  109. package/src/lib/types/filePicker.ts +0 -16
  110. package/src/lib/types/googleMaps.d.ts +0 -51
  111. package/src/lib/types/maps.ts +0 -43
  112. package/src/lib/types/messaging.ts +0 -459
  113. package/src/lib/types/milestone.ts +0 -22
  114. package/src/lib/types/pipeline.ts +0 -150
  115. package/src/lib/types/smartImageEditor.ts +0 -39
  116. package/src/lib/types/templateVars.ts +0 -36
  117. package/src/lib/utils/currency.ts +0 -20
  118. package/src/lib/utils/daisyuiColors.ts +0 -243
  119. package/src/lib/utils/dateFormatters.ts +0 -196
  120. package/src/lib/utils/googleMapsLoader.ts +0 -84
  121. package/src/lib/utils/mentionParser.ts +0 -188
  122. package/src/lib/utils/phone.ts +0 -80
  123. package/src/lib/utils/phoneFormat.ts +0 -74
  124. package/src/lib/utils/taskUtils.ts +0 -75
@@ -1,237 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * SelectInput Component
4
- *
5
- * Dropdown select with searchable mode, grouped options, and validation.
6
- * Converted from Svelte 4 to Svelte 5 runes.
7
- */
8
-
9
- import { onMount } from 'svelte';
10
-
11
- export interface SelectOption {
12
- value: string | number;
13
- label: string;
14
- disabled?: boolean;
15
- group?: string;
16
- }
17
-
18
- interface Props {
19
- label: string;
20
- value?: string | number;
21
- options?: SelectOption[];
22
- placeholder?: string;
23
- required?: boolean;
24
- disabled?: boolean;
25
- searchable?: boolean;
26
- error?: string;
27
- helpText?: string;
28
- size?: 'sm' | 'md' | 'lg';
29
- class?: string;
30
- id?: string;
31
- name?: string;
32
- clearSearchOnSelect?: boolean;
33
- onchange?: (value: string | number, option: SelectOption | undefined) => void;
34
- }
35
-
36
- let {
37
- label,
38
- value = $bindable(''),
39
- options = [],
40
- placeholder = 'Select an option',
41
- required = false,
42
- disabled = false,
43
- searchable = false,
44
- error = '',
45
- helpText = '',
46
- size = 'md',
47
- class: className = '',
48
- id = `select-input-${Math.random().toString(36).substr(2, 9)}`,
49
- name = '',
50
- clearSearchOnSelect = true,
51
- onchange
52
- }: Props = $props();
53
-
54
- let searchTerm = $state('');
55
- let isOpen = $state(false);
56
- let selectElement: HTMLElement | undefined = $state();
57
-
58
- const sizeClass = $derived({ sm: 'select-sm', md: '', lg: 'select-lg' }[size]);
59
-
60
- const selectClass = $derived(
61
- ['select select-bordered w-full', sizeClass, error ? 'select-error' : '', disabled ? 'select-disabled' : '', className]
62
- .filter(Boolean)
63
- .join(' ')
64
- );
65
-
66
- const filteredOptions = $derived(
67
- searchable && searchTerm
68
- ? options.filter((o) => o.label.toLowerCase().includes(searchTerm.toLowerCase()))
69
- : options
70
- );
71
-
72
- const selectedOption = $derived(options.find((o) => o.value === value));
73
-
74
- const groupedOptions = $derived(
75
- filteredOptions.reduce(
76
- (acc, option) => {
77
- const group = option.group || 'default';
78
- if (!acc[group]) acc[group] = [];
79
- acc[group].push(option);
80
- return acc;
81
- },
82
- {} as Record<string, SelectOption[]>
83
- )
84
- );
85
-
86
- function handleSelect(option: SelectOption) {
87
- if (option.disabled) return;
88
- value = option.value;
89
- onchange?.(value, option);
90
- if (clearSearchOnSelect) searchTerm = '';
91
- isOpen = false;
92
- }
93
-
94
- function handleKeydown(event: KeyboardEvent) {
95
- if (event.key === 'Escape') {
96
- isOpen = false;
97
- searchTerm = '';
98
- }
99
- }
100
-
101
- function handleClickOutside(event: Event) {
102
- if (selectElement && !selectElement.contains(event.target as Node)) {
103
- isOpen = false;
104
- searchTerm = '';
105
- }
106
- }
107
-
108
- function handleNativeChange(e: Event) {
109
- const target = e.currentTarget as HTMLSelectElement;
110
- const option = options.find((opt) => opt.value.toString() === target.value);
111
- onchange?.(value!, option);
112
- }
113
-
114
- onMount(() => {
115
- document.addEventListener('click', handleClickOutside);
116
- return () => document.removeEventListener('click', handleClickOutside);
117
- });
118
-
119
- // Error-state shake (transitions.dev). Shakes the whole control wrapper when
120
- // `error` becomes set. See TextInput for the rationale.
121
- let hadError = false;
122
- $effect(() => {
123
- const hasError = !!error;
124
- if (hasError && !hadError && selectElement) {
125
- const reduce =
126
- typeof window !== 'undefined' &&
127
- window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
128
- if (!reduce) {
129
- selectElement.classList.remove('t-input-shake');
130
- void selectElement.offsetWidth;
131
- selectElement.classList.add('t-input-shake');
132
- }
133
- }
134
- hadError = hasError;
135
- });
136
- </script>
137
-
138
- <div
139
- class="form-control w-full"
140
- bind:this={selectElement}
141
- onanimationend={() => selectElement?.classList.remove('t-input-shake')}
142
- >
143
- <label for={id} class="label">
144
- <span class="text-[0.8125rem] font-medium text-base-content/85">
145
- {label}
146
- {#if required}
147
- <span class="text-error ml-1">*</span>
148
- {/if}
149
- </span>
150
- </label>
151
-
152
- {#if searchable}
153
- <div class="dropdown w-full {isOpen ? 'dropdown-open' : ''}">
154
- <div tabindex="0" role="button" class="btn btn-outline w-full justify-between {sizeClass}">
155
- <input
156
- {id}
157
- {name}
158
- type="text"
159
- placeholder={selectedOption?.label || placeholder}
160
- bind:value={searchTerm}
161
- onfocus={() => (isOpen = true)}
162
- onkeydown={handleKeydown}
163
- class="input input-ghost w-full p-0 h-auto min-h-0 focus:outline-none"
164
- {disabled}
165
- {required}
166
- aria-describedby={error ? `${id}-error` : helpText ? `${id}-help` : undefined}
167
- aria-invalid={error ? 'true' : 'false'}
168
- />
169
- <svg class="w-4 h-4 opacity-70" fill="none" stroke="currentColor" viewBox="0 0 24 24">
170
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
171
- </svg>
172
- </div>
173
-
174
- {#if isOpen}
175
- <div class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-full max-h-60 overflow-auto">
176
- {#each Object.entries(groupedOptions) as [groupName, groupOpts]}
177
- {#if groupName !== 'default'}
178
- <div class="menu-title"><span>{groupName}</span></div>
179
- {/if}
180
- {#each groupOpts as option}
181
- <li>
182
- <button
183
- type="button"
184
- class="text-left {option.disabled ? 'disabled' : ''}"
185
- class:active={option.value === value}
186
- onclick={() => handleSelect(option)}
187
- disabled={option.disabled}
188
- >
189
- {option.label}
190
- </button>
191
- </li>
192
- {/each}
193
- {/each}
194
- </div>
195
- {/if}
196
- </div>
197
- {:else}
198
- <select
199
- {id}
200
- {name}
201
- {required}
202
- {disabled}
203
- bind:value
204
- class={selectClass}
205
- aria-describedby={error ? `${id}-error` : helpText ? `${id}-help` : undefined}
206
- aria-invalid={error ? 'true' : 'false'}
207
- onchange={handleNativeChange}
208
- >
209
- {#if placeholder}
210
- <option value="" disabled>{placeholder}</option>
211
- {/if}
212
- {#each Object.entries(groupedOptions) as [groupName, groupOpts]}
213
- {#if groupName !== 'default'}
214
- <optgroup label={groupName}>
215
- {#each groupOpts as option}
216
- <option value={option.value} disabled={option.disabled}>{option.label}</option>
217
- {/each}
218
- </optgroup>
219
- {:else}
220
- {#each groupOpts as option}
221
- <option value={option.value} disabled={option.disabled}>{option.label}</option>
222
- {/each}
223
- {/if}
224
- {/each}
225
- </select>
226
- {/if}
227
-
228
- {#if error}
229
- <div class="label">
230
- <span id="{id}-error" class="text-[0.8125rem] text-error" role="alert">{error}</span>
231
- </div>
232
- {:else if helpText}
233
- <div class="label">
234
- <span id="{id}-help" class="text-[0.8125rem] text-base-content/45">{helpText}</span>
235
- </div>
236
- {/if}
237
- </div>
@@ -1,34 +0,0 @@
1
- <!--
2
- SidebarUserFooter — avatar + name (links to account) + sign out button.
3
- Placed at the bottom of app sidebar drawers (admin, facilitator, portal).
4
- Used in JST template layouts.
5
- -->
6
- <script lang="ts">
7
- import UserAvatar from './UserAvatar.svelte'
8
-
9
- interface Props {
10
- profile?: { full_name?: string | null; avatar_url?: string | null } | null
11
- user?: { email?: string | null } | null
12
- /** Where the avatar/name links to. Defaults to /account */
13
- accountHref?: string
14
- /** Sign out URL. Defaults to /account/sign_out */
15
- signOutHref?: string
16
- }
17
-
18
- let {
19
- profile,
20
- user,
21
- accountHref = '/account',
22
- signOutHref = '/account/sign_out',
23
- }: Props = $props()
24
-
25
- let displayName = $derived(profile?.full_name || user?.email || '?')
26
- </script>
27
-
28
- <div class="flex items-center gap-2 px-2 py-1">
29
- <a href={accountHref} class="flex items-center gap-2 flex-1 min-w-0" title="Account settings">
30
- <UserAvatar name={profile?.full_name} email={user?.email} avatarUrl={profile?.avatar_url} size="sm" />
31
- <span class="truncate text-[0.9375rem]">{displayName}</span>
32
- </a>
33
- <a href={signOutHref} class="btn btn-ghost btn-xs shrink-0">Sign out</a>
34
- </div>
@@ -1,175 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * SignaturePad — Canvas-based digital signature capture with mouse and touch support.
4
- *
5
- * Exports `clear()` and `isEmpty()` methods. Outputs signature as base64 PNG data URL
6
- * via the bindable `signatureData` prop or `onSignatureChange` callback.
7
- */
8
- import { onMount } from 'svelte';
9
-
10
- let {
11
- signatureData = $bindable(''),
12
- onSignatureChange,
13
- width = 400,
14
- height = 150,
15
- strokeColor = '',
16
- strokeWidth = 2,
17
- label = 'Signature',
18
- required = false,
19
- placeholder = 'Sign here',
20
- }: {
21
- signatureData?: string;
22
- onSignatureChange?: (data: string) => void;
23
- width?: number;
24
- height?: number;
25
- strokeColor?: string;
26
- strokeWidth?: number;
27
- label?: string;
28
- required?: boolean;
29
- placeholder?: string;
30
- } = $props();
31
-
32
- let canvas: HTMLCanvasElement;
33
- let isDrawing = false;
34
- let lastX = 0;
35
- let lastY = 0;
36
- let hasDrawn = $state(false);
37
-
38
- onMount(() => {
39
- if (!canvas) return;
40
-
41
- const ctx = canvas.getContext('2d');
42
- if (!ctx) return;
43
-
44
- const resolvedStroke = strokeColor ||
45
- getComputedStyle(canvas).getPropertyValue('--color-base-content').trim() ||
46
- 'oklch(0.21 0 0)';
47
- ctx.strokeStyle = resolvedStroke;
48
- ctx.lineWidth = strokeWidth;
49
- ctx.lineCap = 'round';
50
- ctx.lineJoin = 'round';
51
-
52
- function getCoordinates(e: MouseEvent | TouchEvent) {
53
- const rect = canvas.getBoundingClientRect();
54
- const scaleX = canvas.width / rect.width;
55
- const scaleY = canvas.height / rect.height;
56
-
57
- if (e instanceof MouseEvent) {
58
- return {
59
- x: (e.clientX - rect.left) * scaleX,
60
- y: (e.clientY - rect.top) * scaleY
61
- };
62
- } else {
63
- return {
64
- x: (e.touches[0].clientX - rect.left) * scaleX,
65
- y: (e.touches[0].clientY - rect.top) * scaleY
66
- };
67
- }
68
- }
69
-
70
- function startDrawing(e: MouseEvent | TouchEvent) {
71
- e.preventDefault();
72
- isDrawing = true;
73
- const coords = getCoordinates(e);
74
- lastX = coords.x;
75
- lastY = coords.y;
76
- }
77
-
78
- function draw(e: MouseEvent | TouchEvent) {
79
- if (!isDrawing || !ctx) return;
80
- e.preventDefault();
81
-
82
- const coords = getCoordinates(e);
83
- ctx.beginPath();
84
- ctx.moveTo(lastX, lastY);
85
- ctx.lineTo(coords.x, coords.y);
86
- ctx.stroke();
87
- lastX = coords.x;
88
- lastY = coords.y;
89
- hasDrawn = true;
90
- }
91
-
92
- function stopDrawing() {
93
- if (isDrawing && hasDrawn) {
94
- isDrawing = false;
95
- signatureData = canvas.toDataURL();
96
- onSignatureChange?.(signatureData);
97
- }
98
- isDrawing = false;
99
- }
100
-
101
- canvas.addEventListener('mousedown', startDrawing);
102
- canvas.addEventListener('mousemove', draw);
103
- canvas.addEventListener('mouseup', stopDrawing);
104
- canvas.addEventListener('mouseleave', stopDrawing);
105
-
106
- canvas.addEventListener('touchstart', startDrawing, { passive: false });
107
- canvas.addEventListener('touchmove', draw, { passive: false });
108
- canvas.addEventListener('touchend', stopDrawing);
109
- canvas.addEventListener('touchcancel', stopDrawing);
110
-
111
- return () => {
112
- canvas.removeEventListener('mousedown', startDrawing);
113
- canvas.removeEventListener('mousemove', draw);
114
- canvas.removeEventListener('mouseup', stopDrawing);
115
- canvas.removeEventListener('mouseleave', stopDrawing);
116
- canvas.removeEventListener('touchstart', startDrawing);
117
- canvas.removeEventListener('touchmove', draw);
118
- canvas.removeEventListener('touchend', stopDrawing);
119
- canvas.removeEventListener('touchcancel', stopDrawing);
120
- };
121
- });
122
-
123
- export function clear() {
124
- if (!canvas) return;
125
- const ctx = canvas.getContext('2d');
126
- if (!ctx) return;
127
-
128
- ctx.clearRect(0, 0, canvas.width, canvas.height);
129
- signatureData = '';
130
- hasDrawn = false;
131
- onSignatureChange?.('');
132
- }
133
-
134
- export function isEmpty(): boolean {
135
- return !hasDrawn || !signatureData;
136
- }
137
- </script>
138
-
139
- <div class="signature-pad-container">
140
- {#if label}
141
- <div class="flex justify-between items-center mb-2">
142
- <span class="text-sm text-base-content/70">
143
- {label}
144
- {#if required}
145
- <span class="text-error">*</span>
146
- {/if}
147
- </span>
148
- <button type="button" onclick={() => clear()} class="btn btn-ghost btn-xs">
149
- Clear
150
- </button>
151
- </div>
152
- {/if}
153
-
154
- <div class="rounded-lg bg-base-100 overflow-hidden relative transition-all duration-300
155
- {hasDrawn ? 'border-2 border-success/60' : 'border-2 border-base-300'}">
156
- <canvas
157
- bind:this={canvas}
158
- {width}
159
- {height}
160
- class="w-full touch-none cursor-crosshair"
161
- ></canvas>
162
-
163
- {#if !hasDrawn}
164
- <div class="absolute inset-0 flex items-center justify-center pointer-events-none">
165
- <span class="text-base-content/30 text-sm">{placeholder}</span>
166
- </div>
167
- {/if}
168
- </div>
169
- </div>
170
-
171
- <style>
172
- canvas {
173
- display: block;
174
- }
175
- </style>