@diwauhris/ui 1.0.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/README.md +75 -0
- package/lib/assets/ui.css +154 -0
- package/lib/index.cjs +183 -0
- package/lib/index.mjs +65 -0
- package/lib/index10.cjs +33 -0
- package/lib/index10.cjs.map +1 -0
- package/lib/index10.mjs +33 -0
- package/lib/index10.mjs.map +1 -0
- package/lib/index11.cjs +16 -0
- package/lib/index11.cjs.map +1 -0
- package/lib/index11.mjs +16 -0
- package/lib/index11.mjs.map +1 -0
- package/lib/index12.cjs +16 -0
- package/lib/index12.cjs.map +1 -0
- package/lib/index12.mjs +15 -0
- package/lib/index12.mjs.map +1 -0
- package/lib/index13.cjs +57 -0
- package/lib/index13.cjs.map +1 -0
- package/lib/index13.mjs +57 -0
- package/lib/index13.mjs.map +1 -0
- package/lib/index14.cjs +10 -0
- package/lib/index14.cjs.map +1 -0
- package/lib/index14.mjs +10 -0
- package/lib/index14.mjs.map +1 -0
- package/lib/index15.cjs +30 -0
- package/lib/index15.cjs.map +1 -0
- package/lib/index15.mjs +30 -0
- package/lib/index15.mjs.map +1 -0
- package/lib/index16.cjs +28 -0
- package/lib/index16.cjs.map +1 -0
- package/lib/index16.mjs +26 -0
- package/lib/index16.mjs.map +1 -0
- package/lib/index17.cjs +43 -0
- package/lib/index17.cjs.map +1 -0
- package/lib/index17.mjs +43 -0
- package/lib/index17.mjs.map +1 -0
- package/lib/index18.cjs +59 -0
- package/lib/index18.cjs.map +1 -0
- package/lib/index18.mjs +59 -0
- package/lib/index18.mjs.map +1 -0
- package/lib/index19.cjs +67 -0
- package/lib/index19.cjs.map +1 -0
- package/lib/index19.mjs +67 -0
- package/lib/index19.mjs.map +1 -0
- package/lib/index2.cjs +33 -0
- package/lib/index2.mjs +13 -0
- package/lib/index20.cjs +79 -0
- package/lib/index20.cjs.map +1 -0
- package/lib/index20.mjs +79 -0
- package/lib/index20.mjs.map +1 -0
- package/lib/index21.cjs +105 -0
- package/lib/index21.cjs.map +1 -0
- package/lib/index21.mjs +104 -0
- package/lib/index21.mjs.map +1 -0
- package/lib/index22.cjs +50 -0
- package/lib/index22.cjs.map +1 -0
- package/lib/index22.mjs +50 -0
- package/lib/index22.mjs.map +1 -0
- package/lib/index23.cjs +143 -0
- package/lib/index23.cjs.map +1 -0
- package/lib/index23.mjs +143 -0
- package/lib/index23.mjs.map +1 -0
- package/lib/index25.cjs +177 -0
- package/lib/index25.cjs.map +1 -0
- package/lib/index25.mjs +175 -0
- package/lib/index25.mjs.map +1 -0
- package/lib/index26.cjs +108 -0
- package/lib/index26.cjs.map +1 -0
- package/lib/index26.mjs +108 -0
- package/lib/index26.mjs.map +1 -0
- package/lib/index27.cjs +120 -0
- package/lib/index27.cjs.map +1 -0
- package/lib/index27.mjs +120 -0
- package/lib/index27.mjs.map +1 -0
- package/lib/index28.cjs +54 -0
- package/lib/index28.cjs.map +1 -0
- package/lib/index28.mjs +54 -0
- package/lib/index28.mjs.map +1 -0
- package/lib/index29.cjs +100 -0
- package/lib/index29.cjs.map +1 -0
- package/lib/index29.mjs +100 -0
- package/lib/index29.mjs.map +1 -0
- package/lib/index3.cjs +38 -0
- package/lib/index3.cjs.map +1 -0
- package/lib/index3.mjs +38 -0
- package/lib/index3.mjs.map +1 -0
- package/lib/index30.cjs +27 -0
- package/lib/index30.cjs.map +1 -0
- package/lib/index30.mjs +27 -0
- package/lib/index30.mjs.map +1 -0
- package/lib/index31.cjs +72 -0
- package/lib/index31.cjs.map +1 -0
- package/lib/index31.mjs +72 -0
- package/lib/index31.mjs.map +1 -0
- package/lib/index32.cjs +19 -0
- package/lib/index32.cjs.map +1 -0
- package/lib/index32.mjs +19 -0
- package/lib/index32.mjs.map +1 -0
- package/lib/index33.cjs +25 -0
- package/lib/index33.cjs.map +1 -0
- package/lib/index33.mjs +25 -0
- package/lib/index33.mjs.map +1 -0
- package/lib/index34.cjs +55 -0
- package/lib/index34.cjs.map +1 -0
- package/lib/index34.mjs +51 -0
- package/lib/index34.mjs.map +1 -0
- package/lib/index35.cjs +25 -0
- package/lib/index35.cjs.map +1 -0
- package/lib/index35.mjs +25 -0
- package/lib/index35.mjs.map +1 -0
- package/lib/index36.cjs +54 -0
- package/lib/index36.cjs.map +1 -0
- package/lib/index36.mjs +49 -0
- package/lib/index36.mjs.map +1 -0
- package/lib/index37.cjs +130 -0
- package/lib/index37.cjs.map +1 -0
- package/lib/index37.mjs +128 -0
- package/lib/index37.mjs.map +1 -0
- package/lib/index38.cjs +106 -0
- package/lib/index38.cjs.map +1 -0
- package/lib/index38.mjs +102 -0
- package/lib/index38.mjs.map +1 -0
- package/lib/index39.cjs +137 -0
- package/lib/index39.cjs.map +1 -0
- package/lib/index39.mjs +137 -0
- package/lib/index39.mjs.map +1 -0
- package/lib/index4.cjs +24 -0
- package/lib/index4.cjs.map +1 -0
- package/lib/index4.mjs +24 -0
- package/lib/index4.mjs.map +1 -0
- package/lib/index40.cjs +130 -0
- package/lib/index40.cjs.map +1 -0
- package/lib/index40.mjs +126 -0
- package/lib/index40.mjs.map +1 -0
- package/lib/index41.cjs +60 -0
- package/lib/index41.cjs.map +1 -0
- package/lib/index41.mjs +58 -0
- package/lib/index41.mjs.map +1 -0
- package/lib/index42.cjs +105 -0
- package/lib/index42.cjs.map +1 -0
- package/lib/index42.mjs +105 -0
- package/lib/index42.mjs.map +1 -0
- package/lib/index43.cjs +47 -0
- package/lib/index43.cjs.map +1 -0
- package/lib/index43.mjs +42 -0
- package/lib/index43.mjs.map +1 -0
- package/lib/index44.cjs +40 -0
- package/lib/index44.cjs.map +1 -0
- package/lib/index44.mjs +35 -0
- package/lib/index44.mjs.map +1 -0
- package/lib/index45.cjs +91 -0
- package/lib/index45.cjs.map +1 -0
- package/lib/index45.mjs +91 -0
- package/lib/index45.mjs.map +1 -0
- package/lib/index46.cjs +180 -0
- package/lib/index46.cjs.map +1 -0
- package/lib/index46.mjs +180 -0
- package/lib/index46.mjs.map +1 -0
- package/lib/index47.cjs +61 -0
- package/lib/index47.cjs.map +1 -0
- package/lib/index47.mjs +61 -0
- package/lib/index47.mjs.map +1 -0
- package/lib/index48.cjs +165 -0
- package/lib/index48.cjs.map +1 -0
- package/lib/index48.mjs +161 -0
- package/lib/index48.mjs.map +1 -0
- package/lib/index49.cjs +83 -0
- package/lib/index49.cjs.map +1 -0
- package/lib/index49.mjs +83 -0
- package/lib/index49.mjs.map +1 -0
- package/lib/index5.cjs +39 -0
- package/lib/index5.cjs.map +1 -0
- package/lib/index5.mjs +39 -0
- package/lib/index5.mjs.map +1 -0
- package/lib/index50.cjs +100 -0
- package/lib/index50.cjs.map +1 -0
- package/lib/index50.mjs +100 -0
- package/lib/index50.mjs.map +1 -0
- package/lib/index51.cjs +116 -0
- package/lib/index51.cjs.map +1 -0
- package/lib/index51.mjs +113 -0
- package/lib/index51.mjs.map +1 -0
- package/lib/index52.cjs +93 -0
- package/lib/index52.cjs.map +1 -0
- package/lib/index52.mjs +93 -0
- package/lib/index52.mjs.map +1 -0
- package/lib/index53.cjs +120 -0
- package/lib/index53.cjs.map +1 -0
- package/lib/index53.mjs +120 -0
- package/lib/index53.mjs.map +1 -0
- package/lib/index54.cjs +53 -0
- package/lib/index54.cjs.map +1 -0
- package/lib/index54.mjs +50 -0
- package/lib/index54.mjs.map +1 -0
- package/lib/index55.cjs +130 -0
- package/lib/index55.cjs.map +1 -0
- package/lib/index55.mjs +127 -0
- package/lib/index55.mjs.map +1 -0
- package/lib/index56.cjs +36 -0
- package/lib/index56.cjs.map +1 -0
- package/lib/index56.mjs +35 -0
- package/lib/index56.mjs.map +1 -0
- package/lib/index57.cjs +47 -0
- package/lib/index57.cjs.map +1 -0
- package/lib/index57.mjs +47 -0
- package/lib/index57.mjs.map +1 -0
- package/lib/index58.cjs +97 -0
- package/lib/index58.cjs.map +1 -0
- package/lib/index58.mjs +97 -0
- package/lib/index58.mjs.map +1 -0
- package/lib/index59.cjs +120 -0
- package/lib/index59.cjs.map +1 -0
- package/lib/index59.mjs +116 -0
- package/lib/index59.mjs.map +1 -0
- package/lib/index6.cjs +29 -0
- package/lib/index6.cjs.map +1 -0
- package/lib/index6.mjs +29 -0
- package/lib/index6.mjs.map +1 -0
- package/lib/index60.cjs +34 -0
- package/lib/index60.cjs.map +1 -0
- package/lib/index60.mjs +34 -0
- package/lib/index60.mjs.map +1 -0
- package/lib/index61.cjs +62 -0
- package/lib/index61.cjs.map +1 -0
- package/lib/index61.mjs +62 -0
- package/lib/index61.mjs.map +1 -0
- package/lib/index62.cjs +213 -0
- package/lib/index62.cjs.map +1 -0
- package/lib/index62.mjs +213 -0
- package/lib/index62.mjs.map +1 -0
- package/lib/index63.cjs +42 -0
- package/lib/index63.cjs.map +1 -0
- package/lib/index63.mjs +42 -0
- package/lib/index63.mjs.map +1 -0
- package/lib/index64.cjs +86 -0
- package/lib/index64.cjs.map +1 -0
- package/lib/index64.mjs +86 -0
- package/lib/index64.mjs.map +1 -0
- package/lib/index65.cjs +156 -0
- package/lib/index65.cjs.map +1 -0
- package/lib/index65.mjs +156 -0
- package/lib/index65.mjs.map +1 -0
- package/lib/index66.cjs +107 -0
- package/lib/index66.cjs.map +1 -0
- package/lib/index66.mjs +106 -0
- package/lib/index66.mjs.map +1 -0
- package/lib/index67.cjs +52 -0
- package/lib/index67.cjs.map +1 -0
- package/lib/index67.mjs +52 -0
- package/lib/index67.mjs.map +1 -0
- package/lib/index68.cjs +125 -0
- package/lib/index68.cjs.map +1 -0
- package/lib/index68.mjs +115 -0
- package/lib/index68.mjs.map +1 -0
- package/lib/index69.cjs +34 -0
- package/lib/index69.cjs.map +1 -0
- package/lib/index69.mjs +29 -0
- package/lib/index69.mjs.map +1 -0
- package/lib/index7.cjs +17 -0
- package/lib/index7.cjs.map +1 -0
- package/lib/index7.mjs +17 -0
- package/lib/index7.mjs.map +1 -0
- package/lib/index8.cjs +86 -0
- package/lib/index8.cjs.map +1 -0
- package/lib/index8.mjs +86 -0
- package/lib/index8.mjs.map +1 -0
- package/lib/index9.cjs +29 -0
- package/lib/index9.cjs.map +1 -0
- package/lib/index9.mjs +29 -0
- package/lib/index9.mjs.map +1 -0
- package/lib/types/index.d.ts +1 -0
- package/package.json +68 -0
package/lib/index59.cjs
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
2
|
+
let lucide_react = require("lucide-react");
|
|
3
|
+
//#region src/ui-library/gallery/timeline/Timeline.tsx
|
|
4
|
+
function Timeline({ children, className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6
|
+
className: `w-full space-y-0 ${className}`,
|
|
7
|
+
children
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function TimelineItem({ isFirst, isLast, children }) {
|
|
11
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
12
|
+
className: "flex gap-3",
|
|
13
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14
|
+
className: "flex flex-col items-center shrink-0 pt-4",
|
|
15
|
+
"aria-hidden": "true",
|
|
16
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: `w-2.5 h-2.5 rounded-full ring-2 ring-offset-2 shrink-0 ${isFirst ? "bg-brand-blue ring-brand-blue/30" : "bg-slate-300 ring-slate-100"}` }), !isLast && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "w-px flex-1 bg-slate-200 mt-1.5 min-h-[2rem]" })]
|
|
17
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
18
|
+
className: "flex-1 min-w-0 pb-5",
|
|
19
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
20
|
+
className: "rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden",
|
|
21
|
+
children
|
|
22
|
+
})
|
|
23
|
+
})]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function TimelineValueCard({ beforeLabel = "Previous", afterLabel = "Current", beforeContent, afterContent, beforeAction, afterAction }) {
|
|
27
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
28
|
+
className: "rounded-lg border border-slate-200 overflow-hidden",
|
|
29
|
+
role: "group",
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
32
|
+
className: "px-3 pt-2.5 pb-3 bg-slate-50",
|
|
33
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
34
|
+
className: "flex items-center gap-1 mb-1.5",
|
|
35
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
36
|
+
className: "text-[10px] font-bold text-slate-400 uppercase tracking-wider",
|
|
37
|
+
children: beforeLabel
|
|
38
|
+
}), beforeAction && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
39
|
+
className: "ml-auto",
|
|
40
|
+
children: beforeAction
|
|
41
|
+
})]
|
|
42
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
43
|
+
className: "text-sm text-slate-500 leading-snug",
|
|
44
|
+
"aria-label": `${beforeLabel} value`,
|
|
45
|
+
children: beforeContent
|
|
46
|
+
})]
|
|
47
|
+
}),
|
|
48
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
49
|
+
className: "flex items-center justify-center py-1.5 border-y border-slate-200 bg-white",
|
|
50
|
+
"aria-hidden": "true",
|
|
51
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ArrowDown, {
|
|
52
|
+
size: 12,
|
|
53
|
+
className: "text-slate-400",
|
|
54
|
+
strokeWidth: 2.5
|
|
55
|
+
})
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
58
|
+
className: "px-3 pt-2.5 pb-3 bg-white",
|
|
59
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
60
|
+
className: "flex items-center gap-1 mb-1.5",
|
|
61
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
62
|
+
className: "text-[10px] font-bold text-slate-600 uppercase tracking-wider",
|
|
63
|
+
children: afterLabel
|
|
64
|
+
}), afterAction && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
65
|
+
className: "ml-auto",
|
|
66
|
+
children: afterAction
|
|
67
|
+
})]
|
|
68
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
69
|
+
className: "text-sm font-semibold text-slate-800 leading-snug",
|
|
70
|
+
"aria-label": `${afterLabel} value`,
|
|
71
|
+
children: afterContent
|
|
72
|
+
})]
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function TimelineFooter({ reason, source }) {
|
|
78
|
+
if (!reason && !source) return null;
|
|
79
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
80
|
+
className: "mt-3 pt-3 border-t border-slate-100 space-y-2 text-xs text-slate-500",
|
|
81
|
+
children: [reason && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
82
|
+
className: "font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5",
|
|
83
|
+
children: "Reason"
|
|
84
|
+
}), reason] }), source && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
85
|
+
className: "font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5",
|
|
86
|
+
children: "Source"
|
|
87
|
+
}), source] })]
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function TimelineEmptyState({ icon, title, description }) {
|
|
91
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
92
|
+
className: "py-16 text-center",
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
95
|
+
className: "mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-xl bg-slate-50",
|
|
96
|
+
children: icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Clock, {
|
|
97
|
+
size: 22,
|
|
98
|
+
className: "text-slate-300",
|
|
99
|
+
"aria-hidden": "true"
|
|
100
|
+
})
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
103
|
+
className: "text-sm font-semibold text-slate-500",
|
|
104
|
+
children: title
|
|
105
|
+
}),
|
|
106
|
+
description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
107
|
+
className: "text-xs text-slate-400 mt-1",
|
|
108
|
+
children: description
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
exports.Timeline = Timeline;
|
|
115
|
+
exports.TimelineEmptyState = TimelineEmptyState;
|
|
116
|
+
exports.TimelineFooter = TimelineFooter;
|
|
117
|
+
exports.TimelineItem = TimelineItem;
|
|
118
|
+
exports.TimelineValueCard = TimelineValueCard;
|
|
119
|
+
|
|
120
|
+
//# sourceMappingURL=index59.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index59.cjs","names":[],"sources":["../src/ui-library/gallery/timeline/Timeline.tsx"],"sourcesContent":["/**\n * Timeline — Design System Components\n *\n * Generic vertical timeline primitives for chronological event display.\n * Purely presentational — no domain logic, no API calls, no state.\n *\n * Components:\n * Timeline — vertical timeline wrapper\n * TimelineItem — single timeline node (dot + connector + card)\n * TimelineValueCard — before/after comparison card\n * TimelineFooter — reason/source footer strip\n * TimelineEmptyState — empty state panel\n *\n * Usage:\n * <Timeline>\n * <TimelineItem isFirst isLast={false}>\n * <div>Header: who + when</div>\n * <div className=\"p-4\">\n * <TimelineValueCard\n * beforeContent={<span>Old value</span>}\n * afterContent={<span>New value</span>}\n * />\n * </div>\n * </TimelineItem>\n * </Timeline>\n */\n\nimport type { ReactNode } from 'react';\nimport { ArrowDown, Clock } from 'lucide-react';\n\n// ── Timeline ──────────────────────────────────────────────────────────────────\n\nexport interface TimelineProps {\n children: ReactNode;\n className?: string;\n}\n\nexport function Timeline({ children, className = '' }: TimelineProps) {\n return <div className={`w-full space-y-0 ${className}`}>{children}</div>;\n}\n\n// ── TimelineItem ──────────────────────────────────────────────────────────────\n\nexport interface TimelineItemProps {\n /** True for the first (newest) item — renders an indigo dot. */\n isFirst: boolean;\n /** True for the last visible item — hides the connector line. */\n isLast: boolean;\n children: ReactNode;\n}\n\nexport function TimelineItem({ isFirst, isLast, children }: TimelineItemProps) {\n return (\n <div className=\"flex gap-3\">\n {/* Spine — decorative, hidden from AT */}\n <div className=\"flex flex-col items-center shrink-0 pt-4\" aria-hidden=\"true\">\n <div className={`w-2.5 h-2.5 rounded-full ring-2 ring-offset-2 shrink-0 ${\n isFirst ? 'bg-brand-blue ring-brand-blue/30' : 'bg-slate-300 ring-slate-100'\n }`} />\n {!isLast && <div className=\"w-px flex-1 bg-slate-200 mt-1.5 min-h-[2rem]\" />}\n </div>\n\n {/* Card */}\n <div className=\"flex-1 min-w-0 pb-5\">\n <div className=\"rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden\">\n {children}\n </div>\n </div>\n </div>\n );\n}\n\n// ── TimelineValueCard ─────────────────────────────────────────────────────────\n\nexport interface TimelineValueCardProps {\n /** Label above the \"before\" block. Default: \"Previous\" */\n beforeLabel?: string;\n /** Label above the \"after\" block. Default: \"Current\" */\n afterLabel?: string;\n /** Content for the old value. */\n beforeContent: ReactNode;\n /** Content for the new value. */\n afterContent: ReactNode;\n /** Optional action (e.g. copy button) next to the before label. */\n beforeAction?: ReactNode;\n /** Optional action next to the after label. */\n afterAction?: ReactNode;\n}\n\nexport function TimelineValueCard({\n beforeLabel = 'Previous',\n afterLabel = 'Current',\n beforeContent,\n afterContent,\n beforeAction,\n afterAction,\n}: TimelineValueCardProps) {\n return (\n <div className=\"rounded-lg border border-slate-200 overflow-hidden\" role=\"group\">\n {/* Previous value */}\n <div className=\"px-3 pt-2.5 pb-3 bg-slate-50\">\n <div className=\"flex items-center gap-1 mb-1.5\">\n <span className=\"text-[10px] font-bold text-slate-400 uppercase tracking-wider\">\n {beforeLabel}\n </span>\n {beforeAction && <span className=\"ml-auto\">{beforeAction}</span>}\n </div>\n <div className=\"text-sm text-slate-500 leading-snug\" aria-label={`${beforeLabel} value`}>\n {beforeContent}\n </div>\n </div>\n\n {/* Separator */}\n <div className=\"flex items-center justify-center py-1.5 border-y border-slate-200 bg-white\" aria-hidden=\"true\">\n <ArrowDown size={12} className=\"text-slate-400\" strokeWidth={2.5} />\n </div>\n\n {/* Current value */}\n <div className=\"px-3 pt-2.5 pb-3 bg-white\">\n <div className=\"flex items-center gap-1 mb-1.5\">\n <span className=\"text-[10px] font-bold text-slate-600 uppercase tracking-wider\">\n {afterLabel}\n </span>\n {afterAction && <span className=\"ml-auto\">{afterAction}</span>}\n </div>\n <div className=\"text-sm font-semibold text-slate-800 leading-snug\" aria-label={`${afterLabel} value`}>\n {afterContent}\n </div>\n </div>\n </div>\n );\n}\n\n// ── TimelineFooter ────────────────────────────────────────────────────────────\n\nexport interface TimelineFooterProps {\n /** Reason text. Rendered when provided. */\n reason?: string | null;\n /** Source label. Rendered when provided. */\n source?: string | null;\n}\n\nexport function TimelineFooter({ reason, source }: TimelineFooterProps) {\n if (!reason && !source) return null;\n return (\n <div className=\"mt-3 pt-3 border-t border-slate-100 space-y-2 text-xs text-slate-500\">\n {reason && (\n <p>\n <span className=\"font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5\">\n Reason\n </span>\n {reason}\n </p>\n )}\n {source && (\n <p>\n <span className=\"font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5\">\n Source\n </span>\n {source}\n </p>\n )}\n </div>\n );\n}\n\n// ── TimelineEmptyState ────────────────────────────────────────────────────────\n\nexport interface TimelineEmptyStateProps {\n icon?: ReactNode;\n title: string;\n description?: string;\n}\n\nexport function TimelineEmptyState({ icon, title, description }: TimelineEmptyStateProps) {\n return (\n <div className=\"py-16 text-center\">\n <div className=\"mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-xl bg-slate-50\">\n {icon ?? <Clock size={22} className=\"text-slate-300\" aria-hidden=\"true\" />}\n </div>\n <p className=\"text-sm font-semibold text-slate-500\">{title}</p>\n {description && (\n <p className=\"text-xs text-slate-400 mt-1\">{description}</p>\n )}\n </div>\n );\n}\n"],"mappings":";;;AAqCA,SAAgB,SAAS,EAAE,UAAU,YAAY,MAAqB;CACpE,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EAAK,WAAW,oBAAoB;EAAc;CAAc,CAAA;AACzE;AAYA,SAAgB,aAAa,EAAE,SAAS,QAAQ,YAA+B;CAC7E,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CAEE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAK,WAAU;GAA2C,eAAY;GAAtE,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAK,WAAW,0DACd,UAAU,qCAAqC,gCAC5C,CAAA,GACJ,CAAC,UAAU,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAK,WAAU,+CAAgD,CAAA,CACxE;EAGL,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,WAAU;GACb,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IACZ;GACE,CAAA;EACF,CAAA,CACF;;AAET;AAmBA,SAAgB,kBAAkB,EAChC,cAAc,YACd,aAAa,WACb,eACA,cACA,cACA,eACyB;CACzB,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAAqD,MAAK;EAAzE,UAAA;GAEE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MACb,UAAA;KACG,CAAA,GACL,gBAAgB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAAW,UAAA;KAAmB,CAAA,CAC5D;IACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;KAAK,WAAU;KAAsC,cAAY,GAAG,YAAY;KAC7E,UAAA;IACE,CAAA,CACF;;GAGL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAA6E,eAAY;IACtG,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAA,WAAD;KAAW,MAAM;KAAI,WAAU;KAAiB,aAAa;IAAM,CAAA;GAChE,CAAA;GAGL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MACb,UAAA;KACG,CAAA,GACL,eAAe,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAAW,UAAA;KAAkB,CAAA,CAC1D;IACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;KAAK,WAAU;KAAoD,cAAY,GAAG,WAAW;KAC1F,UAAA;IACE,CAAA,CACF;;EACF;;AAET;AAWA,SAAgB,eAAe,EAAE,QAAQ,UAA+B;CACtE,IAAI,CAAC,UAAU,CAAC,QAAQ,OAAO;CAC/B,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACG,UACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,KAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,WAAU;GAA6E,UAAA;EAEvF,CAAA,GACL,MACA,EAAA,CAAA,GAEJ,UACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,KAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,WAAU;GAA6E,UAAA;EAEvF,CAAA,GACL,MACA,EAAA,CAAA,CAEF;;AAET;AAUA,SAAgB,mBAAmB,EAAE,MAAM,OAAO,eAAwC;CACxF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IACZ,UAAA,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAA,OAAD;KAAO,MAAM;KAAI,WAAU;KAAiB,eAAY;IAAQ,CAAA;GACtE,CAAA;GACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,WAAU;IAAwC,UAAA;GAAS,CAAA;GAC7D,eACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,WAAU;IAA+B,UAAA;GAAe,CAAA;EAE1D;;AAET"}
|
package/lib/index59.mjs
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowDown, Clock } from "lucide-react";
|
|
3
|
+
//#region src/ui-library/gallery/timeline/Timeline.tsx
|
|
4
|
+
function Timeline({ children, className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", {
|
|
6
|
+
className: `w-full space-y-0 ${className}`,
|
|
7
|
+
children
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function TimelineItem({ isFirst, isLast, children }) {
|
|
11
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
12
|
+
className: "flex gap-3",
|
|
13
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
14
|
+
className: "flex flex-col items-center shrink-0 pt-4",
|
|
15
|
+
"aria-hidden": "true",
|
|
16
|
+
children: [/* @__PURE__ */ jsx("div", { className: `w-2.5 h-2.5 rounded-full ring-2 ring-offset-2 shrink-0 ${isFirst ? "bg-brand-blue ring-brand-blue/30" : "bg-slate-300 ring-slate-100"}` }), !isLast && /* @__PURE__ */ jsx("div", { className: "w-px flex-1 bg-slate-200 mt-1.5 min-h-[2rem]" })]
|
|
17
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
18
|
+
className: "flex-1 min-w-0 pb-5",
|
|
19
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: "rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden",
|
|
21
|
+
children
|
|
22
|
+
})
|
|
23
|
+
})]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function TimelineValueCard({ beforeLabel = "Previous", afterLabel = "Current", beforeContent, afterContent, beforeAction, afterAction }) {
|
|
27
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
28
|
+
className: "rounded-lg border border-slate-200 overflow-hidden",
|
|
29
|
+
role: "group",
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsxs("div", {
|
|
32
|
+
className: "px-3 pt-2.5 pb-3 bg-slate-50",
|
|
33
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "flex items-center gap-1 mb-1.5",
|
|
35
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
36
|
+
className: "text-[10px] font-bold text-slate-400 uppercase tracking-wider",
|
|
37
|
+
children: beforeLabel
|
|
38
|
+
}), beforeAction && /* @__PURE__ */ jsx("span", {
|
|
39
|
+
className: "ml-auto",
|
|
40
|
+
children: beforeAction
|
|
41
|
+
})]
|
|
42
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
43
|
+
className: "text-sm text-slate-500 leading-snug",
|
|
44
|
+
"aria-label": `${beforeLabel} value`,
|
|
45
|
+
children: beforeContent
|
|
46
|
+
})]
|
|
47
|
+
}),
|
|
48
|
+
/* @__PURE__ */ jsx("div", {
|
|
49
|
+
className: "flex items-center justify-center py-1.5 border-y border-slate-200 bg-white",
|
|
50
|
+
"aria-hidden": "true",
|
|
51
|
+
children: /* @__PURE__ */ jsx(ArrowDown, {
|
|
52
|
+
size: 12,
|
|
53
|
+
className: "text-slate-400",
|
|
54
|
+
strokeWidth: 2.5
|
|
55
|
+
})
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ jsxs("div", {
|
|
58
|
+
className: "px-3 pt-2.5 pb-3 bg-white",
|
|
59
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
60
|
+
className: "flex items-center gap-1 mb-1.5",
|
|
61
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
62
|
+
className: "text-[10px] font-bold text-slate-600 uppercase tracking-wider",
|
|
63
|
+
children: afterLabel
|
|
64
|
+
}), afterAction && /* @__PURE__ */ jsx("span", {
|
|
65
|
+
className: "ml-auto",
|
|
66
|
+
children: afterAction
|
|
67
|
+
})]
|
|
68
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
69
|
+
className: "text-sm font-semibold text-slate-800 leading-snug",
|
|
70
|
+
"aria-label": `${afterLabel} value`,
|
|
71
|
+
children: afterContent
|
|
72
|
+
})]
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function TimelineFooter({ reason, source }) {
|
|
78
|
+
if (!reason && !source) return null;
|
|
79
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
80
|
+
className: "mt-3 pt-3 border-t border-slate-100 space-y-2 text-xs text-slate-500",
|
|
81
|
+
children: [reason && /* @__PURE__ */ jsxs("p", { children: [/* @__PURE__ */ jsx("span", {
|
|
82
|
+
className: "font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5",
|
|
83
|
+
children: "Reason"
|
|
84
|
+
}), reason] }), source && /* @__PURE__ */ jsxs("p", { children: [/* @__PURE__ */ jsx("span", {
|
|
85
|
+
className: "font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5",
|
|
86
|
+
children: "Source"
|
|
87
|
+
}), source] })]
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function TimelineEmptyState({ icon, title, description }) {
|
|
91
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
92
|
+
className: "py-16 text-center",
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx("div", {
|
|
95
|
+
className: "mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-xl bg-slate-50",
|
|
96
|
+
children: icon ?? /* @__PURE__ */ jsx(Clock, {
|
|
97
|
+
size: 22,
|
|
98
|
+
className: "text-slate-300",
|
|
99
|
+
"aria-hidden": "true"
|
|
100
|
+
})
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ jsx("p", {
|
|
103
|
+
className: "text-sm font-semibold text-slate-500",
|
|
104
|
+
children: title
|
|
105
|
+
}),
|
|
106
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
107
|
+
className: "text-xs text-slate-400 mt-1",
|
|
108
|
+
children: description
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { Timeline, TimelineEmptyState, TimelineFooter, TimelineItem, TimelineValueCard };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=index59.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index59.mjs","names":[],"sources":["../src/ui-library/gallery/timeline/Timeline.tsx"],"sourcesContent":["/**\n * Timeline — Design System Components\n *\n * Generic vertical timeline primitives for chronological event display.\n * Purely presentational — no domain logic, no API calls, no state.\n *\n * Components:\n * Timeline — vertical timeline wrapper\n * TimelineItem — single timeline node (dot + connector + card)\n * TimelineValueCard — before/after comparison card\n * TimelineFooter — reason/source footer strip\n * TimelineEmptyState — empty state panel\n *\n * Usage:\n * <Timeline>\n * <TimelineItem isFirst isLast={false}>\n * <div>Header: who + when</div>\n * <div className=\"p-4\">\n * <TimelineValueCard\n * beforeContent={<span>Old value</span>}\n * afterContent={<span>New value</span>}\n * />\n * </div>\n * </TimelineItem>\n * </Timeline>\n */\n\nimport type { ReactNode } from 'react';\nimport { ArrowDown, Clock } from 'lucide-react';\n\n// ── Timeline ──────────────────────────────────────────────────────────────────\n\nexport interface TimelineProps {\n children: ReactNode;\n className?: string;\n}\n\nexport function Timeline({ children, className = '' }: TimelineProps) {\n return <div className={`w-full space-y-0 ${className}`}>{children}</div>;\n}\n\n// ── TimelineItem ──────────────────────────────────────────────────────────────\n\nexport interface TimelineItemProps {\n /** True for the first (newest) item — renders an indigo dot. */\n isFirst: boolean;\n /** True for the last visible item — hides the connector line. */\n isLast: boolean;\n children: ReactNode;\n}\n\nexport function TimelineItem({ isFirst, isLast, children }: TimelineItemProps) {\n return (\n <div className=\"flex gap-3\">\n {/* Spine — decorative, hidden from AT */}\n <div className=\"flex flex-col items-center shrink-0 pt-4\" aria-hidden=\"true\">\n <div className={`w-2.5 h-2.5 rounded-full ring-2 ring-offset-2 shrink-0 ${\n isFirst ? 'bg-brand-blue ring-brand-blue/30' : 'bg-slate-300 ring-slate-100'\n }`} />\n {!isLast && <div className=\"w-px flex-1 bg-slate-200 mt-1.5 min-h-[2rem]\" />}\n </div>\n\n {/* Card */}\n <div className=\"flex-1 min-w-0 pb-5\">\n <div className=\"rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden\">\n {children}\n </div>\n </div>\n </div>\n );\n}\n\n// ── TimelineValueCard ─────────────────────────────────────────────────────────\n\nexport interface TimelineValueCardProps {\n /** Label above the \"before\" block. Default: \"Previous\" */\n beforeLabel?: string;\n /** Label above the \"after\" block. Default: \"Current\" */\n afterLabel?: string;\n /** Content for the old value. */\n beforeContent: ReactNode;\n /** Content for the new value. */\n afterContent: ReactNode;\n /** Optional action (e.g. copy button) next to the before label. */\n beforeAction?: ReactNode;\n /** Optional action next to the after label. */\n afterAction?: ReactNode;\n}\n\nexport function TimelineValueCard({\n beforeLabel = 'Previous',\n afterLabel = 'Current',\n beforeContent,\n afterContent,\n beforeAction,\n afterAction,\n}: TimelineValueCardProps) {\n return (\n <div className=\"rounded-lg border border-slate-200 overflow-hidden\" role=\"group\">\n {/* Previous value */}\n <div className=\"px-3 pt-2.5 pb-3 bg-slate-50\">\n <div className=\"flex items-center gap-1 mb-1.5\">\n <span className=\"text-[10px] font-bold text-slate-400 uppercase tracking-wider\">\n {beforeLabel}\n </span>\n {beforeAction && <span className=\"ml-auto\">{beforeAction}</span>}\n </div>\n <div className=\"text-sm text-slate-500 leading-snug\" aria-label={`${beforeLabel} value`}>\n {beforeContent}\n </div>\n </div>\n\n {/* Separator */}\n <div className=\"flex items-center justify-center py-1.5 border-y border-slate-200 bg-white\" aria-hidden=\"true\">\n <ArrowDown size={12} className=\"text-slate-400\" strokeWidth={2.5} />\n </div>\n\n {/* Current value */}\n <div className=\"px-3 pt-2.5 pb-3 bg-white\">\n <div className=\"flex items-center gap-1 mb-1.5\">\n <span className=\"text-[10px] font-bold text-slate-600 uppercase tracking-wider\">\n {afterLabel}\n </span>\n {afterAction && <span className=\"ml-auto\">{afterAction}</span>}\n </div>\n <div className=\"text-sm font-semibold text-slate-800 leading-snug\" aria-label={`${afterLabel} value`}>\n {afterContent}\n </div>\n </div>\n </div>\n );\n}\n\n// ── TimelineFooter ────────────────────────────────────────────────────────────\n\nexport interface TimelineFooterProps {\n /** Reason text. Rendered when provided. */\n reason?: string | null;\n /** Source label. Rendered when provided. */\n source?: string | null;\n}\n\nexport function TimelineFooter({ reason, source }: TimelineFooterProps) {\n if (!reason && !source) return null;\n return (\n <div className=\"mt-3 pt-3 border-t border-slate-100 space-y-2 text-xs text-slate-500\">\n {reason && (\n <p>\n <span className=\"font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5\">\n Reason\n </span>\n {reason}\n </p>\n )}\n {source && (\n <p>\n <span className=\"font-bold text-slate-400 uppercase tracking-wider text-[10px] block mb-0.5\">\n Source\n </span>\n {source}\n </p>\n )}\n </div>\n );\n}\n\n// ── TimelineEmptyState ────────────────────────────────────────────────────────\n\nexport interface TimelineEmptyStateProps {\n icon?: ReactNode;\n title: string;\n description?: string;\n}\n\nexport function TimelineEmptyState({ icon, title, description }: TimelineEmptyStateProps) {\n return (\n <div className=\"py-16 text-center\">\n <div className=\"mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-xl bg-slate-50\">\n {icon ?? <Clock size={22} className=\"text-slate-300\" aria-hidden=\"true\" />}\n </div>\n <p className=\"text-sm font-semibold text-slate-500\">{title}</p>\n {description && (\n <p className=\"text-xs text-slate-400 mt-1\">{description}</p>\n )}\n </div>\n );\n}\n"],"mappings":";;;AAqCA,SAAgB,SAAS,EAAE,UAAU,YAAY,MAAqB;CACpE,OAAO,oBAAC,OAAD;EAAK,WAAW,oBAAoB;EAAc;CAAc,CAAA;AACzE;AAYA,SAAgB,aAAa,EAAE,SAAS,QAAQ,YAA+B;CAC7E,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CAEE,qBAAC,OAAD;GAAK,WAAU;GAA2C,eAAY;GAAtE,UAAA,CACE,oBAAC,OAAD,EAAK,WAAW,0DACd,UAAU,qCAAqC,gCAC5C,CAAA,GACJ,CAAC,UAAU,oBAAC,OAAD,EAAK,WAAU,+CAAgD,CAAA,CACxE;EAGL,CAAA,GAAA,oBAAC,OAAD;GAAK,WAAU;GACb,UAAA,oBAAC,OAAD;IAAK,WAAU;IACZ;GACE,CAAA;EACF,CAAA,CACF;;AAET;AAmBA,SAAgB,kBAAkB,EAChC,cAAc,YACd,aAAa,WACb,eACA,cACA,cACA,eACyB;CACzB,OACE,qBAAC,OAAD;EAAK,WAAU;EAAqD,MAAK;EAAzE,UAAA;GAEE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,QAAD;MAAM,WAAU;MACb,UAAA;KACG,CAAA,GACL,gBAAgB,oBAAC,QAAD;MAAM,WAAU;MAAW,UAAA;KAAmB,CAAA,CAC5D;IACL,CAAA,GAAA,oBAAC,OAAD;KAAK,WAAU;KAAsC,cAAY,GAAG,YAAY;KAC7E,UAAA;IACE,CAAA,CACF;;GAGL,oBAAC,OAAD;IAAK,WAAU;IAA6E,eAAY;IACtG,UAAA,oBAAC,WAAD;KAAW,MAAM;KAAI,WAAU;KAAiB,aAAa;IAAM,CAAA;GAChE,CAAA;GAGL,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,QAAD;MAAM,WAAU;MACb,UAAA;KACG,CAAA,GACL,eAAe,oBAAC,QAAD;MAAM,WAAU;MAAW,UAAA;KAAkB,CAAA,CAC1D;IACL,CAAA,GAAA,oBAAC,OAAD;KAAK,WAAU;KAAoD,cAAY,GAAG,WAAW;KAC1F,UAAA;IACE,CAAA,CACF;;EACF;;AAET;AAWA,SAAgB,eAAe,EAAE,QAAQ,UAA+B;CACtE,IAAI,CAAC,UAAU,CAAC,QAAQ,OAAO;CAC/B,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACG,UACC,qBAAC,KAAD,EAAA,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;GAA6E,UAAA;EAEvF,CAAA,GACL,MACA,EAAA,CAAA,GAEJ,UACC,qBAAC,KAAD,EAAA,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;GAA6E,UAAA;EAEvF,CAAA,GACL,MACA,EAAA,CAAA,CAEF;;AAET;AAUA,SAAgB,mBAAmB,EAAE,MAAM,OAAO,eAAwC;CACxF,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,QAAQ,oBAAC,OAAD;KAAO,MAAM;KAAI,WAAU;KAAiB,eAAY;IAAQ,CAAA;GACtE,CAAA;GACL,oBAAC,KAAD;IAAG,WAAU;IAAwC,UAAA;GAAS,CAAA;GAC7D,eACC,oBAAC,KAAD;IAAG,WAAU;IAA+B,UAAA;GAAe,CAAA;EAE1D;;AAET"}
|
package/lib/index6.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
2
|
+
//#region src/ui-library/gallery/spinner/Spinner.tsx
|
|
3
|
+
var SIZE_TRACK = {
|
|
4
|
+
sm: "h-4 w-4 border-2",
|
|
5
|
+
md: "h-6 w-6 border-2",
|
|
6
|
+
lg: "h-9 w-9 border-[3px]"
|
|
7
|
+
};
|
|
8
|
+
var SIZE_TEXT = {
|
|
9
|
+
sm: "text-xs",
|
|
10
|
+
md: "text-sm",
|
|
11
|
+
lg: "text-base"
|
|
12
|
+
};
|
|
13
|
+
function Spinner({ size = "md", label = "Loading…", labelHidden = false, className = "" }) {
|
|
14
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15
|
+
role: "status",
|
|
16
|
+
className: `inline-flex items-center gap-2 ${className}`,
|
|
17
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
18
|
+
"aria-hidden": "true",
|
|
19
|
+
className: ["inline-block animate-spin rounded-full border-slate-200 border-t-brand-blue motion-reduce:animate-none", SIZE_TRACK[size]].join(" ")
|
|
20
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
21
|
+
className: labelHidden ? "sr-only" : `font-medium text-slate-500 ${SIZE_TEXT[size]}`,
|
|
22
|
+
children: label
|
|
23
|
+
})]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.Spinner = Spinner;
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=index6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index6.cjs","names":[],"sources":["../src/ui-library/gallery/spinner/Spinner.tsx"],"sourcesContent":["/**\n * Spinner — Design System Component\n *\n * An indeterminate loading indicator. Purely presentational.\n *\n * Sizes: sm | md | lg\n *\n * Usage:\n * - Inline: inside a button or alongside text\n * - Standalone: centered in a container while content loads\n *\n * Accessibility:\n * - Renders a <span role=\"status\"> that announces label to screen readers\n * - label is required and should describe what is loading\n * - Respects prefers-reduced-motion: animation is suppressed, label stays\n */\n\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n /** Accessible label — required for screen readers */\n label?: string;\n /** Hide the visible label text, keep it for screen readers only */\n labelHidden?: boolean;\n className?: string;\n}\n\nconst SIZE_TRACK: Record<SpinnerSize, string> = {\n sm: 'h-4 w-4 border-2',\n md: 'h-6 w-6 border-2',\n lg: 'h-9 w-9 border-[3px]',\n};\n\nconst SIZE_TEXT: Record<SpinnerSize, string> = {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n};\n\nexport function Spinner({\n size = 'md',\n label = 'Loading…',\n labelHidden = false,\n className = '',\n}: SpinnerProps) {\n return (\n <span\n role=\"status\"\n className={`inline-flex items-center gap-2 ${className}`}\n >\n <span\n aria-hidden=\"true\"\n className={[\n 'inline-block animate-spin rounded-full border-slate-200 border-t-brand-blue motion-reduce:animate-none',\n SIZE_TRACK[size],\n ].join(' ')}\n />\n <span className={labelHidden ? 'sr-only' : `font-medium text-slate-500 ${SIZE_TEXT[size]}`}>\n {label}\n </span>\n </span>\n );\n}\n"],"mappings":";;AA4BA,IAAM,aAA0C;CAC9C,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,YAAyC;CAC7C,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAgB,QAAQ,EACtB,OAAO,MACP,QAAQ,YACR,cAAc,OACd,YAAY,MACG;CACf,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;EACE,MAAK;EACL,WAAW,kCAAkC;EAF/C,UAAA,CAIE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GACE,eAAY;GACZ,WAAW,CACT,0GACA,WAAW,KACb,CAAC,CAAC,KAAK,GAAG;EACX,CAAA,GACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,WAAW,cAAc,YAAY,8BAA8B,UAAU;GAChF,UAAA;EACG,CAAA,CACF;;AAEV"}
|
package/lib/index6.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
//#region src/ui-library/gallery/spinner/Spinner.tsx
|
|
3
|
+
var SIZE_TRACK = {
|
|
4
|
+
sm: "h-4 w-4 border-2",
|
|
5
|
+
md: "h-6 w-6 border-2",
|
|
6
|
+
lg: "h-9 w-9 border-[3px]"
|
|
7
|
+
};
|
|
8
|
+
var SIZE_TEXT = {
|
|
9
|
+
sm: "text-xs",
|
|
10
|
+
md: "text-sm",
|
|
11
|
+
lg: "text-base"
|
|
12
|
+
};
|
|
13
|
+
function Spinner({ size = "md", label = "Loading…", labelHidden = false, className = "" }) {
|
|
14
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
15
|
+
role: "status",
|
|
16
|
+
className: `inline-flex items-center gap-2 ${className}`,
|
|
17
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
18
|
+
"aria-hidden": "true",
|
|
19
|
+
className: ["inline-block animate-spin rounded-full border-slate-200 border-t-brand-blue motion-reduce:animate-none", SIZE_TRACK[size]].join(" ")
|
|
20
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
21
|
+
className: labelHidden ? "sr-only" : `font-medium text-slate-500 ${SIZE_TEXT[size]}`,
|
|
22
|
+
children: label
|
|
23
|
+
})]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Spinner };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=index6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index6.mjs","names":[],"sources":["../src/ui-library/gallery/spinner/Spinner.tsx"],"sourcesContent":["/**\n * Spinner — Design System Component\n *\n * An indeterminate loading indicator. Purely presentational.\n *\n * Sizes: sm | md | lg\n *\n * Usage:\n * - Inline: inside a button or alongside text\n * - Standalone: centered in a container while content loads\n *\n * Accessibility:\n * - Renders a <span role=\"status\"> that announces label to screen readers\n * - label is required and should describe what is loading\n * - Respects prefers-reduced-motion: animation is suppressed, label stays\n */\n\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n /** Accessible label — required for screen readers */\n label?: string;\n /** Hide the visible label text, keep it for screen readers only */\n labelHidden?: boolean;\n className?: string;\n}\n\nconst SIZE_TRACK: Record<SpinnerSize, string> = {\n sm: 'h-4 w-4 border-2',\n md: 'h-6 w-6 border-2',\n lg: 'h-9 w-9 border-[3px]',\n};\n\nconst SIZE_TEXT: Record<SpinnerSize, string> = {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n};\n\nexport function Spinner({\n size = 'md',\n label = 'Loading…',\n labelHidden = false,\n className = '',\n}: SpinnerProps) {\n return (\n <span\n role=\"status\"\n className={`inline-flex items-center gap-2 ${className}`}\n >\n <span\n aria-hidden=\"true\"\n className={[\n 'inline-block animate-spin rounded-full border-slate-200 border-t-brand-blue motion-reduce:animate-none',\n SIZE_TRACK[size],\n ].join(' ')}\n />\n <span className={labelHidden ? 'sr-only' : `font-medium text-slate-500 ${SIZE_TEXT[size]}`}>\n {label}\n </span>\n </span>\n );\n}\n"],"mappings":";;AA4BA,IAAM,aAA0C;CAC9C,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,YAAyC;CAC7C,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAgB,QAAQ,EACtB,OAAO,MACP,QAAQ,YACR,cAAc,OACd,YAAY,MACG;CACf,OACE,qBAAC,QAAD;EACE,MAAK;EACL,WAAW,kCAAkC;EAF/C,UAAA,CAIE,oBAAC,QAAD;GACE,eAAY;GACZ,WAAW,CACT,0GACA,WAAW,KACb,CAAC,CAAC,KAAK,GAAG;EACX,CAAA,GACD,oBAAC,QAAD;GAAM,WAAW,cAAc,YAAY,8BAA8B,UAAU;GAChF,UAAA;EACG,CAAA,CACF;;AAEV"}
|
package/lib/index60.cjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
2
|
+
//#region src/ui-library/gallery/empty-state/EmptyState.tsx
|
|
3
|
+
function EmptyState({ title, hint, icon, action, className = "" }) {
|
|
4
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5
|
+
className: [
|
|
6
|
+
"flex flex-col items-center justify-center gap-2",
|
|
7
|
+
"rounded-lg border border-brand-sky/20 bg-brand-sky/[0.04]",
|
|
8
|
+
"px-6 py-12 text-center",
|
|
9
|
+
className
|
|
10
|
+
].filter(Boolean).join(" "),
|
|
11
|
+
children: [
|
|
12
|
+
icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13
|
+
className: "mb-1 text-brand-sky/50",
|
|
14
|
+
children: icon
|
|
15
|
+
}),
|
|
16
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
17
|
+
className: "text-sm font-bold text-slate-600",
|
|
18
|
+
children: title
|
|
19
|
+
}),
|
|
20
|
+
hint && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
21
|
+
className: "max-w-sm text-xs font-medium text-slate-400",
|
|
22
|
+
children: hint
|
|
23
|
+
}),
|
|
24
|
+
action && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
25
|
+
className: "mt-3",
|
|
26
|
+
children: action
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
exports.EmptyState = EmptyState;
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=index60.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index60.cjs","names":[],"sources":["../src/ui-library/gallery/empty-state/EmptyState.tsx"],"sourcesContent":["/**\n * EmptyState — Design System Component\n *\n * Graceful zero-data placeholder for lists, tables, and content areas.\n * Purely presentational — no state, no API calls, no domain logic.\n *\n * Matches the visual design of the production EmptyState in shared/components/ui.tsx.\n * Adds an optional `action` slot for call-to-action buttons.\n *\n * Accessibility:\n * - Plain presentational markup — no interactive elements by default.\n * - The `icon` should be aria-hidden=\"true\" at the call site (decorative).\n * - When replacing a dynamic list, wrap the parent in aria-live=\"polite\"\n * so screen readers announce the empty state on content change.\n *\n * Usage:\n * <EmptyState title=\"No employees found\" />\n * <EmptyState\n * icon={<Users size={32} aria-hidden=\"true\" />}\n * title=\"No team members yet\"\n * hint=\"Add your first employee to get started.\"\n * action={<button className={btnPrimary} onClick={openCreate}>Add Employee</button>}\n * />\n */\n\nimport type { ReactNode } from 'react';\n\nexport interface EmptyStateProps {\n /** Required title / primary message. */\n title: string;\n /** Optional secondary guidance text. */\n hint?: string;\n /** Optional icon rendered above the title. Use Lucide icons (size 28–40). Mark aria-hidden=\"true\". */\n icon?: ReactNode;\n /** Optional action slot — rendered below the hint. Typically a Button or link. */\n action?: ReactNode;\n /** Additional class on the root container. */\n className?: string;\n}\n\nexport function EmptyState({ title, hint, icon, action, className = '' }: EmptyStateProps) {\n return (\n <div\n className={[\n 'flex flex-col items-center justify-center gap-2',\n 'rounded-lg border border-brand-sky/20 bg-brand-sky/[0.04]',\n 'px-6 py-12 text-center',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {icon && (\n <div className=\"mb-1 text-brand-sky/50\">\n {icon}\n </div>\n )}\n <div className=\"text-sm font-bold text-slate-600\">{title}</div>\n {hint && (\n <div className=\"max-w-sm text-xs font-medium text-slate-400\">{hint}</div>\n )}\n {action && (\n <div className=\"mt-3\">\n {action}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;AAwCA,SAAgB,WAAW,EAAE,OAAO,MAAM,MAAM,QAAQ,YAAY,MAAuB;CACzF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EACE,WAAW;GACT;GACA;GACA;GACA;EACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EARb,UAAA;GAUG,QACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IACZ,UAAA;GACE,CAAA;GAEP,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAAoC,UAAA;GAAW,CAAA;GAC7D,QACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAA+C,UAAA;GAAU,CAAA;GAEzE,UACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IACZ,UAAA;GACE,CAAA;EAEJ;;AAET"}
|
package/lib/index60.mjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
//#region src/ui-library/gallery/empty-state/EmptyState.tsx
|
|
3
|
+
function EmptyState({ title, hint, icon, action, className = "" }) {
|
|
4
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
5
|
+
className: [
|
|
6
|
+
"flex flex-col items-center justify-center gap-2",
|
|
7
|
+
"rounded-lg border border-brand-sky/20 bg-brand-sky/[0.04]",
|
|
8
|
+
"px-6 py-12 text-center",
|
|
9
|
+
className
|
|
10
|
+
].filter(Boolean).join(" "),
|
|
11
|
+
children: [
|
|
12
|
+
icon && /* @__PURE__ */ jsx("div", {
|
|
13
|
+
className: "mb-1 text-brand-sky/50",
|
|
14
|
+
children: icon
|
|
15
|
+
}),
|
|
16
|
+
/* @__PURE__ */ jsx("div", {
|
|
17
|
+
className: "text-sm font-bold text-slate-600",
|
|
18
|
+
children: title
|
|
19
|
+
}),
|
|
20
|
+
hint && /* @__PURE__ */ jsx("div", {
|
|
21
|
+
className: "max-w-sm text-xs font-medium text-slate-400",
|
|
22
|
+
children: hint
|
|
23
|
+
}),
|
|
24
|
+
action && /* @__PURE__ */ jsx("div", {
|
|
25
|
+
className: "mt-3",
|
|
26
|
+
children: action
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { EmptyState };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=index60.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index60.mjs","names":[],"sources":["../src/ui-library/gallery/empty-state/EmptyState.tsx"],"sourcesContent":["/**\n * EmptyState — Design System Component\n *\n * Graceful zero-data placeholder for lists, tables, and content areas.\n * Purely presentational — no state, no API calls, no domain logic.\n *\n * Matches the visual design of the production EmptyState in shared/components/ui.tsx.\n * Adds an optional `action` slot for call-to-action buttons.\n *\n * Accessibility:\n * - Plain presentational markup — no interactive elements by default.\n * - The `icon` should be aria-hidden=\"true\" at the call site (decorative).\n * - When replacing a dynamic list, wrap the parent in aria-live=\"polite\"\n * so screen readers announce the empty state on content change.\n *\n * Usage:\n * <EmptyState title=\"No employees found\" />\n * <EmptyState\n * icon={<Users size={32} aria-hidden=\"true\" />}\n * title=\"No team members yet\"\n * hint=\"Add your first employee to get started.\"\n * action={<button className={btnPrimary} onClick={openCreate}>Add Employee</button>}\n * />\n */\n\nimport type { ReactNode } from 'react';\n\nexport interface EmptyStateProps {\n /** Required title / primary message. */\n title: string;\n /** Optional secondary guidance text. */\n hint?: string;\n /** Optional icon rendered above the title. Use Lucide icons (size 28–40). Mark aria-hidden=\"true\". */\n icon?: ReactNode;\n /** Optional action slot — rendered below the hint. Typically a Button or link. */\n action?: ReactNode;\n /** Additional class on the root container. */\n className?: string;\n}\n\nexport function EmptyState({ title, hint, icon, action, className = '' }: EmptyStateProps) {\n return (\n <div\n className={[\n 'flex flex-col items-center justify-center gap-2',\n 'rounded-lg border border-brand-sky/20 bg-brand-sky/[0.04]',\n 'px-6 py-12 text-center',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {icon && (\n <div className=\"mb-1 text-brand-sky/50\">\n {icon}\n </div>\n )}\n <div className=\"text-sm font-bold text-slate-600\">{title}</div>\n {hint && (\n <div className=\"max-w-sm text-xs font-medium text-slate-400\">{hint}</div>\n )}\n {action && (\n <div className=\"mt-3\">\n {action}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;AAwCA,SAAgB,WAAW,EAAE,OAAO,MAAM,MAAM,QAAQ,YAAY,MAAuB;CACzF,OACE,qBAAC,OAAD;EACE,WAAW;GACT;GACA;GACA;GACA;EACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EARb,UAAA;GAUG,QACC,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA;GACE,CAAA;GAEP,oBAAC,OAAD;IAAK,WAAU;IAAoC,UAAA;GAAW,CAAA;GAC7D,QACC,oBAAC,OAAD;IAAK,WAAU;IAA+C,UAAA;GAAU,CAAA;GAEzE,UACC,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA;GACE,CAAA;EAEJ;;AAET"}
|
package/lib/index61.cjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const require_Avatar = require("./index8.cjs");
|
|
2
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
3
|
+
//#region src/ui-library/gallery/employee-card/EmployeeCard.tsx
|
|
4
|
+
function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
6
|
+
className: `rounded-2xl border border-slate-200 bg-white shadow-sm overflow-hidden ${className}`,
|
|
7
|
+
"aria-label": `${name}${role ? ", " + role : ""}`,
|
|
8
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9
|
+
className: "h-1.5 bg-gradient-to-r from-brand-navy to-brand-blue",
|
|
10
|
+
"aria-hidden": "true"
|
|
11
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
12
|
+
className: "p-4 space-y-3",
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
15
|
+
className: "flex items-start gap-3",
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Avatar.Avatar, {
|
|
18
|
+
name,
|
|
19
|
+
src: avatarSrc,
|
|
20
|
+
size: "lg"
|
|
21
|
+
}),
|
|
22
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
23
|
+
className: "min-w-0 flex-1",
|
|
24
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
25
|
+
className: "text-sm font-bold text-slate-900 truncate",
|
|
26
|
+
children: name
|
|
27
|
+
}), role && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
28
|
+
className: "text-xs font-medium text-slate-500 truncate",
|
|
29
|
+
children: role
|
|
30
|
+
})]
|
|
31
|
+
}),
|
|
32
|
+
status && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
33
|
+
className: "shrink-0",
|
|
34
|
+
children: status
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
}),
|
|
38
|
+
meta && meta.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dl", {
|
|
39
|
+
className: "divide-y divide-slate-100 text-xs",
|
|
40
|
+
children: meta.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
41
|
+
className: "flex items-center justify-between py-1.5",
|
|
42
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
|
|
43
|
+
className: "font-semibold text-slate-400",
|
|
44
|
+
children: row.label
|
|
45
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
46
|
+
className: "font-semibold text-slate-700 text-right",
|
|
47
|
+
children: row.value
|
|
48
|
+
})]
|
|
49
|
+
}, row.label))
|
|
50
|
+
}),
|
|
51
|
+
actions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
52
|
+
className: "flex items-center gap-2 pt-1 border-t border-slate-100",
|
|
53
|
+
children: actions
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
})]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
exports.EmployeeCard = EmployeeCard;
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=index61.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index61.cjs","names":[],"sources":["../src/ui-library/gallery/employee-card/EmployeeCard.tsx"],"sourcesContent":["/**\n * EmployeeCard — Design System Component\n *\n * A compact identity card for displaying a person's avatar, name,\n * role/title, optional metadata rows, optional status badge, and\n * optional action slot. Domain-free — no personnel-module dependencies.\n *\n * Based on the card pattern in approvals/components/manage-employees/EmployeeCard.tsx\n * but extracted as a generic PersonCard primitive.\n *\n * Accessibility:\n * - <article> semantic for an independent card unit\n * - Avatar image/initials have appropriate alt/aria-label\n * - Action buttons should have aria-label\n */\n\nimport type { ReactNode } from 'react';\nimport { Avatar } from '../avatar/Avatar';\n\nexport interface EmployeeCardMeta {\n label: string;\n value: ReactNode;\n}\n\nexport interface EmployeeCardProps {\n name: string;\n role?: string;\n /** Optional avatar image src — falls back to initials */\n avatarSrc?: string | null;\n /** Status badge slot (e.g. <StatusBadge tone=\"success\">Active</StatusBadge>) */\n status?: ReactNode;\n /** Key-value metadata rows below the name/role */\n meta?: EmployeeCardMeta[];\n /** Optional action slot (bottom of card) */\n actions?: ReactNode;\n className?: string;\n}\n\nexport function EmployeeCard({\n name,\n role,\n avatarSrc,\n status,\n meta,\n actions,\n className = '',\n}: EmployeeCardProps) {\n return (\n <article\n className={`rounded-2xl border border-slate-200 bg-white shadow-sm overflow-hidden ${className}`}\n aria-label={`${name}${role ? ', ' + role : ''}`}\n >\n {/* Brand accent strip */}\n <div className=\"h-1.5 bg-gradient-to-r from-brand-navy to-brand-blue\" aria-hidden=\"true\" />\n\n <div className=\"p-4 space-y-3\">\n {/* Identity row */}\n <div className=\"flex items-start gap-3\">\n <Avatar name={name} src={avatarSrc} size=\"lg\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-bold text-slate-900 truncate\">{name}</p>\n {role && <p className=\"text-xs font-medium text-slate-500 truncate\">{role}</p>}\n </div>\n {status && <div className=\"shrink-0\">{status}</div>}\n </div>\n\n {/* Metadata */}\n {meta && meta.length > 0 && (\n <dl className=\"divide-y divide-slate-100 text-xs\">\n {meta.map((row) => (\n <div key={row.label} className=\"flex items-center justify-between py-1.5\">\n <dt className=\"font-semibold text-slate-400\">{row.label}</dt>\n <dd className=\"font-semibold text-slate-700 text-right\">{row.value}</dd>\n </div>\n ))}\n </dl>\n )}\n\n {/* Actions */}\n {actions && (\n <div className=\"flex items-center gap-2 pt-1 border-t border-slate-100\">\n {actions}\n </div>\n )}\n </div>\n </article>\n );\n}\n"],"mappings":";;;AAsCA,SAAgB,aAAa,EAC3B,MACA,MACA,WACA,QACA,MACA,SACA,YAAY,MACQ;CACpB,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;EACE,WAAW,0EAA0E;EACrF,cAAY,GAAG,OAAO,OAAO,OAAO,OAAO;EAF7C,UAAA,CAKE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,WAAU;GAAuD,eAAY;EAAQ,CAAA,GAE1F,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IAEE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,eAAA,QAAD;OAAc;OAAM,KAAK;OAAW,MAAK;MAAM,CAAA;MAC/C,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;QAAG,WAAU;QAA6C,UAAA;OAAQ,CAAA,GACjE,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;QAAG,WAAU;QAA+C,UAAA;OAAQ,CAAA,CAC1E;;MACJ,UAAU,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAY,UAAA;MAAY,CAAA;KAC/C;;IAGJ,QAAQ,KAAK,SAAS,KACrB,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;KAAI,WAAU;KACX,UAAA,KAAK,KAAK,QACT,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAqB,WAAU;MAA/B,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;OAAI,WAAU;OAAgC,UAAA,IAAI;MAAU,CAAA,GAC5D,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;OAAI,WAAU;OAA2C,UAAA,IAAI;MAAU,CAAA,CACpE;KAHK,GAAA,IAAI,KAGT,CACN;IACC,CAAA;IAIL,WACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;KAAK,WAAU;KACZ,UAAA;IACE,CAAA;GAEJ;EACE,CAAA,CAAA;;AAEb"}
|
package/lib/index61.mjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Avatar } from "./index8.mjs";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/ui-library/gallery/employee-card/EmployeeCard.tsx
|
|
4
|
+
function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("article", {
|
|
6
|
+
className: `rounded-2xl border border-slate-200 bg-white shadow-sm overflow-hidden ${className}`,
|
|
7
|
+
"aria-label": `${name}${role ? ", " + role : ""}`,
|
|
8
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
9
|
+
className: "h-1.5 bg-gradient-to-r from-brand-navy to-brand-blue",
|
|
10
|
+
"aria-hidden": "true"
|
|
11
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
12
|
+
className: "p-4 space-y-3",
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ jsxs("div", {
|
|
15
|
+
className: "flex items-start gap-3",
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ jsx(Avatar, {
|
|
18
|
+
name,
|
|
19
|
+
src: avatarSrc,
|
|
20
|
+
size: "lg"
|
|
21
|
+
}),
|
|
22
|
+
/* @__PURE__ */ jsxs("div", {
|
|
23
|
+
className: "min-w-0 flex-1",
|
|
24
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
25
|
+
className: "text-sm font-bold text-slate-900 truncate",
|
|
26
|
+
children: name
|
|
27
|
+
}), role && /* @__PURE__ */ jsx("p", {
|
|
28
|
+
className: "text-xs font-medium text-slate-500 truncate",
|
|
29
|
+
children: role
|
|
30
|
+
})]
|
|
31
|
+
}),
|
|
32
|
+
status && /* @__PURE__ */ jsx("div", {
|
|
33
|
+
className: "shrink-0",
|
|
34
|
+
children: status
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
}),
|
|
38
|
+
meta && meta.length > 0 && /* @__PURE__ */ jsx("dl", {
|
|
39
|
+
className: "divide-y divide-slate-100 text-xs",
|
|
40
|
+
children: meta.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
41
|
+
className: "flex items-center justify-between py-1.5",
|
|
42
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
43
|
+
className: "font-semibold text-slate-400",
|
|
44
|
+
children: row.label
|
|
45
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
46
|
+
className: "font-semibold text-slate-700 text-right",
|
|
47
|
+
children: row.value
|
|
48
|
+
})]
|
|
49
|
+
}, row.label))
|
|
50
|
+
}),
|
|
51
|
+
actions && /* @__PURE__ */ jsx("div", {
|
|
52
|
+
className: "flex items-center gap-2 pt-1 border-t border-slate-100",
|
|
53
|
+
children: actions
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
})]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { EmployeeCard };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=index61.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index61.mjs","names":[],"sources":["../src/ui-library/gallery/employee-card/EmployeeCard.tsx"],"sourcesContent":["/**\n * EmployeeCard — Design System Component\n *\n * A compact identity card for displaying a person's avatar, name,\n * role/title, optional metadata rows, optional status badge, and\n * optional action slot. Domain-free — no personnel-module dependencies.\n *\n * Based on the card pattern in approvals/components/manage-employees/EmployeeCard.tsx\n * but extracted as a generic PersonCard primitive.\n *\n * Accessibility:\n * - <article> semantic for an independent card unit\n * - Avatar image/initials have appropriate alt/aria-label\n * - Action buttons should have aria-label\n */\n\nimport type { ReactNode } from 'react';\nimport { Avatar } from '../avatar/Avatar';\n\nexport interface EmployeeCardMeta {\n label: string;\n value: ReactNode;\n}\n\nexport interface EmployeeCardProps {\n name: string;\n role?: string;\n /** Optional avatar image src — falls back to initials */\n avatarSrc?: string | null;\n /** Status badge slot (e.g. <StatusBadge tone=\"success\">Active</StatusBadge>) */\n status?: ReactNode;\n /** Key-value metadata rows below the name/role */\n meta?: EmployeeCardMeta[];\n /** Optional action slot (bottom of card) */\n actions?: ReactNode;\n className?: string;\n}\n\nexport function EmployeeCard({\n name,\n role,\n avatarSrc,\n status,\n meta,\n actions,\n className = '',\n}: EmployeeCardProps) {\n return (\n <article\n className={`rounded-2xl border border-slate-200 bg-white shadow-sm overflow-hidden ${className}`}\n aria-label={`${name}${role ? ', ' + role : ''}`}\n >\n {/* Brand accent strip */}\n <div className=\"h-1.5 bg-gradient-to-r from-brand-navy to-brand-blue\" aria-hidden=\"true\" />\n\n <div className=\"p-4 space-y-3\">\n {/* Identity row */}\n <div className=\"flex items-start gap-3\">\n <Avatar name={name} src={avatarSrc} size=\"lg\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-bold text-slate-900 truncate\">{name}</p>\n {role && <p className=\"text-xs font-medium text-slate-500 truncate\">{role}</p>}\n </div>\n {status && <div className=\"shrink-0\">{status}</div>}\n </div>\n\n {/* Metadata */}\n {meta && meta.length > 0 && (\n <dl className=\"divide-y divide-slate-100 text-xs\">\n {meta.map((row) => (\n <div key={row.label} className=\"flex items-center justify-between py-1.5\">\n <dt className=\"font-semibold text-slate-400\">{row.label}</dt>\n <dd className=\"font-semibold text-slate-700 text-right\">{row.value}</dd>\n </div>\n ))}\n </dl>\n )}\n\n {/* Actions */}\n {actions && (\n <div className=\"flex items-center gap-2 pt-1 border-t border-slate-100\">\n {actions}\n </div>\n )}\n </div>\n </article>\n );\n}\n"],"mappings":";;;AAsCA,SAAgB,aAAa,EAC3B,MACA,MACA,WACA,QACA,MACA,SACA,YAAY,MACQ;CACpB,OACE,qBAAC,WAAD;EACE,WAAW,0EAA0E;EACrF,cAAY,GAAG,OAAO,OAAO,OAAO,OAAO;EAF7C,UAAA,CAKE,oBAAC,OAAD;GAAK,WAAU;GAAuD,eAAY;EAAQ,CAAA,GAE1F,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IAEE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,oBAAC,QAAD;OAAc;OAAM,KAAK;OAAW,MAAK;MAAM,CAAA;MAC/C,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,oBAAC,KAAD;QAAG,WAAU;QAA6C,UAAA;OAAQ,CAAA,GACjE,QAAQ,oBAAC,KAAD;QAAG,WAAU;QAA+C,UAAA;OAAQ,CAAA,CAC1E;;MACJ,UAAU,oBAAC,OAAD;OAAK,WAAU;OAAY,UAAA;MAAY,CAAA;KAC/C;;IAGJ,QAAQ,KAAK,SAAS,KACrB,oBAAC,MAAD;KAAI,WAAU;KACX,UAAA,KAAK,KAAK,QACT,qBAAC,OAAD;MAAqB,WAAU;MAA/B,UAAA,CACE,oBAAC,MAAD;OAAI,WAAU;OAAgC,UAAA,IAAI;MAAU,CAAA,GAC5D,oBAAC,MAAD;OAAI,WAAU;OAA2C,UAAA,IAAI;MAAU,CAAA,CACpE;KAHK,GAAA,IAAI,KAGT,CACN;IACC,CAAA;IAIL,WACC,oBAAC,OAAD;KAAK,WAAU;KACZ,UAAA;IACE,CAAA;GAEJ;EACE,CAAA,CAAA;;AAEb"}
|