@uniai-fe/uds-primitives 0.2.2 → 0.2.3

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 (61) hide show
  1. package/README.md +1 -1
  2. package/dist/styles.css +299 -81
  3. package/package.json +16 -9
  4. package/src/components/{input/img/calendar → calendar/img}/calendar.svg +5 -0
  5. package/src/components/calendar/index.tsx +5 -3
  6. package/src/components/calendar/markup/Core.tsx +67 -0
  7. package/src/components/calendar/markup/Icon.tsx +20 -0
  8. package/src/components/calendar/markup/Root.tsx +126 -0
  9. package/src/components/calendar/markup/index.tsx +24 -2
  10. package/src/components/calendar/markup/layout/Body.tsx +12 -0
  11. package/src/components/calendar/markup/layout/Container.tsx +43 -0
  12. package/src/components/calendar/markup/layout/Footer.tsx +12 -0
  13. package/src/components/calendar/markup/layout/Header.tsx +12 -0
  14. package/src/components/calendar/styles/index.scss +2 -0
  15. package/src/components/calendar/styles/layout.scss +21 -0
  16. package/src/components/calendar/styles/mantine-calendar.scss +240 -0
  17. package/src/components/calendar/types/calendar.ts +208 -0
  18. package/src/components/calendar/types/index.ts +1 -4
  19. package/src/components/calendar/utils/index.ts +1 -4
  20. package/src/components/calendar/utils/value-mapper.ts +24 -0
  21. package/src/components/input/index.scss +1 -1
  22. package/src/components/input/markup/date/Template.tsx +181 -0
  23. package/src/components/input/markup/date/Trigger.tsx +79 -0
  24. package/src/components/input/markup/date/button/ApplyButton.tsx +38 -0
  25. package/src/components/input/markup/date/button/ClearButton.tsx +36 -0
  26. package/src/components/input/markup/date/button/TodayButton.tsx +36 -0
  27. package/src/components/input/markup/date/footer/Container.tsx +24 -0
  28. package/src/components/input/markup/date/footer/Template.tsx +36 -0
  29. package/src/components/input/markup/date/footer/UtilContainer.tsx +23 -0
  30. package/src/components/input/markup/date/footer/index.ts +3 -0
  31. package/src/components/input/markup/date/index.tsx +27 -0
  32. package/src/components/input/markup/index.tsx +2 -4
  33. package/src/components/input/styles/date.scss +45 -0
  34. package/src/components/input/types/date.ts +366 -0
  35. package/src/components/input/types/index.ts +1 -1
  36. package/src/components/input/utils/address.ts +2 -2
  37. package/src/components/input/utils/date.ts +61 -0
  38. package/src/components/input/utils/index.tsx +1 -0
  39. package/src/components/pop-over/index.scss +1 -0
  40. package/src/components/pop-over/index.tsx +4 -0
  41. package/src/components/pop-over/markup/Content.tsx +77 -0
  42. package/src/components/pop-over/markup/Root.tsx +28 -0
  43. package/src/components/pop-over/markup/Trigger.tsx +26 -0
  44. package/src/components/pop-over/markup/index.tsx +17 -0
  45. package/src/components/pop-over/styles/base.scss +5 -0
  46. package/src/components/pop-over/styles/content.scss +24 -0
  47. package/src/components/pop-over/styles/index.scss +2 -0
  48. package/src/components/pop-over/types/index.ts +1 -0
  49. package/src/components/pop-over/types/pop-over.ts +86 -0
  50. package/src/index.scss +1 -0
  51. package/src/index.tsx +3 -1
  52. package/src/init/mantine.css +5 -0
  53. package/src/init/mantine.ts +2 -0
  54. package/src/components/input/markup/calendar/Base.tsx +0 -329
  55. package/src/components/input/markup/calendar/index.tsx +0 -8
  56. package/src/components/input/styles/calendar.scss +0 -110
  57. package/src/components/input/types/calendar.ts +0 -208
  58. /package/src/components/{input/img/calendar → calendar/img}/chevron-down.svg +0 -0
  59. /package/src/components/{input/img/calendar → calendar/img}/chevron-left.svg +0 -0
  60. /package/src/components/{input/img/calendar → calendar/img}/chevron-right.svg +0 -0
  61. /package/src/components/{input/img/calendar → calendar/img}/chevron-up.svg +0 -0
