@iyulab/components 1.35.6 → 1.36.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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.36.0] - 2026-09-04
4
+
5
+ ### Added
6
+
7
+ - **`UFileInput` (`u-file-input`), a form control wrapping a native
8
+ `<input type="file">`.** Trigger button, selected-file(s) status text,
9
+ and a clear button, styled to match the rest of the form control
10
+ family. `value` is `File[] | null`; native `<form>`/`u-form`
11
+ submission works out of the box via `ElementInternals` (single file)
12
+ or a `FormData` with the file repeatedly appended under the same key
13
+ (multiple files, matching native multi-file submission semantics).
14
+ `accept`/`multiple` pass through to the underlying input.
15
+ Drag-and-drop is out of scope for this release.
16
+
17
+ ## [1.35.7] - 2026-09-03
18
+
19
+ ### Fixed
20
+
21
+ - **`DialogOptions`/`PromptDialogOptions` skill-doc reference had drifted substantially.**
22
+ `DialogOptions` listed a `closable` field that has never existed and was missing five real
23
+ fields (`offset`/`modal`/`buttonClose`/`escapeClose`/`backdropClose`). `PromptDialogOptions`
24
+ claimed `extends DialogOptions` (source: `extends ConfirmDialogOptions`) and a `default`
25
+ field that doesn't exist — the real field is `defaultValue` — while `type` was missing
26
+ entirely. Fixed the reference and the usage example. Found by a new internal tool
27
+ (`type-doc-check.js`) that diffs hand-copied TS interface doc snippets against source.
28
+
3
29
  ## [1.35.6] - 2026-09-03
4
30
 
5
31
  ### Fixed
package/README.md CHANGED
@@ -70,7 +70,7 @@ npx skills add ./node_modules/@iyulab/components
70
70
 
71
71
  **Buttons & Actions** — `u-button`, `u-button-group`, `u-icon-button`, `u-copy-button`, `u-chip`
72
72
 
73
- **Form Controls** — `u-input`, `u-textarea`, `u-select`, `u-date-picker`, `u-checkbox`, `u-radio`, `u-switch`, `u-slider`, `u-rating`, `u-field`, `u-form`, `u-option`
73
+ **Form Controls** — `u-input`, `u-textarea`, `u-select`, `u-date-picker`, `u-file-input`, `u-checkbox`, `u-radio`, `u-switch`, `u-slider`, `u-rating`, `u-field`, `u-form`, `u-option`
74
74
 
75
75
  **Overlay & Floating** — `u-dialog`, `u-drawer`, `u-popover`, `u-tooltip`
76
76
 
@@ -24,6 +24,9 @@ var nextMonth = "الشهر التالي";
24
24
  var close = "إغلاق";
25
25
  var copy = "نسخ";
26
26
  var copied = "تم النسخ";
27
+ var chooseFile = "اختر ملفًا";
28
+ var noFileChosen = "لم يتم اختيار أي ملف";
29
+ var filesSelected = "تم اختيار {count} ملفات";
27
30
  var ar_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var ar_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, ar_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, ar_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Nächster Monat";
24
24
  var close = "Schließen";
25
25
  var copy = "Kopieren";
26
26
  var copied = "Kopiert";
27
+ var chooseFile = "Datei auswählen";
28
+ var noFileChosen = "Keine Datei ausgewählt";
29
+ var filesSelected = "{count} Dateien ausgewählt";
27
30
  var de_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var de_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, de_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, de_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Next month";
24
24
  var close = "Close";
25
25
  var copy = "Copy";
26
26
  var copied = "Copied";
27
+ var chooseFile = "Choose file";
28
+ var noFileChosen = "No file chosen";
29
+ var filesSelected = "{count} files selected";
27
30
  var en_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var en_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, en_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, en_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -23,6 +23,9 @@ var nextMonth = "Mes siguiente";
23
23
  var close = "Cerrar";
24
24
  var copy = "Copiar";
25
25
  var copied = "Copiado";
