@marianmeres/stuic 3.169.0 → 3.170.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/AGENTS.md +2 -2
- package/dist/components/Input/FieldOptions.svelte +1 -56
- package/dist/components/Input/README.md +78 -0
- package/dist/components/Input/field-options-i18n-sk.d.ts +21 -0
- package/dist/components/Input/field-options-i18n-sk.js +61 -0
- package/dist/components/Input/field-options-i18n.d.ts +82 -0
- package/dist/components/Input/field-options-i18n.js +90 -0
- package/dist/components/Input/index.d.ts +2 -0
- package/dist/components/Input/index.js +2 -0
- package/dist/components/Timeline/README.md +204 -0
- package/dist/components/Timeline/Timeline.svelte +246 -0
- package/dist/components/Timeline/Timeline.svelte.d.ts +87 -0
- package/dist/components/Timeline/index.css +311 -0
- package/dist/components/Timeline/index.d.ts +1 -0
- package/dist/components/Timeline/index.js +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/docs/domains/components.md +39 -1
- package/docs/maybe-todo.md +5 -2
- package/package.json +1 -1
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
TIMELINE COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-timeline-marker-size: 1rem; }
|
|
4
|
+
Override locally: <Timeline style="--stuic-timeline-gap-vertical: 1rem;">
|
|
5
|
+
============================================================================ */
|
|
6
|
+
|
|
7
|
+
/* prettier-ignore */
|
|
8
|
+
:root {
|
|
9
|
+
/* Layout */
|
|
10
|
+
--stuic-timeline-gap: 1rem; /* column gap: opposite ↔ rail ↔ content */
|
|
11
|
+
--stuic-timeline-gap-vertical: 1.5rem; /* distance between items */
|
|
12
|
+
--stuic-timeline-line-height: 1.5rem; /* first-line box the marker centers on */
|
|
13
|
+
|
|
14
|
+
/* Connector (the vertical rail line) */
|
|
15
|
+
--stuic-timeline-connector-thickness: 2px;
|
|
16
|
+
--stuic-timeline-connector-bg: var(--stuic-color-border);
|
|
17
|
+
|
|
18
|
+
/* Marker: dot (no icon) */
|
|
19
|
+
--stuic-timeline-marker-size: 0.75rem;
|
|
20
|
+
--stuic-timeline-marker-bg: var(--stuic-color-muted-foreground);
|
|
21
|
+
|
|
22
|
+
/* Marker: icon bubble (item.icon) and custom (renderMarker) */
|
|
23
|
+
--stuic-timeline-marker-size-icon: 2rem;
|
|
24
|
+
--stuic-timeline-marker-bg-icon: var(--stuic-color-muted);
|
|
25
|
+
--stuic-timeline-marker-text-icon: var(--stuic-color-muted-foreground);
|
|
26
|
+
--stuic-timeline-marker-icon-size: 1rem; /* svg inside the bubble */
|
|
27
|
+
|
|
28
|
+
/* Marker ring: separates the marker from the line running behind it */
|
|
29
|
+
--stuic-timeline-marker-ring-width: 2px;
|
|
30
|
+
--stuic-timeline-marker-ring-color: var(--stuic-color-background);
|
|
31
|
+
|
|
32
|
+
/* Time */
|
|
33
|
+
--stuic-timeline-time-font-size: var(--text-sm);
|
|
34
|
+
--stuic-timeline-time-text: var(--stuic-color-muted-foreground);
|
|
35
|
+
|
|
36
|
+
/* Title */
|
|
37
|
+
--stuic-timeline-title-font-size: var(--text-base);
|
|
38
|
+
--stuic-timeline-title-font-weight: var(--font-weight-medium);
|
|
39
|
+
--stuic-timeline-title-text: var(--stuic-color-foreground);
|
|
40
|
+
|
|
41
|
+
/* Description */
|
|
42
|
+
--stuic-timeline-description-font-size: var(--text-sm);
|
|
43
|
+
--stuic-timeline-description-text: var(--stuic-color-muted-foreground);
|
|
44
|
+
--stuic-timeline-description-margin-top: 0.125rem;
|
|
45
|
+
|
|
46
|
+
/* Footer */
|
|
47
|
+
--stuic-timeline-footer-gap: 0.5rem;
|
|
48
|
+
--stuic-timeline-footer-margin-top: 0.5rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@layer components {
|
|
52
|
+
/* ============================================================================
|
|
53
|
+
BASE — the list is a grid; every item is a subgrid row, so the rail (and
|
|
54
|
+
the opposite time column) line up across items regardless of content.
|
|
55
|
+
============================================================================ */
|
|
56
|
+
|
|
57
|
+
.stuic-timeline {
|
|
58
|
+
display: grid;
|
|
59
|
+
column-gap: var(--stuic-timeline-gap);
|
|
60
|
+
list-style: none;
|
|
61
|
+
margin: 0;
|
|
62
|
+
padding: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.stuic-timeline[data-align="start"][data-time-position="inline"] {
|
|
66
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.stuic-timeline[data-align="start"][data-time-position="opposite"] {
|
|
70
|
+
grid-template-columns: auto auto minmax(0, 1fr);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.stuic-timeline[data-align="alternate"] {
|
|
74
|
+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.stuic-timeline-item {
|
|
78
|
+
display: grid;
|
|
79
|
+
grid-column: 1 / -1;
|
|
80
|
+
grid-template-columns: subgrid;
|
|
81
|
+
padding-bottom: var(--stuic-timeline-gap-vertical);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.stuic-timeline-item:last-child {
|
|
85
|
+
padding-bottom: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* every cell sits on the item's single row; columns are assigned below */
|
|
89
|
+
.stuic-timeline-opposite,
|
|
90
|
+
.stuic-timeline-rail,
|
|
91
|
+
.stuic-timeline-content {
|
|
92
|
+
grid-row: 1;
|
|
93
|
+
min-width: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* ============================================================================
|
|
97
|
+
COLUMN PLACEMENT
|
|
98
|
+
============================================================================ */
|
|
99
|
+
|
|
100
|
+
/* start + inline: rail | content */
|
|
101
|
+
.stuic-timeline[data-align="start"][data-time-position="inline"] .stuic-timeline-rail {
|
|
102
|
+
grid-column: 1;
|
|
103
|
+
}
|
|
104
|
+
.stuic-timeline[data-align="start"][data-time-position="inline"]
|
|
105
|
+
.stuic-timeline-content {
|
|
106
|
+
grid-column: 2;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* start + opposite: time | rail | content */
|
|
110
|
+
.stuic-timeline[data-align="start"][data-time-position="opposite"]
|
|
111
|
+
.stuic-timeline-opposite {
|
|
112
|
+
grid-column: 1;
|
|
113
|
+
text-align: end;
|
|
114
|
+
}
|
|
115
|
+
.stuic-timeline[data-align="start"][data-time-position="opposite"]
|
|
116
|
+
.stuic-timeline-rail {
|
|
117
|
+
grid-column: 2;
|
|
118
|
+
}
|
|
119
|
+
.stuic-timeline[data-align="start"][data-time-position="opposite"]
|
|
120
|
+
.stuic-timeline-content {
|
|
121
|
+
grid-column: 3;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* alternate: centered rail; odd items → content end side, even → start side */
|
|
125
|
+
.stuic-timeline[data-align="alternate"] .stuic-timeline-rail {
|
|
126
|
+
grid-column: 2;
|
|
127
|
+
}
|
|
128
|
+
.stuic-timeline[data-align="alternate"]
|
|
129
|
+
.stuic-timeline-item:nth-child(odd)
|
|
130
|
+
.stuic-timeline-content {
|
|
131
|
+
grid-column: 3;
|
|
132
|
+
}
|
|
133
|
+
.stuic-timeline[data-align="alternate"]
|
|
134
|
+
.stuic-timeline-item:nth-child(odd)
|
|
135
|
+
.stuic-timeline-opposite {
|
|
136
|
+
grid-column: 1;
|
|
137
|
+
text-align: end;
|
|
138
|
+
}
|
|
139
|
+
.stuic-timeline[data-align="alternate"]
|
|
140
|
+
.stuic-timeline-item:nth-child(even)
|
|
141
|
+
.stuic-timeline-content {
|
|
142
|
+
grid-column: 1;
|
|
143
|
+
text-align: end;
|
|
144
|
+
}
|
|
145
|
+
.stuic-timeline[data-align="alternate"]
|
|
146
|
+
.stuic-timeline-item:nth-child(even)
|
|
147
|
+
.stuic-timeline-opposite {
|
|
148
|
+
grid-column: 3;
|
|
149
|
+
}
|
|
150
|
+
.stuic-timeline[data-align="alternate"]
|
|
151
|
+
.stuic-timeline-item:nth-child(even)
|
|
152
|
+
.stuic-timeline-footer {
|
|
153
|
+
justify-content: flex-end;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* ============================================================================
|
|
157
|
+
RAIL + CONNECTOR
|
|
158
|
+
The line runs behind the marker in two halves (top → marker center, marker
|
|
159
|
+
center → bottom) so no item needs to know its neighbour's marker size. The
|
|
160
|
+
marker's center is always at half the first-line height.
|
|
161
|
+
============================================================================ */
|
|
162
|
+
|
|
163
|
+
.stuic-timeline-rail {
|
|
164
|
+
position: relative;
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-direction: column;
|
|
167
|
+
align-items: center;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.stuic-timeline-rail::before,
|
|
171
|
+
.stuic-timeline-rail::after {
|
|
172
|
+
content: "";
|
|
173
|
+
position: absolute;
|
|
174
|
+
left: 50%;
|
|
175
|
+
width: var(--stuic-timeline-connector-thickness);
|
|
176
|
+
transform: translateX(-50%);
|
|
177
|
+
background: var(--stuic-timeline-connector-bg);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.stuic-timeline-rail::before {
|
|
181
|
+
top: 0;
|
|
182
|
+
height: calc(var(--stuic-timeline-line-height) / 2);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* the item's bottom padding (gap-vertical) lies outside the grid row, so reach
|
|
186
|
+
through it — the next item's ::before picks the line up at its top edge */
|
|
187
|
+
.stuic-timeline-rail::after {
|
|
188
|
+
top: calc(var(--stuic-timeline-line-height) / 2);
|
|
189
|
+
bottom: calc(-1 * var(--stuic-timeline-gap-vertical));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.stuic-timeline-item:first-child .stuic-timeline-rail::before,
|
|
193
|
+
.stuic-timeline-item:last-child .stuic-timeline-rail::after {
|
|
194
|
+
display: none;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* ============================================================================
|
|
198
|
+
MARKER
|
|
199
|
+
============================================================================ */
|
|
200
|
+
|
|
201
|
+
.stuic-timeline-marker {
|
|
202
|
+
position: relative;
|
|
203
|
+
z-index: 1;
|
|
204
|
+
display: inline-flex;
|
|
205
|
+
align-items: center;
|
|
206
|
+
justify-content: center;
|
|
207
|
+
flex-shrink: 0;
|
|
208
|
+
box-sizing: border-box;
|
|
209
|
+
width: var(--_marker-size);
|
|
210
|
+
height: var(--_marker-size);
|
|
211
|
+
/* center on the first line of the content (may go negative for big markers) */
|
|
212
|
+
margin-top: calc((var(--stuic-timeline-line-height) - var(--_marker-size)) / 2);
|
|
213
|
+
border-radius: var(--stuic-timeline-marker-radius, calc(infinity * 1px));
|
|
214
|
+
box-shadow: 0 0 0 var(--stuic-timeline-marker-ring-width)
|
|
215
|
+
var(--stuic-timeline-marker-ring-color);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.stuic-timeline-marker[data-marker="dot"] {
|
|
219
|
+
--_marker-size: var(--stuic-timeline-marker-size);
|
|
220
|
+
background: var(--stuic-timeline-marker-bg);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.stuic-timeline-marker[data-marker="icon"] {
|
|
224
|
+
--_marker-size: var(--stuic-timeline-marker-size-icon);
|
|
225
|
+
background: var(--stuic-timeline-marker-bg-icon);
|
|
226
|
+
color: var(--stuic-timeline-marker-text-icon);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.stuic-timeline-marker[data-marker="icon"] svg {
|
|
230
|
+
display: block;
|
|
231
|
+
width: var(--stuic-timeline-marker-icon-size);
|
|
232
|
+
height: var(--stuic-timeline-marker-icon-size);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* custom (renderMarker): only the box — the snippet brings its own look */
|
|
236
|
+
.stuic-timeline-marker[data-marker="custom"] {
|
|
237
|
+
--_marker-size: var(--stuic-timeline-marker-size-icon);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* ============================================================================
|
|
241
|
+
INTENT — dot fills with the color, the bubble takes a soft tint
|
|
242
|
+
============================================================================ */
|
|
243
|
+
|
|
244
|
+
.stuic-timeline-item[data-intent="primary"] {
|
|
245
|
+
--_intent: var(--stuic-color-primary);
|
|
246
|
+
}
|
|
247
|
+
.stuic-timeline-item[data-intent="accent"] {
|
|
248
|
+
--_intent: var(--stuic-color-accent);
|
|
249
|
+
}
|
|
250
|
+
.stuic-timeline-item[data-intent="destructive"] {
|
|
251
|
+
--_intent: var(--stuic-color-destructive);
|
|
252
|
+
}
|
|
253
|
+
.stuic-timeline-item[data-intent="warning"] {
|
|
254
|
+
--_intent: var(--stuic-color-warning);
|
|
255
|
+
}
|
|
256
|
+
.stuic-timeline-item[data-intent="success"] {
|
|
257
|
+
--_intent: var(--stuic-color-success);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.stuic-timeline-item[data-intent] .stuic-timeline-marker[data-marker="dot"] {
|
|
261
|
+
background: var(--_intent);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.stuic-timeline-item[data-intent] .stuic-timeline-marker[data-marker="icon"] {
|
|
265
|
+
background: color-mix(in srgb, var(--_intent) 15%, var(--stuic-color-background));
|
|
266
|
+
color: var(--_intent);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* ============================================================================
|
|
270
|
+
CONTENT: time, title, description, footer
|
|
271
|
+
============================================================================ */
|
|
272
|
+
|
|
273
|
+
.stuic-timeline-time {
|
|
274
|
+
display: block;
|
|
275
|
+
font-size: var(--stuic-timeline-time-font-size);
|
|
276
|
+
line-height: var(--stuic-timeline-line-height);
|
|
277
|
+
color: var(--stuic-timeline-time-text);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.stuic-timeline-title {
|
|
281
|
+
font-size: var(--stuic-timeline-title-font-size);
|
|
282
|
+
font-weight: var(--stuic-timeline-title-font-weight);
|
|
283
|
+
line-height: var(--stuic-timeline-line-height);
|
|
284
|
+
color: var(--stuic-timeline-title-text);
|
|
285
|
+
overflow-wrap: anywhere;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.stuic-timeline-link {
|
|
289
|
+
color: inherit;
|
|
290
|
+
text-decoration: none;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.stuic-timeline-link:hover {
|
|
294
|
+
text-decoration: underline;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.stuic-timeline-description {
|
|
298
|
+
margin-top: var(--stuic-timeline-description-margin-top);
|
|
299
|
+
font-size: var(--stuic-timeline-description-font-size);
|
|
300
|
+
color: var(--stuic-timeline-description-text);
|
|
301
|
+
overflow-wrap: anywhere;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.stuic-timeline-footer {
|
|
305
|
+
display: flex;
|
|
306
|
+
flex-wrap: wrap;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: var(--stuic-timeline-footer-gap);
|
|
309
|
+
margin-top: var(--stuic-timeline-footer-margin-top);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Timeline, type Props as TimelineProps, type TimelineItem, type TimelineAlign, type TimelineTimePosition, type TimelineMarkerKind, type TimelineSnippetArg, } from "./Timeline.svelte";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Timeline, } from "./Timeline.svelte";
|
package/dist/index.css
CHANGED
|
@@ -112,6 +112,7 @@ In practice:
|
|
|
112
112
|
@import "./components/Switch/index.css";
|
|
113
113
|
@import "./components/TabbedMenu/index.css";
|
|
114
114
|
@import "./components/ThemePreview/index.css";
|
|
115
|
+
@import "./components/Timeline/index.css";
|
|
115
116
|
@import "./components/Tree/index.css";
|
|
116
117
|
@import "./components/TwCheck/index.css";
|
|
117
118
|
@import "./components/UserAvatarMenu/index.css";
|
package/dist/index.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ export * from "./components/Switch/index.js";
|
|
|
84
84
|
export * from "./components/TabbedMenu/index.js";
|
|
85
85
|
export * from "./components/Thc/index.js";
|
|
86
86
|
export * from "./components/ThemePreview/index.js";
|
|
87
|
+
export * from "./components/Timeline/index.js";
|
|
87
88
|
export * from "./components/Tree/index.js";
|
|
88
89
|
export * from "./components/TwCheck/index.js";
|
|
89
90
|
export * from "./components/TypeaheadInput/index.js";
|
package/dist/index.js
CHANGED
|
@@ -90,6 +90,7 @@ export * from "./components/Switch/index.js";
|
|
|
90
90
|
export * from "./components/TabbedMenu/index.js";
|
|
91
91
|
export * from "./components/Thc/index.js";
|
|
92
92
|
export * from "./components/ThemePreview/index.js";
|
|
93
|
+
export * from "./components/Timeline/index.js";
|
|
93
94
|
// NOTE: TrendChart is deliberately NOT exported here. It statically imports the
|
|
94
95
|
// optional @marianmeres/trend-chart peer, which would then be pulled into the
|
|
95
96
|
// root entry graph of every consumer. It ships as the `@marianmeres/stuic/trend-chart`
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
74 Svelte 5 component directories with consistent API patterns. All use runes-based reactivity.
|
|
6
6
|
|
|
7
7
|
## Component Categories
|
|
8
8
|
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
| Thc | Flexible renderer for text, HTML, components, or snippets |
|
|
101
101
|
| Card | Flexible card with image, title, footer; vertical/horizontal layout |
|
|
102
102
|
| Stat | KPI/stat card: label + value + delta with trend arrow and semantic coloring |
|
|
103
|
+
| Timeline | Vertical event list on a rail: dot/icon/custom markers, inline or opposite time, alternate layout |
|
|
103
104
|
| TrendChart | Svelte wrapper for `@marianmeres/trend-chart` (subpath-only: `@marianmeres/stuic/trend-chart`) |
|
|
104
105
|
| Tree | Hierarchical tree view with keyboard nav and drag-and-drop |
|
|
105
106
|
| X | Styled close/multiply SVG icon |
|
|
@@ -1091,6 +1092,43 @@ Prefix: `--stuic-stepper-*`
|
|
|
1091
1092
|
|
|
1092
1093
|
---
|
|
1093
1094
|
|
|
1095
|
+
## Timeline
|
|
1096
|
+
|
|
1097
|
+
Vertical event list with markers on a rail — activity feeds, audit logs, order tracking, history pages. A real `<ol>` (explicit `role="list"`); every item has a marker (small dot, icon bubble when `item.icon` is set, or anything via `renderMarker`), an optional time label, title, description and footer. Data-driven (`items`), static by design — no "current" step (use `Stepper` vertical for progress flows). The list is a CSS grid with `subgrid` items, so the rail and the optional time column align across items without fixed widths; the rail line runs behind the markers and a background-colored ring separates them.
|
|
1098
|
+
|
|
1099
|
+
### Exports
|
|
1100
|
+
|
|
1101
|
+
| Export | Kind | Description |
|
|
1102
|
+
| ---------------------- | --------- | ------------------------------------------------------------------- |
|
|
1103
|
+
| `Timeline` | component | Main component |
|
|
1104
|
+
| `TimelineProps` | type | Props type |
|
|
1105
|
+
| `TimelineItem` | type | `{ title?, description?, time?, datetime?, icon?, intent?, href? }` |
|
|
1106
|
+
| `TimelineAlign` | type | `"start" \| "alternate"` |
|
|
1107
|
+
| `TimelineTimePosition` | type | `"inline" \| "opposite"` |
|
|
1108
|
+
| `TimelineMarkerKind` | type | `"dot" \| "icon" \| "custom"` (the marker's `data-marker`) |
|
|
1109
|
+
| `TimelineSnippetArg` | type | `{ item, index }` — argument of all three snippets |
|
|
1110
|
+
|
|
1111
|
+
### Key Props
|
|
1112
|
+
|
|
1113
|
+
| Prop | Type | Default | Description |
|
|
1114
|
+
| -------------- | ------------------------- | ---------- | ----------------------------------------------------------------------------- |
|
|
1115
|
+
| `items` | `TimelineItem[]` | required | The events, in display order (title/description/time/icon are THC) |
|
|
1116
|
+
| `align` | `"start" \| "alternate"` | `"start"` | Rail on the start side, or centered rail with content alternating sides |
|
|
1117
|
+
| `timePosition` | `"inline" \| "opposite"` | `"inline"` | Time above the title inside the content, or in its own column across the rail |
|
|
1118
|
+
| `formatTime` | `(datetime, item) => THC` | — | Fallback label for items with `datetime` but no `time` |
|
|
1119
|
+
|
|
1120
|
+
`item.datetime` (string or `Date`, serialized to ISO) renders the label as `<time datetime>`; without it the label is a `<span>`. `item.intent` (`IntentColorKey`) fills the dot / soft-tints the bubble. `item.href` renders the title as a link.
|
|
1121
|
+
|
|
1122
|
+
Snippets (all receive `{ item, index }`): `renderMarker` (replaces every marker, `data-marker="custom"`), `renderItem` (replaces the whole content cell), `renderFooter` (per-item area under the description). Class slots: `class`, `classItem`, `classMarker`, `classContent`, `classTime`, `classTitle`, `classDescription`, `classFooter`. Markers are `aria-hidden`.
|
|
1123
|
+
|
|
1124
|
+
### CSS Tokens
|
|
1125
|
+
|
|
1126
|
+
Prefix: `--stuic-timeline-*`
|
|
1127
|
+
|
|
1128
|
+
`gap`, `gap-vertical`, `line-height`, `connector-thickness`, `connector-bg`, `marker-size`, `marker-bg`, `marker-size-icon`, `marker-bg-icon`, `marker-text-icon`, `marker-icon-size`, `marker-radius`, `marker-ring-width`, `marker-ring-color`, `time-font-size`, `time-text`, `title-font-size`, `title-font-weight`, `title-text`, `description-font-size`, `description-text`, `description-margin-top`, `footer-gap`, `footer-margin-top`
|
|
1129
|
+
|
|
1130
|
+
---
|
|
1131
|
+
|
|
1094
1132
|
## CronInput
|
|
1095
1133
|
|
|
1096
1134
|
Cron expression editor with preset selector, manual 5-field editor, raw expression input, human-readable descriptions, and next-run calculation.
|
package/docs/maybe-todo.md
CHANGED
|
@@ -59,8 +59,11 @@ Checked first, to avoid false positives:
|
|
|
59
59
|
`WithSidePanel`, and `persistent-state` already provide the pieces.
|
|
60
60
|
9. **Range slider (dual-thumb)** — `Slider` is deliberately single-value; a min/max
|
|
61
61
|
range variant (price filters etc.) is a recurring ask.
|
|
62
|
-
10.
|
|
63
|
-
|
|
62
|
+
10. ~~**Timeline / activity feed**~~ — ✅ shipped (see `src/lib/components/Timeline/`):
|
|
63
|
+
vertical event list on a rail with dot / icon-bubble / custom (snippet) markers,
|
|
64
|
+
per-item intent, `<time datetime>` support with an optional formatter, inline or
|
|
65
|
+
opposite time column, `start` / `alternate` alignment; `subgrid` keeps the columns
|
|
66
|
+
aligned without fixed widths.
|
|
64
67
|
11. ~~**Stat / KPI card**~~ — ✅ shipped (see `src/lib/components/Stat/`): label +
|
|
65
68
|
value + delta with trend arrow and semantic coloring (`trendIntent` for
|
|
66
69
|
down-is-good metrics), hint, corner icon, footer/sparkline area.
|