@ttdk-design-system/library-react 0.0.0-stage → 1.0.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.
Files changed (184) hide show
  1. package/AI_GUIDE.md +6518 -0
  2. package/README.md +106 -2
  3. package/llms.txt +6518 -0
  4. package/package.json +1099 -4
  5. package/src/core/index.ts +2 -0
  6. package/src/core/tailwind-preset.cjs +62 -0
  7. package/src/core/tailwind-preset.ts +85 -0
  8. package/src/core/theme/tokens.css +663 -0
  9. package/src/core/types.ts +836 -0
  10. package/src/index.ts +17 -0
  11. package/src/tailwind-preset.cjs +62 -0
  12. package/src/tailwind-preset.ts +85 -0
  13. package/src/types.ts +1 -0
  14. package/src/web/accordion/AI_GUIDE.md +149 -0
  15. package/src/web/accordion/accordion.css +1 -0
  16. package/src/web/accordion/accordion.tsx +430 -0
  17. package/src/web/accordion/index.ts +3 -0
  18. package/src/web/accordion/manifest.json +351 -0
  19. package/src/web/alert/AI_GUIDE.md +139 -0
  20. package/src/web/alert/alert.css +1 -0
  21. package/src/web/alert/alert.tsx +318 -0
  22. package/src/web/alert/index.ts +3 -0
  23. package/src/web/alert/manifest.json +240 -0
  24. package/src/web/avatar/AI_GUIDE.md +118 -0
  25. package/src/web/avatar/avatar.css +1 -0
  26. package/src/web/avatar/avatar.tsx +233 -0
  27. package/src/web/avatar/index.ts +3 -0
  28. package/src/web/avatar/manifest.json +195 -0
  29. package/src/web/badge/AI_GUIDE.md +94 -0
  30. package/src/web/badge/badge.css +1 -0
  31. package/src/web/badge/badge.tsx +140 -0
  32. package/src/web/badge/index.ts +2 -0
  33. package/src/web/badge/manifest.json +141 -0
  34. package/src/web/banner/AI_GUIDE.md +130 -0
  35. package/src/web/banner/banner.css +1 -0
  36. package/src/web/banner/banner.tsx +334 -0
  37. package/src/web/banner/index.ts +3 -0
  38. package/src/web/banner/manifest.json +240 -0
  39. package/src/web/breadcrumb/AI_GUIDE.md +120 -0
  40. package/src/web/breadcrumb/breadcrumb.css +1 -0
  41. package/src/web/breadcrumb/breadcrumb.tsx +306 -0
  42. package/src/web/breadcrumb/index.ts +3 -0
  43. package/src/web/breadcrumb/manifest.json +225 -0
  44. package/src/web/button/AI_GUIDE.md +121 -0
  45. package/src/web/button/button.css +1 -0
  46. package/src/web/button/button.tsx +287 -0
  47. package/src/web/button/index.ts +2 -0
  48. package/src/web/button/manifest.json +177 -0
  49. package/src/web/calendar/AI_GUIDE.md +151 -0
  50. package/src/web/calendar/calendar.css +1 -0
  51. package/src/web/calendar/calendar.tsx +1611 -0
  52. package/src/web/calendar/index.ts +3 -0
  53. package/src/web/calendar/manifest.json +470 -0
  54. package/src/web/card/AI_GUIDE.md +133 -0
  55. package/src/web/card/card.css +1 -0
  56. package/src/web/card/card.tsx +408 -0
  57. package/src/web/card/index.ts +4 -0
  58. package/src/web/card/manifest.json +357 -0
  59. package/src/web/checkbox/AI_GUIDE.md +146 -0
  60. package/src/web/checkbox/checkbox.css +1 -0
  61. package/src/web/checkbox/checkbox.tsx +307 -0
  62. package/src/web/checkbox/index.ts +2 -0
  63. package/src/web/checkbox/manifest.json +294 -0
  64. package/src/web/chip/AI_GUIDE.md +186 -0
  65. package/src/web/chip/chip.css +1 -0
  66. package/src/web/chip/chip.tsx +230 -0
  67. package/src/web/chip/index.ts +2 -0
  68. package/src/web/chip/manifest.json +186 -0
  69. package/src/web/dropdown/AI_GUIDE.md +167 -0
  70. package/src/web/dropdown/dropdown.css +1 -0
  71. package/src/web/dropdown/dropdown.tsx +1274 -0
  72. package/src/web/dropdown/index.ts +3 -0
  73. package/src/web/dropdown/manifest.json +576 -0
  74. package/src/web/flex/AI_GUIDE.md +113 -0
  75. package/src/web/flex/flex-item.tsx +97 -0
  76. package/src/web/flex/flex.css +1 -0
  77. package/src/web/flex/flex.tsx +108 -0
  78. package/src/web/flex/index.ts +5 -0
  79. package/src/web/flex/manifest.json +162 -0
  80. package/src/web/form/index.ts +7 -0
  81. package/src/web/grid/AI_GUIDE.md +112 -0
  82. package/src/web/grid/grid-item.tsx +112 -0
  83. package/src/web/grid/grid.css +1 -0
  84. package/src/web/grid/grid.tsx +99 -0
  85. package/src/web/grid/index.ts +5 -0
  86. package/src/web/grid/manifest.json +153 -0
  87. package/src/web/index.ts +86 -0
  88. package/src/web/input/AI_GUIDE.md +159 -0
  89. package/src/web/input/index.ts +3 -0
  90. package/src/web/input/input.css +1 -0
  91. package/src/web/input/input.tsx +537 -0
  92. package/src/web/input/manifest.json +465 -0
  93. package/src/web/input-number/AI_GUIDE.md +164 -0
  94. package/src/web/input-number/index.ts +3 -0
  95. package/src/web/input-number/input-number.css +1 -0
  96. package/src/web/input-number/input-number.tsx +1193 -0
  97. package/src/web/input-number/manifest.json +575 -0
  98. package/src/web/modal/AI_GUIDE.md +171 -0
  99. package/src/web/modal/index.ts +3 -0
  100. package/src/web/modal/manifest.json +375 -0
  101. package/src/web/modal/modal.css +1 -0
  102. package/src/web/modal/modal.tsx +571 -0
  103. package/src/web/pagination/AI_GUIDE.md +148 -0
  104. package/src/web/pagination/index.ts +21 -0
  105. package/src/web/pagination/manifest.json +432 -0
  106. package/src/web/pagination/pagination-content.tsx +45 -0
  107. package/src/web/pagination/pagination-ellipsis.tsx +54 -0
  108. package/src/web/pagination/pagination-first.tsx +155 -0
  109. package/src/web/pagination/pagination-item.tsx +45 -0
  110. package/src/web/pagination/pagination-last.tsx +155 -0
  111. package/src/web/pagination/pagination-link.tsx +121 -0
  112. package/src/web/pagination/pagination-next.tsx +158 -0
  113. package/src/web/pagination/pagination-previous.tsx +158 -0
  114. package/src/web/pagination/pagination.css +1 -0
  115. package/src/web/pagination/pagination.tsx +687 -0
  116. package/src/web/popover/AI_GUIDE.md +163 -0
  117. package/src/web/popover/index.ts +3 -0
  118. package/src/web/popover/manifest.json +396 -0
  119. package/src/web/popover/popover.css +1 -0
  120. package/src/web/popover/popover.tsx +702 -0
  121. package/src/web/radio/AI_GUIDE.md +155 -0
  122. package/src/web/radio/index.ts +2 -0
  123. package/src/web/radio/manifest.json +294 -0
  124. package/src/web/radio/radio.css +1 -0
  125. package/src/web/radio/radio.tsx +290 -0
  126. package/src/web/selectbox/AI_GUIDE.md +216 -0
  127. package/src/web/selectbox/index.ts +3 -0
  128. package/src/web/selectbox/manifest.json +477 -0
  129. package/src/web/selectbox/selectbox.css +1 -0
  130. package/src/web/selectbox/selectbox.tsx +1048 -0
  131. package/src/web/sonner/AI_GUIDE.md +98 -0
  132. package/src/web/sonner/index.ts +114 -0
  133. package/src/web/sonner/manifest.json +132 -0
  134. package/src/web/sonner/sonner.css +1 -0
  135. package/src/web/sonner/sonner.tsx +177 -0
  136. package/src/web/table/AI_GUIDE.md +145 -0
  137. package/src/web/table/index.ts +35 -0
  138. package/src/web/table/manifest.json +168 -0
  139. package/src/web/table/table-body.tsx +45 -0
  140. package/src/web/table/table-caption.tsx +45 -0
  141. package/src/web/table/table-cell.tsx +74 -0
  142. package/src/web/table/table-empty.tsx +108 -0
  143. package/src/web/table/table-footer.tsx +45 -0
  144. package/src/web/table/table-head.tsx +80 -0
  145. package/src/web/table/table-header.tsx +45 -0
  146. package/src/web/table/table-row.tsx +69 -0
  147. package/src/web/table/table.css +1 -0
  148. package/src/web/table/table.tsx +305 -0
  149. package/src/web/tabs/AI_GUIDE.md +150 -0
  150. package/src/web/tabs/index.ts +3 -0
  151. package/src/web/tabs/manifest.json +315 -0
  152. package/src/web/tabs/tabs.css +1 -0
  153. package/src/web/tabs/tabs.tsx +332 -0
  154. package/src/web/text/AI_GUIDE.md +129 -0
  155. package/src/web/text/index.ts +3 -0
  156. package/src/web/text/manifest.json +195 -0
  157. package/src/web/text/text.css +1 -0
  158. package/src/web/text/text.tsx +689 -0
  159. package/src/web/textarea/AI_GUIDE.md +141 -0
  160. package/src/web/textarea/index.ts +3 -0
  161. package/src/web/textarea/manifest.json +438 -0
  162. package/src/web/textarea/textarea.css +1 -0
  163. package/src/web/textarea/textarea.tsx +467 -0
  164. package/src/web/tooltip/AI_GUIDE.md +110 -0
  165. package/src/web/tooltip/index.ts +3 -0
  166. package/src/web/tooltip/manifest.json +222 -0
  167. package/src/web/tooltip/tooltip.css +1 -0
  168. package/src/web/tooltip/tooltip.tsx +423 -0
  169. package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
  170. package/src/webview/bottomsheet/bottomsheet.css +1 -0
  171. package/src/webview/bottomsheet/bottomsheet.tsx +603 -0
  172. package/src/webview/bottomsheet/index.ts +4 -0
  173. package/src/webview/bottomsheet/manifest.json +377 -0
  174. package/src/webview/button/AI_GUIDE.md +79 -0
  175. package/src/webview/button/button-ios.css +1 -0
  176. package/src/webview/button/button-ios.tsx +138 -0
  177. package/src/webview/button/button-material.css +1 -0
  178. package/src/webview/button/button-material.tsx +138 -0
  179. package/src/webview/button/index.ts +7 -0
  180. package/src/webview/button/manifest.json +148 -0
  181. package/src/webview/index.ts +7 -0
  182. package/tailwind-preset.cjs +62 -0
  183. package/tailwind-preset.js +62 -0
  184. package/ttdk-manifest.json +10188 -0
