@makolabs/ripple 2.5.9 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +403 -497
- package/dist/adapters/storage/S3Adapter.d.ts +49 -1
- package/dist/adapters/storage/S3Adapter.js +38 -1
- package/dist/adapters/storage/types.d.ts +20 -0
- package/dist/ai/AIChatInterface.svelte +2 -1
- package/dist/ai/AIChatInterface.svelte.d.ts +2 -1
- package/dist/ai/CodeRenderer.svelte +7 -2
- package/dist/ai/CodeRenderer.svelte.d.ts +2 -1
- package/dist/ai/ComposeDropdown.svelte +1 -1
- package/dist/ai/MessageBox.svelte +3 -3
- package/dist/ai/MessageBox.svelte.d.ts +3 -2
- package/dist/ai/ThinkingDisplay.svelte +4 -3
- package/dist/ai/ThinkingDisplay.svelte.d.ts +2 -1
- package/dist/ai/ai-types.d.ts +55 -1
- package/dist/button/Button.svelte +5 -5
- package/dist/button/button-types.d.ts +49 -4
- package/dist/button/button.d.ts +9 -9
- package/dist/button/button.js +6 -6
- package/dist/charts/Chart.svelte +8 -16
- package/dist/charts/chart-types.d.ts +78 -1
- package/dist/drawer/Drawer.svelte +6 -26
- package/dist/drawer/drawer-types.d.ts +33 -12
- package/dist/drawer/drawer.d.ts +3 -3
- package/dist/drawer/drawer.js +1 -1
- package/dist/elements/accordion/Accordion.svelte +6 -17
- package/dist/elements/accordion/accordion-types.d.ts +53 -6
- package/dist/elements/alert/Alert.svelte +3 -0
- package/dist/elements/badge/Badge.svelte +1 -1
- package/dist/elements/badge/badge-types.d.ts +22 -0
- package/dist/elements/badge/badge.d.ts +3 -3
- package/dist/elements/badge/badge.js +1 -1
- package/dist/elements/combobox/ComboBox.svelte +244 -0
- package/dist/elements/combobox/ComboBox.svelte.d.ts +4 -0
- package/dist/elements/combobox/combobox-types.d.ts +41 -0
- package/dist/elements/combobox/combobox-types.js +1 -0
- package/dist/elements/context-menu/ContextMenu.svelte +137 -0
- package/dist/elements/context-menu/ContextMenu.svelte.d.ts +4 -0
- package/dist/elements/context-menu/context-menu-types.d.ts +40 -0
- package/dist/elements/context-menu/context-menu-types.js +1 -0
- package/dist/elements/dropdown/Dropdown.svelte +1 -1
- package/dist/elements/dropdown/Select.svelte +4 -1
- package/dist/elements/dropdown/dropdown-types.d.ts +114 -0
- package/dist/elements/dropdown/dropdown.d.ts +3 -3
- package/dist/elements/dropdown/dropdown.js +2 -2
- package/dist/elements/dropdown/select.d.ts +3 -108
- package/dist/elements/dropdown/select.js +38 -47
- package/dist/elements/empty-state/EmptyState.svelte +1 -1
- package/dist/elements/empty-state/empty-state-types.d.ts +32 -1
- package/dist/elements/empty-state/empty-state.d.ts +3 -3
- package/dist/elements/empty-state/empty-state.js +2 -2
- package/dist/elements/file-upload/FileUpload.svelte +5 -0
- package/dist/elements/file-upload/file-upload-types.d.ts +59 -0
- package/dist/elements/pagination/Pagination.svelte +53 -21
- package/dist/elements/pagination/Pagination.svelte.d.ts +33 -5
- package/dist/elements/popover/Popover.svelte +254 -0
- package/dist/elements/popover/Popover.svelte.d.ts +4 -0
- package/dist/elements/popover/index.d.ts +2 -0
- package/dist/elements/popover/index.js +1 -0
- package/dist/elements/popover/popover-types.d.ts +60 -0
- package/dist/elements/popover/popover-types.js +1 -0
- package/dist/elements/progress/Progress.svelte +32 -7
- package/dist/elements/progress/progress-types.d.ts +48 -1
- package/dist/elements/skeleton/Skeleton.svelte +56 -0
- package/dist/elements/skeleton/Skeleton.svelte.d.ts +4 -0
- package/dist/elements/skeleton/index.d.ts +2 -0
- package/dist/elements/skeleton/index.js +1 -0
- package/dist/elements/skeleton/skeleton-types.d.ts +50 -0
- package/dist/elements/skeleton/skeleton-types.js +1 -0
- package/dist/elements/spinner/Spinner.svelte +1 -1
- package/dist/elements/spinner/spinner-types.d.ts +20 -0
- package/dist/elements/spinner/spinner.d.ts +3 -3
- package/dist/elements/spinner/spinner.js +2 -2
- package/dist/elements/tooltip/Tooltip.svelte +108 -11
- package/dist/elements/tooltip/tooltip-types.d.ts +49 -1
- package/dist/file-browser/FileBrowser.svelte +21 -12
- package/dist/filters/CompactFilters.svelte +221 -33
- package/dist/filters/CompactFilters.svelte.d.ts +1 -1
- package/dist/filters/FilterBar.svelte +184 -0
- package/dist/filters/FilterBar.svelte.d.ts +4 -0
- package/dist/filters/FilterPopover.svelte +346 -0
- package/dist/filters/FilterPopover.svelte.d.ts +4 -0
- package/dist/filters/date-presets.d.ts +15 -0
- package/dist/filters/date-presets.js +107 -0
- package/dist/filters/filter-types.d.ts +69 -3
- package/dist/filters/index.d.ts +5 -0
- package/dist/filters/index.js +4 -0
- package/dist/filters/sync-filters-to-url.svelte.d.ts +37 -0
- package/dist/filters/sync-filters-to-url.svelte.js +114 -0
- package/dist/forms/Checkbox.svelte +24 -9
- package/dist/forms/DateRange.svelte +23 -6
- package/dist/forms/Input.svelte +19 -19
- package/dist/forms/MarketSelector.svelte +9 -4
- package/dist/forms/NumberInput.svelte +14 -18
- package/dist/forms/RadioGroup.svelte +127 -0
- package/dist/forms/RadioGroup.svelte.d.ts +4 -0
- package/dist/forms/SegmentedControl.svelte +11 -4
- package/dist/forms/Slider.svelte +72 -3
- package/dist/forms/Tags.svelte +44 -14
- package/dist/forms/Textarea.svelte +121 -0
- package/dist/forms/Textarea.svelte.d.ts +4 -0
- package/dist/forms/Toggle.svelte +30 -22
- package/dist/forms/calendar/Calendar.svelte +315 -0
- package/dist/forms/calendar/Calendar.svelte.d.ts +4 -0
- package/dist/forms/calendar/calendar-types.d.ts +54 -0
- package/dist/forms/calendar/calendar-types.js +1 -0
- package/dist/forms/calendar/index.d.ts +2 -0
- package/dist/forms/calendar/index.js +1 -0
- package/dist/forms/date-picker/DatePicker.svelte +141 -0
- package/dist/forms/date-picker/DatePicker.svelte.d.ts +4 -0
- package/dist/forms/date-picker/date-picker-types.d.ts +29 -0
- package/dist/forms/date-picker/date-picker-types.js +1 -0
- package/dist/forms/form-size.d.ts +37 -0
- package/dist/forms/form-size.js +67 -0
- package/dist/forms/form-types.d.ts +430 -6
- package/dist/forms/market/market-selector-types.d.ts +52 -1
- package/dist/forms/segmented-control.d.ts +5 -2
- package/dist/forms/segmented-control.js +25 -13
- package/dist/forms/slider.d.ts +3 -3
- package/dist/forms/slider.js +37 -30
- package/dist/funcs/user-management.remote.js +1 -1
- package/dist/header/Breadcrumbs.svelte +4 -20
- package/dist/header/PageHeader.svelte +6 -14
- package/dist/header/breadcrumbs.d.ts +3 -11
- package/dist/header/breadcrumbs.js +10 -5
- package/dist/header/header-types.d.ts +62 -11
- package/dist/index.d.ts +35 -9
- package/dist/index.js +24 -4
- package/dist/layout/activity-list/ActivityList.svelte +13 -7
- package/dist/layout/activity-list/activity-list-types.d.ts +46 -7
- package/dist/layout/card/Card.svelte +12 -15
- package/dist/layout/card/MetricCard.svelte +50 -32
- package/dist/layout/card/card-types.d.ts +114 -4
- package/dist/layout/navbar/navbar-types.d.ts +48 -0
- package/dist/layout/navbar/navbar.d.ts +3 -3
- package/dist/layout/navbar/navbar.js +2 -2
- package/dist/layout/sidebar/Sidebar.svelte +87 -11
- package/dist/layout/sidebar/sidebar-types.d.ts +60 -1
- package/dist/layout/stepper/Stepper.svelte +288 -0
- package/dist/layout/stepper/Stepper.svelte.d.ts +4 -0
- package/dist/layout/stepper/stepper-types.d.ts +80 -0
- package/dist/layout/stepper/stepper-types.js +1 -0
- package/dist/layout/table/Table.svelte +91 -85
- package/dist/layout/table/table-types.d.ts +148 -24
- package/dist/layout/table/table.d.ts +3 -3
- package/dist/layout/table/table.js +2 -2
- package/dist/layout/tabs/Tab.svelte +6 -2
- package/dist/layout/tabs/Tab.svelte.d.ts +4 -1
- package/dist/layout/tabs/TabGroup.svelte +9 -2
- package/dist/layout/tabs/tabs-types.d.ts +63 -0
- package/dist/layout/tabs/tabs.d.ts +3 -3
- package/dist/layout/tabs/tabs.js +12 -6
- package/dist/modal/ConfirmDialog.svelte +65 -0
- package/dist/modal/ConfirmDialog.svelte.d.ts +4 -0
- package/dist/modal/Modal.svelte +6 -26
- package/dist/modal/confirm-dialog-types.d.ts +39 -0
- package/dist/modal/confirm-dialog-types.js +1 -0
- package/dist/modal/modal-types.d.ts +51 -12
- package/dist/modal/modal.d.ts +3 -3
- package/dist/modal/modal.js +3 -3
- package/dist/pipeline/Pipeline.svelte +8 -3
- package/dist/pipeline/pipeline-types.d.ts +55 -3
- package/dist/pipeline/pipeline.d.ts +18 -3
- package/dist/pipeline/pipeline.js +7 -2
- package/dist/server/s3.d.ts +35 -3
- package/dist/sonner/Toaster.svelte +29 -0
- package/dist/sonner/Toaster.svelte.d.ts +4 -0
- package/dist/sonner/index.d.ts +21 -0
- package/dist/sonner/index.js +20 -0
- package/dist/user-management/UserManagement.svelte +22 -16
- package/dist/user-management/UserModal.svelte +10 -7
- package/dist/user-management/UserTable.svelte +16 -17
- package/dist/user-management/UserViewModal.svelte +11 -11
- package/dist/user-management/user-management-types.d.ts +118 -31
- package/dist/variants.d.ts +1 -1
- package/dist/variants.js +1 -1
- package/package.json +7 -4
- package/dist/config/ai.d.ts +0 -13
- package/dist/config/ai.js +0 -44
- package/dist/elements/empty-state/EmptyStateTestWrapper.svelte +0 -25
- package/dist/elements/empty-state/EmptyStateTestWrapper.svelte.d.ts +0 -8
- package/dist/elements/tooltip/TooltipTestWrapper.svelte +0 -14
- package/dist/elements/tooltip/TooltipTestWrapper.svelte.d.ts +0 -7
- package/dist/helper/deprecation.d.ts +0 -14
- package/dist/helper/deprecation.js +0 -24
- package/dist/modal/ModalFooterTestWrapper.svelte +0 -17
- package/dist/modal/ModalFooterTestWrapper.svelte.d.ts +0 -8
|
@@ -1,22 +1,69 @@
|
|
|
1
1
|
import type { ClassValue } from 'tailwind-variants';
|
|
2
2
|
import type { VariantColors, VariantSizes } from '../../index.js';
|
|
3
|
+
/** One segment of a multi-segment progress bar (`ProgressProps.segments`). */
|
|
3
4
|
export type ProgressSegment = {
|
|
5
|
+
/** Segment size. Treated as a share of `max` (so segment values should sum to ≤ `max`). */
|
|
4
6
|
value: number;
|
|
7
|
+
/** Segment fill color. */
|
|
5
8
|
color: VariantColors;
|
|
9
|
+
/** Optional label rendered inside the legend when `showLabels` is set. */
|
|
6
10
|
label?: string;
|
|
7
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Props for `<Progress>` — a horizontal progress bar. Supports two modes:
|
|
14
|
+
* 1. **Single value** — pass `value` (and optionally `max`). Renders one filled bar.
|
|
15
|
+
* 2. **Segmented** — pass `segments: ProgressSegment[]`. Renders a stacked bar with
|
|
16
|
+
* per-segment colors and an optional legend below.
|
|
17
|
+
*
|
|
18
|
+
* For KPI-style displays where the progress bar is part of a card,
|
|
19
|
+
* `<MetricCard>` accepts the same `percent`/`segments` props directly.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```svelte
|
|
23
|
+
* <!-- Simple -->
|
|
24
|
+
* <Progress value={68} showLabel />
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```svelte
|
|
29
|
+
* <!-- Multi-segment with legend -->
|
|
30
|
+
* <Progress
|
|
31
|
+
* max={100}
|
|
32
|
+
* segments={[
|
|
33
|
+
* { value: 50, color: 'success', label: 'Healthy' },
|
|
34
|
+
* { value: 30, color: 'warning', label: 'Warning' },
|
|
35
|
+
* { value: 20, color: 'danger', label: 'Critical' }
|
|
36
|
+
* ]}
|
|
37
|
+
* showLabels
|
|
38
|
+
* showValues
|
|
39
|
+
* />
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
8
42
|
export type ProgressProps = {
|
|
9
|
-
value
|
|
43
|
+
/** Current value (single-mode). Ignored when `segments` is provided. @default 0 */
|
|
44
|
+
value?: number;
|
|
45
|
+
/** Max scale value. @default 100 */
|
|
10
46
|
max?: number;
|
|
11
47
|
size?: VariantSizes;
|
|
48
|
+
/** Fill color for single-mode. @default 'primary' */
|
|
12
49
|
color?: VariantColors;
|
|
50
|
+
/** Show "value / max" label next to the bar (single-mode). @default false */
|
|
13
51
|
showLabel?: boolean;
|
|
52
|
+
/** Where to render the label. @default 'top' */
|
|
14
53
|
labelPosition?: 'top' | 'bottom' | 'right';
|
|
54
|
+
/**
|
|
55
|
+
* Segmented bars — when provided, takes precedence over `value`.
|
|
56
|
+
* Each segment renders in its own color, and an optional legend
|
|
57
|
+
* appears below when `showLabels` or `showValues` is set.
|
|
58
|
+
*/
|
|
15
59
|
segments?: ProgressSegment[];
|
|
60
|
+
/** Show the legend under segmented bars. @default false */
|
|
16
61
|
showLabels?: boolean;
|
|
62
|
+
/** Show numeric values alongside labels in the legend. @default false */
|
|
17
63
|
showValues?: boolean;
|
|
18
64
|
class?: ClassValue;
|
|
19
65
|
labelClass?: ClassValue;
|
|
66
|
+
/** Classes on the inner bar element(s). */
|
|
20
67
|
barClass?: ClassValue;
|
|
21
68
|
testId?: string;
|
|
22
69
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { buildTestId } from '../../helper/testid.js';
|
|
4
|
+
import type { SkeletonProps } from './skeleton-types.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
class: className = '',
|
|
8
|
+
variant = 'pulse',
|
|
9
|
+
rounded = 'rounded-md',
|
|
10
|
+
ariaLabel = 'Loading',
|
|
11
|
+
style,
|
|
12
|
+
testId
|
|
13
|
+
}: SkeletonProps = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class={cn(
|
|
18
|
+
'bg-default-200',
|
|
19
|
+
rounded,
|
|
20
|
+
variant === 'pulse' && 'animate-pulse',
|
|
21
|
+
variant === 'shimmer' && 'ripple-skeleton-shimmer overflow-hidden',
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
{style}
|
|
25
|
+
role="status"
|
|
26
|
+
aria-label={ariaLabel}
|
|
27
|
+
aria-busy="true"
|
|
28
|
+
data-testid={buildTestId('skeleton', undefined, testId)}
|
|
29
|
+
></div>
|
|
30
|
+
|
|
31
|
+
<style>
|
|
32
|
+
/* Shimmer variant: gradient sweep using a CSS animation. Kept here (not Tailwind)
|
|
33
|
+
because moving gradients aren't expressible with Tailwind utilities. */
|
|
34
|
+
.ripple-skeleton-shimmer {
|
|
35
|
+
position: relative;
|
|
36
|
+
isolation: isolate;
|
|
37
|
+
}
|
|
38
|
+
.ripple-skeleton-shimmer::after {
|
|
39
|
+
content: '';
|
|
40
|
+
position: absolute;
|
|
41
|
+
inset: 0;
|
|
42
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
|
|
43
|
+
transform: translateX(-100%);
|
|
44
|
+
animation: ripple-skeleton-shimmer 1.6s infinite;
|
|
45
|
+
}
|
|
46
|
+
@keyframes ripple-skeleton-shimmer {
|
|
47
|
+
100% {
|
|
48
|
+
transform: translateX(100%);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
@media (prefers-reduced-motion: reduce) {
|
|
52
|
+
.ripple-skeleton-shimmer::after {
|
|
53
|
+
animation: none;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Skeleton } from './Skeleton.svelte';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ClassValue } from 'tailwind-variants';
|
|
2
|
+
/**
|
|
3
|
+
* Animation style for `<Skeleton>`.
|
|
4
|
+
* - `'pulse'` — subtle opacity pulse (Tailwind's `animate-pulse`)
|
|
5
|
+
* - `'shimmer'` — gradient slides across the block
|
|
6
|
+
*/
|
|
7
|
+
export type SkeletonVariant = 'pulse' | 'shimmer';
|
|
8
|
+
/**
|
|
9
|
+
* Props for `<Skeleton>` — a placeholder block that mimics the shape of
|
|
10
|
+
* content while it loads. Use to preserve layout and avoid layout shift
|
|
11
|
+
* when the real content arrives.
|
|
12
|
+
*
|
|
13
|
+
* For wholesale "is my component loading?" UX, most components expose
|
|
14
|
+
* a `loading` prop that renders skeletons automatically (`<Card loading>`,
|
|
15
|
+
* `<Table loading>`, etc.). Use `<Skeleton>` directly when composing
|
|
16
|
+
* custom placeholder layouts.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```svelte
|
|
20
|
+
* <!-- Three-line text placeholder -->
|
|
21
|
+
* <div class="space-y-2">
|
|
22
|
+
* <Skeleton class="h-4 w-48" />
|
|
23
|
+
* <Skeleton class="h-4 w-64" />
|
|
24
|
+
* <Skeleton class="h-4 w-40" />
|
|
25
|
+
* </div>
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```svelte
|
|
30
|
+
* <!-- Avatar placeholder -->
|
|
31
|
+
* <Skeleton class="size-10" rounded="rounded-full" variant="shimmer" />
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export interface SkeletonProps {
|
|
35
|
+
/** Additional Tailwind classes — typically `w-*` and `h-*` to size the block. */
|
|
36
|
+
class?: ClassValue;
|
|
37
|
+
/**
|
|
38
|
+
* Animation style.
|
|
39
|
+
* - `pulse` (default): subtle opacity pulse via Tailwind's animate-pulse
|
|
40
|
+
* - `shimmer`: gradient slides across the block
|
|
41
|
+
*/
|
|
42
|
+
variant?: SkeletonVariant;
|
|
43
|
+
/** Override the rounded class. Pass `''` to suppress default rounding. @default 'rounded-md' */
|
|
44
|
+
rounded?: string;
|
|
45
|
+
/** Optional accessible label announced by screen readers. @default 'Loading' */
|
|
46
|
+
ariaLabel?: string;
|
|
47
|
+
/** Inline style — useful for dynamic widths/heights that Tailwind can't express. */
|
|
48
|
+
style?: string;
|
|
49
|
+
testId?: string;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import type { ClassValue } from 'tailwind-variants';
|
|
2
2
|
import type { VariantColors, VariantSizes } from '../../index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Props for `<Spinner>` — an animated loading indicator. Use for
|
|
5
|
+
* short-lived waits ("loading the next page of results"). For longer
|
|
6
|
+
* waits where layout shape matters, prefer `<Skeleton>`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```svelte
|
|
10
|
+
* <Spinner />
|
|
11
|
+
*
|
|
12
|
+
* <!-- With accessible label -->
|
|
13
|
+
* <Spinner size="lg" color="primary" label="Loading users" />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
3
16
|
export type SpinnerProps = {
|
|
17
|
+
/** @default 'md' */
|
|
4
18
|
size?: VariantSizes;
|
|
19
|
+
/** @default 'primary' */
|
|
5
20
|
color?: VariantColors;
|
|
21
|
+
/**
|
|
22
|
+
* Accessible text announced to screen readers. Visible labels are
|
|
23
|
+
* rendered next to the spinner; omit for a bare spinner (an
|
|
24
|
+
* `aria-label='Loading'` is still applied).
|
|
25
|
+
*/
|
|
6
26
|
label?: string;
|
|
7
27
|
class?: ClassValue;
|
|
8
28
|
testId?: string;
|
|
@@ -8,7 +8,7 @@ export declare const spinner: import("tailwind-variants").TVReturnType<{
|
|
|
8
8
|
svg: string;
|
|
9
9
|
label: string;
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
md: {
|
|
12
12
|
svg: string;
|
|
13
13
|
label: string;
|
|
14
14
|
};
|
|
@@ -62,7 +62,7 @@ export declare const spinner: import("tailwind-variants").TVReturnType<{
|
|
|
62
62
|
svg: string;
|
|
63
63
|
label: string;
|
|
64
64
|
};
|
|
65
|
-
|
|
65
|
+
md: {
|
|
66
66
|
svg: string;
|
|
67
67
|
label: string;
|
|
68
68
|
};
|
|
@@ -116,7 +116,7 @@ export declare const spinner: import("tailwind-variants").TVReturnType<{
|
|
|
116
116
|
svg: string;
|
|
117
117
|
label: string;
|
|
118
118
|
};
|
|
119
|
-
|
|
119
|
+
md: {
|
|
120
120
|
svg: string;
|
|
121
121
|
label: string;
|
|
122
122
|
};
|
|
@@ -10,7 +10,7 @@ export const spinner = tv({
|
|
|
10
10
|
size: {
|
|
11
11
|
[Size.XS]: { svg: 'h-3 w-3', label: 'text-xs' },
|
|
12
12
|
[Size.SM]: { svg: 'h-4 w-4', label: 'text-xs' },
|
|
13
|
-
[Size.
|
|
13
|
+
[Size.MD]: { svg: 'h-5 w-5', label: 'text-sm' },
|
|
14
14
|
[Size.LG]: { svg: 'h-6 w-6', label: 'text-base' },
|
|
15
15
|
[Size.XL]: { svg: 'h-8 w-8', label: 'text-lg' },
|
|
16
16
|
[Size.XXL]: { svg: 'h-12 w-12', label: 'text-xl' }
|
|
@@ -26,7 +26,7 @@ export const spinner = tv({
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
defaultVariants: {
|
|
29
|
-
size: Size.
|
|
29
|
+
size: Size.MD,
|
|
30
30
|
color: Color.DEFAULT
|
|
31
31
|
}
|
|
32
32
|
});
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../helper/cls.js';
|
|
3
3
|
import { buildTestId } from '../../helper/testid.js';
|
|
4
|
-
import
|
|
4
|
+
import { scale } from 'svelte/transition';
|
|
5
|
+
import { quintOut } from 'svelte/easing';
|
|
6
|
+
import type { TooltipProps, TooltipSize, TooltipVariant } from '../../index.js';
|
|
5
7
|
|
|
6
8
|
let {
|
|
7
9
|
content,
|
|
10
|
+
body,
|
|
8
11
|
placement = 'top',
|
|
12
|
+
size = 'sm',
|
|
13
|
+
variant = 'dark',
|
|
14
|
+
arrow = true,
|
|
9
15
|
delay = 100,
|
|
16
|
+
hideDelay = 0,
|
|
10
17
|
disabled = false,
|
|
11
18
|
class: className = '',
|
|
12
19
|
tooltipClass = '',
|
|
@@ -16,10 +23,12 @@
|
|
|
16
23
|
|
|
17
24
|
let visible = $state(false);
|
|
18
25
|
let showTimer: ReturnType<typeof setTimeout> | undefined;
|
|
26
|
+
let hideTimer: ReturnType<typeof setTimeout> | undefined;
|
|
19
27
|
|
|
20
28
|
function show() {
|
|
21
29
|
if (disabled) return;
|
|
22
30
|
clearTimeout(showTimer);
|
|
31
|
+
clearTimeout(hideTimer);
|
|
23
32
|
if (delay > 0) {
|
|
24
33
|
showTimer = setTimeout(() => {
|
|
25
34
|
visible = true;
|
|
@@ -31,7 +40,19 @@
|
|
|
31
40
|
|
|
32
41
|
function hide() {
|
|
33
42
|
clearTimeout(showTimer);
|
|
34
|
-
|
|
43
|
+
clearTimeout(hideTimer);
|
|
44
|
+
if (hideDelay > 0) {
|
|
45
|
+
hideTimer = setTimeout(() => {
|
|
46
|
+
visible = false;
|
|
47
|
+
}, hideDelay);
|
|
48
|
+
} else {
|
|
49
|
+
visible = false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Keep tooltip open while the user mouses over its body (only meaningful with hideDelay > 0). */
|
|
54
|
+
function cancelHide() {
|
|
55
|
+
if (hideDelay > 0) clearTimeout(hideTimer);
|
|
35
56
|
}
|
|
36
57
|
|
|
37
58
|
const placementClass = $derived(
|
|
@@ -43,16 +64,78 @@
|
|
|
43
64
|
}[placement]
|
|
44
65
|
);
|
|
45
66
|
|
|
67
|
+
const sizeClasses: Record<TooltipSize, string> = {
|
|
68
|
+
sm: 'px-2 py-1 text-xs rounded',
|
|
69
|
+
md: 'px-3 py-1.5 text-sm rounded-md',
|
|
70
|
+
lg: 'px-4 py-2 text-base rounded-lg'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
type VariantStyles = {
|
|
74
|
+
bg: string;
|
|
75
|
+
text: string;
|
|
76
|
+
arrow: { t: string; b: string; l: string; r: string };
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const variantStyles: Record<TooltipVariant, VariantStyles> = {
|
|
80
|
+
dark: {
|
|
81
|
+
bg: 'bg-default-800',
|
|
82
|
+
text: 'text-white',
|
|
83
|
+
arrow: {
|
|
84
|
+
t: 'border-t-default-800',
|
|
85
|
+
b: 'border-b-default-800',
|
|
86
|
+
l: 'border-l-default-800',
|
|
87
|
+
r: 'border-r-default-800'
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
light: {
|
|
91
|
+
bg: 'bg-white border border-default-200',
|
|
92
|
+
text: 'text-default-900',
|
|
93
|
+
arrow: { t: 'border-t-white', b: 'border-b-white', l: 'border-l-white', r: 'border-r-white' }
|
|
94
|
+
},
|
|
95
|
+
primary: {
|
|
96
|
+
bg: 'bg-primary-600',
|
|
97
|
+
text: 'text-white',
|
|
98
|
+
arrow: {
|
|
99
|
+
t: 'border-t-primary-600',
|
|
100
|
+
b: 'border-b-primary-600',
|
|
101
|
+
l: 'border-l-primary-600',
|
|
102
|
+
r: 'border-r-primary-600'
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
danger: {
|
|
106
|
+
bg: 'bg-danger-600',
|
|
107
|
+
text: 'text-white',
|
|
108
|
+
arrow: {
|
|
109
|
+
t: 'border-t-danger-600',
|
|
110
|
+
b: 'border-b-danger-600',
|
|
111
|
+
l: 'border-l-danger-600',
|
|
112
|
+
r: 'border-r-danger-600'
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
success: {
|
|
116
|
+
bg: 'bg-success-600',
|
|
117
|
+
text: 'text-white',
|
|
118
|
+
arrow: {
|
|
119
|
+
t: 'border-t-success-600',
|
|
120
|
+
b: 'border-b-success-600',
|
|
121
|
+
l: 'border-l-success-600',
|
|
122
|
+
r: 'border-r-success-600'
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const styles = $derived(variantStyles[variant]);
|
|
128
|
+
|
|
46
129
|
const arrowClass = $derived(
|
|
47
130
|
{
|
|
48
|
-
top:
|
|
49
|
-
bottom:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
right:
|
|
53
|
-
'right-full top-1/2 -translate-y-1/2 border-r-default-800 border-t-transparent border-b-transparent border-l-transparent'
|
|
131
|
+
top: `top-full left-1/2 -translate-x-1/2 ${styles.arrow.t} border-l-transparent border-r-transparent border-b-transparent`,
|
|
132
|
+
bottom: `bottom-full left-1/2 -translate-x-1/2 ${styles.arrow.b} border-l-transparent border-r-transparent border-t-transparent`,
|
|
133
|
+
left: `left-full top-1/2 -translate-y-1/2 ${styles.arrow.l} border-t-transparent border-b-transparent border-r-transparent`,
|
|
134
|
+
right: `right-full top-1/2 -translate-y-1/2 ${styles.arrow.r} border-t-transparent border-b-transparent border-l-transparent`
|
|
54
135
|
}[placement]
|
|
55
136
|
);
|
|
137
|
+
|
|
138
|
+
const bodyIsInteractive = $derived(hideDelay > 0);
|
|
56
139
|
</script>
|
|
57
140
|
|
|
58
141
|
<span
|
|
@@ -69,14 +152,28 @@
|
|
|
69
152
|
<span
|
|
70
153
|
role="tooltip"
|
|
71
154
|
data-tooltip-visible="true"
|
|
155
|
+
transition:scale={{ duration: 500, start: 0.9, opacity: 0, easing: quintOut }}
|
|
72
156
|
class={cn(
|
|
73
|
-
'
|
|
157
|
+
'absolute z-50 shadow-lg',
|
|
158
|
+
!bodyIsInteractive && 'pointer-events-none',
|
|
159
|
+
body ? '' : 'whitespace-nowrap',
|
|
160
|
+
sizeClasses[size],
|
|
161
|
+
styles.bg,
|
|
162
|
+
styles.text,
|
|
74
163
|
placementClass,
|
|
75
164
|
tooltipClass
|
|
76
165
|
)}
|
|
166
|
+
onmouseenter={cancelHide}
|
|
167
|
+
onmouseleave={hide}
|
|
77
168
|
>
|
|
78
|
-
{
|
|
79
|
-
|
|
169
|
+
{#if body}
|
|
170
|
+
{@render body()}
|
|
171
|
+
{:else}
|
|
172
|
+
{content}
|
|
173
|
+
{/if}
|
|
174
|
+
{#if arrow}
|
|
175
|
+
<span class={cn('absolute h-0 w-0 border-4', arrowClass)} aria-hidden="true"></span>
|
|
176
|
+
{/if}
|
|
80
177
|
</span>
|
|
81
178
|
{/if}
|
|
82
179
|
</span>
|
|
@@ -1,13 +1,61 @@
|
|
|
1
1
|
import type { ClassValue } from 'tailwind-variants';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
/** Placement of the tooltip panel relative to its trigger. */
|
|
3
4
|
export type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
|
5
|
+
/** Size variants specific to Tooltip — a narrower subset of the global `VariantSizes`. */
|
|
6
|
+
export type TooltipSize = 'sm' | 'md' | 'lg';
|
|
7
|
+
/** Tooltip color palette. `'dark'` on light pages, `'light'` on dark pages. */
|
|
8
|
+
export type TooltipVariant = 'dark' | 'light' | 'primary' | 'danger' | 'success';
|
|
9
|
+
/**
|
|
10
|
+
* Props for `<Tooltip>` — small hover/focus-triggered label for a UI
|
|
11
|
+
* element. For longer or interactive content (links, buttons inside
|
|
12
|
+
* the panel), prefer `<Popover trigger="hover" hideDelay={200}>` —
|
|
13
|
+
* Tooltip closes immediately on mouseleave by default.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```svelte
|
|
17
|
+
* <Tooltip content="Delete this user">
|
|
18
|
+
* <Button variant="ghost" color="danger"><TrashIcon /></Button>
|
|
19
|
+
* </Tooltip>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```svelte
|
|
24
|
+
* <!-- Rich content + interactive (keeps open while mouse is over body) -->
|
|
25
|
+
* <Tooltip variant="light" placement="right" hideDelay={200}>
|
|
26
|
+
* {#snippet body()}
|
|
27
|
+
* <div>
|
|
28
|
+
* <strong>Keyboard shortcut</strong>
|
|
29
|
+
* <p class="text-xs">Press ⌘ + K to open search</p>
|
|
30
|
+
* </div>
|
|
31
|
+
* {/snippet}
|
|
32
|
+
* <kbd>⌘ K</kbd>
|
|
33
|
+
* </Tooltip>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
4
36
|
export type TooltipProps = {
|
|
5
|
-
content
|
|
37
|
+
/** Plain text content. Ignored if `body` snippet is also provided. */
|
|
38
|
+
content?: string;
|
|
39
|
+
/** Rich content snippet — takes precedence over `content`. Use for HTML, links, icons, etc. */
|
|
40
|
+
body?: Snippet;
|
|
41
|
+
/** @default 'top' */
|
|
6
42
|
placement?: TooltipPlacement;
|
|
43
|
+
/** Padding/text size. @default 'sm' */
|
|
44
|
+
size?: TooltipSize;
|
|
45
|
+
/** Color palette. @default 'dark' */
|
|
46
|
+
variant?: TooltipVariant;
|
|
47
|
+
/** Show arrow pointing at the trigger. @default true */
|
|
48
|
+
arrow?: boolean;
|
|
49
|
+
/** Delay before showing (ms). @default 100 */
|
|
7
50
|
delay?: number;
|
|
51
|
+
/** Delay before hiding after mouseleave (ms). Non-zero lets users move into the tooltip. @default 0 */
|
|
52
|
+
hideDelay?: number;
|
|
8
53
|
disabled?: boolean;
|
|
54
|
+
/** Classes for the trigger wrapper. */
|
|
9
55
|
class?: ClassValue;
|
|
56
|
+
/** Classes for the tooltip panel. */
|
|
10
57
|
tooltipClass?: ClassValue;
|
|
58
|
+
/** Trigger element(s). */
|
|
11
59
|
children: Snippet;
|
|
12
60
|
testId?: string;
|
|
13
61
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import { cn } from '../helper/cls.js';
|
|
4
|
-
import { Button, Table, Color, Size, Spinner } from '../index.js';
|
|
4
|
+
import { Button, Table, Color, Size, Spinner, Skeleton } from '../index.js';
|
|
5
5
|
import type { TableColumn, FileBrowserProps } from '../index.js';
|
|
6
6
|
import { formatDate } from '../utils/dateUtils.js';
|
|
7
7
|
import type {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
let files = $state<FileItem[]>([]);
|
|
28
28
|
let displayFiles = $state<FileItem[]>([]);
|
|
29
29
|
let currentPath = $state(startPath || '');
|
|
30
|
-
let
|
|
30
|
+
let loading = $state(true);
|
|
31
31
|
let isAuthenticated = $state(false);
|
|
32
32
|
let error = $state<string | null>(null);
|
|
33
33
|
let breadcrumbs = $state<Breadcrumb[]>([]);
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
|
|
163
163
|
// Loading files using the adapter
|
|
164
164
|
async function listFiles(path: string) {
|
|
165
|
-
|
|
165
|
+
loading = true;
|
|
166
166
|
error = null;
|
|
167
167
|
|
|
168
168
|
// Remember the previous selection before loading new files
|
|
@@ -192,7 +192,7 @@
|
|
|
192
192
|
console.error('Error fetching files:', err);
|
|
193
193
|
error = err instanceof Error ? err.message : 'An unknown error occurred';
|
|
194
194
|
} finally {
|
|
195
|
-
|
|
195
|
+
loading = false;
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -647,7 +647,7 @@
|
|
|
647
647
|
];
|
|
648
648
|
|
|
649
649
|
async function handleUnauthenticated() {
|
|
650
|
-
|
|
650
|
+
loading = true;
|
|
651
651
|
|
|
652
652
|
try {
|
|
653
653
|
// Use the adapter's method to set the reopening flag
|
|
@@ -664,11 +664,11 @@
|
|
|
664
664
|
}
|
|
665
665
|
|
|
666
666
|
// Note: authentication usually redirects the page, so code below won't run
|
|
667
|
-
|
|
667
|
+
loading = false;
|
|
668
668
|
} catch (error) {
|
|
669
669
|
console.error('Authentication error:', error);
|
|
670
670
|
console.error('Authentication error');
|
|
671
|
-
|
|
671
|
+
loading = false;
|
|
672
672
|
}
|
|
673
673
|
}
|
|
674
674
|
|
|
@@ -914,9 +914,18 @@
|
|
|
914
914
|
</div>
|
|
915
915
|
|
|
916
916
|
<div class="min-h-0 flex-1 overflow-auto">
|
|
917
|
-
{#if
|
|
918
|
-
<div class="
|
|
919
|
-
|
|
917
|
+
{#if loading}
|
|
918
|
+
<div class="divide-default-100 divide-y px-4" aria-label="Loading files">
|
|
919
|
+
{#each Array(6) as _, i (i)}
|
|
920
|
+
<div class="flex items-center gap-3 py-3">
|
|
921
|
+
<Skeleton class="size-5 shrink-0" />
|
|
922
|
+
<Skeleton class="size-6 shrink-0" rounded="rounded-md" />
|
|
923
|
+
<Skeleton class="h-4 flex-1" style="max-width: {200 + i * 30}px" />
|
|
924
|
+
<Skeleton class="h-3 w-16 shrink-0" />
|
|
925
|
+
<Skeleton class="h-3 w-24 shrink-0" />
|
|
926
|
+
<Skeleton class="h-7 w-16 shrink-0" rounded="rounded-md" />
|
|
927
|
+
</div>
|
|
928
|
+
{/each}
|
|
920
929
|
</div>
|
|
921
930
|
{:else if error}
|
|
922
931
|
<div class="flex h-full flex-col items-center justify-center py-16">
|
|
@@ -931,10 +940,10 @@
|
|
|
931
940
|
<Table
|
|
932
941
|
{columns}
|
|
933
942
|
data={displayFiles}
|
|
934
|
-
loading
|
|
943
|
+
{loading}
|
|
935
944
|
bordered={false}
|
|
936
945
|
onrowclick={handleRowClick}
|
|
937
|
-
|
|
946
|
+
rowClass={(row: FileItem) => {
|
|
938
947
|
let classes = row.isFolder ? 'hover:bg-amber-50 cursor-pointer' : 'hover:bg-blue-50';
|
|
939
948
|
if (isRowSelected(row)) {
|
|
940
949
|
classes += ' bg-primary-50';
|