@makolabs/ripple 2.0.0 → 2.2.0
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 +1 -3
- package/dist/index.js +0 -2
- package/dist/layout/activity-list/ActivityList.svelte +161 -34
- package/dist/layout/activity-list/activity-list-types.d.ts +82 -2
- package/dist/layout/activity-list/activity-list.d.ts +124 -0
- package/dist/layout/activity-list/activity-list.js +98 -9
- package/package.json +1 -1
- package/dist/elements/timeline/Timeline.svelte +0 -95
- package/dist/elements/timeline/Timeline.svelte.d.ts +0 -7
- package/dist/elements/timeline/timeline-types.d.ts +0 -11
- package/dist/elements/timeline/timeline-types.js +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -43,9 +43,8 @@ export type { CollapsibleProps } from './elements/collapsible/collapsible-types.
|
|
|
43
43
|
export type { TooltipProps, TooltipPlacement } from './elements/tooltip/tooltip-types.js';
|
|
44
44
|
export type { ComboboxItem, ComboboxProps } from './elements/combobox/combobox-types.js';
|
|
45
45
|
export type { AccordionProps } from './elements/accordion/accordion-types.js';
|
|
46
|
-
export type { TimelineItem } from './elements/timeline/timeline-types.js';
|
|
47
46
|
export type { FilterTab, FilterGroup, CompactFiltersProps } from './filters/filter-types.js';
|
|
48
|
-
export type { ActivityItemBadge, ActivityItemAction, ActivityItem, ActivityListProps } from './layout/activity-list/activity-list-types.js';
|
|
47
|
+
export type { ActivityItemBadge, ActivityItemAction, ActivityItem, ActivityListProps, ActivityListSize } from './layout/activity-list/activity-list-types.js';
|
|
49
48
|
export type { FileUploadProps, FileUploadSize, FilePreviewProps, UploadedFile, StagedFile } from './elements/file-upload/file-upload-types.js';
|
|
50
49
|
export type { ChatMessageType, StreamingCallback, ChatAction, ChatMessage, ChatResponse, QuickAction, FileBrowserProps } from './ai/ai-types.js';
|
|
51
50
|
export type { GetUsersOptions, GetUsersResult, UserEmail, UserPhone, User, Permission, Role, UserTableProps, UserModalProps, UserViewModalProps, UserManagementAdapter, UserManagementProps, FormErrors } from './user-management/user-management-types.js';
|
|
@@ -88,7 +87,6 @@ export { default as Collapsible } from './elements/collapsible/Collapsible.svelt
|
|
|
88
87
|
export { default as Tooltip } from './elements/tooltip/Tooltip.svelte';
|
|
89
88
|
export { default as Combobox } from './elements/combobox/Combobox.svelte';
|
|
90
89
|
export { default as Accordion } from './elements/accordion/Accordion.svelte';
|
|
91
|
-
export { default as Timeline } from './elements/timeline/Timeline.svelte';
|
|
92
90
|
export { default as Chart } from './charts/Chart.svelte';
|
|
93
91
|
export { default as FileUpload } from './elements/file-upload/FileUpload.svelte';
|
|
94
92
|
export { default as FilesPreview } from './elements/file-upload/FilesPreview.svelte';
|
package/dist/index.js
CHANGED
|
@@ -75,8 +75,6 @@ export { default as Tooltip } from './elements/tooltip/Tooltip.svelte';
|
|
|
75
75
|
export { default as Combobox } from './elements/combobox/Combobox.svelte';
|
|
76
76
|
// Elements - Accordion
|
|
77
77
|
export { default as Accordion } from './elements/accordion/Accordion.svelte';
|
|
78
|
-
// Elements - Timeline
|
|
79
|
-
export { default as Timeline } from './elements/timeline/Timeline.svelte';
|
|
80
78
|
// Chart
|
|
81
79
|
export { default as Chart } from './charts/Chart.svelte';
|
|
82
80
|
// File Upload
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../helper/cls.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
activityList,
|
|
5
|
+
iconCircleClasses,
|
|
6
|
+
accentBarClasses,
|
|
7
|
+
highlightedRowClasses,
|
|
8
|
+
highlightedRingClasses
|
|
9
|
+
} from './activity-list.js';
|
|
10
|
+
import Badge from '../../elements/badge/Badge.svelte';
|
|
11
|
+
import Button from '../../button/Button.svelte';
|
|
12
|
+
import { Color, Size } from '../../variants.js';
|
|
4
13
|
import type { ActivityListProps } from '../../index.js';
|
|
5
|
-
import { Color } from '../../variants.js';
|
|
6
14
|
|
|
7
15
|
let {
|
|
8
16
|
title,
|
|
9
17
|
items = [],
|
|
10
18
|
color = Color.DEFAULT,
|
|
19
|
+
size = 'md',
|
|
20
|
+
timeline = false,
|
|
11
21
|
class: className = '',
|
|
12
22
|
headerClass = '',
|
|
13
23
|
titleClass = '',
|
|
14
24
|
contentClass = '',
|
|
15
25
|
itemClass = '',
|
|
16
26
|
onItemClick,
|
|
17
|
-
children
|
|
27
|
+
children,
|
|
28
|
+
customContent
|
|
18
29
|
}: ActivityListProps = $props();
|
|
19
30
|
|
|
20
31
|
const {
|
|
@@ -23,18 +34,24 @@
|
|
|
23
34
|
title: titleSlot,
|
|
24
35
|
content,
|
|
25
36
|
item,
|
|
37
|
+
accentBar,
|
|
38
|
+
timelineLine,
|
|
39
|
+
iconWrapper,
|
|
40
|
+
iconInner,
|
|
41
|
+
timelineDot,
|
|
26
42
|
itemContent,
|
|
27
43
|
itemMain,
|
|
28
44
|
itemHeader,
|
|
29
45
|
itemTitle,
|
|
30
46
|
itemSubtitle,
|
|
47
|
+
itemTimestamp,
|
|
31
48
|
itemActions
|
|
32
|
-
} = $derived(activityList({ color }));
|
|
49
|
+
} = $derived(activityList({ color, size }));
|
|
33
50
|
|
|
34
51
|
const baseClass = $derived(cn(base(), className));
|
|
35
52
|
const headerClasses = $derived(cn(header(), headerClass));
|
|
36
53
|
const titleClasses = $derived(cn(titleSlot(), titleClass));
|
|
37
|
-
const contentClasses = $derived(cn(content(), contentClass));
|
|
54
|
+
const contentClasses = $derived(cn(content(), contentClass, timeline && 'relative divide-y-0'));
|
|
38
55
|
</script>
|
|
39
56
|
|
|
40
57
|
<div class={baseClass}>
|
|
@@ -48,43 +65,153 @@
|
|
|
48
65
|
{#if children}
|
|
49
66
|
{@render children()}
|
|
50
67
|
{:else}
|
|
68
|
+
{#if timeline && items.length > 1}
|
|
69
|
+
<span class={timelineLine()} aria-hidden="true"></span>
|
|
70
|
+
{/if}
|
|
51
71
|
{#each items as activityItem, index (activityItem.title + index)}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
{@const IconComponent = activityItem.icon}
|
|
73
|
+
{@const iconColorKey = activityItem.iconColor ?? 'default'}
|
|
74
|
+
{@const iconCircle = iconCircleClasses[iconColorKey] ?? iconCircleClasses.default}
|
|
75
|
+
{@const accentBarColor =
|
|
76
|
+
activityItem.accentColor && accentBarClasses[activityItem.accentColor]}
|
|
77
|
+
{@const highlightKey = activityItem.accentColor ?? 'primary'}
|
|
78
|
+
{@const highlightClass =
|
|
79
|
+
activityItem.highlighted &&
|
|
80
|
+
(highlightedRowClasses[highlightKey] ?? highlightedRowClasses.primary)}
|
|
81
|
+
{@const ringClass =
|
|
82
|
+
activityItem.highlighted &&
|
|
83
|
+
(highlightedRingClasses[highlightKey] ?? highlightedRingClasses.primary)}
|
|
84
|
+
{@const isCustom = activityItem.custom && customContent}
|
|
85
|
+
<div
|
|
86
|
+
class={cn(item(), highlightClass, itemClass)}
|
|
87
|
+
data-activity-row=""
|
|
88
|
+
data-activity-highlighted={activityItem.highlighted ? '' : undefined}
|
|
89
|
+
>
|
|
90
|
+
{#if accentBarColor}
|
|
91
|
+
<span class={cn(accentBar(), accentBarColor)} aria-hidden="true"></span>
|
|
92
|
+
{/if}
|
|
93
|
+
|
|
94
|
+
{#if IconComponent}
|
|
95
|
+
<span class={cn(iconWrapper(), iconCircle, ringClass)} aria-hidden="true">
|
|
96
|
+
<IconComponent class={iconInner()} />
|
|
97
|
+
</span>
|
|
98
|
+
{:else if timeline}
|
|
99
|
+
<span class={cn(timelineDot(), ringClass)} aria-hidden="true">
|
|
100
|
+
<span class={cn('size-3 rounded-full', iconCircle)}></span>
|
|
101
|
+
</span>
|
|
102
|
+
{/if}
|
|
103
|
+
|
|
104
|
+
{#if isCustom}
|
|
105
|
+
<div class="min-w-0 flex-1" data-activity-custom="">
|
|
106
|
+
{@render customContent?.(activityItem, index)}
|
|
107
|
+
</div>
|
|
108
|
+
{:else if timeline && activityItem.subtitle}
|
|
109
|
+
<div class="min-w-0 flex-1">
|
|
110
|
+
<div class="flex items-start justify-between gap-3">
|
|
111
|
+
<div
|
|
112
|
+
class="ring-default-200 flex-1 rounded-md bg-white p-3 ring-1"
|
|
113
|
+
data-activity-comment=""
|
|
114
|
+
>
|
|
115
|
+
<div class="mb-1 flex justify-between gap-x-4">
|
|
116
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
117
|
+
<button
|
|
118
|
+
class="text-default-900 text-sm font-medium"
|
|
119
|
+
onclick={() => onItemClick?.(activityItem, index)}
|
|
120
|
+
>
|
|
121
|
+
{activityItem.title}
|
|
122
|
+
</button>
|
|
123
|
+
{#if activityItem.badges}
|
|
124
|
+
{#each activityItem.badges as badge (badge.text)}
|
|
125
|
+
{#if badge.color}
|
|
126
|
+
<Badge color={badge.color} size={Size.SM}>{badge.text}</Badge>
|
|
127
|
+
{:else if badge.class}
|
|
128
|
+
<span
|
|
129
|
+
class="inline-flex rounded-full px-2 py-1 text-xs font-medium {badge.class}"
|
|
130
|
+
>
|
|
131
|
+
{badge.text}
|
|
132
|
+
</span>
|
|
133
|
+
{:else}
|
|
134
|
+
<Badge size={Size.SM}>{badge.text}</Badge>
|
|
135
|
+
{/if}
|
|
136
|
+
{/each}
|
|
137
|
+
{/if}
|
|
138
|
+
</div>
|
|
139
|
+
{#if activityItem.timestamp}
|
|
140
|
+
<div class={itemTimestamp()} data-activity-timestamp="">
|
|
141
|
+
{activityItem.timestamp}
|
|
142
|
+
</div>
|
|
143
|
+
{/if}
|
|
144
|
+
</div>
|
|
145
|
+
<p class="text-default-500 text-sm">{activityItem.subtitle}</p>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
{#if activityItem.actions}
|
|
149
|
+
<div class={cn(itemActions(), 'mt-2')}>
|
|
150
|
+
{#each activityItem.actions as action (action.label)}
|
|
151
|
+
<Button
|
|
152
|
+
size={Size.XS}
|
|
153
|
+
variant={action.variant ?? 'outline'}
|
|
154
|
+
color={action.color ?? Color.DEFAULT}
|
|
155
|
+
onclick={() => action.onClick?.()}
|
|
63
156
|
>
|
|
64
|
-
{
|
|
65
|
-
</
|
|
157
|
+
{action.label}
|
|
158
|
+
</Button>
|
|
66
159
|
{/each}
|
|
67
|
-
{/if}
|
|
68
|
-
</div>
|
|
69
|
-
{#if activityItem.subtitle}
|
|
70
|
-
<div class={itemSubtitle()}>
|
|
71
|
-
{activityItem.subtitle}
|
|
72
160
|
</div>
|
|
73
161
|
{/if}
|
|
74
162
|
</div>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
>
|
|
82
|
-
{action.label}
|
|
163
|
+
{:else}
|
|
164
|
+
<div class={itemContent()}>
|
|
165
|
+
<div class={itemMain()}>
|
|
166
|
+
<div class={itemHeader()}>
|
|
167
|
+
<button class={itemTitle()} onclick={() => onItemClick?.(activityItem, index)}>
|
|
168
|
+
{activityItem.title}
|
|
83
169
|
</button>
|
|
84
|
-
|
|
170
|
+
{#if activityItem.badges}
|
|
171
|
+
{#each activityItem.badges as badge (badge.text)}
|
|
172
|
+
{#if badge.color}
|
|
173
|
+
<Badge color={badge.color} size={Size.SM}>{badge.text}</Badge>
|
|
174
|
+
{:else if badge.class}
|
|
175
|
+
<span
|
|
176
|
+
class="inline-flex rounded-full px-2 py-1 text-xs font-medium {badge.class}"
|
|
177
|
+
>
|
|
178
|
+
{badge.text}
|
|
179
|
+
</span>
|
|
180
|
+
{:else}
|
|
181
|
+
<Badge size={Size.SM}>{badge.text}</Badge>
|
|
182
|
+
{/if}
|
|
183
|
+
{/each}
|
|
184
|
+
{/if}
|
|
185
|
+
</div>
|
|
186
|
+
{#if activityItem.subtitle}
|
|
187
|
+
<div class={itemSubtitle()}>
|
|
188
|
+
{activityItem.subtitle}
|
|
189
|
+
</div>
|
|
190
|
+
{/if}
|
|
85
191
|
</div>
|
|
86
|
-
|
|
87
|
-
|
|
192
|
+
|
|
193
|
+
{#if activityItem.timestamp}
|
|
194
|
+
<div class={itemTimestamp()} data-activity-timestamp="">
|
|
195
|
+
{activityItem.timestamp}
|
|
196
|
+
</div>
|
|
197
|
+
{/if}
|
|
198
|
+
|
|
199
|
+
{#if activityItem.actions}
|
|
200
|
+
<div class={itemActions()}>
|
|
201
|
+
{#each activityItem.actions as action (action.label)}
|
|
202
|
+
<Button
|
|
203
|
+
size={Size.XS}
|
|
204
|
+
variant={action.variant ?? 'outline'}
|
|
205
|
+
color={action.color ?? Color.DEFAULT}
|
|
206
|
+
onclick={() => action.onClick?.()}
|
|
207
|
+
>
|
|
208
|
+
{action.label}
|
|
209
|
+
</Button>
|
|
210
|
+
{/each}
|
|
211
|
+
</div>
|
|
212
|
+
{/if}
|
|
213
|
+
</div>
|
|
214
|
+
{/if}
|
|
88
215
|
</div>
|
|
89
216
|
{/each}
|
|
90
217
|
{/if}
|
|
@@ -1,24 +1,98 @@
|
|
|
1
1
|
import type { ClassValue } from 'tailwind-variants';
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { Snippet, Component } from 'svelte';
|
|
3
3
|
import type { VariantColors } from '../../index.js';
|
|
4
4
|
export type ActivityItemBadge = {
|
|
5
5
|
text: string;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Ripple color for the badge. Renders as a `<Badge color={color}>`
|
|
8
|
+
* in ripple's design system. Preferred over `class` for new code.
|
|
9
|
+
*/
|
|
10
|
+
color?: VariantColors;
|
|
11
|
+
/**
|
|
12
|
+
* Legacy Tailwind class string for the badge (e.g. 'bg-green-100 text-green-800').
|
|
13
|
+
* Kept for backward compatibility with pre-v2.1 callers. If both `color`
|
|
14
|
+
* and `class` are provided, `color` wins.
|
|
15
|
+
*/
|
|
16
|
+
class?: string;
|
|
7
17
|
};
|
|
8
18
|
export type ActivityItemAction = {
|
|
9
19
|
label: string;
|
|
10
20
|
onClick?: () => void;
|
|
21
|
+
/** Optional ripple button color variant. @default 'default' */
|
|
22
|
+
color?: VariantColors;
|
|
23
|
+
/** Optional ripple button variant. @default 'outline' */
|
|
24
|
+
variant?: 'solid' | 'outline' | 'ghost' | 'link';
|
|
11
25
|
};
|
|
12
26
|
export type ActivityItem = {
|
|
13
27
|
title: string;
|
|
14
28
|
subtitle?: string;
|
|
15
29
|
badges?: ActivityItemBadge[];
|
|
16
30
|
actions?: ActivityItemAction[];
|
|
31
|
+
/**
|
|
32
|
+
* Optional icon component rendered on the left of the row inside a
|
|
33
|
+
* colored circle. Use any component that accepts a `class` prop (most
|
|
34
|
+
* icon libraries satisfy this). When the parent list is in
|
|
35
|
+
* `timeline` mode, the icon also acts as the "node" that the
|
|
36
|
+
* connector line passes through.
|
|
37
|
+
*/
|
|
38
|
+
icon?: Component;
|
|
39
|
+
/**
|
|
40
|
+
* Background/foreground color for the icon circle. Only has effect
|
|
41
|
+
* when `icon` is provided (or when the list is in `timeline` mode,
|
|
42
|
+
* which renders a fallback dot when no `icon` is set). Defaults to
|
|
43
|
+
* `default`.
|
|
44
|
+
*/
|
|
45
|
+
iconColor?: VariantColors;
|
|
46
|
+
/**
|
|
47
|
+
* Optional right-aligned timestamp string. Format at will —
|
|
48
|
+
* 'Jan 15', '2h ago', '15:04:23', etc. The component just renders
|
|
49
|
+
* the string with a muted text style.
|
|
50
|
+
*/
|
|
51
|
+
timestamp?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Optional left-edge accent bar color. Renders as a 3px vertical bar
|
|
54
|
+
* on the left of the row in the chosen ripple color. Good for
|
|
55
|
+
* at-a-glance status scanning down a long list.
|
|
56
|
+
*/
|
|
57
|
+
accentColor?: VariantColors;
|
|
58
|
+
/**
|
|
59
|
+
* When true, the row gets a tinted background and a slightly
|
|
60
|
+
* stronger accent to draw attention — useful for pinned, flagged,
|
|
61
|
+
* or otherwise-notable items in an otherwise-uniform list.
|
|
62
|
+
*/
|
|
63
|
+
highlighted?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* When true, the row's content area is rendered by the parent
|
|
66
|
+
* list's `customContent` snippet instead of the default
|
|
67
|
+
* title/subtitle/badges/timestamp/actions block. The icon column,
|
|
68
|
+
* accent bar, and highlighted background still apply, so the row
|
|
69
|
+
* keeps its place in the list visually. Use this to inline charts,
|
|
70
|
+
* progress bars, or any other arbitrary markup into a single row.
|
|
71
|
+
*
|
|
72
|
+
* Items can also carry their own arbitrary fields — define a
|
|
73
|
+
* sub-type that extends `ActivityItem` if you need typed access
|
|
74
|
+
* inside the snippet.
|
|
75
|
+
*/
|
|
76
|
+
custom?: boolean;
|
|
17
77
|
};
|
|
78
|
+
export type ActivityListSize = 'sm' | 'md';
|
|
18
79
|
export type ActivityListProps = {
|
|
19
80
|
title?: string;
|
|
20
81
|
items?: ActivityItem[];
|
|
21
82
|
color?: VariantColors;
|
|
83
|
+
/**
|
|
84
|
+
* Visual density. `md` (default) matches the original spacious look;
|
|
85
|
+
* `sm` tightens padding, shrinks the icon column, and is well-suited
|
|
86
|
+
* to compact panels and sidebars.
|
|
87
|
+
*/
|
|
88
|
+
size?: ActivityListSize;
|
|
89
|
+
/**
|
|
90
|
+
* When true, render items as a vertical timeline — a connector
|
|
91
|
+
* line runs through the icon column tying items together. Items
|
|
92
|
+
* without an `icon` render a fallback dot. Has no effect when
|
|
93
|
+
* using the custom `children` snippet.
|
|
94
|
+
*/
|
|
95
|
+
timeline?: boolean;
|
|
22
96
|
class?: ClassValue;
|
|
23
97
|
headerClass?: ClassValue;
|
|
24
98
|
titleClass?: ClassValue;
|
|
@@ -26,5 +100,11 @@ export type ActivityListProps = {
|
|
|
26
100
|
itemClass?: ClassValue;
|
|
27
101
|
onItemClick?: (item: ActivityItem, index: number) => void;
|
|
28
102
|
children?: Snippet;
|
|
103
|
+
/**
|
|
104
|
+
* Optional snippet used to render the content area of any item
|
|
105
|
+
* with `custom: true`. Receives `(item, index)`. Items without
|
|
106
|
+
* `custom: true` continue to use the default rendering.
|
|
107
|
+
*/
|
|
108
|
+
customContent?: Snippet<[ActivityItem, number]>;
|
|
29
109
|
testId?: string;
|
|
30
110
|
};
|
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
export declare const activityList: import("tailwind-variants").TVReturnType<{
|
|
2
|
+
size: {
|
|
3
|
+
md: {
|
|
4
|
+
header: string;
|
|
5
|
+
title: string;
|
|
6
|
+
item: string;
|
|
7
|
+
timelineLine: string;
|
|
8
|
+
iconWrapper: string;
|
|
9
|
+
iconInner: string;
|
|
10
|
+
timelineDot: string;
|
|
11
|
+
itemHeader: string;
|
|
12
|
+
itemTitle: string;
|
|
13
|
+
itemSubtitle: string;
|
|
14
|
+
itemTimestamp: string;
|
|
15
|
+
};
|
|
16
|
+
sm: {
|
|
17
|
+
header: string;
|
|
18
|
+
title: string;
|
|
19
|
+
item: string;
|
|
20
|
+
timelineLine: string;
|
|
21
|
+
iconWrapper: string;
|
|
22
|
+
iconInner: string;
|
|
23
|
+
timelineDot: string;
|
|
24
|
+
itemHeader: string;
|
|
25
|
+
itemTitle: string;
|
|
26
|
+
itemSubtitle: string;
|
|
27
|
+
itemTimestamp: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
2
30
|
color: {
|
|
3
31
|
default: {
|
|
4
32
|
base: string;
|
|
@@ -42,13 +70,47 @@ export declare const activityList: import("tailwind-variants").TVReturnType<{
|
|
|
42
70
|
title: string;
|
|
43
71
|
content: string;
|
|
44
72
|
item: string;
|
|
73
|
+
accentBar: string;
|
|
74
|
+
timelineLine: string;
|
|
75
|
+
iconWrapper: string;
|
|
76
|
+
iconInner: string;
|
|
77
|
+
timelineDot: string;
|
|
45
78
|
itemContent: string;
|
|
46
79
|
itemMain: string;
|
|
47
80
|
itemHeader: string;
|
|
48
81
|
itemTitle: string;
|
|
49
82
|
itemSubtitle: string;
|
|
83
|
+
itemTimestamp: string;
|
|
50
84
|
itemActions: string;
|
|
51
85
|
}, undefined, {
|
|
86
|
+
size: {
|
|
87
|
+
md: {
|
|
88
|
+
header: string;
|
|
89
|
+
title: string;
|
|
90
|
+
item: string;
|
|
91
|
+
timelineLine: string;
|
|
92
|
+
iconWrapper: string;
|
|
93
|
+
iconInner: string;
|
|
94
|
+
timelineDot: string;
|
|
95
|
+
itemHeader: string;
|
|
96
|
+
itemTitle: string;
|
|
97
|
+
itemSubtitle: string;
|
|
98
|
+
itemTimestamp: string;
|
|
99
|
+
};
|
|
100
|
+
sm: {
|
|
101
|
+
header: string;
|
|
102
|
+
title: string;
|
|
103
|
+
item: string;
|
|
104
|
+
timelineLine: string;
|
|
105
|
+
iconWrapper: string;
|
|
106
|
+
iconInner: string;
|
|
107
|
+
timelineDot: string;
|
|
108
|
+
itemHeader: string;
|
|
109
|
+
itemTitle: string;
|
|
110
|
+
itemSubtitle: string;
|
|
111
|
+
itemTimestamp: string;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
52
114
|
color: {
|
|
53
115
|
default: {
|
|
54
116
|
base: string;
|
|
@@ -92,13 +154,47 @@ export declare const activityList: import("tailwind-variants").TVReturnType<{
|
|
|
92
154
|
title: string;
|
|
93
155
|
content: string;
|
|
94
156
|
item: string;
|
|
157
|
+
accentBar: string;
|
|
158
|
+
timelineLine: string;
|
|
159
|
+
iconWrapper: string;
|
|
160
|
+
iconInner: string;
|
|
161
|
+
timelineDot: string;
|
|
95
162
|
itemContent: string;
|
|
96
163
|
itemMain: string;
|
|
97
164
|
itemHeader: string;
|
|
98
165
|
itemTitle: string;
|
|
99
166
|
itemSubtitle: string;
|
|
167
|
+
itemTimestamp: string;
|
|
100
168
|
itemActions: string;
|
|
101
169
|
}, import("tailwind-variants").TVReturnType<{
|
|
170
|
+
size: {
|
|
171
|
+
md: {
|
|
172
|
+
header: string;
|
|
173
|
+
title: string;
|
|
174
|
+
item: string;
|
|
175
|
+
timelineLine: string;
|
|
176
|
+
iconWrapper: string;
|
|
177
|
+
iconInner: string;
|
|
178
|
+
timelineDot: string;
|
|
179
|
+
itemHeader: string;
|
|
180
|
+
itemTitle: string;
|
|
181
|
+
itemSubtitle: string;
|
|
182
|
+
itemTimestamp: string;
|
|
183
|
+
};
|
|
184
|
+
sm: {
|
|
185
|
+
header: string;
|
|
186
|
+
title: string;
|
|
187
|
+
item: string;
|
|
188
|
+
timelineLine: string;
|
|
189
|
+
iconWrapper: string;
|
|
190
|
+
iconInner: string;
|
|
191
|
+
timelineDot: string;
|
|
192
|
+
itemHeader: string;
|
|
193
|
+
itemTitle: string;
|
|
194
|
+
itemSubtitle: string;
|
|
195
|
+
itemTimestamp: string;
|
|
196
|
+
};
|
|
197
|
+
};
|
|
102
198
|
color: {
|
|
103
199
|
default: {
|
|
104
200
|
base: string;
|
|
@@ -142,10 +238,38 @@ export declare const activityList: import("tailwind-variants").TVReturnType<{
|
|
|
142
238
|
title: string;
|
|
143
239
|
content: string;
|
|
144
240
|
item: string;
|
|
241
|
+
accentBar: string;
|
|
242
|
+
timelineLine: string;
|
|
243
|
+
iconWrapper: string;
|
|
244
|
+
iconInner: string;
|
|
245
|
+
timelineDot: string;
|
|
145
246
|
itemContent: string;
|
|
146
247
|
itemMain: string;
|
|
147
248
|
itemHeader: string;
|
|
148
249
|
itemTitle: string;
|
|
149
250
|
itemSubtitle: string;
|
|
251
|
+
itemTimestamp: string;
|
|
150
252
|
itemActions: string;
|
|
151
253
|
}, undefined, unknown, unknown, undefined>>;
|
|
254
|
+
/**
|
|
255
|
+
* Maps a ripple VariantColor to Tailwind classes for the icon circle
|
|
256
|
+
* (background + foreground text color). Used per-row, not per-list.
|
|
257
|
+
*/
|
|
258
|
+
export declare const iconCircleClasses: Record<string, string>;
|
|
259
|
+
/**
|
|
260
|
+
* Maps a ripple VariantColor to a Tailwind `bg-*` class for the
|
|
261
|
+
* left-edge accent bar.
|
|
262
|
+
*/
|
|
263
|
+
export declare const accentBarClasses: Record<string, string>;
|
|
264
|
+
/**
|
|
265
|
+
* Maps a ripple VariantColor to a tinted background for highlighted
|
|
266
|
+
* rows. Picked to sit harmoniously alongside the matching accent bar
|
|
267
|
+
* and icon circle.
|
|
268
|
+
*/
|
|
269
|
+
export declare const highlightedRowClasses: Record<string, string>;
|
|
270
|
+
/**
|
|
271
|
+
* Ring color used by the icon wrapper to mask the timeline line. Must
|
|
272
|
+
* match the row background — for highlighted rows the white default
|
|
273
|
+
* would draw a visible square, so swap it for the matching tint.
|
|
274
|
+
*/
|
|
275
|
+
export declare const highlightedRingClasses: Record<string, string>;
|
|
@@ -3,18 +3,52 @@ import { Color } from '../../variants.js';
|
|
|
3
3
|
export const activityList = tv({
|
|
4
4
|
slots: {
|
|
5
5
|
base: 'rounded-lg bg-white shadow-sm',
|
|
6
|
-
header: '
|
|
7
|
-
title: '
|
|
6
|
+
header: '',
|
|
7
|
+
title: 'font-medium text-default-900',
|
|
8
8
|
content: 'divide-y divide-default-200',
|
|
9
|
-
item: '
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
item: 'relative flex items-start hover:bg-default-50 transition-colors',
|
|
10
|
+
accentBar: 'absolute inset-y-0 left-0 w-[3px]',
|
|
11
|
+
timelineLine: 'absolute top-0 bottom-0 w-[2px] bg-default-200',
|
|
12
|
+
iconWrapper: 'relative z-10 flex shrink-0 items-center justify-center rounded-full ring-4 ring-white',
|
|
13
|
+
iconInner: '',
|
|
14
|
+
timelineDot: 'relative z-10 flex shrink-0 items-center justify-center ring-4 ring-white',
|
|
15
|
+
itemContent: 'flex flex-1 items-start justify-between gap-3',
|
|
16
|
+
itemMain: 'flex-1 min-w-0',
|
|
17
|
+
itemHeader: 'flex items-center flex-wrap',
|
|
18
|
+
itemTitle: 'font-medium text-default-900 hover:text-primary-600 focus:outline-none focus:text-primary-600 cursor-pointer text-left',
|
|
19
|
+
itemSubtitle: 'text-default-500',
|
|
20
|
+
itemTimestamp: 'text-default-400 shrink-0 whitespace-nowrap',
|
|
21
|
+
itemActions: 'flex items-center gap-2 shrink-0'
|
|
16
22
|
},
|
|
17
23
|
variants: {
|
|
24
|
+
size: {
|
|
25
|
+
md: {
|
|
26
|
+
header: 'border-b border-default-200 px-6 py-4',
|
|
27
|
+
title: 'text-lg',
|
|
28
|
+
item: 'gap-3 px-6 py-4',
|
|
29
|
+
timelineLine: 'left-[calc(1.5rem+1rem-1px)]',
|
|
30
|
+
iconWrapper: 'size-8 mt-0.5',
|
|
31
|
+
iconInner: 'size-4',
|
|
32
|
+
timelineDot: 'size-8 mt-0.5',
|
|
33
|
+
itemHeader: 'gap-2',
|
|
34
|
+
itemTitle: 'text-sm',
|
|
35
|
+
itemSubtitle: 'mt-1 text-xs',
|
|
36
|
+
itemTimestamp: 'text-xs'
|
|
37
|
+
},
|
|
38
|
+
sm: {
|
|
39
|
+
header: 'border-b border-default-200 px-4 py-2.5',
|
|
40
|
+
title: 'text-base',
|
|
41
|
+
item: 'gap-2 px-4 py-2.5',
|
|
42
|
+
timelineLine: 'left-[calc(1rem+0.75rem-1px)]',
|
|
43
|
+
iconWrapper: 'size-6 mt-0',
|
|
44
|
+
iconInner: 'size-3.5',
|
|
45
|
+
timelineDot: 'size-6 mt-0',
|
|
46
|
+
itemHeader: 'gap-1.5',
|
|
47
|
+
itemTitle: 'text-xs',
|
|
48
|
+
itemSubtitle: 'mt-0.5 text-[11px]',
|
|
49
|
+
itemTimestamp: 'text-[11px]'
|
|
50
|
+
}
|
|
51
|
+
},
|
|
18
52
|
color: {
|
|
19
53
|
[Color.DEFAULT]: {
|
|
20
54
|
base: 'bg-white border-default-200',
|
|
@@ -54,6 +88,61 @@ export const activityList = tv({
|
|
|
54
88
|
}
|
|
55
89
|
},
|
|
56
90
|
defaultVariants: {
|
|
91
|
+
size: 'md',
|
|
57
92
|
color: Color.DEFAULT
|
|
58
93
|
}
|
|
59
94
|
});
|
|
95
|
+
/**
|
|
96
|
+
* Maps a ripple VariantColor to Tailwind classes for the icon circle
|
|
97
|
+
* (background + foreground text color). Used per-row, not per-list.
|
|
98
|
+
*/
|
|
99
|
+
export const iconCircleClasses = {
|
|
100
|
+
default: 'bg-default-100 text-default-600',
|
|
101
|
+
primary: 'bg-primary-100 text-primary-600',
|
|
102
|
+
secondary: 'bg-secondary-100 text-secondary-600',
|
|
103
|
+
info: 'bg-info-100 text-info-600',
|
|
104
|
+
success: 'bg-success-100 text-success-700',
|
|
105
|
+
warning: 'bg-warning-100 text-warning-700',
|
|
106
|
+
danger: 'bg-danger-100 text-danger-700'
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Maps a ripple VariantColor to a Tailwind `bg-*` class for the
|
|
110
|
+
* left-edge accent bar.
|
|
111
|
+
*/
|
|
112
|
+
export const accentBarClasses = {
|
|
113
|
+
default: 'bg-default-300',
|
|
114
|
+
primary: 'bg-primary-500',
|
|
115
|
+
secondary: 'bg-secondary-500',
|
|
116
|
+
info: 'bg-info-500',
|
|
117
|
+
success: 'bg-success-500',
|
|
118
|
+
warning: 'bg-warning-500',
|
|
119
|
+
danger: 'bg-danger-500'
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Maps a ripple VariantColor to a tinted background for highlighted
|
|
123
|
+
* rows. Picked to sit harmoniously alongside the matching accent bar
|
|
124
|
+
* and icon circle.
|
|
125
|
+
*/
|
|
126
|
+
export const highlightedRowClasses = {
|
|
127
|
+
default: 'bg-default-50 hover:bg-default-100',
|
|
128
|
+
primary: 'bg-primary-50 hover:bg-primary-100',
|
|
129
|
+
secondary: 'bg-secondary-50 hover:bg-secondary-100',
|
|
130
|
+
info: 'bg-info-50 hover:bg-info-100',
|
|
131
|
+
success: 'bg-success-50 hover:bg-success-100',
|
|
132
|
+
warning: 'bg-warning-50 hover:bg-warning-100',
|
|
133
|
+
danger: 'bg-danger-50 hover:bg-danger-100'
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Ring color used by the icon wrapper to mask the timeline line. Must
|
|
137
|
+
* match the row background — for highlighted rows the white default
|
|
138
|
+
* would draw a visible square, so swap it for the matching tint.
|
|
139
|
+
*/
|
|
140
|
+
export const highlightedRingClasses = {
|
|
141
|
+
default: 'ring-default-50',
|
|
142
|
+
primary: 'ring-primary-50',
|
|
143
|
+
secondary: 'ring-secondary-50',
|
|
144
|
+
info: 'ring-info-50',
|
|
145
|
+
success: 'ring-success-50',
|
|
146
|
+
warning: 'ring-warning-50',
|
|
147
|
+
danger: 'ring-danger-50'
|
|
148
|
+
};
|
package/package.json
CHANGED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { cn } from '../../helper/cls.js';
|
|
3
|
-
import type { TimelineItem } from '../../index.js';
|
|
4
|
-
import { formatDateTime, getRelativeTime } from '../../helper/date.js';
|
|
5
|
-
import { resolve } from '$app/paths';
|
|
6
|
-
|
|
7
|
-
let { items = [] as TimelineItem[], class: className = '' } = $props();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<div class={cn('flow-root', className)}>
|
|
11
|
-
<ul role="list" class="-mb-8">
|
|
12
|
-
{#each items as item, index (item.title + index)}
|
|
13
|
-
<li>
|
|
14
|
-
<div class="relative pb-8">
|
|
15
|
-
{#if index !== items.length - 1}
|
|
16
|
-
<span class="bg-default-200 absolute top-4 left-4 -ml-px h-full w-1" aria-hidden="true"
|
|
17
|
-
></span>
|
|
18
|
-
{/if}
|
|
19
|
-
|
|
20
|
-
{@render ItemWrap({ item })}
|
|
21
|
-
</div>
|
|
22
|
-
</li>
|
|
23
|
-
{/each}
|
|
24
|
-
</ul>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
{#snippet ItemWrap({ item }: { item: TimelineItem })}
|
|
28
|
-
<div class="relative flex gap-x-3" class:items-center={!item.details}>
|
|
29
|
-
<div class="relative ml-0.5 flex-shrink-0">
|
|
30
|
-
{@render TimelineIcon(item)}
|
|
31
|
-
</div>
|
|
32
|
-
{#if item.details}
|
|
33
|
-
{@render CommentItem({ item })}
|
|
34
|
-
{:else}
|
|
35
|
-
{@render StandardItem({ item })}
|
|
36
|
-
{/if}
|
|
37
|
-
</div>
|
|
38
|
-
{/snippet}
|
|
39
|
-
|
|
40
|
-
{#snippet StandardItem({ item }: { item: TimelineItem })}
|
|
41
|
-
<div class="min-w-0 flex-1">
|
|
42
|
-
<div class="flex items-center justify-between">
|
|
43
|
-
<p class="text-default-500 text-sm">
|
|
44
|
-
{item.title}
|
|
45
|
-
{#if item.link}
|
|
46
|
-
<a href={resolve(item.link.url as `/`)} class="text-default-900 font-medium"
|
|
47
|
-
>{item.link.text}</a
|
|
48
|
-
>
|
|
49
|
-
{/if}
|
|
50
|
-
</p>
|
|
51
|
-
{@render TimeStamp(item.time)}
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
{/snippet}
|
|
55
|
-
|
|
56
|
-
{#snippet CommentItem({ item }: { item: TimelineItem })}
|
|
57
|
-
<div class="ring-default-200 w-full flex-grow rounded-md bg-white p-3 ring-1">
|
|
58
|
-
<div class="mb-1 flex justify-between gap-x-4">
|
|
59
|
-
<div class="text-default-900 text-sm font-medium">{item.title}</div>
|
|
60
|
-
{@render TimeStamp(item.time)}
|
|
61
|
-
</div>
|
|
62
|
-
<p class="text-default-500 text-sm">{item.details}</p>
|
|
63
|
-
</div>
|
|
64
|
-
{/snippet}
|
|
65
|
-
|
|
66
|
-
{#snippet TimeStamp(time: Date | string)}
|
|
67
|
-
<time
|
|
68
|
-
datetime={time instanceof Date ? time.toISOString() : time}
|
|
69
|
-
class="text-default-500 text-right text-sm whitespace-nowrap"
|
|
70
|
-
title={formatDateTime(time)}
|
|
71
|
-
>
|
|
72
|
-
{getRelativeTime(time)}
|
|
73
|
-
</time>
|
|
74
|
-
{/snippet}
|
|
75
|
-
|
|
76
|
-
{#snippet TimelineIcon(item: TimelineItem, classes = 'size-7 shrink-0')}
|
|
77
|
-
{#if item.Icon}
|
|
78
|
-
{@const Icon = item.Icon}
|
|
79
|
-
<Icon class={classes} />
|
|
80
|
-
{:else}
|
|
81
|
-
<svg
|
|
82
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
83
|
-
width="16"
|
|
84
|
-
height="16"
|
|
85
|
-
viewBox="0 0 16 16"
|
|
86
|
-
class={classes}
|
|
87
|
-
>
|
|
88
|
-
<circle cx="8" cy="8" r="7" fill="white" />
|
|
89
|
-
<path
|
|
90
|
-
fill="currentColor"
|
|
91
|
-
d="M1 8a7 7 0 1 1 14 0A7 7 0 0 1 1 8m9.854-1.146a.5.5 0 0 0-.708-.708L7.25 9.043L5.854 7.646a.5.5 0 1 0-.708.708l1.75 1.75a.5.5 0 0 0 .708 0z"
|
|
92
|
-
/>
|
|
93
|
-
</svg>
|
|
94
|
-
{/if}
|
|
95
|
-
{/snippet}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|