@makolabs/ripple 1.1.1 → 1.2.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/dist/index.d.ts +21 -1
- package/dist/index.js +2 -0
- package/dist/layout/card/RankedCard.svelte +56 -0
- package/dist/layout/card/RankedCard.svelte.d.ts +4 -0
- package/dist/layout/card/ranked-card.d.ts +104 -0
- package/dist/layout/card/ranked-card.js +28 -0
- package/dist/modal/Modal.svelte +73 -71
- package/dist/modal/Modal.svelte.d.ts +1 -1
- package/dist/modal/modal.d.ts +1 -0
- package/dist/pipeline/Pipeline.svelte +11 -2
- package/dist/pipeline/Pipeline.svelte.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,24 @@ export type AnchorHTMLProps = {
|
|
|
48
48
|
href: string;
|
|
49
49
|
} & Record<string, unknown>;
|
|
50
50
|
export type ButtonProps = BaseButtonProps & (ButtonHTMLProps | AnchorHTMLProps);
|
|
51
|
-
export type
|
|
51
|
+
export type ModalProps = {
|
|
52
|
+
open?: boolean;
|
|
53
|
+
onclose?: () => void;
|
|
54
|
+
title?: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
size?: VariantSizes;
|
|
57
|
+
hideCloseButton?: boolean;
|
|
58
|
+
class?: string;
|
|
59
|
+
contentclass?: string;
|
|
60
|
+
bodyclass?: string;
|
|
61
|
+
titleclass?: string;
|
|
62
|
+
headerclass?: string;
|
|
63
|
+
backdropclass?: string;
|
|
64
|
+
footerclass?: string;
|
|
65
|
+
children?: Snippet;
|
|
66
|
+
footer?: Snippet;
|
|
67
|
+
header?: Snippet;
|
|
68
|
+
};
|
|
52
69
|
export type DrawerProps = {
|
|
53
70
|
open?: boolean;
|
|
54
71
|
onclose?: () => void;
|
|
@@ -159,6 +176,7 @@ export type MetricCardProps = {
|
|
|
159
176
|
segments?: ProgressSegment[];
|
|
160
177
|
class?: ClassValue;
|
|
161
178
|
};
|
|
179
|
+
export type { RankedCardProps, RankedCardItem, RankedCardMetric } from './layout/card/ranked-card.js';
|
|
162
180
|
export type DataRow = Record<string, any>;
|
|
163
181
|
export type KeyType = keyof DataRow;
|
|
164
182
|
export type StatusType = 'active' | 'inactive' | 'pending' | 'error' | 'default';
|
|
@@ -327,6 +345,7 @@ export { default as Dropdown } from './elements/dropdown/Dropdown.svelte';
|
|
|
327
345
|
export { default as Select } from './elements/dropdown/Select.svelte';
|
|
328
346
|
export { default as Card } from './layout/card/Card.svelte';
|
|
329
347
|
export { default as MetricCard } from './layout/card/MetricCard.svelte';
|
|
348
|
+
export { default as RankedCard } from './layout/card/RankedCard.svelte';
|
|
330
349
|
export { default as Alert } from './elements/alert/Alert.svelte';
|
|
331
350
|
export type TabProps = {
|
|
332
351
|
value: string;
|
|
@@ -376,6 +395,7 @@ export { drawer } from './drawer/drawer.js';
|
|
|
376
395
|
export { selectTV } from './elements/dropdown/select.js';
|
|
377
396
|
export { breadcrumbs } from './header/breadcrumbs.js';
|
|
378
397
|
export { metricCard } from './layout/card/metric-card.js';
|
|
398
|
+
export { rankedCard } from './layout/card/ranked-card.js';
|
|
379
399
|
export { activityList } from './layout/activity-list/activity-list.js';
|
|
380
400
|
export type ChartColorKey = keyof typeof ChartColor;
|
|
381
401
|
export type ChartColorValue = (typeof ChartColor)[ChartColorKey];
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ export { default as Select } from './elements/dropdown/Select.svelte';
|
|
|
30
30
|
// Elements - Card
|
|
31
31
|
export { default as Card } from './layout/card/Card.svelte';
|
|
32
32
|
export { default as MetricCard } from './layout/card/MetricCard.svelte';
|
|
33
|
+
export { default as RankedCard } from './layout/card/RankedCard.svelte';
|
|
33
34
|
// Elements - Alert
|
|
34
35
|
export { default as Alert } from './elements/alert/Alert.svelte';
|
|
35
36
|
export { default as Tab } from './layout/tabs/Tab.svelte';
|
|
@@ -55,6 +56,7 @@ export { drawer } from './drawer/drawer.js';
|
|
|
55
56
|
export { selectTV } from './elements/dropdown/select.js';
|
|
56
57
|
export { breadcrumbs } from './header/breadcrumbs.js';
|
|
57
58
|
export { metricCard } from './layout/card/metric-card.js';
|
|
59
|
+
export { rankedCard } from './layout/card/ranked-card.js';
|
|
58
60
|
export { activityList } from './layout/activity-list/activity-list.js';
|
|
59
61
|
export { default as Chart } from './charts/Chart.svelte';
|
|
60
62
|
export { default as FileUpload } from './elements/file-upload/FileUpload.svelte';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { rankedCard, type RankedCardProps } from './ranked-card.js';
|
|
4
|
+
|
|
5
|
+
let { items, columns = 3, class: className = '' }: RankedCardProps = $props();
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
container,
|
|
9
|
+
card,
|
|
10
|
+
header,
|
|
11
|
+
rank,
|
|
12
|
+
title,
|
|
13
|
+
metricsContainer,
|
|
14
|
+
metricRow,
|
|
15
|
+
metricLabel,
|
|
16
|
+
metricValue,
|
|
17
|
+
actionContainer,
|
|
18
|
+
actionText,
|
|
19
|
+
actionLabel
|
|
20
|
+
} = $derived(rankedCard({ columns }));
|
|
21
|
+
|
|
22
|
+
const containerClass = $derived(cn(container(), className));
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<div class={containerClass}>
|
|
26
|
+
{#each items as item}
|
|
27
|
+
<div class={card()}>
|
|
28
|
+
<!-- Header with Rank and Title -->
|
|
29
|
+
<div class={header()}>
|
|
30
|
+
<span class={rank()}>#{item.rank}</span>
|
|
31
|
+
<h4 class={title()}>{item.title}</h4>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Metrics -->
|
|
35
|
+
<div class={metricsContainer()}>
|
|
36
|
+
{#each item.metrics as metric}
|
|
37
|
+
<div class={metricRow()}>
|
|
38
|
+
<span class={metricLabel()}>{metric.label}:</span>
|
|
39
|
+
<span class={cn(metricValue(), metric.color || '')}>{metric.value}</span>
|
|
40
|
+
</div>
|
|
41
|
+
{/each}
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<!-- Action/Recommendation -->
|
|
45
|
+
{#if item.action}
|
|
46
|
+
<div class={actionContainer()}>
|
|
47
|
+
<p class={actionText()}>
|
|
48
|
+
<span class={actionLabel()}>Action:</span>
|
|
49
|
+
<span class={item.action.color || ''}>{item.action.text}</span>
|
|
50
|
+
</p>
|
|
51
|
+
</div>
|
|
52
|
+
{/if}
|
|
53
|
+
</div>
|
|
54
|
+
{/each}
|
|
55
|
+
</div>
|
|
56
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export declare const rankedCard: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
columns: {
|
|
3
|
+
1: {
|
|
4
|
+
container: string;
|
|
5
|
+
};
|
|
6
|
+
2: {
|
|
7
|
+
container: string;
|
|
8
|
+
};
|
|
9
|
+
3: {
|
|
10
|
+
container: string;
|
|
11
|
+
};
|
|
12
|
+
4: {
|
|
13
|
+
container: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}, {
|
|
17
|
+
container: string;
|
|
18
|
+
card: string;
|
|
19
|
+
header: string;
|
|
20
|
+
rank: string;
|
|
21
|
+
title: string;
|
|
22
|
+
metricsContainer: string;
|
|
23
|
+
metricRow: string;
|
|
24
|
+
metricLabel: string;
|
|
25
|
+
metricValue: string;
|
|
26
|
+
actionContainer: string;
|
|
27
|
+
actionText: string;
|
|
28
|
+
actionLabel: string;
|
|
29
|
+
}, undefined, {
|
|
30
|
+
columns: {
|
|
31
|
+
1: {
|
|
32
|
+
container: string;
|
|
33
|
+
};
|
|
34
|
+
2: {
|
|
35
|
+
container: string;
|
|
36
|
+
};
|
|
37
|
+
3: {
|
|
38
|
+
container: string;
|
|
39
|
+
};
|
|
40
|
+
4: {
|
|
41
|
+
container: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}, {
|
|
45
|
+
container: string;
|
|
46
|
+
card: string;
|
|
47
|
+
header: string;
|
|
48
|
+
rank: string;
|
|
49
|
+
title: string;
|
|
50
|
+
metricsContainer: string;
|
|
51
|
+
metricRow: string;
|
|
52
|
+
metricLabel: string;
|
|
53
|
+
metricValue: string;
|
|
54
|
+
actionContainer: string;
|
|
55
|
+
actionText: string;
|
|
56
|
+
actionLabel: string;
|
|
57
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
58
|
+
columns: {
|
|
59
|
+
1: {
|
|
60
|
+
container: string;
|
|
61
|
+
};
|
|
62
|
+
2: {
|
|
63
|
+
container: string;
|
|
64
|
+
};
|
|
65
|
+
3: {
|
|
66
|
+
container: string;
|
|
67
|
+
};
|
|
68
|
+
4: {
|
|
69
|
+
container: string;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
}, {
|
|
73
|
+
container: string;
|
|
74
|
+
card: string;
|
|
75
|
+
header: string;
|
|
76
|
+
rank: string;
|
|
77
|
+
title: string;
|
|
78
|
+
metricsContainer: string;
|
|
79
|
+
metricRow: string;
|
|
80
|
+
metricLabel: string;
|
|
81
|
+
metricValue: string;
|
|
82
|
+
actionContainer: string;
|
|
83
|
+
actionText: string;
|
|
84
|
+
actionLabel: string;
|
|
85
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
86
|
+
export type RankedCardMetric = {
|
|
87
|
+
label: string;
|
|
88
|
+
value: string;
|
|
89
|
+
color?: string;
|
|
90
|
+
};
|
|
91
|
+
export type RankedCardItem = {
|
|
92
|
+
rank: number;
|
|
93
|
+
title: string;
|
|
94
|
+
metrics: RankedCardMetric[];
|
|
95
|
+
action?: {
|
|
96
|
+
text: string;
|
|
97
|
+
color?: string;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
export type RankedCardProps = {
|
|
101
|
+
items: RankedCardItem[];
|
|
102
|
+
columns?: 1 | 2 | 3 | 4;
|
|
103
|
+
class?: string;
|
|
104
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const rankedCard = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
container: 'grid gap-4',
|
|
5
|
+
card: 'border border-default-200 rounded-lg p-4',
|
|
6
|
+
header: 'flex items-center gap-2 mb-3',
|
|
7
|
+
rank: 'text-base font-bold text-default-400',
|
|
8
|
+
title: 'text-sm font-semibold text-default-900',
|
|
9
|
+
metricsContainer: 'space-y-2 mb-3',
|
|
10
|
+
metricRow: 'flex items-center justify-between text-sm',
|
|
11
|
+
metricLabel: 'text-default-600',
|
|
12
|
+
metricValue: 'font-medium text-default-900',
|
|
13
|
+
actionContainer: 'pt-3 border-t border-default-200',
|
|
14
|
+
actionText: 'text-xs text-default-600',
|
|
15
|
+
actionLabel: 'font-semibold text-default-700'
|
|
16
|
+
},
|
|
17
|
+
variants: {
|
|
18
|
+
columns: {
|
|
19
|
+
1: { container: 'grid-cols-1' },
|
|
20
|
+
2: { container: 'grid-cols-1 md:grid-cols-2' },
|
|
21
|
+
3: { container: 'grid-cols-1 md:grid-cols-3' },
|
|
22
|
+
4: { container: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4' }
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
columns: 3
|
|
27
|
+
}
|
|
28
|
+
});
|
package/dist/modal/Modal.svelte
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { fade, scale } from 'svelte/transition';
|
|
3
3
|
import { quintOut } from 'svelte/easing';
|
|
4
4
|
import { cn } from '../helper/cls.js';
|
|
5
|
-
import { modal
|
|
6
|
-
|
|
5
|
+
import { modal } from './modal.js';
|
|
6
|
+
import type { ModalProps } from '../index.js';
|
|
7
|
+
|
|
7
8
|
let {
|
|
8
9
|
open = $bindable(false),
|
|
9
10
|
onclose = () => {},
|
|
@@ -18,7 +19,8 @@
|
|
|
18
19
|
headerclass: headerClassName = '',
|
|
19
20
|
backdropclass: backdropClassName = '',
|
|
20
21
|
children,
|
|
21
|
-
footer
|
|
22
|
+
footer,
|
|
23
|
+
header
|
|
22
24
|
}: ModalProps = $props();
|
|
23
25
|
|
|
24
26
|
const styles = $derived(modal({ size }));
|
|
@@ -28,26 +30,28 @@
|
|
|
28
30
|
const containerClass = $derived(cn(styles.container(), contentClassName));
|
|
29
31
|
const headerClass = $derived(cn(styles.header(), headerClassName));
|
|
30
32
|
const titleClass = $derived(cn(styles.title(), titleClassName));
|
|
31
|
-
const bodyClass = $derived(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const bodyClass = $derived(
|
|
34
|
+
cn(
|
|
35
|
+
'flex-1 px-6 overflow-y-auto',
|
|
36
|
+
// Adjust top padding based on header presence
|
|
37
|
+
title || description ? 'py-4' : 'pt-6 pb-4',
|
|
38
|
+
bodyClassName
|
|
39
|
+
)
|
|
40
|
+
);
|
|
37
41
|
const footerClass = $derived(cn(styles.footer(), ''));
|
|
38
42
|
const closeClass = $derived(cn(styles.close(), ''));
|
|
39
43
|
const descriptionClass = $derived(cn(styles.description(), ''));
|
|
40
|
-
|
|
44
|
+
|
|
41
45
|
function handleBackdropClick() {
|
|
42
46
|
onclose();
|
|
43
47
|
}
|
|
44
|
-
|
|
48
|
+
|
|
45
49
|
function handleKeydown(e: KeyboardEvent) {
|
|
46
50
|
if (e.key === 'Escape' && open) {
|
|
47
51
|
onclose();
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
|
-
|
|
54
|
+
|
|
51
55
|
$effect(() => {
|
|
52
56
|
if (open) {
|
|
53
57
|
document.body.style.overflow = 'hidden';
|
|
@@ -56,7 +60,7 @@
|
|
|
56
60
|
document.body.style.overflow = '';
|
|
57
61
|
document.removeEventListener('keydown', handleKeydown);
|
|
58
62
|
}
|
|
59
|
-
|
|
63
|
+
|
|
60
64
|
return () => {
|
|
61
65
|
document.body.style.overflow = '';
|
|
62
66
|
document.removeEventListener('keydown', handleKeydown);
|
|
@@ -64,78 +68,76 @@
|
|
|
64
68
|
});
|
|
65
69
|
</script>
|
|
66
70
|
|
|
71
|
+
{#snippet predefinedHeader()}
|
|
72
|
+
{#if title || description}
|
|
73
|
+
<header class={headerClass}>
|
|
74
|
+
<div class="flex-1">
|
|
75
|
+
{#if title}
|
|
76
|
+
<h2 class={titleClass}>{title}</h2>
|
|
77
|
+
{/if}
|
|
78
|
+
</div>
|
|
79
|
+
{#if !hideCloseButton}
|
|
80
|
+
<button type="button" class={closeClass} onclick={onclose} aria-label="Close">
|
|
81
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
82
|
+
<path
|
|
83
|
+
d="M15 5L5 15M5 5L15 15"
|
|
84
|
+
stroke="currentColor"
|
|
85
|
+
stroke-width="2"
|
|
86
|
+
stroke-linecap="round"
|
|
87
|
+
/>
|
|
88
|
+
</svg>
|
|
89
|
+
</button>
|
|
90
|
+
{/if}
|
|
91
|
+
</header>
|
|
92
|
+
|
|
93
|
+
{/if}
|
|
94
|
+
|
|
95
|
+
<!-- Close button only (positioned absolutely when no header) -->
|
|
96
|
+
{#if !title && !description && !hideCloseButton}
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
class="absolute top-4 right-4 z-10 rounded-lg p-2 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600"
|
|
100
|
+
onclick={onclose}
|
|
101
|
+
aria-label="Close"
|
|
102
|
+
>
|
|
103
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
104
|
+
<path
|
|
105
|
+
d="M15 5L5 15M5 5L15 15"
|
|
106
|
+
stroke="currentColor"
|
|
107
|
+
stroke-width="2"
|
|
108
|
+
stroke-linecap="round"
|
|
109
|
+
/>
|
|
110
|
+
</svg>
|
|
111
|
+
</button>
|
|
112
|
+
{/if}
|
|
113
|
+
{/snippet}
|
|
114
|
+
|
|
67
115
|
{#if open}
|
|
68
116
|
<div class={baseClass} role="dialog" aria-modal="true">
|
|
69
117
|
<!-- Backdrop -->
|
|
70
|
-
<div
|
|
118
|
+
<div
|
|
71
119
|
class={backdropClass}
|
|
72
120
|
onclick={handleBackdropClick}
|
|
73
121
|
transition:fade={{ duration: 200 }}
|
|
74
|
-
role="presentation"
|
|
75
|
-
|
|
122
|
+
role="presentation"
|
|
123
|
+
></div>
|
|
124
|
+
|
|
76
125
|
<!-- Modal Container -->
|
|
77
|
-
<div
|
|
78
|
-
class={containerClass}
|
|
79
|
-
transition:scale={{ duration: 200, easing: quintOut, start: 0.95 }}
|
|
80
|
-
>
|
|
126
|
+
<div class={containerClass} transition:scale={{ duration: 200, easing: quintOut, start: 0.95 }}>
|
|
81
127
|
<!-- Header -->
|
|
82
|
-
{#if
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
<h2 class={titleClass}>{title}</h2>
|
|
87
|
-
{/if}
|
|
88
|
-
{#if description}
|
|
89
|
-
<p class={descriptionClass}>{description}</p>
|
|
90
|
-
{/if}
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
{#if !hideCloseButton}
|
|
94
|
-
<button
|
|
95
|
-
type="button"
|
|
96
|
-
class={closeClass}
|
|
97
|
-
onclick={onclose}
|
|
98
|
-
aria-label="Close"
|
|
99
|
-
>
|
|
100
|
-
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
101
|
-
<path
|
|
102
|
-
d="M15 5L5 15M5 5L15 15"
|
|
103
|
-
stroke="currentColor"
|
|
104
|
-
stroke-width="2"
|
|
105
|
-
stroke-linecap="round"
|
|
106
|
-
/>
|
|
107
|
-
</svg>
|
|
108
|
-
</button>
|
|
109
|
-
{/if}
|
|
110
|
-
</header>
|
|
111
|
-
{/if}
|
|
112
|
-
|
|
113
|
-
<!-- Close button only (positioned absolutely when no header) -->
|
|
114
|
-
{#if !title && !description && !hideCloseButton}
|
|
115
|
-
<button
|
|
116
|
-
type="button"
|
|
117
|
-
class="absolute top-4 right-4 p-2 rounded-lg text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors z-10"
|
|
118
|
-
onclick={onclose}
|
|
119
|
-
aria-label="Close"
|
|
120
|
-
>
|
|
121
|
-
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
122
|
-
<path
|
|
123
|
-
d="M15 5L5 15M5 5L15 15"
|
|
124
|
-
stroke="currentColor"
|
|
125
|
-
stroke-width="2"
|
|
126
|
-
stroke-linecap="round"
|
|
127
|
-
/>
|
|
128
|
-
</svg>
|
|
129
|
-
</button>
|
|
128
|
+
{#if header}
|
|
129
|
+
{@render header()}
|
|
130
|
+
{:else}
|
|
131
|
+
{@render predefinedHeader()}
|
|
130
132
|
{/if}
|
|
131
|
-
|
|
133
|
+
|
|
132
134
|
<!-- Body -->
|
|
133
135
|
{#if children}
|
|
134
136
|
<div class={bodyClass}>
|
|
135
137
|
{@render children()}
|
|
136
138
|
</div>
|
|
137
139
|
{/if}
|
|
138
|
-
|
|
140
|
+
|
|
139
141
|
<!-- Footer -->
|
|
140
142
|
{#if footer}
|
|
141
143
|
<footer class={footerClass}>
|
|
@@ -144,4 +146,4 @@
|
|
|
144
146
|
{/if}
|
|
145
147
|
</div>
|
|
146
148
|
</div>
|
|
147
|
-
{/if}
|
|
149
|
+
{/if}
|
package/dist/modal/modal.d.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
size?: 'sm' | 'base' | 'lg';
|
|
16
16
|
equalWidth?: boolean;
|
|
17
17
|
children?: Snippet<[PipelineStage, number]>;
|
|
18
|
+
beneathChildren?: Snippet<[PipelineStage, number]>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
let {
|
|
@@ -22,7 +23,8 @@
|
|
|
22
23
|
class: className = '',
|
|
23
24
|
size = 'base',
|
|
24
25
|
equalWidth = true,
|
|
25
|
-
children
|
|
26
|
+
children,
|
|
27
|
+
beneathChildren
|
|
26
28
|
}: Props = $props();
|
|
27
29
|
|
|
28
30
|
const pipeline = tv({
|
|
@@ -126,7 +128,7 @@
|
|
|
126
128
|
{@const isLast = index === stages.length - 1}
|
|
127
129
|
{@const chevronWidth = 20}
|
|
128
130
|
|
|
129
|
-
<div class={getStageStyles(stage).stage()} style="{!isFirst ? `margin-left: -${chevronWidth}px; z-index: ${stages.length - index}` : `z-index: ${stages.length - index}`}">
|
|
131
|
+
<div class="flex flex-col {getStageStyles(stage).stage()}" style="{!isFirst ? `margin-left: -${chevronWidth}px; z-index: ${stages.length - index}` : `z-index: ${stages.length - index}`}">
|
|
130
132
|
<!-- BACKGROUND LAYER (Border color - larger) -->
|
|
131
133
|
<div
|
|
132
134
|
class="{getStageStyles(stage).borderLayer()}"
|
|
@@ -153,6 +155,13 @@
|
|
|
153
155
|
{/if}
|
|
154
156
|
</div>
|
|
155
157
|
</div>
|
|
158
|
+
|
|
159
|
+
<!-- Beneath Children - Rendered directly below this stage -->
|
|
160
|
+
{#if beneathChildren}
|
|
161
|
+
<div class="mt-4">
|
|
162
|
+
{@render beneathChildren(stage, index)}
|
|
163
|
+
</div>
|
|
164
|
+
{/if}
|
|
156
165
|
</div>
|
|
157
166
|
{/each}
|
|
158
167
|
</div>
|
|
@@ -11,6 +11,7 @@ interface Props {
|
|
|
11
11
|
size?: 'sm' | 'base' | 'lg';
|
|
12
12
|
equalWidth?: boolean;
|
|
13
13
|
children?: Snippet<[PipelineStage, number]>;
|
|
14
|
+
beneathChildren?: Snippet<[PipelineStage, number]>;
|
|
14
15
|
}
|
|
15
16
|
declare const Pipeline: import("svelte").Component<Props, {}, "">;
|
|
16
17
|
type Pipeline = ReturnType<typeof Pipeline>;
|