@bigtablet/design-system 1.13.0 → 1.14.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/dist/index.css CHANGED
@@ -6,8 +6,6 @@
6
6
  .card_bordered {
7
7
  border: 1px solid #e5e5e5;
8
8
  }
9
- .card {
10
- }
11
9
  .card_shadow_none {
12
10
  box-shadow: none;
13
11
  }
@@ -20,8 +18,6 @@
20
18
  .card_shadow_lg {
21
19
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(0, 0, 0, 0.06);
22
20
  }
23
- .card {
24
- }
25
21
  .card_p_none {
26
22
  padding: 0;
27
23
  }
@@ -34,8 +30,6 @@
34
30
  .card_p_lg {
35
31
  padding: 1.5rem;
36
32
  }
37
- .card {
38
- }
39
33
  .card_title {
40
34
  font-size: 1.25rem;
41
35
  font-weight: 600;
@@ -43,14 +37,12 @@
43
37
  margin-bottom: 0.75rem;
44
38
  color: #1f2937;
45
39
  }
46
- .card {
47
- }
48
40
  .card_body {
49
41
  width: 100%;
50
42
  }
51
43
 
52
44
  /* src/ui/feedback/alert/style.scss */
53
- @keyframes fade_in {
45
+ @keyframes alert_fade_in {
54
46
  from {
55
47
  opacity: 0;
56
48
  }
@@ -58,7 +50,7 @@
58
50
  opacity: 1;
59
51
  }
60
52
  }
