@conscience-technology/ctds 0.3.4 → 0.4.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.
- package/assets/components/Button/Button.module.css +2 -2
- package/assets/components/EventListItem/EventListItem.module.css +220 -0
- package/assets/components/EventListItem/EventListItem.tsx +205 -0
- package/assets/components/EventListItem/index.ts +8 -0
- package/assets/components/Icon/Icon.tsx +80 -41
- package/assets/components/Kanban/Kanban.module.css +339 -0
- package/assets/components/Kanban/Kanban.tsx +371 -0
- package/assets/components/Kanban/index.ts +10 -0
- package/assets/components/ListItem/ListItem.module.css +91 -211
- package/assets/components/ListItem/ListItem.tsx +130 -154
- package/assets/components/ListItem/index.ts +2 -2
- package/assets/components/MetricCard/MetricCard.module.css +5 -5
- package/assets/components/PageHeader/PageHeader.module.css +109 -0
- package/assets/components/PageHeader/PageHeader.tsx +112 -0
- package/assets/components/PageHeader/index.ts +2 -0
- package/assets/components/Sidebar/Sidebar.module.css +81 -4
- package/assets/components/Sidebar/Sidebar.tsx +11 -2
- package/assets/components/SplitButton/SplitButton.module.css +3 -3
- package/assets/components/Stepper/Stepper.module.css +196 -52
- package/assets/components/Stepper/Stepper.tsx +68 -13
- package/assets/components/Switch/Switch.module.css +1 -9
- package/assets/components/Topbar/Topbar.module.css +33 -5
- package/assets/components/Topbar/Topbar.tsx +62 -7
- package/assets/components/_data.ts +11 -4
- package/assets/components/index.ts +2 -0
- package/assets/components/tokens.css +23 -10
- package/assets/prompts/ASSEMBLY.md +219 -0
- package/assets/prompts/PRINCIPLES.md +70 -0
- package/assets/prompts/axes/icon.md +7 -1
- package/assets/prompts/axes/palette.md +11 -0
- package/assets/prompts/components/_variants.md +5 -1
- package/assets/prompts/components/callout.md +3 -3
- package/assets/prompts/components/event-list-item.md +103 -0
- package/assets/prompts/components/generated-image.md +80 -0
- package/assets/prompts/components/hint.md +57 -0
- package/assets/prompts/components/kanban.md +167 -0
- package/assets/prompts/components/list-item.md +182 -204
- package/assets/prompts/components/metric-card.md +2 -2
- package/assets/prompts/components/page-header.md +155 -0
- package/assets/prompts/components/toast.md +1 -0
- package/assets/prompts/components/topbar.md +77 -59
- package/assets/prompts/recipes/README.md +102 -0
- package/assets/prompts/recipes/card-row.md +58 -0
- package/assets/prompts/recipes/form-footer.md +76 -0
- package/assets/prompts/recipes/meta-line.md +61 -0
- package/assets/prompts/recipes/page-banner.md +121 -0
- package/assets/prompts/recipes/page-header.md +93 -0
- package/assets/prompts/recipes/section-header.md +90 -0
- package/assets/prompts/themes/focus.md +72 -0
- package/assets/skills/ctds/SKILL.md +1 -0
- package/assets/skills/ctds-page/SKILL.md +12 -2
- package/assets/skills/ctds-wireframe/SKILL.md +35 -1
- package/package.json +2 -4
|
@@ -96,8 +96,8 @@
|
|
|
96
96
|
}
|
|
97
97
|
.md {
|
|
98
98
|
height: var(--control-h-md);
|
|
99
|
-
padding-inline: var(--space-
|
|
100
|
-
gap: var(--space-
|
|
99
|
+
padding-inline: var(--space-3);
|
|
100
|
+
gap: var(--space-1_5);
|
|
101
101
|
font-size: var(--label-md-size);
|
|
102
102
|
border-radius: var(--radius-sm);
|
|
103
103
|
--btn-icon-size: var(--space-4);
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* EventListItem — 리스트에 쌓이는 일정 아이템.
|
|
3
|
+
* 좌: 날짜 블록(큰 숫자 + 요일 소문자) · 세로 hairline · 우: 제목 + status + meta.
|
|
4
|
+
*
|
|
5
|
+
* variant:
|
|
6
|
+
* card — 1px --border + --radius-lg + --bg (기본, 단독 카드)
|
|
7
|
+
* line — radius 없음, 하단 hairline만 (리스트 흐름 자리)
|
|
8
|
+
* fill — 기본은 중립 --bg-subtle(가장 연한 회색). status 지정 시 info/warning/success/destructive subtle 톤
|
|
9
|
+
*
|
|
10
|
+
* interactive: href 있을 때만 hover/focus ring.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
.root {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: stretch;
|
|
16
|
+
gap: var(--space-3);
|
|
17
|
+
color: inherit;
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
min-width: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* size — padding, 날짜 트랙 폭, 폰트 크기까지 한 단계씩. */
|
|
23
|
+
.md {
|
|
24
|
+
padding: var(--space-4) var(--space-5);
|
|
25
|
+
}
|
|
26
|
+
.sm {
|
|
27
|
+
padding: var(--space-3) var(--space-4);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* card — border + radius + bg */
|
|
31
|
+
.card {
|
|
32
|
+
background: var(--bg);
|
|
33
|
+
border: 1px solid var(--border);
|
|
34
|
+
border-radius: var(--radius-lg);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* line — radius 없이 하단 hairline만. 리스트 자리에서 쭉 흐른다. */
|
|
38
|
+
.line {
|
|
39
|
+
background: transparent;
|
|
40
|
+
border-bottom: 1px solid var(--border);
|
|
41
|
+
border-radius: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* fill — 기본은 중립 soft 회색(--bg-subtle). status 지정 시 아래 fillInfo/… 가 override. */
|
|
45
|
+
.fill {
|
|
46
|
+
background: var(--bg-subtle);
|
|
47
|
+
border-radius: var(--radius-lg);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.fillInfo {
|
|
51
|
+
background: var(--info-subtle);
|
|
52
|
+
}
|
|
53
|
+
.fillWarning {
|
|
54
|
+
background: var(--warning-subtle);
|
|
55
|
+
}
|
|
56
|
+
.fillSuccess {
|
|
57
|
+
background: var(--success-subtle);
|
|
58
|
+
}
|
|
59
|
+
.fillDestructive {
|
|
60
|
+
background: var(--destructive-subtle);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.interactive {
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
transition: var(--transition-colors), var(--transition-ring);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.card.interactive:hover,
|
|
69
|
+
.line.interactive:hover {
|
|
70
|
+
background: var(--hover);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* fill은 이미 status 색을 입고 있어 bg 교체 금지(색이 날아간다).
|
|
74
|
+
hover는 --hover를 inset 그림자로 겹쳐 톤만 살짝 어둡게. */
|
|
75
|
+
.fill.interactive:hover {
|
|
76
|
+
box-shadow: inset 0 0 0 999rem var(--hover);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.interactive:focus-visible {
|
|
80
|
+
outline: none;
|
|
81
|
+
box-shadow: var(--ring-shadow);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* fill variant에서 hover + focus 동시 유지 */
|
|
85
|
+
.fill.interactive:hover:focus-visible {
|
|
86
|
+
box-shadow: inset 0 0 0 999rem var(--hover), var(--ring-shadow);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* 날짜 블록 — 좌측 고정 폭. 숫자가 2자리 기준으로 흔들리지 않도록 min-width 트랙. */
|
|
90
|
+
.dateBlock {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
padding-inline: var(--space-0_5);
|
|
96
|
+
flex-shrink: 0;
|
|
97
|
+
}
|
|
98
|
+
.md .dateBlock {
|
|
99
|
+
min-width: var(--space-10);
|
|
100
|
+
}
|
|
101
|
+
.sm .dateBlock {
|
|
102
|
+
min-width: var(--space-8);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.day {
|
|
106
|
+
font-weight: var(--font-weight-semibold); /* 20px 이상 → semibold 허용 */
|
|
107
|
+
font-variant-numeric: tabular-nums;
|
|
108
|
+
color: var(--fg-strong);
|
|
109
|
+
line-height: var(--lh-tight);
|
|
110
|
+
}
|
|
111
|
+
.md .day {
|
|
112
|
+
font-size: var(--text-2xl);
|
|
113
|
+
}
|
|
114
|
+
.sm .day {
|
|
115
|
+
font-size: var(--text-xl);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.weekday {
|
|
119
|
+
font-weight: var(--font-weight-regular);
|
|
120
|
+
color: var(--fg-muted);
|
|
121
|
+
/* 소문자 유지. uppercase 금지 */
|
|
122
|
+
}
|
|
123
|
+
.md .weekday {
|
|
124
|
+
font-size: var(--text-2xs);
|
|
125
|
+
line-height: var(--lh-2xs);
|
|
126
|
+
}
|
|
127
|
+
.sm .weekday {
|
|
128
|
+
font-size: var(--text-3xs);
|
|
129
|
+
line-height: var(--lh-3xs);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* 세로 hairline — border-left shorthand로 (리터럴 width 금지 회피) */
|
|
133
|
+
.divider {
|
|
134
|
+
border-inline-start: 1px solid var(--border);
|
|
135
|
+
align-self: stretch;
|
|
136
|
+
flex-shrink: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* 본문 — 제목 + 메타 라인 */
|
|
140
|
+
.body {
|
|
141
|
+
flex: 1;
|
|
142
|
+
min-width: 0;
|
|
143
|
+
display: flex;
|
|
144
|
+
flex-direction: column;
|
|
145
|
+
gap: var(--space-1);
|
|
146
|
+
justify-content: center;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.title {
|
|
150
|
+
margin: 0;
|
|
151
|
+
font-weight: var(--font-weight-medium); /* 20px 미만 → medium */
|
|
152
|
+
color: var(--fg-strong);
|
|
153
|
+
min-width: 0;
|
|
154
|
+
overflow: hidden;
|
|
155
|
+
text-overflow: ellipsis;
|
|
156
|
+
white-space: nowrap;
|
|
157
|
+
}
|
|
158
|
+
.md .title {
|
|
159
|
+
font-size: var(--text-sm);
|
|
160
|
+
line-height: var(--lh-sm);
|
|
161
|
+
}
|
|
162
|
+
.sm .title {
|
|
163
|
+
font-size: var(--text-xs);
|
|
164
|
+
line-height: var(--lh-xs);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* 메타 라인 — status Badge + 아이콘+텍스트 N개. 사이는 짧은 세로 hairline. */
|
|
168
|
+
.metaRow {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: center;
|
|
171
|
+
gap: var(--space-1_5);
|
|
172
|
+
flex-wrap: wrap;
|
|
173
|
+
min-width: 0;
|
|
174
|
+
color: var(--fg-muted);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.metaItem {
|
|
178
|
+
display: inline-flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: var(--space-1);
|
|
181
|
+
color: var(--fg-muted);
|
|
182
|
+
min-width: 0;
|
|
183
|
+
}
|
|
184
|
+
.md .metaItem {
|
|
185
|
+
font-size: var(--text-xs);
|
|
186
|
+
line-height: var(--lh-xs);
|
|
187
|
+
}
|
|
188
|
+
.sm .metaItem {
|
|
189
|
+
font-size: var(--text-2xs);
|
|
190
|
+
line-height: var(--lh-2xs);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* 메타 라인 안에서 "앞선 형제가 있을 때만" 왼쪽 hairline. 첫 아이템은 항상 제거,
|
|
194
|
+
앞 slot이 비었다가 뒤에 하나만 나오는 경우에도 자동으로 안 그려진다. */
|
|
195
|
+
.metaRow > * + .metaItem {
|
|
196
|
+
padding-inline-start: var(--space-1_5);
|
|
197
|
+
border-inline-start: 1px solid var(--border);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* showMetaDivider=false — meta 사이 hairline/padding 제거. gap만으로 분리. */
|
|
201
|
+
.noMetaDivider .metaRow > * + .metaItem {
|
|
202
|
+
padding-inline-start: 0;
|
|
203
|
+
border-inline-start: none;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.metaIcon {
|
|
207
|
+
display: inline-flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
justify-content: center;
|
|
210
|
+
color: var(--fg-muted);
|
|
211
|
+
line-height: 1;
|
|
212
|
+
flex-shrink: 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.metaLabel {
|
|
216
|
+
min-width: 0;
|
|
217
|
+
overflow: hidden;
|
|
218
|
+
text-overflow: ellipsis;
|
|
219
|
+
white-space: nowrap;
|
|
220
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
forwardRef,
|
|
5
|
+
type AnchorHTMLAttributes,
|
|
6
|
+
type HTMLAttributes,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
type Ref,
|
|
9
|
+
} from "react";
|
|
10
|
+
|
|
11
|
+
import { Badge } from "../Badge";
|
|
12
|
+
import { Icon, type IconName } from "../Icon";
|
|
13
|
+
|
|
14
|
+
import styles from "./EventListItem.module.css";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* EventListItem — 리스트에 쌓이는 "하나의 일정" 아이템.
|
|
18
|
+
* 좌: 날짜 블록 (큰 숫자 + 요일), 우: 제목 + status + meta.
|
|
19
|
+
*
|
|
20
|
+
* EventChip은 캘린더 셀 안 색 바 전용. 이 컴포넌트는 리스트 아이템.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export type EventListItemStatus = "upcoming" | "pending" | "completed" | "cancelled";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* variant:
|
|
27
|
+
* - "card"(기본) — border + radius + bg. 단독 떠있는 리스트 아이템.
|
|
28
|
+
* - "line" — radius 없음, 하단 hairline만. 리스트가 가로 폭 꽉 채워 흐르는 자리.
|
|
29
|
+
* - "fill" — 기본은 중립 soft bg. status를 명시하면 info/warning/success/destructive 톤으로 덮어씀.
|
|
30
|
+
* fill + status 조합일 땐 Badge 중복 방지로 자동 숨김.
|
|
31
|
+
*/
|
|
32
|
+
export type EventListItemVariant = "card" | "line" | "fill";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* size:
|
|
36
|
+
* - "md"(기본) — 대시보드·상세 뷰 등 일반 자리.
|
|
37
|
+
* - "sm" — 사이드바·밀집 리스트처럼 세로 공간이 아쉬운 자리.
|
|
38
|
+
*/
|
|
39
|
+
export type EventListItemSize = "md" | "sm";
|
|
40
|
+
|
|
41
|
+
export type EventListItemMeta = {
|
|
42
|
+
icon?: IconName;
|
|
43
|
+
label: ReactNode;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type Common = {
|
|
47
|
+
date: Date;
|
|
48
|
+
title: ReactNode;
|
|
49
|
+
variant?: EventListItemVariant;
|
|
50
|
+
size?: EventListItemSize;
|
|
51
|
+
status?: EventListItemStatus;
|
|
52
|
+
statusLabel?: ReactNode;
|
|
53
|
+
meta?: EventListItemMeta[];
|
|
54
|
+
/** 날짜 블록 오른쪽 세로 hairline 표시 여부. 기본 true. */
|
|
55
|
+
showDateDivider?: boolean;
|
|
56
|
+
/** meta 아이템 사이 세로 hairline 분리선 표시 여부. 기본 true. */
|
|
57
|
+
showMetaDivider?: boolean;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
type DivProps = Common &
|
|
61
|
+
Omit<HTMLAttributes<HTMLDivElement>, keyof Common> & { href?: undefined };
|
|
62
|
+
|
|
63
|
+
type AnchorProps = Common &
|
|
64
|
+
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof Common> & { href: string };
|
|
65
|
+
|
|
66
|
+
export type EventListItemProps = DivProps | AnchorProps;
|
|
67
|
+
|
|
68
|
+
const statusMap: Record<
|
|
69
|
+
EventListItemStatus,
|
|
70
|
+
{ badgeStatus: "info" | "warning" | "success" | "destructive"; defaultLabel: string }
|
|
71
|
+
> = {
|
|
72
|
+
upcoming: { badgeStatus: "info", defaultLabel: "Upcoming" },
|
|
73
|
+
pending: { badgeStatus: "warning", defaultLabel: "Pending" },
|
|
74
|
+
completed: { badgeStatus: "success", defaultLabel: "Completed" },
|
|
75
|
+
cancelled: { badgeStatus: "destructive", defaultLabel: "Cancelled" },
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/* locale 고정 없이 사용자 로케일에 맡기면 리스트 안에서 길이가 들쭉날쭉.
|
|
79
|
+
요일 3글자 약어는 en-US 기준으로 맞추고, 대문자 금지 규칙에 따라 수동 소문자화. */
|
|
80
|
+
function formatDay(date: Date): string {
|
|
81
|
+
return String(date.getDate()).padStart(2, "0");
|
|
82
|
+
}
|
|
83
|
+
function formatWeekday(date: Date): string {
|
|
84
|
+
return date
|
|
85
|
+
.toLocaleDateString("en-US", { weekday: "short" })
|
|
86
|
+
.toLowerCase();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const variantClass: Record<EventListItemVariant, string> = {
|
|
90
|
+
card: styles.card,
|
|
91
|
+
line: styles.line,
|
|
92
|
+
fill: styles.fill,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const sizeClass: Record<EventListItemSize, string> = {
|
|
96
|
+
md: styles.md,
|
|
97
|
+
sm: styles.sm,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/* meta 아이콘 size — md는 14px, sm은 12px. */
|
|
101
|
+
const metaIconSize: Record<EventListItemSize, number> = {
|
|
102
|
+
md: 14,
|
|
103
|
+
sm: 12,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const fillStatusClass: Record<EventListItemStatus, string> = {
|
|
107
|
+
upcoming: styles.fillInfo,
|
|
108
|
+
pending: styles.fillWarning,
|
|
109
|
+
completed: styles.fillSuccess,
|
|
110
|
+
cancelled: styles.fillDestructive,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const EventListItem = forwardRef<HTMLElement, EventListItemProps>((props, ref) => {
|
|
114
|
+
const {
|
|
115
|
+
className,
|
|
116
|
+
date,
|
|
117
|
+
title,
|
|
118
|
+
variant = "card",
|
|
119
|
+
size = "md",
|
|
120
|
+
status,
|
|
121
|
+
statusLabel,
|
|
122
|
+
meta,
|
|
123
|
+
showDateDivider = true,
|
|
124
|
+
showMetaDivider = true,
|
|
125
|
+
...rest
|
|
126
|
+
} = props as Common & { className?: string } & Record<string, unknown>;
|
|
127
|
+
|
|
128
|
+
const isLink = typeof (props as AnchorProps).href === "string";
|
|
129
|
+
|
|
130
|
+
const rootClass = [
|
|
131
|
+
styles.root,
|
|
132
|
+
variantClass[variant],
|
|
133
|
+
sizeClass[size],
|
|
134
|
+
variant === "fill" && status ? fillStatusClass[status] : "",
|
|
135
|
+
!showMetaDivider ? styles.noMetaDivider : "",
|
|
136
|
+
isLink ? styles.interactive : "",
|
|
137
|
+
className ?? "",
|
|
138
|
+
]
|
|
139
|
+
.filter(Boolean)
|
|
140
|
+
.join(" ");
|
|
141
|
+
|
|
142
|
+
const mapped = status ? statusMap[status] : undefined;
|
|
143
|
+
const effectiveStatusLabel = statusLabel ?? mapped?.defaultLabel;
|
|
144
|
+
/* fill + status 조합일 때만 Badge 중복 숨김. fill 단독(중립 회색)일 땐 status 자체가 없다. */
|
|
145
|
+
const showStatusBadge = Boolean(mapped) && !(variant === "fill" && status);
|
|
146
|
+
|
|
147
|
+
const content = (
|
|
148
|
+
<>
|
|
149
|
+
<div className={styles.dateBlock} aria-hidden>
|
|
150
|
+
<span className={styles.day}>{formatDay(date)}</span>
|
|
151
|
+
<span className={styles.weekday}>{formatWeekday(date)}</span>
|
|
152
|
+
</div>
|
|
153
|
+
{showDateDivider && <div className={styles.divider} aria-hidden />}
|
|
154
|
+
<div className={styles.body}>
|
|
155
|
+
<h3 className={styles.title}>{title}</h3>
|
|
156
|
+
{(showStatusBadge || meta?.length) && (
|
|
157
|
+
<div className={styles.metaRow}>
|
|
158
|
+
{showStatusBadge && mapped && effectiveStatusLabel && (
|
|
159
|
+
<Badge variant="soft" status={mapped.badgeStatus}>
|
|
160
|
+
{effectiveStatusLabel}
|
|
161
|
+
</Badge>
|
|
162
|
+
)}
|
|
163
|
+
{meta?.map((m, i) => (
|
|
164
|
+
<span key={i} className={styles.metaItem}>
|
|
165
|
+
{m.icon && (
|
|
166
|
+
<span className={styles.metaIcon} aria-hidden>
|
|
167
|
+
<Icon name={m.icon} size={metaIconSize[size]} />
|
|
168
|
+
</span>
|
|
169
|
+
)}
|
|
170
|
+
<span className={styles.metaLabel}>{m.label}</span>
|
|
171
|
+
</span>
|
|
172
|
+
))}
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
</div>
|
|
176
|
+
</>
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
if (isLink) {
|
|
180
|
+
return (
|
|
181
|
+
<a
|
|
182
|
+
ref={ref as Ref<HTMLAnchorElement>}
|
|
183
|
+
className={rootClass}
|
|
184
|
+
{...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}
|
|
185
|
+
href={(props as AnchorProps).href}
|
|
186
|
+
>
|
|
187
|
+
{content}
|
|
188
|
+
</a>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<div
|
|
194
|
+
ref={ref as Ref<HTMLDivElement>}
|
|
195
|
+
className={rootClass}
|
|
196
|
+
{...(rest as HTMLAttributes<HTMLDivElement>)}
|
|
197
|
+
>
|
|
198
|
+
{content}
|
|
199
|
+
</div>
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
EventListItem.displayName = "EventListItem";
|
|
204
|
+
|
|
205
|
+
export { EventListItem };
|