@joewinke/jatui 0.1.23 → 0.1.25

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,203 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * FilterDropdown Component
4
- * Reusable multi-select filter component for filter bars
5
- *
6
- * Supports two modes:
7
- * - dropdown: Click button to show options in dropdown menu (default)
8
- * - inline: Options displayed inline without dropdown wrapper
9
- *
10
- * Supports two styles:
11
- * - badge: Clickable badge buttons (default, good for compact filters)
12
- * - checkbox: Checkbox list in menu format (good for longer lists)
13
- */
14
-
15
- interface FilterOption {
16
- value: string;
17
- label: string;
18
- count: number;
19
- }
20
-
21
- interface Props {
22
- /** Label shown on dropdown trigger button */
23
- label: string;
24
- /** Available options to select from */
25
- options: FilterOption[];
26
- /** Currently selected values */
27
- selected: Set<string>;
28
- /** Callback when option is toggled */
29
- onToggle: (value: string) => void;
30
- /** Function to get badge color class for a value */
31
- colorFn?: (value: string, isSelected: boolean) => string;
32
- /** Text to show when all options are selected */
33
- allSelectedText?: string;
34
- /** If true, empty selection means "all" (vs "none") */
35
- emptyMeansAll?: boolean;
36
- /** Display mode: 'dropdown' (default) or 'inline' */
37
- mode?: 'dropdown' | 'inline';
38
- /** Selection style: 'badge' (default) or 'checkbox' */
39
- style?: 'badge' | 'checkbox';
40
- /** Additional CSS class for the container */
41
- class?: string;
42
- /** Dropdown menu width class (e.g., 'w-44', 'w-52') */
43
- menuWidth?: string;
44
- /** Max height for scrollable content (e.g., 'max-h-60') */
45
- maxHeight?: string;
46
- /** Show hover effect on dropdown trigger */
47
- hoverTrigger?: boolean;
48
- }
49
-
50
- let {
51
- label,
52
- options,
53
- selected,
54
- onToggle,
55
- colorFn = () => 'badge-primary',
56
- allSelectedText = 'all',
57
- emptyMeansAll = false,
58
- mode = 'dropdown',
59
- style = 'badge',
60
- class: className = '',
61
- menuWidth = 'min-w-48',
62
- maxHeight = '',
63
- hoverTrigger = true
64
- }: Props = $props();
65
-
66
- // Compute display text for the trigger button
67
- const displayText = $derived.by(() => {
68
- if (emptyMeansAll && selected.size === 0) {
69
- return allSelectedText;
70
- }
71
- if (selected.size === options.length && options.length > 0) {
72
- return allSelectedText;
73
- }
74
- return String(selected.size);
75
- });
76
-
77
- // Compute badge class for trigger (show primary when filters active)
78
- const triggerBadgeClass = $derived.by(() => {
79
- if (emptyMeansAll) {
80
- return selected.size > 0 ? 'badge-primary' : 'badge-ghost';
81
- }
82
- return 'badge-primary';
83
- });
84
-
85
- // Handle option toggle
86
- function handleToggle(value: string) {
87
- onToggle(value);
88
- }
89
-
90
- // Handle keyboard navigation
91
- function handleKeydown(e: KeyboardEvent, value: string) {
92
- if (e.key === 'Enter' || e.key === ' ') {
93
- e.preventDefault();
94
- handleToggle(value);
95
- }
96
- }
97
- </script>
98
-
99
- {#if mode === 'inline'}
100
- <!-- Inline Mode: No dropdown wrapper, just badge/checkbox grid -->
101
- <div class="flex flex-wrap gap-1.5 {className}">
102
- {#each options as opt, index}
103
- {#if style === 'checkbox'}
104
- <label class="label cursor-pointer justify-start gap-2">
105
- <input
106
- type="checkbox"
107
- class="checkbox checkbox-sm"
108
- checked={selected.has(opt.value)}
109
- onchange={() => handleToggle(opt.value)}
110
- />
111
- <span>{opt.label}</span>
112
- <span class="text-[0.75rem] opacity-60">({opt.count})</span>
113
- </label>
114
- {:else}
115
- <button
116
- class="badge badge-sm transition-all duration-200 cursor-pointer {selected.has(opt.value)
117
- ? colorFn(opt.value, true)
118
- : 'badge-ghost hover:badge-primary/20'}"
119
- onclick={() => handleToggle(opt.value)}
120
- onkeydown={(e) => handleKeydown(e, opt.value)}
121
- >
122
- {opt.label}
123
- <span class="ml-1 text-[0.75rem] opacity-60">({opt.count})</span>
124
- </button>
125
- {/if}
126
- {/each}
127
- </div>
128
- {:else}
129
- <!-- Dropdown Mode: Click to show options -->
130
- <div class="dropdown {hoverTrigger ? 'dropdown-hover' : ''} {className}">
131
- <!-- Trigger Button -->
132
- <div
133
- tabindex="0"
134
- role="button"
135
- class="px-2.5 py-1 rounded cursor-pointer transition-all flex items-center gap-1.5 text-[0.8125rem] bg-base-200 border border-base-300 text-base-content/60"
136
- >
137
- <span>{label}</span>
138
- <span
139
- class="px-1.5 py-0.5 rounded text-[0.75rem] {selected.size > 0 && !(emptyMeansAll && selected.size === 0) ? 'bg-primary/20 text-primary' : 'bg-base-300 text-base-content opacity-60'}"
140
- >
141
- {displayText}
142
- </span>
143
- <svg
144
- xmlns="http://www.w3.org/2000/svg"
145
- fill="none"
146
- viewBox="0 0 24 24"
147
- stroke-width="1.5"
148
- stroke="currentColor"
149
- class="w-3.5 h-3.5 text-base-content/50"
150
- >
151
- <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
152
- </svg>
153
- </div>
154
-
155
- <!-- Dropdown Content -->
156
- {#if style === 'checkbox'}
157
- <!-- Checkbox style: Menu with checkboxes -->
158
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
159
- <ul
160
- tabindex="0"
161
- class="dropdown-content z-40 menu p-2 shadow rounded-box {menuWidth} {maxHeight ? maxHeight + ' overflow-y-auto' : ''} bg-base-200 border border-base-300"
162
- >
163
- {#each options as opt, index}
164
- <li>
165
- <label
166
- class="label cursor-pointer justify-start gap-2 rounded text-base-content/70"
167
- >
168
- <input
169
- type="checkbox"
170
- class="checkbox checkbox-sm border-base-content/40"
171
- checked={selected.has(opt.value)}
172
- onchange={() => handleToggle(opt.value)}
173
- />
174
- <span class="truncate text-[0.8125rem]">{opt.label}</span>
175
- <span class="text-[0.75rem] text-base-content/45">({opt.count})</span>
176
- </label>
177
- </li>
178
- {/each}
179
- </ul>
180
- {:else}
181
- <!-- Badge style: Grid of clickable badges -->
182
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
183
- <div
184
- tabindex="0"
185
- role="menu"
186
- class="dropdown-content rounded-box p-2 z-40 {menuWidth} mt-1 {maxHeight ? maxHeight + ' overflow-y-auto' : ''} bg-base-200 border border-base-300"
187
- >
188
- <div class="flex flex-wrap gap-1.5">
189
- {#each options as opt, index}
190
- <button
191
- class="px-2 py-0.5 rounded text-[0.75rem] transition-all cursor-pointer border {selected.has(opt.value) ? 'bg-primary/20 border-primary/40 text-primary' : 'bg-base-300 border-base-content/20 text-base-content opacity-70 hover:opacity-100'}"
192
- onclick={() => handleToggle(opt.value)}
193
- onkeydown={(e) => handleKeydown(e, opt.value)}
194
- >
195
- {opt.label}
196
- <span class="ml-1 text-base-content/50">({opt.count})</span>
197
- </button>
198
- {/each}
199
- </div>
200
- </div>
201
- {/if}
202
- </div>
203
- {/if}
@@ -1,354 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * FloatingActionBar Component
4
- * Fixed bottom-center bar for bulk selection actions on tables/lists.
5
- *
6
- * Usage:
7
- * <FloatingActionBar
8
- * count={selectedTasks.size}
9
- * {actions}
10
- * {dropdowns}
11
- * loading={bulkActionLoading}
12
- * onClear={clearSelection}
13
- * />
14
- */
15
-
16
- import { fade } from 'svelte/transition';
17
-
18
- export interface ActionButton {
19
- /** Unique key */
20
- id: string;
21
- /** Button label */
22
- label: string;
23
- /** SVG path string for a 24×24 icon (optional) */
24
- icon?: string;
25
- /** Color variant */
26
- variant?: 'default' | 'primary' | 'danger' | 'warning' | 'success';
27
- /** Called when clicked */
28
- onclick: () => void;
29
- }
30
-
31
- export interface DropdownItem {
32
- /** Display label */
33
- label: string;
34
- /** Optional colored dot (oklch string) */
35
- dotColor?: string;
36
- /** Optional SVG snippet rendered before the label */
37
- iconSnippet?: import('svelte').Snippet;
38
- /** Called when this item is clicked */
39
- onclick: () => void;
40
- }
41
-
42
- export interface ActionDropdown {
43
- /** Unique key */
44
- id: string;
45
- /** Button label */
46
- label: string;
47
- /** SVG path string for a 24×24 icon (optional) */
48
- icon?: string;
49
- /** Color variant */
50
- variant?: 'default' | 'primary' | 'info' | 'purple';
51
- /** Items in the dropdown */
52
- items: DropdownItem[];
53
- }
54
-
55
- interface Props {
56
- /** Number of selected items — bar is hidden when 0 */
57
- count: number;
58
- /** Primary action buttons */
59
- actions?: ActionButton[];
60
- /** Dropdown menus (open upward from the bar) */
61
- dropdowns?: ActionDropdown[];
62
- /** Disables all buttons while true and shows a spinner */
63
- loading?: boolean;
64
- /** Called when the "Clear" button is clicked */
65
- onClear?: () => void;
66
- /** Label for the selection count (default: "selected") */
67
- countLabel?: string;
68
- }
69
-
70
- let {
71
- count,
72
- actions = [],
73
- dropdowns = [],
74
- loading = false,
75
- onClear,
76
- countLabel = 'selected',
77
- }: Props = $props();
78
-
79
- let openDropdownId = $state<string | null>(null);
80
-
81
- // Close dropdown on outside click
82
- $effect(() => {
83
- if (!openDropdownId) return;
84
- function handleClick(e: MouseEvent) {
85
- if (!(e.target as HTMLElement).closest('.fab-dropdown-wrapper')) {
86
- openDropdownId = null;
87
- }
88
- }
89
- const timer = setTimeout(() => document.addEventListener('click', handleClick), 0);
90
- return () => {
91
- clearTimeout(timer);
92
- document.removeEventListener('click', handleClick);
93
- };
94
- });
95
-
96
- function variantClass(variant: ActionButton['variant'] | ActionDropdown['variant']): string {
97
- switch (variant) {
98
- case 'primary': return 'fab-btn-primary';
99
- case 'danger': return 'fab-btn-danger';
100
- case 'warning': return 'fab-btn-warning';
101
- case 'success': return 'fab-btn-success';
102
- case 'info': return 'fab-btn-info';
103
- case 'purple': return 'fab-btn-purple';
104
- default: return 'fab-btn-default';
105
- }
106
- }
107
- </script>
108
-
109
- {#if count > 0}
110
- <div class="fab" transition:fade={{ duration: 150 }}>
111
- <span class="fab-count">{count} {countLabel}</span>
112
-
113
- {#if actions.length > 0}
114
- <div class="fab-divider"></div>
115
- {#each actions as action}
116
- <button
117
- type="button"
118
- class="fab-btn {variantClass(action.variant)}"
119
- onclick={action.onclick}
120
- disabled={loading}
121
- >
122
- {#if action.icon}
123
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
124
- <!-- svelte-ignore a11y_consider_explicit_label -->
125
- {@html action.icon}
126
- </svg>
127
- {/if}
128
- {action.label}
129
- </button>
130
- {/each}
131
- {/if}
132
-
133
- {#if dropdowns.length > 0}
134
- <div class="fab-divider"></div>
135
- {#each dropdowns as dropdown}
136
- <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
137
- <div
138
- class="fab-dropdown-wrapper"
139
- role="group"
140
- onclick={(e) => e.stopPropagation()}
141
- onkeydown={(e) => e.stopPropagation()}
142
- >
143
- <button
144
- type="button"
145
- class="fab-btn {variantClass(dropdown.variant)}"
146
- onclick={() => openDropdownId = openDropdownId === dropdown.id ? null : dropdown.id}
147
- disabled={loading}
148
- >
149
- {#if dropdown.icon}
150
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
151
- <!-- svelte-ignore a11y_consider_explicit_label -->
152
- {@html dropdown.icon}
153
- </svg>
154
- {/if}
155
- {dropdown.label}
156
- </button>
157
- {#if openDropdownId === dropdown.id}
158
- <div class="fab-dropdown" transition:fade={{ duration: 100 }}>
159
- {#each dropdown.items as item}
160
- <button
161
- class="fab-dropdown-item"
162
- onclick={() => { item.onclick(); openDropdownId = null; }}
163
- >
164
- {#if item.dotColor}
165
- <span class="fab-dot" style="background: {item.dotColor};"></span>
166
- {/if}
167
- {#if item.iconSnippet}
168
- {@render item.iconSnippet()}
169
- {/if}
170
- {item.label}
171
- </button>
172
- {/each}
173
- </div>
174
- {/if}
175
- </div>
176
- {/each}
177
- {/if}
178
-
179
- {#if onClear}
180
- <div class="fab-divider"></div>
181
- <button type="button" class="fab-btn fab-btn-clear" onclick={onClear} disabled={loading}>
182
- Clear
183
- </button>
184
- {/if}
185
-
186
- {#if loading}
187
- <div class="fab-spinner"></div>
188
- {/if}
189
- </div>
190
- {/if}
191
-
192
- <style>
193
- .fab {
194
- position: fixed;
195
- bottom: 1.5rem;
196
- left: 50%;
197
- transform: translateX(-50%);
198
- z-index: 50;
199
- display: flex;
200
- align-items: center;
201
- gap: 0.5rem;
202
- padding: 0.5rem 0.75rem;
203
- background: oklch(0.16 0.02 250);
204
- border: 1px solid oklch(0.30 0.02 250);
205
- border-radius: 0.75rem;
206
- box-shadow: 0 8px 32px oklch(0.05 0 0 / 0.6), 0 2px 8px oklch(0.05 0 0 / 0.3);
207
- }
208
-
209
- .fab-count {
210
- font-size: 0.8125rem;
211
- font-weight: 600;
212
- color: oklch(0.85 0.02 250);
213
- white-space: nowrap;
214
- }
215
-
216
- .fab-divider {
217
- width: 1px;
218
- height: 1.25rem;
219
- background: oklch(0.30 0.02 250);
220
- }
221
-
222
- .fab-btn {
223
- display: flex;
224
- align-items: center;
225
- gap: 0.375rem;
226
- padding: 0.375rem 0.625rem;
227
- border: 1px solid transparent;
228
- border-radius: 0.375rem;
229
- font-size: 0.75rem;
230
- font-weight: 500;
231
- cursor: pointer;
232
- transition: all 0.15s;
233
- white-space: nowrap;
234
- }
235
- .fab-btn:disabled {
236
- opacity: 0.5;
237
- pointer-events: none;
238
- }
239
-
240
- /* Variants */
241
- .fab-btn-default {
242
- background: oklch(0.25 0.02 250 / 0.5);
243
- color: oklch(0.75 0.02 250);
244
- border-color: oklch(0.35 0.02 250);
245
- }
246
- .fab-btn-default:hover { background: oklch(0.30 0.02 250); }
247
-
248
- .fab-btn-primary {
249
- background: oklch(0.65 0.18 250 / 0.15);
250
- color: oklch(0.82 0.14 250);
251
- border-color: oklch(0.65 0.18 250 / 0.3);
252
- }
253
- .fab-btn-primary:hover { background: oklch(0.65 0.18 250 / 0.25); }
254
-
255
- .fab-btn-danger {
256
- background: oklch(0.55 0.18 30 / 0.15);
257
- color: oklch(0.80 0.15 30);
258
- border-color: oklch(0.55 0.18 30 / 0.3);
259
- }
260
- .fab-btn-danger:hover { background: oklch(0.55 0.18 30 / 0.25); }
261
-
262
- .fab-btn-warning {
263
- background: oklch(0.75 0.15 85 / 0.12);
264
- color: oklch(0.80 0.12 85);
265
- border-color: oklch(0.75 0.15 85 / 0.25);
266
- }
267
- .fab-btn-warning:hover { background: oklch(0.75 0.15 85 / 0.22); }
268
-
269
- .fab-btn-success {
270
- background: oklch(0.55 0.15 145 / 0.15);
271
- color: oklch(0.80 0.12 145);
272
- border-color: oklch(0.55 0.15 145 / 0.3);
273
- }
274
- .fab-btn-success:hover { background: oklch(0.55 0.15 145 / 0.25); }
275
-
276
- .fab-btn-info {
277
- background: oklch(0.55 0.15 200 / 0.15);
278
- color: oklch(0.80 0.12 200);
279
- border-color: oklch(0.55 0.15 200 / 0.3);
280
- }
281
- .fab-btn-info:hover { background: oklch(0.55 0.15 200 / 0.25); }
282
-
283
- .fab-btn-purple {
284
- background: oklch(0.55 0.15 300 / 0.15);
285
- color: oklch(0.80 0.12 300);
286
- border-color: oklch(0.55 0.15 300 / 0.3);
287
- }
288
- .fab-btn-purple:hover { background: oklch(0.55 0.15 300 / 0.25); }
289
-
290
- .fab-btn-clear {
291
- background: transparent;
292
- color: oklch(0.65 0.02 250);
293
- border-color: transparent;
294
- }
295
- .fab-btn-clear:hover {
296
- background: oklch(0.25 0.02 250);
297
- color: oklch(0.80 0.02 250);
298
- }
299
-
300
- .fab-spinner {
301
- width: 14px;
302
- height: 14px;
303
- border: 2px solid oklch(0.35 0.02 250);
304
- border-top-color: oklch(0.70 0.15 240);
305
- border-radius: 50%;
306
- animation: fab-spin 0.6s linear infinite;
307
- flex-shrink: 0;
308
- }
309
- @keyframes fab-spin {
310
- to { transform: rotate(360deg); }
311
- }
312
-
313
- /* Dropdown */
314
- .fab-dropdown-wrapper {
315
- position: relative;
316
- }
317
- .fab-dropdown {
318
- position: absolute;
319
- bottom: calc(100% + 8px);
320
- left: 50%;
321
- transform: translateX(-50%);
322
- min-width: 160px;
323
- background: oklch(0.18 0.02 250);
324
- border: 1px solid oklch(0.30 0.02 250);
325
- border-radius: 0.5rem;
326
- padding: 0.375rem;
327
- box-shadow: 0 8px 24px oklch(0.05 0 0 / 0.5);
328
- z-index: 60;
329
- }
330
- .fab-dropdown-item {
331
- display: flex;
332
- align-items: center;
333
- gap: 0.5rem;
334
- width: 100%;
335
- padding: 0.375rem 0.625rem;
336
- border: none;
337
- background: transparent;
338
- color: oklch(0.80 0.02 250);
339
- font-size: 0.75rem;
340
- text-align: left;
341
- border-radius: 0.375rem;
342
- cursor: pointer;
343
- transition: background 0.1s;
344
- white-space: nowrap;
345
- }
346
- .fab-dropdown-item:hover { background: oklch(0.25 0.02 250); }
347
-
348
- .fab-dot {
349
- width: 8px;
350
- height: 8px;
351
- border-radius: 50%;
352
- flex-shrink: 0;
353
- }
354
- </style>