@godxjp/ui 13.16.4 → 13.17.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.
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
+
import { type LucideIcon } from "lucide-react";
|
|
3
|
+
export type TimelineStatus = "done" | "current" | "pending";
|
|
4
|
+
export type TimelineVariant = "icon" | "ordinal" | "status";
|
|
2
5
|
export type TimelineItem = {
|
|
3
6
|
title: ReactNode;
|
|
4
7
|
location?: ReactNode;
|
|
5
8
|
time?: ReactNode;
|
|
6
9
|
note?: ReactNode;
|
|
10
|
+
/** Shorthand for `status: "current"`. `status` wins when both are set. */
|
|
7
11
|
current?: boolean;
|
|
12
|
+
/** Explicit 3-state. Resolves as `status ?? (current ? "current" : <legacy>)`. */
|
|
13
|
+
status?: TimelineStatus;
|
|
14
|
+
/** Per-item glyph override; wins over the variant/status auto-glyph. */
|
|
15
|
+
icon?: LucideIcon;
|
|
8
16
|
};
|
|
9
17
|
export type TimelineProps = {
|
|
10
18
|
items: TimelineItem[];
|
|
19
|
+
/**
|
|
20
|
+
* Rail glyph strategy. `icon` (default) keeps the legacy look (Plane for the
|
|
21
|
+
* current step, CheckCircle2 otherwise). `ordinal` numbers every step
|
|
22
|
+
* (1,2,3…) and lets status drive colour only. `status` picks the glyph by
|
|
23
|
+
* status: done → check, current → filled dot, pending → the step number.
|
|
24
|
+
*/
|
|
25
|
+
variant?: TimelineVariant;
|
|
11
26
|
};
|
|
12
|
-
export declare function Timeline({ items }: TimelineProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export declare function Timeline({ items, variant }: TimelineProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,22 +1,72 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { CheckCircle2, Plane } from "lucide-react";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { Check, CheckCircle2, Plane } from "lucide-react";
|
|
3
|
+
const SR_PREFIX = {
|
|
4
|
+
done: "Completed: ",
|
|
5
|
+
current: "Current: ",
|
|
6
|
+
pending: "Upcoming: "
|
|
7
|
+
};
|
|
8
|
+
function resolveStatus(item) {
|
|
9
|
+
if (item.status) {
|
|
10
|
+
return item.status;
|
|
11
|
+
}
|
|
12
|
+
if (item.current) {
|
|
13
|
+
return "current";
|
|
14
|
+
}
|
|
15
|
+
return "done";
|
|
16
|
+
}
|
|
17
|
+
function Timeline({ items, variant = "icon" }) {
|
|
18
|
+
return /* @__PURE__ */ jsx("ol", { className: "ui-timeline", "data-variant": variant, children: items.map((item, index) => {
|
|
19
|
+
const status = resolveStatus(item);
|
|
20
|
+
const isCurrent = status === "current";
|
|
21
|
+
const ordinal = index + 1;
|
|
22
|
+
const lineCompleted = status === "done" || status === "current";
|
|
23
|
+
let glyph;
|
|
24
|
+
if (item.icon) {
|
|
25
|
+
const Icon = item.icon;
|
|
26
|
+
glyph = /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" });
|
|
27
|
+
} else if (variant === "ordinal") {
|
|
28
|
+
glyph = /* @__PURE__ */ jsx("span", { className: "ui-timeline-ordinal", children: ordinal });
|
|
29
|
+
} else if (variant === "status") {
|
|
30
|
+
if (status === "done") {
|
|
31
|
+
glyph = /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" });
|
|
32
|
+
} else if (status === "current") {
|
|
33
|
+
glyph = /* @__PURE__ */ jsx("span", { className: "ui-timeline-pip", "aria-hidden": "true" });
|
|
34
|
+
} else {
|
|
35
|
+
glyph = /* @__PURE__ */ jsx("span", { className: "ui-timeline-ordinal", children: ordinal });
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
const Icon = isCurrent ? Plane : CheckCircle2;
|
|
39
|
+
glyph = /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" });
|
|
40
|
+
}
|
|
6
41
|
return /* @__PURE__ */ jsxs(
|
|
7
42
|
"li",
|
|
8
43
|
{
|
|
9
44
|
className: "ui-timeline-item",
|
|
10
|
-
"
|
|
45
|
+
"data-status": status,
|
|
46
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
11
47
|
children: [
|
|
12
48
|
/* @__PURE__ */ jsxs("div", { className: "ui-timeline-rail", children: [
|
|
13
|
-
/* @__PURE__ */ jsx(
|
|
14
|
-
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
"span",
|
|
51
|
+
{
|
|
52
|
+
className: "ui-timeline-dot",
|
|
53
|
+
"data-status": status,
|
|
54
|
+
"data-current": isCurrent ? "true" : void 0,
|
|
55
|
+
children: glyph
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
index !== items.length - 1 ? /* @__PURE__ */ jsx(
|
|
59
|
+
"span",
|
|
60
|
+
{
|
|
61
|
+
className: "ui-timeline-line",
|
|
62
|
+
"data-completed": lineCompleted ? "true" : void 0
|
|
63
|
+
}
|
|
64
|
+
) : null
|
|
15
65
|
] }),
|
|
16
66
|
/* @__PURE__ */ jsxs("div", { className: "ui-timeline-body", children: [
|
|
17
67
|
/* @__PURE__ */ jsxs("div", { className: "ui-timeline-head", children: [
|
|
18
|
-
/* @__PURE__ */ jsxs("span", { className: "ui-timeline-title", children: [
|
|
19
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children:
|
|
68
|
+
/* @__PURE__ */ jsxs("span", { className: "ui-timeline-title", "data-current": isCurrent ? "true" : void 0, children: [
|
|
69
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: SR_PREFIX[status] }),
|
|
20
70
|
item.title
|
|
21
71
|
] }),
|
|
22
72
|
item.time ? /* @__PURE__ */ jsx("span", { className: "ui-timeline-time", children: item.time }) : null
|
|
@@ -149,14 +149,34 @@
|
|
|
149
149
|
width: 1.5rem;
|
|
150
150
|
height: 1.5rem;
|
|
151
151
|
place-items: center;
|
|
152
|
+
border: 1px solid transparent;
|
|
152
153
|
border-radius: var(--radius-pill);
|
|
153
154
|
background: hsl(var(--success));
|
|
154
155
|
color: hsl(var(--success-foreground));
|
|
156
|
+
font-size: var(--timeline-note-font-size);
|
|
157
|
+
font-weight: var(--font-weight-medium);
|
|
158
|
+
line-height: 1;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* done → success fill. */
|
|
162
|
+
.ui-timeline-dot[data-status="done"] {
|
|
163
|
+
background: hsl(var(--success));
|
|
164
|
+
color: hsl(var(--success-foreground));
|
|
155
165
|
}
|
|
156
166
|
|
|
167
|
+
/* current → primary fill + ring (also the legacy data-current shorthand). */
|
|
168
|
+
.ui-timeline-dot[data-status="current"],
|
|
157
169
|
.ui-timeline-dot[data-current="true"] {
|
|
158
170
|
background: hsl(var(--primary));
|
|
159
171
|
color: hsl(var(--primary-foreground));
|
|
172
|
+
box-shadow: 0 0 0 3px hsl(var(--primary) / 0.18);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* pending → muted outline on the surface (no fill). */
|
|
176
|
+
.ui-timeline-dot[data-status="pending"] {
|
|
177
|
+
border-color: hsl(var(--border));
|
|
178
|
+
background: hsl(var(--background));
|
|
179
|
+
color: hsl(var(--muted-foreground));
|
|
160
180
|
}
|
|
161
181
|
|
|
162
182
|
.ui-timeline-dot svg {
|
|
@@ -164,6 +184,15 @@
|
|
|
164
184
|
height: 0.75rem;
|
|
165
185
|
}
|
|
166
186
|
|
|
187
|
+
/* current pip glyph for variant="status" (filled inner dot). */
|
|
188
|
+
.ui-timeline-pip {
|
|
189
|
+
display: block;
|
|
190
|
+
width: 0.5rem;
|
|
191
|
+
height: 0.5rem;
|
|
192
|
+
border-radius: var(--radius-pill);
|
|
193
|
+
background: currentColor;
|
|
194
|
+
}
|
|
195
|
+
|
|
167
196
|
.ui-timeline-line {
|
|
168
197
|
width: 1px;
|
|
169
198
|
min-height: 2.25rem;
|
|
@@ -171,6 +200,11 @@
|
|
|
171
200
|
background: hsl(var(--border));
|
|
172
201
|
}
|
|
173
202
|
|
|
203
|
+
/* The segment below a done/current step reads as travelled (completed). */
|
|
204
|
+
.ui-timeline-line[data-completed="true"] {
|
|
205
|
+
background: hsl(var(--primary));
|
|
206
|
+
}
|
|
207
|
+
|
|
174
208
|
.ui-timeline-head {
|
|
175
209
|
display: flex;
|
|
176
210
|
align-items: center;
|
|
@@ -182,6 +216,11 @@
|
|
|
182
216
|
font-weight: var(--font-weight-medium);
|
|
183
217
|
}
|
|
184
218
|
|
|
219
|
+
.ui-timeline-title[data-current="true"] {
|
|
220
|
+
color: hsl(var(--primary));
|
|
221
|
+
font-weight: var(--font-weight-semibold);
|
|
222
|
+
}
|
|
223
|
+
|
|
185
224
|
.ui-timeline-time,
|
|
186
225
|
.ui-timeline-location,
|
|
187
226
|
.ui-timeline-note {
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
.ui-form-field {
|
|
21
21
|
display: grid;
|
|
22
22
|
gap: var(--field-label-gap);
|
|
23
|
+
/* Never stretch to a taller grid-row sibling (e.g. a field carrying a
|
|
24
|
+
* helper/error). Stretching would let .ui-form-field-control's
|
|
25
|
+
* align-content:center vertically centre the control, so a field WITHOUT a
|
|
26
|
+
* helper sits lower than one WITH a helper in the same ResponsiveGrid row.
|
|
27
|
+
* Hugging content keeps every control top-aligned across the row. */
|
|
28
|
+
align-self: start;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
.ui-form-field-label {
|