@makolabs/ripple 0.0.1 → 0.0.4
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 +575 -8
- package/dist/adapters/storage/BaseAdapter.d.ts +20 -0
- package/dist/adapters/storage/BaseAdapter.js +171 -0
- package/dist/adapters/storage/S3Adapter.d.ts +21 -0
- package/dist/adapters/storage/S3Adapter.js +194 -0
- package/dist/adapters/storage/index.d.ts +3 -0
- package/dist/adapters/storage/index.js +3 -0
- package/dist/adapters/storage/types.d.ts +102 -0
- package/dist/adapters/storage/types.js +4 -0
- package/dist/button/Button.svelte +48 -0
- package/dist/button/Button.svelte.d.ts +4 -0
- package/dist/button/button.d.ts +113 -0
- package/dist/button/button.js +168 -0
- package/dist/charts/Chart.svelte +545 -0
- package/dist/charts/Chart.svelte.d.ts +4 -0
- package/dist/drawer/Drawer.svelte +224 -0
- package/dist/drawer/Drawer.svelte.d.ts +4 -0
- package/dist/drawer/drawer.d.ts +160 -0
- package/dist/drawer/drawer.js +80 -0
- package/dist/elements/accordion/Accordion.svelte +98 -0
- package/dist/elements/accordion/Accordion.svelte.d.ts +4 -0
- package/dist/elements/accordion/accordion.d.ts +227 -0
- package/dist/elements/accordion/accordion.js +138 -0
- package/dist/elements/alert/Alert.svelte +57 -0
- package/dist/elements/alert/Alert.svelte.d.ts +4 -0
- package/dist/elements/badge/Badge.svelte +43 -0
- package/dist/elements/badge/Badge.svelte.d.ts +4 -0
- package/dist/elements/badge/badge.d.ts +181 -0
- package/dist/elements/badge/badge.js +65 -0
- package/dist/elements/dropdown/Dropdown.svelte +234 -0
- package/dist/elements/dropdown/Dropdown.svelte.d.ts +4 -0
- package/dist/elements/dropdown/Select.svelte +333 -0
- package/dist/elements/dropdown/Select.svelte.d.ts +4 -0
- package/dist/elements/dropdown/dropdown.d.ts +251 -0
- package/dist/elements/dropdown/dropdown.js +95 -0
- package/dist/elements/dropdown/select.d.ts +200 -0
- package/dist/elements/dropdown/select.js +82 -0
- package/dist/elements/file-upload/FileUpload.svelte +135 -0
- package/dist/elements/file-upload/FileUpload.svelte.d.ts +4 -0
- package/dist/elements/file-upload/FilesPreview.svelte +93 -0
- package/dist/elements/file-upload/FilesPreview.svelte.d.ts +4 -0
- package/dist/elements/progress/Progress.svelte +145 -0
- package/dist/elements/progress/Progress.svelte.d.ts +4 -0
- package/dist/elements/timeline/Timeline.svelte +92 -0
- package/dist/elements/timeline/Timeline.svelte.d.ts +7 -0
- package/dist/file-browser/FileBrowser.svelte +877 -0
- package/dist/file-browser/FileBrowser.svelte.d.ts +14 -0
- package/dist/file-browser/index.d.ts +1 -0
- package/dist/file-browser/index.js +1 -0
- package/dist/filters/CompactFilters.svelte +147 -0
- package/dist/filters/CompactFilters.svelte.d.ts +4 -0
- package/dist/filters/index.d.ts +1 -0
- package/dist/filters/index.js +1 -0
- package/dist/forms/Checkbox.svelte +54 -0
- package/dist/forms/Checkbox.svelte.d.ts +4 -0
- package/dist/forms/DateRange.svelte +493 -0
- package/dist/forms/DateRange.svelte.d.ts +4 -0
- package/dist/forms/Form.svelte +39 -0
- package/dist/forms/Form.svelte.d.ts +4 -0
- package/dist/forms/Input.svelte +86 -0
- package/dist/forms/Input.svelte.d.ts +4 -0
- package/dist/forms/NumberInput.svelte +159 -0
- package/dist/forms/NumberInput.svelte.d.ts +4 -0
- package/dist/forms/RadioInputs.svelte +64 -0
- package/dist/forms/RadioInputs.svelte.d.ts +4 -0
- package/dist/forms/RadioPill.svelte +66 -0
- package/dist/forms/RadioPill.svelte.d.ts +4 -0
- package/dist/forms/Slider.svelte +342 -0
- package/dist/forms/Slider.svelte.d.ts +4 -0
- package/dist/forms/Tags.svelte +181 -0
- package/dist/forms/Tags.svelte.d.ts +4 -0
- package/dist/forms/Toggle.svelte +132 -0
- package/dist/forms/Toggle.svelte.d.ts +4 -0
- package/dist/forms/slider.d.ts +143 -0
- package/dist/forms/slider.js +62 -0
- package/dist/header/Breadcrumbs.svelte +73 -0
- package/dist/header/Breadcrumbs.svelte.d.ts +4 -0
- package/dist/header/PageHeader.svelte +68 -0
- package/dist/header/PageHeader.svelte.d.ts +4 -0
- package/dist/header/breadcrumbs.d.ts +226 -0
- package/dist/header/breadcrumbs.js +87 -0
- package/dist/helper/cls.d.ts +1 -0
- package/dist/helper/cls.js +4 -0
- package/dist/helper/date.d.ts +7 -0
- package/dist/helper/date.js +15 -0
- package/dist/helper/nav.svelte.d.ts +6 -0
- package/dist/helper/nav.svelte.js +23 -0
- package/dist/index.d.ts +856 -1
- package/dist/index.js +78 -1
- package/dist/layout/card/Card.svelte +41 -0
- package/dist/layout/card/Card.svelte.d.ts +4 -0
- package/dist/layout/card/MetricCard.svelte +64 -0
- package/dist/layout/card/MetricCard.svelte.d.ts +4 -0
- package/dist/layout/card/StatsCard.svelte +266 -0
- package/dist/layout/card/StatsCard.svelte.d.ts +4 -0
- package/dist/layout/card/card.d.ts +128 -0
- package/dist/layout/card/card.js +51 -0
- package/dist/layout/card/metric-card.d.ts +49 -0
- package/dist/layout/card/metric-card.js +10 -0
- package/dist/layout/card/stats-card.d.ts +191 -0
- package/dist/layout/card/stats-card.js +73 -0
- package/dist/layout/navbar/Navbar.svelte +206 -0
- package/dist/layout/navbar/Navbar.svelte.d.ts +4 -0
- package/dist/layout/navbar/navbar.d.ts +205 -0
- package/dist/layout/navbar/navbar.js +98 -0
- package/dist/layout/sidebar/NavGroup.svelte +91 -0
- package/dist/layout/sidebar/NavGroup.svelte.d.ts +4 -0
- package/dist/layout/sidebar/NavItem.svelte +29 -0
- package/dist/layout/sidebar/NavItem.svelte.d.ts +4 -0
- package/dist/layout/sidebar/Sidebar.svelte +193 -0
- package/dist/layout/sidebar/Sidebar.svelte.d.ts +4 -0
- package/dist/layout/table/Cells.svelte +111 -0
- package/dist/layout/table/Cells.svelte.d.ts +27 -0
- package/dist/layout/table/Table.svelte +790 -0
- package/dist/layout/table/Table.svelte.d.ts +4 -0
- package/dist/layout/table/table.d.ts +256 -0
- package/dist/layout/table/table.js +141 -0
- package/dist/layout/tabs/Tab.svelte +60 -0
- package/dist/layout/tabs/Tab.svelte.d.ts +4 -0
- package/dist/layout/tabs/TabContent.svelte +30 -0
- package/dist/layout/tabs/TabContent.svelte.d.ts +4 -0
- package/dist/layout/tabs/TabGroup.svelte +62 -0
- package/dist/layout/tabs/TabGroup.svelte.d.ts +4 -0
- package/dist/layout/tabs/tabs.d.ts +140 -0
- package/dist/layout/tabs/tabs.js +298 -0
- package/dist/modal/Modal.svelte +207 -0
- package/dist/modal/Modal.svelte.d.ts +4 -0
- package/dist/modal/modal.d.ts +211 -0
- package/dist/modal/modal.js +81 -0
- package/dist/sonner/sonner.svelte +13 -0
- package/dist/sonner/sonner.svelte.d.ts +4 -0
- package/dist/types/variants.d.ts +1 -0
- package/dist/types/variants.js +1 -0
- package/dist/utils/Portal.svelte +108 -0
- package/dist/utils/Portal.svelte.d.ts +8 -0
- package/dist/utils/dateUtils.d.ts +7 -0
- package/dist/utils/dateUtils.js +26 -0
- package/dist/variants.d.ts +30 -0
- package/dist/variants.js +36 -0
- package/package.json +39 -6
- package/dist/layout/Card.svelte +0 -179
- package/dist/layout/Card.svelte.d.ts +0 -208
- package/dist/layout/index.d.ts +0 -1
- package/dist/layout/index.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1 +1,78 @@
|
|
|
1
|
-
|
|
1
|
+
import { ChartColor, Color, Size } from './variants.js';
|
|
2
|
+
/**
|
|
3
|
+
* Color System:
|
|
4
|
+
* - Color.*: UI component colors (buttons, text, backgrounds)
|
|
5
|
+
* Options: DEFAULT, PRIMARY, SECONDARY, INFO, SUCCESS, WARNING, DANGER
|
|
6
|
+
* - ChartColor.*: Chart-specific colors, only supported within series configurations (lines, areas, bars)
|
|
7
|
+
* Options: HEALTH, PROPERTY, AUTO, LIFE, OTHER, DEFAULT
|
|
8
|
+
* - ChartColors: Record type mapping ChartColor enum to string values
|
|
9
|
+
*/
|
|
10
|
+
export { Color, Size, ChartColor };
|
|
11
|
+
// Helper utilities
|
|
12
|
+
export { tv, cn } from './helper/cls.js';
|
|
13
|
+
export { isRouteActive } from './helper/nav.svelte.js';
|
|
14
|
+
// Direct Component Exports
|
|
15
|
+
// Button
|
|
16
|
+
export { default as Button } from './button/Button.svelte';
|
|
17
|
+
// Modal
|
|
18
|
+
export { default as Modal } from './modal/Modal.svelte';
|
|
19
|
+
// Drawer
|
|
20
|
+
export { default as Drawer } from './drawer/Drawer.svelte';
|
|
21
|
+
// Header
|
|
22
|
+
export { default as PageHeader } from './header/PageHeader.svelte';
|
|
23
|
+
export { default as Breadcrumbs } from './header/Breadcrumbs.svelte';
|
|
24
|
+
// Elements
|
|
25
|
+
export { default as Badge } from './elements/badge/Badge.svelte';
|
|
26
|
+
export { default as Dropdown } from './elements/dropdown/Dropdown.svelte';
|
|
27
|
+
export { default as Select } from './elements/dropdown/Select.svelte';
|
|
28
|
+
// Elements - Card
|
|
29
|
+
export { default as Card } from './layout/card/Card.svelte';
|
|
30
|
+
export { default as StatsCard } from './layout/card/StatsCard.svelte';
|
|
31
|
+
export { default as MetricCard } from './layout/card/MetricCard.svelte';
|
|
32
|
+
// Elements - Alert
|
|
33
|
+
export { default as Alert } from './elements/alert/Alert.svelte';
|
|
34
|
+
export { default as Tab } from './layout/tabs/Tab.svelte';
|
|
35
|
+
export { default as TabContent } from './layout/tabs/TabContent.svelte';
|
|
36
|
+
export { default as TabGroup } from './layout/tabs/TabGroup.svelte';
|
|
37
|
+
// Elements - Table
|
|
38
|
+
export { default as Table } from './layout/table/Table.svelte';
|
|
39
|
+
export { default as Cells } from './layout/table/Cells.svelte';
|
|
40
|
+
// Elements - Navbar
|
|
41
|
+
export { default as Navbar } from './layout/navbar/Navbar.svelte';
|
|
42
|
+
// Elements - Sidebar
|
|
43
|
+
export { default as Sidebar } from './layout/sidebar/Sidebar.svelte';
|
|
44
|
+
export { default as NavItem } from './layout/sidebar/NavItem.svelte';
|
|
45
|
+
export { default as NavGroup } from './layout/sidebar/NavGroup.svelte';
|
|
46
|
+
// Component Variant Utilities
|
|
47
|
+
export { dropdownMenu } from './elements/dropdown/dropdown.js';
|
|
48
|
+
export { badge } from './elements/badge/badge.js';
|
|
49
|
+
export { buttonVariants } from './button/button.js';
|
|
50
|
+
export { modal } from './modal/modal.js';
|
|
51
|
+
export { drawer } from './drawer/drawer.js';
|
|
52
|
+
export { selectTV } from './elements/dropdown/select.js';
|
|
53
|
+
export { breadcrumbs } from './header/breadcrumbs.js';
|
|
54
|
+
export { metricCard } from './layout/card/metric-card.js';
|
|
55
|
+
export { default as Chart } from './charts/Chart.svelte';
|
|
56
|
+
export { default as FileUpload } from './elements/file-upload/FileUpload.svelte';
|
|
57
|
+
export { default as FilesPreview } from './elements/file-upload/FilesPreview.svelte';
|
|
58
|
+
// Toaster: Should be registered in +layout.svelte
|
|
59
|
+
export { default as Toaster } from './sonner/sonner.svelte';
|
|
60
|
+
// Form Component Exports
|
|
61
|
+
export { default as Form } from './forms/Form.svelte';
|
|
62
|
+
export { default as Input } from './forms/Input.svelte';
|
|
63
|
+
export { default as RadioInputs } from './forms/RadioInputs.svelte';
|
|
64
|
+
export { default as Checkbox } from './forms/Checkbox.svelte';
|
|
65
|
+
export { default as Toggle } from './forms/Toggle.svelte';
|
|
66
|
+
export { default as Slider } from './forms/Slider.svelte';
|
|
67
|
+
export { default as NumberInput } from './forms/NumberInput.svelte';
|
|
68
|
+
export { default as DateRange } from './forms/DateRange.svelte';
|
|
69
|
+
export { default as Tags } from './forms/Tags.svelte';
|
|
70
|
+
export { default as RadioPill } from './forms/RadioPill.svelte';
|
|
71
|
+
export { default as Progress } from './elements/progress/Progress.svelte';
|
|
72
|
+
export { default as Accordion } from './elements/accordion/Accordion.svelte';
|
|
73
|
+
export { default as Timeline } from './elements/timeline/Timeline.svelte';
|
|
74
|
+
// Re-export filters
|
|
75
|
+
export { CompactFilters } from './filters/index.js';
|
|
76
|
+
// File Browser and Storage Adapters
|
|
77
|
+
export * from './file-browser/index.js';
|
|
78
|
+
export * from './adapters/storage/index.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { card } from './card.js';
|
|
4
|
+
import type { CardProps } from '../../index.js';
|
|
5
|
+
import { Color } from '../../variants.js';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
children,
|
|
9
|
+
custom,
|
|
10
|
+
title,
|
|
11
|
+
color = Color.DEFAULT,
|
|
12
|
+
class: className = '',
|
|
13
|
+
titleclass: titleClass = '',
|
|
14
|
+
bodyclass: bodyClass = ''
|
|
15
|
+
}: CardProps = $props();
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
base,
|
|
19
|
+
title: titleSlot,
|
|
20
|
+
body: bodySlot
|
|
21
|
+
} = $derived(card({ color }));
|
|
22
|
+
|
|
23
|
+
const baseClass = $derived(cn(base(), className));
|
|
24
|
+
const titleClasses = $derived(cn(titleSlot(), titleClass));
|
|
25
|
+
const bodyClasses = $derived(cn(bodySlot(), bodyClass));
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div class={baseClass}>
|
|
29
|
+
{#if custom}
|
|
30
|
+
{@render custom()}
|
|
31
|
+
{:else}
|
|
32
|
+
{#if title}
|
|
33
|
+
<h3 class={titleClasses}>{title}</h3>
|
|
34
|
+
{/if}
|
|
35
|
+
{#if children}
|
|
36
|
+
<div class={bodyClasses}>
|
|
37
|
+
{@render children()}
|
|
38
|
+
</div>
|
|
39
|
+
{/if}
|
|
40
|
+
{/if}
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { metricCard } from './metric-card.js';
|
|
4
|
+
import type { MetricCardProps } from '../../index.js';
|
|
5
|
+
import Progress from '../../elements/progress/Progress.svelte';
|
|
6
|
+
import { Size, Color } from '../../variants.js';
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
title,
|
|
10
|
+
value,
|
|
11
|
+
details = [],
|
|
12
|
+
percent,
|
|
13
|
+
segments,
|
|
14
|
+
class: className = ''
|
|
15
|
+
}: MetricCardProps = $props();
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
base,
|
|
19
|
+
title: titleSlot,
|
|
20
|
+
value: valueSlot,
|
|
21
|
+
detail: detailSlot,
|
|
22
|
+
progress: progressSlot
|
|
23
|
+
} = $derived(metricCard());
|
|
24
|
+
|
|
25
|
+
const baseClass = $derived(cn(base(), 'flex flex-col h-full', className));
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div class={baseClass}>
|
|
29
|
+
{#if title}
|
|
30
|
+
<div class={titleSlot()}>{title}</div>
|
|
31
|
+
{/if}
|
|
32
|
+
|
|
33
|
+
{#if value !== undefined}
|
|
34
|
+
<div class={valueSlot()}>{value}</div>
|
|
35
|
+
{/if}
|
|
36
|
+
|
|
37
|
+
{#if details.length > 0}
|
|
38
|
+
<div class={detailSlot()}>
|
|
39
|
+
{#each details as detail, index (detail.label + index)}
|
|
40
|
+
<div class="flex justify-between text-xs">
|
|
41
|
+
<span class="text-default-500">{detail.label}</span>
|
|
42
|
+
<span class="font-medium {detail.color || 'text-default-900'}">{detail.value}</span>
|
|
43
|
+
</div>
|
|
44
|
+
{/each}
|
|
45
|
+
</div>
|
|
46
|
+
{/if}
|
|
47
|
+
|
|
48
|
+
{#if segments}
|
|
49
|
+
<div class={cn(progressSlot(), 'pt-2')}>
|
|
50
|
+
<Progress
|
|
51
|
+
value={0}
|
|
52
|
+
{segments}
|
|
53
|
+
size={Size.SM}
|
|
54
|
+
showLabels={false}
|
|
55
|
+
showValues={false}
|
|
56
|
+
showLabel={false}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
{:else if percent !== undefined}
|
|
60
|
+
<div class={cn(progressSlot(), 'pt-2')}>
|
|
61
|
+
<Progress value={percent} size={Size.SM} color={Color.SUCCESS} showLabel={false} />
|
|
62
|
+
</div>
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { statsCard } from './stats-card.js';
|
|
4
|
+
import { onMount } from 'svelte';
|
|
5
|
+
import * as echarts from 'echarts/core';
|
|
6
|
+
|
|
7
|
+
// @ts-expect-error - ECharts types are not available
|
|
8
|
+
import { LineChart } from 'echarts/charts';
|
|
9
|
+
|
|
10
|
+
// @ts-expect-error - ECharts types are not available
|
|
11
|
+
import { GridComponent } from 'echarts/components';
|
|
12
|
+
// @ts-expect-error - ECharts types are not available
|
|
13
|
+
import { SVGRenderer } from 'echarts/renderers';
|
|
14
|
+
import { Color } from '../../variants.js';
|
|
15
|
+
import type { StatsCardProps } from '../../index.js';
|
|
16
|
+
|
|
17
|
+
// @ts-expect-error - ECharts types are not available
|
|
18
|
+
echarts.use([LineChart, GridComponent, SVGRenderer]);
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
label,
|
|
22
|
+
value,
|
|
23
|
+
previousValue,
|
|
24
|
+
previousValuePrefix = 'from',
|
|
25
|
+
trend,
|
|
26
|
+
color = Color.PRIMARY,
|
|
27
|
+
chartData,
|
|
28
|
+
children,
|
|
29
|
+
class: className = '',
|
|
30
|
+
formatLargeNumbers = true
|
|
31
|
+
}: StatsCardProps = $props();
|
|
32
|
+
|
|
33
|
+
// Chart container reference
|
|
34
|
+
let chartContainer: HTMLDivElement | undefined = $state();
|
|
35
|
+
// @ts-expect-error - ECharts types are not available
|
|
36
|
+
let chart: echarts.ECharts | undefined = $state();
|
|
37
|
+
|
|
38
|
+
function getTrendDirection(trendX?: number): 'up' | 'down' | 'neutral' {
|
|
39
|
+
if (trendX === undefined || trendX === null) return 'neutral';
|
|
40
|
+
if (trendX > 0) {
|
|
41
|
+
return 'up';
|
|
42
|
+
} else if (trendX < 0) {
|
|
43
|
+
return 'down';
|
|
44
|
+
}
|
|
45
|
+
return 'neutral';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function formatValue(val?: string | number): string {
|
|
49
|
+
if (val === undefined || val === null) return '';
|
|
50
|
+
|
|
51
|
+
let numValue: number;
|
|
52
|
+
let currencySymbol: string | null = null;
|
|
53
|
+
|
|
54
|
+
// Handle string inputs
|
|
55
|
+
if (typeof val === 'string') {
|
|
56
|
+
// Check for currency symbols
|
|
57
|
+
const currencyMatch = val.match(/^(\$|€|£|¥)/);
|
|
58
|
+
if (currencyMatch) {
|
|
59
|
+
currencySymbol = currencyMatch[0];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Extract the numeric value
|
|
63
|
+
const cleanedStr = val.replace(/[^0-9.-]/g, '');
|
|
64
|
+
if (/^-?\d+(\.\d+)?$/.test(cleanedStr)) {
|
|
65
|
+
numValue = parseFloat(cleanedStr);
|
|
66
|
+
} else {
|
|
67
|
+
// Not a number we can format
|
|
68
|
+
return val;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// Already a number
|
|
72
|
+
numValue = val;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Format based on whether it's currency and size
|
|
76
|
+
if (currencySymbol) {
|
|
77
|
+
// Currency formatting with compact notation if needed
|
|
78
|
+
return new Intl.NumberFormat('en-US', {
|
|
79
|
+
style: 'currency',
|
|
80
|
+
currency: currencySymbolToCode(currencySymbol),
|
|
81
|
+
notation: formatLargeNumbers ? 'compact' : 'standard',
|
|
82
|
+
compactDisplay: 'short',
|
|
83
|
+
maximumFractionDigits: 1
|
|
84
|
+
}).format(numValue);
|
|
85
|
+
} else {
|
|
86
|
+
// Regular number formatting with compact notation if needed
|
|
87
|
+
return new Intl.NumberFormat('en-US', {
|
|
88
|
+
notation: formatLargeNumbers ? 'compact' : 'standard',
|
|
89
|
+
compactDisplay: 'short',
|
|
90
|
+
maximumFractionDigits: 1
|
|
91
|
+
}).format(numValue);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Helper function to convert currency symbols to ISO codes
|
|
96
|
+
function currencySymbolToCode(symbol: string): string {
|
|
97
|
+
const map: Record<string, string> = {
|
|
98
|
+
$: 'USD',
|
|
99
|
+
'€': 'EUR',
|
|
100
|
+
'£': 'GBP',
|
|
101
|
+
'¥': 'JPY'
|
|
102
|
+
};
|
|
103
|
+
return map[symbol] || 'USD';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const chartColorMap = {
|
|
107
|
+
[Color.PRIMARY]: '#4F46E5',
|
|
108
|
+
[Color.SECONDARY]: '#6B7280',
|
|
109
|
+
[Color.INFO]: '#3B82F6',
|
|
110
|
+
[Color.SUCCESS]: '#10B981',
|
|
111
|
+
[Color.WARNING]: '#F59E0B',
|
|
112
|
+
[Color.DANGER]: '#EF4444',
|
|
113
|
+
[Color.DEFAULT]: '#6B7280'
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const trendDirection = $derived(getTrendDirection(trend));
|
|
117
|
+
const formattedValue = $derived(formatValue(value));
|
|
118
|
+
const formattedPreviousValue = $derived(
|
|
119
|
+
previousValue !== undefined ? formatValue(previousValue) : undefined
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const {
|
|
123
|
+
base,
|
|
124
|
+
label: labelSlot,
|
|
125
|
+
value: valueSlot,
|
|
126
|
+
trend: trendSlot,
|
|
127
|
+
previousValue: previousValueSlot
|
|
128
|
+
} = $derived(
|
|
129
|
+
statsCard({
|
|
130
|
+
color,
|
|
131
|
+
trendDirection
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const labelClasses = $derived(cn(labelSlot(), 'text-sm font-medium mb-1'));
|
|
136
|
+
const valueClasses = $derived(cn(valueSlot(), 'text-4xl font-bold'));
|
|
137
|
+
const trendClasses = $derived(cn(trendSlot(), 'text-sm font-medium ml-2'));
|
|
138
|
+
const previousValueClasses = $derived(cn(previousValueSlot(), 'text-sm text-default-500 mt-1'));
|
|
139
|
+
|
|
140
|
+
const trendFormatted = $derived.by(() => {
|
|
141
|
+
if (trend === undefined || trend === null) return '';
|
|
142
|
+
const absValue = Math.abs(trend);
|
|
143
|
+
const formattedValue = absValue.toFixed(1).replace(/\.0$/, '');
|
|
144
|
+
return trend >= 0 ? `+${formattedValue}%` : `-${formattedValue}%`;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const chartColor = $derived(chartColorMap[color] || chartColorMap[Color.DEFAULT]);
|
|
148
|
+
|
|
149
|
+
onMount(() => {
|
|
150
|
+
if (!chartData || chartData.length < 2 || !chartContainer) return;
|
|
151
|
+
|
|
152
|
+
// @ts-expect-error - ECharts types are not available
|
|
153
|
+
chart = echarts.init(chartContainer);
|
|
154
|
+
|
|
155
|
+
// Set chart options
|
|
156
|
+
const options = {
|
|
157
|
+
grid: {
|
|
158
|
+
left: 0,
|
|
159
|
+
right: 0,
|
|
160
|
+
top: 0,
|
|
161
|
+
bottom: 0
|
|
162
|
+
},
|
|
163
|
+
xAxis: {
|
|
164
|
+
type: 'category',
|
|
165
|
+
show: false,
|
|
166
|
+
data: Array.from({ length: chartData.length }, (_, i) => i)
|
|
167
|
+
},
|
|
168
|
+
yAxis: {
|
|
169
|
+
type: 'value',
|
|
170
|
+
show: false
|
|
171
|
+
},
|
|
172
|
+
series: [
|
|
173
|
+
{
|
|
174
|
+
data: chartData,
|
|
175
|
+
type: 'line',
|
|
176
|
+
symbol: 'none',
|
|
177
|
+
lineStyle: {
|
|
178
|
+
color: chartColor,
|
|
179
|
+
width: 2
|
|
180
|
+
},
|
|
181
|
+
areaStyle: {
|
|
182
|
+
color: {
|
|
183
|
+
type: 'linear',
|
|
184
|
+
x: 0,
|
|
185
|
+
y: 0,
|
|
186
|
+
x2: 0,
|
|
187
|
+
y2: 1,
|
|
188
|
+
colorStops: [
|
|
189
|
+
{
|
|
190
|
+
offset: 0,
|
|
191
|
+
color: chartColor + '40' // 25% opacity
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
offset: 1,
|
|
195
|
+
color: chartColor + '00' // 0% opacity
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
smooth: true
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
animation: false,
|
|
204
|
+
animationDuration: 1000
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
chart.setOption(options);
|
|
208
|
+
|
|
209
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
210
|
+
chart && chart.resize();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
resizeObserver.observe(chartContainer);
|
|
214
|
+
|
|
215
|
+
return () => {
|
|
216
|
+
resizeObserver.disconnect();
|
|
217
|
+
chart.dispose();
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
</script>
|
|
221
|
+
|
|
222
|
+
<div
|
|
223
|
+
class={cn(
|
|
224
|
+
base(),
|
|
225
|
+
'@container flex flex-col rounded-lg border border-default-200 bg-white p-6 shadow-sm',
|
|
226
|
+
className
|
|
227
|
+
)}
|
|
228
|
+
>
|
|
229
|
+
<div class="flex items-center justify-between">
|
|
230
|
+
{#if label}
|
|
231
|
+
<dt class={labelClasses}>{label}</dt>
|
|
232
|
+
{/if}
|
|
233
|
+
{#if trend !== undefined && trend !== null}
|
|
234
|
+
<span class={trendClasses}>
|
|
235
|
+
{trendFormatted}
|
|
236
|
+
</span>
|
|
237
|
+
{/if}
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<div class="mt-1 flex flex-row items-center overflow-clip">
|
|
241
|
+
<div class="w-full flex-grow">
|
|
242
|
+
{#if value !== undefined}
|
|
243
|
+
<dd class={valueClasses} title={value}>
|
|
244
|
+
{formattedValue}
|
|
245
|
+
</dd>
|
|
246
|
+
{/if}
|
|
247
|
+
|
|
248
|
+
{#if previousValue !== undefined}
|
|
249
|
+
<div class={previousValueClasses}>
|
|
250
|
+
{previousValuePrefix}
|
|
251
|
+
{formattedPreviousValue}
|
|
252
|
+
</div>
|
|
253
|
+
{/if}
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
{#if chartData && chartData.length > 1}
|
|
257
|
+
<div class="h-10 w-full min-w-32 @max-[212.862px]:hidden" bind:this={chartContainer}></div>
|
|
258
|
+
{/if}
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
{#if children}
|
|
262
|
+
<div class="mt-4">
|
|
263
|
+
{@render children()}
|
|
264
|
+
</div>
|
|
265
|
+
{/if}
|
|
266
|
+
</div>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Color } from '../../variants.js';
|
|
2
|
+
export declare const card: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
color: {
|
|
4
|
+
[Color.DEFAULT]: {
|
|
5
|
+
base: string;
|
|
6
|
+
title: string;
|
|
7
|
+
body: string;
|
|
8
|
+
};
|
|
9
|
+
[Color.PRIMARY]: {
|
|
10
|
+
base: string;
|
|
11
|
+
title: string;
|
|
12
|
+
body: string;
|
|
13
|
+
};
|
|
14
|
+
[Color.SECONDARY]: {
|
|
15
|
+
base: string;
|
|
16
|
+
title: string;
|
|
17
|
+
body: string;
|
|
18
|
+
};
|
|
19
|
+
[Color.INFO]: {
|
|
20
|
+
base: string;
|
|
21
|
+
title: string;
|
|
22
|
+
body: string;
|
|
23
|
+
};
|
|
24
|
+
[Color.SUCCESS]: {
|
|
25
|
+
base: string;
|
|
26
|
+
title: string;
|
|
27
|
+
body: string;
|
|
28
|
+
};
|
|
29
|
+
[Color.WARNING]: {
|
|
30
|
+
base: string;
|
|
31
|
+
title: string;
|
|
32
|
+
body: string;
|
|
33
|
+
};
|
|
34
|
+
[Color.DANGER]: {
|
|
35
|
+
base: string;
|
|
36
|
+
title: string;
|
|
37
|
+
body: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}, {
|
|
41
|
+
base: string;
|
|
42
|
+
title: string;
|
|
43
|
+
body: string;
|
|
44
|
+
}, undefined, {
|
|
45
|
+
color: {
|
|
46
|
+
[Color.DEFAULT]: {
|
|
47
|
+
base: string;
|
|
48
|
+
title: string;
|
|
49
|
+
body: string;
|
|
50
|
+
};
|
|
51
|
+
[Color.PRIMARY]: {
|
|
52
|
+
base: string;
|
|
53
|
+
title: string;
|
|
54
|
+
body: string;
|
|
55
|
+
};
|
|
56
|
+
[Color.SECONDARY]: {
|
|
57
|
+
base: string;
|
|
58
|
+
title: string;
|
|
59
|
+
body: string;
|
|
60
|
+
};
|
|
61
|
+
[Color.INFO]: {
|
|
62
|
+
base: string;
|
|
63
|
+
title: string;
|
|
64
|
+
body: string;
|
|
65
|
+
};
|
|
66
|
+
[Color.SUCCESS]: {
|
|
67
|
+
base: string;
|
|
68
|
+
title: string;
|
|
69
|
+
body: string;
|
|
70
|
+
};
|
|
71
|
+
[Color.WARNING]: {
|
|
72
|
+
base: string;
|
|
73
|
+
title: string;
|
|
74
|
+
body: string;
|
|
75
|
+
};
|
|
76
|
+
[Color.DANGER]: {
|
|
77
|
+
base: string;
|
|
78
|
+
title: string;
|
|
79
|
+
body: string;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}, {
|
|
83
|
+
base: string;
|
|
84
|
+
title: string;
|
|
85
|
+
body: string;
|
|
86
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
87
|
+
color: {
|
|
88
|
+
[Color.DEFAULT]: {
|
|
89
|
+
base: string;
|
|
90
|
+
title: string;
|
|
91
|
+
body: string;
|
|
92
|
+
};
|
|
93
|
+
[Color.PRIMARY]: {
|
|
94
|
+
base: string;
|
|
95
|
+
title: string;
|
|
96
|
+
body: string;
|
|
97
|
+
};
|
|
98
|
+
[Color.SECONDARY]: {
|
|
99
|
+
base: string;
|
|
100
|
+
title: string;
|
|
101
|
+
body: string;
|
|
102
|
+
};
|
|
103
|
+
[Color.INFO]: {
|
|
104
|
+
base: string;
|
|
105
|
+
title: string;
|
|
106
|
+
body: string;
|
|
107
|
+
};
|
|
108
|
+
[Color.SUCCESS]: {
|
|
109
|
+
base: string;
|
|
110
|
+
title: string;
|
|
111
|
+
body: string;
|
|
112
|
+
};
|
|
113
|
+
[Color.WARNING]: {
|
|
114
|
+
base: string;
|
|
115
|
+
title: string;
|
|
116
|
+
body: string;
|
|
117
|
+
};
|
|
118
|
+
[Color.DANGER]: {
|
|
119
|
+
base: string;
|
|
120
|
+
title: string;
|
|
121
|
+
body: string;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
}, {
|
|
125
|
+
base: string;
|
|
126
|
+
title: string;
|
|
127
|
+
body: string;
|
|
128
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
import { Color } from '../../variants.js';
|
|
3
|
+
export const card = tv({
|
|
4
|
+
slots: {
|
|
5
|
+
base: 'flex flex-col p-4 gap-2 border rounded-md shadow-sm',
|
|
6
|
+
title: 'text-base font-semibold',
|
|
7
|
+
body: 'text-base'
|
|
8
|
+
},
|
|
9
|
+
variants: {
|
|
10
|
+
color: {
|
|
11
|
+
[Color.DEFAULT]: {
|
|
12
|
+
base: 'bg-default-50 border-default-200',
|
|
13
|
+
title: 'text-default-900',
|
|
14
|
+
body: 'text-default-700'
|
|
15
|
+
},
|
|
16
|
+
[Color.PRIMARY]: {
|
|
17
|
+
base: 'bg-primary-50 border-primary-200',
|
|
18
|
+
title: 'text-primary-900',
|
|
19
|
+
body: 'text-primary-700'
|
|
20
|
+
},
|
|
21
|
+
[Color.SECONDARY]: {
|
|
22
|
+
base: 'bg-secondary-50 border-secondary-200',
|
|
23
|
+
title: 'text-secondary-900',
|
|
24
|
+
body: 'text-secondary-700'
|
|
25
|
+
},
|
|
26
|
+
[Color.INFO]: {
|
|
27
|
+
base: 'bg-info-50 border-info-200',
|
|
28
|
+
title: 'text-info-900',
|
|
29
|
+
body: 'text-info-700'
|
|
30
|
+
},
|
|
31
|
+
[Color.SUCCESS]: {
|
|
32
|
+
base: 'bg-success-50 border-success-200',
|
|
33
|
+
title: 'text-success-900',
|
|
34
|
+
body: 'text-success-700'
|
|
35
|
+
},
|
|
36
|
+
[Color.WARNING]: {
|
|
37
|
+
base: 'bg-warning-50 border-warning-200',
|
|
38
|
+
title: 'text-warning-900',
|
|
39
|
+
body: 'text-warning-700'
|
|
40
|
+
},
|
|
41
|
+
[Color.DANGER]: {
|
|
42
|
+
base: 'bg-danger-50 border-danger-200',
|
|
43
|
+
title: 'text-danger-900',
|
|
44
|
+
body: 'text-danger-700'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
defaultVariants: {
|
|
49
|
+
color: Color.DEFAULT
|
|
50
|
+
}
|
|
51
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export declare const metricCard: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
[key: string]: {
|
|
3
|
+
[key: string]: import("tailwind-merge").ClassNameValue | {
|
|
4
|
+
base?: import("tailwind-merge").ClassNameValue;
|
|
5
|
+
value?: import("tailwind-merge").ClassNameValue;
|
|
6
|
+
title?: import("tailwind-merge").ClassNameValue;
|
|
7
|
+
progress?: import("tailwind-merge").ClassNameValue;
|
|
8
|
+
detail?: import("tailwind-merge").ClassNameValue;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
} | {
|
|
12
|
+
[x: string]: {
|
|
13
|
+
[x: string]: import("tailwind-merge").ClassNameValue | {
|
|
14
|
+
base?: import("tailwind-merge").ClassNameValue;
|
|
15
|
+
value?: import("tailwind-merge").ClassNameValue;
|
|
16
|
+
title?: import("tailwind-merge").ClassNameValue;
|
|
17
|
+
progress?: import("tailwind-merge").ClassNameValue;
|
|
18
|
+
detail?: import("tailwind-merge").ClassNameValue;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
} | {}, {
|
|
22
|
+
base: string;
|
|
23
|
+
title: string;
|
|
24
|
+
value: string;
|
|
25
|
+
detail: string;
|
|
26
|
+
progress: string;
|
|
27
|
+
}, undefined, {
|
|
28
|
+
[key: string]: {
|
|
29
|
+
[key: string]: import("tailwind-merge").ClassNameValue | {
|
|
30
|
+
base?: import("tailwind-merge").ClassNameValue;
|
|
31
|
+
value?: import("tailwind-merge").ClassNameValue;
|
|
32
|
+
title?: import("tailwind-merge").ClassNameValue;
|
|
33
|
+
progress?: import("tailwind-merge").ClassNameValue;
|
|
34
|
+
detail?: import("tailwind-merge").ClassNameValue;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
} | {}, {
|
|
38
|
+
base: string;
|
|
39
|
+
title: string;
|
|
40
|
+
value: string;
|
|
41
|
+
detail: string;
|
|
42
|
+
progress: string;
|
|
43
|
+
}, import("tailwind-variants").TVReturnType<unknown, {
|
|
44
|
+
base: string;
|
|
45
|
+
title: string;
|
|
46
|
+
value: string;
|
|
47
|
+
detail: string;
|
|
48
|
+
progress: string;
|
|
49
|
+
}, undefined, unknown, unknown, undefined>>;
|