@joewinke/jatui 0.1.24 → 0.1.26
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/dist/actions/collapse.d.ts +80 -0
- package/dist/actions/collapse.js +134 -0
- package/dist/actions/railNav.d.ts +167 -0
- package/dist/actions/railNav.js +351 -0
- package/dist/components/AnnotationLayer.svelte +108 -0
- package/dist/components/AnnotationLayer.svelte.d.ts +12 -0
- package/dist/components/AnnotationPanel.svelte +319 -0
- package/dist/components/AnnotationPanel.svelte.d.ts +13 -0
- package/dist/components/AudioWaveform.svelte +701 -0
- package/dist/components/AudioWaveform.svelte.d.ts +19 -0
- package/dist/components/AvailabilityModal.svelte +177 -0
- package/dist/components/AvailabilityModal.svelte.d.ts +14 -0
- package/dist/components/AvatarUpload.svelte +234 -0
- package/dist/components/AvatarUpload.svelte.d.ts +23 -0
- package/dist/components/Badge.svelte +38 -0
- package/dist/components/Badge.svelte.d.ts +14 -0
- package/dist/components/BookingForm.svelte +278 -0
- package/dist/components/BookingForm.svelte.d.ts +37 -0
- package/dist/components/BurndownChart.svelte +778 -0
- package/dist/components/BurndownChart.svelte.d.ts +17 -0
- package/dist/components/Button.svelte +81 -0
- package/dist/components/Button.svelte.d.ts +21 -0
- package/dist/components/CalendarPicker.svelte +284 -0
- package/dist/components/CalendarPicker.svelte.d.ts +22 -0
- package/dist/components/Card.svelte +67 -0
- package/dist/components/Card.svelte.d.ts +17 -0
- package/dist/components/CharacterCounter.svelte +82 -0
- package/dist/components/CharacterCounter.svelte.d.ts +10 -0
- package/dist/components/ChipInput.svelte +609 -0
- package/dist/components/ChipInput.svelte.d.ts +55 -0
- package/dist/components/Collapse.svelte +91 -0
- package/dist/components/Collapse.svelte.d.ts +18 -0
- package/dist/components/ColorSelector.svelte +167 -0
- package/dist/components/ColorSelector.svelte.d.ts +9 -0
- package/dist/components/CommentThread.svelte +773 -0
- package/dist/components/CommentThread.svelte.d.ts +32 -0
- package/dist/components/ConfirmDialog.svelte +348 -0
- package/dist/components/ConfirmDialog.svelte.d.ts +3 -0
- package/dist/components/ConfirmModal.svelte +142 -0
- package/dist/components/ConfirmModal.svelte.d.ts +15 -0
- package/dist/components/ContextMenu.svelte +188 -0
- package/dist/components/ContextMenu.svelte.d.ts +31 -0
- package/dist/components/CountdownTimer.svelte +94 -0
- package/dist/components/CountdownTimer.svelte.d.ts +10 -0
- package/dist/components/DateRangePicker.svelte +194 -0
- package/dist/components/DateRangePicker.svelte.d.ts +10 -0
- package/dist/components/Drawer.svelte +143 -0
- package/dist/components/Drawer.svelte.d.ts +33 -0
- package/dist/components/EmojiPicker.svelte +159 -0
- package/dist/components/EmojiPicker.svelte.d.ts +8 -0
- package/dist/components/EntityPreviewCard.svelte +104 -0
- package/dist/components/EntityPreviewCard.svelte.d.ts +9 -0
- package/dist/components/FileDropzone.svelte +493 -0
- package/dist/components/FileDropzone.svelte.d.ts +40 -0
- package/dist/components/FilePicker.svelte +488 -0
- package/dist/components/FilePicker.svelte.d.ts +20 -0
- package/dist/components/FileThumbnail.svelte +80 -0
- package/dist/components/FileThumbnail.svelte.d.ts +12 -0
- package/dist/components/FilterDropdown.svelte +203 -0
- package/dist/components/FilterDropdown.svelte.d.ts +48 -0
- package/dist/components/FloatingActionBar.svelte +354 -0
- package/dist/components/FloatingActionBar.svelte.d.ts +51 -0
- package/dist/components/GPSTracker.svelte +202 -0
- package/dist/components/GPSTracker.svelte.d.ts +34 -0
- package/dist/components/HunkDiffView.svelte +348 -0
- package/dist/components/HunkDiffView.svelte.d.ts +9 -0
- package/dist/components/ImageLightbox.svelte +274 -0
- package/dist/components/ImageLightbox.svelte.d.ts +25 -0
- package/dist/components/ImageUpload.svelte +147 -0
- package/dist/components/ImageUpload.svelte.d.ts +10 -0
- package/dist/components/InlineEdit.svelte +291 -0
- package/dist/components/InlineEdit.svelte.d.ts +45 -0
- package/dist/components/InputDialog.svelte +327 -0
- package/dist/components/InputDialog.svelte.d.ts +3 -0
- package/dist/components/KeyboardShortcutsOverlay.svelte +296 -0
- package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +42 -0
- package/dist/components/LazyImage.svelte +123 -0
- package/dist/components/LazyImage.svelte.d.ts +14 -0
- package/dist/components/LinkShortener.svelte +274 -0
- package/dist/components/LinkShortener.svelte.d.ts +27 -0
- package/dist/components/LoadingSpinner.svelte +106 -0
- package/dist/components/LoadingSpinner.svelte.d.ts +21 -0
- package/dist/components/LocationMap.svelte +186 -0
- package/dist/components/LocationMap.svelte.d.ts +11 -0
- package/dist/components/MapView.svelte +341 -0
- package/dist/components/MapView.svelte.d.ts +20 -0
- package/dist/components/MarkupEditor.svelte +485 -0
- package/dist/components/MarkupEditor.svelte.d.ts +10 -0
- package/dist/components/MarkupOverlay.svelte +55 -0
- package/dist/components/MarkupOverlay.svelte.d.ts +8 -0
- package/dist/components/MediaWorkbench.svelte +871 -0
- package/dist/components/MediaWorkbench.svelte.d.ts +9 -0
- package/dist/components/MilestoneCard.svelte +98 -0
- package/dist/components/MilestoneCard.svelte.d.ts +16 -0
- package/dist/components/MilestoneTimeline.svelte +91 -0
- package/dist/components/MilestoneTimeline.svelte.d.ts +15 -0
- package/dist/components/Modal.svelte +244 -0
- package/dist/components/Modal.svelte.d.ts +35 -0
- package/dist/components/PDFViewer.svelte +105 -0
- package/dist/components/PDFViewer.svelte.d.ts +9 -0
- package/dist/components/PdfThumbnail.svelte +63 -0
- package/dist/components/PdfThumbnail.svelte.d.ts +9 -0
- package/dist/components/PhoneInput.svelte +212 -0
- package/dist/components/PhoneInput.svelte.d.ts +25 -0
- package/dist/components/ResizableDivider.svelte +307 -0
- package/dist/components/ResizableDivider.svelte.d.ts +26 -0
- package/dist/components/ResizablePanel.svelte +305 -0
- package/dist/components/ResizablePanel.svelte.d.ts +18 -0
- package/dist/components/SearchDropdown.svelte +421 -0
- package/dist/components/SearchDropdown.svelte.d.ts +24 -0
- package/dist/components/SelectInput.svelte +237 -0
- package/dist/components/SelectInput.svelte.d.ts +26 -0
- package/dist/components/SidebarUserFooter.svelte +34 -0
- package/dist/components/SidebarUserFooter.svelte.d.ts +16 -0
- package/dist/components/SignaturePad.svelte +175 -0
- package/dist/components/SignaturePad.svelte.d.ts +17 -0
- package/dist/components/SmartImageEditor.svelte +720 -0
- package/dist/components/SmartImageEditor.svelte.d.ts +24 -0
- package/dist/components/SortDropdown.svelte +156 -0
- package/dist/components/SortDropdown.svelte.d.ts +40 -0
- package/dist/components/Sparkline.svelte +116 -0
- package/dist/components/Sparkline.svelte.d.ts +12 -0
- package/dist/components/SpeechForm.svelte +114 -0
- package/dist/components/SpeechForm.svelte.d.ts +17 -0
- package/dist/components/StatusBadge.svelte +157 -0
- package/dist/components/StatusBadge.svelte.d.ts +24 -0
- package/dist/components/TaskTypeIcon.svelte +54 -0
- package/dist/components/TaskTypeIcon.svelte.d.ts +17 -0
- package/dist/components/TextArea.svelte +162 -0
- package/dist/components/TextArea.svelte.d.ts +30 -0
- package/dist/components/TextInput.svelte +131 -0
- package/dist/components/TextInput.svelte.d.ts +29 -0
- package/dist/components/ThemeSelector.svelte +206 -0
- package/dist/components/ThemeSelector.svelte.d.ts +14 -0
- package/dist/components/TimeSlotPicker.svelte +162 -0
- package/dist/components/TimeSlotPicker.svelte.d.ts +18 -0
- package/dist/components/UserAvatar.svelte +72 -0
- package/dist/components/UserAvatar.svelte.d.ts +11 -0
- package/dist/components/VariablePicker.svelte +170 -0
- package/dist/components/VariablePicker.svelte.d.ts +40 -0
- package/dist/components/VoicePlayer.svelte +422 -0
- package/dist/components/VoicePlayer.svelte.d.ts +18 -0
- package/dist/components/linked-columns/LinkedColumns.svelte +526 -0
- package/dist/components/linked-columns/LinkedColumns.svelte.d.ts +130 -0
- package/dist/components/markup.d.ts +47 -0
- package/dist/components/markup.js +201 -0
- package/dist/components/messaging/Avatar.svelte +81 -0
- package/dist/components/messaging/Avatar.svelte.d.ts +11 -0
- package/dist/components/messaging/ChannelInfoModal.svelte +163 -0
- package/dist/components/messaging/ChannelInfoModal.svelte.d.ts +18 -0
- package/dist/components/messaging/ChannelList.svelte +107 -0
- package/dist/components/messaging/ChannelList.svelte.d.ts +11 -0
- package/dist/components/messaging/ChannelMemberAvatarStack.svelte +69 -0
- package/dist/components/messaging/ChannelMemberAvatarStack.svelte.d.ts +11 -0
- package/dist/components/messaging/ChannelMembersModal.svelte +182 -0
- package/dist/components/messaging/ChannelMembersModal.svelte.d.ts +16 -0
- package/dist/components/messaging/CreateChannelModal.svelte +190 -0
- package/dist/components/messaging/CreateChannelModal.svelte.d.ts +14 -0
- package/dist/components/messaging/DirectMessageList.svelte +145 -0
- package/dist/components/messaging/DirectMessageList.svelte.d.ts +12 -0
- package/dist/components/messaging/EmojiSelector.svelte +261 -0
- package/dist/components/messaging/EmojiSelector.svelte.d.ts +19 -0
- package/dist/components/messaging/MentionAutocomplete.svelte +193 -0
- package/dist/components/messaging/MentionAutocomplete.svelte.d.ts +17 -0
- package/dist/components/messaging/MessageAttachment.svelte +273 -0
- package/dist/components/messaging/MessageAttachment.svelte.d.ts +13 -0
- package/dist/components/messaging/MessageAttachmentUpload.svelte +243 -0
- package/dist/components/messaging/MessageAttachmentUpload.svelte.d.ts +19 -0
- package/dist/components/messaging/MessageInput.svelte +452 -0
- package/dist/components/messaging/MessageInput.svelte.d.ts +28 -0
- package/dist/components/messaging/MessageItem.svelte +341 -0
- package/dist/components/messaging/MessageItem.svelte.d.ts +41 -0
- package/dist/components/messaging/MessageThread.svelte +306 -0
- package/dist/components/messaging/MessageThread.svelte.d.ts +30 -0
- package/dist/components/messaging/NotificationSettingsModal.svelte +234 -0
- package/dist/components/messaging/NotificationSettingsModal.svelte.d.ts +13 -0
- package/dist/components/messaging/QuotedMessageDisplay.svelte +123 -0
- package/dist/components/messaging/QuotedMessageDisplay.svelte.d.ts +10 -0
- package/dist/components/messaging/StartDMModal.svelte +100 -0
- package/dist/components/messaging/StartDMModal.svelte.d.ts +14 -0
- package/dist/components/messaging/ThreadPanel.svelte +153 -0
- package/dist/components/messaging/ThreadPanel.svelte.d.ts +16 -0
- package/dist/components/pipeline/DESIGN.md +361 -0
- package/dist/components/pipeline/Pipeline.svelte +391 -0
- package/dist/components/pipeline/Pipeline.svelte.d.ts +28 -0
- package/dist/components/pipeline/PipelineCard.svelte +94 -0
- package/dist/components/pipeline/PipelineCard.svelte.d.ts +13 -0
- package/dist/components/pipeline/PipelineColumn.svelte +163 -0
- package/dist/components/pipeline/PipelineColumn.svelte.d.ts +30 -0
- package/dist/components/replay/ChapterTimeline.svelte +326 -0
- package/dist/components/replay/ChapterTimeline.svelte.d.ts +39 -0
- package/dist/components/session-nav/transcriptModel.d.ts +132 -0
- package/dist/components/session-nav/transcriptModel.js +285 -0
- package/dist/data/emojis.d.ts +18 -0
- package/dist/data/emojis.js +1196 -0
- package/dist/index.d.ts +142 -0
- package/dist/index.js +142 -0
- package/dist/stores/confirmDialog.svelte.d.ts +21 -0
- package/dist/stores/confirmDialog.svelte.js +31 -0
- package/dist/stores/inputDialog.svelte.d.ts +24 -0
- package/dist/stores/inputDialog.svelte.js +32 -0
- package/dist/styles/rail.css +63 -0
- package/dist/types/annotation.d.ts +32 -0
- package/dist/types/annotation.js +3 -0
- package/dist/types/booking.d.ts +115 -0
- package/dist/types/booking.js +24 -0
- package/dist/types/comments.d.ts +65 -0
- package/dist/types/comments.js +22 -0
- package/dist/types/entityPreview.d.ts +42 -0
- package/dist/types/entityPreview.js +10 -0
- package/dist/types/filePicker.d.ts +15 -0
- package/dist/types/filePicker.js +1 -0
- package/dist/types/googleMaps.d.ts +51 -0
- package/dist/types/maps.d.ts +43 -0
- package/dist/types/maps.js +4 -0
- package/dist/types/messaging.d.ts +282 -0
- package/dist/types/messaging.js +100 -0
- package/dist/types/milestone.d.ts +20 -0
- package/dist/types/milestone.js +7 -0
- package/dist/types/pipeline.d.ts +115 -0
- package/dist/types/pipeline.js +15 -0
- package/dist/types/smartImageEditor.d.ts +42 -0
- package/dist/types/smartImageEditor.js +1 -0
- package/dist/types/templateVars.d.ts +34 -0
- package/dist/types/templateVars.js +12 -0
- package/dist/utils/currency.d.ts +8 -0
- package/dist/utils/currency.js +17 -0
- package/dist/utils/daisyuiColors.d.ts +37 -0
- package/dist/utils/daisyuiColors.js +152 -0
- package/dist/utils/dateFormatters.d.ts +69 -0
- package/dist/utils/dateFormatters.js +199 -0
- package/dist/utils/googleMapsLoader.d.ts +19 -0
- package/dist/utils/googleMapsLoader.js +121 -0
- package/dist/utils/mentionParser.d.ts +67 -0
- package/dist/utils/mentionParser.js +132 -0
- package/dist/utils/phone.d.ts +13 -0
- package/dist/utils/phone.js +67 -0
- package/dist/utils/phoneFormat.d.ts +26 -0
- package/dist/utils/phoneFormat.js +69 -0
- package/dist/utils/taskUtils.d.ts +37 -0
- package/dist/utils/taskUtils.js +71 -0
- package/package.json +3 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ImageProcessingSpec, VariantResult } from "../types/smartImageEditor";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
spec?: ImageProcessingSpec;
|
|
4
|
+
uploadEndpoint?: string;
|
|
5
|
+
value?: string;
|
|
6
|
+
onComplete?: (variants: VariantResult[]) => void;
|
|
7
|
+
/** Called when the user confirms delete on a variant tile. The host
|
|
8
|
+
* decides what "delete" means (typically: remove from storage + clear
|
|
9
|
+
* the stored URL). Returning false (or throwing) leaves the tile in
|
|
10
|
+
* place; returning truthy clears the tile's variant state. */
|
|
11
|
+
onDelete?: (variantName: string) => Promise<boolean | void> | boolean | void;
|
|
12
|
+
/** Called when the user drops/picks a file directly into an empty
|
|
13
|
+
* variant tile — bypasses the AI pipeline. The host uploads the file
|
|
14
|
+
* to its variant slot and returns the resulting VariantResult (or
|
|
15
|
+
* null on failure). When provided, idle tiles become drop-targets. */
|
|
16
|
+
onDirectUpload?: (variantName: string, file: File) => Promise<VariantResult | null>;
|
|
17
|
+
accept?: string;
|
|
18
|
+
maxSizeMb?: number;
|
|
19
|
+
/** Pre-populate variant cells with existing stored URLs (keyed by variant name). */
|
|
20
|
+
previewUrls?: Record<string, string>;
|
|
21
|
+
};
|
|
22
|
+
declare const SmartImageEditor: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
23
|
+
type SmartImageEditor = ReturnType<typeof SmartImageEditor>;
|
|
24
|
+
export default SmartImageEditor;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SortDropdown Component - Reusable sort dropdown with optional filter input
|
|
4
|
+
*
|
|
5
|
+
* A standardized dropdown for sorting lists with:
|
|
6
|
+
* - Sort button showing current option icon, label, and direction indicator
|
|
7
|
+
* - Dropdown menu with configurable sort options
|
|
8
|
+
* - Optional filter input for search/filtering
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
type SortDirection = 'asc' | 'desc';
|
|
12
|
+
|
|
13
|
+
export interface SortOption {
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
icon: string;
|
|
17
|
+
defaultDir?: SortDirection;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
/** Sort options array (required) */
|
|
22
|
+
options: SortOption[];
|
|
23
|
+
/** Current sort value */
|
|
24
|
+
sortBy: string;
|
|
25
|
+
/** Current sort direction */
|
|
26
|
+
sortDir: SortDirection;
|
|
27
|
+
/** Current filter input value */
|
|
28
|
+
filterValue?: string;
|
|
29
|
+
/** Whether to show the filter input */
|
|
30
|
+
showFilter?: boolean;
|
|
31
|
+
/** Placeholder text for filter input */
|
|
32
|
+
filterPlaceholder?: string;
|
|
33
|
+
/** Button size variant */
|
|
34
|
+
size?: 'xs' | 'sm' | 'md';
|
|
35
|
+
/** Show label on small screens */
|
|
36
|
+
showLabelOnMobile?: boolean;
|
|
37
|
+
/** Callback when sort changes */
|
|
38
|
+
onSortChange?: (value: string, dir: SortDirection) => void;
|
|
39
|
+
/** Callback when filter changes */
|
|
40
|
+
onFilterChange?: (value: string) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let {
|
|
44
|
+
options,
|
|
45
|
+
sortBy,
|
|
46
|
+
sortDir,
|
|
47
|
+
filterValue = '',
|
|
48
|
+
showFilter = false,
|
|
49
|
+
filterPlaceholder = 'Filter...',
|
|
50
|
+
size = 'xs',
|
|
51
|
+
showLabelOnMobile = false,
|
|
52
|
+
onSortChange,
|
|
53
|
+
onFilterChange
|
|
54
|
+
}: Props = $props();
|
|
55
|
+
|
|
56
|
+
// Find current sort option
|
|
57
|
+
const currentOption = $derived(options.find(o => o.value === sortBy));
|
|
58
|
+
const currentIcon = $derived(currentOption?.icon || '');
|
|
59
|
+
const currentLabel = $derived(currentOption?.label || 'Sort');
|
|
60
|
+
|
|
61
|
+
// Handle sort option click
|
|
62
|
+
function handleSortClick(value: string) {
|
|
63
|
+
if (sortBy === value) {
|
|
64
|
+
onSortChange?.(value, sortDir === 'asc' ? 'desc' : 'asc');
|
|
65
|
+
} else {
|
|
66
|
+
const opt = options.find(o => o.value === value);
|
|
67
|
+
onSortChange?.(value, opt?.defaultDir ?? 'asc');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Handle filter input change
|
|
72
|
+
function handleFilterInput(e: Event) {
|
|
73
|
+
const target = e.currentTarget as HTMLInputElement;
|
|
74
|
+
onFilterChange?.(target.value);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Size classes
|
|
78
|
+
const buttonSizeClass = $derived({
|
|
79
|
+
xs: 'btn-xs',
|
|
80
|
+
sm: 'btn-sm',
|
|
81
|
+
md: ''
|
|
82
|
+
}[size]);
|
|
83
|
+
|
|
84
|
+
const menuSizeClass = $derived({
|
|
85
|
+
xs: 'menu-xs',
|
|
86
|
+
sm: 'menu-sm',
|
|
87
|
+
md: ''
|
|
88
|
+
}[size]);
|
|
89
|
+
|
|
90
|
+
const inputSizeClass = $derived({
|
|
91
|
+
xs: 'input-xs',
|
|
92
|
+
sm: 'input-sm',
|
|
93
|
+
md: ''
|
|
94
|
+
}[size]);
|
|
95
|
+
|
|
96
|
+
const inputWidthClass = $derived({
|
|
97
|
+
xs: 'w-20 focus:w-32',
|
|
98
|
+
sm: 'w-24 focus:w-36',
|
|
99
|
+
md: 'w-32 focus:w-44'
|
|
100
|
+
}[size]);
|
|
101
|
+
|
|
102
|
+
import { fly } from 'svelte/transition';
|
|
103
|
+
import { cubicOut } from 'svelte/easing';
|
|
104
|
+
</script>
|
|
105
|
+
|
|
106
|
+
<div class="flex items-center gap-1">
|
|
107
|
+
<!-- Sort dropdown -->
|
|
108
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
109
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
110
|
+
<div class="dropdown dropdown-end flex-shrink-0" onclick={(e) => e.stopPropagation()}>
|
|
111
|
+
<button
|
|
112
|
+
tabindex="0"
|
|
113
|
+
class="btn {buttonSizeClass} btn-ghost gap-1 text-[0.75rem] opacity-70 hover:opacity-100"
|
|
114
|
+
title="Sort"
|
|
115
|
+
>
|
|
116
|
+
<span>{currentIcon}</span>
|
|
117
|
+
<span class="{showLabelOnMobile ? '' : 'hidden sm:inline'}">{currentLabel}</span>
|
|
118
|
+
<span class="text-[9px]">{sortDir === 'asc' ? '▲' : '▼'}</span>
|
|
119
|
+
</button>
|
|
120
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
121
|
+
<ul tabindex="0" class="dropdown-content menu {menuSizeClass} bg-base-200 rounded-box z-40 w-36 p-1 border border-base-300">
|
|
122
|
+
{#each options as opt (opt.value)}
|
|
123
|
+
<li>
|
|
124
|
+
<button
|
|
125
|
+
class="flex items-center gap-2 {sortBy === opt.value ? 'active' : ''}"
|
|
126
|
+
onclick={() => handleSortClick(opt.value)}
|
|
127
|
+
>
|
|
128
|
+
<span>{opt.icon}</span>
|
|
129
|
+
<span class="flex-1">{opt.label}</span>
|
|
130
|
+
{#if sortBy === opt.value}
|
|
131
|
+
<span class="text-[9px] opacity-70">{sortDir === 'asc' ? '▲' : '▼'}</span>
|
|
132
|
+
{/if}
|
|
133
|
+
</button>
|
|
134
|
+
</li>
|
|
135
|
+
{/each}
|
|
136
|
+
</ul>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<!-- Filter input (optional) -->
|
|
140
|
+
{#if showFilter}
|
|
141
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
142
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
143
|
+
<div class="flex-shrink-0" onclick={(e) => e.stopPropagation()}
|
|
144
|
+
in:fly={{ x: -8, duration: 180, easing: cubicOut }}
|
|
145
|
+
out:fly={{ x: -4, duration: 120, easing: cubicOut }}
|
|
146
|
+
>
|
|
147
|
+
<input
|
|
148
|
+
type="text"
|
|
149
|
+
placeholder={filterPlaceholder}
|
|
150
|
+
value={filterValue}
|
|
151
|
+
oninput={handleFilterInput}
|
|
152
|
+
class="input {inputSizeClass} input-bordered {inputWidthClass} transition-all duration-200 bg-base-200/50"
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
{/if}
|
|
156
|
+
</div>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SortDropdown Component - Reusable sort dropdown with optional filter input
|
|
3
|
+
*
|
|
4
|
+
* A standardized dropdown for sorting lists with:
|
|
5
|
+
* - Sort button showing current option icon, label, and direction indicator
|
|
6
|
+
* - Dropdown menu with configurable sort options
|
|
7
|
+
* - Optional filter input for search/filtering
|
|
8
|
+
*/
|
|
9
|
+
type SortDirection = 'asc' | 'desc';
|
|
10
|
+
export interface SortOption {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
icon: string;
|
|
14
|
+
defaultDir?: SortDirection;
|
|
15
|
+
}
|
|
16
|
+
interface Props {
|
|
17
|
+
/** Sort options array (required) */
|
|
18
|
+
options: SortOption[];
|
|
19
|
+
/** Current sort value */
|
|
20
|
+
sortBy: string;
|
|
21
|
+
/** Current sort direction */
|
|
22
|
+
sortDir: SortDirection;
|
|
23
|
+
/** Current filter input value */
|
|
24
|
+
filterValue?: string;
|
|
25
|
+
/** Whether to show the filter input */
|
|
26
|
+
showFilter?: boolean;
|
|
27
|
+
/** Placeholder text for filter input */
|
|
28
|
+
filterPlaceholder?: string;
|
|
29
|
+
/** Button size variant */
|
|
30
|
+
size?: 'xs' | 'sm' | 'md';
|
|
31
|
+
/** Show label on small screens */
|
|
32
|
+
showLabelOnMobile?: boolean;
|
|
33
|
+
/** Callback when sort changes */
|
|
34
|
+
onSortChange?: (value: string, dir: SortDirection) => void;
|
|
35
|
+
/** Callback when filter changes */
|
|
36
|
+
onFilterChange?: (value: string) => void;
|
|
37
|
+
}
|
|
38
|
+
declare const SortDropdown: import("svelte").Component<Props, {}, "">;
|
|
39
|
+
type SortDropdown = ReturnType<typeof SortDropdown>;
|
|
40
|
+
export default SortDropdown;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Sparkline — Lightweight D3 bar chart for trend visualization.
|
|
4
|
+
* Animated entrance with staggered bars, configurable color and opacity gradient.
|
|
5
|
+
*
|
|
6
|
+
* Requires `d3` as a peer dependency.
|
|
7
|
+
*/
|
|
8
|
+
import * as d3 from 'd3';
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
values,
|
|
12
|
+
width = 120,
|
|
13
|
+
height = 32,
|
|
14
|
+
color = 'var(--color-primary)',
|
|
15
|
+
fillOpacity = 0.15,
|
|
16
|
+
labels,
|
|
17
|
+
}: {
|
|
18
|
+
values: number[];
|
|
19
|
+
width?: number | 'auto';
|
|
20
|
+
height?: number;
|
|
21
|
+
color?: string;
|
|
22
|
+
fillOpacity?: number;
|
|
23
|
+
/** Optional tooltip label per bar. If provided, shown as SVG title on hover. */
|
|
24
|
+
labels?: string[];
|
|
25
|
+
} = $props();
|
|
26
|
+
|
|
27
|
+
let el: HTMLDivElement | undefined = $state();
|
|
28
|
+
let animated = false;
|
|
29
|
+
|
|
30
|
+
function getEffectiveWidth(): number {
|
|
31
|
+
if (width === 'auto' && el) return el.clientWidth;
|
|
32
|
+
if (typeof width === 'number') return width;
|
|
33
|
+
return 120;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
$effect(() => {
|
|
37
|
+
if (!el || values.length < 2) return;
|
|
38
|
+
|
|
39
|
+
const w = getEffectiveWidth();
|
|
40
|
+
if (w <= 0) return;
|
|
41
|
+
|
|
42
|
+
d3.select(el).select('svg').remove();
|
|
43
|
+
|
|
44
|
+
const pad = 1;
|
|
45
|
+
const innerW = w - pad * 2;
|
|
46
|
+
const innerH = height - pad * 2;
|
|
47
|
+
|
|
48
|
+
if (innerW <= 0 || innerH <= 0) return;
|
|
49
|
+
|
|
50
|
+
const svg = d3
|
|
51
|
+
.select(el)
|
|
52
|
+
.append('svg')
|
|
53
|
+
.attr('width', w)
|
|
54
|
+
.attr('height', height);
|
|
55
|
+
|
|
56
|
+
const g = svg.append('g').attr('transform', `translate(${pad},${pad})`);
|
|
57
|
+
|
|
58
|
+
const x = d3
|
|
59
|
+
.scaleBand<number>()
|
|
60
|
+
.domain(values.map((_, i) => i))
|
|
61
|
+
.range([0, innerW])
|
|
62
|
+
.padding(0.15);
|
|
63
|
+
|
|
64
|
+
const yMin = d3.min(values)! * 0.95;
|
|
65
|
+
const yMax = d3.max(values)! * 1.05;
|
|
66
|
+
const y = d3.scaleLinear().domain([yMin, yMax]).range([innerH, 0]);
|
|
67
|
+
|
|
68
|
+
const n = Math.max(1, values.length - 1);
|
|
69
|
+
const shouldAnimate = !animated;
|
|
70
|
+
animated = true;
|
|
71
|
+
|
|
72
|
+
const bars = g
|
|
73
|
+
.selectAll('.bar')
|
|
74
|
+
.data(values)
|
|
75
|
+
.join('rect')
|
|
76
|
+
.attr('x', (_, i) => x(i)!)
|
|
77
|
+
.attr('width', x.bandwidth())
|
|
78
|
+
.attr('rx', Math.min(1, x.bandwidth() / 4))
|
|
79
|
+
.style('fill', color)
|
|
80
|
+
.style('fill-opacity', (_, i) => fillOpacity + (1 - fillOpacity) * (i / n));
|
|
81
|
+
|
|
82
|
+
bars.each(function (d, i) {
|
|
83
|
+
d3.select(this).selectAll('title').remove();
|
|
84
|
+
const label = labels && labels[i] !== undefined ? labels[i] : String(d);
|
|
85
|
+
d3.select(this).append('title').text(label);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (shouldAnimate) {
|
|
89
|
+
bars
|
|
90
|
+
.attr('y', innerH)
|
|
91
|
+
.attr('height', 0)
|
|
92
|
+
.transition()
|
|
93
|
+
.duration(400)
|
|
94
|
+
.delay((_, i) => i * 15)
|
|
95
|
+
.ease(d3.easeCubicOut)
|
|
96
|
+
.attr('y', (d) => y(d))
|
|
97
|
+
.attr('height', (d) => innerH - y(d));
|
|
98
|
+
} else {
|
|
99
|
+
bars.attr('y', (d) => y(d)).attr('height', (d) => innerH - y(d));
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
{#if values.length >= 2}
|
|
105
|
+
<div
|
|
106
|
+
bind:this={el}
|
|
107
|
+
style="{width === 'auto' ? 'width: 100%' : `width: ${width}px`}; height: {height}px"
|
|
108
|
+
></div>
|
|
109
|
+
{:else}
|
|
110
|
+
<div
|
|
111
|
+
class="flex items-center justify-center text-base-content/30 text-xs"
|
|
112
|
+
style="{width === 'auto' ? 'width: 100%' : `width: ${width}px`}; height: {height}px"
|
|
113
|
+
>
|
|
114
|
+
--
|
|
115
|
+
</div>
|
|
116
|
+
{/if}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
values: number[];
|
|
3
|
+
width?: number | 'auto';
|
|
4
|
+
height?: number;
|
|
5
|
+
color?: string;
|
|
6
|
+
fillOpacity?: number;
|
|
7
|
+
/** Optional tooltip label per bar. If provided, shown as SVG title on hover. */
|
|
8
|
+
labels?: string[];
|
|
9
|
+
};
|
|
10
|
+
declare const Sparkline: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type Sparkline = ReturnType<typeof Sparkline>;
|
|
12
|
+
export default Sparkline;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SpeechForm — Text-to-speech generation form with voice selection, character limit, and audio preview.
|
|
4
|
+
*
|
|
5
|
+
* Voice options are configurable via the `voiceOptions` prop. Includes a textarea with character counter,
|
|
6
|
+
* voice selector dropdown, optional audio preview player, and submit/cancel buttons.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
text = $bindable(""),
|
|
11
|
+
voice = $bindable("en-US-female-27"),
|
|
12
|
+
previewUrl = null,
|
|
13
|
+
isCreating = false,
|
|
14
|
+
maxLength = 1000,
|
|
15
|
+
voiceOptions = [
|
|
16
|
+
{ id: "en-US-female-27", label: "US Female (Clear)" },
|
|
17
|
+
{ id: "en-US-male-27", label: "US Male (Clear)" },
|
|
18
|
+
{ id: "en-GB-female-11", label: "UK Female" },
|
|
19
|
+
{ id: "en-GB-male-10", label: "UK Male" },
|
|
20
|
+
{ id: "en-US-female-24", label: "US Female (Warm)" },
|
|
21
|
+
{ id: "en-US-male-24", label: "US Male (Deep)" },
|
|
22
|
+
],
|
|
23
|
+
infoText = "The system will convert your text to natural-sounding speech which you can download and use.",
|
|
24
|
+
onSubmit,
|
|
25
|
+
onCancel,
|
|
26
|
+
} = $props<{
|
|
27
|
+
text?: string
|
|
28
|
+
voice?: string
|
|
29
|
+
previewUrl?: string | null
|
|
30
|
+
isCreating?: boolean
|
|
31
|
+
maxLength?: number
|
|
32
|
+
voiceOptions?: { id: string; label: string }[]
|
|
33
|
+
infoText?: string
|
|
34
|
+
onSubmit: () => void
|
|
35
|
+
onCancel: () => void
|
|
36
|
+
}>()
|
|
37
|
+
|
|
38
|
+
let remaining = $derived(maxLength - (text?.length || 0))
|
|
39
|
+
|
|
40
|
+
$effect(() => {
|
|
41
|
+
return () => {
|
|
42
|
+
if (previewUrl) {
|
|
43
|
+
URL.revokeObjectURL(previewUrl)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<div class="space-y-4">
|
|
50
|
+
<div class="form-control">
|
|
51
|
+
<label class="label" for="speech-text-input">
|
|
52
|
+
<span class="label-text font-medium">Text to Convert</span>
|
|
53
|
+
<span class="label-text-alt">{remaining} characters left</span>
|
|
54
|
+
</label>
|
|
55
|
+
<textarea
|
|
56
|
+
id="speech-text-input"
|
|
57
|
+
bind:value={text}
|
|
58
|
+
placeholder="Enter the text you want to convert to speech..."
|
|
59
|
+
class="textarea min-h-32"
|
|
60
|
+
maxlength={maxLength}
|
|
61
|
+
disabled={isCreating}
|
|
62
|
+
></textarea>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="form-control">
|
|
66
|
+
<label class="label" for="speech-voice-select">
|
|
67
|
+
<span class="label-text font-medium">Voice</span>
|
|
68
|
+
</label>
|
|
69
|
+
<select id="speech-voice-select" bind:value={voice} class="select" disabled={isCreating}>
|
|
70
|
+
{#each voiceOptions as option}
|
|
71
|
+
<option value={option.id}>{option.label}</option>
|
|
72
|
+
{/each}
|
|
73
|
+
</select>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{#if previewUrl}
|
|
77
|
+
<div class="form-control">
|
|
78
|
+
<div class="label">
|
|
79
|
+
<span class="label-text font-medium">Preview</span>
|
|
80
|
+
</div>
|
|
81
|
+
<audio src={previewUrl} controls class="w-full" aria-label="Generated speech preview">
|
|
82
|
+
Your browser does not support the audio element.
|
|
83
|
+
</audio>
|
|
84
|
+
</div>
|
|
85
|
+
{/if}
|
|
86
|
+
|
|
87
|
+
{#if infoText}
|
|
88
|
+
<div class="flex items-center gap-2 text-info bg-info/10 p-3 rounded">
|
|
89
|
+
<!-- Info icon -->
|
|
90
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
|
|
91
|
+
<p class="text-sm">{infoText}</p>
|
|
92
|
+
</div>
|
|
93
|
+
{/if}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="flex justify-end gap-2 mt-6">
|
|
97
|
+
<button class="btn btn-ghost" onclick={onCancel} disabled={isCreating}>
|
|
98
|
+
Cancel
|
|
99
|
+
</button>
|
|
100
|
+
<button
|
|
101
|
+
class="btn btn-primary gap-2"
|
|
102
|
+
onclick={onSubmit}
|
|
103
|
+
disabled={isCreating || !text}
|
|
104
|
+
>
|
|
105
|
+
{#if isCreating}
|
|
106
|
+
<span class="loading loading-spinner loading-sm"></span>
|
|
107
|
+
Converting...
|
|
108
|
+
{:else}
|
|
109
|
+
<!-- Mic icon -->
|
|
110
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>
|
|
111
|
+
Generate Speech
|
|
112
|
+
{/if}
|
|
113
|
+
</button>
|
|
114
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
text?: string;
|
|
3
|
+
voice?: string;
|
|
4
|
+
previewUrl?: string | null;
|
|
5
|
+
isCreating?: boolean;
|
|
6
|
+
maxLength?: number;
|
|
7
|
+
voiceOptions?: {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
}[];
|
|
11
|
+
infoText?: string;
|
|
12
|
+
onSubmit: () => void;
|
|
13
|
+
onCancel: () => void;
|
|
14
|
+
};
|
|
15
|
+
declare const SpeechForm: import("svelte").Component<$$ComponentProps, {}, "text" | "voice">;
|
|
16
|
+
type SpeechForm = ReturnType<typeof SpeechForm>;
|
|
17
|
+
export default SpeechForm;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
export type StatusValue =
|
|
3
|
+
| 'active'
|
|
4
|
+
| 'inactive'
|
|
5
|
+
| 'pending'
|
|
6
|
+
| 'completed'
|
|
7
|
+
| 'cancelled'
|
|
8
|
+
| 'draft'
|
|
9
|
+
| 'scheduled'
|
|
10
|
+
| 'in-progress'
|
|
11
|
+
| 'overdue'
|
|
12
|
+
| 'paid'
|
|
13
|
+
| 'unpaid'
|
|
14
|
+
| 'partial'
|
|
15
|
+
| 'assigned'
|
|
16
|
+
| 'available';
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
/**
|
|
21
|
+
* StatusBadge Component
|
|
22
|
+
*
|
|
23
|
+
* Predefined status badge with semantic colors, icons, and dot indicators.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
interface Props {
|
|
27
|
+
status: StatusValue;
|
|
28
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
29
|
+
showIcon?: boolean;
|
|
30
|
+
showDot?: boolean;
|
|
31
|
+
customText?: string;
|
|
32
|
+
clickable?: boolean;
|
|
33
|
+
outlined?: boolean;
|
|
34
|
+
class?: string;
|
|
35
|
+
ariaLabel?: string;
|
|
36
|
+
onclick?: (event: { event: MouseEvent; status: string }) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let {
|
|
40
|
+
status,
|
|
41
|
+
size = 'md',
|
|
42
|
+
showIcon = false,
|
|
43
|
+
showDot = false,
|
|
44
|
+
customText = '',
|
|
45
|
+
clickable = false,
|
|
46
|
+
outlined = false,
|
|
47
|
+
class: className = '',
|
|
48
|
+
ariaLabel = '',
|
|
49
|
+
onclick
|
|
50
|
+
}: Props = $props();
|
|
51
|
+
|
|
52
|
+
const statusConfig: Record<string, { text: string; variant: string; icon: string }> = {
|
|
53
|
+
active: { text: 'Active', variant: 'success', icon: '✓' },
|
|
54
|
+
inactive: { text: 'Inactive', variant: 'error', icon: '✗' },
|
|
55
|
+
pending: { text: 'Pending', variant: 'warning', icon: '' },
|
|
56
|
+
completed: { text: 'Completed', variant: 'success', icon: '✓' },
|
|
57
|
+
cancelled: { text: 'Cancelled', variant: 'error', icon: '✗' },
|
|
58
|
+
draft: { text: 'Draft', variant: 'default', icon: '' },
|
|
59
|
+
scheduled: { text: 'Scheduled', variant: 'info', icon: '' },
|
|
60
|
+
'in-progress': { text: 'In Progress', variant: 'primary', icon: '' },
|
|
61
|
+
overdue: { text: 'Overdue', variant: 'error', icon: '' },
|
|
62
|
+
paid: { text: 'Paid', variant: 'success', icon: '✓' },
|
|
63
|
+
unpaid: { text: 'Unpaid', variant: 'warning', icon: '' },
|
|
64
|
+
partial: { text: 'Partial', variant: 'warning', icon: '' },
|
|
65
|
+
assigned: { text: 'Assigned', variant: 'success', icon: '✓' },
|
|
66
|
+
available: { text: 'Available', variant: 'info', icon: '' }
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const config = $derived(statusConfig[status] || { text: status || 'Unknown', variant: 'default', icon: '?' });
|
|
70
|
+
const displayText = $derived(customText || config.text);
|
|
71
|
+
|
|
72
|
+
const variantMap: Record<string, string> = {
|
|
73
|
+
default: 'badge-ghost',
|
|
74
|
+
primary: 'badge-primary',
|
|
75
|
+
secondary: 'badge-secondary',
|
|
76
|
+
accent: 'badge-accent',
|
|
77
|
+
success: 'badge-success',
|
|
78
|
+
warning: 'badge-warning',
|
|
79
|
+
error: 'badge-error',
|
|
80
|
+
info: 'badge-info'
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const outlinedVariantMap: Record<string, string> = {
|
|
84
|
+
default: 'badge-outline',
|
|
85
|
+
primary: 'badge-primary badge-outline',
|
|
86
|
+
secondary: 'badge-secondary badge-outline',
|
|
87
|
+
accent: 'badge-accent badge-outline',
|
|
88
|
+
success: 'badge-success badge-outline',
|
|
89
|
+
warning: 'badge-warning badge-outline',
|
|
90
|
+
error: 'badge-error badge-outline',
|
|
91
|
+
info: 'badge-info badge-outline'
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const variantClass = $derived(outlined ? outlinedVariantMap[config.variant] : variantMap[config.variant]);
|
|
95
|
+
const sizeClass = $derived({ xs: 'badge-xs', sm: 'badge-sm', md: 'badge-md', lg: 'badge-lg' }[size]);
|
|
96
|
+
|
|
97
|
+
const dotColor = $derived(
|
|
98
|
+
{
|
|
99
|
+
default: 'bg-base-content',
|
|
100
|
+
primary: 'bg-primary',
|
|
101
|
+
secondary: 'bg-secondary',
|
|
102
|
+
accent: 'bg-accent',
|
|
103
|
+
success: 'bg-success',
|
|
104
|
+
warning: 'bg-warning',
|
|
105
|
+
error: 'bg-error',
|
|
106
|
+
info: 'bg-info'
|
|
107
|
+
}[config.variant]
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const badgeClass = $derived(
|
|
111
|
+
['badge', variantClass, sizeClass, clickable ? 'cursor-pointer hover:opacity-80' : '', className]
|
|
112
|
+
.filter(Boolean)
|
|
113
|
+
.join(' ')
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
function handleClick(event: MouseEvent) {
|
|
117
|
+
if (clickable && onclick) {
|
|
118
|
+
onclick({ event, status });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
123
|
+
if (clickable && onclick && (event.key === 'Enter' || event.key === ' ')) {
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
onclick({ event: event as any, status });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
</script>
|
|
129
|
+
|
|
130
|
+
{#if clickable}
|
|
131
|
+
<span
|
|
132
|
+
class={badgeClass}
|
|
133
|
+
role="button"
|
|
134
|
+
tabindex="0"
|
|
135
|
+
aria-label={ariaLabel || `Status: ${displayText}`}
|
|
136
|
+
onclick={handleClick}
|
|
137
|
+
onkeydown={handleKeyDown}
|
|
138
|
+
>
|
|
139
|
+
{#if showDot}
|
|
140
|
+
<span class="w-2 h-2 rounded-full {dotColor} mr-1.5 {status === 'active' ? 'animate-pulse' : ''}"></span>
|
|
141
|
+
{/if}
|
|
142
|
+
{#if showIcon}
|
|
143
|
+
<span class="mr-1">{config.icon}</span>
|
|
144
|
+
{/if}
|
|
145
|
+
{displayText}
|
|
146
|
+
</span>
|
|
147
|
+
{:else}
|
|
148
|
+
<span class={badgeClass} aria-label={ariaLabel || `Status: ${displayText}`}>
|
|
149
|
+
{#if showDot}
|
|
150
|
+
<span class="w-2 h-2 rounded-full {dotColor} mr-1.5 {status === 'active' ? 'animate-pulse' : ''}"></span>
|
|
151
|
+
{/if}
|
|
152
|
+
{#if showIcon}
|
|
153
|
+
<span class="mr-1">{config.icon}</span>
|
|
154
|
+
{/if}
|
|
155
|
+
{displayText}
|
|
156
|
+
</span>
|
|
157
|
+
{/if}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type StatusValue = 'active' | 'inactive' | 'pending' | 'completed' | 'cancelled' | 'draft' | 'scheduled' | 'in-progress' | 'overdue' | 'paid' | 'unpaid' | 'partial' | 'assigned' | 'available';
|
|
2
|
+
/**
|
|
3
|
+
* StatusBadge Component
|
|
4
|
+
*
|
|
5
|
+
* Predefined status badge with semantic colors, icons, and dot indicators.
|
|
6
|
+
*/
|
|
7
|
+
interface Props {
|
|
8
|
+
status: StatusValue;
|
|
9
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
10
|
+
showIcon?: boolean;
|
|
11
|
+
showDot?: boolean;
|
|
12
|
+
customText?: string;
|
|
13
|
+
clickable?: boolean;
|
|
14
|
+
outlined?: boolean;
|
|
15
|
+
class?: string;
|
|
16
|
+
ariaLabel?: string;
|
|
17
|
+
onclick?: (event: {
|
|
18
|
+
event: MouseEvent;
|
|
19
|
+
status: string;
|
|
20
|
+
}) => void;
|
|
21
|
+
}
|
|
22
|
+
declare const StatusBadge: import("svelte").Component<Props, {}, "">;
|
|
23
|
+
type StatusBadge = ReturnType<typeof StatusBadge>;
|
|
24
|
+
export default StatusBadge;
|