61
- @keyframes slide_up {
53
+ @keyframes alert_slide_up {
62
54
  from {
63
55
  opacity: 0;
64
56
  transform: translateY(20px);
@@ -76,7 +68,7 @@
76
68
  align-items: center;
77
69
  justify-content: center;
78
70
  z-index: 10000;
79
- animation: fade_in 0.2s ease-in-out;
71
+ animation: alert_fade_in 0.2s ease-in-out;
80
72
  }
81
73
  .alert_modal {
82
74
  background: #ffffff;
@@ -84,17 +76,17 @@
84
76
  min-width: 320px;
85
77
  max-width: 480px;
86
78
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
87
- animation: slide_up 0.3s ease-in-out;
79
+ animation: alert_slide_up 0.3s ease-in-out;
88
80
  overflow: hidden;
89
81
  }
90
- .alert_modal_title {
82
+ .alert_title {
91
83
  font-size: 1.125rem;
92
84
  line-height: 1.5;
93
85
  font-weight: 600;
94
86
  color: #3b82f6;
95
87
  padding: 0.75rem 1.25rem 0.25rem;
96
88
  }
97
- .alert_modal_message {
89
+ .alert_message {
98
90
  font-size: 0.9375rem;
99
91
  font-weight: 400;
100
92
  line-height: 1.5;
@@ -102,22 +94,22 @@
102
94
  padding: 1.25rem;
103
95
  line-height: 1.75;
104
96
  }
105
- .alert_modal_actions {
97
+ .alert_actions {
106
98
  display: flex;
107
99
  gap: 0.5rem;
108
100
  align-items: center;
109
101
  padding: 0 1.25rem 1.25rem;
110
102
  }
111
- .alert_modal_actions_left {
103
+ .alert_actions_left {
112
104
  justify-content: flex-start;
113
105
  }
114
- .alert_modal_actions_center {
106
+ .alert_actions_center {
115
107
  justify-content: center;
116
108
  }
117
- .alert_modal_actions_right {
109
+ .alert_actions_right {
118
110
  justify-content: flex-end;
119
111
  }
120
- .alert_modal_button {
112
+ .alert_button {
121
113
  min-width: 80px;
122
114
  padding: 10px 24px;
123
115
  border-radius: 6px;
@@ -131,87 +123,115 @@
131
123
  box-shadow 0.2s ease-in-out,
132
124
  transform 0.2s ease-in-out;
133
125
  }
134
- .alert_modal_button:focus-visible {
126
+ .alert_button:focus-visible {
135
127
  outline: none;
136
128
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.15);
137
129
  }
138
- .alert_modal_button:active:not(:disabled) {
130
+ .alert_button:active:not(:disabled) {
139
131
  transform: scale(0.98);
140
132
  }
141
- .alert_modal_button:disabled {
133
+ .alert_button:disabled {
142
134
  cursor: not-allowed;
143
135
  opacity: 0.6;
144
136
  }
145
- .alert_modal_button_cancel {
137
+ .alert_button_cancel {
146
138
  background: #ffffff;
147
139
  border-color: #e5e5e5;
148
140
  color: #1a1a1a;
149
141
  }
150
- .alert_modal_button_cancel:hover:not(:disabled) {
142
+ .alert_button_cancel:hover:not(:disabled) {
151
143
  background: #fafafa;
152
144
  border-color: rgba(0, 0, 0, 0.08);
153
145
  }
154
- .alert_modal_button_confirm {
146
+ .alert_button_confirm {
155
147
  color: #ffffff;
156
148
  }
157
- .alert_modal_info .alert_modal_title {
149
+ .alert_variant_info .alert_title {
158
150
  color: #3b82f6;
159
151
  }
160
- .alert_modal_info .alert_modal_button_confirm {
152
+ .alert_variant_info .alert_button_confirm {
161
153
  background: #3b82f6;
162
154
  border-color: #3b82f6;
163
155
  }
164
- .alert_modal_info .alert_modal_button_confirm:hover:not(:disabled) {
156
+ .alert_variant_info .alert_button_confirm:hover:not(:disabled) {
165
157
  background: rgb(29.7434146341, 111.3414634146, 244.6565853659);
166
158
  border-color: rgb(29.7434146341, 111.3414634146, 244.6565853659);
167
159
  }
168
- .alert_modal_success .alert_modal_title {
160
+ .alert_variant_success .alert_title {
169
161
  color: #10b981;
170
162
  }
171
- .alert_modal_success .alert_modal_button_confirm {
163
+ .alert_variant_success .alert_button_confirm {
172
164
  background: #10b981;
173
165
  border-color: #10b981;
174
166
  }
175
- .alert_modal_success .alert_modal_button_confirm:hover:not(:disabled) {
167
+ .alert_variant_success .alert_button_confirm:hover:not(:disabled) {
176
168
  background: rgb(13.5641791045, 156.8358208955, 109.3611940299);
177
169
  border-color: rgb(13.5641791045, 156.8358208955, 109.3611940299);
178
170
  }
179
- .alert_modal_warning .alert_modal_title {
171
+ .alert_variant_warning .alert_title {
180
172
  color: #f59e0b;
181
173
  }
182
- .alert_modal_warning .alert_modal_button_confirm {
174
+ .alert_variant_warning .alert_button_confirm {
183
175
  background: #f59e0b;
184
176
  border-color: #f59e0b;
185
177
  }
186
- .alert_modal_warning .alert_modal_button_confirm:hover:not(:disabled) {
178
+ .alert_variant_warning .alert_button_confirm:hover:not(:disabled) {
187
179
  background: rgb(216.525984252, 139.3220472441, 8.874015748);
188
180
  border-color: rgb(216.525984252, 139.3220472441, 8.874015748);
189
181
  }
190
- .alert_modal_error .alert_modal_title {
182
+ .alert_variant_error .alert_title {
191
183
  color: #ef4444;
192
184
  }
193
- .alert_modal_error .alert_modal_button_confirm {
185
+ .alert_variant_error .alert_button_confirm {
194
186
  background: #ef4444;
195
187
  border-color: #ef4444;
196
188
  }
197
- .alert_modal_error .alert_modal_button_confirm:hover:not(:disabled) {
189
+ .alert_variant_error .alert_button_confirm:hover:not(:disabled) {
198
190
  background: rgb(236.5881773399, 39.8118226601, 39.8118226601);
199
191
  border-color: rgb(236.5881773399, 39.8118226601, 39.8118226601);
200
192
  }
201
193
 
202
- /* src/ui/feedback/loading/style.scss */
203
- @keyframes loading_spin {
194
+ /* src/ui/feedback/spinner/style.scss */
195
+ @keyframes spinner_spin {
204
196
  to {
205
197
  transform: rotate(360deg);
206
198
  }
207
199
  }
208
- .loading {
200
+ .spinner {
209
201
  display: inline-block;
210
202
  box-sizing: border-box;
211
203
  border-radius: 50%;
212
204
  border: 2px solid #e5e5e5;
213
205
  border-top-color: #000000;
214
- animation: loading_spin 0.8s linear infinite;
206
+ animation: spinner_spin 0.8s linear infinite;
207
+ }
208
+
209
+ /* src/ui/feedback/top-loading/style.scss */
210
+ .top_loading {
211
+ position: fixed;
212
+ top: 0;
213
+ left: 0;
214
+ right: 0;
215
+ z-index: 10001;
216
+ overflow: hidden;
217
+ background-color: transparent;
218
+ }
219
+ .top_loading_bar {
220
+ height: 100%;
221
+ background-color: #000000;
222
+ transition: width 0.2s ease-in-out;
223
+ }
224
+ .top_loading_indeterminate {
225
+ width: 30%;
226
+ animation: top_loading_indeterminate 1.5s ease-in-out infinite;
227
+ }
228
+ @keyframes top_loading_indeterminate {
229
+ 0% {
230
+ transform: translateX(-100%);
231
+ }
232
+ 100% {
233
+ transform: translateX(400%);
234
+ }
215
235
  }
216
236
 
217
237
  /* src/ui/general/button/style.scss */
@@ -392,6 +412,9 @@
392
412
  display: inline-flex;
393
413
  align-items: center;
394
414
  }
415
+ .file_input:hover .file_input_label {
416
+ border-color: rgba(0, 0, 0, 0.08);
417
+ }
395
418
  .file_input_control {
396
419
  position: absolute;
397
420
  inset: 0;
@@ -411,9 +434,6 @@
411
434
  border-color 0.2s ease-in-out,
412
435
  box-shadow 0.2s ease-in-out;
413
436
  }
414
- .file_input:hover .file_input_label {
415
- border-color: rgba(0, 0, 0, 0.08);
416
- }
417
437
  .file_input_control:focus-visible + .file_input_label {
418
438
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.08);
419
439
  border-color: #000000;
@@ -550,57 +570,56 @@
550
570
  background: #fafafa;
551
571
  color: #999999;
552
572
  }
553
- .select_control_variant_outline {
573
+ .select_variant_outline {
554
574
  border: 1px solid #e5e5e5;
555
575
  }
556
- .select_control_variant_outline:hover:not(.is_disabled) {
576
+ .select_variant_outline:hover:not(.is_disabled) {
557
577
  border-color: rgba(0, 0, 0, 0.08);
558
578
  }
559
- .select_control_variant_outline.is_open {
579
+ .select_variant_outline.is_open {
560
580
  border-color: #000000;
561
581
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.15);
562
582
  }
563
- .select_control_variant_filled {
583
+ .select_variant_filled {
564
584
  background: #fafafa;
565
585
  border: 1px solid transparent;
566
586
  }
567
- .select_control_variant_filled:hover:not(.is_disabled) {
587
+ .select_variant_filled:hover:not(.is_disabled) {
568
588
  background: rgb(253.5, 253.5, 253.5);
569
589
  }
570
- .select_control_variant_filled.is_open {
590
+ .select_variant_filled.is_open {
571
591
  background: #ffffff;
572
592
  border-color: #000000;
573
593
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.15);
574
594
  }
575
- .select_control_variant_ghost {
595
+ .select_variant_ghost {
576
596
  background: transparent;
577
597
  border: 1px solid transparent;
578
598
  }
579
- .select_control_variant_ghost:hover:not(.is_disabled) {
599
+ .select_variant_ghost:hover:not(.is_disabled) {
580
600
  background: rgba(0, 0, 0, 0.03);
581
601
  }
582
- .select_control_variant_ghost.is_open {
602
+ .select_variant_ghost.is_open {
583
603
  background: #ffffff;
584
604
  border-color: #000000;
585
605
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.15);
586
606
  }
587
- .select_control_size_sm {
607
+ .select_size_sm {
588
608
  padding: 0.5rem 1rem;
589
609
  font-size: 0.875rem;
590
610
  line-height: 1.5;
591
611
  }
592
- .select_control_size_md {
612
+ .select_size_md {
593
613
  padding: 0.75rem 1.25rem;
594
614
  font-size: 0.9375rem;
595
615
  line-height: 1.5;
596
616
  }
597
- .select_control_size_lg {
617
+ .select_size_lg {
598
618
  padding: 1rem 1.5rem;
599
619
  font-size: 1rem;
600
620
  line-height: 1.5;
601
621
  }
602
- .select_value,
603
- .select_placeholder {
622
+ .select_value {
604
623
  flex: 1 1 auto;
605
624
  min-width: 0;
606
625
  overflow: hidden;
@@ -612,6 +631,15 @@
612
631
  line-height: 1.5;
613
632
  }
614
633
  .select_placeholder {
634
+ flex: 1 1 auto;
635
+ min-width: 0;
636
+ overflow: hidden;
637
+ text-overflow: ellipsis;
638
+ white-space: nowrap;
639
+ text-align: start;
640
+ font-size: 0.9375rem;
641
+ font-weight: 400;
642
+ line-height: 1.5;
615
643
  color: #999999;
616
644
  }
617
645
  .select_icon {
@@ -870,23 +898,9 @@
870
898
  /* src/ui/form/date-picker/style.scss */
871
899
  .date_picker {
872
900
  display: flex;
901
+ flex-direction: column;
873
902
  gap: 0.25rem;
874
903
  }
875
- .date_picker_label {
876
- color: #1a1a1a;
877
- margin-bottom: 0.25rem;
878
- font-weight: 500;
879
- font-size: 0.875rem;
880
- line-height: 1.5;
881
- }
882
- .date_picker_required {
883
- margin-left: 0.25rem;
884
- color: #ef4444;
885
- }
886
- .date_picker_fields {
887
- display: flex;
888
- gap: 0.5rem;
889
- }
890
904
  .date_picker select {
891
905
  min-width: 88px;
892
906
  height: 44px;
@@ -936,6 +950,32 @@
936
950
  .date_picker select option {
937
951
  color: #1a1a1a;
938
952
  }
953
+ @media (max-width: 480px) {
954
+ .date_picker select {
955
+ flex: 1;
956
+ min-width: 0;
957
+ }
958
+ }
959
+ .date_picker_label {
960
+ color: #1a1a1a;
961
+ margin-bottom: 0.25rem;
962
+ font-weight: 500;
963
+ font-size: 0.875rem;
964
+ line-height: 1.5;
965
+ }
966
+ .date_picker_required {
967
+ margin-left: 0.25rem;
968
+ color: #ef4444;
969
+ }
970
+ .date_picker_fields {
971
+ display: flex;
972
+ gap: 0.5rem;
973
+ }
974
+ @media (max-width: 480px) {
975
+ .date_picker_fields {
976
+ gap: 0.25rem;
977
+ }
978
+ }
939
979
  .date_picker_full {
940
980
  width: 100%;
941
981
  }
@@ -949,15 +989,6 @@
949
989
  .date_picker_disabled .date_picker_label {
950
990
  color: #9ca3af;
951
991
  }
952
- @media (max-width: 480px) {
953
- .date_picker_fields {
954
- gap: 0.25rem;
955
- }
956
- .date_picker select {
957
- flex: 1;
958
- min-width: 0;
959
- }
960
- }
961
992
 
962
993
  /* src/ui/navigation/pagination/style.scss */
963
994
  .pagination {
@@ -994,7 +1025,7 @@
994
1025
  align-items: center;
995
1026
  gap: 6px;
996
1027
  }
997
- .pagination_pageButton {
1028
+ .pagination_page_button {
998
1029
  border: 0;
999
1030
  background: transparent;
1000
1031
  min-width: 36px;
@@ -1005,14 +1036,14 @@
1005
1036
  color: #666666;
1006
1037
  transition: background 0.2s ease-in-out, color 0.2s ease-in-out;
1007
1038
  }
1008
- .pagination_pageButton:hover {
1039
+ .pagination_page_button:hover {
1009
1040
  background: #fafafa;
1010
1041
  color: #1a1a1a;
1011
1042
  }
1012
- .pagination_pageButton:focus-visible {
1043
+ .pagination_page_button:focus-visible {
1013
1044
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.08);
1014
1045
  }
1015
- .pagination_pageButton.is-active {
1046
+ .pagination_active {
1016
1047
  color: #1a1a1a;
1017
1048
  font-weight: 600;
1018
1049
  }
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import * as react_toastify from 'react-toastify';
4
4
 
5
- /** Card UI */
6
5
  interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
7
6
  heading?: React.ReactNode;
8
7
  shadow?: "none" | "sm" | "md" | "lg";
@@ -32,10 +31,22 @@ declare const AlertProvider: React.FC<{
32
31
  children: React.ReactNode;
33
32
  }>;
34
33
 
35
- interface LoadingProps {
34
+ interface SpinnerProps {
36
35
  size?: number;
37
36
  }
38
- declare const Loading: ({ size }: LoadingProps) => react_jsx_runtime.JSX.Element;
37
+ declare const Spinner: ({ size }: SpinnerProps) => react_jsx_runtime.JSX.Element;
38
+
39
+ interface TopLoadingProps {
40
+ /** 진행률 (0-100). undefined면 indeterminate 모드 */
41
+ progress?: number;
42
+ /** 로딩바 색상 (기본: primary) */
43
+ color?: string;
44
+ /** 로딩바 높이 (기본: 3px) */
45
+ height?: number;
46
+ /** 표시 여부 */
47
+ isLoading?: boolean;
48
+ }
49
+ declare const TopLoading: ({ progress, color, height, isLoading, }: TopLoadingProps) => react_jsx_runtime.JSX.Element | null;
39
50
 
40
51
  interface ToastProviderProps {
41
52
  containerId?: string;
@@ -165,4 +176,4 @@ interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">
165
176
  }
166
177
  declare const Modal: ({ open, onClose, closeOnOverlay, width, title, children, className, ...props }: ModalProps) => react_jsx_runtime.JSX.Element | null;
167
178
 
168
- export { AlertProvider, Button, Card, Checkbox, DatePicker, FileInput, Loading, Modal, Pagination, Radio, Select, type SelectOption, Switch, TextField, ToastProvider, useAlert, useToast };
179
+ export { AlertProvider, Button, Card, Checkbox, DatePicker, FileInput, Modal, Pagination, Radio, Select, type SelectOption, Spinner, Switch, TextField, ToastProvider, TopLoading, useAlert, useToast };
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ var Card = ({
22
22
  "card",
23
23
  `card_shadow_${shadow}`,
24
24
  `card_p_${padding}`,
25
- bordered ? "card_bordered" : "",
25
+ bordered && "card_bordered",
26
26
  className ?? ""
27
27
  ].filter(Boolean).join(" ");
28
28
  return /* @__PURE__ */ jsxs("div", { className: cls, ...props, children: [
@@ -89,24 +89,32 @@ var AlertModal = ({
89
89
  onCancel,
90
90
  onClose
91
91
  }) => {
92
+ const modalClassName = [
93
+ "alert_modal",
94
+ `alert_variant_${variant}`
95
+ ].filter(Boolean).join(" ");
96
+ const actionsClassName = [
97
+ "alert_actions",
98
+ `alert_actions_${actionsAlign}`
99
+ ].filter(Boolean).join(" ");
92
100
  return /* @__PURE__ */ jsx("div", { className: "alert_overlay", onClick: onClose, children: /* @__PURE__ */ jsxs(
93
101
  "div",
94
102
  {
95
- className: `alert_modal alert_modal_${variant}`,
103
+ className: modalClassName,
96
104
  onClick: (e) => e.stopPropagation(),
97
105
  role: "alertdialog",
98
106
  "aria-modal": "true",
99
107
  "aria-labelledby": "alert_title",
100
108
  "aria-describedby": "alert_message",
101
109
  children: [
102
- title && /* @__PURE__ */ jsx("div", { className: "alert_modal_title", id: "alert_title", children: title }),
103
- message && /* @__PURE__ */ jsx("div", { className: "alert_modal_message", id: "alert_message", children: message }),
104
- /* @__PURE__ */ jsxs("div", { className: `alert_modal_actions alert_modal_actions_${actionsAlign}`, children: [
110
+ title && /* @__PURE__ */ jsx("div", { className: "alert_title", id: "alert_title", children: title }),
111
+ message && /* @__PURE__ */ jsx("div", { className: "alert_message", id: "alert_message", children: message }),
112
+ /* @__PURE__ */ jsxs("div", { className: actionsClassName, children: [
105
113
  showCancel && /* @__PURE__ */ jsx(
106
114
  "button",
107
115
  {
108
116
  type: "button",
109
- className: "alert_modal_button alert_modal_button_cancel",
117
+ className: "alert_button alert_button_cancel",
110
118
  onClick: onCancel,
111
119
  children: cancelText
112
120
  }
@@ -115,7 +123,7 @@ var AlertModal = ({
115
123
  "button",
116
124
  {
117
125
  type: "button",
118
- className: "alert_modal_button alert_modal_button_confirm",
126
+ className: "alert_button alert_button_confirm",
119
127
  onClick: onConfirm,
120
128
  children: confirmText
121
129
  }
@@ -125,17 +133,51 @@ var AlertModal = ({
125
133
  }
126
134
  ) });
127
135
  };
128
- var Loading = ({ size = 24 }) => {
136
+ var Spinner = ({ size = 24 }) => {
129
137
  return /* @__PURE__ */ jsx(
130
138
  "span",
131
139
  {
132
- className: "loading",
140
+ className: "spinner",
133
141
  style: { width: size, height: size },
134
142
  role: "status",
135
143
  "aria-label": "\uB85C\uB529 \uC911"
136
144
  }
137
145
  );
138
146
  };
147
+ var TopLoading = ({
148
+ progress,
149
+ color,
150
+ height = 3,
151
+ isLoading = true
152
+ }) => {
153
+ if (!isLoading) return null;
154
+ const isIndeterminate = progress === void 0;
155
+ return /* @__PURE__ */ jsx(
156
+ "div",
157
+ {
158
+ className: "top_loading",
159
+ style: { height },
160
+ role: "progressbar",
161
+ "aria-valuemin": 0,
162
+ "aria-valuemax": 100,
163
+ "aria-valuenow": isIndeterminate ? void 0 : progress,
164
+ "aria-label": "\uD398\uC774\uC9C0 \uB85C\uB529 \uC911",
165
+ children: /* @__PURE__ */ jsx(
166
+ "div",
167
+ {
168
+ className: [
169
+ "top_loading_bar",
170
+ isIndeterminate && "top_loading_indeterminate"
171
+ ].filter(Boolean).join(" "),
172
+ style: {
173
+ width: isIndeterminate ? void 0 : `${progress}%`,
174
+ backgroundColor: color
175
+ }
176
+ }
177
+ )
178
+ }
179
+ );
180
+ };
139
181
  var ToastProvider = ({ containerId = "default" }) => {
140
182
  return /* @__PURE__ */ jsx(
141
183
  ToastContainer,
@@ -219,7 +261,11 @@ var FileInput = ({
219
261
  ...props
220
262
  }) => {
221
263
  const inputId = React3.useId();
222
- const rootClassName = ["file_input", disabled ? "file_input_disabled" : "", className ?? ""].filter(Boolean).join(" ");
264
+ const rootClassName = [
265
+ "file_input",
266
+ disabled && "file_input_disabled",
267
+ className ?? ""
268
+ ].filter(Boolean).join(" ");
223
269
  return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
224
270
  /* @__PURE__ */ jsx(
225
271
  "input",
@@ -236,7 +282,11 @@ var FileInput = ({
236
282
  ] });
237
283
  };
238
284
  var Radio = ({ label, size = "md", className, ...props }) => {
239
- const rootClassName = ["radio", `radio_size_${size}`, className ?? ""].filter(Boolean).join(" ");
285
+ const rootClassName = [
286
+ "radio",
287
+ `radio_size_${size}`,
288
+ className ?? ""
289
+ ].filter(Boolean).join(" ");
240
290
  return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
241
291
  /* @__PURE__ */ jsx("input", { type: "radio", className: "radio_input", ...props }),
242
292
  /* @__PURE__ */ jsx("span", { className: "radio_dot", "aria-hidden": "true" }),
@@ -366,8 +416,8 @@ var Select = ({
366
416
  const rootClassName = ["select", className ?? ""].filter(Boolean).join(" ");
367
417
  const controlClassName = [
368
418
  "select_control",
369
- `select_control_variant_${variant}`,
370
- `select_control_size_${size}`,
419
+ `select_variant_${variant}`,
420
+ `select_size_${size}`,
371
421
  isOpen && "is_open",
372
422
  disabled && "is_disabled"
373
423
  ].filter(Boolean).join(" ");
@@ -631,53 +681,55 @@ var DatePicker = ({
631
681
  };
632
682
  return /* @__PURE__ */ jsxs("div", { className: "date_picker", style: { width: normalizeWidth(width?.container) }, children: [
633
683
  label && /* @__PURE__ */ jsx("label", { className: "date_picker_label", children: label }),
634
- /* @__PURE__ */ jsxs(
635
- "select",
636
- {
637
- style: { width: normalizeWidth(width?.year) },
638
- value: year,
639
- disabled,
640
- onChange: (e) => emit(Number(e.target.value), month || minMonth, day || minDay),
641
- children: [
642
- /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
643
- Array.from(
644
- { length: maxYear - startYear + 1 },
645
- (_, i) => startYear + i
646
- ).map((y2) => /* @__PURE__ */ jsx("option", { value: y2, children: y2 }, y2))
647
- ]
648
- }
649
- ),
650
- /* @__PURE__ */ jsxs(
651
- "select",
652
- {
653
- style: { width: normalizeWidth(width?.month) },
654
- value: month,
655
- disabled: disabled || !year,
656
- onChange: (e) => emit(year, Number(e.target.value), day || minDay),
657
- children: [
658
- /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
659
- Array.from({ length: maxMonth - minMonth + 1 }, (_, i) => minMonth + i).map(
660
- (m2) => /* @__PURE__ */ jsx("option", { value: m2, children: pad(m2) }, m2)
661
- )
662
- ]
663
- }
664
- ),
665
- mode === "year-month-day" && /* @__PURE__ */ jsxs(
666
- "select",
667
- {
668
- style: { width: normalizeWidth(width?.day) },
669
- value: day,
670
- disabled: disabled || !month,
671
- onChange: (e) => emit(year, month, Number(e.target.value)),
672
- children: [
673
- /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
674
- Array.from(
675
- { length: days - minDay + 1 },
676
- (_, i) => minDay + i
677
- ).map((d2) => /* @__PURE__ */ jsx("option", { value: d2, children: pad(d2) }, d2))
678
- ]
679
- }
680
- )
684
+ /* @__PURE__ */ jsxs("div", { className: "date_picker_fields", children: [
685
+ /* @__PURE__ */ jsxs(
686
+ "select",
687
+ {
688
+ style: { width: normalizeWidth(width?.year) },
689
+ value: year,
690
+ disabled,
691
+ onChange: (e) => emit(Number(e.target.value), month || minMonth, day || minDay),
692
+ children: [
693
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
694
+ Array.from(
695
+ { length: maxYear - startYear + 1 },
696
+ (_, i) => startYear + i
697
+ ).map((y2) => /* @__PURE__ */ jsx("option", { value: y2, children: y2 }, y2))
698
+ ]
699
+ }
700
+ ),
701
+ /* @__PURE__ */ jsxs(
702
+ "select",
703
+ {
704
+ style: { width: normalizeWidth(width?.month) },
705
+ value: month,
706
+ disabled: disabled || !year,
707
+ onChange: (e) => emit(year, Number(e.target.value), day || minDay),
708
+ children: [
709
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
710
+ Array.from({ length: maxMonth - minMonth + 1 }, (_, i) => minMonth + i).map(
711
+ (m2) => /* @__PURE__ */ jsx("option", { value: m2, children: pad(m2) }, m2)
712
+ )
713
+ ]
714
+ }
715
+ ),
716
+ mode === "year-month-day" && /* @__PURE__ */ jsxs(
717
+ "select",
718
+ {
719
+ style: { width: normalizeWidth(width?.day) },
720
+ value: day,
721
+ disabled: disabled || !month,
722
+ onChange: (e) => emit(year, month, Number(e.target.value)),
723
+ children: [
724
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
725
+ Array.from(
726
+ { length: days - minDay + 1 },
727
+ (_, i) => minDay + i
728
+ ).map((d2) => /* @__PURE__ */ jsx("option", { value: d2, children: pad(d2) }, d2))
729
+ ]
730
+ }
731
+ )
732
+ ] })
681
733
  ] });
682
734
  };
683
735
  var range = (start, end) => {
@@ -721,11 +773,15 @@ var Pagination = ({ page, totalPages, onChange }) => {
721
773
  return /* @__PURE__ */ jsx("span", { className: "pagination_ellipsis", "aria-hidden": "true", children: "\u2026" }, `e-${idx}`);
722
774
  }
723
775
  const isActive = it === page;
776
+ const buttonClassName = [
777
+ "pagination_page_button",
778
+ isActive && "pagination_active"
779
+ ].filter(Boolean).join(" ");
724
780
  return /* @__PURE__ */ jsx(
725
781
  "button",
726
782
  {
727
783
  type: "button",
728
- className: `pagination_pageButton ${isActive ? "is-active" : ""}`,
784
+ className: buttonClassName,
729
785
  onClick: () => onChange(it),
730
786
  "aria-current": isActive ? "page" : void 0,
731
787
  children: it
@@ -764,6 +820,7 @@ var Modal = ({
764
820
  return () => document.removeEventListener("keydown", onKeyDown);
765
821
  }, [open, onClose]);
766
822
  if (!open) return null;
823
+ const panelClassName = ["modal_panel", className].filter(Boolean).join(" ");
767
824
  return /* @__PURE__ */ jsx(
768
825
  "div",
769
826
  {
@@ -774,7 +831,7 @@ var Modal = ({
774
831
  children: /* @__PURE__ */ jsxs(
775
832
  "div",
776
833
  {
777
- className: ["modal_panel", className].filter(Boolean).join(" "),
834
+ className: panelClassName,
778
835
  style: { width },
779
836
  onClick: (e) => e.stopPropagation(),
780
837
  ...props,
@@ -788,4 +845,4 @@ var Modal = ({
788
845
  );
789
846
  };
790
847
 
791
- export { AlertProvider, Button, Card, Checkbox, DatePicker, FileInput, Loading, Modal, Pagination, Radio, Select, Switch, TextField, ToastProvider, useAlert, useToast };
848
+ export { AlertProvider, Button, Card, Checkbox, DatePicker, FileInput, Modal, Pagination, Radio, Select, Spinner, Switch, TextField, ToastProvider, TopLoading, useAlert, useToast };
package/dist/next.css CHANGED
@@ -11,7 +11,7 @@
11
11
  overflow: hidden;
12
12
  transition: width 0.3s ease-in-out;
13
13
  }
14
- .sidebar.is_closed {
14
+ .sidebar_is_closed {
15
15
  width: 56px;
16
16
  }
17
17
  .sidebar_brand {
@@ -49,7 +49,7 @@
49
49
  background: #fafafa;
50
50
  color: #1f2937;
51
51
  }
52
- .sidebar_item.is_active {
52
+ .sidebar_item_active {
53
53
  background: #ffffff;
54
54
  color: #1f2937;
55
55
  box-shadow: inset 0 0 0 1px #e5e5e5;
@@ -70,7 +70,7 @@
70
70
  .sidebar_chevron {
71
71
  transition: transform 0.2s ease-in-out;
72
72
  }
73
- .sidebar_chevron.is_open {
73
+ .sidebar_chevron_open {
74
74
  transform: rotate(180deg);
75
75
  }
76
76
  .sidebar_label {
@@ -90,7 +90,7 @@
90
90
  opacity 0.2s ease-in-out,
91
91
  transform 0.2s ease-in-out;
92
92
  }
93
- .sidebar_sub.is_open {
93
+ .sidebar_sub_open {
94
94
  max-height: 500px;
95
95
  opacity: 1;
96
96
  transform: translateY(0);
@@ -110,7 +110,7 @@
110
110
  background: #fafafa;
111
111
  color: #1f2937;
112
112
  }
113
- .sidebar_sub_item.is_active {
113
+ .sidebar_sub_item_active {
114
114
  color: #000000;
115
115
  font-weight: 500;
116
116
  }
package/dist/next.js CHANGED
@@ -40,14 +40,15 @@ var Sidebar = ({
40
40
  (prev) => prev.includes(id) ? prev.filter((v) => v !== id) : [...prev, id]
41
41
  );
42
42
  };
43
+ const sidebarClassName = [
44
+ "sidebar",
45
+ isOpen ? "sidebar_is_open" : "sidebar_is_closed",
46
+ className ?? ""
47
+ ].filter(Boolean).join(" ");
43
48
  return /* @__PURE__ */ jsx(
44
49
  "aside",
45
50
  {
46
- className: [
47
- "sidebar",
48
- isOpen ? "is_open" : "is_closed",
49
- className ?? ""
50
- ].filter(Boolean).join(" "),
51
+ className: sidebarClassName,
51
52
  style,
52
53
  children: isOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
53
54
  /* @__PURE__ */ jsx("div", { className: "sidebar_brand", children: /* @__PURE__ */ jsxs(Link, { href: brandHref, className: "sidebar_brand_link", children: [
@@ -76,6 +77,14 @@ var Sidebar = ({
76
77
  /* @__PURE__ */ jsx("nav", { className: "sidebar_nav", children: items.map((item) => {
77
78
  if (item.type === "group") {
78
79
  const open = openGroups.includes(item.id);
80
+ const subClassName = [
81
+ "sidebar_sub",
82
+ open && "sidebar_sub_open"
83
+ ].filter(Boolean).join(" ");
84
+ const chevronClassName = [
85
+ "sidebar_chevron",
86
+ open && "sidebar_chevron_open"
87
+ ].filter(Boolean).join(" ");
79
88
  return /* @__PURE__ */ jsxs("div", { className: "sidebar_group", children: [
80
89
  /* @__PURE__ */ jsxs(
81
90
  "button",
@@ -92,63 +101,53 @@ var Sidebar = ({
92
101
  ChevronDown,
93
102
  {
94
103
  size: 16,
95
- className: [
96
- "sidebar_chevron",
97
- open && "is_open"
98
- ].filter(Boolean).join(" ")
104
+ className: chevronClassName
99
105
  }
100
106
  ) })
101
107
  ]
102
108
  }
103
109
  ),
104
- /* @__PURE__ */ jsx(
105
- "div",
106
- {
107
- className: [
108
- "sidebar_sub",
109
- open && "is_open"
110
- ].filter(Boolean).join(" "),
111
- children: item.children.map((child) => {
112
- const active2 = isActive(
113
- child.href
114
- );
115
- return /* @__PURE__ */ jsxs(
116
- Link,
117
- {
118
- href: child.href,
119
- className: [
120
- "sidebar_sub_item",
121
- active2 && "is_active"
122
- ].filter(Boolean).join(" "),
123
- onClick: () => onItemSelect?.(
124
- child.href
125
- ),
126
- children: [
127
- /* @__PURE__ */ jsx("span", { className: "sidebar_sub_icon", children: /* @__PURE__ */ jsx(
128
- CornerDownRight,
129
- {
130
- size: 14
131
- }
132
- ) }),
133
- /* @__PURE__ */ jsx("span", { className: "sidebar_sub_label", children: child.label })
134
- ]
135
- },
110
+ /* @__PURE__ */ jsx("div", { className: subClassName, children: item.children.map((child) => {
111
+ const active2 = isActive(
112
+ child.href
113
+ );
114
+ const subItemClassName = [
115
+ "sidebar_sub_item",
116
+ active2 && "sidebar_sub_item_active"
117
+ ].filter(Boolean).join(" ");
118
+ return /* @__PURE__ */ jsxs(
119
+ Link,
120
+ {
121
+ href: child.href,
122
+ className: subItemClassName,
123
+ onClick: () => onItemSelect?.(
136
124
  child.href
137
- );
138
- })
139
- }
140
- )
125
+ ),
126
+ children: [
127
+ /* @__PURE__ */ jsx("span", { className: "sidebar_sub_icon", children: /* @__PURE__ */ jsx(
128
+ CornerDownRight,
129
+ {
130
+ size: 14
131
+ }
132
+ ) }),
133
+ /* @__PURE__ */ jsx("span", { className: "sidebar_sub_label", children: child.label })
134
+ ]
135
+ },
136
+ child.href
137
+ );
138
+ }) })
141
139
  ] }, item.id);
142
140
  }
143
141
  const active = isActive(item.href);
142
+ const itemClassName = [
143
+ "sidebar_item",
144
+ active && "sidebar_item_active"
145
+ ].filter(Boolean).join(" ");
144
146
  return /* @__PURE__ */ jsx(
145
147
  Link,
146
148
  {
147
149
  href: item.href,
148
- className: [
149
- "sidebar_item",
150
- active && "is_active"
151
- ].filter(Boolean).join(" "),
150
+ className: itemClassName,
152
151
  onClick: () => onItemSelect?.(item.href),
153
152
  children: /* @__PURE__ */ jsxs("div", { className: "sidebar_item_left", children: [
154
153
  item.icon && /* @__PURE__ */ jsx("span", { className: "sidebar_icon", children: /* @__PURE__ */ jsx(item.icon, { size: 16 }) }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigtablet/design-system",
3
- "version": "1.13.0",
3
+ "version": "1.14.1",
4
4
  "description": "Bigtablet Design System UI Components",
5
5
  "type": "module",
6
6
  "types": "dist/index.d.ts",
@@ -66,25 +66,31 @@
66
66
  "@semantic-release/git": "^10.0.1",
67
67
  "@semantic-release/github": "^12.0.1",
68
68
  "@semantic-release/npm": "^13.1.1",
69
- "@storybook/react": "10.1.10",
70
- "@storybook/react-vite": "10.1.10",
69
+ "@storybook/addon-docs": "^10.1.11",
70
+ "@storybook/addon-vitest": "10.1.11",
71
+ "@storybook/react": "10.1.11",
72
+ "@storybook/react-vite": "10.1.11",
71
73
  "@types/node": "^24",
72
74
  "@types/react": "^19",
73
75
  "@types/react-dom": "^19",
76
+ "@vitest/browser-playwright": "^4.0.17",
77
+ "@vitest/coverage-v8": "^4.0.17",
74
78
  "chromatic": "^13.3.3",
75
79
  "conventional-changelog-conventionalcommits": "^9.1.0",
76
80
  "esbuild-sass-plugin": "^3",
77
81
  "lucide-react": "^0.552.0",
78
82
  "next": "16.0.10",
83
+ "playwright": "^1.57.0",
79
84
  "react": "19.2.0",
80
85
  "react-dom": "19.2.0",
81
86
  "react-toastify": "^11.0.5",
82
87
  "sass-embedded": "^1.93.3",
83
88
  "semantic-release": "^25.0.1",
84
- "storybook": "10.1.10",
89
+ "storybook": "10.1.11",
85
90
  "tsup": "^8.5.0",
86
91
  "typescript": "^5",
87
- "vite": "^5"
92
+ "vite": "^5",
93
+ "vitest": "^4.0.17"
88
94
  },
89
95
  "publishConfig": {
90
96
  "access": "public",