@@ -0,0 +1,408 @@
1
+ "use client";
2
+ import * as React from "react";
3
+
4
+ export type CardUiProps = UiProps;
5
+ export interface CardProps {
6
+ /**
7
+ * Gaya varian visual kartu.
8
+ * - 'bordered': Kartu dengan border halus dan background card standar.
9
+ * - 'elevated': Kartu dengan bayangan elevasi bertingkat (shadow).
10
+ * - 'flat': Kartu dengan latar netral subtle tanpa bayangan.
11
+ * - 'ghost': Kartu transparan minimalis tanpa border atau bayangan.
12
+ *
13
+ * @default 'default'
14
+ */
15
+ variant?: "bordered" | "elevated" | "flat" | "ghost";
16
+
17
+ /**
18
+ * Kepadatan padding internal kartu.
19
+ * - 'sm': Padding kompak (12px / 16px).
20
+ * - 'md': Padding proporsional standar (20px / 24px).
21
+ * - 'lg': Padding lapang / hero (28px / 32px).
22
+ *
23
+ * @default 'md'
24
+ */
25
+ size?: "sm" | "md" | "lg";
26
+
27
+ /**
28
+ * Preset batas lebar kartu sesuai standar token TTDK.
29
+ * - 'auto': Fleksibel mengikuti lebar kontainer parent.
30
+ * - 'full': Lebar penuh 100%.
31
+ * - '1-1': 1128px (Grid Desktop Maksimal).
32
+ * - '1-2': 552px (Grid 1/2).
33
+ * - '1-3': 360px (Grid 1/3).
34
+ * - '1-4': 264px (Grid 1/4).
35
+ * - 'mobile': 328px (Optimal Layar Seluler).
36
+ *
37
+ * @default 'auto'
38
+ */
39
+ cardWidth?: "auto" | "full" | "1-1" | "1-2" | "1-3" | "1-4" | "mobile";
40
+
41
+ /**
42
+ * Sudut kelengkungan radius kartu.
43
+ *
44
+ * @default 'md'
45
+ */
46
+ rounded?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "full";
47
+
48
+ /**
49
+ * Menambahkan efek hover interaktif (elevasi bayangan naik + border highlight + pointer kursor).
50
+ *
51
+ * @default false
52
+ */
53
+ hoverable?: boolean;
54
+
55
+ /**
56
+ * Menjadikan kartu sebagai elemen interaktif yang dapat diklik.
57
+ *
58
+ * @default false
59
+ */
60
+ clickable?: boolean;
61
+
62
+ /**
63
+ * Menampilkan efek placeholder shimmer / skeleton loader saat kartu dalam proses memuat data.
64
+ *
65
+ * @default false
66
+ */
67
+ loading?: boolean;
68
+
69
+ /**
70
+ * Menonaktifkan interaksi kartu dan meredupkan opacity.
71
+ *
72
+ * @default false
73
+ */
74
+ disabled?: boolean;
75
+
76
+ /**
77
+ * Judul kartu pada area header.
78
+ */
79
+ title?: any;
80
+
81
+ /**
82
+ * Subjudul atau teks deskripsi singkat di bawah judul.
83
+ */
84
+ subtitle?: any;
85
+
86
+ /**
87
+ * Konten pelengkap di sudut kanan atas header kartu (badge, menu tombol, link aksi).
88
+ */
89
+ extra?: any;
90
+
91
+ /**
92
+ * Media gambar cover atau banner visual kartu (berupa URL string gambar atau elemen/node kustom).
93
+ */
94
+ cover?: any;
95
+
96
+ /**
97
+ * Alt text untuk gambar cover jika `cover` berupa URL string.
98
+ */
99
+ coverAlt?: string;
100
+
101
+ /**
102
+ * Posisi media cover pada kartu ('top' atau 'bottom').
103
+ *
104
+ * @default 'top'
105
+ */
106
+ coverPosition?: "top" | "bottom";
107
+
108
+ /**
109
+ * Grup tombol aksi terstruktur di area footer kartu.
110
+ */
111
+ actions?: any;
112
+
113
+ /**
114
+ * Konten kustom untuk area footer kartu.
115
+ */
116
+ footer?: any;
117
+
118
+ /**
119
+ * Menampilkan garis pembatas divider di bawah header kartu.
120
+ *
121
+ * @default true
122
+ */
123
+ headerBorder?: boolean;
124
+
125
+ /**
126
+ * Menampilkan garis pembatas divider di atas footer kartu.
127
+ *
128
+ * @default true
129
+ */
130
+ footerBorder?: boolean;
131
+
132
+ /**
133
+ * Callback event saat kartu diklik.
134
+ */
135
+ onClick?: (event: any) => void;
136
+
137
+ /**
138
+ * Kustomisasi visual granular root kontainer kartu (UiProps).
139
+ */
140
+ ui?: UiProps;
141
+
142
+ /**
143
+ * Inline CSS style object native.
144
+ */
145
+ style?: React.CSSProperties;
146
+
147
+ /**
148
+ * Class CSS kustom untuk root kontainer kartu.
149
+ */
150
+ className?: string;
151
+
152
+ /**
153
+ * Style kustom untuk area header kartu (UiProps).
154
+ */
155
+ headerStyle?: UiProps;
156
+
157
+ /**
158
+ * Class CSS kustom untuk area header kartu.
159
+ */
160
+ headerClass?: string;
161
+
162
+ /**
163
+ * Style kustom untuk teks judul kartu (UiProps).
164
+ */
165
+ titleStyle?: UiProps;
166
+
167
+ /**
168
+ * Class CSS kustom untuk teks judul kartu.
169
+ */
170
+ titleClass?: string;
171
+
172
+ /**
173
+ * Style kustom untuk teks subjudul / deskripsi header (UiProps).
174
+ */
175
+ subtitleStyle?: UiProps;
176
+
177
+ /**
178
+ * Class CSS kustom untuk teks subjudul / deskripsi header.
179
+ */
180
+ subtitleClass?: string;
181
+
182
+ /**
183
+ * Style kustom untuk elemen extra di sudut kanan header (UiProps).
184
+ */
185
+ extraStyle?: UiProps;
186
+
187
+ /**
188
+ * Class CSS kustom untuk elemen extra di sudut kanan header.
189
+ */
190
+ extraClass?: string;
191
+
192
+ /**
193
+ * Style kustom untuk area body / konten utama kartu (UiProps).
194
+ */
195
+ bodyStyle?: UiProps;
196
+
197
+ /**
198
+ * Class CSS kustom untuk area body / konten utama kartu.
199
+ */
200
+ bodyClass?: string;
201
+
202
+ /**
203
+ * Style kustom untuk area footer kartu (UiProps).
204
+ */
205
+ footerStyle?: UiProps;
206
+
207
+ /**
208
+ * Class CSS kustom untuk area footer kartu.
209
+ */
210
+ footerClass?: string;
211
+
212
+ /**
213
+ * Style kustom untuk area media cover kartu (UiProps).
214
+ */
215
+ coverStyle?: UiProps;
216
+
217
+ /**
218
+ * Class CSS kustom untuk area media cover kartu.
219
+ */
220
+ coverClass?: string;
221
+
222
+ /**
223
+ * Konten anak atau slot kustom (children).
224
+ */
225
+ children?: any;
226
+ }
227
+
228
+ import { buildUiVars, UiProps } from "../../core/types";
229
+
230
+ function Card(props: CardProps) {
231
+ return (
232
+ <div
233
+ className={`ttdk-card ${props.className || ""}`.trim()}
234
+ data-variant={props.variant || "default"}
235
+ data-size={props.size || "md"}
236
+ data-rounded={props.rounded || "md"}
237
+ data-width={props.cardWidth || "auto"}
238
+ data-hoverable={props.hoverable ? "true" : "false"}
239
+ data-clickable={props.clickable || props.onClick ? "true" : "false"}
240
+ data-disabled={props.disabled ? "true" : "false"}
241
+ data-loading={props.loading ? "true" : "false"}
242
+ tabIndex={props.clickable || props.onClick ? 0 : undefined}
243
+ role={props.clickable || props.onClick ? "button" : undefined}
244
+ onClick={(event) => {
245
+ if (props.disabled || props.loading) return;
246
+ if (props.onClick) props.onClick(event);
247
+ }}
248
+ onKeyDown={(event) => {
249
+ if (props.disabled || props.loading) return;
250
+ if (
251
+ (props.clickable || props.onClick) &&
252
+ (event.key === "Enter" || event.key === " ")
253
+ ) {
254
+ event.preventDefault();
255
+ if (props.onClick) props.onClick(event);
256
+ }
257
+ }}
258
+ style={{
259
+ ...buildUiVars(props.ui),
260
+ ...((props as any)["style"] || {}),
261
+ ...props.style,
262
+ }}
263
+ >
264
+ {props.cover &&
265
+ (!props.coverPosition || props.coverPosition === "top") ? (
266
+ <div
267
+ className={`ttdk-card-cover ttdk-card-cover-top ${
268
+ props.coverClass || ""
269
+ }`.trim()}
270
+ style={{
271
+ ...buildUiVars(props.coverStyle),
272
+ }}
273
+ >
274
+ {typeof props.cover === "string" ? (
275
+ <img src={props.cover} alt={props.coverAlt || ""} />
276
+ ) : null}
277
+ {typeof props.cover !== "string" ? <>{props.cover}</> : null}
278
+ </div>
279
+ ) : null}
280
+ {props.loading ? (
281
+ <div className="ttdk-card-skeleton">
282
+ <div className="ttdk-card-skeleton-header">
283
+ <div className="ttdk-card-skeleton-avatar" />
284
+ <div className="ttdk-card-skeleton-title-group">
285
+ <div className="ttdk-card-skeleton-line ttdk-card-skeleton-line-title" />
286
+ <div className="ttdk-card-skeleton-line ttdk-card-skeleton-line-subtitle" />
287
+ </div>
288
+ </div>
289
+ <div className="ttdk-card-skeleton-body">
290
+ <div
291
+ className="ttdk-card-skeleton-line"
292
+ style={{
293
+ width: "100%",
294
+ }}
295
+ />
296
+ <div
297
+ className="ttdk-card-skeleton-line"
298
+ style={{
299
+ width: "85%",
300
+ }}
301
+ />
302
+ <div
303
+ className="ttdk-card-skeleton-line"
304
+ style={{
305
+ width: "60%",
306
+ }}
307
+ />
308
+ </div>
309
+ </div>
310
+ ) : null}
311
+ {!props.loading ? (
312
+ <>
313
+ {props.title || props.subtitle || props.extra ? (
314
+ <div
315
+ className={`ttdk-card-header ${
316
+ props.headerBorder !== false ? "ttdk-card-header-bordered" : ""
317
+ } ${props.headerClass || ""}`.trim()}
318
+ style={{
319
+ ...buildUiVars(props.headerStyle),
320
+ }}
321
+ >
322
+ <div className="ttdk-card-header-main">
323
+ {props.title ? (
324
+ <div
325
+ className={`ttdk-card-title ${
326
+ props.titleClass || ""
327
+ }`.trim()}
328
+ style={{
329
+ ...buildUiVars(props.titleStyle),
330
+ }}
331
+ >
332
+ {props.title}
333
+ </div>
334
+ ) : null}
335
+ {props.subtitle ? (
336
+ <div
337
+ className={`ttdk-card-subtitle ${
338
+ props.subtitleClass || ""
339
+ }`.trim()}
340
+ style={{
341
+ ...buildUiVars(props.subtitleStyle),
342
+ }}
343
+ >
344
+ {props.subtitle}
345
+ </div>
346
+ ) : null}
347
+ </div>
348
+ {props.extra ? (
349
+ <div
350
+ className={`ttdk-card-extra ${props.extraClass || ""}`.trim()}
351
+ style={{
352
+ ...buildUiVars(props.extraStyle),
353
+ }}
354
+ >
355
+ {props.extra}
356
+ </div>
357
+ ) : null}
358
+ </div>
359
+ ) : null}
360
+ <div
361
+ className={`ttdk-card-body ${props.bodyClass || ""}`.trim()}
362
+ style={{
363
+ ...buildUiVars(props.bodyStyle),
364
+ }}
365
+ >
366
+ <>{props.children}</>
367
+ </div>
368
+ {props.footer || props.actions ? (
369
+ <div
370
+ className={`ttdk-card-footer ${
371
+ props.footerBorder !== false ? "ttdk-card-footer-bordered" : ""
372
+ } ${props.footerClass || ""}`.trim()}
373
+ style={{
374
+ ...buildUiVars(props.footerStyle),
375
+ }}
376
+ >
377
+ {props.footer ? (
378
+ <div className="ttdk-card-footer-content">{props.footer}</div>
379
+ ) : null}
380
+ {props.actions ? (
381
+ <div className="ttdk-card-actions">{props.actions}</div>
382
+ ) : null}
383
+ </div>
384
+ ) : null}
385
+ </>
386
+ ) : null}
387
+ {props.cover && props.coverPosition === "bottom" ? (
388
+ <div
389
+ className={`ttdk-card-cover ttdk-card-cover-bottom ${
390
+ props.coverClass || ""
391
+ }`.trim()}
392
+ style={{
393
+ ...buildUiVars(props.coverStyle),
394
+ }}
395
+ >
396
+ {typeof props.cover === "string" ? (
397
+ <img src={props.cover} alt={props.coverAlt || ""} />
398
+ ) : null}
399
+ {typeof props.cover !== "string" ? <>{props.cover}</> : null}
400
+ </div>
401
+ ) : null}
402
+ </div>
403
+ );
404
+ }
405
+
406
+ export default Card;
407
+
408
+ export { Card };
@@ -0,0 +1,4 @@
1
+ export { default as Card } from './card';
2
+ export { default } from './card';
3
+ export * from './card';
4
+ export type { CardProps, CardUiProps } from './card'