@signal9/era-ui 34.12.2 → 34.13.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/CHANGELOG.md +6 -0
- package/dist/ui/timeline/context.svelte.d.ts +6 -0
- package/dist/ui/timeline/context.svelte.js +12 -0
- package/dist/ui/timeline/timeline-step.svelte +153 -25
- package/dist/ui/timeline/timeline-step.svelte.d.ts +2 -0
- package/dist/ui/timeline/timeline.svelte +73 -24
- package/dist/ui/timeline/timeline.svelte.d.ts +11 -2
- package/package.json +1 -1
- package/skills/era-ui/references/releases/34.md +6 -0
- package/skills/era-ui/references/releases/index.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [34.13.0](https://github.com/sig-nine/era-ui/compare/v34.12.2...v34.13.0) (2026-08-31)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **timeline:** add activity inspection ([e43d313](https://github.com/sig-nine/era-ui/commit/e43d313577473f854c1b39ea7eda5ecafd0ff3db))
|
|
6
|
+
|
|
1
7
|
## [34.12.2](https://github.com/sig-nine/era-ui/compare/v34.12.1...v34.12.2) (2026-08-31)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -53,6 +53,10 @@ export declare class TimelineData {
|
|
|
53
53
|
activityLayout: ActivityTimelineLayout;
|
|
54
54
|
selectedId: TimelineStepId | null;
|
|
55
55
|
onselect: ((step: ActivityTimelineStep) => void) | undefined;
|
|
56
|
+
expandedId: TimelineStepId | null;
|
|
57
|
+
hasActivityDetails: boolean;
|
|
58
|
+
onexpandedchange: ((id: TimelineStepId | null) => void) | undefined;
|
|
59
|
+
instanceId: string;
|
|
56
60
|
/** Live clock, ticked by the root while any step is running. */
|
|
57
61
|
now: number;
|
|
58
62
|
/**
|
|
@@ -68,6 +72,8 @@ export declare class TimelineData {
|
|
|
68
72
|
elapsed(step: AnyTimelineStep): number;
|
|
69
73
|
get total(): number;
|
|
70
74
|
get running(): boolean;
|
|
75
|
+
detailsId(): string;
|
|
76
|
+
toggleExpanded(step: ActivityTimelineStep): void;
|
|
71
77
|
/**
|
|
72
78
|
* This step's GROW FACTOR — its duration, straight.
|
|
73
79
|
*
|
|
@@ -31,6 +31,10 @@ export class TimelineData {
|
|
|
31
31
|
activityLayout = $state('scroll');
|
|
32
32
|
selectedId = $state(null);
|
|
33
33
|
onselect = $state();
|
|
34
|
+
expandedId = $state(null);
|
|
35
|
+
hasActivityDetails = $state(false);
|
|
36
|
+
onexpandedchange = $state();
|
|
37
|
+
instanceId = $state('');
|
|
34
38
|
/** Live clock, ticked by the root while any step is running. */
|
|
35
39
|
now = $state(0);
|
|
36
40
|
/**
|
|
@@ -55,6 +59,14 @@ export class TimelineData {
|
|
|
55
59
|
get running() {
|
|
56
60
|
return this.steps.some((s) => s.state === 'running');
|
|
57
61
|
}
|
|
62
|
+
detailsId() {
|
|
63
|
+
return `${this.instanceId}-activity-details`;
|
|
64
|
+
}
|
|
65
|
+
toggleExpanded(step) {
|
|
66
|
+
if (!this.hasActivityDetails)
|
|
67
|
+
return;
|
|
68
|
+
this.onexpandedchange?.(this.expandedId === step.id ? null : step.id);
|
|
69
|
+
}
|
|
58
70
|
/**
|
|
59
71
|
* This step's GROW FACTOR — its duration, straight.
|
|
60
72
|
*
|
|
@@ -47,7 +47,9 @@
|
|
|
47
47
|
import CircleSlash from '@lucide/svelte/icons/circle-slash';
|
|
48
48
|
import CircleX from '@lucide/svelte/icons/circle-x';
|
|
49
49
|
import LoaderCircle from '@lucide/svelte/icons/loader-circle';
|
|
50
|
+
import { mergeProps } from 'bits-ui';
|
|
50
51
|
import { cn } from '../../utils/index.js';
|
|
52
|
+
import * as Tooltip from '../tooltip/index.js';
|
|
51
53
|
import {
|
|
52
54
|
getTimelineData,
|
|
53
55
|
formatDuration,
|
|
@@ -60,11 +62,15 @@
|
|
|
60
62
|
step,
|
|
61
63
|
showClock = true,
|
|
62
64
|
activityCompletedIcon,
|
|
65
|
+
activityIcon,
|
|
66
|
+
activityTooltip,
|
|
63
67
|
class: className
|
|
64
68
|
}: {
|
|
65
69
|
step: AnyTimelineStep;
|
|
66
70
|
showClock?: boolean;
|
|
67
71
|
activityCompletedIcon?: Snippet<[ActivityTimelineStep]>;
|
|
72
|
+
activityIcon?: Snippet<[ActivityTimelineStep]>;
|
|
73
|
+
activityTooltip?: Snippet<[ActivityTimelineStep]>;
|
|
68
74
|
class?: string;
|
|
69
75
|
} = $props();
|
|
70
76
|
|
|
@@ -78,10 +84,49 @@
|
|
|
78
84
|
const activityTone = $derived(ACTIVITY_TONE[activityStep.state]);
|
|
79
85
|
const stateLabel = $derived(ACTIVITY_STATE_LABEL[activityStep.state]);
|
|
80
86
|
const selected = $derived(data?.selectedId === step.id);
|
|
81
|
-
const
|
|
87
|
+
const expanded = $derived(data?.expandedId === step.id);
|
|
88
|
+
const interactive = $derived(
|
|
89
|
+
data?.variant === 'activity' && (!!data.onselect || data.hasActivityDetails)
|
|
90
|
+
);
|
|
82
91
|
const durationActivity = $derived(
|
|
83
92
|
data?.variant === 'activity' && data.activityLayout === 'duration'
|
|
84
93
|
);
|
|
94
|
+
|
|
95
|
+
function activateActivity() {
|
|
96
|
+
data?.onselect?.(activityStep);
|
|
97
|
+
data?.toggleExpanded(activityStep);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function handleActivityKeydown(event: KeyboardEvent) {
|
|
101
|
+
if (!data) return;
|
|
102
|
+
if (event.key === 'Escape' && expanded && data.hasActivityDetails) {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
data.onexpandedchange?.(null);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const destinations = ['ArrowLeft', 'ArrowRight', 'Home', 'End'];
|
|
108
|
+
if (!destinations.includes(event.key)) return;
|
|
109
|
+
const list = (event.currentTarget as HTMLElement).closest('[role="list"]');
|
|
110
|
+
const controls = list
|
|
111
|
+
? [...list.querySelectorAll<HTMLElement>('[data-timeline-activity-control]')]
|
|
112
|
+
: [];
|
|
113
|
+
const current = controls.indexOf(event.currentTarget as HTMLElement);
|
|
114
|
+
if (current < 0 || controls.length === 0) return;
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
const target =
|
|
117
|
+
event.key === 'Home'
|
|
118
|
+
? 0
|
|
119
|
+
: event.key === 'End'
|
|
120
|
+
? controls.length - 1
|
|
121
|
+
: event.key === 'ArrowLeft'
|
|
122
|
+
? Math.max(0, current - 1)
|
|
123
|
+
: Math.min(controls.length - 1, current + 1);
|
|
124
|
+
controls[target]?.focus();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function handleActivityFocus(event: FocusEvent) {
|
|
128
|
+
(event.currentTarget as HTMLElement).scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
129
|
+
}
|
|
85
130
|
</script>
|
|
86
131
|
|
|
87
132
|
<!--
|
|
@@ -109,7 +154,36 @@
|
|
|
109
154
|
-->
|
|
110
155
|
{#if data?.variant === 'activity'}
|
|
111
156
|
{#snippet activityContent()}
|
|
112
|
-
{#if
|
|
157
|
+
{#if activityIcon}
|
|
158
|
+
<span
|
|
159
|
+
class="flex size-icon shrink-0 items-center justify-center {activityTone.icon}"
|
|
160
|
+
data-timeline-activity-identity
|
|
161
|
+
aria-hidden="true"
|
|
162
|
+
>
|
|
163
|
+
{@render activityIcon(activityStep)}
|
|
164
|
+
<span
|
|
165
|
+
class="flex items-center justify-center rounded-full bg-elevated {activityTone.icon}"
|
|
166
|
+
data-timeline-activity-indicator
|
|
167
|
+
>
|
|
168
|
+
{#if activityStep.state === 'running'}
|
|
169
|
+
<LoaderCircle
|
|
170
|
+
class="motion-safe:animate-spin"
|
|
171
|
+
style="animation-duration: calc(var(--era-duration) * 8)"
|
|
172
|
+
/>
|
|
173
|
+
{:else if activityStep.state === 'awaiting'}
|
|
174
|
+
<CircleAlert />
|
|
175
|
+
{:else if activityStep.state === 'done'}
|
|
176
|
+
<CircleCheck />
|
|
177
|
+
{:else if activityStep.state === 'failed'}
|
|
178
|
+
<CircleX />
|
|
179
|
+
{:else if activityStep.state === 'cancelled'}
|
|
180
|
+
<CircleSlash />
|
|
181
|
+
{:else}
|
|
182
|
+
<Circle />
|
|
183
|
+
{/if}
|
|
184
|
+
</span>
|
|
185
|
+
</span>
|
|
186
|
+
{:else if activityStep.state === 'running'}
|
|
113
187
|
<LoaderCircle
|
|
114
188
|
class="size-icon shrink-0 {activityTone.icon} [animation-duration:calc(var(--era-duration)*8)] motion-safe:animate-spin"
|
|
115
189
|
aria-hidden="true"
|
|
@@ -176,29 +250,61 @@
|
|
|
176
250
|
data-timeline-activity-density={durationActivity ? data.density : undefined}
|
|
177
251
|
data-timeline-step-id={step.id}
|
|
178
252
|
>
|
|
179
|
-
{
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
253
|
+
<Tooltip.Provider delayDuration={250}>
|
|
254
|
+
<Tooltip.Root>
|
|
255
|
+
<Tooltip.Trigger>
|
|
256
|
+
{#snippet child({ props })}
|
|
257
|
+
{#if interactive}
|
|
258
|
+
{@const triggerProps = mergeProps(props, {
|
|
259
|
+
onclick: activateActivity,
|
|
260
|
+
onkeydown: handleActivityKeydown,
|
|
261
|
+
onfocus: handleActivityFocus
|
|
262
|
+
})}
|
|
263
|
+
<button
|
|
264
|
+
{...triggerProps}
|
|
265
|
+
type="button"
|
|
266
|
+
aria-current={selected ? 'step' : undefined}
|
|
267
|
+
aria-label={`${step.label}: ${stateLabel}`}
|
|
268
|
+
aria-expanded={data.hasActivityDetails ? expanded : undefined}
|
|
269
|
+
aria-controls={data.hasActivityDetails ? data.detailsId() : undefined}
|
|
270
|
+
class={activityClass}
|
|
271
|
+
data-state={activityStep.state}
|
|
272
|
+
data-selected={selected ? '' : undefined}
|
|
273
|
+
data-expanded={expanded ? '' : undefined}
|
|
274
|
+
data-layout={data.activityLayout}
|
|
275
|
+
data-timeline-activity-control
|
|
276
|
+
>
|
|
277
|
+
{@render activityContent()}
|
|
278
|
+
</button>
|
|
279
|
+
{:else}
|
|
280
|
+
<div
|
|
281
|
+
{...props}
|
|
282
|
+
aria-label={`${step.label}: ${stateLabel}`}
|
|
283
|
+
class={activityClass}
|
|
284
|
+
data-state={activityStep.state}
|
|
285
|
+
data-selected={selected ? '' : undefined}
|
|
286
|
+
data-expanded={expanded ? '' : undefined}
|
|
287
|
+
data-layout={data.activityLayout}
|
|
288
|
+
data-timeline-activity-control
|
|
289
|
+
>
|
|
290
|
+
{@render activityContent()}
|
|
291
|
+
</div>
|
|
292
|
+
{/if}
|
|
293
|
+
{/snippet}
|
|
294
|
+
</Tooltip.Trigger>
|
|
295
|
+
<Tooltip.Content
|
|
296
|
+
role="tooltip"
|
|
297
|
+
class="h-auto max-w-prose flex-col items-start py-inset-pill whitespace-normal"
|
|
298
|
+
>
|
|
299
|
+
{#if activityTooltip}
|
|
300
|
+
{@render activityTooltip(activityStep)}
|
|
301
|
+
{:else}
|
|
302
|
+
<span class="text-fg">{step.label}</span>
|
|
303
|
+
<span class="font-mono text-micro text-muted tabular-nums">{activityTitle}</span>
|
|
304
|
+
{/if}
|
|
305
|
+
</Tooltip.Content>
|
|
306
|
+
</Tooltip.Root>
|
|
307
|
+
</Tooltip.Provider>
|
|
202
308
|
</div>
|
|
203
309
|
{:else}
|
|
204
310
|
<div
|
|
@@ -250,6 +356,28 @@
|
|
|
250
356
|
container-type: inline-size;
|
|
251
357
|
}
|
|
252
358
|
|
|
359
|
+
[data-timeline-activity-identity] {
|
|
360
|
+
position: relative;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
[data-timeline-activity-identity] > :not([data-timeline-activity-indicator]) {
|
|
364
|
+
width: 100%;
|
|
365
|
+
height: 100%;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
[data-timeline-activity-indicator] {
|
|
369
|
+
position: absolute;
|
|
370
|
+
right: calc(var(--era-sp) / -8);
|
|
371
|
+
bottom: calc(var(--era-sp) / -8);
|
|
372
|
+
width: var(--era-sp);
|
|
373
|
+
height: var(--era-sp);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
[data-timeline-activity-indicator] > :global(svg) {
|
|
377
|
+
width: 100%;
|
|
378
|
+
height: 100%;
|
|
379
|
+
}
|
|
380
|
+
|
|
253
381
|
/* Once a segment has less than one control tier plus roughly three glyphs,
|
|
254
382
|
fragments stop communicating useful information. Collapse the whole text
|
|
255
383
|
treatment at once and preserve a concentric, state-bearing icon control. */
|
|
@@ -6,6 +6,8 @@ type $$ComponentProps = {
|
|
|
6
6
|
step: AnyTimelineStep;
|
|
7
7
|
showClock?: boolean;
|
|
8
8
|
activityCompletedIcon?: Snippet<[ActivityTimelineStep]>;
|
|
9
|
+
activityIcon?: Snippet<[ActivityTimelineStep]>;
|
|
10
|
+
activityTooltip?: Snippet<[ActivityTimelineStep]>;
|
|
9
11
|
class?: string;
|
|
10
12
|
};
|
|
11
13
|
declare const TimelineStep: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -23,10 +23,15 @@
|
|
|
23
23
|
ariaLabel = 'Build timeline',
|
|
24
24
|
selectedId = null,
|
|
25
25
|
onselect,
|
|
26
|
+
expandedId = $bindable(null),
|
|
27
|
+
onexpandedchange,
|
|
26
28
|
reveal,
|
|
27
29
|
tick = 100,
|
|
28
30
|
showClock = true,
|
|
29
31
|
activityCompletedIcon,
|
|
32
|
+
activityIcon,
|
|
33
|
+
activityDetails,
|
|
34
|
+
activityTooltip,
|
|
30
35
|
children,
|
|
31
36
|
class: className
|
|
32
37
|
}: {
|
|
@@ -43,19 +48,33 @@
|
|
|
43
48
|
selectedId?: TimelineStepId | null;
|
|
44
49
|
/** Supplying this callback turns activity steps into native buttons. */
|
|
45
50
|
onselect?: (step: ActivityTimelineStep) => void;
|
|
51
|
+
/** Controlled expanded activity. Bind it or update it from `onexpandedchange`. */
|
|
52
|
+
expandedId?: TimelineStepId | null;
|
|
53
|
+
onexpandedchange?: (id: TimelineStepId | null) => void;
|
|
46
54
|
/** Opt-in horizontal reveal target. `latest` follows appends; `running` follows the first active step. */
|
|
47
55
|
reveal?: TimelineStepId | 'latest' | 'running';
|
|
48
56
|
/** Live counter interval in ms. 0 stops the clock (the counter freezes). */
|
|
49
57
|
tick?: number;
|
|
50
58
|
showClock?: boolean;
|
|
51
59
|
/** Consumer-rendered identity for completed activity steps. Other states keep
|
|
52
|
-
* Era's lifecycle glyphs
|
|
60
|
+
* Era's lifecycle glyphs. Ignored when the general `activityIcon` is supplied. */
|
|
53
61
|
activityCompletedIcon?: Snippet<[ActivityTimelineStep]>;
|
|
62
|
+
/** Persistent consumer identity rendered throughout every activity lifecycle state. */
|
|
63
|
+
activityIcon?: Snippet<[ActivityTimelineStep]>;
|
|
64
|
+
/** Detail content rendered in Era's controlled disclosure panel. */
|
|
65
|
+
activityDetails?: Snippet<[ActivityTimelineStep]>;
|
|
66
|
+
/** Optional replacement for Era's label, state, duration, and description tooltip. */
|
|
67
|
+
activityTooltip?: Snippet<[ActivityTimelineStep]>;
|
|
54
68
|
children?: Snippet;
|
|
55
69
|
class?: string;
|
|
56
70
|
} = $props();
|
|
71
|
+
const instanceId = $props.id();
|
|
57
72
|
|
|
58
73
|
const data = setTimelineData(new TimelineData());
|
|
74
|
+
function requestExpanded(id: TimelineStepId | null) {
|
|
75
|
+
expandedId = id;
|
|
76
|
+
onexpandedchange?.(id);
|
|
77
|
+
}
|
|
59
78
|
$effect(() => {
|
|
60
79
|
data.steps = steps;
|
|
61
80
|
data.variant = variant;
|
|
@@ -63,7 +82,16 @@
|
|
|
63
82
|
data.density = density;
|
|
64
83
|
data.selectedId = selectedId;
|
|
65
84
|
data.onselect = onselect;
|
|
85
|
+
data.expandedId = expandedId;
|
|
86
|
+
data.hasActivityDetails = !!activityDetails;
|
|
87
|
+
data.onexpandedchange = requestExpanded;
|
|
88
|
+
data.instanceId = instanceId;
|
|
66
89
|
});
|
|
90
|
+
const expandedStep = $derived(
|
|
91
|
+
variant === 'activity' && activityDetails
|
|
92
|
+
? (steps.find((step) => step.id === expandedId) as ActivityTimelineStep | undefined)
|
|
93
|
+
: undefined
|
|
94
|
+
);
|
|
67
95
|
|
|
68
96
|
let lastRevealed = '';
|
|
69
97
|
$effect(() => {
|
|
@@ -126,6 +154,32 @@
|
|
|
126
154
|
});
|
|
127
155
|
</script>
|
|
128
156
|
|
|
157
|
+
{#snippet timelineList()}
|
|
158
|
+
<div
|
|
159
|
+
bind:this={ref}
|
|
160
|
+
role="list"
|
|
161
|
+
aria-label={ariaLabel}
|
|
162
|
+
aria-live={variant === 'activity' ? 'polite' : undefined}
|
|
163
|
+
class={cn(
|
|
164
|
+
'flex w-full min-w-0 gap-gutter',
|
|
165
|
+
variant === 'activity'
|
|
166
|
+
? activityLayout === 'duration'
|
|
167
|
+
? 'max-w-full items-center overflow-x-clip overflow-y-visible'
|
|
168
|
+
: 'scrollbar-none max-w-full items-center overflow-x-auto overscroll-x-contain'
|
|
169
|
+
: 'items-start',
|
|
170
|
+
className
|
|
171
|
+
)}
|
|
172
|
+
>
|
|
173
|
+
{#if children}
|
|
174
|
+
{@render children()}
|
|
175
|
+
{:else}
|
|
176
|
+
{#each data.steps as step, i (step.id ?? i)}
|
|
177
|
+
<Step {activityCompletedIcon} {activityIcon} {activityTooltip} {step} {showClock} />
|
|
178
|
+
{/each}
|
|
179
|
+
{/if}
|
|
180
|
+
</div>
|
|
181
|
+
{/snippet}
|
|
182
|
+
|
|
129
183
|
<!--
|
|
130
184
|
A build timeline: one full-width bar cut into a segment per step, where a
|
|
131
185
|
segment's WIDTH is how long that step took. You read "installing took three
|
|
@@ -138,26 +192,21 @@
|
|
|
138
192
|
carries its own sr-only summary because the visual encoding — width — is
|
|
139
193
|
exactly the part that does not survive being read aloud.
|
|
140
194
|
-->
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
>
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
{#each data.steps as step, i (step.id ?? i)}
|
|
160
|
-
<Step {activityCompletedIcon} {step} {showClock} />
|
|
161
|
-
{/each}
|
|
162
|
-
{/if}
|
|
163
|
-
</div>
|
|
195
|
+
{#if variant === 'activity' && activityDetails}
|
|
196
|
+
<div class="w-full min-w-0">
|
|
197
|
+
{@render timelineList()}
|
|
198
|
+
{#if expandedStep}
|
|
199
|
+
<div
|
|
200
|
+
id={data.detailsId()}
|
|
201
|
+
role="region"
|
|
202
|
+
aria-label={`${expandedStep.label} details`}
|
|
203
|
+
class="mt-gutter w-full min-w-0 overflow-hidden border border-divider bg-well p-card text-body text-fg"
|
|
204
|
+
data-timeline-activity-details={expandedStep.id}
|
|
205
|
+
>
|
|
206
|
+
{@render activityDetails(expandedStep)}
|
|
207
|
+
</div>
|
|
208
|
+
{/if}
|
|
209
|
+
</div>
|
|
210
|
+
{:else}
|
|
211
|
+
{@render timelineList()}
|
|
212
|
+
{/if}
|
|
@@ -14,17 +14,26 @@ type $$ComponentProps = {
|
|
|
14
14
|
selectedId?: TimelineStepId | null;
|
|
15
15
|
/** Supplying this callback turns activity steps into native buttons. */
|
|
16
16
|
onselect?: (step: ActivityTimelineStep) => void;
|
|
17
|
+
/** Controlled expanded activity. Bind it or update it from `onexpandedchange`. */
|
|
18
|
+
expandedId?: TimelineStepId | null;
|
|
19
|
+
onexpandedchange?: (id: TimelineStepId | null) => void;
|
|
17
20
|
/** Opt-in horizontal reveal target. `latest` follows appends; `running` follows the first active step. */
|
|
18
21
|
reveal?: TimelineStepId | 'latest' | 'running';
|
|
19
22
|
/** Live counter interval in ms. 0 stops the clock (the counter freezes). */
|
|
20
23
|
tick?: number;
|
|
21
24
|
showClock?: boolean;
|
|
22
25
|
/** Consumer-rendered identity for completed activity steps. Other states keep
|
|
23
|
-
* Era's lifecycle glyphs
|
|
26
|
+
* Era's lifecycle glyphs. Ignored when the general `activityIcon` is supplied. */
|
|
24
27
|
activityCompletedIcon?: Snippet<[ActivityTimelineStep]>;
|
|
28
|
+
/** Persistent consumer identity rendered throughout every activity lifecycle state. */
|
|
29
|
+
activityIcon?: Snippet<[ActivityTimelineStep]>;
|
|
30
|
+
/** Detail content rendered in Era's controlled disclosure panel. */
|
|
31
|
+
activityDetails?: Snippet<[ActivityTimelineStep]>;
|
|
32
|
+
/** Optional replacement for Era's label, state, duration, and description tooltip. */
|
|
33
|
+
activityTooltip?: Snippet<[ActivityTimelineStep]>;
|
|
25
34
|
children?: Snippet;
|
|
26
35
|
class?: string;
|
|
27
36
|
};
|
|
28
|
-
declare const Timeline: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
37
|
+
declare const Timeline: import("svelte").Component<$$ComponentProps, {}, "ref" | "expandedId">;
|
|
29
38
|
type Timeline = ReturnType<typeof Timeline>;
|
|
30
39
|
export default Timeline;
|
package/package.json
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Era UI v34 release history
|
|
2
2
|
|
|
3
|
+
## [34.13.0](https://github.com/sig-nine/era-ui/compare/v34.12.2...v34.13.0) (2026-08-31)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **timeline:** add activity inspection ([e43d313](https://github.com/sig-nine/era-ui/commit/e43d313577473f854c1b39ea7eda5ecafd0ff3db))
|
|
8
|
+
|
|
3
9
|
## [34.12.2](https://github.com/sig-nine/era-ui/compare/v34.12.1...v34.12.2) (2026-08-31)
|
|
4
10
|
|
|
5
11
|
### Bug Fixes
|
|
@@ -5,7 +5,7 @@ Load only the major versions crossed by an upgrade; use the package-root `CHANGE
|
|
|
5
5
|
|
|
6
6
|
| Major | Range | Releases | History |
|
|
7
7
|
| ---: | --- | ---: | --- |
|
|
8
|
-
| 34 | 34.0.0–34.
|
|
8
|
+
| 34 | 34.0.0–34.13.0 | 41 | [Read](./34.md) |
|
|
9
9
|
| 33 | 33.0.0–33.0.1 | 2 | [Read](./33.md) |
|
|
10
10
|
| 32 | 32.0.0–32.0.1 | 2 | [Read](./32.md) |
|
|
11
11
|
| 31 | 31.0.0–31.0.0 | 1 | [Read](./31.md) |
|