package/README.md CHANGED
@@ -140,7 +140,7 @@ import "@uniai-fe/uds-primitives/css";
140
140
 
141
141
  ThemeProvider는 CSS를 import하지 않으므로 foundation/primitives styles를 앱 루트에서 1회만 로드하면 중복 없이 토큰 매핑이 적용된다. Provider 자체는 foundation 패키지(`@uniai-fe/uds-foundation/provider`)에서만 export된다(one-source 규칙).
142
142
 
143
- > modules 레포 내부(Storybook 등)에서는 개발 편의를 위해 `@uniai-fe/uds-primitives/src/index.scss`를 직접 import하지만, 외부 서비스/패키지는 `@uniai-fe/uds-primitives/css` 엔트리만 사용한다.
143
+ > modules 레포 내부(Storybook 등)에서는 개발 편의를 위해 `@uniai-fe/uds-primitives/styles` 엔트리를 import하지만, 외부 서비스/패키지는 `@uniai-fe/uds-primitives/css` 엔트리만 사용한다.
144
144
 
145
145
  ### 토큰 스코프 & ThemeProvider
146
146
 
package/dist/styles.css CHANGED
@@ -1011,6 +1011,260 @@
1011
1011
  border-radius: var(--button-round-radius-large, 30px);
1012
1012
  }
1013
1013
 
