@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.
- package/AI_GUIDE.md +6518 -0
- package/README.md +106 -2
- package/llms.txt +6518 -0
- package/package.json +1099 -4
- package/src/core/index.ts +2 -0
- package/src/core/tailwind-preset.cjs +62 -0
- package/src/core/tailwind-preset.ts +85 -0
- package/src/core/theme/tokens.css +663 -0
- package/src/core/types.ts +836 -0
- package/src/index.ts +17 -0
- package/src/tailwind-preset.cjs +62 -0
- package/src/tailwind-preset.ts +85 -0
- package/src/types.ts +1 -0
- package/src/web/accordion/AI_GUIDE.md +149 -0
- package/src/web/accordion/accordion.css +1 -0
- package/src/web/accordion/accordion.tsx +430 -0
- package/src/web/accordion/index.ts +3 -0
- package/src/web/accordion/manifest.json +351 -0
- package/src/web/alert/AI_GUIDE.md +139 -0
- package/src/web/alert/alert.css +1 -0
- package/src/web/alert/alert.tsx +318 -0
- package/src/web/alert/index.ts +3 -0
- package/src/web/alert/manifest.json +240 -0
- package/src/web/avatar/AI_GUIDE.md +118 -0
- package/src/web/avatar/avatar.css +1 -0
- package/src/web/avatar/avatar.tsx +233 -0
- package/src/web/avatar/index.ts +3 -0
- package/src/web/avatar/manifest.json +195 -0
- package/src/web/badge/AI_GUIDE.md +94 -0
- package/src/web/badge/badge.css +1 -0
- package/src/web/badge/badge.tsx +140 -0
- package/src/web/badge/index.ts +2 -0
- package/src/web/badge/manifest.json +141 -0
- package/src/web/banner/AI_GUIDE.md +130 -0
- package/src/web/banner/banner.css +1 -0
- package/src/web/banner/banner.tsx +334 -0
- package/src/web/banner/index.ts +3 -0
- package/src/web/banner/manifest.json +240 -0
- package/src/web/breadcrumb/AI_GUIDE.md +120 -0
- package/src/web/breadcrumb/breadcrumb.css +1 -0
- package/src/web/breadcrumb/breadcrumb.tsx +306 -0
- package/src/web/breadcrumb/index.ts +3 -0
- package/src/web/breadcrumb/manifest.json +225 -0
- package/src/web/button/AI_GUIDE.md +121 -0
- package/src/web/button/button.css +1 -0
- package/src/web/button/button.tsx +287 -0
- package/src/web/button/index.ts +2 -0
- package/src/web/button/manifest.json +177 -0
- package/src/web/calendar/AI_GUIDE.md +151 -0
- package/src/web/calendar/calendar.css +1 -0
- package/src/web/calendar/calendar.tsx +1611 -0
- package/src/web/calendar/index.ts +3 -0
- package/src/web/calendar/manifest.json +470 -0
- package/src/web/card/AI_GUIDE.md +133 -0
- package/src/web/card/card.css +1 -0
- package/src/web/card/card.tsx +408 -0
- package/src/web/card/index.ts +4 -0
- package/src/web/card/manifest.json +357 -0
- package/src/web/checkbox/AI_GUIDE.md +146 -0
- package/src/web/checkbox/checkbox.css +1 -0
- package/src/web/checkbox/checkbox.tsx +307 -0
- package/src/web/checkbox/index.ts +2 -0
- package/src/web/checkbox/manifest.json +294 -0
- package/src/web/chip/AI_GUIDE.md +186 -0
- package/src/web/chip/chip.css +1 -0
- package/src/web/chip/chip.tsx +230 -0
- package/src/web/chip/index.ts +2 -0
- package/src/web/chip/manifest.json +186 -0
- package/src/web/dropdown/AI_GUIDE.md +167 -0
- package/src/web/dropdown/dropdown.css +1 -0
- package/src/web/dropdown/dropdown.tsx +1274 -0
- package/src/web/dropdown/index.ts +3 -0
- package/src/web/dropdown/manifest.json +576 -0
- package/src/web/flex/AI_GUIDE.md +113 -0
- package/src/web/flex/flex-item.tsx +97 -0
- package/src/web/flex/flex.css +1 -0
- package/src/web/flex/flex.tsx +108 -0
- package/src/web/flex/index.ts +5 -0
- package/src/web/flex/manifest.json +162 -0
- package/src/web/form/index.ts +7 -0
- package/src/web/grid/AI_GUIDE.md +112 -0
- package/src/web/grid/grid-item.tsx +112 -0
- package/src/web/grid/grid.css +1 -0
- package/src/web/grid/grid.tsx +99 -0
- package/src/web/grid/index.ts +5 -0
- package/src/web/grid/manifest.json +153 -0
- package/src/web/index.ts +86 -0
- package/src/web/input/AI_GUIDE.md +159 -0
- package/src/web/input/index.ts +3 -0
- package/src/web/input/input.css +1 -0
- package/src/web/input/input.tsx +537 -0
- package/src/web/input/manifest.json +465 -0
- package/src/web/input-number/AI_GUIDE.md +164 -0
- package/src/web/input-number/index.ts +3 -0
- package/src/web/input-number/input-number.css +1 -0
- package/src/web/input-number/input-number.tsx +1193 -0
- package/src/web/input-number/manifest.json +575 -0
- package/src/web/modal/AI_GUIDE.md +171 -0
- package/src/web/modal/index.ts +3 -0
- package/src/web/modal/manifest.json +375 -0
- package/src/web/modal/modal.css +1 -0
- package/src/web/modal/modal.tsx +571 -0
- package/src/web/pagination/AI_GUIDE.md +148 -0
- package/src/web/pagination/index.ts +21 -0
- package/src/web/pagination/manifest.json +432 -0
- package/src/web/pagination/pagination-content.tsx +45 -0
- package/src/web/pagination/pagination-ellipsis.tsx +54 -0
- package/src/web/pagination/pagination-first.tsx +155 -0
- package/src/web/pagination/pagination-item.tsx +45 -0
- package/src/web/pagination/pagination-last.tsx +155 -0
- package/src/web/pagination/pagination-link.tsx +121 -0
- package/src/web/pagination/pagination-next.tsx +158 -0
- package/src/web/pagination/pagination-previous.tsx +158 -0
- package/src/web/pagination/pagination.css +1 -0
- package/src/web/pagination/pagination.tsx +687 -0
- package/src/web/popover/AI_GUIDE.md +163 -0
- package/src/web/popover/index.ts +3 -0
- package/src/web/popover/manifest.json +396 -0
- package/src/web/popover/popover.css +1 -0
- package/src/web/popover/popover.tsx +702 -0
- package/src/web/radio/AI_GUIDE.md +155 -0
- package/src/web/radio/index.ts +2 -0
- package/src/web/radio/manifest.json +294 -0
- package/src/web/radio/radio.css +1 -0
- package/src/web/radio/radio.tsx +290 -0
- package/src/web/selectbox/AI_GUIDE.md +216 -0
- package/src/web/selectbox/index.ts +3 -0
- package/src/web/selectbox/manifest.json +477 -0
- package/src/web/selectbox/selectbox.css +1 -0
- package/src/web/selectbox/selectbox.tsx +1048 -0
- package/src/web/sonner/AI_GUIDE.md +98 -0
- package/src/web/sonner/index.ts +114 -0
- package/src/web/sonner/manifest.json +132 -0
- package/src/web/sonner/sonner.css +1 -0
- package/src/web/sonner/sonner.tsx +177 -0
- package/src/web/table/AI_GUIDE.md +145 -0
- package/src/web/table/index.ts +35 -0
- package/src/web/table/manifest.json +168 -0
- package/src/web/table/table-body.tsx +45 -0
- package/src/web/table/table-caption.tsx +45 -0
- package/src/web/table/table-cell.tsx +74 -0
- package/src/web/table/table-empty.tsx +108 -0
- package/src/web/table/table-footer.tsx +45 -0
- package/src/web/table/table-head.tsx +80 -0
- package/src/web/table/table-header.tsx +45 -0
- package/src/web/table/table-row.tsx +69 -0
- package/src/web/table/table.css +1 -0
- package/src/web/table/table.tsx +305 -0
- package/src/web/tabs/AI_GUIDE.md +150 -0
- package/src/web/tabs/index.ts +3 -0
- package/src/web/tabs/manifest.json +315 -0
- package/src/web/tabs/tabs.css +1 -0
- package/src/web/tabs/tabs.tsx +332 -0
- package/src/web/text/AI_GUIDE.md +129 -0
- package/src/web/text/index.ts +3 -0
- package/src/web/text/manifest.json +195 -0
- package/src/web/text/text.css +1 -0
- package/src/web/text/text.tsx +689 -0
- package/src/web/textarea/AI_GUIDE.md +141 -0
- package/src/web/textarea/index.ts +3 -0
- package/src/web/textarea/manifest.json +438 -0
- package/src/web/textarea/textarea.css +1 -0
- package/src/web/textarea/textarea.tsx +467 -0
- package/src/web/tooltip/AI_GUIDE.md +110 -0
- package/src/web/tooltip/index.ts +3 -0
- package/src/web/tooltip/manifest.json +222 -0
- package/src/web/tooltip/tooltip.css +1 -0
- package/src/web/tooltip/tooltip.tsx +423 -0
- package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
- package/src/webview/bottomsheet/bottomsheet.css +1 -0
- package/src/webview/bottomsheet/bottomsheet.tsx +603 -0
- package/src/webview/bottomsheet/index.ts +4 -0
- package/src/webview/bottomsheet/manifest.json +377 -0
- package/src/webview/button/AI_GUIDE.md +79 -0
- package/src/webview/button/button-ios.css +1 -0
- package/src/webview/button/button-ios.tsx +138 -0
- package/src/webview/button/button-material.css +1 -0
- package/src/webview/button/button-material.tsx +138 -0
- package/src/webview/button/index.ts +7 -0
- package/src/webview/button/manifest.json +148 -0
- package/src/webview/index.ts +7 -0
- package/tailwind-preset.cjs +62 -0
- package/tailwind-preset.js +62 -0
- package/ttdk-manifest.json +10188 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
export type RadioUiProps = UiProps;
|
|
5
|
+
export interface RadioProps {
|
|
6
|
+
/**
|
|
7
|
+
* Status apakah radio button sedang dalam kondisi terpilih (checked).
|
|
8
|
+
*
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
checked?: boolean;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Teks label utama yang ditampilkan di samping lingkaran radio.
|
|
15
|
+
*/
|
|
16
|
+
label?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Deskripsi atau teks bantuan yang ditampilkan di bawah label.
|
|
20
|
+
*/
|
|
21
|
+
description?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Teks bantuan atau keterangan di bawah label (dapat digunakan bergantian dengan description).
|
|
25
|
+
*/
|
|
26
|
+
helperText?: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Status error visual atau string pesan error.
|
|
30
|
+
*/
|
|
31
|
+
error?: boolean | string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Pesan error yang ditampilkan jika validasi form gagal.
|
|
35
|
+
*/
|
|
36
|
+
errorMessage?: string;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Skala ukuran radio button:
|
|
40
|
+
* - `'sm'`: Lingkaran 16px, font 13px.
|
|
41
|
+
* - `'md'`: Lingkaran 18px, font 14px (standar).
|
|
42
|
+
* - `'lg'`: Lingkaran 22px, font 16px.
|
|
43
|
+
*
|
|
44
|
+
* @default 'md'
|
|
45
|
+
*/
|
|
46
|
+
size?: "sm" | "md" | "lg";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Varian warna semantik saat radio button dipilih:
|
|
50
|
+
* - `'primary'`: Aksen toska aksi (#16b3ac, standar).
|
|
51
|
+
* - `'info'`: Aksen biru informasi (#2196f3).
|
|
52
|
+
* - `'success'`: Warna hijau sukses (#047b5d).
|
|
53
|
+
* - `'warning'`: Warna peringatan kuning/oranye (#fb8c00).
|
|
54
|
+
* - `'danger'`: Warna bahaya merah (#c50a24).
|
|
55
|
+
* - `'neutral'`: Warna abu-abu netral (#4a4f53).
|
|
56
|
+
*
|
|
57
|
+
* @default 'primary'
|
|
58
|
+
*/
|
|
59
|
+
variant?: "primary" | "info" | "success" | "warning" | "danger" | "neutral";
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Menonaktifkan interaksi pada radio button.
|
|
63
|
+
*
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
disabled?: boolean;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Menandakan bahwa field radio wajib diisi (required) pada formulir.
|
|
70
|
+
*
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
required?: boolean;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Name atribut untuk elemen HTML `<input type="radio">`.
|
|
77
|
+
* Digunakan untuk mengelompokkan radio button dalam satu grup.
|
|
78
|
+
*/
|
|
79
|
+
name?: string;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Value atribut untuk elemen HTML input.
|
|
83
|
+
*/
|
|
84
|
+
value?: string;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Identifier unik elemen radio button (untuk kaitan dengan label form).
|
|
88
|
+
*/
|
|
89
|
+
id?: string;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Kustomisasi visual granular melalui style-like object (+ support pseudo-class: hover, active).
|
|
93
|
+
*/
|
|
94
|
+
ui?: UiProps;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Inline CSS style object native.
|
|
98
|
+
*/
|
|
99
|
+
style?: React.CSSProperties;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Style kustom untuk lingkaran kontrol radio (UiProps).
|
|
103
|
+
*/
|
|
104
|
+
controlStyle?: UiProps;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Class CSS kustom untuk lingkaran kontrol radio (Tailwind / class kustom).
|
|
108
|
+
*/
|
|
109
|
+
controlClass?: string;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Style kustom untuk titik (dot) di dalam radio button saat checked (UiProps).
|
|
113
|
+
*/
|
|
114
|
+
dotStyle?: UiProps;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Class CSS kustom untuk titik (dot) di dalam radio button saat checked (Tailwind / class kustom).
|
|
118
|
+
*/
|
|
119
|
+
dotClass?: string;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Style kustom untuk teks label radio (UiProps).
|
|
123
|
+
*/
|
|
124
|
+
labelStyle?: UiProps;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Class CSS kustom untuk teks label radio (Tailwind / class kustom).
|
|
128
|
+
*/
|
|
129
|
+
labelClass?: string;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Style kustom untuk teks deskripsi bantuan (UiProps).
|
|
133
|
+
*/
|
|
134
|
+
descStyle?: UiProps;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Class CSS kustom untuk teks deskripsi bantuan (Tailwind / class kustom).
|
|
138
|
+
*/
|
|
139
|
+
descClass?: string;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Style kustom untuk elemen helper text (UiProps).
|
|
143
|
+
*/
|
|
144
|
+
helperTextStyle?: UiProps;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Class CSS kustom untuk elemen helper text.
|
|
148
|
+
*/
|
|
149
|
+
helperTextClass?: string;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Style kustom untuk teks pesan error validasi (UiProps).
|
|
153
|
+
*/
|
|
154
|
+
errorMessageStyle?: UiProps;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Class CSS kustom untuk teks pesan error validasi (Tailwind / class kustom).
|
|
158
|
+
*/
|
|
159
|
+
errorMessageClass?: string;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Event handler yang dipanggil saat nilai radio button berubah.
|
|
163
|
+
* Mengembalikan `(checked: boolean, event: Event)`.
|
|
164
|
+
*/
|
|
165
|
+
onChange?: (checked: boolean, event?: any) => void;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Class CSS kustom.
|
|
169
|
+
*/
|
|
170
|
+
className?: string;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Slot konten label kustom yang menggantikan prop `label`.
|
|
174
|
+
*/
|
|
175
|
+
children?: any;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
import { buildUiVars, UiProps } from "../../core/types";
|
|
179
|
+
|
|
180
|
+
function Radio(props: RadioProps) {
|
|
181
|
+
return (
|
|
182
|
+
<label
|
|
183
|
+
className={`ttdk-radio-wrapper ttdk-radio-root ${
|
|
184
|
+
props.className || ""
|
|
185
|
+
}`.trim()}
|
|
186
|
+
data-size={props.size || "md"}
|
|
187
|
+
data-variant={props.variant || "primary"}
|
|
188
|
+
data-disabled={props.disabled ? "true" : "false"}
|
|
189
|
+
data-checked={props.checked ? "true" : "false"}
|
|
190
|
+
data-state={props.checked ? "checked" : "unchecked"}
|
|
191
|
+
data-error={Boolean(props.errorMessage || props.error) ? "true" : "false"}
|
|
192
|
+
data-has-description={
|
|
193
|
+
Boolean(props.description || props.helperText) ? "true" : "false"
|
|
194
|
+
}
|
|
195
|
+
style={{
|
|
196
|
+
...buildUiVars(props.ui),
|
|
197
|
+
...((props as any)["style"] || {}),
|
|
198
|
+
...props.style,
|
|
199
|
+
}}
|
|
200
|
+
>
|
|
201
|
+
<input
|
|
202
|
+
type="radio"
|
|
203
|
+
className="ttdk-radio-native ttdk-radio-input"
|
|
204
|
+
id={props.id}
|
|
205
|
+
name={props.name}
|
|
206
|
+
value={props.value}
|
|
207
|
+
checked={props.checked}
|
|
208
|
+
disabled={props.disabled}
|
|
209
|
+
required={props.required}
|
|
210
|
+
onChange={(event) => {
|
|
211
|
+
props.onChange?.(event.target.checked, event);
|
|
212
|
+
}}
|
|
213
|
+
/>
|
|
214
|
+
<span
|
|
215
|
+
className={`ttdk-radio-control ${props.controlClass || ""}`.trim()}
|
|
216
|
+
style={{
|
|
217
|
+
...buildUiVars(props.controlStyle),
|
|
218
|
+
}}
|
|
219
|
+
>
|
|
220
|
+
{props.checked ? (
|
|
221
|
+
<span
|
|
222
|
+
className={`ttdk-radio-dot ${props.dotClass || ""}`.trim()}
|
|
223
|
+
style={{
|
|
224
|
+
...buildUiVars(props.dotStyle),
|
|
225
|
+
}}
|
|
226
|
+
/>
|
|
227
|
+
) : null}
|
|
228
|
+
</span>
|
|
229
|
+
{props.label ||
|
|
230
|
+
props.description ||
|
|
231
|
+
props.helperText ||
|
|
232
|
+
props.children ||
|
|
233
|
+
props.errorMessage ||
|
|
234
|
+
(typeof props.error === "string" && props.error) ? (
|
|
235
|
+
<div className="ttdk-radio-label-wrapper">
|
|
236
|
+
{props.label || props.children ? (
|
|
237
|
+
<span
|
|
238
|
+
className={`ttdk-radio-label ${props.labelClass || ""}`.trim()}
|
|
239
|
+
style={{
|
|
240
|
+
...buildUiVars(props.labelStyle),
|
|
241
|
+
}}
|
|
242
|
+
>
|
|
243
|
+
{props.label}
|
|
244
|
+
<>{props.children}</>
|
|
245
|
+
</span>
|
|
246
|
+
) : null}
|
|
247
|
+
{props.helperText || props.description ? (
|
|
248
|
+
<span
|
|
249
|
+
className={`ttdk-radio-desc ttdk-radio-helper-text ${
|
|
250
|
+
props.helperTextClass || props.descClass || ""
|
|
251
|
+
}`.trim()}
|
|
252
|
+
style={{
|
|
253
|
+
...buildUiVars(props.helperTextStyle || props.descStyle),
|
|
254
|
+
}}
|
|
255
|
+
onClick={(e) => {
|
|
256
|
+
e.preventDefault();
|
|
257
|
+
e.stopPropagation();
|
|
258
|
+
}}
|
|
259
|
+
>
|
|
260
|
+
{props.helperText || props.description}
|
|
261
|
+
</span>
|
|
262
|
+
) : null}
|
|
263
|
+
{props.errorMessage ||
|
|
264
|
+
(typeof props.error === "string" && props.error) ? (
|
|
265
|
+
<span
|
|
266
|
+
role="alert"
|
|
267
|
+
className={`ttdk-radio-error-msg ${
|
|
268
|
+
props.errorMessageClass || ""
|
|
269
|
+
}`.trim()}
|
|
270
|
+
style={{
|
|
271
|
+
...buildUiVars(props.errorMessageStyle),
|
|
272
|
+
}}
|
|
273
|
+
onClick={(e) => {
|
|
274
|
+
e.preventDefault();
|
|
275
|
+
e.stopPropagation();
|
|
276
|
+
}}
|
|
277
|
+
>
|
|
278
|
+
{props.errorMessage ||
|
|
279
|
+
(typeof props.error === "string" ? props.error : "")}
|
|
280
|
+
</span>
|
|
281
|
+
) : null}
|
|
282
|
+
</div>
|
|
283
|
+
) : null}
|
|
284
|
+
</label>
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export default Radio;
|
|
289
|
+
|
|
290
|
+
export { Radio };
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# <Selectbox /> — TTDK Component Reference
|
|
2
|
+
|
|
3
|
+
Komponen Selectbox TTDK sesuai spesifikasi Desain: - Single Select dengan Checkmark indicator dan Active Teal border (#00A3A6) - Multi-Select dengan Checkbox list, Chip tags (Label ✕), dan Action footer (Reset & Terapkan) - Searchable filter bar dengan input Cari 🔍 - Visual States: Default, Active/Open, Filled, Error (#FF3A39), Disabled (#E4E5E7)
|
|
4
|
+
|
|
5
|
+
## 1. Stylesheets & Theming (Pure CSS)
|
|
6
|
+
Import the corresponding stylesheet for the theme you wish to use:
|
|
7
|
+
- **COMMON Theme**: `import "@ttdk-design-system/library-<react|vue|svelte>/web/selectbox/selectbox.css";`
|
|
8
|
+
|
|
9
|
+
## 2. Subpath Component Import
|
|
10
|
+
```ts
|
|
11
|
+
// React
|
|
12
|
+
import Selectbox from "@ttdk-design-system/library-react/web/selectbox";
|
|
13
|
+
|
|
14
|
+
// Vue 3
|
|
15
|
+
import Selectbox from "@ttdk-design-system/library-vue/web/selectbox";
|
|
16
|
+
|
|
17
|
+
// Svelte
|
|
18
|
+
import Selectbox from "@ttdk-design-system/library-svelte/web/selectbox";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 3. Props & API Reference
|
|
22
|
+
|
|
23
|
+
| Prop | Type | Default | Description |
|
|
24
|
+
| :--- | :--- | :--- | :--- |
|
|
25
|
+
| `label?` | `string` | `-` | Teks label judul field yang ditampilkan di atas selectbox (14px Semibold, #141313). |
|
|
26
|
+
| `labelStyle?` | `UiProps` | `-` | Style kustom untuk elemen label judul field (UiProps). |
|
|
27
|
+
| `labelClass?` | `string` | `-` | Class CSS kustom untuk elemen label judul field. |
|
|
28
|
+
| `controlStyle?` | `UiProps` | `-` | Style kustom untuk elemen trigger kontrol selectbox (UiProps). |
|
|
29
|
+
| `controlClass?` | `string` | `-` | Class CSS kustom untuk elemen trigger kontrol selectbox. |
|
|
30
|
+
| `menuStyle?` | `UiProps` | `-` | Style kustom untuk elemen menu dropdown popover (UiProps). |
|
|
31
|
+
| `menuClass?` | `string` | `-` | Class CSS kustom untuk elemen menu dropdown popover. |
|
|
32
|
+
| `listStyle?` | `UiProps` | `-` | Alias untuk menuStyle (konsistensi dengan Dropdown listStyle). |
|
|
33
|
+
| `listClass?` | `string` | `-` | Class CSS kustom untuk opsi list dropdown (atau alias menuClass). |
|
|
34
|
+
| `errorMessageStyle?` | `UiProps` | `-` | Style kustom untuk elemen pesan error validasi (UiProps). |
|
|
35
|
+
| `errorMessageClass?` | `string` | `-` | Class CSS kustom untuk elemen pesan error validasi. |
|
|
36
|
+
| `helperTextStyle?` | `UiProps` | `-` | Style kustom untuk elemen helper text (UiProps). |
|
|
37
|
+
| `helperTextClass?` | `string` | `-` | Class CSS kustom untuk elemen helper text. |
|
|
38
|
+
| `optional?` | `boolean` | `false` | Menandai field sebagai opsi opsional dengan menambahkan teks '(Opsional)' (12px Regular, #9698A2). |
|
|
39
|
+
| `optionalText?` | `string` | `(Opsional)` | Kustomisasi teks keterangan opsional. |
|
|
40
|
+
| `placeholder?` | `string` | `Pilih dropdown menu` | Teks petunjuk saat belum ada opsi yang dipilih. |
|
|
41
|
+
| `value?` | `any` | `-` | Nilai terpilih saat ini (single string/number atau array nilai untuk mode multiple). |
|
|
42
|
+
| `defaultValue?` | `any` | `-` | Nilai awal tidak terkontrol (uncontrolled initial value). |
|
|
43
|
+
| `options?` | `Array<SelectboxOption | string>` | `-` | Daftar pilihan opsi dropdown. Dapat berupa array of object `{ label, value }` atau array of string. |
|
|
44
|
+
| `multiple?` | `boolean` | `false` | Mode pemilihan jamak (multi-select) dengan tampilan chips/tag dan daftar checkbox. |
|
|
45
|
+
| `searchable?` | `boolean` | `false` | Mengaktifkan kotak pencarian (search input) di dalam menu dropdown. |
|
|
46
|
+
| `searchPlaceholder?` | `string` | `Cari` | Placeholder pada kotak pencarian di dalam dropdown. |
|
|
47
|
+
| `applyText?` | `string` | `Terapkan` | Teks tombol terapkan pada footer multi-select. |
|
|
48
|
+
| `resetText?` | `string` | `Reset` | Teks tombol reset pada footer multi-select. |
|
|
49
|
+
| `name?` | `string` | `-` | Nama form field HTML. |
|
|
50
|
+
| `id?` | `string` | `-` | Identifier unik elemen selectbox. |
|
|
51
|
+
| `error?` | `boolean` | `false` | Status apakah selectbox sedang dalam kondisi error / tidak valid. |
|
|
52
|
+
| `errorMessage?` | `string` | `-` | Pesan teks penjelasan kesalahan validasi di bawah field. |
|
|
53
|
+
| `helperText?` | `string` | `-` | Teks petunjuk atau keterangan bantuan di bawah field (12px Regular, #3C4245). |
|
|
54
|
+
| `helperTextPosition?` | `'top' | 'bottom'` | `-` | Posisi teks helper |
|
|
55
|
+
| `size?` | `'sm' | 'md' | 'lg'` | `md` | Skala ukuran selectbox. - `'sm'`: 36px - `'md'`: 48px (standar desain) - `'lg'`: 56px |
|
|
56
|
+
| `rounded?` | `'none' | 'sm' | 'md' | 'lg' | 'full'` | `md` | Bentuk sudut kelengkungan selectbox. - `'none'`: 0px - `'sm'`: 4px - `'md'`: 8px (standar desain) - `'lg'`: 12px - `'full'`: 9999px (kapsul) |
|
|
57
|
+
| `block?` | `boolean` | `false` | Menjadikan lebar field selectbox memenuhi kontainer penuh (full-width 100%). |
|
|
58
|
+
| `disabled?` | `boolean` | `false` | Status apakah selectbox dinonaktifkan (disabled). |
|
|
59
|
+
| `required?` | `boolean` | `false` | Menandai field sebagai input wajib diisi (menampilkan tanda bintang merah *). |
|
|
60
|
+
| `inputRef?` | `any` | `-` | Ref instance elemen control selectbox untuk akses DOM langsung. |
|
|
61
|
+
| `clearable?` | `boolean` | `false` | Menampilkan tombol × untuk menghapus pilihan yang sudah dipilih. |
|
|
62
|
+
| `loading?` | `boolean` | `false` | Menampilkan spinner loading dan menonaktifkan interaksi selectbox. |
|
|
63
|
+
| `readOnly?` | `boolean` | `false` | Menjadikan selectbox hanya-baca (tidak bisa dibuka/diubah). |
|
|
64
|
+
| `style?` | `any` | `-` | Inline CSS style object native. |
|
|
65
|
+
| `ui?` | `UiProps` | `-` | Kustomisasi visual granular root / form-item (UiProps). |
|
|
66
|
+
| `onChange?` | `(value: any) => void` | `-` | Callback event saat nilai pilihan berubah. |
|
|
67
|
+
| `onSearch?` | `(query: string) => void` | `-` | Callback event saat pengguna mengetik di kolom pencarian. |
|
|
68
|
+
| `onOpen?` | `() => void` | `-` | Callback event saat menu dropdown terbuka. |
|
|
69
|
+
| `className?` | `string` | `-` | Class CSS kustom. |
|
|
70
|
+
| `disableShift?` | `boolean` | `false` | Menonaktifkan middleware `shift` pada floating-ui sehingga posisi list popover tidak bergeser secara horizontal mengikuti tepi layar. Berguna saat ingin list tetap berada di tengah atau posisi placement yang ditentukan. |
|
|
71
|
+
| `onClose?` | `() => void` | `-` | Callback event saat menu dropdown ditutup. |
|
|
72
|
+
|
|
73
|
+
### Sub-interface: `SelectboxOption`
|
|
74
|
+
|
|
75
|
+
| Field | Type | Default | Description |
|
|
76
|
+
| :--- | :--- | :--- | :--- |
|
|
77
|
+
| `label` | `string` | `-` | Teks label tampilan pilihan dropdown. |
|
|
78
|
+
| `value` | `string | number` | `-` | Nilai unik (value) dari opsi pilihan. |
|
|
79
|
+
| `disabled?` | `boolean` | `false` | Status apakah opsi ini dinonaktifkan dari pemilihan. |
|
|
80
|
+
|
|
81
|
+
## 4. Usage Examples
|
|
82
|
+
|
|
83
|
+
### React Example
|
|
84
|
+
```tsx
|
|
85
|
+
import { useState } from "react";
|
|
86
|
+
import Selectbox from "@ttdk-design-system/library-react/web/selectbox";
|
|
87
|
+
import "@ttdk-design-system/library-react/web/selectbox/selectbox.css";
|
|
88
|
+
|
|
89
|
+
export function Example() {
|
|
90
|
+
const [singleVal, setSingleVal] = useState("jabar");
|
|
91
|
+
const [multiVal, setMultiVal] = useState(["puskesmas", "rs"]);
|
|
92
|
+
|
|
93
|
+
const provinceOptions = [
|
|
94
|
+
{ label: "DKI Jakarta", value: "dki" },
|
|
95
|
+
{ label: "Jawa Barat", value: "jabar" },
|
|
96
|
+
{ label: "Jawa Tengah", value: "jateng" },
|
|
97
|
+
{ label: "Jawa Timur", value: "jatim" }
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
const faskesTypes = [
|
|
101
|
+
{ label: "Puskesmas", value: "puskesmas" },
|
|
102
|
+
{ label: "Rumah Sakit Umum", value: "rs" },
|
|
103
|
+
{ label: "Klinik Pratama", value: "klinik" },
|
|
104
|
+
{ label: "Laboratorium", value: "lab" }
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '400px' }}>
|
|
109
|
+
<Selectbox
|
|
110
|
+
label="Provinsi"
|
|
111
|
+
options={provinceOptions}
|
|
112
|
+
value={singleVal}
|
|
113
|
+
searchable
|
|
114
|
+
onChange={(val) => setSingleVal(val)}
|
|
115
|
+
/>
|
|
116
|
+
<Selectbox
|
|
117
|
+
label="Jenis Fasilitas (Multi-Select)"
|
|
118
|
+
options={faskesTypes}
|
|
119
|
+
value={multiVal}
|
|
120
|
+
multiple
|
|
121
|
+
searchable
|
|
122
|
+
onChange={(val) => setMultiVal(val)}
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Vue 3 Example
|
|
130
|
+
```vue
|
|
131
|
+
<script setup lang="ts">
|
|
132
|
+
import { ref } from "vue";
|
|
133
|
+
import Selectbox from "@ttdk-design-system/library-vue/web/selectbox";
|
|
134
|
+
import "@ttdk-design-system/library-vue/web/selectbox/selectbox.css";
|
|
135
|
+
|
|
136
|
+
const singleVal = ref("jabar");
|
|
137
|
+
const multiVal = ref(["puskesmas", "rs"]);
|
|
138
|
+
|
|
139
|
+
const provinceOptions = [
|
|
140
|
+
{ label: "DKI Jakarta", value: "dki" },
|
|
141
|
+
{ label: "Jawa Barat", value: "jabar" },
|
|
142
|
+
{ label: "Jawa Tengah", value: "jateng" },
|
|
143
|
+
{ label: "Jawa Timur", value: "jatim" }
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
const faskesTypes = [
|
|
147
|
+
{ label: "Puskesmas", value: "puskesmas" },
|
|
148
|
+
{ label: "Rumah Sakit Umum", value: "rs" },
|
|
149
|
+
{ label: "Klinik Pratama", value: "klinik" },
|
|
150
|
+
{ label: "Laboratorium", value: "lab" }
|
|
151
|
+
];
|
|
152
|
+
</script>
|
|
153
|
+
|
|
154
|
+
<template>
|
|
155
|
+
<div style="display: flex; flex-direction: column; gap: 16px; max-width: 400px;">
|
|
156
|
+
<Selectbox
|
|
157
|
+
label="Provinsi"
|
|
158
|
+
:options="provinceOptions"
|
|
159
|
+
:value="singleVal"
|
|
160
|
+
:searchable="true"
|
|
161
|
+
@change="(val: any) => (singleVal = val)"
|
|
162
|
+
/>
|
|
163
|
+
<Selectbox
|
|
164
|
+
label="Jenis Fasilitas (Multi-Select)"
|
|
165
|
+
:options="faskesTypes"
|
|
166
|
+
:value="multiVal"
|
|
167
|
+
:multiple="true"
|
|
168
|
+
:searchable="true"
|
|
169
|
+
@change="(val: any) => (multiVal = val)"
|
|
170
|
+
/>
|
|
171
|
+
</div>
|
|
172
|
+
</template>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Svelte Example
|
|
176
|
+
```svelte
|
|
177
|
+
<script lang="ts">
|
|
178
|
+
import Selectbox from "@ttdk-design-system/library-svelte/web/selectbox";
|
|
179
|
+
import "@ttdk-design-system/library-svelte/web/selectbox/selectbox.css";
|
|
180
|
+
|
|
181
|
+
let singleVal = "jabar";
|
|
182
|
+
let multiVal = ["puskesmas", "rs"];
|
|
183
|
+
|
|
184
|
+
const provinceOptions = [
|
|
185
|
+
{ label: "DKI Jakarta", value: "dki" },
|
|
186
|
+
{ label: "Jawa Barat", value: "jabar" },
|
|
187
|
+
{ label: "Jawa Tengah", value: "jateng" },
|
|
188
|
+
{ label: "Jawa Timur", value: "jatim" }
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
const faskesTypes = [
|
|
192
|
+
{ label: "Puskesmas", value: "puskesmas" },
|
|
193
|
+
{ label: "Rumah Sakit Umum", value: "rs" },
|
|
194
|
+
{ label: "Klinik Pratama", value: "klinik" },
|
|
195
|
+
{ label: "Laboratorium", value: "lab" }
|
|
196
|
+
];
|
|
197
|
+
</script>
|
|
198
|
+
|
|
199
|
+
<div style="display: flex; flex-direction: column; gap: 16px; max-width: 400px;">
|
|
200
|
+
<Selectbox
|
|
201
|
+
label="Provinsi"
|
|
202
|
+
options={provinceOptions}
|
|
203
|
+
value={singleVal}
|
|
204
|
+
searchable={true}
|
|
205
|
+
on:change={(e) => (singleVal = e.detail)}
|
|
206
|
+
/>
|
|
207
|
+
<Selectbox
|
|
208
|
+
label="Jenis Fasilitas (Multi-Select)"
|
|
209
|
+
options={faskesTypes}
|
|
210
|
+
value={multiVal}
|
|
211
|
+
multiple={true}
|
|
212
|
+
searchable={true}
|
|
213
|
+
on:change={(e) => (multiVal = e.detail)}
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
216
|
+
```
|