@joewinke/jatui 0.1.10 → 0.1.19

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 (91) hide show
  1. package/README.md +123 -0
  2. package/package.json +3 -1
  3. package/src/lib/actions/railNav.ts +473 -0
  4. package/src/lib/components/AnnotationLayer.svelte +108 -0
  5. package/src/lib/components/AnnotationPanel.svelte +319 -0
  6. package/src/lib/components/AudioWaveform.svelte +9 -5
  7. package/src/lib/components/AvailabilityModal.svelte +7 -3
  8. package/src/lib/components/AvatarUpload.svelte +27 -4
  9. package/src/lib/components/BookingForm.svelte +11 -9
  10. package/src/lib/components/BurndownChart.svelte +778 -0
  11. package/src/lib/components/Button.svelte +10 -1
  12. package/src/lib/components/CalendarPicker.svelte +3 -3
  13. package/src/lib/components/Card.svelte +2 -2
  14. package/src/lib/components/ChipInput.svelte +21 -15
  15. package/src/lib/components/ColorSelector.svelte +17 -13
  16. package/src/lib/components/CommentThread.svelte +773 -0
  17. package/src/lib/components/ConfirmDialog.svelte +348 -0
  18. package/src/lib/components/ConfirmModal.svelte +78 -11
  19. package/src/lib/components/ContextMenu.svelte +188 -0
  20. package/src/lib/components/CountdownTimer.svelte +1 -1
  21. package/src/lib/components/DateRangePicker.svelte +6 -4
  22. package/src/lib/components/Drawer.svelte +36 -3
  23. package/src/lib/components/EntityPreviewCard.svelte +104 -0
  24. package/src/lib/components/FileDropzone.svelte +493 -0
  25. package/src/lib/components/FilePicker.svelte +83 -14
  26. package/src/lib/components/FileThumbnail.svelte +80 -0
  27. package/src/lib/components/FilterDropdown.svelte +11 -11
  28. package/src/lib/components/HunkDiffView.svelte +348 -0
  29. package/src/lib/components/ImageLightbox.svelte +274 -0
  30. package/src/lib/components/ImageUpload.svelte +58 -9
  31. package/src/lib/components/InlineEdit.svelte +15 -9
  32. package/src/lib/components/InputDialog.svelte +327 -0
  33. package/src/lib/components/LazyImage.svelte +1 -0
  34. package/src/lib/components/LinkShortener.svelte +1 -1
  35. package/src/lib/components/LoadingSpinner.svelte +6 -2
  36. package/src/lib/components/MarkupEditor.svelte +485 -0
  37. package/src/lib/components/MarkupOverlay.svelte +55 -0
  38. package/src/lib/components/MediaWorkbench.svelte +871 -0
  39. package/src/lib/components/MilestoneCard.svelte +1 -1
  40. package/src/lib/components/MilestoneTimeline.svelte +1 -1
  41. package/src/lib/components/Modal.svelte +39 -4
  42. package/src/lib/components/PDFViewer.svelte +105 -0
  43. package/src/lib/components/PdfThumbnail.svelte +3 -1
  44. package/src/lib/components/PhoneInput.svelte +183 -63
  45. package/src/lib/components/ResizablePanel.svelte +4 -4
  46. package/src/lib/components/SearchDropdown.svelte +26 -13
  47. package/src/lib/components/SelectInput.svelte +26 -4
  48. package/src/lib/components/SidebarUserFooter.svelte +1 -1
  49. package/src/lib/components/SignaturePad.svelte +8 -4
  50. package/src/lib/components/SmartImageEditor.svelte +720 -0
  51. package/src/lib/components/SortDropdown.svelte +9 -3
  52. package/src/lib/components/Sparkline.svelte +9 -0
  53. package/src/lib/components/StatusBadge.svelte +20 -18
  54. package/src/lib/components/TextArea.svelte +24 -5
  55. package/src/lib/components/TextInput.svelte +29 -6
  56. package/src/lib/components/ThemeSelector.svelte +15 -4
  57. package/src/lib/components/TimeSlotPicker.svelte +7 -7
  58. package/src/lib/components/UserAvatar.svelte +14 -1
  59. package/src/lib/components/VariablePicker.svelte +170 -0
  60. package/src/lib/components/VoicePlayer.svelte +4 -3
  61. package/src/lib/components/markup.ts +287 -0
  62. package/src/lib/components/messaging/ChannelInfoModal.svelte +9 -9
  63. package/src/lib/components/messaging/ChannelList.svelte +1 -1
  64. package/src/lib/components/messaging/ChannelMembersModal.svelte +1 -1
  65. package/src/lib/components/messaging/CreateChannelModal.svelte +1 -1
  66. package/src/lib/components/messaging/DirectMessageList.svelte +1 -1
  67. package/src/lib/components/messaging/EmojiSelector.svelte +2 -1
  68. package/src/lib/components/messaging/MentionAutocomplete.svelte +1 -1
  69. package/src/lib/components/messaging/MessageAttachment.svelte +3 -3
  70. package/src/lib/components/messaging/MessageAttachmentUpload.svelte +3 -3
  71. package/src/lib/components/messaging/MessageInput.svelte +1 -1
  72. package/src/lib/components/messaging/MessageItem.svelte +6 -3
  73. package/src/lib/components/messaging/NotificationSettingsModal.svelte +1 -1
  74. package/src/lib/components/messaging/QuotedMessageDisplay.svelte +6 -1
  75. package/src/lib/components/messaging/StartDMModal.svelte +1 -1
  76. package/src/lib/components/pipeline/Pipeline.svelte +4 -4
  77. package/src/lib/components/pipeline/PipelineCard.svelte +1 -1
  78. package/src/lib/components/pipeline/PipelineColumn.svelte +8 -3
  79. package/src/lib/index.ts +105 -1
  80. package/src/lib/stores/confirmDialog.svelte.ts +48 -0
  81. package/src/lib/stores/inputDialog.svelte.ts +51 -0
  82. package/src/lib/styles/rail.css +63 -0
  83. package/src/lib/types/annotation.ts +38 -0
  84. package/src/lib/types/comments.ts +97 -0
  85. package/src/lib/types/entityPreview.ts +45 -0
  86. package/src/lib/types/filePicker.ts +2 -0
  87. package/src/lib/types/smartImageEditor.ts +39 -0
  88. package/src/lib/types/templateVars.ts +36 -0
  89. package/src/lib/utils/dateFormatters.ts +12 -10
  90. package/src/lib/utils/phone.ts +80 -0
  91. package/src/lib/utils/taskUtils.ts +21 -7
