@ttdk-design-system/library-vue 0.0.0-stage → 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.
Files changed (232) hide show
  1. package/AI_GUIDE.md +6518 -0
  2. package/llms.txt +6518 -0
  3. package/package.json +1096 -4
  4. package/src/core/index.ts +2 -0
  5. package/src/core/tailwind-preset.cjs +62 -0
  6. package/src/core/tailwind-preset.ts +85 -0
  7. package/src/core/theme/tokens.css +663 -0
  8. package/src/core/types.ts +836 -0
  9. package/src/index.ts +17 -0
  10. package/src/tailwind-preset.cjs +62 -0
  11. package/src/tailwind-preset.ts +85 -0
  12. package/src/types.ts +1 -0
  13. package/src/web/accordion/AI_GUIDE.md +149 -0
  14. package/src/web/accordion/accordion.css +1 -0
  15. package/src/web/accordion/accordion.vue +432 -0
  16. package/src/web/accordion/accordion.vue.d.ts +227 -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.vue +290 -0
  22. package/src/web/alert/alert.vue.d.ts +154 -0
  23. package/src/web/alert/index.ts +3 -0
  24. package/src/web/alert/manifest.json +240 -0
  25. package/src/web/avatar/AI_GUIDE.md +118 -0
  26. package/src/web/avatar/avatar.css +1 -0
  27. package/src/web/avatar/avatar.vue +217 -0
  28. package/src/web/avatar/avatar.vue.d.ts +135 -0
  29. package/src/web/avatar/index.ts +3 -0
  30. package/src/web/avatar/manifest.json +195 -0
  31. package/src/web/badge/AI_GUIDE.md +94 -0
  32. package/src/web/badge/badge.css +1 -0
  33. package/src/web/badge/badge.vue +135 -0
  34. package/src/web/badge/badge.vue.d.ts +108 -0
  35. package/src/web/badge/index.ts +3 -0
  36. package/src/web/badge/manifest.json +141 -0
  37. package/src/web/banner/AI_GUIDE.md +130 -0
  38. package/src/web/banner/banner.css +1 -0
  39. package/src/web/banner/banner.vue +303 -0
  40. package/src/web/banner/banner.vue.d.ts +162 -0
  41. package/src/web/banner/index.ts +3 -0
  42. package/src/web/banner/manifest.json +240 -0
  43. package/src/web/breadcrumb/AI_GUIDE.md +120 -0
  44. package/src/web/breadcrumb/breadcrumb.css +1 -0
  45. package/src/web/breadcrumb/breadcrumb.vue +313 -0
  46. package/src/web/breadcrumb/breadcrumb.vue.d.ts +139 -0
  47. package/src/web/breadcrumb/index.ts +3 -0
  48. package/src/web/breadcrumb/manifest.json +225 -0
  49. package/src/web/button/AI_GUIDE.md +121 -0
  50. package/src/web/button/button.css +1 -0
  51. package/src/web/button/button.vue +283 -0
  52. package/src/web/button/button.vue.d.ts +147 -0
  53. package/src/web/button/index.ts +3 -0
  54. package/src/web/button/manifest.json +177 -0
  55. package/src/web/calendar/AI_GUIDE.md +151 -0
  56. package/src/web/calendar/calendar.css +1 -0
  57. package/src/web/calendar/calendar.vue +1536 -0
  58. package/src/web/calendar/calendar.vue.d.ts +261 -0
  59. package/src/web/calendar/index.ts +3 -0
  60. package/src/web/calendar/manifest.json +470 -0
  61. package/src/web/card/AI_GUIDE.md +133 -0
  62. package/src/web/card/card.css +1 -0
  63. package/src/web/card/card.vue +423 -0
  64. package/src/web/card/card.vue.d.ts +232 -0
  65. package/src/web/card/index.ts +3 -0
  66. package/src/web/card/manifest.json +357 -0
  67. package/src/web/checkbox/AI_GUIDE.md +146 -0
  68. package/src/web/checkbox/checkbox.css +1 -0
  69. package/src/web/checkbox/checkbox.vue +304 -0
  70. package/src/web/checkbox/checkbox.vue.d.ts +189 -0
  71. package/src/web/checkbox/index.ts +3 -0
  72. package/src/web/checkbox/manifest.json +294 -0
  73. package/src/web/chip/AI_GUIDE.md +186 -0
  74. package/src/web/chip/chip.css +1 -0
  75. package/src/web/chip/chip.vue +220 -0
  76. package/src/web/chip/chip.vue.d.ts +140 -0
  77. package/src/web/chip/index.ts +3 -0
  78. package/src/web/chip/manifest.json +186 -0
  79. package/src/web/dropdown/AI_GUIDE.md +167 -0
  80. package/src/web/dropdown/dropdown.css +1 -0
  81. package/src/web/dropdown/dropdown.vue +1257 -0
  82. package/src/web/dropdown/dropdown.vue.d.ts +381 -0
  83. package/src/web/dropdown/index.ts +3 -0
  84. package/src/web/dropdown/manifest.json +576 -0
  85. package/src/web/flex/AI_GUIDE.md +113 -0
  86. package/src/web/flex/flex-item.vue +94 -0
  87. package/src/web/flex/flex-item.vue.d.ts +84 -0
  88. package/src/web/flex/flex.css +1 -0
  89. package/src/web/flex/flex.vue +103 -0
  90. package/src/web/flex/flex.vue.d.ts +92 -0
  91. package/src/web/flex/index.ts +5 -0
  92. package/src/web/flex/manifest.json +162 -0
  93. package/src/web/form/index.ts +7 -0
  94. package/src/web/grid/AI_GUIDE.md +112 -0
  95. package/src/web/grid/grid-item.vue +109 -0
  96. package/src/web/grid/grid-item.vue.d.ts +99 -0
  97. package/src/web/grid/grid.css +1 -0
  98. package/src/web/grid/grid.vue +94 -0
  99. package/src/web/grid/grid.vue.d.ts +84 -0
  100. package/src/web/grid/index.ts +5 -0
  101. package/src/web/grid/manifest.json +153 -0
  102. package/src/web/index.ts +86 -0
  103. package/src/web/input/AI_GUIDE.md +159 -0
  104. package/src/web/input/index.ts +3 -0
  105. package/src/web/input/input.css +1 -0
  106. package/src/web/input/input.vue +521 -0
  107. package/src/web/input/input.vue.d.ts +274 -0
  108. package/src/web/input/manifest.json +465 -0
  109. package/src/web/input-number/AI_GUIDE.md +164 -0
  110. package/src/web/input-number/index.ts +3 -0
  111. package/src/web/input-number/input-number.css +1 -0
  112. package/src/web/input-number/input-number.vue +1153 -0
  113. package/src/web/input-number/input-number.vue.d.ts +343 -0
  114. package/src/web/input-number/manifest.json +575 -0
  115. package/src/web/modal/AI_GUIDE.md +171 -0
  116. package/src/web/modal/index.ts +3 -0
  117. package/src/web/modal/manifest.json +375 -0
  118. package/src/web/modal/modal.css +1 -0
  119. package/src/web/modal/modal.vue +344 -0
  120. package/src/web/modal/modal.vue.d.ts +64 -0
  121. package/src/web/pagination/AI_GUIDE.md +148 -0
  122. package/src/web/pagination/index.ts +21 -0
  123. package/src/web/pagination/manifest.json +432 -0
  124. package/src/web/pagination/pagination-content.vue +42 -0
  125. package/src/web/pagination/pagination-content.vue.d.ts +28 -0
  126. package/src/web/pagination/pagination-ellipsis.vue +55 -0
  127. package/src/web/pagination/pagination-ellipsis.vue.d.ts +28 -0
  128. package/src/web/pagination/pagination-first.vue +161 -0
  129. package/src/web/pagination/pagination-first.vue.d.ts +67 -0
  130. package/src/web/pagination/pagination-item.vue +42 -0
  131. package/src/web/pagination/pagination-item.vue.d.ts +28 -0
  132. package/src/web/pagination/pagination-last.vue +161 -0
  133. package/src/web/pagination/pagination-last.vue.d.ts +67 -0
  134. package/src/web/pagination/pagination-link.vue +118 -0
  135. package/src/web/pagination/pagination-link.vue.d.ts +61 -0
  136. package/src/web/pagination/pagination-next.vue +160 -0
  137. package/src/web/pagination/pagination-next.vue.d.ts +68 -0
  138. package/src/web/pagination/pagination-previous.vue +160 -0
  139. package/src/web/pagination/pagination-previous.vue.d.ts +68 -0
  140. package/src/web/pagination/pagination.css +1 -0
  141. package/src/web/pagination/pagination.vue +730 -0
  142. package/src/web/pagination/pagination.vue.d.ts +247 -0
  143. package/src/web/popover/AI_GUIDE.md +163 -0
  144. package/src/web/popover/index.ts +3 -0
  145. package/src/web/popover/manifest.json +396 -0
  146. package/src/web/popover/popover.css +1 -0
  147. package/src/web/popover/popover.vue +579 -0
  148. package/src/web/popover/popover.vue.d.ts +83 -0
  149. package/src/web/radio/AI_GUIDE.md +155 -0
  150. package/src/web/radio/index.ts +3 -0
  151. package/src/web/radio/manifest.json +294 -0
  152. package/src/web/radio/radio.css +1 -0
  153. package/src/web/radio/radio.vue +288 -0
  154. package/src/web/radio/radio.vue.d.ts +182 -0
  155. package/src/web/selectbox/AI_GUIDE.md +216 -0
  156. package/src/web/selectbox/index.ts +3 -0
  157. package/src/web/selectbox/manifest.json +477 -0
  158. package/src/web/selectbox/selectbox.css +1 -0
  159. package/src/web/selectbox/selectbox.vue +1024 -0
  160. package/src/web/selectbox/selectbox.vue.d.ts +300 -0
  161. package/src/web/sonner/AI_GUIDE.md +98 -0
  162. package/src/web/sonner/index.ts +114 -0
  163. package/src/web/sonner/manifest.json +132 -0
  164. package/src/web/sonner/sonner.css +1 -0
  165. package/src/web/sonner/sonner.vue +180 -0
  166. package/src/web/sonner/sonner.vue.d.ts +113 -0
  167. package/src/web/table/AI_GUIDE.md +145 -0
  168. package/src/web/table/index.ts +34 -0
  169. package/src/web/table/manifest.json +168 -0
  170. package/src/web/table/table-body.vue +42 -0
  171. package/src/web/table/table-body.vue.d.ts +28 -0
  172. package/src/web/table/table-caption.vue +42 -0
  173. package/src/web/table/table-caption.vue.d.ts +28 -0
  174. package/src/web/table/table-cell.vue +71 -0
  175. package/src/web/table/table-cell.vue.d.ts +49 -0
  176. package/src/web/table/table-empty.vue +105 -0
  177. package/src/web/table/table-empty.vue.d.ts +57 -0
  178. package/src/web/table/table-footer.vue +42 -0
  179. package/src/web/table/table-footer.vue.d.ts +28 -0
  180. package/src/web/table/table-head.vue +78 -0
  181. package/src/web/table/table-head.vue.d.ts +50 -0
  182. package/src/web/table/table-header.vue +42 -0
  183. package/src/web/table/table-header.vue.d.ts +28 -0
  184. package/src/web/table/table-row.vue +70 -0
  185. package/src/web/table/table-row.vue.d.ts +44 -0
  186. package/src/web/table/table.css +1 -0
  187. package/src/web/table/table.vue +298 -0
  188. package/src/web/table/table.vue.d.ts +119 -0
  189. package/src/web/tabs/AI_GUIDE.md +150 -0
  190. package/src/web/tabs/index.ts +2 -0
  191. package/src/web/tabs/manifest.json +315 -0
  192. package/src/web/tabs/tabs.css +1 -0
  193. package/src/web/tabs/tabs.vue +164 -0
  194. package/src/web/tabs/tabs.vue.d.ts +60 -0
  195. package/src/web/text/AI_GUIDE.md +129 -0
  196. package/src/web/text/index.ts +2 -0
  197. package/src/web/text/manifest.json +195 -0
  198. package/src/web/text/text.css +1 -0
  199. package/src/web/text/text.vue +195 -0
  200. package/src/web/text/text.vue.d.ts +161 -0
  201. package/src/web/textarea/AI_GUIDE.md +141 -0
  202. package/src/web/textarea/index.ts +3 -0
  203. package/src/web/textarea/manifest.json +438 -0
  204. package/src/web/textarea/textarea.css +1 -0
  205. package/src/web/textarea/textarea.vue +458 -0
  206. package/src/web/textarea/textarea.vue.d.ts +265 -0
  207. package/src/web/tooltip/AI_GUIDE.md +110 -0
  208. package/src/web/tooltip/index.ts +3 -0
  209. package/src/web/tooltip/manifest.json +222 -0
  210. package/src/web/tooltip/tooltip.css +1 -0
  211. package/src/web/tooltip/tooltip.vue +417 -0
  212. package/src/web/tooltip/tooltip.vue.d.ts +150 -0
  213. package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
  214. package/src/webview/bottomsheet/bottomsheet.css +1 -0
  215. package/src/webview/bottomsheet/bottomsheet.vue +441 -0
  216. package/src/webview/bottomsheet/bottomsheet.vue.d.ts +178 -0
  217. package/src/webview/bottomsheet/index.ts +4 -0
  218. package/src/webview/bottomsheet/manifest.json +377 -0
  219. package/src/webview/button/AI_GUIDE.md +79 -0
  220. package/src/webview/button/button-ios.css +1 -0
  221. package/src/webview/button/button-ios.vue +138 -0
  222. package/src/webview/button/button-ios.vue.d.ts +102 -0
  223. package/src/webview/button/button-material.css +1 -0
  224. package/src/webview/button/button-material.vue +138 -0
  225. package/src/webview/button/button-material.vue.d.ts +102 -0
  226. package/src/webview/button/index.ts +7 -0
  227. package/src/webview/button/manifest.json +148 -0
  228. package/src/webview/index.ts +7 -0
  229. package/tailwind-preset.cjs +62 -0
  230. package/tailwind-preset.js +62 -0
  231. package/ttdk-manifest.json +10188 -0
  232. package/README.md +0 -3