1014
+ .calendar-root {
1015
+ width: fit-content;
1016
+ max-width: 100%;
1017
+ }
1018
+
1019
+ .calendar-trigger {
1020
+ width: 100%;
1021
+ }
1022
+
1023
+ .calendar-container {
1024
+ display: grid;
1025
+ gap: var(--spacing-gap-3);
1026
+ width: fit-content;
1027
+ max-width: 100%;
1028
+ }
1029
+
1030
+ .calendar-body,
1031
+ .calendar-grid {
1032
+ width: fit-content;
1033
+ max-width: 100%;
1034
+ }
1035
+
1036
+ .calendar-root,
1037
+ .calendar-grid {
1038
+ --calendar-width: 375px;
1039
+ --calendar-inline-padding: var(--spacing-padding-6);
1040
+ --calendar-body-width: calc(
1041
+ var(--calendar-width) - (var(--calendar-inline-padding) * 2)
1042
+ );
1043
+ }
1044
+
1045
+ .calendar-root {
1046
+ padding: var(--spacing-padding-10) var(--spacing-padding-6) var(--spacing-padding-6);
1047
+ display: grid;
1048
+ gap: var(--spacing-gap-3);
1049
+ width: var(--calendar-width);
1050
+ min-width: var(--calendar-width);
1051
+ max-width: min(100vw - var(--spacing-padding-5) * 2, 420px);
1052
+ box-sizing: border-box;
1053
+ z-index: 30;
1054
+ }
1055
+
1056
+ .calendar-header {
1057
+ margin-bottom: var(--spacing-gap-2);
1058
+ }
1059
+
1060
+ .calendar-body {
1061
+ display: grid;
1062
+ gap: var(--spacing-gap-5);
1063
+ }
1064
+
1065
+ .calendar-grid {
1066
+ width: var(--calendar-body-width);
1067
+ }
1068
+
1069
+ .calendar-grid table {
1070
+ width: auto;
1071
+ }
1072
+
1073
+ .calendar-month-level {
1074
+ width: 100%;
1075
+ }
1076
+
1077
+ .calendar-month-level > [data-month-level=true],
1078
+ .calendar-month-level > [data-year-level=true],
1079
+ .calendar-month-level > [data-decade-level=true] {
1080
+ width: 100%;
1081
+ }
1082
+
1083
+ .calendar-header-row {
1084
+ display: grid;
1085
+ grid-template-columns: 44px 1fr 44px;
1086
+ align-items: center;
1087
+ width: 100%;
1088
+ max-width: none;
1089
+ column-gap: var(--spacing-gap-5);
1090
+ padding: 0 var(--spacing-padding-9);
1091
+ margin-bottom: var(--spacing-gap-5);
1092
+ --dch-fz: var(--font-heading-small-size) !important;
1093
+ }
1094
+
1095
+ .calendar-header-control {
1096
+ width: 44px;
1097
+ height: 44px;
1098
+ border-radius: 999px;
1099
+ display: inline-flex;
1100
+ align-items: center;
1101
+ justify-content: center;
1102
+ color: var(--color-label-alternative);
1103
+ transition: background-color 0.2s ease, color 0.2s ease;
1104
+ }
1105
+
1106
+ .calendar-header-control[data-direction=previous] {
1107
+ justify-self: start;
1108
+ }
1109
+
1110
+ .calendar-header-control[data-direction=next] {
1111
+ justify-self: end;
1112
+ }
1113
+
1114
+ .calendar-header-level {
1115
+ justify-self: center;
1116
+ font-size: var(--font-heading-small-size);
1117
+ font-weight: var(--font-heading-small-weight);
1118
+ text-align: center;
1119
+ white-space: nowrap;
1120
+ writing-mode: horizontal-tb;
1121
+ letter-spacing: 0.2px;
1122
+ /* Month/Year 헤더 텍스트는 디자인 기준에 맞춰 strong 컬러를 사용한다. */
1123
+ color: var(--color-label-strong);
1124
+ }
1125
+
1126
+ .calendar-header-control:where(:not([data-disabled=true])):hover {
1127
+ background-color: var(--color-tertiary-default);
1128
+ color: var(--color-label-standard);
1129
+ }
1130
+
1131
+ .calendar-month-table {
1132
+ width: 100%;
1133
+ max-width: 100%;
1134
+ margin: 0 auto;
1135
+ table-layout: fixed;
1136
+ border-collapse: collapse;
1137
+ border-spacing: 0;
1138
+ }
1139
+
1140
+ .calendar-month-cell {
1141
+ width: 46px;
1142
+ padding: 1px;
1143
+ }
1144
+
1145
+ .calendar-months-list {
1146
+ width: 100%;
1147
+ max-width: 100%;
1148
+ margin: 0 auto;
1149
+ table-layout: fixed;
1150
+ border-collapse: separate;
1151
+ border-spacing: var(--spacing-gap-3);
1152
+ }
1153
+
1154
+ .calendar-months-list-cell {
1155
+ padding: 0;
1156
+ }
1157
+
1158
+ .calendar-months-list-control {
1159
+ width: 100%;
1160
+ min-width: 0;
1161
+ height: 44px;
1162
+ padding: 0 var(--spacing-padding-2);
1163
+ border: none;
1164
+ border-radius: var(--theme-radius-medium-3);
1165
+ font-size: var(--font-body-medium-size);
1166
+ font-weight: var(--font-body-medium-weight);
1167
+ line-height: 1.5;
1168
+ color: var(--color-label-standard);
1169
+ text-transform: none;
1170
+ }
1171
+
1172
+ .calendar-months-list-control[data-selected=true] {
1173
+ background-color: var(--color-primary-default);
1174
+ color: var(--color-common-100);
1175
+ }
1176
+
1177
+ .calendar-months-list-control:where(:not([data-disabled=true], [data-selected=true])):hover {
1178
+ background-color: var(--color-secondary-default);
1179
+ }
1180
+
1181
+ .calendar-years-list {
1182
+ width: 100%;
1183
+ max-width: 100%;
1184
+ margin: 0 auto;
1185
+ table-layout: fixed;
1186
+ border-collapse: separate;
1187
+ border-spacing: var(--spacing-gap-3);
1188
+ }
1189
+
1190
+ .calendar-years-list-cell {
1191
+ padding: 0;
1192
+ }
1193
+
1194
+ .calendar-years-list-control {
1195
+ width: 100%;
1196
+ min-width: 0;
1197
+ height: 44px;
1198
+ padding: 0 var(--spacing-padding-2);
1199
+ border: none;
1200
+ border-radius: var(--theme-radius-medium-3);
1201
+ font-size: var(--font-body-medium-size);
1202
+ font-weight: var(--font-body-medium-weight);
1203
+ line-height: 1.5;
1204
+ color: var(--color-label-standard);
1205
+ text-transform: none;
1206
+ }
1207
+
1208
+ .calendar-years-list-control[data-selected=true] {
1209
+ background-color: var(--color-primary-default);
1210
+ color: var(--color-common-100);
1211
+ }
1212
+
1213
+ .calendar-years-list-control:where(:not([data-disabled=true], [data-selected=true])):hover {
1214
+ background-color: var(--color-secondary-default);
1215
+ }
1216
+
1217
+ .calendar-weekdays {
1218
+ text-transform: none;
1219
+ --wr-fz: var(--font-heading-xxsmall-size) !important;
1220
+ --wr-spacing: 10px !important;
1221
+ }
1222
+
1223
+ .calendar-weekday {
1224
+ text-transform: none;
1225
+ width: 46px;
1226
+ min-width: 46px;
1227
+ height: 30px;
1228
+ padding-bottom: 5px;
1229
+ font-size: var(--font-heading-xxsmall-size);
1230
+ font-weight: var(--font-heading-xxsmall-weight);
1231
+ line-height: 1.5;
1232
+ letter-spacing: 0.2px;
1233
+ color: var(--color-label-alternative);
1234
+ text-align: center;
1235
+ vertical-align: middle;
1236
+ }
1237
+
1238
+ .calendar-day {
1239
+ width: 44px;
1240
+ height: 44px;
1241
+ padding: 0;
1242
+ border: none;
1243
+ border-radius: var(--theme-radius-large-1);
1244
+ font-size: var(--font-body-medium-size);
1245
+ color: var(--color-label-standard);
1246
+ }
1247
+
1248
+ .calendar-day[data-outside=true] {
1249
+ color: var(--color-label-alternative);
1250
+ }
1251
+
1252
+ .calendar-day[data-selected=true],
1253
+ .calendar-day[data-focused=true] {
1254
+ background-color: var(--color-primary-default);
1255
+ color: var(--color-common-100);
1256
+ }
1257
+
1258
+ .calendar-day:where(:not([data-disabled=true])):hover {
1259
+ background-color: var(--color-secondary-default);
1260
+ color: var(--color-label-standard);
1261
+ border: none;
1262
+ }
1263
+
1264
+ .calendar-footer {
1265
+ width: 100%;
1266
+ }
1267
+
1014
1268
 