26
+ var chooseFile = "Elegir archivo";
27
+ var noFileChosen = "Ningún archivo elegido";
28
+ var filesSelected = "{count} archivos seleccionados";
26
29
  var es_default = {
27
30
  valueMissing,
28
31
  badInput,
@@ -48,7 +51,10 @@ var es_default = {
48
51
  nextMonth,
49
52
  close,
50
53
  copy,
51
- copied
54
+ copied,
55
+ chooseFile,
56
+ noFileChosen,
57
+ filesSelected
52
58
  };
53
59
  //#endregion
54
- export { badInput, chooseDate, clear, close, copied, copy, decrement, es_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, tooLong, tooShort, typeMismatch, valueMissing };
60
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, es_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Mois suivant";
24
24
  var close = "Fermer";
25
25
  var copy = "Copier";
26
26
  var copied = "Copié";
27
+ var chooseFile = "Choisir un fichier";
28
+ var noFileChosen = "Aucun fichier choisi";
29
+ var filesSelected = "{count} fichiers sélectionnés";
27
30
  var fr_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var fr_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, fr_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, fr_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Bulan berikutnya";
24
24
  var close = "Tutup";
25
25
  var copy = "Salin";
26
26
  var copied = "Disalin";
27
+ var chooseFile = "Pilih berkas";
28
+ var noFileChosen = "Tidak ada berkas dipilih";
29
+ var filesSelected = "{count} berkas dipilih";
27
30
  var id_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var id_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, id_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, id_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "翌月";
24
24
  var close = "閉じる";
25
25
  var copy = "コピー";
26
26
  var copied = "コピーしました";
27
+ var chooseFile = "ファイルを選択";
28
+ var noFileChosen = "ファイルが選択されていません";
29
+ var filesSelected = "{count}個のファイルを選択しました";
27
30
  var ja_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var ja_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, ja_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, ja_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "다음 달";
24
24
  var close = "닫기";
25
25
  var copy = "복사";
26
26
  var copied = "복사됨";
27
+ var chooseFile = "파일 선택";
28
+ var noFileChosen = "선택된 파일 없음";
29
+ var filesSelected = "{count}개 파일 선택됨";
27
30
  var ko_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var ko_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, ko_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, ko_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Próximo mês";
24
24
  var close = "Fechar";
25
25
  var copy = "Copiar";
26
26
  var copied = "Copiado";
27
+ var chooseFile = "Escolher arquivo";
28
+ var noFileChosen = "Nenhum arquivo escolhido";
29
+ var filesSelected = "{count} arquivos selecionados";
27
30
  var pt_BR_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var pt_BR_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, pt_BR_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, pt_BR_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Следующий месяц";
24
24
  var close = "Закрыть";
25
25
  var copy = "Копировать";
26
26
  var copied = "Скопировано";
27
+ var chooseFile = "Выбрать файл";
28
+ var noFileChosen = "Файл не выбран";
29
+ var filesSelected = "Выбрано файлов: {count}";
27
30
  var ru_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var ru_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, ru_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, ru_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "เดือนถัดไป";
24
24
  var close = "ปิด";
25
25
  var copy = "คัดลอก";
26
26
  var copied = "คัดลอกแล้ว";
27
+ var chooseFile = "เลือกไฟล์";
28
+ var noFileChosen = "ยังไม่ได้เลือกไฟล์";
29
+ var filesSelected = "เลือกแล้ว {count} ไฟล์";
27
30
  var th_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var th_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, th_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, th_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "Tháng sau";
24
24
  var close = "Đóng";
25
25
  var copy = "Sao chép";
26
26
  var copied = "Đã sao chép";
27
+ var chooseFile = "Chọn tệp";
28
+ var noFileChosen = "Chưa chọn tệp nào";
29
+ var filesSelected = "Đã chọn {count} tệp";
27
30
  var vi_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var vi_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, vi_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, vi_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "下个月";
24
24
  var close = "关闭";
25
25
  var copy = "复制";
26
26
  var copied = "已复制";
27
+ var chooseFile = "选择文件";
28
+ var noFileChosen = "未选择文件";
29
+ var filesSelected = "已选择{count}个文件";
27
30
  var zh_CN_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var zh_CN_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, zh_CN_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, zh_CN_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -24,6 +24,9 @@ var nextMonth = "下個月";
24
24
  var close = "關閉";
25
25
  var copy = "複製";
26
26
  var copied = "已複製";
27
+ var chooseFile = "選擇檔案";
28
+ var noFileChosen = "未選擇檔案";
29
+ var filesSelected = "已選擇{count}個檔案";
27
30
  var zh_TW_default = {
28
31
  valueMissing,
29
32
  badInput,
@@ -49,7 +52,10 @@ var zh_TW_default = {
49
52
  nextMonth,
50
53
  close,
51
54
  copy,
52
- copied
55
+ copied,
56
+ chooseFile,
57
+ noFileChosen,
58
+ filesSelected
53
59
  };
54
60
  //#endregion
55
- export { badInput, chooseDate, clear, close, copied, copy, decrement, zh_TW_default as default, goToSlide, hidePassword, increment, nextMonth, nextSlide, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
61
+ export { badInput, chooseDate, chooseFile, clear, close, copied, copy, decrement, zh_TW_default as default, filesSelected, goToSlide, hidePassword, increment, nextMonth, nextSlide, noFileChosen, patternMismatch, previousMonth, previousSlide, rangeOverflow, rangeUnderflow, showPassword, stepMismatch, time, today, tooLong, tooShort, typeMismatch, valueMissing };
@@ -0,0 +1,57 @@
1
+ import { PropertyValues } from 'lit';
2
+ import { UFormControlElement } from '../UFormControlElement.js';
3
+ /**
4
+ * 파일 선택 입력 컴포넌트입니다. 네이티브 `<input type="file">`를 감싸
5
+ * 디자인시스템 톤의 트리거 버튼 + 선택 결과 표시로 렌더링합니다.
6
+ *
7
+ * 값은 항상 `File[] | null`입니다 — `multiple`이 꺼져 있어도 선택된 파일은
8
+ * 배열(0개 또는 1개)로 담깁니다. 폼 제출 시 파일이 1개면 그 `File`을,
9
+ * 여러 개면 같은 `name`으로 반복 append한 `FormData`를 `ElementInternals`에
10
+ * 전달합니다 — 네이티브 `<input type="file" multiple>`과 같은 제출 형태입니다.
11
+ *
12
+ * @csspart field - u-field 요소
13
+ * @csspart container - 트리거·상태 텍스트·지우기 버튼을 감싸는 컨테이너
14
+ * @csspart trigger - 파일 선택 트리거 버튼
15
+ * @csspart status - 선택 상태 텍스트("선택된 파일 없음" · 파일명 · "N개 파일 선택됨")
16
+ * @csspart clear-button - 선택 해제 버튼(u-icon)
17
+ * @csspart input - 숨겨진 네이티브 `<input type="file">`
18
+ *
19
+ * @cssprop --u-file-input-display - 호스트의 display (기본값: inline-block)
20
+ * @cssprop --u-file-input-width - 호스트의 width (기본값: auto)
21
+ *
22
+ * @event change - 선택된 파일이 바뀔 때 발생(선택·지우기 공통)
23
+ */
24
+ export declare class UFileInput extends UFormControlElement<File[] | null> {
25
+ static styles: import('lit').CSSResultGroup[];
26
+ /** 값은 attribute로 표현될 수 없다 — 항상 프로그램적으로만 설정된다. */
27
+ value: File[] | null;
28
+ /** 선택 가능한 파일 형식을 제한한다(네이티브 `accept` 속성 그대로 통과). */
29
+ accept?: string;
30
+ /** 여러 파일을 한 번에 선택할 수 있는지 여부. */
31
+ multiple: boolean;
32
+ triggerEl?: HTMLButtonElement;
33
+ inputEl?: HTMLInputElement;
34
+ /** `value`가 바뀌는 모든 경로(선택·지우기)에서 폼 제출값을 동기화한다 —
35
+ * `UInput`/`UCheckbox`와 같은 경계(`DL-289-1`). 파일은 문자열로 표현할 수
36
+ * 없으므로 1개면 `File`을, 여러 개면 같은 키로 반복 append한 `FormData`를
37
+ * 넘긴다 — 네이티브 `<input type="file" multiple>`의 제출 형태와 동일하다. */
38
+ protected updated(changedProperties: PropertyValues): void;
39
+ private syncFormValue;
40
+ render(): import('lit-html').TemplateResult<1>;
41
+ protected setValidity(): void;
42
+ reset(): void;
43
+ focus(options?: FocusOptions): void;
44
+ blur(): void;
45
+ private handleTriggerClick;
46
+ private handleInputChange;
47
+ private handleClearButtonClick;
48
+ /** `clear-btn`은 순수 표시 요소(`u-icon`)라 네이티브 키보드 활성화가 없다 —
49
+ * `role="button"`+`tabindex="0"`로 포커스 가능하게 한 뒤, Enter/Space를 같은
50
+ * 클릭 핸들러로 릴레이한다(`UInput.handleSuffixIconKeydown`과 같은 패턴). */
51
+ private handleClearButtonKeydown;
52
+ }
53
+ declare global {
54
+ interface HTMLElementTagNameMap {
55
+ 'u-file-input': UFileInput;
56
+ }
57
+ }
@@ -0,0 +1,140 @@
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
3
+ import { UFormControlElement } from "../UFormControlElement.js";
4
+ import "../icon/UIcon.js";
5
+ import { Locale } from "../../utilities/Locale.js";
6
+ import "../field/UField.js";
7
+ import { styles } from "./UFileInput.styles.js";
8
+ import { html } from "lit";
9
+ import { customElement, property, query } from "lit/decorators.js";
10
+ import { ifDefined } from "lit/directives/if-defined.js";
11
+ //#region src/components/file-input/UFileInput.ts
12
+ var UFileInput = class UFileInput extends UFormControlElement {
13
+ constructor(..._args) {
14
+ super(..._args);
15
+ this.value = null;
16
+ this.multiple = false;
17
+ this.handleTriggerClick = (e) => {
18
+ e.stopImmediatePropagation();
19
+ if (this.disabled || this.readonly) return;
20
+ this.inputEl?.click();
21
+ };
22
+ this.handleInputChange = (e) => {
23
+ const input = e.target;
24
+ this.value = input.files && input.files.length > 0 ? Array.from(input.files) : null;
25
+ if (!this.novalidate) this.validate();
26
+ this.relay(e);
27
+ };
28
+ this.handleClearButtonClick = (e) => {
29
+ e.stopImmediatePropagation();
30
+ this.reset();
31
+ this.dispatchEvent(new InputEvent("input", {
32
+ bubbles: true,
33
+ composed: true
34
+ }));
35
+ this.dispatchEvent(new Event("change", {
36
+ bubbles: true,
37
+ composed: true
38
+ }));
39
+ this.focus();
40
+ };
41
+ this.handleClearButtonKeydown = (e) => {
42
+ if (e.key !== "Enter" && e.key !== " ") return;
43
+ e.preventDefault();
44
+ this.handleClearButtonClick(e);
45
+ };
46
+ }
47
+ static {
48
+ this.styles = [super.styles, styles];
49
+ }
50
+ /** `value`가 바뀌는 모든 경로(선택·지우기)에서 폼 제출값을 동기화한다 —
51
+ * `UInput`/`UCheckbox`와 같은 경계(`DL-289-1`). 파일은 문자열로 표현할 수
52
+ * 없으므로 1개면 `File`을, 여러 개면 같은 키로 반복 append한 `FormData`를
53
+ * 넘긴다 — 네이티브 `<input type="file" multiple>`의 제출 형태와 동일하다. */
54
+ updated(changedProperties) {
55
+ super.updated(changedProperties);
56
+ if (changedProperties.has("value")) this.syncFormValue();
57
+ }
58
+ syncFormValue() {
59
+ const files = this.value ?? [];
60
+ if (files.length === 0) this.internals?.setFormValue(null);
61
+ else if (files.length === 1) this.internals?.setFormValue(files[0]);
62
+ else {
63
+ const fd = new FormData();
64
+ for (const file of files) fd.append(this.name ?? "", file);
65
+ this.internals?.setFormValue(fd);
66
+ }
67
+ }
68
+ render() {
69
+ const files = this.value ?? [];
70
+ const hasFiles = files.length > 0;
71
+ const status = !hasFiles ? Locale.getValue("noFileChosen") : files.length === 1 ? files[0].name : Locale.getValue("filesSelected", { count: files.length });
72
+ return html`
73
+ <u-field part="field"
74
+ ?required=${this.required}
75
+ ?disabled=${this.disabled}
76
+ ?invalid=${this.invalid}
77
+ .label=${this.label}
78
+ .description=${this.description}
79
+ .validationMessage=${this.validationMessage}
80
+ >
81
+ <div class="container" part="container">
82
+ <button class="trigger" part="trigger"
83
+ type="button"
84
+ ?disabled=${this.disabled || this.readonly}
85
+ @click=${this.handleTriggerClick}
86
+ >${Locale.getValue("chooseFile")}</button>
87
+
88
+ <span class="status" part="status" ?data-empty=${!hasFiles}>${status}</span>
89
+
90
+ <u-icon class="clear-btn" part="clear-button"
91
+ ?hidden=${!hasFiles || this.disabled || this.readonly}
92
+ role="button"
93
+ tabindex="0"
94
+ aria-label=${Locale.getValue("clear")}
95
+ lib="internal"
96
+ name="x"
97
+ @click=${this.handleClearButtonClick}
98
+ @keydown=${this.handleClearButtonKeydown}
99
+ ></u-icon>
100
+
101
+ <input class="native-input" part="input"
102
+ type="file"
103
+ hidden
104
+ name=${ifDefined(this.name)}
105
+ accept=${ifDefined(this.accept)}
106
+ ?multiple=${this.multiple}
107
+ ?disabled=${this.disabled || this.readonly}
108
+ @change=${this.handleInputChange}
109
+ />
110
+ </div>
111
+ </u-field>
112
+ `;
113
+ }
114
+ setValidity() {
115
+ const missing = this.required && (!this.value || this.value.length === 0);
116
+ this.commit(missing ? { valueMissing: true } : {}, missing ? Locale.getValue("valueMissing") : "", this.triggerEl ?? void 0);
117
+ }
118
+ reset() {
119
+ this.value = null;
120
+ this.invalid = false;
121
+ if (this.inputEl) this.inputEl.value = "";
122
+ }
123
+ focus(options) {
124
+ this.triggerEl?.focus(options);
125
+ }
126
+ blur() {
127
+ this.triggerEl?.blur();
128
+ }
129
+ };
130
+ __decorate([property({ attribute: false }), __decorateMetadata("design:type", Object)], UFileInput.prototype, "value", void 0);
131
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UFileInput.prototype, "accept", void 0);
132
+ __decorate([property({
133
+ type: Boolean,
134
+ reflect: true
135
+ }), __decorateMetadata("design:type", Boolean)], UFileInput.prototype, "multiple", void 0);
136
+ __decorate([query(".trigger", true), __decorateMetadata("design:type", typeof HTMLButtonElement === "undefined" ? Object : HTMLButtonElement)], UFileInput.prototype, "triggerEl", void 0);
137
+ __decorate([query("input[type=\"file\"]", true), __decorateMetadata("design:type", typeof HTMLInputElement === "undefined" ? Object : HTMLInputElement)], UFileInput.prototype, "inputEl", void 0);
138
+ UFileInput = __decorate([customElement("u-file-input")], UFileInput);
139
+ //#endregion
140
+ export { UFileInput };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,80 @@
1
+ import { css } from "lit";
2
+ //#region src/components/file-input/UFileInput.styles.ts
3
+ var styles = css`
4
+ :host {
5
+ display: var(--u-file-input-display, inline-block);
6
+ width: var(--u-file-input-width, auto);
7
+ color: var(--u-txt-color, #212121);
8
+ font-size: inherit;
9
+ font-family: var(--u-font-base);
10
+ }
11
+
12
+ .container {
13
+ display: flex;
14
+ flex-direction: row;
15
+ align-items: center;
16
+ gap: 0.6em;
17
+ }
18
+
19
+ .trigger {
20
+ flex-shrink: 0;
21
+ display: inline-flex;
22
+ align-items: center;
23
+ padding: 0.4em 0.9em;
24
+ border: 1px solid var(--u-input-border-color, #E0E0E0);
25
+ border-radius: 0.25em;
26
+ background-color: var(--u-panel-bg-color, #FFFFFF);
27
+ color: var(--u-primary-color, #1976D2);
28
+ font: inherit;
29
+ font-weight: 500;
30
+ cursor: pointer;
31
+ transition: border-color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), background-color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
32
+ }
33
+ .trigger:hover:not(:disabled) {
34
+ background-color: var(--u-neutral-100, #F5F5F5);
35
+ border-color: var(--u-input-border-color-hover, #BDBDBD);
36
+ }
37
+ .trigger:focus-visible {
38
+ outline: none;
39
+ box-shadow: 0 0 0 1px var(--u-input-border-color-focus, #1565C0),
40
+ 0 0 0 3px color-mix(in srgb, var(--u-primary-color-strong, #1565C0) 22%, transparent);
41
+ }
42
+ .trigger:disabled {
43
+ color: var(--u-txt-color-weak, #757575);
44
+ background-color: var(--u-bg-color-disabled, #FAFAFA);
45
+ border-color: var(--u-border-color-weak, #EEEEEE);
46
+ cursor: not-allowed;
47
+ }
48
+
49
+ .status {
50
+ flex: 1 1 auto;
51
+ min-width: 0;
52
+ overflow: hidden;
53
+ text-overflow: ellipsis;
54
+ white-space: nowrap;
55
+ font-size: 0.9em;
56
+ }
57
+ .status[data-empty] {
58
+ color: var(--u-txt-color-weak, #757575);
59
+ }
60
+
61
+ .clear-btn {
62
+ flex-shrink: 0;
63
+ color: var(--u-icon-color, #616161);
64
+ font-size: 1em;
65
+ cursor: pointer;
66
+ transition: color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
67
+ }
68
+ .clear-btn:hover {
69
+ color: var(--u-icon-color-hover, #1565C0);
70
+ }
71
+ .clear-btn:active {
72
+ color: var(--u-icon-color-active, #1565C0);
73
+ }
74
+
75
+ :host([invalid]) .trigger {
76
+ border-color: var(--u-input-border-color-invalid, #C62828);
77
+ }
78
+ `;
79
+ //#endregion
80
+ export { styles };
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ export * from './components/divider/UDivider.js';
20
20
  export * from './components/drawer/UDrawer.js';
21
21
  export * from './components/expander/UExpander.js';
22
22
  export * from './components/field/UField.js';
23
+ export * from './components/file-input/UFileInput.js';
23
24
  export * from './components/form/UForm.js';
24
25
  export * from './components/icon/UIcon.js';
25
26
  export * from './components/icon-button/UIconButton.js';
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ import { UDialog } from "./components/dialog/UDialog.js";
32
32
  import { UDivider } from "./components/divider/UDivider.js";
33
33
  import { UDrawer } from "./components/drawer/UDrawer.js";
34
34
  import { UExpander } from "./components/expander/UExpander.js";
35
+ import { UFileInput } from "./components/file-input/UFileInput.js";
35
36
  import { UForm } from "./components/form/UForm.js";
36
37
  import { UOption } from "./components/option/UOption.js";
37
38
  import { UInput } from "./components/input/UInput.js";
@@ -57,4 +58,4 @@ import { BrowserStorage } from "./utilities/BrowserStorage.js";
57
58
  import { Dialog } from "./utilities/Dialog.js";
58
59
  import { Theme } from "./utilities/Theme.js";
59
60
  import { Toast } from "./utilities/Toast.js";
60
- export { BrowserStorage, Dialog, IconCache, IconRegistry, Locale, OverlayManager, Theme, Toast, UAlert, UAvatar, UBadge, UBreadcrumb, UBreadcrumbItem, UButton, UButtonGroup, UCard, UCarousel, UCheckbox, UChip, UCopyButton, UDatePicker, UDialog, UDivider, UDrawer, UElement, UExpander, 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, UText, UTextarea, UTooltip, UTree, UTreeItem, arrayAttrConverter, booleanAttrConverter, dateAttrConverter, formatCurrency, formatDate, formatNumber, getDefaultBaseUrl, getParentElement, isCoarsePointer, jsonAttrConverter, querySelectorAllWithin, querySelectorWithin, setDefaultBaseUrl, urlAttrConverter };
61
+ export { BrowserStorage, Dialog, IconCache, IconRegistry, Locale, OverlayManager, Theme, Toast, UAlert, UAvatar, UBadge, UBreadcrumb, UBreadcrumbItem, UButton, UButtonGroup, UCard, UCarousel, UCheckbox, UChip, UCopyButton, UDatePicker, UDialog, UDivider, UDrawer, UElement, UExpander, UField, UFileInput, 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, UText, UTextarea, UTooltip, UTree, UTreeItem, arrayAttrConverter, booleanAttrConverter, dateAttrConverter, formatCurrency, formatDate, formatNumber, getDefaultBaseUrl, getParentElement, isCoarsePointer, jsonAttrConverter, querySelectorAllWithin, querySelectorWithin, setDefaultBaseUrl, urlAttrConverter };
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { UFileInput as UFileInputElement } from '../components/file-input/UFileInput';
3
+
4
+ export declare const UFileInput: React.ForwardRefExoticComponent<
5
+ Omit<Partial<UFileInputElement>, keyof React.HTMLAttributes<UFileInputElement>>
6
+ & Omit<React.HTMLAttributes<UFileInputElement>, 'onChange'>
7
+ & React.RefAttributes<UFileInputElement>
8
+ & {
9
+ onChange?: (event: CustomEvent) => void;
10
+ }
11
+ >;
12
+
13
+ export type UFileInputProps = React.ComponentProps<typeof UFileInput>;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { createComponent } from '@lit/react';
3
+ import { UFileInput as UFileInputElement } from '../components/file-input/UFileInput.js';
4
+
5
+ export const UFileInput = createComponent({
6
+ react: React,
7
+ tagName: 'u-file-input',
8
+ elementClass: UFileInputElement,
9
+ events: {
10
+ onChange: 'change',
11
+ },
12
+ });
@@ -25,6 +25,7 @@ export { UInput, UInputProps } from './UInput';
25
25
  export { UIconButton, UIconButtonProps } from './UIconButton';
26
26
  export { UIcon, UIconProps } from './UIcon';
27
27
  export { UForm, UFormProps } from './UForm';
28
+ export { UFileInput, UFileInputProps } from './UFileInput';
28
29
  export { UField, UFieldProps } from './UField';
29
30
  export { UExpander, UExpanderProps } from './UExpander';
30
31
  export { UDrawer, UDrawerProps } from './UDrawer';
@@ -25,6 +25,7 @@ export { UInput } from './UInput.js';
25
25
  export { UIconButton } from './UIconButton.js';
26
26
  export { UIcon } from './UIcon.js';
27
27
  export { UForm } from './UForm.js';
28
+ export { UFileInput } from './UFileInput.js';
28
29
  export { UField } from './UField.js';
29
30
  export { UExpander } from './UExpander.js';
30
31
  export { UDrawer } from './UDrawer.js';
@@ -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' | 'today' | 'time' | 'showPassword' | 'hidePassword' | 'previousSlide' | 'nextSlide' | 'goToSlide' | 'chooseDate' | 'previousMonth' | 'nextMonth' | 'close' | 'copy' | 'copied';
15
+ export type LocaleMessageKey = 'valueMissing' | 'badInput' | 'typeMismatch' | 'patternMismatch' | 'rangeUnderflow' | 'rangeOverflow' | 'stepMismatch' | 'tooShort' | 'tooLong' | 'increment' | 'decrement' | 'clear' | 'today' | 'time' | 'showPassword' | 'hidePassword' | 'previousSlide' | 'nextSlide' | 'goToSlide' | 'chooseDate' | 'previousMonth' | 'nextMonth' | 'close' | 'copy' | 'copied' | 'chooseFile' | 'noFileChosen' | 'filesSelected';
16
16
  type LocaleTable = Record<LocaleMessageKey, string>;
17
17
  /**
18
18
  * 한 패키지(또는 앱 영역)의 문자열 묶음.
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.35.6",
4
+ "version": "1.36.0",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "components",
@@ -67,6 +67,8 @@ import { UButton, UInput } from '@iyulab/components/react';
67
67
  - [`u-input`](./references/components/input.md) — Text input; combobox mode when `u-option` children are present
68
68
  - [`u-textarea`](./references/components/textarea.md) — Multi-line text input with auto-resize and character counter
69
69
  - [`u-select`](./references/components/select.md) — Dropdown select; single or multiple, with search
70
+ - [`u-date-picker`](./references/components/date-picker.md) — Single-date(-time) selection with a popover calendar
71
+ - [`u-file-input`](./references/components/file-input.md) — File picker with a design-system trigger button and selected-file(s) display
70
72
  - [`u-checkbox`](./references/components/checkbox.md) — Checkbox with indeterminate state support
71
73
  - [`u-radio`](./references/components/radio.md) — Radio group built from `u-option` children
72
74
  - [`u-switch`](./references/components/switch.md) — Toggle switch
@@ -0,0 +1,81 @@
1
+ # u-file-input
2
+
3
+ ```ts
4
+ import '@iyulab/components/dist/components/file-input/UFileInput.js';
5
+ ```
6
+
7
+ **Tag:** `u-file-input`
8
+
9
+ File picker with a design-system-styled trigger button and a selected-file(s) status display,
10
+ wrapping a hidden native `<input type="file">`. Form-associated (`formAssociated = true`).
11
+
12
+ `value` is always `File[] | null` — even with `multiple` off, a selected file is held as a
13
+ one-element array. On form submission: 0 files → nothing is sent for `name`; 1 file → the `File`
14
+ itself; more than 1 file → a `FormData` with the same `File` repeatedly appended under `name`,
15
+ matching what a native `<input type="file" multiple>` submits.
16
+
17
+ ```html
18
+ <u-file-input name="attachment" required accept="image/*"></u-file-input>
19
+
20
+ <u-file-input name="attachments" multiple accept=".csv,.xlsx"></u-file-input>
21
+ ```
22
+
23
+ ```ts
24
+ const picker = document.querySelector('u-file-input');
25
+ picker.addEventListener('change', () => {
26
+ console.log(picker.value); // File[] | null
27
+ });
28
+ ```
29
+
30
+ No drag-and-drop in this version — it is a minimal wrapper (trigger + status + clear), by design.
31
+
32
+ ---
33
+
34
+ ## Properties
35
+
36
+ | Property | Type | Default | Reflect | Description |
37
+ |----------|------|---------|---------|-------------|
38
+ | `value` | `File[] \| null` | `null` | — | Selected files (always an array, even for single-file selection) |
39
+ | `accept` | `string` | — | — | Passed through to the native `accept` attribute |
40
+ | `multiple` | `boolean` | `false` | ✓ | Allow selecting more than one file |
41
+ | `disabled` | `boolean` | `false` | ✓ | Disable the control |
42
+ | `readonly` | `boolean` | `false` | ✓ | Read-only (trigger and clear button inert) |
43
+ | `required` | `boolean` | `false` | ✓ | Required field |
44
+ | `invalid` | `boolean` | `false` | ✓ | Validation failed state |
45
+ | `name` | `string` | — | — | Form field name |
46
+ | `label` | `string` | — | — | Label text |
47
+ | `description` | `string` | — | — | Helper text below the control |
48
+ | `validationMessage` | `string` | — | — | Custom validation message |
49
+
50
+ ## Methods
51
+
52
+ | Method | Returns | Description |
53
+ |--------|---------|-------------|
54
+ | `validate()` | `boolean` | Run validation; sets `invalid` |
55
+ | `reset()` | `void` | Clear the selection and validation state |
56
+ | `focus(options?)` | `void` | Focus the trigger button |
57
+ | `blur()` | `void` | Blur the trigger button |
58
+
59
+ ## CSS Parts
60
+
61
+ | Part | Description |
62
+ |------|-------------|
63
+ | `field` | Inner `u-field` element (label/description/validation layout) |
64
+ | `container` | Wrapper around the trigger, status text, and clear button |
65
+ | `trigger` | The file-picker trigger button |
66
+ | `status` | Status text — "No file chosen", the filename, or "N files selected" |
67
+ | `clear-button` | Clear-selection button (a `u-icon`) |
68
+ | `input` | The hidden native `<input type="file">` |
69
+
70
+ ## CSS Custom Properties
71
+
72
+ | Property | Description |
73
+ |----------|--------------|
74
+ | `--u-file-input-display` | Host `display` (default: `inline-block`) |
75
+ | `--u-file-input-width` | Host `width` (default: `auto`) |
76
+
77
+ ## Events
78
+
79
+ | Event | Description |
80
+ |-------|-------------|
81
+ | `change` | Fires when the selection changes (picking files or clearing) |
@@ -17,7 +17,7 @@ const confirmed = await Dialog.confirm('Delete this item?');
17
17
  if (confirmed) deleteItem();
18
18
 
19
19
  // Prompt — returns entered string or null if cancelled
20
- const name = await Dialog.prompt('Enter your name:', { default: 'Alice' });
20
+ const name = await Dialog.prompt('Enter your name:', { defaultValue: 'Alice' });
21
21
 
22
22
  // Custom dialog with action buttons
23
23
  const result = await Dialog.show({
@@ -44,26 +44,29 @@ const result = await Dialog.show({
44
44
 
45
45
  ```ts
46
46
  interface DialogOptions {
47
- target?: HTMLElement;
47
+ target?: HTMLElement; // shows contained instead of as an overlay when set
48
48
  title?: string;
49
- closable?: boolean;
50
49
  placement?: DialogPlacement;
50
+ offset?: number; // gap from the edge, px
51
+ modal?: boolean; // default: true
52
+ buttonClose?: boolean; // show an explicit close button — default: false
53
+ escapeClose?: boolean; // close on Esc — default: true
54
+ backdropClose?: boolean; // close on backdrop click — default: true
51
55
  }
52
56
 
53
57
  interface ConfirmDialogOptions extends DialogOptions {
54
- confirmLabel?: string;
55
- cancelLabel?: string;
58
+ confirmLabel?: string; // default: 'Confirm'
59
+ cancelLabel?: string; // default: 'Cancel'
56
60
  }
57
61
 
58
- interface PromptDialogOptions extends DialogOptions {
59
- default?: string;
62
+ interface PromptDialogOptions extends ConfirmDialogOptions {
63
+ type?: InputType; // input field type — default: 'text'
64
+ defaultValue?: string;
60
65
  placeholder?: string;
61
- confirmLabel?: string;
62
- cancelLabel?: string;
63
66
  }
64
67
 
65
68
  interface CustomDialogOptions extends DialogOptions {
66
- content?: string | HTMLElement | TemplateResult;
69
+ content: string | TemplateResult;
67
70
  actions?: DialogAction[];
68
71
  }
69
72