@iyulab/components 1.33.4 → 1.35.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/CHANGELOG.md +37 -0
- package/dist/assets/locales/ar.json.js +5 -1
- package/dist/assets/locales/de.json.js +5 -1
- package/dist/assets/locales/en.json.js +5 -1
- package/dist/assets/locales/es.json.js +4 -1
- package/dist/assets/locales/fr.json.js +5 -1
- package/dist/assets/locales/id.json.js +5 -1
- package/dist/assets/locales/ja.json.js +5 -1
- package/dist/assets/locales/ko.json.js +5 -1
- package/dist/assets/locales/pt-BR.json.js +5 -1
- package/dist/assets/locales/ru.json.js +5 -1
- package/dist/assets/locales/th.json.js +5 -1
- package/dist/assets/locales/vi.json.js +5 -1
- package/dist/assets/locales/zh-CN.json.js +5 -1
- package/dist/assets/locales/zh-TW.json.js +5 -1
- package/dist/components/date-picker/UDatePicker.d.ts +43 -6
- package/dist/components/date-picker/UDatePicker.js +100 -10
- package/dist/components/date-picker/UDatePicker.styles.js +29 -0
- package/dist/components/select/USelect.d.ts +3 -0
- package/dist/components/select/USelect.js +4 -0
- package/dist/react/USelect.d.ts +2 -1
- package/dist/react/USelect.js +1 -0
- package/dist/utilities/Locale.d.ts +1 -1
- package/package.json +1 -1
- package/skills/iyulab-components/references/components/date-picker.md +21 -5
- package/skills/iyulab-components/references/components/select.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.35.0] - 2026-08-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`USelect` fires a `search` event on every search-input change when
|
|
8
|
+
`searchable`.** The search text was already computed internally to drive
|
|
9
|
+
the built-in local option filtering, but never surfaced — a consumer
|
|
10
|
+
binding `USelect` to a large server-paginated dataset had no way to hook
|
|
11
|
+
into it and had to rebuild the search UI from scratch to do remote
|
|
12
|
+
search. `search` (`detail: { query: string }`, non-cancelable) fires
|
|
13
|
+
alongside the existing local filtering, so a consumer can subscribe and
|
|
14
|
+
drive remote search without losing the built-in search input. Mapped
|
|
15
|
+
through to the React wrapper as `onSearch`.
|
|
16
|
+
|
|
17
|
+
## [1.34.0] - 2026-08-28
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **`UDatePicker` gains a `mode="datetime"` option for combined date+time
|
|
22
|
+
selection.** Previously the component had no concept of time of day at
|
|
23
|
+
all, so a date+time field had no picker UI and consumers fell back to
|
|
24
|
+
free-text input with no format guarantee. `mode="datetime"` adds a native
|
|
25
|
+
time input to the calendar popover; the resulting `value` is always a
|
|
26
|
+
complete ISO-8601 `DateTimeOffset` string — seconds and the local UTC
|
|
27
|
+
offset are filled in automatically regardless of how coarse the time
|
|
28
|
+
input was. Picking a day preserves whatever time was already set; only
|
|
29
|
+
the "today" quick action overwrites both to right now. 12/24-hour display
|
|
30
|
+
is left to the browser's native time input rather than a custom widget.
|
|
31
|
+
Adds the `time` locale key (14 locales).
|
|
32
|
+
- **`UDatePicker`'s calendar popover gains visible "today"/"clear"
|
|
33
|
+
quick-action buttons.** The calendar already computed today's date (for
|
|
34
|
+
the today-cell highlight) and already exposed value clearing via the
|
|
35
|
+
trigger's clear icon — these buttons just surface both as visible,
|
|
36
|
+
keyboard-accessible controls in the popover footer. Adds the `today`
|
|
37
|
+
locale key (14 locales), reusing the existing `clear` key for the reset
|
|
38
|
+
button label.
|
|
39
|
+
|
|
3
40
|
## [1.33.4] - 2026-08-27
|
|
4
41
|
|
|
5
42
|
### Fixed
|
|
@@ -11,6 +11,8 @@ var tooLong = "يجب ألا تتجاوز {max}";
|
|
|
11
11
|
var increment = "زيادة القيمة";
|
|
12
12
|
var decrement = "إنقاص القيمة";
|
|
13
13
|
var clear = "مسح القيمة";
|
|
14
|
+
var today = "اليوم";
|
|
15
|
+
var time = "الوقت";
|
|
14
16
|
var showPassword = "إظهار كلمة المرور";
|
|
15
17
|
var hidePassword = "إخفاء كلمة المرور";
|
|
16
18
|
var previousSlide = "الشريحة السابقة";
|
|
@@ -29,6 +31,8 @@ var ar_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var ar_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, ar_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, ar_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Darf höchstens {max} betragen";
|
|
|
11
11
|
var increment = "Wert erhöhen";
|
|
12
12
|
var decrement = "Wert verringern";
|
|
13
13
|
var clear = "Wert löschen";
|
|
14
|
+
var today = "Heute";
|
|
15
|
+
var time = "Uhrzeit";
|
|
14
16
|
var showPassword = "Passwort anzeigen";
|
|
15
17
|
var hidePassword = "Passwort verbergen";
|
|
16
18
|
var previousSlide = "Vorherige Folie";
|
|
@@ -29,6 +31,8 @@ var de_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var de_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, de_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, de_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Must be at most {max}";
|
|
|
11
11
|
var increment = "Increase value";
|
|
12
12
|
var decrement = "Decrease value";
|
|
13
13
|
var clear = "Clear value";
|
|
14
|
+
var today = "Today";
|
|
15
|
+
var time = "Time";
|
|
14
16
|
var showPassword = "Show password";
|
|
15
17
|
var hidePassword = "Hide password";
|
|
16
18
|
var previousSlide = "Previous slide";
|
|
@@ -29,6 +31,8 @@ var en_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var en_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, en_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, en_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,7 @@ var tooLong = "Debe ser como máximo {max}";
|
|
|
11
11
|
var increment = "Aumentar valor";
|
|
12
12
|
var decrement = "Disminuir valor";
|
|
13
13
|
var clear = "Borrar valor";
|
|
14
|
+
var time = "Hora";
|
|
14
15
|
var showPassword = "Mostrar contraseña";
|
|
15
16
|
var hidePassword = "Ocultar contraseña";
|
|
16
17
|
var previousSlide = "Diapositiva anterior";
|
|
@@ -29,6 +30,8 @@ var es_default = {
|
|
|
29
30
|
increment,
|
|
30
31
|
decrement,
|
|
31
32
|
clear,
|
|
33
|
+
today: "Hoy",
|
|
34
|
+
time,
|
|
32
35
|
showPassword,
|
|
33
36
|
hidePassword,
|
|
34
37
|
previousSlide,
|
|
@@ -36,4 +39,4 @@ var es_default = {
|
|
|
36
39
|
goToSlide
|
|
37
40
|
};
|
|
38
41
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, es_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
42
|
+
export { badInput, clear, decrement, es_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Doit être au plus {max}";
|
|
|
11
11
|
var increment = "Augmenter la valeur";
|
|
12
12
|
var decrement = "Diminuer la valeur";
|
|
13
13
|
var clear = "Effacer la valeur";
|
|
14
|
+
var today = "Aujourd’hui";
|
|
15
|
+
var time = "Heure";
|
|
14
16
|
var showPassword = "Afficher le mot de passe";
|
|
15
17
|
var hidePassword = "Masquer le mot de passe";
|
|
16
18
|
var previousSlide = "Diapositive précédente";
|
|
@@ -29,6 +31,8 @@ var fr_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var fr_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, fr_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, fr_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Harus maksimal {max}";
|
|
|
11
11
|
var increment = "Tambah nilai";
|
|
12
12
|
var decrement = "Kurangi nilai";
|
|
13
13
|
var clear = "Hapus nilai";
|
|
14
|
+
var today = "Hari ini";
|
|
15
|
+
var time = "Waktu";
|
|
14
16
|
var showPassword = "Tampilkan kata sandi";
|
|
15
17
|
var hidePassword = "Sembunyikan kata sandi";
|
|
16
18
|
var previousSlide = "Slide sebelumnya";
|
|
@@ -29,6 +31,8 @@ var id_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var id_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, id_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, id_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "{max}以下である必要があります";
|
|
|
11
11
|
var increment = "値を増やす";
|
|
12
12
|
var decrement = "値を減らす";
|
|
13
13
|
var clear = "値をクリア";
|
|
14
|
+
var today = "今日";
|
|
15
|
+
var time = "時刻";
|
|
14
16
|
var showPassword = "パスワードを表示";
|
|
15
17
|
var hidePassword = "パスワードを隠す";
|
|
16
18
|
var previousSlide = "前のスライド";
|
|
@@ -29,6 +31,8 @@ var ja_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var ja_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, ja_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, ja_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "최대 {max} 이하여야 합니다";
|
|
|
11
11
|
var increment = "값 증가";
|
|
12
12
|
var decrement = "값 감소";
|
|
13
13
|
var clear = "값 지우기";
|
|
14
|
+
var today = "오늘";
|
|
15
|
+
var time = "시간";
|
|
14
16
|
var showPassword = "비밀번호 표시";
|
|
15
17
|
var hidePassword = "비밀번호 숨기기";
|
|
16
18
|
var previousSlide = "이전 슬라이드";
|
|
@@ -29,6 +31,8 @@ var ko_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var ko_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, ko_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, ko_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Deve ser no máximo {max}";
|
|
|
11
11
|
var increment = "Aumentar valor";
|
|
12
12
|
var decrement = "Diminuir valor";
|
|
13
13
|
var clear = "Limpar valor";
|
|
14
|
+
var today = "Hoje";
|
|
15
|
+
var time = "Hora";
|
|
14
16
|
var showPassword = "Mostrar senha";
|
|
15
17
|
var hidePassword = "Ocultar senha";
|
|
16
18
|
var previousSlide = "Slide anterior";
|
|
@@ -29,6 +31,8 @@ var pt_BR_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var pt_BR_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, pt_BR_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, pt_BR_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Должно быть не более {max}";
|
|
|
11
11
|
var increment = "Увеличить значение";
|
|
12
12
|
var decrement = "Уменьшить значение";
|
|
13
13
|
var clear = "Очистить значение";
|
|
14
|
+
var today = "Сегодня";
|
|
15
|
+
var time = "Время";
|
|
14
16
|
var showPassword = "Показать пароль";
|
|
15
17
|
var hidePassword = "Скрыть пароль";
|
|
16
18
|
var previousSlide = "Предыдущий слайд";
|
|
@@ -29,6 +31,8 @@ var ru_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var ru_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, ru_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, ru_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "ต้องไม่เกิน {max}";
|
|
|
11
11
|
var increment = "เพิ่มค่า";
|
|
12
12
|
var decrement = "ลดค่า";
|
|
13
13
|
var clear = "ล้างค่า";
|
|
14
|
+
var today = "วันนี้";
|
|
15
|
+
var time = "เวลา";
|
|
14
16
|
var showPassword = "แสดงรหัสผ่าน";
|
|
15
17
|
var hidePassword = "ซ่อนรหัสผ่าน";
|
|
16
18
|
var previousSlide = "สไลด์ก่อนหน้า";
|
|
@@ -29,6 +31,8 @@ var th_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var th_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, th_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, th_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "Phải nhỏ hơn hoặc bằng {max}";
|
|
|
11
11
|
var increment = "Tăng giá trị";
|
|
12
12
|
var decrement = "Giảm giá trị";
|
|
13
13
|
var clear = "Xóa giá trị";
|
|
14
|
+
var today = "Hôm nay";
|
|
15
|
+
var time = "Giờ";
|
|
14
16
|
var showPassword = "Hiện mật khẩu";
|
|
15
17
|
var hidePassword = "Ẩn mật khẩu";
|
|
16
18
|
var previousSlide = "Slide trước";
|
|
@@ -29,6 +31,8 @@ var vi_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var vi_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, vi_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, vi_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "最多不能超过{max}";
|
|
|
11
11
|
var increment = "增加值";
|
|
12
12
|
var decrement = "减少值";
|
|
13
13
|
var clear = "清除值";
|
|
14
|
+
var today = "今天";
|
|
15
|
+
var time = "时间";
|
|
14
16
|
var showPassword = "显示密码";
|
|
15
17
|
var hidePassword = "隐藏密码";
|
|
16
18
|
var previousSlide = "上一张幻灯片";
|
|
@@ -29,6 +31,8 @@ var zh_CN_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var zh_CN_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, zh_CN_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, zh_CN_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -11,6 +11,8 @@ var tooLong = "最多不能超過{max}";
|
|
|
11
11
|
var increment = "增加值";
|
|
12
12
|
var decrement = "減少值";
|
|
13
13
|
var clear = "清除值";
|
|
14
|
+
var today = "今天";
|
|
15
|
+
var time = "時間";
|
|
14
16
|
var showPassword = "顯示密碼";
|
|
15
17
|
var hidePassword = "隱藏密碼";
|
|
16
18
|
var previousSlide = "上一張投影片";
|
|
@@ -29,6 +31,8 @@ var zh_TW_default = {
|
|
|
29
31
|
increment,
|
|
30
32
|
decrement,
|
|
31
33
|
clear,
|
|
34
|
+
today,
|
|
35
|
+
time,
|
|
32
36
|
showPassword,
|
|
33
37
|
hidePassword,
|
|
34
38
|
previousSlide,
|
|
@@ -36,4 +40,4 @@ var zh_TW_default = {
|
|
|
36
40
|
goToSlide
|
|
37
41
|
};
|
|
38
42
|
//#endregion
|
|
39
|
-
export { badInput, clear, decrement, zh_TW_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, tooLong, tooShort, typeMismatch, valueMissing };
|
|
43
|
+
export { badInput, clear, decrement, zh_TW_default as default, goToSlide, hidePassword, increment, nextSlide, patternMismatch, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { PropertyValues } from 'lit';
|
|
2
2
|
import { UFormControlElement } from '../UFormControlElement.js';
|
|
3
3
|
import { UPopover } from '../popover/UPopover.js';
|
|
4
|
+
export type DatePickerMode = 'date' | 'datetime';
|
|
4
5
|
/**
|
|
5
|
-
* A single-date-selection form control.
|
|
6
|
-
* native `input[type=date]`: an ISO `YYYY-MM-DD` string.
|
|
6
|
+
* A single-date(-time)-selection form control. In `mode="date"` (default) the value follows
|
|
7
|
+
* the same convention as the native `input[type=date]`: an ISO `YYYY-MM-DD` string. In
|
|
8
|
+
* `mode="datetime"` the value is a complete ISO-8601 `DateTimeOffset` string
|
|
9
|
+
* (`YYYY-MM-DDTHH:mm:ss±HH:mm`) — the component always fills in seconds and the browser's
|
|
10
|
+
* local UTC offset, so the value is unconditionally valid regardless of how coarse the time
|
|
11
|
+
* input was.
|
|
7
12
|
*
|
|
8
13
|
* The calendar week always starts on Sunday, regardless of locale — harmless for the
|
|
9
14
|
* locales this library currently ships (en/ko), but not correct for locales where Monday
|
|
@@ -20,17 +25,25 @@ import { UPopover } from '../popover/UPopover.js';
|
|
|
20
25
|
* @csspart calendar-weekdays - the weekday header row
|
|
21
26
|
* @csspart calendar-grid - the date grid
|
|
22
27
|
* @csspart day - a date cell button
|
|
28
|
+
* @csspart calendar-footer - the row holding the "today"/"clear" quick-action buttons
|
|
29
|
+
* @csspart calendar-time - the row holding the time-of-day input (datetime mode only)
|
|
23
30
|
*
|
|
24
31
|
* @cssprop --date-picker-popover-width - width of the calendar popover (default: 296px, independent of trigger width — a fixed-width calendar reads more naturally)
|
|
25
32
|
*
|
|
26
|
-
* @event change - fires when the user clicks a date cell, confirms via keyboard,
|
|
27
|
-
*
|
|
33
|
+
* @event change - fires when the user clicks a date cell, confirms via keyboard, changes the
|
|
34
|
+
* time input (datetime mode, once a date is set), or clicks the clear button. Programmatic
|
|
35
|
+
* value assignment does not fire it (same contract as native form controls).
|
|
28
36
|
*/
|
|
29
37
|
export declare class UDatePicker extends UFormControlElement<string> {
|
|
30
38
|
static styles: import('lit').CSSResultGroup[];
|
|
31
|
-
/**
|
|
39
|
+
/** `date` (default) selects a calendar day only. `datetime` also captures a time-of-day and
|
|
40
|
+
* the value becomes a complete ISO-8601 `DateTimeOffset` string. */
|
|
41
|
+
mode: DatePickerMode;
|
|
42
|
+
/** Minimum value (ISO YYYY-MM-DD) — dates before this cannot be selected. Date-only even in
|
|
43
|
+
* `mode="datetime"`; time-of-day is never range-checked. */
|
|
32
44
|
min?: string;
|
|
33
|
-
/** Maximum value (ISO YYYY-MM-DD) — dates after this cannot be selected.
|
|
45
|
+
/** Maximum value (ISO YYYY-MM-DD) — dates after this cannot be selected. Date-only even in
|
|
46
|
+
* `mode="datetime"`; time-of-day is never range-checked. */
|
|
34
47
|
max?: string;
|
|
35
48
|
/** Whether to show the clear button */
|
|
36
49
|
clearable: boolean;
|
|
@@ -43,14 +56,28 @@ export declare class UDatePicker extends UFormControlElement<string> {
|
|
|
43
56
|
private open;
|
|
44
57
|
private viewDate;
|
|
45
58
|
private focusedDate;
|
|
59
|
+
/** Time-of-day for the next selection while no `value` exists yet (`mode="datetime"` only) —
|
|
60
|
+
* once `value` is set, the time input reads/writes its time portion directly instead. */
|
|
61
|
+
private pendingTime;
|
|
46
62
|
private grabFocusOnUpdate;
|
|
47
63
|
protected updated(changed: PropertyValues): void;
|
|
48
64
|
render(): import('lit-html').TemplateResult<1>;
|
|
49
65
|
private renderCalendar;
|
|
66
|
+
private renderTimeRow;
|
|
67
|
+
private renderFooter;
|
|
50
68
|
private renderDay;
|
|
51
69
|
private isOutOfRange;
|
|
52
70
|
private focusDayButton;
|
|
71
|
+
/** `timeOverride` lets a caller force the time-of-day (the "today" quick action wants
|
|
72
|
+
* "right now", overriding whatever time was previously set) — a plain day-cell click omits
|
|
73
|
+
* it, which preserves the existing time-of-day (or `pendingTime`) so switching the date
|
|
74
|
+
* alone doesn't clobber a time the user already picked. */
|
|
53
75
|
private selectDay;
|
|
76
|
+
/** Time input change — only commits into `value` once a date already exists (matches native
|
|
77
|
+
* `datetime-local`: a time alone isn't a complete value). Before that, it just remembers
|
|
78
|
+
* `pendingTime` for whenever a day gets picked. Doesn't close the popover or refocus the
|
|
79
|
+
* trigger — unlike selecting a day, adjusting the time doesn't conclude the interaction. */
|
|
80
|
+
private handleTimeChange;
|
|
54
81
|
private handlePrevMonth;
|
|
55
82
|
private handleNextMonth;
|
|
56
83
|
private navigateMonth;
|
|
@@ -59,6 +86,16 @@ export declare class UDatePicker extends UFormControlElement<string> {
|
|
|
59
86
|
private handlePopoverShow;
|
|
60
87
|
private handlePopoverHide;
|
|
61
88
|
private handleClearClick;
|
|
89
|
+
/** "오늘" 퀵액션 — `today` 셀이 이미 렌더에서 계산해 표시 중인 값(`renderDay`의
|
|
90
|
+
* `isSameDay(date, new Date())`)을 실제로 선택하는 것뿐이라 `selectDay`를 그대로 탄다
|
|
91
|
+
* (범위 밖이면 `selectDay`가 조용히 no-op — 클릭 불가 상태인 day 셀과 동일 규약).
|
|
92
|
+
* datetime 모드에서는 "지금"을 통째로 채우는 것이 요청의 본질(§D-28 항목 2 docket 코멘트)
|
|
93
|
+
* 이라 시간까지 `now`로 덮어쓴다 — 평범한 day 셀 클릭과 달리 기존 시각을 보존하지 않는다. */
|
|
94
|
+
private handleTodayClick;
|
|
95
|
+
/** 캘린더 팝오버 안 "초기화" 퀵액션 — 트리거의 clear 아이콘(`handleClearClick`)과 값을
|
|
96
|
+
* 비우는 로직은 같지만, 팝오버가 열린 채로 눌렸으므로 선택 완료와 동일하게 닫아 준다. */
|
|
97
|
+
private handleFooterResetClick;
|
|
98
|
+
private resetValue;
|
|
62
99
|
/** suffix `u-icon`은 순수 표시 요소(버튼 아님)라 네이티브 키보드 활성화가 없다 —
|
|
63
100
|
* `role="button"`+`tabindex="0"`로 포커스 가능하게 한 뒤, Enter/Space를 같은 클릭
|
|
64
101
|
* 핸들러로 릴레이한다(`UInput`/`USelect`의 동일 패턴과 일치). */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/decorateMetadata.js";
|
|
2
2
|
import __decorate from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/decorate.js";
|
|
3
3
|
import { UFormControlElement } from "../UFormControlElement.js";
|
|
4
|
+
import "../button/UButton.js";
|
|
4
5
|
import "../icon/UIcon.js";
|
|
5
6
|
import "../icon-button/UIconButton.js";
|
|
6
7
|
import { Locale } from "../../utilities/Locale.js";
|
|
@@ -34,6 +35,31 @@ function addDays(date, delta) {
|
|
|
34
35
|
function daysInMonth(date) {
|
|
35
36
|
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
36
37
|
}
|
|
38
|
+
/** `±HH:mm` for the browser's local timezone at `date` (DST-aware — recomputed per date,
|
|
39
|
+
* not cached — `getTimezoneOffset()`'s sign is the inverse of the ISO-8601 offset sign). */
|
|
40
|
+
function getLocalOffset(date) {
|
|
41
|
+
const minutes = -date.getTimezoneOffset();
|
|
42
|
+
const sign = minutes >= 0 ? "+" : "-";
|
|
43
|
+
const abs = Math.abs(minutes);
|
|
44
|
+
return `${sign}${String(Math.floor(abs / 60)).padStart(2, "0")}:${String(abs % 60).padStart(2, "0")}`;
|
|
45
|
+
}
|
|
46
|
+
/** Builds the `value` for the given mode — `datetime` always emits seconds + local offset so
|
|
47
|
+
* the result is unconditionally a valid, unambiguous ISO-8601 `DateTimeOffset` regardless of
|
|
48
|
+
* how coarse the UI input was (this is the guarantee the datetime mode request asked for). */
|
|
49
|
+
function buildValue(date, mode, time) {
|
|
50
|
+
return mode === "datetime" ? `${toISODate(date)}T${time}:00${getLocalOffset(date)}` : toISODate(date);
|
|
51
|
+
}
|
|
52
|
+
/** Splits a `value` into its date portion (as a `Date`, via the local `parseISODate` above —
|
|
53
|
+
* date-only, no timezone conversion) and its `HH:mm` time-of-day (`'00:00'` if absent —
|
|
54
|
+
* covers both plain date-mode values and a datetime value with no time captured yet). */
|
|
55
|
+
function splitValue(value) {
|
|
56
|
+
const [datePart, rest] = value.split("T");
|
|
57
|
+
const match = rest?.match(/^(\d{2}:\d{2})/);
|
|
58
|
+
return {
|
|
59
|
+
date: parseISODate(datePart),
|
|
60
|
+
time: match ? match[1] : "00:00"
|
|
61
|
+
};
|
|
62
|
+
}
|
|
37
63
|
/** Cells to render for the calendar grid — leading `null`s pad the previous month's weekday offset. */
|
|
38
64
|
function buildMonthGrid(viewDate) {
|
|
39
65
|
const startOffset = startOfMonth(viewDate).getDay();
|
|
@@ -58,12 +84,23 @@ function getWeekdayLabels(locale) {
|
|
|
58
84
|
var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
59
85
|
constructor(..._args) {
|
|
60
86
|
super(..._args);
|
|
87
|
+
this.mode = "date";
|
|
61
88
|
this.clearable = false;
|
|
62
89
|
this.calendarId = `u-date-picker-calendar-${Math.random().toString(36).slice(2, 8)}`;
|
|
63
90
|
this.open = false;
|
|
64
91
|
this.viewDate = startOfMonth(/* @__PURE__ */ new Date());
|
|
65
92
|
this.focusedDate = /* @__PURE__ */ new Date();
|
|
93
|
+
this.pendingTime = "00:00";
|
|
66
94
|
this.grabFocusOnUpdate = false;
|
|
95
|
+
this.handleTimeChange = (e) => {
|
|
96
|
+
const time = e.target.value || "00:00";
|
|
97
|
+
this.pendingTime = time;
|
|
98
|
+
if (!this.value) return;
|
|
99
|
+
const iso = buildValue(splitValue(this.value).date, this.mode, time);
|
|
100
|
+
const changed = iso !== this.value;
|
|
101
|
+
this.value = iso;
|
|
102
|
+
if (changed) this.emitChange();
|
|
103
|
+
};
|
|
67
104
|
this.handlePrevMonth = () => this.navigateMonth(-1);
|
|
68
105
|
this.handleNextMonth = () => this.navigateMonth(1);
|
|
69
106
|
this.handleDayKeydown = (e, date) => {
|
|
@@ -106,7 +143,7 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
106
143
|
this.handlePopoverShow = () => {
|
|
107
144
|
this.open = true;
|
|
108
145
|
this.grabFocusOnUpdate = true;
|
|
109
|
-
const base = this.value ?
|
|
146
|
+
const base = this.value ? splitValue(this.value).date : /* @__PURE__ */ new Date();
|
|
110
147
|
this.viewDate = startOfMonth(base);
|
|
111
148
|
this.focusedDate = base;
|
|
112
149
|
};
|
|
@@ -116,9 +153,17 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
116
153
|
this.handleClearClick = (e) => {
|
|
117
154
|
e.preventDefault();
|
|
118
155
|
e.stopPropagation();
|
|
119
|
-
|
|
120
|
-
this.
|
|
121
|
-
|
|
156
|
+
this.resetValue();
|
|
157
|
+
this.containerEl?.focus();
|
|
158
|
+
};
|
|
159
|
+
this.handleTodayClick = () => {
|
|
160
|
+
const now = /* @__PURE__ */ new Date();
|
|
161
|
+
const time = this.mode === "datetime" ? `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}` : void 0;
|
|
162
|
+
this.selectDay(now, time);
|
|
163
|
+
};
|
|
164
|
+
this.handleFooterResetClick = () => {
|
|
165
|
+
this.resetValue();
|
|
166
|
+
this.popoverEl?.hide();
|
|
122
167
|
this.containerEl?.focus();
|
|
123
168
|
};
|
|
124
169
|
this.handleClearKeydown = (e) => {
|
|
@@ -139,7 +184,10 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
139
184
|
}
|
|
140
185
|
}
|
|
141
186
|
render() {
|
|
142
|
-
const displayText = this.value ? formatDate(this.value
|
|
187
|
+
const displayText = this.value ? formatDate(this.value, this.mode === "datetime" ? {
|
|
188
|
+
dateStyle: "medium",
|
|
189
|
+
timeStyle: "short"
|
|
190
|
+
} : void 0) : "";
|
|
143
191
|
return html`
|
|
144
192
|
<u-field part="field"
|
|
145
193
|
?required=${this.required}
|
|
@@ -216,11 +264,37 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
216
264
|
</div>
|
|
217
265
|
`)}
|
|
218
266
|
</div>
|
|
267
|
+
${this.renderTimeRow()}
|
|
268
|
+
${this.renderFooter()}
|
|
269
|
+
</div>
|
|
270
|
+
`;
|
|
271
|
+
}
|
|
272
|
+
renderTimeRow() {
|
|
273
|
+
if (this.mode !== "datetime") return "";
|
|
274
|
+
const time = this.value ? splitValue(this.value).time : this.pendingTime;
|
|
275
|
+
return html`
|
|
276
|
+
<div class="calendar-time" part="calendar-time">
|
|
277
|
+
<input type="time" class="time-input" part="time-input"
|
|
278
|
+
aria-label=${Locale.getValue("time")}
|
|
279
|
+
.value=${time}
|
|
280
|
+
@change=${this.handleTimeChange}
|
|
281
|
+
/>
|
|
282
|
+
</div>
|
|
283
|
+
`;
|
|
284
|
+
}
|
|
285
|
+
renderFooter() {
|
|
286
|
+
const todayDisabled = this.isOutOfRange(/* @__PURE__ */ new Date());
|
|
287
|
+
return html`
|
|
288
|
+
<div class="calendar-footer" part="calendar-footer">
|
|
289
|
+
<u-button variant="ghost" size="sm" ?disabled=${todayDisabled} @click=${this.handleTodayClick}>${Locale.getValue("today")}</u-button>
|
|
290
|
+
${this.clearable && this.value ? html`
|
|
291
|
+
<u-button variant="ghost" size="sm" @click=${this.handleFooterResetClick}>${Locale.getValue("clear")}</u-button>
|
|
292
|
+
` : ""}
|
|
219
293
|
</div>
|
|
220
294
|
`;
|
|
221
295
|
}
|
|
222
296
|
renderDay(date) {
|
|
223
|
-
const selected = this.value ? isSameDay(date,
|
|
297
|
+
const selected = this.value ? isSameDay(date, splitValue(this.value).date) : false;
|
|
224
298
|
const focused = isSameDay(date, this.focusedDate);
|
|
225
299
|
const today = isSameDay(date, /* @__PURE__ */ new Date());
|
|
226
300
|
const outOfRange = this.isOutOfRange(date);
|
|
@@ -249,11 +323,17 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
249
323
|
const iso = toISODate(date);
|
|
250
324
|
this.renderRoot.querySelector(`button.day[data-iso="${iso}"]`)?.focus();
|
|
251
325
|
}
|
|
252
|
-
|
|
326
|
+
/** `timeOverride` lets a caller force the time-of-day (the "today" quick action wants
|
|
327
|
+
* "right now", overriding whatever time was previously set) — a plain day-cell click omits
|
|
328
|
+
* it, which preserves the existing time-of-day (or `pendingTime`) so switching the date
|
|
329
|
+
* alone doesn't clobber a time the user already picked. */
|
|
330
|
+
selectDay(date, timeOverride) {
|
|
253
331
|
if (this.isOutOfRange(date)) return;
|
|
254
|
-
const
|
|
332
|
+
const time = timeOverride ?? (this.value ? splitValue(this.value).time : this.pendingTime);
|
|
333
|
+
const iso = buildValue(date, this.mode, time);
|
|
255
334
|
const changed = iso !== this.value;
|
|
256
335
|
this.value = iso;
|
|
336
|
+
if (this.mode === "datetime") this.pendingTime = time;
|
|
257
337
|
if (changed) this.emitChange();
|
|
258
338
|
this.popoverEl?.hide();
|
|
259
339
|
this.containerEl?.focus();
|
|
@@ -271,6 +351,11 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
271
351
|
if (next.getMonth() !== this.viewDate.getMonth() || next.getFullYear() !== this.viewDate.getFullYear()) this.viewDate = startOfMonth(next);
|
|
272
352
|
this.focusedDate = next;
|
|
273
353
|
}
|
|
354
|
+
resetValue() {
|
|
355
|
+
const hadValue = !!this.value;
|
|
356
|
+
this.value = void 0;
|
|
357
|
+
if (hadValue) this.emitChange();
|
|
358
|
+
}
|
|
274
359
|
emitChange() {
|
|
275
360
|
if (!this.novalidate) this.validate();
|
|
276
361
|
this.dispatchEvent(new Event("change", {
|
|
@@ -284,10 +369,10 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
284
369
|
if (this.required && !this.value) {
|
|
285
370
|
flags = { valueMissing: true };
|
|
286
371
|
message = Locale.getValue("valueMissing");
|
|
287
|
-
} else if (this.value && this.min &&
|
|
372
|
+
} else if (this.value && this.min && splitValue(this.value).date.getTime() < parseISODate(this.min).getTime()) {
|
|
288
373
|
flags = { rangeUnderflow: true };
|
|
289
374
|
message = Locale.getValue("rangeUnderflow", { min: this.min });
|
|
290
|
-
} else if (this.value && this.max &&
|
|
375
|
+
} else if (this.value && this.max && splitValue(this.value).date.getTime() > parseISODate(this.max).getTime()) {
|
|
291
376
|
flags = { rangeOverflow: true };
|
|
292
377
|
message = Locale.getValue("rangeOverflow", { max: this.max });
|
|
293
378
|
}
|
|
@@ -308,6 +393,10 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
|
|
|
308
393
|
this.containerEl?.blur();
|
|
309
394
|
}
|
|
310
395
|
};
|
|
396
|
+
__decorate([property({
|
|
397
|
+
type: String,
|
|
398
|
+
reflect: true
|
|
399
|
+
}), __decorateMetadata("design:type", Object)], UDatePicker.prototype, "mode", void 0);
|
|
311
400
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UDatePicker.prototype, "min", void 0);
|
|
312
401
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UDatePicker.prototype, "max", void 0);
|
|
313
402
|
__decorate([property({
|
|
@@ -320,6 +409,7 @@ __decorate([query("u-popover", true), __decorateMetadata("design:type", typeof U
|
|
|
320
409
|
__decorate([state(), __decorateMetadata("design:type", Boolean)], UDatePicker.prototype, "open", void 0);
|
|
321
410
|
__decorate([state(), __decorateMetadata("design:type", typeof Date === "undefined" ? Object : Date)], UDatePicker.prototype, "viewDate", void 0);
|
|
322
411
|
__decorate([state(), __decorateMetadata("design:type", typeof Date === "undefined" ? Object : Date)], UDatePicker.prototype, "focusedDate", void 0);
|
|
412
|
+
__decorate([state(), __decorateMetadata("design:type", String)], UDatePicker.prototype, "pendingTime", void 0);
|
|
323
413
|
UDatePicker = __decorate([customElement("u-date-picker")], UDatePicker);
|
|
324
414
|
//#endregion
|
|
325
415
|
export { UDatePicker };
|
|
@@ -142,6 +142,35 @@ var styles = css`
|
|
|
142
142
|
color: var(--u-txt-color-disabled, #BDBDBD);
|
|
143
143
|
cursor: not-allowed;
|
|
144
144
|
}
|
|
145
|
+
|
|
146
|
+
.calendar-time {
|
|
147
|
+
display: flex;
|
|
148
|
+
justify-content: flex-end;
|
|
149
|
+
padding: 4px 4px 0;
|
|
150
|
+
}
|
|
151
|
+
.time-input {
|
|
152
|
+
font-family: inherit;
|
|
153
|
+
font-size: 0.9em;
|
|
154
|
+
padding: 2px 6px;
|
|
155
|
+
border: 1px solid var(--u-input-border-color, #E0E0E0);
|
|
156
|
+
border-radius: 0.25em;
|
|
157
|
+
background-color: var(--u-input-bg-color, #FFFFFF);
|
|
158
|
+
color: var(--u-txt-color, #212121);
|
|
159
|
+
}
|
|
160
|
+
.time-input:focus-visible {
|
|
161
|
+
outline: none;
|
|
162
|
+
box-shadow: 0 0 0 1px var(--u-input-border-color-focus, #1565C0);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.calendar-footer {
|
|
166
|
+
display: flex;
|
|
167
|
+
justify-content: space-between;
|
|
168
|
+
align-items: center;
|
|
169
|
+
gap: 8px;
|
|
170
|
+
padding-top: 8px;
|
|
171
|
+
margin-top: 4px;
|
|
172
|
+
border-top: 1px solid var(--u-border-color-weak, #EEEEEE);
|
|
173
|
+
}
|
|
145
174
|
`;
|
|
146
175
|
//#endregion
|
|
147
176
|
export { styles };
|
|
@@ -24,6 +24,9 @@ export type SelectVariant = 'outlined' | 'filled' | 'underlined' | 'borderless';
|
|
|
24
24
|
*
|
|
25
25
|
* @event change - 사용자 상호작용(옵션 클릭·칩 제거·지우기)으로 선택 값이 변경될 때 발생.
|
|
26
26
|
* 네이티브 select와 동일하게 프로그램적 value 세팅·옵션 등록으로는 발화하지 않는다.
|
|
27
|
+
* @event search - `searchable`일 때 검색 입력이 바뀔 때마다 발생(`detail: { query: string }`).
|
|
28
|
+
* 로컬 필터링(이미 렌더된 `u-option`의 `hidden` 토글)과 별개로 발행되므로, 서버/원격 검색이
|
|
29
|
+
* 필요한 소비자는 이 이벤트를 구독해 자체적으로 옵션을 갱신할 수 있다.
|
|
27
30
|
*/
|
|
28
31
|
export declare class USelect extends UFormControlElement<string | string[]> {
|
|
29
32
|
static styles: import('lit').CSSResultGroup[];
|
|
@@ -86,6 +86,10 @@ var USelect = class USelect extends UFormControlElement {
|
|
|
86
86
|
const value = option.value.toLowerCase();
|
|
87
87
|
option.hidden = !label.includes(query) && !value.includes(query);
|
|
88
88
|
}
|
|
89
|
+
this.fire("search", {
|
|
90
|
+
detail: { query },
|
|
91
|
+
cancelable: false
|
|
92
|
+
});
|
|
89
93
|
};
|
|
90
94
|
this.handleSearchKeydown = (e) => {
|
|
91
95
|
const options = this.options.filter((o) => !o.hidden && !o.disabled);
|
package/dist/react/USelect.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ import { USelect as USelectElement } from '../components/select/USelect';
|
|
|
3
3
|
|
|
4
4
|
export declare const USelect: React.ForwardRefExoticComponent<
|
|
5
5
|
Omit<Partial<USelectElement>, keyof React.HTMLAttributes<USelectElement>>
|
|
6
|
-
& Omit<React.HTMLAttributes<USelectElement>, 'onChange'>
|
|
6
|
+
& Omit<React.HTMLAttributes<USelectElement>, 'onChange' | 'onSearch'>
|
|
7
7
|
& React.RefAttributes<USelectElement>
|
|
8
8
|
& {
|
|
9
9
|
onChange?: (event: CustomEvent) => void;
|
|
10
|
+
onSearch?: (event: CustomEvent<{ query: string }>) => void;
|
|
10
11
|
}
|
|
11
12
|
>;
|
|
12
13
|
|
package/dist/react/USelect.js
CHANGED
|
@@ -12,7 +12,7 @@ export type SupportedLocale = 'en' | 'ko' | 'ja' | 'zh-CN' | 'zh-TW' | 'es' | 'f
|
|
|
12
12
|
/** 내장 로케일은 자동완성되지만, 임의의 BCP47 태그도 그대로 받는다. */
|
|
13
13
|
export type LocaleTag = SupportedLocale | (string & {});
|
|
14
14
|
/** 라이브러리가 제공하는 chrome 문자열 키. 지금은 검증 메시지뿐이지만 이후 다른 UI 문구도 추가될 수 있다. */
|
|
15
|
-
export type LocaleMessageKey = 'valueMissing' | 'badInput' | 'typeMismatch' | 'patternMismatch' | 'rangeUnderflow' | 'rangeOverflow' | 'stepMismatch' | 'tooShort' | 'tooLong' | 'increment' | 'decrement' | 'clear' | 'showPassword' | 'hidePassword' | 'previousSlide' | 'nextSlide' | 'goToSlide';
|
|
15
|
+
export type LocaleMessageKey = 'valueMissing' | 'badInput' | 'typeMismatch' | 'patternMismatch' | 'rangeUnderflow' | 'rangeOverflow' | 'stepMismatch' | 'tooShort' | 'tooLong' | 'increment' | 'decrement' | 'clear' | 'today' | 'time' | 'showPassword' | 'hidePassword' | 'previousSlide' | 'nextSlide' | 'goToSlide';
|
|
16
16
|
type LocaleTable = Record<LocaleMessageKey, string>;
|
|
17
17
|
/**
|
|
18
18
|
* 한 패키지(또는 앱 영역)의 문자열 묶음.
|
package/package.json
CHANGED
|
@@ -6,15 +6,28 @@ import '@iyulab/components/dist/components/date-picker/UDatePicker.js';
|
|
|
6
6
|
|
|
7
7
|
**Tag:** `u-date-picker`
|
|
8
8
|
|
|
9
|
-
Single-date selection with a popover calendar.
|
|
9
|
+
Single-date(-time) selection with a popover calendar. `mode="date"` (default) follows the same
|
|
10
|
+
convention as the native `input[type=date]`: an ISO `YYYY-MM-DD` string. `mode="datetime"` adds
|
|
11
|
+
a time-of-day input and the value becomes a complete ISO-8601 `DateTimeOffset` string
|
|
12
|
+
(`YYYY-MM-DDTHH:mm:ss±HH:mm`, seconds and the browser's local UTC offset always filled in — the
|
|
13
|
+
value is unconditionally valid regardless of how coarse the time input was). Form-associated.
|
|
10
14
|
|
|
11
15
|
> The calendar week always starts on Sunday, regardless of locale.
|
|
12
16
|
|
|
17
|
+
The calendar popover has a footer with a "Today" quick-action button (selects today's date —
|
|
18
|
+
in `mode="datetime"` this also sets the time to right now — disabled when today falls outside
|
|
19
|
+
`min`/`max`) and, when `clearable` and a value is set, a "Clear" button next to it. Picking a
|
|
20
|
+
day preserves whatever time-of-day was already set; only the "Today" button overrides the time.
|
|
21
|
+
`min`/`max` are always date-only, even in `mode="datetime"` — time-of-day is never range-checked.
|
|
22
|
+
|
|
13
23
|
```html
|
|
14
24
|
<u-date-picker name="start-date" label="Start date"></u-date-picker>
|
|
15
25
|
|
|
16
26
|
<!-- Clearable with a bounded range -->
|
|
17
27
|
<u-date-picker name="due-date" label="Due date" clearable min="2026-01-01" max="2026-12-31"></u-date-picker>
|
|
28
|
+
|
|
29
|
+
<!-- Date + time, value is a full ISO-8601 DateTimeOffset string -->
|
|
30
|
+
<u-date-picker name="sent-at" label="Sent at" mode="datetime"></u-date-picker>
|
|
18
31
|
```
|
|
19
32
|
|
|
20
33
|
---
|
|
@@ -23,9 +36,10 @@ Single-date selection with a popover calendar. The value follows the same conven
|
|
|
23
36
|
|
|
24
37
|
| Property | Type | Default | Reflect | Description |
|
|
25
38
|
|----------|------|---------|---------|-------------|
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
39
|
+
| `mode` | `'date' \| 'datetime'` | `'date'` | ✓ | `datetime` adds a time input; value becomes a full ISO-8601 `DateTimeOffset` string |
|
|
40
|
+
| `value` | `string` | — | — | Selected date (ISO `YYYY-MM-DD`), or full ISO-8601 datetime in `mode="datetime"` |
|
|
41
|
+
| `min` | `string` | — | — | Minimum selectable date (ISO `YYYY-MM-DD`, date-only in both modes) |
|
|
42
|
+
| `max` | `string` | — | — | Maximum selectable date (ISO `YYYY-MM-DD`, date-only in both modes) |
|
|
29
43
|
| `clearable` | `boolean` | `false` | ✓ | Show clear button |
|
|
30
44
|
| `placeholder` | `string` | — | — | Placeholder text |
|
|
31
45
|
| `disabled` | `boolean` | `false` | ✓ | Disable |
|
|
@@ -41,7 +55,7 @@ Single-date selection with a popover calendar. The value follows the same conven
|
|
|
41
55
|
|
|
42
56
|
| Event | Description |
|
|
43
57
|
|-------|-------------|
|
|
44
|
-
| `change` | Fires when the user clicks a date cell, confirms via keyboard, or clicks the clear button. Programmatic value assignment does not fire it. |
|
|
58
|
+
| `change` | Fires when the user clicks a date cell, confirms via keyboard, changes the time input (`mode="datetime"`, once a date is set), or clicks the clear button. Programmatic value assignment does not fire it. |
|
|
45
59
|
|
|
46
60
|
## Methods
|
|
47
61
|
|
|
@@ -65,6 +79,8 @@ Single-date selection with a popover calendar. The value follows the same conven
|
|
|
65
79
|
| `calendar-weekdays` | The weekday header row |
|
|
66
80
|
| `calendar-grid` | The date grid |
|
|
67
81
|
| `day` | A date cell button |
|
|
82
|
+
| `calendar-footer` | The row holding the "Today"/"Clear" quick-action buttons |
|
|
83
|
+
| `calendar-time` | The row holding the time-of-day input (`mode="datetime"` only) |
|
|
68
84
|
|
|
69
85
|
## CSS Custom Properties
|
|
70
86
|
|
|
@@ -59,6 +59,7 @@ Dropdown select with single or multiple selection, search, and clear support. Fo
|
|
|
59
59
|
| Event | Description |
|
|
60
60
|
|-------|-------------|
|
|
61
61
|
| `change` | Fires when selection changes |
|
|
62
|
+
| `search` | Fires on every search input change when `searchable` (`detail: { query: string }`). Fires alongside the built-in local filtering — subscribe to it to drive remote/server-side search instead of (or in addition to) the local filter |
|
|
62
63
|
|
|
63
64
|
## Methods
|
|
64
65
|
|