1015
1269
 
1016
1270
  .checkbox {
@@ -1623,6 +1877,34 @@ figure.chip {
1623
1877
  padding: 0;
1624
1878
  }
1625
1879
 
1880
+ .pop-over-content {
1881
+ position: relative;
1882
+ z-index: 50;
1883
+ outline: none;
1884
+ }
1885
+
1886
+ .pop-over-content {
1887
+ width: fit-content;
1888
+ max-width: min(100vw - 24px, max-content);
1889
+ box-sizing: border-box;
1890
+ background-color: var(--color-common-100);
1891
+ border-radius: var(--theme-radius-large-2);
1892
+ overflow: hidden;
1893
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.16), 0 0 2px rgba(0, 0, 0, 0.12);
1894
+ }
1895
+
1896
+ .pop-over-content[data-width=match] {
1897
+ width: var(--radix-popover-trigger-width);
1898
+ }
1899
+
1900
+ .pop-over-content[data-width=fit-content] {
1901
+ width: fit-content;
1902
+ }
1903
+
1904
+ .pop-over-content[data-width=max-content] {
1905
+ width: max-content;
1906
+ }
1907
+
1626
1908
 
1627
1909
 
1628
1910
  .input {
@@ -2019,110 +2301,46 @@ figure.chip {
2019
2301
  font-weight: var(--font-body-xxsmall-weight);
2020
2302
  }
2021
2303
 
2022
- .input-calendar {
2023
- display: flex;
2024
- flex-direction: column;
2025
- gap: var(--spacing-gap-6, 20px);
2304
+ .input-date-field {
2305
+ display: grid;
2306
+ gap: var(--spacing-gap-5);
2026
2307
  width: 100%;
2027
2308
  }
2028
- .input-calendar[data-disabled=true] {
2029
- opacity: 0.6;
2030
- }
2031
-
2032
- .input-calendar-container {
2033
- background-color: var(--color-common-100, #fff);
2034
- border-radius: var(--theme-radius-large-3, 16px);
2035
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.16), 0 0 2px rgba(0, 0, 0, 0.12);
2036
- padding: var(--spacing-padding-10, 32px) var(--spacing-padding-6, 16px) var(--spacing-padding-6, 16px);
2037
- display: flex;
2038
- flex-direction: column;
2039
- gap: var(--spacing-gap-5, 16px);
2040
- }
2041
2309
 
2042
- .input-calendar-root {
2310
+ .input-date-trigger-input {
2043
2311
  width: 100%;
2044
2312
  }
2045
2313
 
2046
- .input-calendar-panel {
2047
- width: 100%;
2048
- border-radius: var(--theme-radius-large-1, 12px);
2049
- background-color: transparent;
2050
- }
2051
-
2052
- .input-calendar-header {
2053
- display: flex;
2054
- align-items: center;
2055
- justify-content: space-between;
2056
- padding-inline: var(--spacing-padding-6, 16px);
2057
- margin-bottom: var(--spacing-gap-4, 12px);
2058
- }
2059
-
2060
- .input-calendar-header-control {
2061
- width: 24px;
2062
- height: 24px;
2314
+ .input-date-trigger-icon {
2315
+ margin: 0;
2063
2316
  display: inline-flex;
2064
2317
  align-items: center;
2065
2318
  justify-content: center;
2066
- border-radius: 999px;
2067
- background: transparent;
2068
- color: var(--color-label-strong, #18191b);
2069
- }
2070
-
2071
- .input-calendar-header-level {
2072
- font-size: var(--font-heading-small-size, 19px);
2073
- font-weight: var(--font-heading-small-weight, 600);
2319
+ width: 28px;
2320
+ height: 28px;
2321
+ color: var(--color-label-alternative);
2322
+ pointer-events: none;
2074
2323
  }
2075
2324
 
2076
- .input-calendar-weekdays {
2325
+ .input-date-footer-template {
2077
2326
  display: grid;
2078
- grid-template-columns: repeat(7, minmax(0, 1fr));
2079
- padding-bottom: var(--spacing-padding-2, 4px);
2080
- }
2081
-
2082
- .input-calendar-weekday {
2083
- text-transform: none;
2084
- font-size: var(--font-heading-xxsmall-size, 15px);
2085
- color: var(--color-label-alternative, #afb1b6);
2086
- text-align: center;
2087
- }
2088
-
2089
- .input-calendar-day {
2090
- width: 44px;
2091
- height: 44px;
2092
- border-radius: var(--theme-radius-large-1, 12px);
2093
- justify-self: center;
2094
- font-size: var(--font-body-medium-size, 17px);
2095
- color: var(--color-label-strong, #3d3f43);
2096
- }
2097
-
2098
- .input-calendar-footer {
2099
- display: flex;
2100
- flex-direction: column;
2101
- gap: var(--spacing-gap-4, 12px);
2327
+ gap: var(--spacing-gap-5);
2102
2328
  width: 100%;
2103
2329
  }
2104
2330
 
2105
- .input-calendar-footer-actions {
2331
+ .input-date-footer-util {
2106
2332
  display: flex;
2107
2333
  align-items: center;
2108
2334
  justify-content: space-between;
2109
- gap: var(--spacing-gap-3, 8px);
2110
- }
2111
-
2112
- .input-calendar-action-button {
2335
+ gap: var(--spacing-gap-3);
2113
2336
  width: 100%;
2114
2337
  }
2115
2338
 
2116
- .input-calendar-footer-actions > :first-child {
2117
- flex: 1 1 auto;
2118
- }
2119
-
2120
- .input-calendar-footer-actions > :last-child {
2121
- flex: 1 1 auto;
2122
- justify-content: flex-end;
2339
+ .input-date-action-button {
2340
+ width: auto;
2123
2341
  }
2124
2342
 
2125
- .input-calendar-apply {
2343
+ .input-date-apply-button {
2126
2344
  width: 100%;
2127
2345
  }
2128
2346
 
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@uniai-fe/uds-primitives",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "UNIAI Design System; Primitives Components Package",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "sideEffects": [
8
8
  "./src/**/*.scss",
9
- "./src/theme/**/*.scss",
10
- "./styles.scss"
9
+ "./styles.scss",
10
+ "./src/**/*.css",
11
+ "./src/init/*.ts"
11
12
  ],
12
13
  "license": "MIT",
13
14
  "homepage": "https://www.uniai.co.kr/",
@@ -36,6 +37,8 @@
36
37
  "./styles": "./styles.scss",
37
38
  "./css": "./dist/styles.css",
38
39
  "./init/dayjs": "./src/init/dayjs",
40
+ "./init/mantine": "./src/init/mantine",
41
+ "./mantine-style": "./src/init/mantine.css",
39
42
  "./*": "./src/*"
40
43
  },
41
44
  "scripts": {
@@ -53,27 +56,31 @@
53
56
  "design-primitives:dev": "pnpm run dev"
54
57
  },
55
58
  "peerDependencies": {
56
- "@radix-ui/react-visually-hidden": "^1.2.4",
59
+ "@mantine/core": "^8",
60
+ "@mantine/dates": "^8",
61
+ "@mantine/hooks": "^8",
57
62
  "@uniai-fe/uds-foundation": "^0.1.0",
58
63
  "@uniai-fe/util-functions": "^0.2.3",
59
64
  "react": "^19",
65
+ "react-daum-postcode": "^3",
60
66
  "react-dom": "^19",
61
- "react-hook-form": "^7",
62
- "react-daum-postcode": "^3"
67
+ "react-hook-form": "^7"
63
68
  },
64
69
  "dependencies": {
65
- "@mantine/dates": "^8.3.14",
66
- "@mantine/hooks": "^8.3.14",
67
70
  "@radix-ui/react-checkbox": "^1.3.3",
68
71
  "@radix-ui/react-dropdown-menu": "^2.1.16",
72
+ "@radix-ui/react-popover": "^1.1.15",
69
73
  "@radix-ui/react-radio-group": "^1.3.8",
70
74
  "@radix-ui/react-tabs": "^1.1.13",
75
+ "@radix-ui/react-visually-hidden": "^1.2.4",
71
76
  "clsx": "^2.1.1",
72
77
  "dayjs": "^1.11.19",
73
78
  "react-daum-postcode": "^3.2.0"
74
79
  },
75
80
  "devDependencies": {
76
- "@radix-ui/react-visually-hidden": "^1.2.4",
81
+ "@mantine/core": "^8.3.14",
82
+ "@mantine/dates": "^8.3.14",
83
+ "@mantine/hooks": "^8.3.14",
77
84
  "@svgr/webpack": "^8.1.0",
78
85
  "@types/node": "^24.10.2",
79
86
  "@types/react": "^19.2.11",
@@ -2,6 +2,11 @@
2
2
  <rect x="20.2" y="6.8" width="13.4" height="16.4" rx="1.2" transform="rotate(90 20.2 6.8)" stroke="#BCBEC2" stroke-width="1.6"/>
3
3
  <path d="M4 10C9.33333 10 20 10 20 10" stroke="#BCBEC2" stroke-width="1.6"/>
4
4
  <path d="M7 13L9 13" stroke="#BCBEC2" stroke-width="1.6"/>
5
+ <path d="M11 13L13 13" stroke="#BCBEC2" stroke-width="1.6"/>
6
+ <path d="M15 13L17 13" stroke="#BCBEC2" stroke-width="1.6"/>
7
+ <path d="M7 17L9 17" stroke="#BCBEC2" stroke-width="1.6"/>
8
+ <path d="M11 17L13 17" stroke="#BCBEC2" stroke-width="1.6"/>
9
+ <path d="M15 17L17 17" stroke="#BCBEC2" stroke-width="1.6"/>
5
10
  <path d="M8.8 4C8.8 3.55817 8.44183 3.2 8 3.2C7.55817 3.2 7.2 3.55817 7.2 4L8 4L8.8 4ZM8 4L7.2 4L7.2 6L8 6L8.8 6L8.8 4L8 4Z" fill="#BCBEC2"/>
6
11
  <path d="M16.8 4C16.8 3.55817 16.4418 3.2 16 3.2C15.5582 3.2 15.2 3.55817 15.2 4L16 4L16.8 4ZM16 4L15.2 4L15.2 6L16 6L16.8 6L16.8 4L16 4Z" fill="#BCBEC2"/>
7
12
  </svg>
@@ -1,4 +1,6 @@
1
- /**
2
- * calendar 카테고리 배럴 placeholder: 실제 구현은 markup/ 하위에 추가한다.
3
- */
1
+ import "./index.scss";
2
+
4
3
  export * from "./markup";
4
+ export * as CalendarHooks from "./hooks";
5
+ export * as CalendarUtils from "./utils";
6
+ export type * from "./types";
@@ -0,0 +1,67 @@
1
+ "use client";
2
+
3
+ import { DatePicker } from "@mantine/dates";
4
+ import { CalendarIcon } from "./Icon";
5
+ import type { CalendarGridProps } from "../types";
6
+ import { mapValueToPicker, parseValueFromPicker } from "../utils";
7
+
8
+ /**
9
+ * Calendar Grid; Mantine DatePicker 래퍼.
10
+ * @component
11
+ * @param {CalendarGridProps} props grid props
12
+ * @param {CalendarValue} props.value 현재 선택 값(YYYY-MM-DD)
13
+ * @param {CalendarOnChange} props.onChange 값 변경 핸들러
14
+ * @param {CalendarDatePickerProps} [props.datePickerProps] Mantine DatePicker 옵션
15
+ * @example
16
+ * <Calendar.Grid value={value} onChange={setValue} />
17
+ */
18
+ export default function CalendarCore({
19
+ value,
20
+ onChange,
21
+ datePickerProps,
22
+ }: CalendarGridProps) {
23
+ // 기본 DatePicker 옵션/스타일 책임을 Calendar.Core에 고정한다.
24
+ const resolvedDatePickerProps = {
25
+ size: "sm" as const,
26
+ firstDayOfWeek: 0 as const,
27
+ weekendDays: [] as Array<0 | 1 | 2 | 3 | 4 | 5 | 6>,
28
+ nextIcon: <CalendarIcon.Chevron.right />,
29
+ previousIcon: <CalendarIcon.Chevron.left />,
30
+ ...datePickerProps,
31
+ classNames: {
32
+ levelsGroup: "calendar-month-level",
33
+ month: "calendar-month-table",
34
+ monthCell: "calendar-month-cell",
35
+ calendarHeader: "calendar-header-row",
36
+ calendarHeaderControl: "calendar-header-control",
37
+ calendarHeaderLevel: "calendar-header-level",
38
+ day: "calendar-day",
39
+ weekday: "calendar-weekday",
40
+ weekdaysRow: "calendar-weekdays",
41
+ monthsList: "calendar-months-list",
42
+ monthsListCell: "calendar-months-list-cell",
43
+ monthsListControl: "calendar-months-list-control",
44
+ yearsList: "calendar-years-list",
45
+ yearsListCell: "calendar-years-list-cell",
46
+ yearsListControl: "calendar-years-list-control",
47
+ ...(datePickerProps?.classNames ?? {}),
48
+ },
49
+ };
50
+
51
+ const handleChange = (nextValue: unknown) => {
52
+ const parsed = parseValueFromPicker(nextValue as Date | null);
53
+ onChange(parsed);
54
+ };
55
+
56
+ return (
57
+ <DatePicker
58
+ className="calendar-grid"
59
+ // Core는 SOT 단일 달력으로 고정한다.
60
+ numberOfColumns={1}
61
+ type="default"
62
+ value={mapValueToPicker(value) as never}
63
+ onChange={handleChange as never}
64
+ {...resolvedDatePickerProps}
65
+ />
66
+ );
67
+ }
@@ -0,0 +1,20 @@
1
+ import CalendarInputIcon from "../img/calendar.svg";
2
+ import ChevronDownIcon from "../img/chevron-down.svg";
3
+ import ChevronLeftIcon from "../img/chevron-left.svg";
4
+ import ChevronRightIcon from "../img/chevron-right.svg";
5
+ import ChevronUpIcon from "../img/chevron-up.svg";
6
+
7
+ /**
8
+ * Calendar; 아이콘
9
+ * - Calendar
10
+ * - Chevron (left, right, up, down)
11
+ */
12
+ export const CalendarIcon = {
13
+ Calendar: CalendarInputIcon,
14
+ Chevron: {
15
+ left: ChevronLeftIcon,
16
+ right: ChevronRightIcon,
17
+ up: ChevronUpIcon,
18
+ down: ChevronDownIcon,
19
+ },
20
+ };