gladvn 0.2.35 → 0.2.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +2 -1
- package/scripts/strip-comments.ts +79 -0
- package/src/blocks/auth-form.tsx +34 -30
- package/src/blocks/auth-recovery.tsx +9 -13
- package/src/blocks/auth-split.tsx +46 -36
- package/src/blocks/settings.tsx +84 -117
- package/src/components/macro/alert-preset.tsx +3 -1
- package/src/components/macro/carousel-preset.tsx +0 -1
- package/src/components/macro/checkbox-preset.test.tsx +2 -2
- package/src/components/macro/checkbox-preset.tsx +1 -2
- package/src/components/macro/command-preset.tsx +1 -1
- package/src/components/macro/date-picker.tsx +5 -18
- package/src/components/macro/dialog-preset.tsx +5 -3
- package/src/components/macro/input-preset.tsx +0 -1
- package/src/components/macro/select-preset.tsx +1 -1
- package/src/components/macro/switch-preset.test.tsx +1 -1
- package/src/components/micro/accordion.test.tsx +6 -12
- package/src/components/micro/alert-dialog.tsx +0 -2
- package/src/components/micro/alert.test.tsx +5 -8
- package/src/components/micro/alert.tsx +0 -2
- package/src/components/micro/badge.test.tsx +5 -7
- package/src/components/micro/badge.tsx +1 -3
- package/src/components/micro/button.test.tsx +19 -26
- package/src/components/micro/button.tsx +3 -11
- package/src/components/micro/calendar.tsx +12 -13
- package/src/components/micro/card.test.tsx +3 -5
- package/src/components/micro/carousel.tsx +0 -1
- package/src/components/micro/chart.tsx +3 -2
- package/src/components/micro/checkbox.test.tsx +9 -18
- package/src/components/micro/combobox.tsx +1 -3
- package/src/components/micro/command.tsx +23 -11
- package/src/components/micro/context-menu.tsx +0 -2
- package/src/components/micro/dialog.test.tsx +6 -14
- package/src/components/micro/dialog.tsx +0 -2
- package/src/components/micro/drawer.tsx +0 -3
- package/src/components/micro/dropdown-menu.test.tsx +8 -14
- package/src/components/micro/dropdown-menu.tsx +0 -2
- package/src/components/micro/field.tsx +3 -3
- package/src/components/micro/hover-card.tsx +0 -2
- package/src/components/micro/input-group.tsx +9 -42
- package/src/components/micro/input.test.tsx +15 -24
- package/src/components/micro/navigation-menu.tsx +0 -2
- package/src/components/micro/popover.test.tsx +5 -9
- package/src/components/micro/progress.tsx +5 -1
- package/src/components/micro/select.test.tsx +5 -18
- package/src/components/micro/select.tsx +3 -5
- package/src/components/micro/separator.tsx +1 -1
- package/src/components/micro/sheet.test.tsx +6 -14
- package/src/components/micro/sheet.tsx +0 -2
- package/src/components/micro/sidebar.tsx +5 -6
- package/src/components/micro/sonner.tsx +0 -1
- package/src/components/micro/switch.test.tsx +9 -18
- package/src/components/micro/switch.tsx +1 -1
- package/src/components/micro/tabs.test.tsx +5 -11
- package/src/components/micro/theme-provider.tsx +0 -12
- package/src/components/micro/toggle-group.tsx +1 -12
- package/src/components/micro/tooltip.test.tsx +7 -12
- package/src/dev/App.tsx +6 -6
- package/src/dev/components/BlockViewer.tsx +15 -4
- package/src/dev/components/Container.tsx +20 -0
- package/src/dev/components/GladvnLogo.tsx +3 -9
- package/src/dev/components/code-highlighter.tsx +5 -3
- package/src/dev/components/showcase.tsx +116 -168
- package/src/dev/sections/buttons.tsx +4 -9
- package/src/dev/sections/display.tsx +68 -72
- package/src/dev/sections/feedback.tsx +304 -314
- package/src/dev/sections/forms.tsx +10 -14
- package/src/dev/sections/interactive.tsx +32 -32
- package/src/dev/sections/overview.tsx +2 -10
- package/src/dev/showcase/accordion.tsx +512 -554
- package/src/dev/showcase/alert-dialog.tsx +525 -565
- package/src/dev/showcase/alert.tsx +352 -402
- package/src/dev/showcase/aspect-ratio.tsx +167 -193
- package/src/dev/showcase/avatar.tsx +231 -269
- package/src/dev/showcase/badge.tsx +92 -140
- package/src/dev/showcase/breadcrumb.tsx +113 -135
- package/src/dev/showcase/button.tsx +140 -173
- package/src/dev/showcase/calendar.tsx +187 -237
- package/src/dev/showcase/card.tsx +229 -261
- package/src/dev/showcase/carousel.tsx +288 -315
- package/src/dev/showcase/chart.tsx +44 -50
- package/src/dev/showcase/checkbox.tsx +286 -330
- package/src/dev/showcase/collapsible.tsx +143 -160
- package/src/dev/showcase/combobox.tsx +327 -369
- package/src/dev/showcase/command.tsx +106 -120
- package/src/dev/showcase/context-menu.tsx +93 -107
- package/src/dev/showcase/dialog.tsx +585 -630
- package/src/dev/showcase/drawer.tsx +176 -196
- package/src/dev/showcase/dropdown-menu.tsx +183 -201
- package/src/dev/showcase/empty.tsx +232 -274
- package/src/dev/showcase/hover-card.tsx +153 -180
- package/src/dev/showcase/input-group.tsx +221 -253
- package/src/dev/showcase/input-otp.tsx +204 -250
- package/src/dev/showcase/input.tsx +246 -325
- package/src/dev/showcase/item.tsx +134 -152
- package/src/dev/showcase/kbd.tsx +149 -172
- package/src/dev/showcase/label.tsx +50 -68
- package/src/dev/showcase/menubar.tsx +194 -213
- package/src/dev/showcase/navigation-menu.tsx +119 -133
- package/src/dev/showcase/overview-components/ArchitectureSection.tsx +126 -0
- package/src/dev/showcase/overview-components/CodeBlock.tsx +50 -0
- package/src/dev/showcase/overview-components/ColorPaletteSection.tsx +44 -0
- package/src/dev/showcase/overview-components/DashboardPreview.tsx +159 -0
- package/src/dev/showcase/overview-components/FeatureGridSection.tsx +535 -0
- package/src/dev/showcase/overview-components/FooterCTA.tsx +137 -0
- package/src/dev/showcase/overview-components/HeroSection.tsx +65 -0
- package/src/dev/showcase/overview-components/PrinciplesSection.tsx +128 -0
- package/src/dev/showcase/overview.tsx +21 -1163
- package/src/dev/showcase/pagination.tsx +144 -190
- package/src/dev/showcase/popover.tsx +181 -196
- package/src/dev/showcase/progress.tsx +141 -189
- package/src/dev/showcase/radio-group.tsx +272 -332
- package/src/dev/showcase/resizable.tsx +119 -141
- package/src/dev/showcase/scroll-area.tsx +21 -36
- package/src/dev/showcase/select.tsx +262 -322
- package/src/dev/showcase/separator.tsx +75 -73
- package/src/dev/showcase/sheet.tsx +333 -361
- package/src/dev/showcase/sidebar.tsx +53 -59
- package/src/dev/showcase/skeleton.tsx +93 -112
- package/src/dev/showcase/slider.tsx +244 -296
- package/src/dev/showcase/sonner.tsx +251 -258
- package/src/dev/showcase/spinner.tsx +46 -67
- package/src/dev/showcase/switch.tsx +298 -362
- package/src/dev/showcase/table.tsx +76 -80
- package/src/dev/showcase/tabs.tsx +302 -355
- package/src/dev/showcase/textarea.tsx +240 -293
- package/src/dev/showcase/toast.tsx +48 -54
- package/src/dev/showcase/toggle-group.tsx +104 -129
- package/src/dev/showcase/toggle.tsx +82 -102
- package/src/dev/showcase/tooltip.tsx +173 -192
- package/src/dev/showcase/why.tsx +6 -12
- package/src/hooks/use-mobile.test.ts +3 -2
- package/src/lib/utils.test.ts +5 -4
|
@@ -19,122 +19,105 @@ import {
|
|
|
19
19
|
DocsH3,
|
|
20
20
|
DocsP,
|
|
21
21
|
ExampleGrid,
|
|
22
|
-
|
|
22
|
+
ShowcaseExample,
|
|
23
23
|
Showcase,
|
|
24
24
|
ShowcaseDocs
|
|
25
25
|
} from "../../dev/components/showcase";
|
|
26
26
|
import { type Size } from "../../lib/types";
|
|
27
27
|
|
|
28
|
-
// ──────────────────────────────────────────────────────────
|
|
29
|
-
// SECTION 1: Macro Content
|
|
30
|
-
// ──────────────────────────────────────────────────────────
|
|
31
28
|
function InputOTPMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
32
29
|
return (
|
|
33
|
-
<div className="space-y-10
|
|
30
|
+
<div className="space-y-10">
|
|
34
31
|
<ExampleGrid>
|
|
35
|
-
<
|
|
36
|
-
label="Tiêu chuẩn (2 nhóm)"
|
|
37
|
-
description="Chia mã 6 số thành 2 nhóm (mỗi nhóm 3 số) cách nhau bởi dấu gạch ngang."
|
|
38
|
-
codeString={`<InputOTPPreset
|
|
32
|
+
<ShowcaseExample title="Tiêu chuẩn (2 nhóm)" description="Chia mã 6 số thành 2 nhóm (mỗi nhóm 3 số) cách nhau bởi dấu gạch ngang." code={`<InputOTPPreset
|
|
39
33
|
groups={[3, 3]}
|
|
40
34
|
size="md"
|
|
41
35
|
label="Mã xác thực"
|
|
42
36
|
description="Vui lòng nhập mã 6 số được gửi tới điện thoại của bạn."
|
|
43
|
-
/>`}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
/>`} preview={
|
|
38
|
+
<>
|
|
39
|
+
<InputOTPPreset
|
|
40
|
+
className="w-full"
|
|
41
|
+
groups={[3, 3]}
|
|
42
|
+
size={globalSize}
|
|
43
|
+
label="Mã xác thực"
|
|
44
|
+
description="Vui lòng nhập mã 6 số được gửi tới điện thoại của bạn."
|
|
45
|
+
/>
|
|
46
|
+
</>
|
|
47
|
+
} />
|
|
53
48
|
|
|
54
|
-
<
|
|
55
|
-
label="Trạng thái Lỗi (Error)"
|
|
56
|
-
description="Hiển thị viền đỏ và thông báo lỗi khi nhập sai mã."
|
|
57
|
-
codeString={`<InputOTPPreset
|
|
49
|
+
<ShowcaseExample title="Trạng thái Lỗi (Error)" description="Hiển thị viền đỏ và thông báo lỗi khi nhập sai mã." code={`<InputOTPPreset
|
|
58
50
|
groups={[3, 3]}
|
|
59
51
|
size="md"
|
|
60
52
|
label="Mã bảo mật"
|
|
61
53
|
errorMessage="Mã xác nhận không chính xác. Vui lòng thử lại."
|
|
62
|
-
/>`}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
54
|
+
/>`} preview={
|
|
55
|
+
<>
|
|
56
|
+
<InputOTPPreset
|
|
57
|
+
className="w-full"
|
|
58
|
+
groups={[3, 3]}
|
|
59
|
+
size={globalSize}
|
|
60
|
+
label="Mã bảo mật (Lỗi)"
|
|
61
|
+
errorMessage="Mã xác nhận không chính xác. Vui lòng thử lại."
|
|
62
|
+
/>
|
|
63
|
+
</>
|
|
64
|
+
} />
|
|
72
65
|
</ExampleGrid>
|
|
73
66
|
|
|
74
67
|
<ExampleGrid>
|
|
75
|
-
<
|
|
76
|
-
label="Khóa / Bất hoạt (Disabled)"
|
|
77
|
-
description="Người dùng không thể nhập mã khi ở trạng thái này."
|
|
78
|
-
codeString={`<InputOTPPreset
|
|
68
|
+
<ShowcaseExample title="Khóa / Bất hoạt (Disabled)" description="Người dùng không thể nhập mã khi ở trạng thái này." code={`<InputOTPPreset
|
|
79
69
|
groups={[4]}
|
|
80
70
|
size="md"
|
|
81
71
|
label="Mã khôi phục"
|
|
82
72
|
description="Tài khoản của bạn đang bị khóa tạm thời."
|
|
83
73
|
disabled
|
|
84
|
-
/>`}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
74
|
+
/>`} preview={
|
|
75
|
+
<>
|
|
76
|
+
<InputOTPPreset
|
|
77
|
+
className="w-full"
|
|
78
|
+
groups={[4]}
|
|
79
|
+
size={globalSize}
|
|
80
|
+
label="Mã khôi phục"
|
|
81
|
+
description="Tài khoản của bạn đang bị khóa tạm thời."
|
|
82
|
+
disabled
|
|
83
|
+
/>
|
|
84
|
+
</>
|
|
85
|
+
} />
|
|
95
86
|
|
|
96
|
-
<
|
|
97
|
-
label="Tuỳ biến Nhóm & Dấu phân cách"
|
|
98
|
-
description="Dùng mảng groups tuỳ ý và đổi icon phân cách."
|
|
99
|
-
codeString={`<InputOTPPreset
|
|
87
|
+
<ShowcaseExample title="Tuỳ biến Nhóm & Dấu phân cách" description="Dùng mảng groups tuỳ ý và đổi icon phân cách." code={`<InputOTPPreset
|
|
100
88
|
groups={[2, 2, 2]}
|
|
101
89
|
separator={
|
|
102
90
|
<span className="text-muted-foreground/50">/</span>
|
|
103
91
|
}
|
|
104
92
|
size="md"
|
|
105
93
|
label="Ngày sinh (DD/MM/YY)"
|
|
106
|
-
/>`}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
94
|
+
/>`} preview={
|
|
95
|
+
<>
|
|
96
|
+
<div className="w-full flex flex-col gap-6">
|
|
97
|
+
<InputOTPPreset
|
|
98
|
+
groups={[2, 2, 2]}
|
|
99
|
+
separator={
|
|
100
|
+
<span className="text-muted-foreground/50 text-sm font-semibold">
|
|
101
|
+
/
|
|
102
|
+
</span>
|
|
103
|
+
}
|
|
104
|
+
size={globalSize}
|
|
105
|
+
label="Định dạng tuỳ chỉnh"
|
|
106
|
+
description="Chia thành 3 nhóm, phân cách bằng dấu gạch chéo."
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
</>
|
|
110
|
+
} />
|
|
122
111
|
</ExampleGrid>
|
|
123
112
|
</div>
|
|
124
113
|
);
|
|
125
114
|
}
|
|
126
115
|
|
|
127
|
-
// ──────────────────────────────────────────────────────────
|
|
128
|
-
// SECTION 2: Micro Content
|
|
129
|
-
// ──────────────────────────────────────────────────────────
|
|
130
116
|
function InputOTPMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
131
117
|
return (
|
|
132
|
-
<div className="space-y-10
|
|
118
|
+
<div className="space-y-10">
|
|
133
119
|
<ExampleGrid>
|
|
134
|
-
<
|
|
135
|
-
label="Cơ bản (Primitive)"
|
|
136
|
-
description="Mã 6 chữ số liền mạch không có dấu phân cách."
|
|
137
|
-
codeString={`<Field size="md">
|
|
120
|
+
<ShowcaseExample title="Cơ bản (Primitive)" description="Mã 6 chữ số liền mạch không có dấu phân cách." code={`<Field size="md">
|
|
138
121
|
<FieldLabel htmlFor="otp-basic">Mã PIN</FieldLabel>
|
|
139
122
|
<FieldContent>
|
|
140
123
|
<InputOTP id="otp-basic" size="md" maxLength={6}>
|
|
@@ -145,29 +128,27 @@ function InputOTPMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
145
128
|
</InputOTPGroup>
|
|
146
129
|
</InputOTP>
|
|
147
130
|
</FieldContent>
|
|
148
|
-
</Field>`}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
131
|
+
</Field>`} preview={
|
|
132
|
+
<>
|
|
133
|
+
<Field className="w-full" size={globalSize}>
|
|
134
|
+
<FieldLabel htmlFor="tf-otp-0">Mã PIN</FieldLabel>
|
|
135
|
+
<FieldContent>
|
|
136
|
+
<InputOTP id="tf-otp-0" size={globalSize} maxLength={6}>
|
|
137
|
+
<InputOTPGroup>
|
|
138
|
+
{Array.from({ length: 6 }).map((_, index) => (
|
|
139
|
+
<InputOTPSlot
|
|
140
|
+
key={`tf-otp-0-slot-${index}`}
|
|
141
|
+
index={index}
|
|
142
|
+
/>
|
|
143
|
+
))}
|
|
144
|
+
</InputOTPGroup>
|
|
145
|
+
</InputOTP>
|
|
146
|
+
</FieldContent>
|
|
147
|
+
</Field>
|
|
148
|
+
</>
|
|
149
|
+
} />
|
|
166
150
|
|
|
167
|
-
<
|
|
168
|
-
label="Phân tách thủ công"
|
|
169
|
-
description="Tự chèn InputOTPSeparator vào giữa các nhóm."
|
|
170
|
-
codeString={`<Field size="md">
|
|
151
|
+
<ShowcaseExample title="Phân tách thủ công" description="Tự chèn InputOTPSeparator vào giữa các nhóm." code={`<Field size="md">
|
|
171
152
|
<FieldLabel htmlFor="otp-sep">Mã bảo mật</FieldLabel>
|
|
172
153
|
<FieldContent>
|
|
173
154
|
<InputOTP id="otp-sep" size="md" maxLength={6}>
|
|
@@ -184,40 +165,38 @@ function InputOTPMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
184
165
|
</InputOTPGroup>
|
|
185
166
|
</InputOTP>
|
|
186
167
|
</FieldContent>
|
|
187
|
-
</Field>`}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
168
|
+
</Field>`} preview={
|
|
169
|
+
<>
|
|
170
|
+
<Field className="w-full" size={globalSize}>
|
|
171
|
+
<FieldLabel htmlFor="tf-otp-1">Mã bảo mật</FieldLabel>
|
|
172
|
+
<FieldContent>
|
|
173
|
+
<InputOTP id="tf-otp-1" size={globalSize} maxLength={6}>
|
|
174
|
+
<InputOTPGroup>
|
|
175
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
176
|
+
<InputOTPSlot
|
|
177
|
+
key={`tf-otp-1-slot-a-${index}`}
|
|
178
|
+
index={index}
|
|
179
|
+
/>
|
|
180
|
+
))}
|
|
181
|
+
</InputOTPGroup>
|
|
182
|
+
<InputOTPSeparator />
|
|
183
|
+
<InputOTPGroup>
|
|
184
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
185
|
+
<InputOTPSlot
|
|
186
|
+
key={`tf-otp-1-slot-b-${index + 3}`}
|
|
187
|
+
index={index + 3}
|
|
188
|
+
/>
|
|
189
|
+
))}
|
|
190
|
+
</InputOTPGroup>
|
|
191
|
+
</InputOTP>
|
|
192
|
+
</FieldContent>
|
|
193
|
+
</Field>
|
|
194
|
+
</>
|
|
195
|
+
} />
|
|
214
196
|
</ExampleGrid>
|
|
215
197
|
|
|
216
198
|
<ExampleGrid>
|
|
217
|
-
<
|
|
218
|
-
label="Trạng thái Lỗi thủ công"
|
|
219
|
-
description="Gắn data-invalid vào Field để thay đổi màu sắc."
|
|
220
|
-
codeString={`<Field size="md" data-invalid={true}>
|
|
199
|
+
<ShowcaseExample title="Trạng thái Lỗi thủ công" description="Gắn data-invalid vào Field để thay đổi màu sắc." code={`<Field size="md" data-invalid={true}>
|
|
221
200
|
<FieldLabel htmlFor="otp-err">Mã xác minh</FieldLabel>
|
|
222
201
|
<FieldContent>
|
|
223
202
|
<InputOTP id="otp-err" size="md" maxLength={4}>
|
|
@@ -229,30 +208,28 @@ function InputOTPMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
229
208
|
</InputOTP>
|
|
230
209
|
</FieldContent>
|
|
231
210
|
<FieldError>Mã không hợp lệ.</FieldError>
|
|
232
|
-
</Field>`}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
211
|
+
</Field>`} preview={
|
|
212
|
+
<>
|
|
213
|
+
<Field className="w-full" size={globalSize} data-invalid={true}>
|
|
214
|
+
<FieldLabel htmlFor="tf-otp-err">Mã xác minh</FieldLabel>
|
|
215
|
+
<FieldContent>
|
|
216
|
+
<InputOTP id="tf-otp-err" size={globalSize} maxLength={4}>
|
|
217
|
+
<InputOTPGroup>
|
|
218
|
+
{Array.from({ length: 4 }).map((_, index) => (
|
|
219
|
+
<InputOTPSlot
|
|
220
|
+
key={`tf-otp-err-slot-${index}`}
|
|
221
|
+
index={index}
|
|
222
|
+
/>
|
|
223
|
+
))}
|
|
224
|
+
</InputOTPGroup>
|
|
225
|
+
</InputOTP>
|
|
226
|
+
</FieldContent>
|
|
227
|
+
<FieldError>Mã không hợp lệ.</FieldError>
|
|
228
|
+
</Field>
|
|
229
|
+
</>
|
|
230
|
+
} />
|
|
251
231
|
|
|
252
|
-
<
|
|
253
|
-
label="Disabled thủ công"
|
|
254
|
-
description="Truyền thuộc tính disabled."
|
|
255
|
-
codeString={`<Field size="md">
|
|
232
|
+
<ShowcaseExample title="Disabled thủ công" description="Truyền thuộc tính disabled." code={`<Field size="md">
|
|
256
233
|
<FieldLabel htmlFor="otp-disabled">Mã OTP</FieldLabel>
|
|
257
234
|
<FieldContent>
|
|
258
235
|
<InputOTP
|
|
@@ -268,38 +245,34 @@ function InputOTPMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
268
245
|
</InputOTPGroup>
|
|
269
246
|
</InputOTP>
|
|
270
247
|
</FieldContent>
|
|
271
|
-
</Field>`}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
248
|
+
</Field>`} preview={
|
|
249
|
+
<>
|
|
250
|
+
<Field className="w-full" size={globalSize}>
|
|
251
|
+
<FieldLabel htmlFor="tf-otp-d">Mã OTP</FieldLabel>
|
|
252
|
+
<FieldContent>
|
|
253
|
+
<InputOTP id="tf-otp-d" size={globalSize} maxLength={4} disabled>
|
|
254
|
+
<InputOTPGroup>
|
|
255
|
+
{Array.from({ length: 4 }).map((_, index) => (
|
|
256
|
+
<InputOTPSlot
|
|
257
|
+
key={`tf-otp-d-slot-${index}`}
|
|
258
|
+
index={index}
|
|
259
|
+
/>
|
|
260
|
+
))}
|
|
261
|
+
</InputOTPGroup>
|
|
262
|
+
</InputOTP>
|
|
263
|
+
</FieldContent>
|
|
264
|
+
</Field>
|
|
265
|
+
</>
|
|
266
|
+
} />
|
|
289
267
|
</ExampleGrid>
|
|
290
268
|
|
|
291
|
-
<
|
|
292
|
-
label="🧭 Use Case Comparison"
|
|
293
|
-
description="So sánh nhanh khi nào dùng Micro và Macro."
|
|
294
|
-
fullWidth
|
|
295
|
-
codeString={`{/* Macro — đơn giản, 1 dòng khai báo */}
|
|
269
|
+
<ShowcaseExample title="🧭 So sánh Use Case" description="So sánh nhanh khi nào dùng Micro và Macro." code={`{}
|
|
296
270
|
<InputOTPPreset
|
|
297
271
|
groups={[3, 3]}
|
|
298
272
|
size="md"
|
|
299
273
|
label="Mã xác thực"
|
|
300
274
|
/>
|
|
301
275
|
|
|
302
|
-
{/* Micro — khi cần custom từng slot */}
|
|
303
276
|
<InputOTP size="md" maxLength={6}>
|
|
304
277
|
<InputOTPGroup>
|
|
305
278
|
{Array.from({ length: 3 }).map((_, i) => (
|
|
@@ -312,56 +285,57 @@ function InputOTPMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
312
285
|
<InputOTPSlot key={i + 3} index={i + 3} />
|
|
313
286
|
))}
|
|
314
287
|
</InputOTPGroup>
|
|
315
|
-
</InputOTP>`}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
288
|
+
</InputOTP>`} preview={
|
|
289
|
+
<>
|
|
290
|
+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
291
|
+
{/* Story 1: Macro wins */}
|
|
292
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
293
|
+
<div className="flex items-start gap-3">
|
|
294
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
|
|
295
|
+
<ShieldIcon className="size-4" aria-hidden="true" />
|
|
296
|
+
</span>
|
|
297
|
+
<div>
|
|
298
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
299
|
+
Story 1 · Dùng Macro
|
|
300
|
+
</p>
|
|
301
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
302
|
+
Form xác thực SMS thông thường
|
|
303
|
+
</h3>
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
307
|
+
Thay vì phải dùng vòng lặp <DocsCode>.map()</DocsCode> dài dòng
|
|
308
|
+
cho từng nhóm số, dùng Preset{" "}
|
|
309
|
+
<DocsCode>groups={`{[3, 3]}`}</DocsCode> để code sinh ra y chang
|
|
310
|
+
chỉ với 1 dòng khai báo. Cực kỳ sạch.
|
|
311
|
+
</p>
|
|
312
|
+
</div>
|
|
340
313
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
314
|
+
{/* Story 2: Micro wins */}
|
|
315
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
316
|
+
<div className="flex items-start gap-3">
|
|
317
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
|
|
318
|
+
<WrenchIcon className="size-4" aria-hidden="true" />
|
|
319
|
+
</span>
|
|
320
|
+
<div>
|
|
321
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
322
|
+
Story 2 · Dùng Micro
|
|
323
|
+
</p>
|
|
324
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
325
|
+
Custom Slot Design
|
|
326
|
+
</h3>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
330
|
+
Bạn cần can thiệp trực tiếp vào từng ô số (ví dụ: style lại các ô
|
|
331
|
+
đầu là số, ô cuối là chữ cái đặc biệt, hoặc xen kẽ Icon vào giữa
|
|
332
|
+
thay vì dấu gạch ngang). Lúc này bạn buộc phải viết vòng lặp{" "}
|
|
333
|
+
<DocsCode>.map()</DocsCode> và dùng Micro.
|
|
334
|
+
</p>
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
</>
|
|
338
|
+
} />
|
|
365
339
|
</div>
|
|
366
340
|
);
|
|
367
341
|
}
|
|
@@ -375,38 +349,18 @@ export default function InputOTPShowcase() {
|
|
|
375
349
|
<Showcase
|
|
376
350
|
title="Input OTP"
|
|
377
351
|
description="Trường nhập mật khẩu một lần (One-Time Password) có khả năng tự động tách chữ số và paste."
|
|
378
|
-
|
|
352
|
+
guideline={
|
|
379
353
|
<ShowcaseDocs>
|
|
380
354
|
<DocsP>
|
|
381
355
|
Dùng để nhập các đoạn mã có chiều dài cố định như OTP, PIN code,
|
|
382
356
|
2FA.
|
|
383
357
|
</DocsP>
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
<DocsCode>InputOTPPreset</DocsCode> tự động sinh ra các nhóm số
|
|
387
|
-
(`InputOTPGroup`) và dấu phân cách (`InputOTPSeparator`) dựa vào
|
|
388
|
-
prop <DocsCode>groups</DocsCode> (ví dụ: `groups={[3, 3]}`). Dùng
|
|
389
|
-
Preset này cho 99% các trường hợp form nhập mã xác thực (OTP) vì nó
|
|
390
|
-
đã tích hợp sẵn Label và Error Message.
|
|
391
|
-
</DocsP>
|
|
392
|
-
<DocsH3>Khi nào nên dùng Micro</DocsH3>
|
|
393
|
-
<DocsP>
|
|
394
|
-
Dùng <DocsCode>InputOTP</DocsCode> và{" "}
|
|
395
|
-
<DocsCode>InputOTPGroup</DocsCode> thủ công khi bạn cần một giao
|
|
396
|
-
diện nhập mã đặc thù không theo chuẩn (ví dụ: các ô số nằm rải rác
|
|
397
|
-
trong một thiết kế đồ hoạ) hoặc khi chèn trực tiếp vào một luồng
|
|
398
|
-
không có Label đi kèm.
|
|
399
|
-
</DocsP>
|
|
358
|
+
|
|
359
|
+
|
|
400
360
|
</ShowcaseDocs>
|
|
401
361
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
label: "Micro (Primitive)",
|
|
405
|
-
content: <InputOTPMicroShowcase globalSize={globalSize} /> },
|
|
406
|
-
{
|
|
407
|
-
label: "Macro (Preset)",
|
|
408
|
-
content: <InputOTPMacroShowcase globalSize={globalSize} /> },
|
|
409
|
-
]}
|
|
362
|
+
micro={{ content: <InputOTPMicroShowcase globalSize={globalSize} /> }}
|
|
363
|
+
macro={{ content: <InputOTPMacroShowcase globalSize={globalSize} /> }}
|
|
410
364
|
/>
|
|
411
365
|
);
|
|
412
366
|
}
|