@@ -12,6 +12,8 @@
12
12
  type?: 'button' | 'submit' | 'reset';
13
13
  disabled?: boolean;
14
14
  loading?: boolean;
15
+ /** When true, show an animated success check before the label (transitions.dev "Success check"). */
16
+ success?: boolean;
15
17
  class?: string;
16
18
  onclick?: (e: MouseEvent) => void;
17
19
  children?: import('svelte').Snippet;
@@ -24,6 +26,7 @@
24
26
  type = 'button',
25
27
  disabled = false,
26
28
  loading = false,
29
+ success = false,
27
30
  class: className = '',
28
31
  onclick,
29
32
  children
@@ -61,9 +64,15 @@
61
64
  {/if}
62
65
  </a>
63
66
  {:else}
64
- <button {type} {disabled} class={buttonClass} {onclick}>
67
+ <button {type} disabled={disabled || loading} aria-busy={loading || undefined} class={buttonClass} {onclick}>
65
68
  {#if loading}
66
69
  <span class="loading loading-spinner loading-xs"></span>
70
+ {:else if success}
71
+ <span class="t-success-check" data-state="in" aria-hidden="true">
72
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
73
+ <path pathLength="1" d="M5 13l4 4L19 7" />
74
+ </svg>
75
+ </span>
67
76
  {/if}
68
77
  {#if children}
69
78
  {@render children()}
@@ -207,7 +207,7 @@
207
207
  <!-- Day Headers -->
208
208
  <div class="grid grid-cols-7 gap-1 mb-2">
209
209
  {#each DAYS_SHORT as day}
210
- <div class="text-center text-sm font-medium text-base-content/50 py-2">
210
+ <div class="text-center text-[0.8125rem] text-base-content/45 py-2">
211
211
  {day}
212
212
  </div>
213
213
  {/each}
@@ -224,7 +224,7 @@
224
224
  <button
225
225
  onclick={() => handleDateClick(date)}
226
226
  disabled={!available}
227
- class="aspect-square flex flex-col items-center justify-center rounded-lg text-sm font-medium
227
+ class="aspect-square flex flex-col items-center justify-center rounded-lg text-[0.9375rem] font-medium
228
228
  transition-all duration-200 relative
229
229
  {currentMonth ? '' : 'opacity-30'}
230
230
  {available
@@ -255,7 +255,7 @@
255
255
 
256
256
  <!-- Legend -->
257
257
  {#if getAvailability}
258
- <div class="flex flex-wrap items-center gap-x-5 gap-y-2 mt-6 pt-4 border-t border-base-300 text-sm">
258
+ <div class="flex flex-wrap items-center gap-x-5 gap-y-2 mt-6 pt-4 border-t border-base-300 text-[0.75rem]">
259
259
  <div class="flex items-center gap-2">
260
260
  <div class="flex gap-0.5">
261
261
  <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
@@ -21,7 +21,7 @@
21
21
  {#if onclick || role}
22
22
  <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
23
23
  <div
24
- class="card bg-base-100 shadow-xl border border-base-300 {className}"
24
+ class="card bg-base-200 border border-base-300 transition-[transform,border-color] duration-150 hover:-translate-y-[1px] hover:border-base-content/20 cursor-pointer {className}"
25
25
  {onclick}
26
26
  role={role || (onclick ? 'button' : undefined)}
27
27
  tabindex={tabindex ?? 0}
@@ -45,7 +45,7 @@
45
45
  {/if}
46
46
  </div>
47
47
  {:else}
48
- <div class="card bg-base-100 shadow-xl border border-base-300 {className}">
48
+ <div class="card bg-base-200 border border-base-300 {className}">
49
49
  {#if header}
50
50
  <div class="card-body pb-4">
51
51
  <div class="flex justify-between items-center">
@@ -1,15 +1,4 @@
1
- <script lang="ts">
2
- /**
3
- * ChipInput - Generic contenteditable input with inline chips and autocomplete.
4
- *
5
- * Handles:
6
- * - Contenteditable div with placeholder
7
- * - Chip insertion/deletion (non-editable inline spans)
8
- * - Autocomplete dropdown with keyboard navigation
9
- * - Serialization (DOM -> text with chip markers)
10
- */
11
-
12
- // --- Types ---
1
+ <script module lang="ts">
13
2
  export interface ChipSuggestion {
14
3
  label: string;
15
4
  description?: string;
@@ -39,6 +28,18 @@
39
28
  /** If true, insert as plain text instead of a chip element */
40
29
  insertAsText?: boolean;
41
30
  }
31
+ </script>
32
+
33
+ <script lang="ts">
34
+ /**
35
+ * ChipInput - Generic contenteditable input with inline chips and autocomplete.
36
+ *
37
+ * Handles:
38
+ * - Contenteditable div with placeholder
39
+ * - Chip insertion/deletion (non-editable inline spans)
40
+ * - Autocomplete dropdown with keyboard navigation
41
+ * - Serialization (DOM -> text with chip markers)
42
+ */
42
43
 
43
44
  // --- Props ---
44
45
  let {
@@ -389,6 +390,9 @@
389
390
  export function getElement(): HTMLDivElement | null {
390
391
  return editableRef;
391
392
  }
393
+
394
+ import { fly } from 'svelte/transition';
395
+ import { cubicOut } from 'svelte/easing';
392
396
  </script>
393
397
 
394
398
  <div class="chip-input-wrapper relative">
@@ -398,7 +402,7 @@
398
402
  role="textbox"
399
403
  tabindex={disabled ? -1 : 0}
400
404
  aria-multiline="true"
401
- class="chip-input-editable w-full rounded-md text-sm"
405
+ class="chip-input-editable w-full rounded-md text-[0.9375rem]"
402
406
  class:chip-input-monospace={monospace}
403
407
  class:chip-input-compact={compact}
404
408
  style="
@@ -415,7 +419,7 @@
415
419
 
416
420
  <!-- Placeholder overlay -->
417
421
  {#if !value.trim()}
418
- <div class="chip-input-placeholder absolute top-0 left-0 text-sm pointer-events-none"
422
+ <div class="chip-input-placeholder absolute top-0 left-0 text-[0.9375rem] pointer-events-none"
419
423
  class:chip-input-placeholder-compact={compact}
420
424
  class:chip-input-placeholder-mono={monospace}
421
425
  >
@@ -427,7 +431,9 @@
427
431
  {#if showAutocomplete && totalItems > 0}
428
432
  <div
429
433
  bind:this={autocompleteRef}
430
- class="chip-input-dropdown absolute z-50 w-full mt-1 rounded-lg overflow-hidden shadow-xl"
434
+ class="chip-input-dropdown absolute z-50 w-full mt-1 rounded-lg overflow-hidden bg-base-200 border border-base-300"
435
+ in:fly={{ y: -6, duration: 150, easing: cubicOut }}
436
+ out:fly={{ y: -4, duration: 100, easing: cubicOut }}
431
437
  >
432
438
  {#if isGrouped}
433
439
  {@const flatIdx = { current: 0 }}
@@ -14,6 +14,7 @@
14
14
  }>()
15
15
 
16
16
  let showSelector = $state(false)
17
+ // svelte-ignore state_referenced_locally
17
18
  let lastSelectedColor = $state(selectedColor)
18
19
  let selectionAnimating = $state(false)
19
20
 
@@ -71,7 +72,7 @@
71
72
  </button>
72
73
 
73
74
  {#if showSelector}
74
- <div class="color-selector-wrapper transition-all" transition:slide={{ duration: 200 }}>
75
+ <div class="color-selector-wrapper" transition:slide={{ duration: 200 }}>
75
76
  <div class="grid grid-cols-4 gap-3 p-4 bg-base-200 rounded-lg">
76
77
  {#each colorOptions as option}
77
78
  <button
@@ -116,34 +117,37 @@
116
117
  display: flex;
117
118
  align-items: center;
118
119
  justify-content: center;
119
- transition: all 0.2s ease;
120
+ transition: transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);
120
121
  cursor: pointer;
121
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
122
122
  }
123
123
 
124
124
  .color-btn:hover {
125
125
  transform: scale(1.05);
126
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
127
126
  }
128
127
 
129
128
  .color-btn.selected {
130
- border-color: white;
131
- box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.2);
129
+ border-color: color-mix(in oklch, var(--color-base-100) 90%, transparent);
130
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-base-content) 25%, transparent);
132
131
  }
133
132
 
134
133
  .color-btn.selecting {
135
- transform: scale(1.15);
136
- border-color: white;
137
- box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.3), 0 0 15px rgba(255, 255, 255, 0.5);
138
- animation: pulse 0.5s ease;
134
+ transform: scale(1.12);
135
+ border-color: color-mix(in oklch, var(--color-base-100) 90%, transparent);
136
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-base-content) 35%, transparent);
137
+ animation: pulse 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
138
+ }
139
+
140
+ @media (prefers-reduced-motion: reduce) {
141
+ .color-btn { transition: none; }
142
+ .color-btn:hover { transform: none; }
143
+ .color-btn.selecting { transform: none; animation: none; }
139
144
  }
140
145
 
141
146
  .color-preview {
142
147
  width: 15px;
143
148
  height: 15px;
144
149
  border-radius: 50%;
145
- border: 1px solid hsla(var(--bc) / 0.2);
146
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
150
+ border: 1px solid color-mix(in oklch, var(--color-base-content) 20%, transparent);
147
151
  }
148
152
 
149
153
  @keyframes pulse {
@@ -153,7 +157,7 @@
153
157
  }
154
158
 
155
159
  .animate-checkmark {
156
- animation: zoom-in 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
160
+ animation: zoom-in 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
157
161
  }
158
162
 
159
163
  @keyframes zoom-in {