@iyulab/components 1.0.10 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/UFormControlElement.d.ts +2 -0
- package/dist/components/UFormControlElement.js +1 -0
- package/dist/components/rating/URating.js +6 -4
- package/dist/components/select/USelect.js +5 -3
- package/dist/components/slider/USlider.js +5 -3
- package/dist/core/locale.d.ts +69 -0
- package/dist/core/locale.js +85 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/package.json +6 -3
|
@@ -23,6 +23,8 @@ export declare abstract class UFormControlElement<T> extends UElement {
|
|
|
23
23
|
description?: string;
|
|
24
24
|
/** 커스텀 유효성 검증 메시지 */
|
|
25
25
|
validationMessage?: string;
|
|
26
|
+
/** chrome 문자열(검증 메시지 등)에 사용할 로케일 태그 (예: 'ko-KR'). 미지정 시 전역 기본/문서 언어를 따른다. */
|
|
27
|
+
locale?: string;
|
|
26
28
|
/** 폼 제출 시 사용되는 이름 */
|
|
27
29
|
name?: string;
|
|
28
30
|
/** 폼 제출 시 사용되는 값 */
|
|
@@ -62,6 +62,7 @@ __decorate([property({ type: Boolean }), __decorateMetadata("design:type", Boole
|
|
|
62
62
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UFormControlElement.prototype, "label", void 0);
|
|
63
63
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UFormControlElement.prototype, "description", void 0);
|
|
64
64
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UFormControlElement.prototype, "validationMessage", void 0);
|
|
65
|
+
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UFormControlElement.prototype, "locale", void 0);
|
|
65
66
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UFormControlElement.prototype, "name", void 0);
|
|
66
67
|
__decorate([property({ type: Object }), __decorateMetadata("design:type", Object)], UFormControlElement.prototype, "value", void 0);
|
|
67
68
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatTemplate, getLocaleStrings, resolveLocale } from "../../core/locale.js";
|
|
1
2
|
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorateMetadata.js";
|
|
2
3
|
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
3
4
|
import { UFormControlElement } from "../UFormControlElement.js";
|
|
@@ -153,23 +154,24 @@ var URating = class URating extends UFormControlElement {
|
|
|
153
154
|
}
|
|
154
155
|
getValidity() {
|
|
155
156
|
const v = this.value || 0;
|
|
157
|
+
const s = getLocaleStrings(resolveLocale(this.locale));
|
|
156
158
|
if (this.required && !v) return {
|
|
157
159
|
flags: { valueMissing: true },
|
|
158
|
-
message:
|
|
160
|
+
message: s.required
|
|
159
161
|
};
|
|
160
162
|
if (v && v < this.min) return {
|
|
161
163
|
flags: { rangeUnderflow: true },
|
|
162
|
-
message:
|
|
164
|
+
message: formatTemplate(s.minValue, { min: this.min })
|
|
163
165
|
};
|
|
164
166
|
if (v && v > this.max) return {
|
|
165
167
|
flags: { rangeOverflow: true },
|
|
166
|
-
message:
|
|
168
|
+
message: formatTemplate(s.maxValue, { max: this.max })
|
|
167
169
|
};
|
|
168
170
|
if (v && this.precision < 1) {
|
|
169
171
|
const remainder = Math.abs(v % this.precision);
|
|
170
172
|
if (remainder > .001 && Math.abs(remainder - this.precision) > .001) return {
|
|
171
173
|
flags: { stepMismatch: true },
|
|
172
|
-
message:
|
|
174
|
+
message: formatTemplate(s.stepMismatch, { step: this.precision })
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
return {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatTemplate, getLocaleStrings, resolveLocale } from "../../core/locale.js";
|
|
1
2
|
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorateMetadata.js";
|
|
2
3
|
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
3
4
|
import { UFormControlElement } from "../UFormControlElement.js";
|
|
@@ -261,17 +262,18 @@ var USelect = class USelect extends UFormControlElement {
|
|
|
261
262
|
}));
|
|
262
263
|
}
|
|
263
264
|
getValidity(values) {
|
|
265
|
+
const s = getLocaleStrings(resolveLocale(this.locale));
|
|
264
266
|
if (this.required && !values.length) return {
|
|
265
267
|
flags: { valueMissing: true },
|
|
266
|
-
message:
|
|
268
|
+
message: s.required
|
|
267
269
|
};
|
|
268
270
|
if (this.multiple && this.minCount != null && values.length > 0 && values.length < this.minCount) return {
|
|
269
271
|
flags: { rangeUnderflow: true },
|
|
270
|
-
message:
|
|
272
|
+
message: formatTemplate(s.minCount, { min: this.minCount })
|
|
271
273
|
};
|
|
272
274
|
if (this.multiple && this.maxCount != null && values.length > this.maxCount) return {
|
|
273
275
|
flags: { rangeOverflow: true },
|
|
274
|
-
message:
|
|
276
|
+
message: formatTemplate(s.maxCount, { max: this.maxCount })
|
|
275
277
|
};
|
|
276
278
|
return {
|
|
277
279
|
flags: {},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatTemplate, getLocaleStrings, resolveLocale } from "../../core/locale.js";
|
|
1
2
|
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorateMetadata.js";
|
|
2
3
|
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
|
|
3
4
|
import { UFormControlElement } from "../UFormControlElement.js";
|
|
@@ -194,17 +195,18 @@ var USlider = class USlider extends UFormControlElement {
|
|
|
194
195
|
}
|
|
195
196
|
getValidity() {
|
|
196
197
|
const v = this.valueAsNumber;
|
|
198
|
+
const s = getLocaleStrings(resolveLocale(this.locale));
|
|
197
199
|
if (this.required && !v) return {
|
|
198
200
|
flags: { valueMissing: true },
|
|
199
|
-
message:
|
|
201
|
+
message: s.required
|
|
200
202
|
};
|
|
201
203
|
if (v < this.min) return {
|
|
202
204
|
flags: { rangeUnderflow: true },
|
|
203
|
-
message:
|
|
205
|
+
message: formatTemplate(s.minValue, { min: this.min })
|
|
204
206
|
};
|
|
205
207
|
if (v > this.max) return {
|
|
206
208
|
flags: { rangeOverflow: true },
|
|
207
|
-
message:
|
|
209
|
+
message: formatTemplate(s.maxValue, { max: this.max })
|
|
208
210
|
};
|
|
209
211
|
return {
|
|
210
212
|
flags: {},
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @iyulab/components 의 경량 로케일 레지스트리.
|
|
3
|
+
*
|
|
4
|
+
* 범위: 라이브러리가 스스로 생성하는 chrome 문자열(검증 메시지 등)만 대상.
|
|
5
|
+
* 일반 i18n 프레임워크가 아니다. 앱 콘텐츠 번역은 consumer 의 i18n 계층(예:
|
|
6
|
+
* modern-app 의 i18next)이 담당한다.
|
|
7
|
+
*
|
|
8
|
+
* 영어가 내장 기본값이며, 한국어 등 도메인 로케일은 consumer 가 등록한다:
|
|
9
|
+
* registerLocale('ko', { required: '필수 항목입니다.', ... });
|
|
10
|
+
* setDefaultLocale('ko');
|
|
11
|
+
*
|
|
12
|
+
* 모노레포 로케일 표준(packages/u-widgets/src/core/locale.ts)과 동일한 계약을 따른다.
|
|
13
|
+
*/
|
|
14
|
+
export interface UComponentsLocaleStrings {
|
|
15
|
+
required: string;
|
|
16
|
+
minValue: string;
|
|
17
|
+
maxValue: string;
|
|
18
|
+
stepMismatch: string;
|
|
19
|
+
minCount: string;
|
|
20
|
+
maxCount: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 로케일을 등록한다. 부분 등록은 영어 기본값에 병합된다.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerLocale(lang: string, strings: Partial<UComponentsLocaleStrings>): void;
|
|
26
|
+
/**
|
|
27
|
+
* 주어진 언어 태그에 대한 로케일 문자열을 해석한다.
|
|
28
|
+
*
|
|
29
|
+
* 해석 순서:
|
|
30
|
+
* 1. 정확히 일치 (예: 'ko-KR')
|
|
31
|
+
* 2. 기반 언어 (예: 'ko')
|
|
32
|
+
* 3. 영어 폴백
|
|
33
|
+
*/
|
|
34
|
+
export declare function getLocaleStrings(lang?: string): UComponentsLocaleStrings;
|
|
35
|
+
/**
|
|
36
|
+
* 템플릿 문자열의 {key} 플레이스홀더를 치환한다.
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatTemplate(template: string, params: Record<string, string | number>): string;
|
|
39
|
+
/**
|
|
40
|
+
* 영어 기본값을 반환한다 (테스트/참조용).
|
|
41
|
+
*/
|
|
42
|
+
export declare function getDefaultLocale(): UComponentsLocaleStrings;
|
|
43
|
+
/**
|
|
44
|
+
* 모든 컴포넌트에 적용되는 전역 기본 로케일을 설정한다.
|
|
45
|
+
*
|
|
46
|
+
* 해석 순서(우선순위 높은 순):
|
|
47
|
+
* 1. 컴포넌트별 `locale` 속성/프로퍼티
|
|
48
|
+
* 2. setDefaultLocale() 값
|
|
49
|
+
* 3. document.documentElement.lang (브라우저)
|
|
50
|
+
* 4. 영어 폴백
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { setDefaultLocale } from '@iyulab/components';
|
|
55
|
+
* setDefaultLocale('ko-KR');
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function setDefaultLocale(lang: string | undefined): void;
|
|
59
|
+
/**
|
|
60
|
+
* setDefaultLocale() 로 설정된 전역 기본 로케일을 반환한다.
|
|
61
|
+
* 설정되지 않았으면 undefined 를 반환한다.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getEffectiveLocale(): string | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* 컴포넌트가 사용할 로케일을 해석한다.
|
|
66
|
+
*
|
|
67
|
+
* 우선순위: widgetLocale > setDefaultLocale() > document.lang > undefined
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveLocale(widgetLocale?: string | null): string | undefined;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//#region src/core/locale.ts
|
|
2
|
+
var EN = {
|
|
3
|
+
required: "This field is required",
|
|
4
|
+
minValue: "Value must be at least {min}",
|
|
5
|
+
maxValue: "Value must be at most {max}",
|
|
6
|
+
stepMismatch: "Value must be a multiple of {step}",
|
|
7
|
+
minCount: "Please select at least {min} items",
|
|
8
|
+
maxCount: "Please select no more than {max} items"
|
|
9
|
+
};
|
|
10
|
+
var registry = /* @__PURE__ */ new Map();
|
|
11
|
+
/**
|
|
12
|
+
* 로케일을 등록한다. 부분 등록은 영어 기본값에 병합된다.
|
|
13
|
+
*/
|
|
14
|
+
function registerLocale(lang, strings) {
|
|
15
|
+
registry.set(lang.toLowerCase(), {
|
|
16
|
+
...EN,
|
|
17
|
+
...strings
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 주어진 언어 태그에 대한 로케일 문자열을 해석한다.
|
|
22
|
+
*
|
|
23
|
+
* 해석 순서:
|
|
24
|
+
* 1. 정확히 일치 (예: 'ko-KR')
|
|
25
|
+
* 2. 기반 언어 (예: 'ko')
|
|
26
|
+
* 3. 영어 폴백
|
|
27
|
+
*/
|
|
28
|
+
function getLocaleStrings(lang) {
|
|
29
|
+
if (!lang) return EN;
|
|
30
|
+
const key = lang.toLowerCase();
|
|
31
|
+
if (registry.has(key)) return registry.get(key);
|
|
32
|
+
const base = key.split("-")[0];
|
|
33
|
+
if (base !== key && registry.has(base)) return registry.get(base);
|
|
34
|
+
return EN;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 템플릿 문자열의 {key} 플레이스홀더를 치환한다.
|
|
38
|
+
*/
|
|
39
|
+
function formatTemplate(template, params) {
|
|
40
|
+
return template.replace(/\{(\w+)\}/g, (_, key) => params[key] != null ? String(params[key]) : `{${key}}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 영어 기본값을 반환한다 (테스트/참조용).
|
|
44
|
+
*/
|
|
45
|
+
function getDefaultLocale() {
|
|
46
|
+
return { ...EN };
|
|
47
|
+
}
|
|
48
|
+
var _defaultLocale;
|
|
49
|
+
/**
|
|
50
|
+
* 모든 컴포넌트에 적용되는 전역 기본 로케일을 설정한다.
|
|
51
|
+
*
|
|
52
|
+
* 해석 순서(우선순위 높은 순):
|
|
53
|
+
* 1. 컴포넌트별 `locale` 속성/프로퍼티
|
|
54
|
+
* 2. setDefaultLocale() 값
|
|
55
|
+
* 3. document.documentElement.lang (브라우저)
|
|
56
|
+
* 4. 영어 폴백
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { setDefaultLocale } from '@iyulab/components';
|
|
61
|
+
* setDefaultLocale('ko-KR');
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
function setDefaultLocale(lang) {
|
|
65
|
+
_defaultLocale = lang;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* setDefaultLocale() 로 설정된 전역 기본 로케일을 반환한다.
|
|
69
|
+
* 설정되지 않았으면 undefined 를 반환한다.
|
|
70
|
+
*/
|
|
71
|
+
function getEffectiveLocale() {
|
|
72
|
+
return _defaultLocale;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 컴포넌트가 사용할 로케일을 해석한다.
|
|
76
|
+
*
|
|
77
|
+
* 우선순위: widgetLocale > setDefaultLocale() > document.lang > undefined
|
|
78
|
+
*/
|
|
79
|
+
function resolveLocale(widgetLocale) {
|
|
80
|
+
if (widgetLocale) return widgetLocale;
|
|
81
|
+
if (_defaultLocale) return _defaultLocale;
|
|
82
|
+
if (typeof document !== "undefined" && document.documentElement?.lang) return document.documentElement.lang;
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { formatTemplate, getDefaultLocale, getEffectiveLocale, getLocaleStrings, registerLocale, resolveLocale, setDefaultLocale };
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatTemplate, getDefaultLocale, getEffectiveLocale, getLocaleStrings, registerLocale, resolveLocale, setDefaultLocale } from "./core/locale.js";
|
|
1
2
|
import { UElement } from "./components/UElement.js";
|
|
2
3
|
import { UFormControlElement } from "./components/UFormControlElement.js";
|
|
3
4
|
import { IconCache, IconRegistry, getDefaultBaseUrl, setDefaultBaseUrl } from "./utilities/icons.js";
|
|
@@ -53,4 +54,4 @@ import { BrowserStorage } from "./utilities/BrowserStorage.js";
|
|
|
53
54
|
import { Dialog } from "./utilities/Dialog.js";
|
|
54
55
|
import { Theme } from "./utilities/Theme.js";
|
|
55
56
|
import { Toast } from "./utilities/Toast.js";
|
|
56
|
-
export { BrowserStorage, Dialog, IconCache, IconRegistry, OverlayManager, Theme, Toast, UAlert, UAvatar, UBadge, UBreadcrumb, UBreadcrumbItem, UButton, UButtonGroup, UCard, UCarousel, UCheckbox, UChip, UDataElement, UDialog, UDivider, UDrawer, UElement, UField, UFloatingElement, UForm, UFormControlElement, UIcon, UIconButton, UInput, UMenu, UMenuItem, UOption, UOverlayElement, UPanel, UPopover, UProgressBar, UProgressRing, URadio, URating, USelect, USkeleton, USlider, USpinner, USplitPanel, USwitch, UTab, UTabPanel, UTag, UTextarea, UTooltip, UTree, UTreeItem, arrayAttrConverter, booleanAttrConverter, buildElementHTML, dateAttrConverter, escapeHtmlAttr, escapeHtmlHref, escapeHtmlText, getDefaultBaseUrl, getParentElement, jsonAttrConverter, querySelectorAllWithin, querySelectorWithin, setDefaultBaseUrl, stripZeroWidth, urlAttrConverter };
|
|
57
|
+
export { BrowserStorage, Dialog, IconCache, IconRegistry, OverlayManager, Theme, Toast, UAlert, UAvatar, UBadge, UBreadcrumb, UBreadcrumbItem, UButton, UButtonGroup, UCard, UCarousel, UCheckbox, UChip, UDataElement, UDialog, UDivider, UDrawer, UElement, UField, UFloatingElement, UForm, UFormControlElement, UIcon, UIconButton, UInput, UMenu, UMenuItem, UOption, UOverlayElement, UPanel, UPopover, UProgressBar, UProgressRing, URadio, URating, USelect, USkeleton, USlider, USpinner, USplitPanel, USwitch, UTab, UTabPanel, UTag, UTextarea, UTooltip, UTree, UTreeItem, arrayAttrConverter, booleanAttrConverter, buildElementHTML, dateAttrConverter, escapeHtmlAttr, escapeHtmlHref, escapeHtmlText, formatTemplate, getDefaultBaseUrl, getDefaultLocale, getEffectiveLocale, getLocaleStrings, getParentElement, jsonAttrConverter, querySelectorAllWithin, querySelectorWithin, registerLocale, resolveLocale, setDefaultBaseUrl, setDefaultLocale, stripZeroWidth, urlAttrConverter };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/components",
|
|
3
3
|
"description": "web-components library based on lit-element made by iyulab",
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iyulab",
|
|
7
7
|
"components",
|
|
@@ -39,7 +39,9 @@
|
|
|
39
39
|
"./plugins/*": "./plugins/*"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
|
-
"
|
|
42
|
+
"dev": "vite --force",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"test:watch": "vitest",
|
|
43
45
|
"build:plugins": "tsc -p plugins/tsconfig.json",
|
|
44
46
|
"build": "eslint && vite build && npm run build:plugins"
|
|
45
47
|
},
|
|
@@ -72,6 +74,7 @@
|
|
|
72
74
|
"typescript-eslint": "^8.59.3",
|
|
73
75
|
"vite": "^8.0.13",
|
|
74
76
|
"vite-plugin-dts": "^5.0.0",
|
|
75
|
-
"vite-plugin-static-copy": "^4.1.0"
|
|
77
|
+
"vite-plugin-static-copy": "^4.1.0",
|
|
78
|
+
"vitest": "^4.1.8"
|
|
76
79
|
}
|
|
77
80
|
}
|