@@ -0,0 +1,458 @@
1
+ <template>
2
+ <div
3
+ :class="`ttdk-form-item ${className || ''}`.trim()"
4
+ :data-disabled="disabled"
5
+ :data-error="Boolean(error || errorMessage)"
6
+ :data-size="size || 'md'"
7
+ :data-block="block ? 'true' : undefined"
8
+ :style="{
9
+ ...buildUiVars(ui),
10
+ ...(ui || {}),
11
+ ...(typeof style === 'object' ? style : {}),
12
+ }"
13
+ >
14
+ <template v-if="label">
15
+ <label
16
+ :class="`ttdk-form-label ${labelClass || ''}`.trim()"
17
+ :for="id"
18
+ :style="{
19
+ ...buildUiVars(labelStyle),
20
+ }"
21
+ ><span>{{ label }}</span>
22
+ <template v-if="required">
23
+ <span class="ttdk-form-required" aria-hidden="true"> * </span>
24
+ </template>
25
+
26
+ <template v-if="optional">
27
+ <span class="ttdk-form-optional">{{
28
+ optionalText || "(Opsional)"
29
+ }}</span>
30
+ </template>
31
+ </label>
32
+ </template>
33
+
34
+ <template v-if="helperText && helperTextPosition === 'top'">
35
+ <div
36
+ :class="`ttdk-form-helper-text ${helperTextClass || ''}`.trim()"
37
+ :style="{
38
+ ...buildUiVars(helperTextStyle),
39
+ }"
40
+ >
41
+ {{ helperText }}
42
+ </div>
43
+ </template>
44
+
45
+ <div
46
+ :class="`ttdk-textarea-wrapper ${wrapperClass || ''}`.trim()"
47
+ :data-filled="Boolean(value !== undefined ? value : innerValue)"
48
+ :data-error="Boolean(error || errorMessage)"
49
+ :data-disabled="Boolean(disabled)"
50
+ :data-size="size || 'md'"
51
+ :data-rounded="rounded || 'md'"
52
+ :style="{
53
+ ...buildUiVars(wrapperStyle),
54
+ }"
55
+ >
56
+ <textarea
57
+ ref="inputRef"
58
+ :class="`ttdk-textarea-control ${textareaClass || ''}`.trim()"
59
+ :name="name"
60
+ :id="id"
61
+ :value="value !== undefined ? value : innerValue"
62
+ :placeholder="placeholder"
63
+ :rows="rows || 4"
64
+ :disabled="disabled"
65
+ :readOnly="readOnly"
66
+ :required="required"
67
+ :autocomplete="autoComplete"
68
+ :maxLength="maxLength"
69
+ :minLength="minLength"
70
+ :aria-invalid="Boolean(error || errorMessage)"
71
+ :style="{
72
+ resize: resize || 'vertical',
73
+ ...buildUiVars(textareaStyle),
74
+ }"
75
+ @change="async (e) => handleChange(e)"
76
+ @input="async (e) => handleInput(e)"
77
+ @blur="async (e) => onBlur && onBlur(e)"
78
+ @focus="async (e) => onFocus && onFocus(e)"
79
+ @keydown="async (e) => onKeyDown && onKeyDown(e)"
80
+ @keyup="async (e) => onKeyUp && onKeyUp(e)"
81
+ ></textarea>
82
+ </div>
83
+ <template
84
+ v-if="
85
+ (helperText && helperTextPosition !== 'top') ||
86
+ (errorMessage && (error || errorMessage)) ||
87
+ showCount
88
+ "
89
+ >
90
+ <div class="ttdk-form-footer">
91
+ <template
92
+ v-if="
93
+ (helperText && helperTextPosition !== 'top') ||
94
+ (errorMessage && (error || errorMessage))
95
+ "
96
+ >
97
+ <div class="ttdk-form-footer-message">
98
+ <template v-if="helperText && helperTextPosition !== 'top'">
99
+ <div
100
+ :class="`ttdk-form-helper-text ${helperTextClass || ''}`.trim()"
101
+ :style="{
102
+ ...buildUiVars(helperTextStyle),
103
+ }"
104
+ >
105
+ {{ helperText }}
106
+ </div>
107
+ </template>
108
+
109
+ <template v-if="errorMessage && (error || errorMessage)">
110
+ <div
111
+ role="alert"
112
+ :class="`ttdk-form-error-msg ${errorMessageClass || ''}`.trim()"
113
+ :style="{
114
+ ...buildUiVars(errorMessageStyle),
115
+ }"
116
+ >
117
+ <span>{{ errorMessage }}</span>
118
+ </div>
119
+ </template>
120
+ </div>
121
+ </template>
122
+
123
+ <template v-if="showCount">
124
+ <div
125
+ aria-live="polite"
126
+ :class="`ttdk-form-char-count ${charCountClass || ''}`.trim()"
127
+ :style="{
128
+ ...buildUiVars(charCountStyle),
129
+ }"
130
+ >
131
+ {{ currentLength }}
132
+ <template v-if="maxLength">
133
+ {{ ` / ${maxLength}` }}
134
+ </template>
135
+
136
+ <template v-else>
137
+ <div _text=""></div>
138
+ </template>
139
+ </div>
140
+ </template>
141
+ </div>
142
+ </template>
143
+ </div>
144
+ </template>
145
+
146
+ <script setup lang="ts">
147
+ import { computed, ref, watch } from "vue";
148
+
149
+ import { buildUiVars, UiProps } from "../../core/types";
150
+
151
+ export type TextareaUiProps = UiProps;
152
+ export interface TextareaProps {
153
+ /**
154
+ * Teks label judul field yang ditampilkan di atas textarea (14px Semibold, #141313).
155
+ */
156
+ label?: string;
157
+
158
+ /**
159
+ * Style kustom untuk elemen label judul field (UiProps).
160
+ */
161
+ labelStyle?: UiProps;
162
+
163
+ /**
164
+ * Class CSS kustom untuk elemen label judul field.
165
+ */
166
+ labelClass?: string;
167
+
168
+ /**
169
+ * Style kustom untuk elemen kontainer textarea wrapper (UiProps).
170
+ */
171
+ wrapperStyle?: UiProps;
172
+
173
+ /**
174
+ * Class CSS kustom untuk elemen kontainer textarea wrapper.
175
+ */
176
+ wrapperClass?: string;
177
+
178
+ /**
179
+ * Style kustom untuk elemen textarea control HTML (UiProps).
180
+ */
181
+ textareaStyle?: UiProps;
182
+
183
+ /**
184
+ * Class CSS kustom untuk elemen textarea control HTML.
185
+ */
186
+ textareaClass?: string;
187
+
188
+ /**
189
+ * Style kustom untuk elemen pesan error validasi (UiProps).
190
+ */
191
+ errorMessageStyle?: UiProps;
192
+
193
+ /**
194
+ * Class CSS kustom untuk elemen pesan error validasi.
195
+ */
196
+ errorMessageClass?: string;
197
+
198
+ /**
199
+ * Style kustom untuk elemen helper text (UiProps).
200
+ */
201
+ helperTextStyle?: UiProps;
202
+
203
+ /**
204
+ * Class CSS kustom untuk elemen helper text.
205
+ */
206
+ helperTextClass?: string;
207
+
208
+ /**
209
+ * Style kustom untuk elemen penghitung karakter (UiProps).
210
+ */
211
+ charCountStyle?: UiProps;
212
+
213
+ /**
214
+ * Class CSS kustom untuk elemen penghitung karakter.
215
+ */
216
+ charCountClass?: string;
217
+
218
+ /**
219
+ * Menandai field sebagai opsi opsional dengan menambahkan teks '(Opsional)' (12px Regular, #9698A2).
220
+ */
221
+ optional?: boolean;
222
+
223
+ /**
224
+ * Kustomisasi teks keterangan opsional.
225
+ * @default '(Opsional)'
226
+ */
227
+ optionalText?: string;
228
+
229
+ /**
230
+ * Nilai teks placeholder saat textarea kosong (#9698A2).
231
+ */
232
+ placeholder?: string;
233
+
234
+ /**
235
+ * Nilai terkontrol (controlled value) pada textarea.
236
+ */
237
+ value?: string;
238
+
239
+ /**
240
+ * Nilai awal tidak terkontrol (uncontrolled initial value).
241
+ */
242
+ defaultValue?: string;
243
+
244
+ /**
245
+ * Jumlah baris default yang ditampilkan.
246
+ * @default 4
247
+ */
248
+ rows?: number;
249
+
250
+ /**
251
+ * Nama form field HTML untuk integrasi formulir.
252
+ */
253
+ name?: string;
254
+
255
+ /**
256
+ * Identifier unik elemen textarea.
257
+ */
258
+ id?: string;
259
+
260
+ /**
261
+ * Kontrol orientasi resize oleh pengguna.
262
+ * - `'none'`: Tidak dapat di-resize
263
+ * - `'vertical'`: Hanya dapat di-resize vertikal (standar)
264
+ * - `'horizontal'`: Hanya dapat di-resize horizontal
265
+ * - `'both'`: Bebas di-resize kedua arah
266
+ * @default 'vertical'
267
+ */
268
+ resize?: "none" | "vertical" | "horizontal" | "both";
269
+
270
+ /**
271
+ * Status apakah textarea sedang dalam kondisi error / tidak valid.
272
+ * @default false
273
+ */
274
+ error?: boolean;
275
+
276
+ /**
277
+ * Pesan teks penjelasan kesalahan validasi di bawah field.
278
+ */
279
+ errorMessage?: string;
280
+
281
+ /**
282
+ * Teks petunjuk atau keterangan bantuan di bawah field (12px Regular, #3C4245).
283
+ */
284
+ helperText?: string;
285
+
286
+ /**
287
+ * Posisi teks helper
288
+ */
289
+ helperTextPosition?: "top" | "bottom";
290
+
291
+ /**
292
+ * Skala ukuran textarea.
293
+ * - `'sm'`: Padding rapat
294
+ * - `'md'`: Standar
295
+ * - `'lg'`: Padding lapang
296
+ * @default 'md'
297
+ */
298
+ size?: "sm" | "md" | "lg";
299
+
300
+ /**
301
+ * Bentuk sudut kelengkungan textarea.
302
+ * - `'none'`: 0px
303
+ * - `'sm'`: 4px
304
+ * - `'md'`: 8px (standar desain)
305
+ * - `'lg'`: 12px
306
+ * - `'full'`: 16px
307
+ * @default 'md'
308
+ */
309
+ rounded?: "none" | "sm" | "md" | "lg" | "full";
310
+
311
+ /**
312
+ * Menjadikan lebar field textarea memenuhi kontainer penuh (full-width 100%).
313
+ * @default false
314
+ */
315
+ block?: boolean;
316
+
317
+ /**
318
+ * Status apakah field dinonaktifkan (disabled).
319
+ * @default false
320
+ */
321
+ disabled?: boolean;
322
+
323
+ /**
324
+ * Status apakah field bersifat hanya-baca (readonly).
325
+ * @default false
326
+ */
327
+ readOnly?: boolean;
328
+
329
+ /**
330
+ * Menandai field sebagai input wajib diisi (menampilkan tanda bintang merah *).
331
+ * @default false
332
+ */
333
+ required?: boolean;
334
+
335
+ /**
336
+ * Konfigurasi atribut autocomplete HTML.
337
+ */
338
+ autoComplete?: string;
339
+
340
+ /**
341
+ * Batas maksimum panjang karakter.
342
+ */
343
+ maxLength?: number;
344
+
345
+ /**
346
+ * Batas minimum panjang karakter.
347
+ */
348
+ minLength?: number;
349
+
350
+ /**
351
+ * Inline CSS style object native.
352
+ */
353
+ style?: any;
354
+
355
+ /**
356
+ * Kustomisasi visual granular root / form-item (UiProps).
357
+ */
358
+ ui?: UiProps;
359
+
360
+ /**
361
+ * Callback event saat nilai textarea berubah.
362
+ */
363
+ onChange?: (event: any) => void;
364
+
365
+ /**
366
+ * Callback event saat pengguna mengetik (input event).
367
+ */
368
+ onInput?: (event: any) => void;
369
+
370
+ /**
371
+ * Callback event saat textarea kehilangan fokus (blur).
372
+ */
373
+ onBlur?: (event: any) => void;
374
+
375
+ /**
376
+ * Callback event saat textarea mendapatkan fokus.
377
+ */
378
+ onFocus?: (event: any) => void;
379
+
380
+ /**
381
+ * Ref instance elemen textarea HTML untuk akses kontrol DOM langsung (focus, blur, select).
382
+ */
383
+ inputRef?: any;
384
+
385
+ /**
386
+ * Class CSS kustom.
387
+ */
388
+ className?: string;
389
+
390
+ /**
391
+ * Callback event tombol keyboard ditekan.
392
+ */
393
+ onKeyDown?: (event: any) => void;
394
+
395
+ /**
396
+ * Callback event tombol keyboard dilepaskan.
397
+ */
398
+ onKeyUp?: (event: any) => void;
399
+
400
+ /**
401
+ * Menampilkan penghitung karakter di bawah textarea (format: `x / maxLength`).
402
+ * Memerlukan prop `maxLength` untuk berfungsi.
403
+ * @default false
404
+ */
405
+ showCount?: boolean;
406
+ }
407
+
408
+ /**
409
+ * Komponen Textarea TTDK sesuai spesifikasi Anatomy Desain:
410
+ * 1. Field title (14px Semibold, #141313)
411
+ * 2. (Opsional) label (12px Regular, #9698A2)
412
+ * 3. Border radius 8px
413
+ * 4. Field content (14px Regular, #141313, placeholder #9698A2)
414
+ * 5. Additional information / Helper text (12px Regular, #3C4245)
415
+ */
416
+
417
+ const props = defineProps<TextareaProps>();
418
+ const innerValue = ref(
419
+ props.value !== undefined
420
+ ? String(props.value)
421
+ : props.defaultValue !== undefined
422
+ ? String(props.defaultValue)
423
+ : ""
424
+ );
425
+
426
+ const currentLength = computed(() => {
427
+ if (props.value !== undefined) {
428
+ return String(props.value).length;
429
+ }
430
+ return innerValue.value.length;
431
+ });
432
+
433
+ watch(
434
+ () => [props.value],
435
+ () => {
436
+ if (props.value !== undefined) {
437
+ innerValue.value = String(props.value);
438
+ }
439
+ },
440
+ { immediate: true }
441
+ );
442
+ function handleInput(e: any) {
443
+ if (props.value === undefined) {
444
+ innerValue.value = e.target.value;
445
+ }
446
+ if (props.onInput) {
447
+ props.onInput(e);
448
+ }
449
+ }
450
+ function handleChange(e: any) {
451
+ if (props.value === undefined) {
452
+ innerValue.value = e.target.value;
453
+ }
454
+ if (props.onChange) {
455
+ props.onChange(e);
456
+ }
457
+ }
458
+ </script>
@@ -0,0 +1,265 @@
1
+ /* eslint-disable */
2
+ // Auto-generated by TTDK Design System Vue Type Generator
3
+ import type { DefineComponent } from "vue";
4
+ import { buildUiVars, UiProps } from "../../core/types";
5
+
6
+ export type TextareaUiProps = UiProps;
7
+
8
+ export interface TextareaProps {
9
+ /**
10
+ * Teks label judul field yang ditampilkan di atas textarea (14px Semibold, #141313).
11
+ */
12
+ label?: string;
13
+
14
+ /**
15
+ * Style kustom untuk elemen label judul field (UiProps).
16
+ */
17
+ labelStyle?: UiProps;
18
+
19
+ /**
20
+ * Class CSS kustom untuk elemen label judul field.
21
+ */
22
+ labelClass?: string;
23
+
24
+ /**
25
+ * Style kustom untuk elemen kontainer textarea wrapper (UiProps).
26
+ */
27
+ wrapperStyle?: UiProps;
28
+
29
+ /**
30
+ * Class CSS kustom untuk elemen kontainer textarea wrapper.
31
+ */
32
+ wrapperClass?: string;
33
+
34
+ /**
35
+ * Style kustom untuk elemen textarea control HTML (UiProps).
36
+ */
37
+ textareaStyle?: UiProps;
38
+
39
+ /**
40
+ * Class CSS kustom untuk elemen textarea control HTML.
41
+ */
42
+ textareaClass?: string;
43
+
44
+ /**
45
+ * Style kustom untuk elemen pesan error validasi (UiProps).
46
+ */
47
+ errorMessageStyle?: UiProps;
48
+
49
+ /**
50
+ * Class CSS kustom untuk elemen pesan error validasi.
51
+ */
52
+ errorMessageClass?: string;
53
+
54
+ /**
55
+ * Style kustom untuk elemen helper text (UiProps).
56
+ */
57
+ helperTextStyle?: UiProps;
58
+
59
+ /**
60
+ * Class CSS kustom untuk elemen helper text.
61
+ */
62
+ helperTextClass?: string;
63
+
64
+ /**
65
+ * Style kustom untuk elemen penghitung karakter (UiProps).
66
+ */
67
+ charCountStyle?: UiProps;
68
+
69
+ /**
70
+ * Class CSS kustom untuk elemen penghitung karakter.
71
+ */
72
+ charCountClass?: string;
73
+
74
+ /**
75
+ * Menandai field sebagai opsi opsional dengan menambahkan teks '(Opsional)' (12px Regular, #9698A2).
76
+ */
77
+ optional?: boolean;
78
+
79
+ /**
80
+ * Kustomisasi teks keterangan opsional.
81
+ * @default '(Opsional)'
82
+ */
83
+ optionalText?: string;
84
+
85
+ /**
86
+ * Nilai teks placeholder saat textarea kosong (#9698A2).
87
+ */
88
+ placeholder?: string;
89
+
90
+ /**
91
+ * Nilai terkontrol (controlled value) pada textarea.
92
+ */
93
+ value?: string;
94
+
95
+ /**
96
+ * Nilai awal tidak terkontrol (uncontrolled initial value).
97
+ */
98
+ defaultValue?: string;
99
+
100
+ /**
101
+ * Jumlah baris default yang ditampilkan.
102
+ * @default 4
103
+ */
104
+ rows?: number;
105
+
106
+ /**
107
+ * Nama form field HTML untuk integrasi formulir.
108
+ */
109
+ name?: string;
110
+
111
+ /**
112
+ * Identifier unik elemen textarea.
113
+ */
114
+ id?: string;
115
+
116
+ /**
117
+ * Kontrol orientasi resize oleh pengguna.
118
+ * - `'none'`: Tidak dapat di-resize
119
+ * - `'vertical'`: Hanya dapat di-resize vertikal (standar)
120
+ * - `'horizontal'`: Hanya dapat di-resize horizontal
121
+ * - `'both'`: Bebas di-resize kedua arah
122
+ * @default 'vertical'
123
+ */
124
+ resize?: "none" | "vertical" | "horizontal" | "both";
125
+
126
+ /**
127
+ * Status apakah textarea sedang dalam kondisi error / tidak valid.
128
+ * @default false
129
+ */
130
+ error?: boolean;
131
+
132
+ /**
133
+ * Pesan teks penjelasan kesalahan validasi di bawah field.
134
+ */
135
+ errorMessage?: string;
136
+
137
+ /**
138
+ * Teks petunjuk atau keterangan bantuan di bawah field (12px Regular, #3C4245).
139
+ */
140
+ helperText?: string;
141
+
142
+ /**
143
+ * Posisi teks helper
144
+ */
145
+ helperTextPosition?: "top" | "bottom";
146
+
147
+ /**
148
+ * Skala ukuran textarea.
149
+ * - `'sm'`: Padding rapat
150
+ * - `'md'`: Standar
151
+ * - `'lg'`: Padding lapang
152
+ * @default 'md'
153
+ */
154
+ size?: "sm" | "md" | "lg";
155
+
156
+ /**
157
+ * Bentuk sudut kelengkungan textarea.
158
+ * - `'none'`: 0px
159
+ * - `'sm'`: 4px
160
+ * - `'md'`: 8px (standar desain)
161
+ * - `'lg'`: 12px
162
+ * - `'full'`: 16px
163
+ * @default 'md'
164
+ */
165
+ rounded?: "none" | "sm" | "md" | "lg" | "full";
166
+
167
+ /**
168
+ * Menjadikan lebar field textarea memenuhi kontainer penuh (full-width 100%).
169
+ * @default false
170
+ */
171
+ block?: boolean;
172
+
173
+ /**
174
+ * Status apakah field dinonaktifkan (disabled).
175
+ * @default false
176
+ */
177
+ disabled?: boolean;
178
+
179
+ /**
180
+ * Status apakah field bersifat hanya-baca (readonly).
181
+ * @default false
182
+ */
183
+ readOnly?: boolean;
184
+
185
+ /**
186
+ * Menandai field sebagai input wajib diisi (menampilkan tanda bintang merah *).
187
+ * @default false
188
+ */
189
+ required?: boolean;
190
+
191
+ /**
192
+ * Konfigurasi atribut autocomplete HTML.
193
+ */
194
+ autoComplete?: string;
195
+
196
+ /**
197
+ * Batas maksimum panjang karakter.
198
+ */
199
+ maxLength?: number;
200
+
201
+ /**
202
+ * Batas minimum panjang karakter.
203
+ */
204
+ minLength?: number;
205
+
206
+ /**
207
+ * Inline CSS style object native.
208
+ */
209
+ style?: any;
210
+
211
+ /**
212
+ * Kustomisasi visual granular root / form-item (UiProps).
213
+ */
214
+ ui?: UiProps;
215
+
216
+ /**
217
+ * Callback event saat nilai textarea berubah.
218
+ */
219
+ onChange?: (event: any) => void;
220
+
221
+ /**
222
+ * Callback event saat pengguna mengetik (input event).
223
+ */
224
+ onInput?: (event: any) => void;
225
+
226
+ /**
227
+ * Callback event saat textarea kehilangan fokus (blur).
228
+ */
229
+ onBlur?: (event: any) => void;
230
+
231
+ /**
232
+ * Callback event saat textarea mendapatkan fokus.
233
+ */
234
+ onFocus?: (event: any) => void;
235
+
236
+ /**
237
+ * Ref instance elemen textarea HTML untuk akses kontrol DOM langsung (focus, blur, select).
238
+ */
239
+ inputRef?: any;
240
+
241
+ /**
242
+ * Class CSS kustom.
243
+ */
244
+ className?: string;
245
+
246
+ /**
247
+ * Callback event tombol keyboard ditekan.
248
+ */
249
+ onKeyDown?: (event: any) => void;
250
+
251
+ /**
252
+ * Callback event tombol keyboard dilepaskan.
253
+ */
254
+ onKeyUp?: (event: any) => void;
255
+
256
+ /**
257
+ * Menampilkan penghitung karakter di bawah textarea (format: `x / maxLength`).
258
+ * Memerlukan prop `maxLength` untuk berfungsi.
259
+ * @default false
260
+ */
261
+ showCount?: boolean;
262
+ }
263
+
264
+ declare const component: DefineComponent<TextareaProps>;
265
+ export default component;