@uniai-fe/uds-templates 0.5.8 → 0.5.10

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.
@@ -1,151 +1,150 @@
1
- .weather-base-container {
2
- width: fit-content;
1
+ .weather-page-header {
3
2
  display: flex;
4
3
  align-items: center;
5
-
6
- span {
7
- font-size: 1.4rem;
8
- }
4
+ gap: 1.6rem;
5
+ width: fit-content;
6
+ height: 2.4rem;
7
+ white-space: nowrap;
9
8
  }
10
9
 
11
10
  .weather-base-icon {
11
+ position: relative;
12
12
  width: 2.5rem;
13
13
  height: 2.4rem;
14
- position: relative;
14
+ flex: 0 0 auto;
15
15
  }
16
16
 
17
- .weather-base-text-info {
17
+ .weather-address {
18
18
  display: flex;
19
19
  align-items: center;
20
+ gap: 0.4rem;
21
+ width: fit-content;
22
+ }
20
23
 
21
- dt {
22
- margin-right: 0.8rem;
23
- font-size: 0;
24
-
25
- span {
26
- color: var(--color-cool-gray-35);
27
- }
28
- }
24
+ .weather-address-icon {
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ width: 1.6rem;
29
+ height: 1.6rem;
30
+ flex: 0 0 auto;
31
+ }
29
32
 
30
- dd {
31
- font-size: 0;
32
- display: flex;
33
- align-items: flex-start;
33
+ .weather-address-text {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 0.4rem;
37
+ color: var(--color-cool-gray-10);
38
+ font-size: 1.3rem;
39
+ font-weight: 500;
40
+ line-height: 1.5;
41
+ letter-spacing: 0;
42
+ }
34
43
 
35
- span {
36
- color: var(--color-cool-gray-10);
37
- font-weight: 600;
38
- }
39
- }
44
+ .weather-address-date {
45
+ color: var(--color-cool-gray-40);
40
46
  }
41
47
 
42
- .weather-base-divider {
43
- width: 1px;
44
- height: 1.3rem;
45
- margin: 0 0.8rem;
46
- background: var(--color-cool-gray-85);
48
+ .weather-today-container {
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 0.8rem;
52
+ width: fit-content;
47
53
  }
48
54
 
49
- .weather-address {
55
+ .weather-today-text {
50
56
  display: flex;
51
57
  align-items: center;
58
+ gap: 0.8rem;
52
59
  width: fit-content;
60
+ }
53
61
 
54
- &-icon {
55
- width: 1.6rem;
56
- height: 1.6rem;
57
- margin-right: 0.4rem;
58
- position: relative;
59
- }
60
-
61
- &-text {
62
- width: fit-content;
63
- margin-right: 1rem;
64
- display: flex;
65
- align-items: center;
66
-
67
- span {
68
- font-size: 1.6rem;
69
- color: var(--color-cool-gray-10);
70
- font-weight: 600;
71
- white-space: nowrap;
72
- transform: translateY(0.1rem);
73
- }
74
- }
62
+ .weather-next-days-container {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 0.8rem;
66
+ width: fit-content;
75
67
  }
76
68
 
77
- .weather-today-container {
78
- @extend .weather-base-container;
69
+ .weather-temperature-text {
70
+ color: var(--color-cool-gray-10);
71
+ font-size: 0;
72
+ font-weight: 500;
73
+ line-height: 1.5;
74
+ letter-spacing: 0;
75
+ }
79
76
 
80
- span {
81
- white-space: nowrap;
82
- }
77
+ .weather-humidity-text {
78
+ color: var(--color-cool-gray-10);
79
+ font-size: 0;
80
+ font-weight: 500;
81
+ line-height: 1.5;
82
+ letter-spacing: 0;
83
+ }
83
84
 
84
- .empty-text {
85
- font-size: 1.4rem;
86
- padding-right: 4rem;
87
- }
85
+ .weather-forecast-text {
86
+ color: var(--color-cool-gray-10);
87
+ font-size: 0;
88
+ font-weight: 500;
89
+ line-height: 1.5;
90
+ letter-spacing: 0;
88
91
  }
89
92
 
90
- .weather-today-temperature {
91
- margin-left: 1rem;
92
- display: flex;
93
- align-items: flex-start;
93
+ .weather-label {
94
+ color: var(--color-cool-gray-40);
95
+ font-size: 1.3rem;
96
+ font-weight: 500;
97
+ }
94
98
 
95
- span {
96
- font-size: 2rem;
97
- font-weight: 700;
98
- color: var(--color-blue-55);
99
- }
99
+ .weather-value {
100
+ color: var(--color-cool-gray-10);
101
+ font-size: 1.3rem;
102
+ font-weight: 600;
103
+ }
100
104
 
101
- .unit {
102
- font-size: 1.2rem;
103
- }
105
+ .weather-unit {
106
+ color: var(--color-cool-gray-10);
107
+ font-size: 0.84rem;
108
+ font-weight: 600;
104
109
  }
105
110
 
106
- .weather-today-humidity {
107
- margin-left: 1.4rem;
111
+ .weather-range {
112
+ color: var(--color-cool-gray-10);
113
+ font-size: 1.3rem;
114
+ font-weight: 600;
108
115
  }
109
116
 
110
117
  .weather-alert {
111
- width: fit-content;
112
- height: 2.6rem;
113
- padding: 0 1rem;
114
- margin-left: 1rem;
115
- border-radius: 0.8rem;
116
- background-color: var(--color-cool-gray-95, #f4f6f8);
117
118
  display: flex;
118
119
  align-items: center;
119
-
120
- &-text {
121
- height: fit-content;
122
- font-size: 0;
123
-
124
- span {
125
- font-size: 1.2rem;
126
- color: var(--color-blue-55, #007cdb);
127
- font-weight: 600;
128
- line-height: 1.6;
129
- }
130
- }
120
+ justify-content: center;
121
+ width: fit-content;
122
+ height: 2rem;
123
+ padding: 0 0.6rem;
124
+ border-radius: 0.6rem;
125
+ background-color: var(--color-blue-95);
131
126
  }
132
127
 
133
- .weather-next-days-container {
134
- @extend .weather-base-container;
128
+ .weather-alert-loading {
129
+ display: flex;
130
+ align-items: center;
131
+ width: fit-content;
132
+ height: 2.4rem;
135
133
  }
136
134
 
137
- .weather-next-days-text {
138
- @extend .weather-base-text-info;
139
-
140
- dt {
141
- margin-right: 0.8rem;
142
- }
143
-
144
- dd:nth-of-type(n + 2) {
145
- margin-left: 0.8rem;
135
+ .weather-alert-text {
136
+ display: flex;
137
+ align-items: center;
138
+ color: var(--color-blue-55);
139
+ font-size: 1.1rem;
140
+ font-weight: 400;
141
+ line-height: 1.5;
142
+ letter-spacing: 0;
143
+ }
146
144
 
147
- .unit {
148
- font-size: 1rem;
149
- }
150
- }
145
+ .weather-alert-text span {
146
+ color: inherit;
147
+ font-size: inherit;
148
+ font-weight: inherit;
149
+ line-height: inherit;
151
150
  }
@@ -22,6 +22,26 @@ export type WeatherGeoCoordinate = {
22
22
  lng: number | null;
23
23
  };
24
24
 
25
+ /**
26
+ * 날씨 API locale 요청 옵션.
27
+ * @property {string} [locale] 요청 언어 코드. 기본 지원값은 ko, en, ja이며 타입은 확장 가능한 string으로 유지한다.
28
+ */
29
+ export interface WeatherApiLocaleOptions {
30
+ /**
31
+ * 요청 언어 코드. 기본 지원값은 ko, en, ja이며 타입은 확장 가능한 string으로 유지한다.
32
+ */
33
+ locale?: string;
34
+ }
35
+
36
+ /**
37
+ * OpenWeatherMap 요청 파라미터.
38
+ * @property {number | null} lat 위도
39
+ * @property {number | null} lng 경도
40
+ * @property {string} [locale] 요청 언어 코드
41
+ */
42
+ export type WeatherOpenWeatherMapParams = WeatherGeoCoordinate &
43
+ WeatherApiLocaleOptions;
44
+
25
45
  /**
26
46
  * 좌표와 주소 정보를 함께 담는 구조.
27
47
  * @property {string | null} address 좌표 주소
@@ -2,3 +2,4 @@ export type * from "./base";
2
2
  export type * from "./api";
3
3
  export type * from "./korea";
4
4
  export type * from "./open-weather-map";
5
+ export type * from "./page-header";
@@ -0,0 +1,277 @@
1
+ import type {
2
+ API_Res_WeatherKoreaForecast,
3
+ API_Res_WeatherKoreaNextDays,
4
+ API_Res_WeatherKoreaNow,
5
+ } from "./api";
6
+ import type {
7
+ OWM_Res_Weather_Forecast,
8
+ OWM_Res_Weather_Now,
9
+ } from "./open-weather-map";
10
+
11
+ /**
12
+ * Weather Page Header; locale 옵션
13
+ * @property {string} [locale] 표시 언어 코드. 기본 지원값은 ko, en, ja이며 타입은 확장 가능한 string으로 유지한다.
14
+ */
15
+ export interface WeatherLocaleOptions {
16
+ /**
17
+ * 표시 언어 코드. 기본 지원값은 ko, en, ja이며 타입은 확장 가능한 string으로 유지한다.
18
+ */
19
+ locale?: string;
20
+ }
21
+
22
+ /**
23
+ * Weather Page Header; 텍스트 옵션
24
+ * @property {string} currentWeatherLoading 현재 날씨 로딩 문구
25
+ * @property {string} forecastWeatherLoading 예보 날씨 로딩 문구
26
+ * @property {string} alertLoading 특보 로딩 문구
27
+ * @property {string} currentLabel 현재 기온 라벨
28
+ * @property {string} maxTemperatureLabel 최고 기온 라벨
29
+ * @property {string} minTemperatureLabel 최저 기온 라벨
30
+ * @property {string} humidityLabel 습도 라벨
31
+ * @property {string} tomorrowLabel 내일 라벨
32
+ * @property {string} dayAfterTomorrowLabel 모레 라벨
33
+ * @property {string} weatherIconAlt 날씨 아이콘 기본 대체 텍스트
34
+ * @property {string} addressIconAlt 위치 아이콘 대체 텍스트
35
+ * @property {string} conditionFallbackLabel 날씨 상태 fallback 텍스트
36
+ * @property {string} alertPreliminaryLevelLabel 예비 특보 수준 라벨
37
+ * @property {string} alertWatchLevelLabel 주의보 수준 라벨
38
+ * @property {string} alertCancelCommandLabel 특보 해제 명령 라벨
39
+ * @property {string} alertIssueCommandLabel 특보 발령 명령 라벨
40
+ */
41
+ export interface WeatherPageHeaderTexts {
42
+ /**
43
+ * 현재 날씨 로딩 문구
44
+ */
45
+ currentWeatherLoading: string;
46
+ /**
47
+ * 예보 날씨 로딩 문구
48
+ */
49
+ forecastWeatherLoading: string;
50
+ /**
51
+ * 특보 로딩 문구
52
+ */
53
+ alertLoading: string;
54
+ /**
55
+ * 현재 기온 라벨
56
+ */
57
+ currentLabel: string;
58
+ /**
59
+ * 최고 기온 라벨
60
+ */
61
+ maxTemperatureLabel: string;
62
+ /**
63
+ * 최저 기온 라벨
64
+ */
65
+ minTemperatureLabel: string;
66
+ /**
67
+ * 습도 라벨
68
+ */
69
+ humidityLabel: string;
70
+ /**
71
+ * 내일 라벨
72
+ */
73
+ tomorrowLabel: string;
74
+ /**
75
+ * 모레 라벨
76
+ */
77
+ dayAfterTomorrowLabel: string;
78
+ /**
79
+ * 날씨 아이콘 기본 대체 텍스트
80
+ */
81
+ weatherIconAlt: string;
82
+ /**
83
+ * 위치 아이콘 대체 텍스트
84
+ */
85
+ addressIconAlt: string;
86
+ /**
87
+ * 날씨 상태 fallback 텍스트
88
+ */
89
+ conditionFallbackLabel: string;
90
+ /**
91
+ * 예비 특보 수준 라벨
92
+ */
93
+ alertPreliminaryLevelLabel: string;
94
+ /**
95
+ * 주의보 수준 라벨
96
+ */
97
+ alertWatchLevelLabel: string;
98
+ /**
99
+ * 특보 해제 명령 라벨
100
+ */
101
+ alertCancelCommandLabel: string;
102
+ /**
103
+ * 특보 발령 명령 라벨
104
+ */
105
+ alertIssueCommandLabel: string;
106
+ }
107
+
108
+ /**
109
+ * Weather Page Header; locale과 텍스트 override 조합 옵션
110
+ * @property {string} [locale] 표시 언어 코드
111
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
112
+ */
113
+ export interface WeatherPageHeaderLocaleOptions extends WeatherLocaleOptions {
114
+ /**
115
+ * 서비스에서 주입한 표시 문구
116
+ */
117
+ texts?: Partial<WeatherPageHeaderTexts>;
118
+ }
119
+
120
+ /**
121
+ * Weather Page Header; KMA weather query 결과
122
+ * @property {API_Res_WeatherKoreaNow} [now] 현재 날씨 응답
123
+ * @property {API_Res_WeatherKoreaForecast} [forecast] 예보 날씨 응답
124
+ * @property {boolean} isFetchingNow 현재 날씨 조회 상태
125
+ * @property {boolean} isFetchingForecast 예보 날씨 조회 상태
126
+ */
127
+ export interface WeatherPageHeaderKoreaWeather {
128
+ /**
129
+ * 현재 날씨 응답
130
+ */
131
+ now?: API_Res_WeatherKoreaNow;
132
+ /**
133
+ * 예보 날씨 응답
134
+ */
135
+ forecast?: API_Res_WeatherKoreaForecast;
136
+ /**
137
+ * 현재 날씨 조회 상태
138
+ */
139
+ isFetchingNow: boolean;
140
+ /**
141
+ * 예보 날씨 조회 상태
142
+ */
143
+ isFetchingForecast: boolean;
144
+ }
145
+
146
+ /**
147
+ * Weather Page Header; OpenWeatherMap query 결과
148
+ * @property {OWM_Res_Weather_Now} [now] 현재 날씨 응답
149
+ * @property {OWM_Res_Weather_Forecast} [forecast] 예보 날씨 응답
150
+ * @property {boolean} isFetchingNow 현재 날씨 조회 상태
151
+ * @property {boolean} isFetchingForecast 예보 날씨 조회 상태
152
+ */
153
+ export interface WeatherPageHeaderOpenWeatherMapWeather {
154
+ /**
155
+ * 현재 날씨 응답
156
+ */
157
+ now?: OWM_Res_Weather_Now;
158
+ /**
159
+ * 예보 날씨 응답
160
+ */
161
+ forecast?: OWM_Res_Weather_Forecast;
162
+ /**
163
+ * 현재 날씨 조회 상태
164
+ */
165
+ isFetchingNow: boolean;
166
+ /**
167
+ * 예보 날씨 조회 상태
168
+ */
169
+ isFetchingForecast: boolean;
170
+ }
171
+
172
+ /**
173
+ * Weather Page Header; 상위 container에서 준비한 weather query 결과
174
+ * @property {WeatherPageHeaderKoreaWeather} [koreaWeather] KMA weather query 결과
175
+ * @property {WeatherPageHeaderOpenWeatherMapWeather} [openWeatherMapWeather] OpenWeatherMap query 결과
176
+ */
177
+ export interface WeatherPageHeaderDataOptions {
178
+ /**
179
+ * KMA weather query 결과
180
+ */
181
+ koreaWeather?: WeatherPageHeaderKoreaWeather;
182
+ /**
183
+ * OpenWeatherMap query 결과
184
+ */
185
+ openWeatherMapWeather?: WeatherPageHeaderOpenWeatherMapWeather;
186
+ }
187
+
188
+ /**
189
+ * Weather Page Header; container props
190
+ * @property {string} [locale] 표시 언어 코드
191
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
192
+ */
193
+ export type WeatherPageHeaderContainerProps = WeatherPageHeaderLocaleOptions;
194
+
195
+ /**
196
+ * Weather Page Header; address props
197
+ * @property {string} [locale] 표시 언어 코드
198
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
199
+ */
200
+ export type WeatherPageHeaderAddressProps = WeatherPageHeaderLocaleOptions;
201
+
202
+ /**
203
+ * Weather Page Header; today props
204
+ * @property {string} [locale] 표시 언어 코드
205
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
206
+ * @property {WeatherPageHeaderKoreaWeather} [koreaWeather] KMA weather query 결과
207
+ * @property {WeatherPageHeaderOpenWeatherMapWeather} [openWeatherMapWeather] OpenWeatherMap query 결과
208
+ */
209
+ export type WeatherPageHeaderTodayProps = WeatherPageHeaderLocaleOptions &
210
+ WeatherPageHeaderDataOptions;
211
+
212
+ /**
213
+ * Weather Page Header; forecast props
214
+ * @property {string} [locale] 표시 언어 코드
215
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
216
+ * @property {WeatherPageHeaderKoreaWeather} [koreaWeather] KMA weather query 결과
217
+ * @property {WeatherPageHeaderOpenWeatherMapWeather} [openWeatherMapWeather] OpenWeatherMap query 결과
218
+ */
219
+ export type WeatherPageHeaderForecastProps = WeatherPageHeaderLocaleOptions &
220
+ WeatherPageHeaderDataOptions;
221
+
222
+ /**
223
+ * Weather Page Header; alert props
224
+ * @property {string} [locale] 표시 언어 코드
225
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
226
+ */
227
+ export type WeatherPageHeaderAlertProps = WeatherPageHeaderLocaleOptions;
228
+
229
+ /**
230
+ * Weather Page Header; next days props
231
+ * @property {string} title 날짜 라벨
232
+ * @property {API_Res_WeatherKoreaNextDays} [data] 예보 데이터
233
+ * @property {string} [locale] 표시 언어 코드
234
+ * @property {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 표시 문구
235
+ */
236
+ export interface WeatherPageHeaderNextDaysProps extends WeatherPageHeaderLocaleOptions {
237
+ /**
238
+ * 날짜 라벨
239
+ */
240
+ title: string;
241
+ /**
242
+ * 예보 데이터
243
+ */
244
+ data?: API_Res_WeatherKoreaNextDays;
245
+ }
246
+
247
+ /**
248
+ * Weather Icon; 날씨 아이콘 props
249
+ * @property {string | null} [code] 날씨 아이콘 코드
250
+ * @property {string | null} [name] 날씨 상태 이름
251
+ * @property {string} [alt] 아이콘 대체 텍스트 fallback
252
+ */
253
+ export interface WeatherIconProps {
254
+ /**
255
+ * 날씨 아이콘 코드
256
+ */
257
+ code?: string | null;
258
+ /**
259
+ * 날씨 상태 이름
260
+ */
261
+ name?: string | null;
262
+ /**
263
+ * 아이콘 대체 텍스트 fallback
264
+ */
265
+ alt?: string;
266
+ }
267
+
268
+ /**
269
+ * Weather Address Icon; 위치 아이콘 props
270
+ * @property {string} [alt] 아이콘 대체 텍스트
271
+ */
272
+ export interface WeatherAddressIconProps {
273
+ /**
274
+ * 아이콘 대체 텍스트
275
+ */
276
+ alt?: string;
277
+ }
@@ -2,3 +2,4 @@ export * from "./location";
2
2
  export * from "./date-time";
3
3
  export * from "./weather";
4
4
  export * from "./alert";
5
+ export * from "./locale";
@@ -0,0 +1,73 @@
1
+ import type { WeatherPageHeaderTexts } from "../types";
2
+
3
+ const WEATHER_PAGE_HEADER_DEFAULT_TEXTS: WeatherPageHeaderTexts = {
4
+ currentWeatherLoading: "현재 날씨 불러오는 중...",
5
+ forecastWeatherLoading: "예보 날씨 불러오는 중...",
6
+ alertLoading: "특보 불러오는 중...",
7
+ currentLabel: "현재",
8
+ maxTemperatureLabel: "최고:",
9
+ minTemperatureLabel: "최저:",
10
+ humidityLabel: "습도",
11
+ tomorrowLabel: "내일",
12
+ dayAfterTomorrowLabel: "모레",
13
+ weatherIconAlt: "날씨 아이콘",
14
+ addressIconAlt: "날씨 위치",
15
+ conditionFallbackLabel: "-",
16
+ alertPreliminaryLevelLabel: "예비특보",
17
+ alertWatchLevelLabel: "주의보",
18
+ alertCancelCommandLabel: "해제",
19
+ alertIssueCommandLabel: "발령",
20
+ };
21
+
22
+ const OPEN_WEATHER_MAP_LANG_BY_LOCALE: Record<string, string> = {
23
+ ko: "kr",
24
+ en: "en",
25
+ ja: "ja",
26
+ };
27
+
28
+ /**
29
+ * Weather Locale; locale 기준 키 정규화
30
+ * @param {string} [locale] locale 코드
31
+ * @return {string} 전달된 locale의 기본 언어 코드
32
+ * @example
33
+ * getWeatherLocaleKey("ko-KR")
34
+ */
35
+ export const getWeatherLocaleKey = (locale?: string): string =>
36
+ locale?.trim().toLowerCase().split(/[-_]/)[0] || "ko";
37
+
38
+ /**
39
+ * Weather Locale; KMA provider 사용 여부
40
+ * @param {string} [locale] locale 코드
41
+ * @return {boolean} KMA provider 대상 locale 여부
42
+ * @example
43
+ * isKoreaWeatherLocale("ko-KR")
44
+ */
45
+ export const isKoreaWeatherLocale = (locale?: string): boolean =>
46
+ getWeatherLocaleKey(locale) === "ko";
47
+
48
+ /**
49
+ * Weather Locale; page-header 텍스트 병합
50
+ * @param {Partial<WeatherPageHeaderTexts>} [texts] 서비스에서 주입한 텍스트
51
+ * @return {WeatherPageHeaderTexts} 기본 fallback과 서비스 주입 텍스트를 병합한 텍스트
52
+ * @example
53
+ * resolveWeatherPageHeaderTexts({ humidityLabel: "습도" })
54
+ */
55
+ export const resolveWeatherPageHeaderTexts = (
56
+ texts?: Partial<WeatherPageHeaderTexts>,
57
+ ): WeatherPageHeaderTexts => ({
58
+ ...WEATHER_PAGE_HEADER_DEFAULT_TEXTS,
59
+ ...texts,
60
+ });
61
+
62
+ /**
63
+ * Weather Locale; OpenWeatherMap API lang 값 변환
64
+ * @param {string} [locale] locale 코드
65
+ * @return {string} OpenWeatherMap lang 파라미터
66
+ * @example
67
+ * getOpenWeatherMapLang("ko")
68
+ */
69
+ export const getOpenWeatherMapLang = (locale?: string): string => {
70
+ const localeKey = getWeatherLocaleKey(locale);
71
+
72
+ return OPEN_WEATHER_MAP_LANG_BY_LOCALE[localeKey] ?? localeKey;
73
+ };