@iyulab/flex-table 0.34.3 → 0.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.
@@ -447,20 +447,39 @@ var l = r`
447
447
 
448
448
  /* --- Filter UI --- */
449
449
 
450
- .ft-filter-btn {
450
+ /* 열 메뉴 버튼 — 필터·숨기기·폭 조절이 모두 여기서 열린다. 24px 은 WCAG 2.2 SC 2.5.8 하한이고,
451
+ 6px 리사이즈 핸들의 «등가 수단» 이 이 버튼의 메뉴다. */
452
+ .ft-column-menu-btn {
451
453
  all: unset;
454
+ box-sizing: border-box;
455
+ display: inline-flex;
456
+ align-items: center;
457
+ justify-content: center;
458
+ inline-size: 24px;
459
+ block-size: 24px;
460
+ margin-left: auto;
461
+ flex-shrink: 0;
462
+ border-radius: 4px;
452
463
  cursor: pointer;
453
- font-size: 10px;
464
+ font-size: 16px;
465
+ line-height: 1;
454
466
  color: var(--ft-sort-indicator-color);
455
- padding: 0 2px;
456
- margin-left: auto;
457
467
  opacity: 0.7;
458
- flex-shrink: 0;
459
468
  }
460
469
 
461
- .ft-filter-btn:hover { opacity: 1; }
470
+ .ft-column-menu-btn:hover,
471
+ .ft-column-menu-btn[aria-expanded="true"] {
472
+ opacity: 1;
473
+ background: var(--ft-header-hover-bg);
474
+ }
475
+
476
+ .ft-column-menu-btn:focus-visible {
477
+ opacity: 1;
478
+ outline: 2px solid var(--ft-active-color);
479
+ outline-offset: -2px;
480
+ }
462
481
 
463
- .ft-filter-btn.ft-filter-active {
482
+ .ft-column-menu-btn.ft-filter-active {
464
483
  color: var(--ft-active-color);
465
484
  opacity: 1;
466
485
  }
@@ -639,21 +658,36 @@ var l = r`
639
658
  min-width: 160px;
640
659
  border-radius: 4px;
641
660
  overflow: hidden;
661
+ display: flex;
662
+ flex-direction: column;
663
+ padding-block: 4px;
642
664
  }
643
665
 
644
666
  .ft-header-menu-item {
667
+ all: unset;
668
+ box-sizing: border-box;
669
+ display: block;
670
+ min-block-size: 28px;
645
671
  padding: 6px 12px;
646
672
  cursor: pointer;
647
673
  font-size: var(--ft-font-size, 14px);
648
674
  color: var(--ft-text-color);
649
675
  white-space: nowrap;
676
+ text-align: start;
650
677
  }
651
678
 
652
- .ft-header-menu-item:hover {
679
+ .ft-header-menu-item:hover,
680
+ .ft-header-menu-item:focus-visible {
653
681
  background: var(--ft-selection-bg);
654
682
  color: var(--ft-active-color);
655
683
  }
656
684
 
685
+ .ft-header-menu-separator {
686
+ block-size: 1px;
687
+ margin-block: 4px;
688
+ background: var(--ft-border-color);
689
+ }
690
+
657
691
  /* Hidden column indicator in header */
658
692
  .ft-hidden-col-indicator {
659
693
  position: absolute;
@@ -693,20 +727,28 @@ var l = r`
693
727
  }
694
728
 
695
729
  .ft-context-menu-item {
730
+ all: unset;
731
+ box-sizing: border-box;
732
+ display: block;
733
+ inline-size: 100%;
734
+ min-block-size: 28px;
696
735
  padding: 6px 14px;
697
736
  cursor: pointer;
698
737
  font-size: var(--ft-font-size, 14px);
699
738
  color: var(--ft-text-color);
700
739
  white-space: nowrap;
701
740
  user-select: none;
741
+ text-align: start;
702
742
  }
703
743
 
704
- .ft-context-menu-item:hover {
744
+ .ft-context-menu-item:hover,
745
+ .ft-context-menu-item:focus-visible {
705
746
  background: var(--ft-selection-bg);
706
747
  color: var(--ft-active-color);
707
748
  }
708
749
 
709
- .ft-context-menu-item.ft-context-menu-danger:hover {
750
+ .ft-context-menu-item.ft-context-menu-danger:hover,
751
+ .ft-context-menu-item.ft-context-menu-danger:focus-visible {
710
752
  background: #fdd;
711
753
  color: #c0392b;
712
754
  }
@@ -936,8 +978,697 @@ function y(e) {
936
978
  return String(e);
937
979
  }
938
980
  //#endregion
981
+ //#region node_modules/@iyulab/components/dist/utilities/Locale.js
982
+ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
983
+ "../assets/locales/ar.json": {
984
+ valueMissing: "هذا الحقل مطلوب",
985
+ badInput: "يرجى إدخال قيمة صالحة",
986
+ typeMismatch: "يرجى إدخال قيمة بالتنسيق الصحيح",
987
+ patternMismatch: "يرجى اتباع التنسيق المطلوب",
988
+ rangeUnderflow: "يجب أن تكون القيمة {min} على الأقل",
989
+ rangeOverflow: "يجب ألا تتجاوز القيمة {max}",
990
+ stepMismatch: "يجب أن تكون القيمة من مضاعفات {step}",
991
+ tooShort: "يجب أن تكون {min} على الأقل",
992
+ tooLong: "يجب ألا تتجاوز {max}",
993
+ increment: "زيادة القيمة",
994
+ decrement: "إنقاص القيمة",
995
+ clear: "مسح القيمة",
996
+ today: "اليوم",
997
+ time: "الوقت",
998
+ showPassword: "إظهار كلمة المرور",
999
+ hidePassword: "إخفاء كلمة المرور",
1000
+ previousSlide: "الشريحة السابقة",
1001
+ nextSlide: "الشريحة التالية",
1002
+ goToSlide: "الانتقال إلى الشريحة {n}",
1003
+ chooseDate: "اختر التاريخ",
1004
+ previousMonth: "الشهر السابق",
1005
+ nextMonth: "الشهر التالي",
1006
+ close: "إغلاق",
1007
+ copy: "نسخ",
1008
+ copied: "تم النسخ",
1009
+ chooseFile: "اختر ملفًا",
1010
+ noFileChosen: "لم يتم اختيار أي ملف",
1011
+ filesSelected: "تم اختيار {count} ملفات",
1012
+ resizePanels: "تغيير حجم اللوحات",
1013
+ search: "بحث",
1014
+ alertError: "خطأ",
1015
+ alertWarning: "تحذير",
1016
+ alertSuccess: "نجاح",
1017
+ alertInfo: "معلومات",
1018
+ alertNotice: "إشعار",
1019
+ alertMessage: "رسالة",
1020
+ remove: "إزالة",
1021
+ closeTab: "إغلاق علامة التبويب"
1022
+ },
1023
+ "../assets/locales/de.json": {
1024
+ valueMissing: "Dieses Feld ist erforderlich",
1025
+ badInput: "Bitte geben Sie einen gültigen Wert ein",
1026
+ typeMismatch: "Bitte geben Sie einen gültigen Wert ein",
1027
+ patternMismatch: "Bitte halten Sie sich an das angeforderte Format",
1028
+ rangeUnderflow: "Der Wert muss mindestens {min} betragen",
1029
+ rangeOverflow: "Der Wert darf höchstens {max} betragen",
1030
+ stepMismatch: "Der Wert muss ein Vielfaches von {step} sein",
1031
+ tooShort: "Muss mindestens {min} betragen",
1032
+ tooLong: "Darf höchstens {max} betragen",
1033
+ increment: "Wert erhöhen",
1034
+ decrement: "Wert verringern",
1035
+ clear: "Wert löschen",
1036
+ today: "Heute",
1037
+ time: "Uhrzeit",
1038
+ showPassword: "Passwort anzeigen",
1039
+ hidePassword: "Passwort verbergen",
1040
+ previousSlide: "Vorherige Folie",
1041
+ nextSlide: "Nächste Folie",
1042
+ goToSlide: "Zu Folie {n} wechseln",
1043
+ chooseDate: "Datum auswählen",
1044
+ previousMonth: "Vorheriger Monat",
1045
+ nextMonth: "Nächster Monat",
1046
+ close: "Schließen",
1047
+ copy: "Kopieren",
1048
+ copied: "Kopiert",
1049
+ chooseFile: "Datei auswählen",
1050
+ noFileChosen: "Keine Datei ausgewählt",
1051
+ filesSelected: "{count} Dateien ausgewählt",
1052
+ resizePanels: "Bereichsgröße ändern",
1053
+ search: "Suchen",
1054
+ alertError: "Fehler",
1055
+ alertWarning: "Warnung",
1056
+ alertSuccess: "Erfolg",
1057
+ alertInfo: "Information",
1058
+ alertNotice: "Hinweis",
1059
+ alertMessage: "Nachricht",
1060
+ remove: "Entfernen",
1061
+ closeTab: "Tab schließen"
1062
+ },
1063
+ "../assets/locales/en.json": {
1064
+ valueMissing: "This field is required",
1065
+ badInput: "Please enter a valid value",
1066
+ typeMismatch: "Please enter a valid value",
1067
+ patternMismatch: "Please match the requested format",
1068
+ rangeUnderflow: "Value must be at least {min}",
1069
+ rangeOverflow: "Value must be at most {max}",
1070
+ stepMismatch: "Value must be a multiple of {step}",
1071
+ tooShort: "Must be at least {min}",
1072
+ tooLong: "Must be at most {max}",
1073
+ increment: "Increase value",
1074
+ decrement: "Decrease value",
1075
+ clear: "Clear value",
1076
+ today: "Today",
1077
+ time: "Time",
1078
+ showPassword: "Show password",
1079
+ hidePassword: "Hide password",
1080
+ previousSlide: "Previous slide",
1081
+ nextSlide: "Next slide",
1082
+ goToSlide: "Go to slide {n}",
1083
+ chooseDate: "Choose date",
1084
+ previousMonth: "Previous month",
1085
+ nextMonth: "Next month",
1086
+ close: "Close",
1087
+ copy: "Copy",
1088
+ copied: "Copied",
1089
+ chooseFile: "Choose file",
1090
+ noFileChosen: "No file chosen",
1091
+ filesSelected: "{count} files selected",
1092
+ resizePanels: "Resize panels",
1093
+ search: "Search",
1094
+ alertError: "Error",
1095
+ alertWarning: "Warning",
1096
+ alertSuccess: "Success",
1097
+ alertInfo: "Information",
1098
+ alertNotice: "Notice",
1099
+ alertMessage: "Message",
1100
+ remove: "Remove",
1101
+ closeTab: "Close tab"
1102
+ },
1103
+ "../assets/locales/es.json": {
1104
+ valueMissing: "Este campo es obligatorio",
1105
+ badInput: "Introduzca un valor válido",
1106
+ typeMismatch: "Introduzca un valor con el formato correcto",
1107
+ patternMismatch: "Ajuste el valor al formato solicitado",
1108
+ rangeUnderflow: "El valor debe ser como mínimo {min}",
1109
+ rangeOverflow: "El valor debe ser como máximo {max}",
1110
+ stepMismatch: "El valor debe ser múltiplo de {step}",
1111
+ tooShort: "Debe ser como mínimo {min}",
1112
+ tooLong: "Debe ser como máximo {max}",
1113
+ increment: "Aumentar valor",
1114
+ decrement: "Disminuir valor",
1115
+ clear: "Borrar valor",
1116
+ today: "Hoy",
1117
+ time: "Hora",
1118
+ showPassword: "Mostrar contraseña",
1119
+ hidePassword: "Ocultar contraseña",
1120
+ previousSlide: "Diapositiva anterior",
1121
+ nextSlide: "Siguiente diapositiva",
1122
+ goToSlide: "Ir a la diapositiva {n}",
1123
+ chooseDate: "Elegir fecha",
1124
+ previousMonth: "Mes anterior",
1125
+ nextMonth: "Mes siguiente",
1126
+ close: "Cerrar",
1127
+ copy: "Copiar",
1128
+ copied: "Copiado",
1129
+ chooseFile: "Elegir archivo",
1130
+ noFileChosen: "Ningún archivo elegido",
1131
+ filesSelected: "{count} archivos seleccionados",
1132
+ resizePanels: "Cambiar el tamaño de los paneles",
1133
+ search: "Buscar",
1134
+ alertError: "Error",
1135
+ alertWarning: "Advertencia",
1136
+ alertSuccess: "Éxito",
1137
+ alertInfo: "Información",
1138
+ alertNotice: "Aviso",
1139
+ alertMessage: "Mensaje",
1140
+ remove: "Quitar",
1141
+ closeTab: "Cerrar pestaña"
1142
+ },
1143
+ "../assets/locales/fr.json": {
1144
+ valueMissing: "Ce champ est obligatoire",
1145
+ badInput: "Veuillez saisir une valeur valide",
1146
+ typeMismatch: "Veuillez saisir une valeur au format correct",
1147
+ patternMismatch: "Veuillez respecter le format demandé",
1148
+ rangeUnderflow: "La valeur doit être supérieure ou égale à {min}",
1149
+ rangeOverflow: "La valeur doit être inférieure ou égale à {max}",
1150
+ stepMismatch: "La valeur doit être un multiple de {step}",
1151
+ tooShort: "Doit être au moins {min}",
1152
+ tooLong: "Doit être au plus {max}",
1153
+ increment: "Augmenter la valeur",
1154
+ decrement: "Diminuer la valeur",
1155
+ clear: "Effacer la valeur",
1156
+ today: "Aujourd’hui",
1157
+ time: "Heure",
1158
+ showPassword: "Afficher le mot de passe",
1159
+ hidePassword: "Masquer le mot de passe",
1160
+ previousSlide: "Diapositive précédente",
1161
+ nextSlide: "Diapositive suivante",
1162
+ goToSlide: "Aller à la diapositive {n}",
1163
+ chooseDate: "Choisir une date",
1164
+ previousMonth: "Mois précédent",
1165
+ nextMonth: "Mois suivant",
1166
+ close: "Fermer",
1167
+ copy: "Copier",
1168
+ copied: "Copié",
1169
+ chooseFile: "Choisir un fichier",
1170
+ noFileChosen: "Aucun fichier choisi",
1171
+ filesSelected: "{count} fichiers sélectionnés",
1172
+ resizePanels: "Redimensionner les panneaux",
1173
+ search: "Rechercher",
1174
+ alertError: "Erreur",
1175
+ alertWarning: "Avertissement",
1176
+ alertSuccess: "Succès",
1177
+ alertInfo: "Information",
1178
+ alertNotice: "Avis",
1179
+ alertMessage: "Message",
1180
+ remove: "Supprimer",
1181
+ closeTab: "Fermer l'onglet"
1182
+ },
1183
+ "../assets/locales/id.json": {
1184
+ valueMissing: "Kolom ini wajib diisi",
1185
+ badInput: "Masukkan nilai yang valid",
1186
+ typeMismatch: "Masukkan nilai dengan format yang benar",
1187
+ patternMismatch: "Sesuaikan dengan format yang diminta",
1188
+ rangeUnderflow: "Nilai harus minimal {min}",
1189
+ rangeOverflow: "Nilai harus maksimal {max}",
1190
+ stepMismatch: "Nilai harus kelipatan dari {step}",
1191
+ tooShort: "Harus minimal {min}",
1192
+ tooLong: "Harus maksimal {max}",
1193
+ increment: "Tambah nilai",
1194
+ decrement: "Kurangi nilai",
1195
+ clear: "Hapus nilai",
1196
+ today: "Hari ini",
1197
+ time: "Waktu",
1198
+ showPassword: "Tampilkan kata sandi",
1199
+ hidePassword: "Sembunyikan kata sandi",
1200
+ previousSlide: "Slide sebelumnya",
1201
+ nextSlide: "Slide berikutnya",
1202
+ goToSlide: "Buka slide {n}",
1203
+ chooseDate: "Pilih tanggal",
1204
+ previousMonth: "Bulan sebelumnya",
1205
+ nextMonth: "Bulan berikutnya",
1206
+ close: "Tutup",
1207
+ copy: "Salin",
1208
+ copied: "Disalin",
1209
+ chooseFile: "Pilih berkas",
1210
+ noFileChosen: "Tidak ada berkas dipilih",
1211
+ filesSelected: "{count} berkas dipilih",
1212
+ resizePanels: "Ubah ukuran panel",
1213
+ search: "Cari",
1214
+ alertError: "Kesalahan",
1215
+ alertWarning: "Peringatan",
1216
+ alertSuccess: "Berhasil",
1217
+ alertInfo: "Informasi",
1218
+ alertNotice: "Pemberitahuan",
1219
+ alertMessage: "Pesan",
1220
+ remove: "Hapus",
1221
+ closeTab: "Tutup tab"
1222
+ },
1223
+ "../assets/locales/ja.json": {
1224
+ valueMissing: "この項目は必須です",
1225
+ badInput: "有効な値を入力してください",
1226
+ typeMismatch: "正しい形式の値を入力してください",
1227
+ patternMismatch: "指定された形式で入力してください",
1228
+ rangeUnderflow: "値は{min}以上である必要があります",
1229
+ rangeOverflow: "値は{max}以下である必要があります",
1230
+ stepMismatch: "値は{step}の倍数である必要があります",
1231
+ tooShort: "{min}以上である必要があります",
1232
+ tooLong: "{max}以下である必要があります",
1233
+ increment: "値を増やす",
1234
+ decrement: "値を減らす",
1235
+ clear: "値をクリア",
1236
+ today: "今日",
1237
+ time: "時刻",
1238
+ showPassword: "パスワードを表示",
1239
+ hidePassword: "パスワードを隠す",
1240
+ previousSlide: "前のスライド",
1241
+ nextSlide: "次のスライド",
1242
+ goToSlide: "スライド{n}に移動",
1243
+ chooseDate: "日付を選択",
1244
+ previousMonth: "前月",
1245
+ nextMonth: "翌月",
1246
+ close: "閉じる",
1247
+ copy: "コピー",
1248
+ copied: "コピーしました",
1249
+ chooseFile: "ファイルを選択",
1250
+ noFileChosen: "ファイルが選択されていません",
1251
+ filesSelected: "{count}個のファイルを選択しました",
1252
+ resizePanels: "パネルのサイズ変更",
1253
+ search: "検索",
1254
+ alertError: "エラー",
1255
+ alertWarning: "警告",
1256
+ alertSuccess: "完了",
1257
+ alertInfo: "お知らせ",
1258
+ alertNotice: "通知",
1259
+ alertMessage: "メッセージ",
1260
+ remove: "削除",
1261
+ closeTab: "タブを閉じる"
1262
+ },
1263
+ "../assets/locales/ko.json": {
1264
+ valueMissing: "필수 항목입니다",
1265
+ badInput: "올바른 값을 입력하세요",
1266
+ typeMismatch: "올바른 형식의 값을 입력하세요",
1267
+ patternMismatch: "요청된 형식에 맞게 입력하세요",
1268
+ rangeUnderflow: "값은 {min} 이상이어야 합니다",
1269
+ rangeOverflow: "값은 {max} 이하여야 합니다",
1270
+ stepMismatch: "값은 {step}의 배수여야 합니다",
1271
+ tooShort: "최소 {min} 이상이어야 합니다",
1272
+ tooLong: "최대 {max} 이하여야 합니다",
1273
+ increment: "값 증가",
1274
+ decrement: "값 감소",
1275
+ clear: "값 지우기",
1276
+ today: "오늘",
1277
+ time: "시간",
1278
+ showPassword: "비밀번호 표시",
1279
+ hidePassword: "비밀번호 숨기기",
1280
+ previousSlide: "이전 슬라이드",
1281
+ nextSlide: "다음 슬라이드",
1282
+ goToSlide: "{n}번 슬라이드로 이동",
1283
+ chooseDate: "날짜 선택",
1284
+ previousMonth: "이전 달",
1285
+ nextMonth: "다음 달",
1286
+ close: "닫기",
1287
+ copy: "복사",
1288
+ copied: "복사됨",
1289
+ chooseFile: "파일 선택",
1290
+ noFileChosen: "선택된 파일 없음",
1291
+ filesSelected: "{count}개 파일 선택됨",
1292
+ resizePanels: "패널 크기 조절",
1293
+ search: "검색",
1294
+ alertError: "오류",
1295
+ alertWarning: "경고",
1296
+ alertSuccess: "완료",
1297
+ alertInfo: "안내",
1298
+ alertNotice: "알림",
1299
+ alertMessage: "메시지",
1300
+ remove: "제거",
1301
+ closeTab: "탭 닫기"
1302
+ },
1303
+ "../assets/locales/pt-BR.json": {
1304
+ valueMissing: "Este campo é obrigatório",
1305
+ badInput: "Insira um valor válido",
1306
+ typeMismatch: "Insira um valor no formato correto",
1307
+ patternMismatch: "Siga o formato solicitado",
1308
+ rangeUnderflow: "O valor deve ser no mínimo {min}",
1309
+ rangeOverflow: "O valor deve ser no máximo {max}",
1310
+ stepMismatch: "O valor deve ser um múltiplo de {step}",
1311
+ tooShort: "Deve ser no mínimo {min}",
1312
+ tooLong: "Deve ser no máximo {max}",
1313
+ increment: "Aumentar valor",
1314
+ decrement: "Diminuir valor",
1315
+ clear: "Limpar valor",
1316
+ today: "Hoje",
1317
+ time: "Hora",
1318
+ showPassword: "Mostrar senha",
1319
+ hidePassword: "Ocultar senha",
1320
+ previousSlide: "Slide anterior",
1321
+ nextSlide: "Próximo slide",
1322
+ goToSlide: "Ir para o slide {n}",
1323
+ chooseDate: "Escolher data",
1324
+ previousMonth: "Mês anterior",
1325
+ nextMonth: "Próximo mês",
1326
+ close: "Fechar",
1327
+ copy: "Copiar",
1328
+ copied: "Copiado",
1329
+ chooseFile: "Escolher arquivo",
1330
+ noFileChosen: "Nenhum arquivo escolhido",
1331
+ filesSelected: "{count} arquivos selecionados",
1332
+ resizePanels: "Redimensionar painéis",
1333
+ search: "Pesquisar",
1334
+ alertError: "Erro",
1335
+ alertWarning: "Aviso",
1336
+ alertSuccess: "Sucesso",
1337
+ alertInfo: "Informação",
1338
+ alertNotice: "Nota",
1339
+ alertMessage: "Mensagem",
1340
+ remove: "Remover",
1341
+ closeTab: "Fechar aba"
1342
+ },
1343
+ "../assets/locales/ru.json": {
1344
+ valueMissing: "Это поле обязательно для заполнения",
1345
+ badInput: "Введите допустимое значение",
1346
+ typeMismatch: "Введите значение в правильном формате",
1347
+ patternMismatch: "Введите значение в требуемом формате",
1348
+ rangeUnderflow: "Значение должно быть не менее {min}",
1349
+ rangeOverflow: "Значение должно быть не более {max}",
1350
+ stepMismatch: "Значение должно быть кратно {step}",
1351
+ tooShort: "Должно быть не менее {min}",
1352
+ tooLong: "Должно быть не более {max}",
1353
+ increment: "Увеличить значение",
1354
+ decrement: "Уменьшить значение",
1355
+ clear: "Очистить значение",
1356
+ today: "Сегодня",
1357
+ time: "Время",
1358
+ showPassword: "Показать пароль",
1359
+ hidePassword: "Скрыть пароль",
1360
+ previousSlide: "Предыдущий слайд",
1361
+ nextSlide: "Следующий слайд",
1362
+ goToSlide: "Перейти к слайду {n}",
1363
+ chooseDate: "Выбрать дату",
1364
+ previousMonth: "Предыдущий месяц",
1365
+ nextMonth: "Следующий месяц",
1366
+ close: "Закрыть",
1367
+ copy: "Копировать",
1368
+ copied: "Скопировано",
1369
+ chooseFile: "Выбрать файл",
1370
+ noFileChosen: "Файл не выбран",
1371
+ filesSelected: "Выбрано файлов: {count}",
1372
+ resizePanels: "Изменить размер панелей",
1373
+ search: "Поиск",
1374
+ alertError: "Ошибка",
1375
+ alertWarning: "Предупреждение",
1376
+ alertSuccess: "Успешно",
1377
+ alertInfo: "Информация",
1378
+ alertNotice: "Уведомление",
1379
+ alertMessage: "Сообщение",
1380
+ remove: "Удалить",
1381
+ closeTab: "Закрыть вкладку"
1382
+ },
1383
+ "../assets/locales/th.json": {
1384
+ valueMissing: "จำเป็นต้องกรอกข้อมูลนี้",
1385
+ badInput: "กรุณากรอกค่าที่ถูกต้อง",
1386
+ typeMismatch: "กรุณากรอกค่าให้ถูกรูปแบบ",
1387
+ patternMismatch: "กรุณากรอกให้ตรงตามรูปแบบที่กำหนด",
1388
+ rangeUnderflow: "ค่าต้องมากกว่าหรือเท่ากับ {min}",
1389
+ rangeOverflow: "ค่าต้องน้อยกว่าหรือเท่ากับ {max}",
1390
+ stepMismatch: "ค่าต้องเป็นจำนวนทวีคูณของ {step}",
1391
+ tooShort: "ต้องมีอย่างน้อย {min}",
1392
+ tooLong: "ต้องไม่เกิน {max}",
1393
+ increment: "เพิ่มค่า",
1394
+ decrement: "ลดค่า",
1395
+ clear: "ล้างค่า",
1396
+ today: "วันนี้",
1397
+ time: "เวลา",
1398
+ showPassword: "แสดงรหัสผ่าน",
1399
+ hidePassword: "ซ่อนรหัสผ่าน",
1400
+ previousSlide: "สไลด์ก่อนหน้า",
1401
+ nextSlide: "สไลด์ถัดไป",
1402
+ goToSlide: "ไปที่สไลด์ที่ {n}",
1403
+ chooseDate: "เลือกวันที่",
1404
+ previousMonth: "เดือนก่อนหน้า",
1405
+ nextMonth: "เดือนถัดไป",
1406
+ close: "ปิด",
1407
+ copy: "คัดลอก",
1408
+ copied: "คัดลอกแล้ว",
1409
+ chooseFile: "เลือกไฟล์",
1410
+ noFileChosen: "ยังไม่ได้เลือกไฟล์",
1411
+ filesSelected: "เลือกแล้ว {count} ไฟล์",
1412
+ resizePanels: "ปรับขนาดแผง",
1413
+ search: "ค้นหา",
1414
+ alertError: "ข้อผิดพลาด",
1415
+ alertWarning: "คำเตือน",
1416
+ alertSuccess: "สำเร็จ",
1417
+ alertInfo: "ข้อมูล",
1418
+ alertNotice: "ประกาศ",
1419
+ alertMessage: "ข้อความ",
1420
+ remove: "ลบ",
1421
+ closeTab: "ปิดแท็บ"
1422
+ },
1423
+ "../assets/locales/vi.json": {
1424
+ valueMissing: "Trường này là bắt buộc",
1425
+ badInput: "Vui lòng nhập giá trị hợp lệ",
1426
+ typeMismatch: "Vui lòng nhập giá trị đúng định dạng",
1427
+ patternMismatch: "Vui lòng nhập đúng định dạng yêu cầu",
1428
+ rangeUnderflow: "Giá trị phải lớn hơn hoặc bằng {min}",
1429
+ rangeOverflow: "Giá trị phải nhỏ hơn hoặc bằng {max}",
1430
+ stepMismatch: "Giá trị phải là bội số của {step}",
1431
+ tooShort: "Phải lớn hơn hoặc bằng {min}",
1432
+ tooLong: "Phải nhỏ hơn hoặc bằng {max}",
1433
+ increment: "Tăng giá trị",
1434
+ decrement: "Giảm giá trị",
1435
+ clear: "Xóa giá trị",
1436
+ today: "Hôm nay",
1437
+ time: "Giờ",
1438
+ showPassword: "Hiện mật khẩu",
1439
+ hidePassword: "Ẩn mật khẩu",
1440
+ previousSlide: "Slide trước",
1441
+ nextSlide: "Slide sau",
1442
+ goToSlide: "Đi đến slide {n}",
1443
+ chooseDate: "Chọn ngày",
1444
+ previousMonth: "Tháng trước",
1445
+ nextMonth: "Tháng sau",
1446
+ close: "Đóng",
1447
+ copy: "Sao chép",
1448
+ copied: "Đã sao chép",
1449
+ chooseFile: "Chọn tệp",
1450
+ noFileChosen: "Chưa chọn tệp nào",
1451
+ filesSelected: "Đã chọn {count} tệp",
1452
+ resizePanels: "Thay đổi kích thước bảng",
1453
+ search: "Tìm kiếm",
1454
+ alertError: "Lỗi",
1455
+ alertWarning: "Cảnh báo",
1456
+ alertSuccess: "Thành công",
1457
+ alertInfo: "Thông tin",
1458
+ alertNotice: "Lưu ý",
1459
+ alertMessage: "Thông báo",
1460
+ remove: "Xóa",
1461
+ closeTab: "Đóng tab"
1462
+ },
1463
+ "../assets/locales/zh-CN.json": {
1464
+ valueMissing: "此项为必填项",
1465
+ badInput: "请输入有效的值",
1466
+ typeMismatch: "请输入正确格式的值",
1467
+ patternMismatch: "请按照要求的格式输入",
1468
+ rangeUnderflow: "值必须大于或等于{min}",
1469
+ rangeOverflow: "值必须小于或等于{max}",
1470
+ stepMismatch: "值必须是{step}的倍数",
1471
+ tooShort: "至少需要{min}",
1472
+ tooLong: "最多不能超过{max}",
1473
+ increment: "增加值",
1474
+ decrement: "减少值",
1475
+ clear: "清除值",
1476
+ today: "今天",
1477
+ time: "时间",
1478
+ showPassword: "显示密码",
1479
+ hidePassword: "隐藏密码",
1480
+ previousSlide: "上一张幻灯片",
1481
+ nextSlide: "下一张幻灯片",
1482
+ goToSlide: "转到幻灯片{n}",
1483
+ chooseDate: "选择日期",
1484
+ previousMonth: "上个月",
1485
+ nextMonth: "下个月",
1486
+ close: "关闭",
1487
+ copy: "复制",
1488
+ copied: "已复制",
1489
+ chooseFile: "选择文件",
1490
+ noFileChosen: "未选择文件",
1491
+ filesSelected: "已选择{count}个文件",
1492
+ resizePanels: "调整面板大小",
1493
+ search: "搜索",
1494
+ alertError: "错误",
1495
+ alertWarning: "警告",
1496
+ alertSuccess: "成功",
1497
+ alertInfo: "信息",
1498
+ alertNotice: "提示",
1499
+ alertMessage: "消息",
1500
+ remove: "移除",
1501
+ closeTab: "关闭标签页"
1502
+ },
1503
+ "../assets/locales/zh-TW.json": {
1504
+ valueMissing: "此欄位為必填",
1505
+ badInput: "請輸入有效的值",
1506
+ typeMismatch: "請輸入正確格式的值",
1507
+ patternMismatch: "請依照要求的格式輸入",
1508
+ rangeUnderflow: "值必須大於或等於{min}",
1509
+ rangeOverflow: "值必須小於或等於{max}",
1510
+ stepMismatch: "值必須是{step}的倍數",
1511
+ tooShort: "至少需要{min}",
1512
+ tooLong: "最多不能超過{max}",
1513
+ increment: "增加值",
1514
+ decrement: "減少值",
1515
+ clear: "清除值",
1516
+ today: "今天",
1517
+ time: "時間",
1518
+ showPassword: "顯示密碼",
1519
+ hidePassword: "隱藏密碼",
1520
+ previousSlide: "上一張投影片",
1521
+ nextSlide: "下一張投影片",
1522
+ goToSlide: "前往投影片{n}",
1523
+ chooseDate: "選擇日期",
1524
+ previousMonth: "上個月",
1525
+ nextMonth: "下個月",
1526
+ close: "關閉",
1527
+ copy: "複製",
1528
+ copied: "已複製",
1529
+ chooseFile: "選擇檔案",
1530
+ noFileChosen: "未選擇檔案",
1531
+ filesSelected: "已選擇{count}個檔案",
1532
+ resizePanels: "調整面板大小",
1533
+ search: "搜尋",
1534
+ alertError: "錯誤",
1535
+ alertWarning: "警告",
1536
+ alertSuccess: "成功",
1537
+ alertInfo: "資訊",
1538
+ alertNotice: "提示",
1539
+ alertMessage: "訊息",
1540
+ remove: "移除",
1541
+ closeTab: "關閉分頁"
1542
+ }
1543
+ })).map(([e, t]) => [(e.split("/").pop()?.replace(".json", "") || "").toLowerCase(), t])), x = /* @__PURE__ */ new Map();
1544
+ function S() {
1545
+ return typeof document < "u" && document.documentElement?.lang ? document.documentElement.lang : typeof window < "u" && typeof navigator < "u" && navigator.language ? navigator.language : "en";
1546
+ }
1547
+ var C = S();
1548
+ function w(e) {
1549
+ let t = e.toLowerCase(), n = t.split("-")[0];
1550
+ return n === t ? [t, "en"] : [
1551
+ t,
1552
+ n,
1553
+ "en"
1554
+ ];
1555
+ }
1556
+ function T(e, t) {
1557
+ return t ? e.replace(/\{(\w+)\}/g, (e, n) => t[n] == null ? `{${n}}` : String(t[n])) : e;
1558
+ }
1559
+ function E(e, t) {
1560
+ for (let n of w(e)) {
1561
+ let e = x.get(n)?.[t] ?? b.get(n)?.[t];
1562
+ if (e) return e;
1563
+ }
1564
+ return b.get("en")[t];
1565
+ }
1566
+ var D = /* @__PURE__ */ new Map(), O = class {
1567
+ constructor() {}
1568
+ static set(e) {
1569
+ C = e;
1570
+ }
1571
+ static get() {
1572
+ return C;
1573
+ }
1574
+ static register(e, t) {
1575
+ let n = e.toLowerCase(), r = x.get(n) ?? b.get(n) ?? b.get("en");
1576
+ x.set(n, {
1577
+ ...r,
1578
+ ...t
1579
+ });
1580
+ }
1581
+ static getValue(e, t) {
1582
+ return T(E(C, e), t);
1583
+ }
1584
+ static namespace(e) {
1585
+ return {
1586
+ name: e,
1587
+ register(t, n) {
1588
+ let r = D.get(e) ?? /* @__PURE__ */ new Map(), i = t.toLowerCase();
1589
+ r.set(i, {
1590
+ ...r.get(i),
1591
+ ...n
1592
+ }), D.set(e, r);
1593
+ },
1594
+ text(t, n) {
1595
+ let r = D.get(e);
1596
+ for (let e of w(C)) {
1597
+ let i = r?.get(e)?.[t];
1598
+ if (i) return T(i, n);
1599
+ }
1600
+ return t;
1601
+ }
1602
+ };
1603
+ }
1604
+ }.namespace("flex-table");
1605
+ O.register("en", {
1606
+ showHiddenColumns: "Show hidden column(s)",
1607
+ columnMenu: "Column menu",
1608
+ cellActions: "Cell actions",
1609
+ noColumnsDefined: "No columns defined",
1610
+ addCommentPlaceholder: "Add a comment… (Ctrl+Enter to save)",
1611
+ cancel: "Cancel",
1612
+ save: "Save",
1613
+ clear: "Clear",
1614
+ blankCells: "Blank cells",
1615
+ emptyOnly: "Empty only",
1616
+ nonEmptyOnly: "Non-empty only",
1617
+ blankAll: "— All —",
1618
+ all: "All",
1619
+ contains: "Contains",
1620
+ startsWith: "Starts with",
1621
+ endsWith: "Ends with",
1622
+ wildcard: "Wildcard",
1623
+ searchPlaceholder: "Search...",
1624
+ valuePlaceholder: "Value",
1625
+ fromPlaceholder: "From",
1626
+ toPlaceholder: "To",
1627
+ findPlaceholder: "Find...",
1628
+ findPrevious: "Previous (Shift+Enter)",
1629
+ findNext: "Next (Enter)",
1630
+ matchCase: "Match case",
1631
+ wholeCell: "Whole cell",
1632
+ closeFind: "Close (Escape)",
1633
+ replaceWithPlaceholder: "Replace with...",
1634
+ replace: "Replace",
1635
+ replaceAll: "Replace all"
1636
+ }), O.register("ko", {
1637
+ showHiddenColumns: "숨긴 열 보기",
1638
+ columnMenu: "열 메뉴",
1639
+ cellActions: "셀 작업",
1640
+ noColumnsDefined: "정의된 열이 없습니다",
1641
+ addCommentPlaceholder: "메모 입력… (Ctrl+Enter 로 저장)",
1642
+ cancel: "취소",
1643
+ save: "저장",
1644
+ clear: "지우기",
1645
+ blankCells: "빈 셀",
1646
+ emptyOnly: "빈 값만",
1647
+ nonEmptyOnly: "빈 값 제외",
1648
+ blankAll: "— 전체 —",
1649
+ all: "전체",
1650
+ contains: "포함",
1651
+ startsWith: "시작 문자",
1652
+ endsWith: "끝 문자",
1653
+ wildcard: "와일드카드",
1654
+ searchPlaceholder: "검색...",
1655
+ valuePlaceholder: "값",
1656
+ fromPlaceholder: "시작",
1657
+ toPlaceholder: "끝",
1658
+ findPlaceholder: "찾기...",
1659
+ findPrevious: "이전 (Shift+Enter)",
1660
+ findNext: "다음 (Enter)",
1661
+ matchCase: "대/소문자 구분",
1662
+ wholeCell: "셀 전체 일치",
1663
+ closeFind: "닫기 (Escape)",
1664
+ replaceWithPlaceholder: "바꿀 내용...",
1665
+ replace: "바꾸기",
1666
+ replaceAll: "모두 바꾸기"
1667
+ });
1668
+ var k = (e) => O.text(e);
1669
+ //#endregion
939
1670
  //#region src/core/selection.ts
940
- function b(e) {
1671
+ function ee(e) {
941
1672
  return {
942
1673
  startRow: Math.min(e.startRow, e.endRow),
943
1674
  startCol: Math.min(e.startCol, e.endCol),
@@ -945,7 +1676,7 @@ function b(e) {
945
1676
  endCol: Math.max(e.startCol, e.endCol)
946
1677
  };
947
1678
  }
948
- var x = class {
1679
+ var te = class {
949
1680
  constructor() {
950
1681
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
951
1682
  }
@@ -972,7 +1703,7 @@ var x = class {
972
1703
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
973
1704
  row: e,
974
1705
  col: t
975
- }, this.rangeAnchor && (this.range = b({
1706
+ }, this.rangeAnchor && (this.range = ee({
976
1707
  startRow: this.rangeAnchor.row,
977
1708
  startCol: this.rangeAnchor.col,
978
1709
  endRow: e,
@@ -1043,7 +1774,7 @@ var x = class {
1043
1774
  shiftMoveRight() {
1044
1775
  return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
1045
1776
  }
1046
- }, S = class {
1777
+ }, ne = class {
1047
1778
  constructor() {
1048
1779
  this.current = null;
1049
1780
  }
@@ -1064,7 +1795,7 @@ var x = class {
1064
1795
  let e = this.current;
1065
1796
  return this.current = null, e;
1066
1797
  }
1067
- }, C = class {
1798
+ }, A = class {
1068
1799
  constructor() {
1069
1800
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
1070
1801
  }
@@ -1125,7 +1856,7 @@ var x = class {
1125
1856
  };
1126
1857
  //#endregion
1127
1858
  //#region src/core/filtering.ts
1128
- function w(e, t, n) {
1859
+ function j(e, t, n) {
1129
1860
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
1130
1861
  let r = [];
1131
1862
  for (let i = 0; i < e.length; i++) {
@@ -1144,9 +1875,9 @@ function w(e, t, n) {
1144
1875
  }
1145
1876
  //#endregion
1146
1877
  //#region src/core/undo.ts
1147
- var T = 100, E = class {
1878
+ var re = 100, M = class {
1148
1879
  constructor() {
1149
- this._undoStack = [], this._redoStack = [], this._maxSize = T;
1880
+ this._undoStack = [], this._redoStack = [], this._maxSize = re;
1150
1881
  }
1151
1882
  get maxSize() {
1152
1883
  return this._maxSize;
@@ -1183,7 +1914,7 @@ var T = 100, E = class {
1183
1914
  };
1184
1915
  //#endregion
1185
1916
  //#region src/clipboard/clipboard.ts
1186
- function D(e, t, n) {
1917
+ function ie(e, t, n) {
1187
1918
  let r = [];
1188
1919
  for (let i = n.startRow; i <= n.endRow; i++) {
1189
1920
  let a = e[i], o = [];
@@ -1195,7 +1926,7 @@ function D(e, t, n) {
1195
1926
  }
1196
1927
  return r.join("\n");
1197
1928
  }
1198
- function O(e) {
1929
+ function N(e) {
1199
1930
  let t = e.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), n = [], r = [], i = 0, a = t.length;
1200
1931
  for (; i <= a;) {
1201
1932
  if (i === a) {
@@ -1225,7 +1956,7 @@ function O(e) {
1225
1956
  }
1226
1957
  return n;
1227
1958
  }
1228
- function k(e, t) {
1959
+ function P(e, t) {
1229
1960
  if (e === "") return null;
1230
1961
  switch (t.type) {
1231
1962
  case "number": {
@@ -1238,7 +1969,7 @@ function k(e, t) {
1238
1969
  }
1239
1970
  //#endregion
1240
1971
  //#region src/export/xlsx-writer.ts
1241
- var A = (() => {
1972
+ var ae = (() => {
1242
1973
  let e = /* @__PURE__ */ new Uint32Array(256);
1243
1974
  for (let t = 0; t < 256; t++) {
1244
1975
  let n = t;
@@ -1247,56 +1978,56 @@ var A = (() => {
1247
1978
  }
1248
1979
  return e;
1249
1980
  })();
1250
- function j(e) {
1981
+ function oe(e) {
1251
1982
  let t = 4294967295;
1252
- for (let n = 0; n < e.length; n++) t = A[(t ^ e[n]) & 255] ^ t >>> 8;
1983
+ for (let n = 0; n < e.length; n++) t = ae[(t ^ e[n]) & 255] ^ t >>> 8;
1253
1984
  return (t ^ 4294967295) >>> 0;
1254
1985
  }
1255
- var M = new TextEncoder();
1256
- function ee(e) {
1986
+ var F = new TextEncoder();
1987
+ function se(e) {
1257
1988
  let t = [], n = [], r = 0;
1258
1989
  for (let i of e) {
1259
- let e = M.encode(i.name), a = j(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1990
+ let e = F.encode(i.name), a = oe(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1260
1991
  c.setUint32(0, 67324752, !0), c.setUint16(4, 20, !0), c.setUint16(6, 0, !0), c.setUint16(8, 0, !0), c.setUint16(10, 0, !0), c.setUint16(12, 33, !0), c.setUint32(14, a, !0), c.setUint32(18, o, !0), c.setUint32(22, o, !0), c.setUint16(26, e.length, !0), c.setUint16(28, 0, !0), new Uint8Array(s, 30).set(e), t.push(new Uint8Array(s)), t.push(i.data);
1261
1992
  let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
1262
1993
  u.setUint32(0, 33639248, !0), u.setUint16(4, 20, !0), u.setUint16(6, 20, !0), u.setUint16(8, 0, !0), u.setUint16(10, 0, !0), u.setUint16(12, 0, !0), u.setUint16(14, 33, !0), u.setUint32(16, a, !0), u.setUint32(20, o, !0), u.setUint32(24, o, !0), u.setUint16(28, e.length, !0), u.setUint16(30, 0, !0), u.setUint16(32, 0, !0), u.setUint16(34, 0, !0), u.setUint16(36, 0, !0), u.setUint32(38, 0, !0), u.setUint32(42, r, !0), new Uint8Array(l, 46).set(e), n.push(new Uint8Array(l)), r += 30 + e.length + o;
1263
1994
  }
1264
- let i = N(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1265
- return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), N([
1995
+ let i = I(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1996
+ return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), I([
1266
1997
  ...t,
1267
1998
  i,
1268
1999
  new Uint8Array(a)
1269
2000
  ]);
1270
2001
  }
1271
- function N(e) {
2002
+ function I(e) {
1272
2003
  let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
1273
2004
  for (let t of e) n.set(t, r), r += t.length;
1274
2005
  return n;
1275
2006
  }
1276
- function P(e) {
2007
+ function L(e) {
1277
2008
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1278
2009
  }
1279
- function F(e) {
2010
+ function ce(e) {
1280
2011
  let t = "";
1281
2012
  for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1282
2013
  return t;
1283
2014
  }
1284
- function I(e, t) {
1285
- return F(t) + (e + 1);
2015
+ function R(e, t) {
2016
+ return ce(t) + (e + 1);
1286
2017
  }
1287
- function te(e) {
2018
+ function le(e) {
1288
2019
  let t = Date.UTC(1899, 11, 30);
1289
2020
  return (e.getTime() - t) / 864e5;
1290
2021
  }
1291
- var ne = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", re = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", ie = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\n <sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>\n</workbook>", ae = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n</Relationships>", oe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n <numFmts count=\"1\"><numFmt numFmtId=\"164\" formatCode=\"yyyy-mm-dd\"/></numFmts>\n <fonts count=\"2\">\n <font><sz val=\"11\"/><name val=\"Calibri\"/></font>\n <font><sz val=\"11\"/><b/><name val=\"Calibri\"/></font>\n </fonts>\n <fills count=\"2\">\n <fill><patternFill patternType=\"none\"/></fill>\n <fill><patternFill patternType=\"gray125\"/></fill>\n </fills>\n <borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>\n <cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>\n <cellXfs count=\"3\">\n <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>\n <xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>\n <xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>\n </cellXfs>\n</styleSheet>";
1292
- function se(e, t) {
1293
- let n = [], r = t.map((e, t) => `<c r="${I(0, t)}" t="str" s="2"><v>${P(e.header)}</v></c>`);
2022
+ var ue = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", de = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", fe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\n <sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>\n</workbook>", z = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n</Relationships>", B = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n <numFmts count=\"1\"><numFmt numFmtId=\"164\" formatCode=\"yyyy-mm-dd\"/></numFmts>\n <fonts count=\"2\">\n <font><sz val=\"11\"/><name val=\"Calibri\"/></font>\n <font><sz val=\"11\"/><b/><name val=\"Calibri\"/></font>\n </fonts>\n <fills count=\"2\">\n <fill><patternFill patternType=\"none\"/></fill>\n <fill><patternFill patternType=\"gray125\"/></fill>\n </fills>\n <borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>\n <cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>\n <cellXfs count=\"3\">\n <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>\n <xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>\n <xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>\n </cellXfs>\n</styleSheet>";
2023
+ function V(e, t) {
2024
+ let n = [], r = t.map((e, t) => `<c r="${R(0, t)}" t="str" s="2"><v>${L(e.header)}</v></c>`);
1294
2025
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1295
2026
  let i = t.map((t, n) => {
1296
- let i = I(r + 1, n), a = e[t.key];
2027
+ let i = R(r + 1, n), a = e[t.key];
1297
2028
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1298
2029
  let o = t.type ?? "text";
1299
- return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${te(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${P(String(a))}</v></c>`;
2030
+ return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${le(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${L(String(a))}</v></c>`;
1300
2031
  });
1301
2032
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1302
2033
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -1304,55 +2035,55 @@ function se(e, t) {
1304
2035
  <sheetData>${n.join("")}</sheetData>
1305
2036
  </worksheet>`;
1306
2037
  }
1307
- function ce(e, t) {
1308
- let n = se(e, t);
1309
- return ee([
2038
+ function pe(e, t) {
2039
+ let n = V(e, t);
2040
+ return se([
1310
2041
  {
1311
2042
  name: "[Content_Types].xml",
1312
- data: M.encode(ne)
2043
+ data: F.encode(ue)
1313
2044
  },
1314
2045
  {
1315
2046
  name: "_rels/.rels",
1316
- data: M.encode(re)
2047
+ data: F.encode(de)
1317
2048
  },
1318
2049
  {
1319
2050
  name: "xl/workbook.xml",
1320
- data: M.encode(ie)
2051
+ data: F.encode(fe)
1321
2052
  },
1322
2053
  {
1323
2054
  name: "xl/_rels/workbook.xml.rels",
1324
- data: M.encode(ae)
2055
+ data: F.encode(z)
1325
2056
  },
1326
2057
  {
1327
2058
  name: "xl/worksheets/sheet1.xml",
1328
- data: M.encode(n)
2059
+ data: F.encode(n)
1329
2060
  },
1330
2061
  {
1331
2062
  name: "xl/styles.xml",
1332
- data: M.encode(oe)
2063
+ data: F.encode(B)
1333
2064
  }
1334
2065
  ]);
1335
2066
  }
1336
2067
  //#endregion
1337
2068
  //#region src/export/export.ts
1338
- function L(e, t, n) {
2069
+ function H(e, t, n) {
1339
2070
  switch (n) {
1340
- case "csv": return z(e, t, ",");
1341
- case "tsv": return z(e, t, " ");
1342
- case "json": return V(e, t);
1343
- case "xlsx": return ce(e, t);
2071
+ case "csv": return U(e, t, ",");
2072
+ case "tsv": return U(e, t, " ");
2073
+ case "json": return he(e, t);
2074
+ case "xlsx": return pe(e, t);
1344
2075
  }
1345
2076
  }
1346
- function R(e, t) {
2077
+ function me(e, t) {
1347
2078
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
1348
2079
  }
1349
- function z(e, t, n) {
1350
- return [t.map((e) => B(e.header, n)).join(n), ...e.map((e) => t.map((t) => B(R(e[t.key], t), n)).join(n))].join("\n");
2080
+ function U(e, t, n) {
2081
+ return [t.map((e) => W(e.header, n)).join(n), ...e.map((e) => t.map((t) => W(me(e[t.key], t), n)).join(n))].join("\n");
1351
2082
  }
1352
- function B(e, t) {
2083
+ function W(e, t) {
1353
2084
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
1354
2085
  }
1355
- function V(e, t) {
2086
+ function he(e, t) {
1356
2087
  let n = e.map((e) => {
1357
2088
  let n = {};
1358
2089
  for (let r of t) {
@@ -1363,35 +2094,35 @@ function V(e, t) {
1363
2094
  });
1364
2095
  return JSON.stringify(n, null, 2);
1365
2096
  }
1366
- function H(e, t, n) {
2097
+ function ge(e, t, n) {
1367
2098
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
1368
2099
  a.href = i, a.download = t, a.style.display = "none", document.body.appendChild(a), a.click(), document.body.removeChild(a), setTimeout(() => URL.revokeObjectURL(i), 100);
1369
2100
  }
1370
- var U = {
2101
+ var _e = {
1371
2102
  csv: "text/csv;charset=utf-8",
1372
2103
  tsv: "text/tab-separated-values;charset=utf-8",
1373
2104
  json: "application/json;charset=utf-8",
1374
2105
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1375
- }, W = {
2106
+ }, ve = {
1376
2107
  csv: ".csv",
1377
2108
  tsv: ".tsv",
1378
2109
  json: ".json",
1379
2110
  xlsx: ".xlsx"
1380
2111
  };
1381
- function le(e) {
1382
- return U[e];
2112
+ function ye(e) {
2113
+ return _e[e];
1383
2114
  }
1384
- function ue(e) {
1385
- return W[e];
2115
+ function be(e) {
2116
+ return ve[e];
1386
2117
  }
1387
2118
  //#endregion
1388
2119
  //#region src/export/xlsx-reader.ts
1389
- function de(e) {
2120
+ function xe(e) {
1390
2121
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
1391
2122
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
1392
2123
  }
1393
- function fe(e) {
1394
- let t = de(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
2124
+ function Se(e) {
2125
+ let t = xe(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
1395
2126
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
1396
2127
  let t = e.getUint16(o + 10, !0), n = e.getUint32(o + 20, !0), r = e.getUint32(o + 24, !0), s = e.getUint16(o + 28, !0), c = e.getUint16(o + 30, !0), l = e.getUint16(o + 32, !0), u = e.getUint32(o + 42, !0), d = i.decode(new Uint8Array(e.buffer, o + 46, s));
1397
2128
  a.push({
@@ -1404,7 +2135,7 @@ function fe(e) {
1404
2135
  }
1405
2136
  return a;
1406
2137
  }
1407
- async function pe(e) {
2138
+ async function Ce(e) {
1408
2139
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
1409
2140
  n.write(e), n.close();
1410
2141
  let i = [];
@@ -1417,32 +2148,32 @@ async function pe(e) {
1417
2148
  for (let e of i) o.set(e, s), s += e.length;
1418
2149
  return o;
1419
2150
  }
1420
- async function me(e, t) {
2151
+ async function we(e, t) {
1421
2152
  let n = t.localHeaderOffset, r = e.getUint16(n + 26, !0), i = e.getUint16(n + 28, !0), a = n + 30 + r + i, o = new Uint8Array(e.buffer, a, t.compressedSize);
1422
2153
  if (t.compressionMethod === 0) return o.slice();
1423
- if (t.compressionMethod === 8) return pe(o);
2154
+ if (t.compressionMethod === 8) return Ce(o);
1424
2155
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
1425
2156
  }
1426
- async function he(e) {
1427
- let t = new DataView(e), n = fe(t), r = /* @__PURE__ */ new Map();
1428
- for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await me(t, e));
2157
+ async function Te(e) {
2158
+ let t = new DataView(e), n = Se(t), r = /* @__PURE__ */ new Map();
2159
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await we(t, e));
1429
2160
  return r;
1430
2161
  }
1431
- var ge = new TextDecoder("utf-8");
2162
+ var Ee = new TextDecoder("utf-8");
1432
2163
  function G(e) {
1433
- let t = ge.decode(e);
2164
+ let t = Ee.decode(e);
1434
2165
  return new DOMParser().parseFromString(t, "application/xml");
1435
2166
  }
1436
- function _e(e) {
2167
+ function De(e) {
1437
2168
  if (!e) return [];
1438
2169
  let t = G(e);
1439
2170
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
1440
2171
  }
1441
- function ve(e) {
2172
+ function Oe(e) {
1442
2173
  let t = (e - 1) * 864e5 + Date.UTC(1899, 11, 30);
1443
2174
  return new Date(t).toISOString().slice(0, 10);
1444
2175
  }
1445
- function ye(e, t) {
2176
+ function ke(e, t) {
1446
2177
  let n = G(e).querySelectorAll("row");
1447
2178
  if (n.length === 0) return [];
1448
2179
  let r = 0, i = /* @__PURE__ */ new Map();
@@ -1450,7 +2181,7 @@ function ye(e, t) {
1450
2181
  let n = parseInt(e.getAttribute("r") ?? "1", 10) - 1, a = /* @__PURE__ */ new Map();
1451
2182
  i.set(n, a);
1452
2183
  for (let n of e.querySelectorAll("c")) {
1453
- let e = be(n.getAttribute("r") ?? "");
2184
+ let e = Ae(n.getAttribute("r") ?? "");
1454
2185
  e > r && (r = e);
1455
2186
  let i = n.getAttribute("t") ?? "", o = n.getAttribute("s") ?? "", s = n.querySelector("v")?.textContent ?? "", c = n.querySelector("is > t")?.textContent ?? null, l;
1456
2187
  if (i === "s") l = t[parseInt(s, 10)] ?? "";
@@ -1459,7 +2190,7 @@ function ye(e, t) {
1459
2190
  else if (s === "") l = "";
1460
2191
  else {
1461
2192
  let e = parseFloat(s);
1462
- l = !isNaN(e) && o !== "" && parseInt(o, 10) > 0 && e >= 1 && e <= 73050 ? ve(e) : s;
2193
+ l = !isNaN(e) && o !== "" && parseInt(o, 10) > 0 && e >= 1 && e <= 73050 ? Oe(e) : s;
1463
2194
  }
1464
2195
  a.set(e, l);
1465
2196
  }
@@ -1473,13 +2204,13 @@ function ye(e, t) {
1473
2204
  }
1474
2205
  return o;
1475
2206
  }
1476
- function be(e) {
2207
+ function Ae(e) {
1477
2208
  let t = 0, n = 0;
1478
2209
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
1479
2210
  return t - 1;
1480
2211
  }
1481
- async function K(e) {
1482
- let t = await he(e), n = _e(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
2212
+ async function je(e) {
2213
+ let t = await Te(e), n = De(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1483
2214
  if (!r) {
1484
2215
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
1485
2216
  r = n;
@@ -1487,7 +2218,7 @@ async function K(e) {
1487
2218
  }
1488
2219
  }
1489
2220
  if (!r) throw Error("XLSX: No worksheet found");
1490
- let i = ye(r, n);
2221
+ let i = ke(r, n);
1491
2222
  return i.length === 0 ? {
1492
2223
  headers: [],
1493
2224
  rows: []
@@ -1497,8 +2228,8 @@ async function K(e) {
1497
2228
  };
1498
2229
  }
1499
2230
  //#endregion
1500
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
1501
- function q(e, t, n, r) {
2231
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
2232
+ function K(e, t, n, r) {
1502
2233
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
1503
2234
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
1504
2235
  else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
@@ -1506,16 +2237,16 @@ function q(e, t, n, r) {
1506
2237
  }
1507
2238
  //#endregion
1508
2239
  //#region src/flex-table.ts
1509
- var J = {
2240
+ var q = {
1510
2241
  eq: "=",
1511
2242
  neq: "≠",
1512
2243
  gt: ">",
1513
2244
  lt: "<",
1514
2245
  gte: "≥",
1515
2246
  lte: "≤"
1516
- }, Y = 120, X = 40, Z = 32, Q = 5, xe = 200, $ = class extends n {
2247
+ }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Me = 200, $ = class extends n {
1517
2248
  constructor(...e) {
1518
- super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new x(), this._editing = new S(), this._rowSelection = new C(), this._undo = new E(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._warnedUnconstrained = !1, this._onCommentPopupOutsideClick = () => {
2249
+ super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new te(), this._editing = new ne(), this._rowSelection = new A(), this._undo = new M(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._warnedUnconstrained = !1, this._onCommentPopupOutsideClick = () => {
1519
2250
  this._commitCommentPopup();
1520
2251
  }, this._invalidCells = /* @__PURE__ */ new Map(), this._textFilterState = /* @__PURE__ */ new Map(), this._numberFilterState = /* @__PURE__ */ new Map(), this._dateFilterState = /* @__PURE__ */ new Map(), this._emptyFilterState = /* @__PURE__ */ new Map();
1521
2252
  }
@@ -1880,12 +2611,12 @@ var J = {
1880
2611
  if (!t) return "";
1881
2612
  let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
1882
2613
  for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
1883
- return L(r, n, e);
2614
+ return H(r, n, e);
1884
2615
  }
1885
- return L(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2616
+ return H(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
1886
2617
  }
1887
2618
  exportToFile(e, t) {
1888
- H(this.exportToString(e), t ?? `export${ue(e)}`, le(e));
2619
+ ge(this.exportToString(e), t ?? `export${be(e)}`, ye(e));
1889
2620
  }
1890
2621
  setComment(e, t, n) {
1891
2622
  let r = this.getComment(e, t);
@@ -1942,10 +2673,10 @@ var J = {
1942
2673
  async importFromFile(e) {
1943
2674
  let t = e.name.toLowerCase();
1944
2675
  if (t.endsWith(".xlsx")) {
1945
- let t = await K(await e.arrayBuffer());
2676
+ let t = await je(await e.arrayBuffer());
1946
2677
  this._applyImportedSheet(t);
1947
2678
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
1948
- let t = O(await e.text());
2679
+ let t = N(await e.text());
1949
2680
  this._applyImportedRows(t);
1950
2681
  } else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
1951
2682
  }
@@ -1956,7 +2687,7 @@ var J = {
1956
2687
  let a = t.get(e);
1957
2688
  if (!a) return;
1958
2689
  let o = this.columns.find((e) => e.key === a);
1959
- r[a] = o ? k(n[i] ?? "", o) : n[i] ?? null;
2690
+ r[a] = o ? P(n[i] ?? "", o) : n[i] ?? null;
1960
2691
  }), r;
1961
2692
  }), r = [...this.data];
1962
2693
  this.data = n, this._undo.push({
@@ -1981,7 +2712,7 @@ var J = {
1981
2712
  let a = n.get(t);
1982
2713
  if (!a) return;
1983
2714
  let o = this.columns.find((e) => e.key === a);
1984
- r[a] = o ? k(e[i] ?? "", o) : e[i] ?? null;
2715
+ r[a] = o ? P(e[i] ?? "", o) : e[i] ?? null;
1985
2716
  }), r;
1986
2717
  }), i = [...this.data];
1987
2718
  this.data = r, this._undo.push({
@@ -2034,8 +2765,8 @@ var J = {
2034
2765
  return this._columnWidths.get(e);
2035
2766
  }
2036
2767
  _getColWidth(e) {
2037
- let t = this._columnWidths.get(e.key) ?? e.width ?? Y;
2038
- return Math.max(t, e.minWidth ?? X);
2768
+ let t = this._columnWidths.get(e.key) ?? e.width ?? J;
2769
+ return Math.max(t, e.minWidth ?? Y);
2039
2770
  }
2040
2771
  get headerHeight() {
2041
2772
  return this.rowHeight + 8;
@@ -2115,7 +2846,7 @@ var J = {
2115
2846
  (!(e.size <= 2 && !e.has("data") && !e.has("columns") && !e.has("_openFilterKey") && !e.has("_editingCell") && !e.has("_activeCell") && (e.has("_scrollTop") || e.has("_scrollLeft"))) || this._viewDirty) && (this._recomputeView(), this._viewDirty = !1), this._updateColOffsets(), this._selection.setDimensions(this._visibleRowCount, this.visibleColumns.length), this._rowSelection.setRowCount(this._visibleRowCount);
2116
2847
  }
2117
2848
  updated(e) {
2118
- this._focusEditor(), this._adjustFilterDropdown(), e.has("stylesheets") && this._syncStylesheets();
2849
+ this._focusEditor(), this._adjustFilterDropdown(), e.has("_headerMenu") && this._keepMenuInView(".ft-header-menu"), e.has("_bodyContextMenu") && this._bodyContextMenu && (this._keepMenuInView(".ft-body-context-menu"), this.shadowRoot?.querySelector(".ft-body-context-menu [role=\"menuitem\"]")?.focus()), e.has("stylesheets") && this._syncStylesheets();
2119
2850
  let t = String(this._visibleRowCount), n = String(this.visibleColumns.length);
2120
2851
  if (this.getAttribute("aria-rowcount") !== t && this.setAttribute("aria-rowcount", t), this.getAttribute("aria-colcount") !== n && this.setAttribute("aria-colcount", n), this.loading ? this.getAttribute("aria-busy") !== "true" && this.setAttribute("aria-busy", "true") : this.hasAttribute("aria-busy") && this.removeAttribute("aria-busy"), e.has("_commentPopup") && this._commentPopup) {
2121
2852
  let e = this.shadowRoot?.querySelector(".ft-comment-popup textarea");
@@ -2127,7 +2858,7 @@ var J = {
2127
2858
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
2128
2859
  return;
2129
2860
  }
2130
- if (this._filteredIndices = w(this.data, this._filters, (e, t, n) => {
2861
+ if (this._filteredIndices = j(this.data, this._filters, (e, t, n) => {
2131
2862
  this.dispatchEvent(new CustomEvent("filter-error", {
2132
2863
  detail: {
2133
2864
  error: e,
@@ -2157,7 +2888,7 @@ var J = {
2157
2888
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2158
2889
  }
2159
2890
  _warnIfUnconstrained() {
2160
- this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < xe || this.scrollHeight > this.clientHeight + 1 || (this._warnedUnconstrained = !0, console.warn(`[@iyulab/flex-table] ${this._visibleRowCount} rows but the host has no height constraint — it grew to fit every row, so virtual scrolling is off and all rows are rendered. Give the host a height (e.g. height: 400px, or flex: 1 1 auto with min-height: 0 inside a sized parent) so it becomes the scroll container.`));
2891
+ this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Me || this.scrollHeight > this.clientHeight + 1 || (this._warnedUnconstrained = !0, console.warn(`[@iyulab/flex-table] ${this._visibleRowCount} rows but the host has no height constraint — it grew to fit every row, so virtual scrolling is off and all rows are rendered. Give the host a height (e.g. height: 400px, or flex: 1 1 auto with min-height: 0 inside a sized parent) so it becomes the scroll container.`));
2161
2892
  }
2162
2893
  _onScroll() {
2163
2894
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -2287,7 +3018,7 @@ var J = {
2287
3018
  }
2288
3019
  let t = this.shadowRoot?.querySelector(".ft-editor");
2289
3020
  if (t) {
2290
- let n = k(t.value, e);
3021
+ let n = P(t.value, e);
2291
3022
  this._applyEdit(n);
2292
3023
  } else this._cancelEdit();
2293
3024
  }
@@ -2481,17 +3212,21 @@ var J = {
2481
3212
  if (!e.altKey || !this._activeCell || e.key !== "ArrowLeft" && e.key !== "ArrowRight") return !1;
2482
3213
  e.preventDefault();
2483
3214
  let n = t[this._activeCell.col];
2484
- if (!n) return !0;
2485
- let r = this._columnWidths.get(n.key) ?? n.width ?? Y, i = e.key === "ArrowRight" ? 20 : -20, a = n.minWidth ?? X, o = Math.max(a, r + i);
2486
- return this._columnWidths.set(n.key, o), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
3215
+ return n && this._resizeColumnBy(n.key, e.key === "ArrowRight" ? X : -20), !0;
3216
+ }
3217
+ _resizeColumnBy(e, t) {
3218
+ let n = this.visibleColumns.findIndex((t) => t.key === e), r = this.visibleColumns[n];
3219
+ if (!r) return;
3220
+ let i = this._columnWidths.get(r.key) ?? r.width ?? J, a = r.minWidth ?? Y, o = Math.max(a, i + t);
3221
+ this._columnWidths.set(r.key, o), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
2487
3222
  detail: {
2488
- key: n.key,
3223
+ key: r.key,
2489
3224
  width: o,
2490
- colIndex: this._activeCell.col
3225
+ colIndex: n
2491
3226
  },
2492
3227
  bubbles: !0,
2493
3228
  composed: !0
2494
- })), !0;
3229
+ }));
2495
3230
  }
2496
3231
  _handleNavigation(e) {
2497
3232
  switch (e.key) {
@@ -2511,7 +3246,7 @@ var J = {
2511
3246
  async _handleCopy(e) {
2512
3247
  let t = this._selection.getEffectiveRange();
2513
3248
  if (!t) return;
2514
- let n = this.visibleColumns, r = D(this._sortedIndices.map((e) => this.data[e]), n, t);
3249
+ let n = this.visibleColumns, r = ie(this._sortedIndices.map((e) => this.data[e]), n, t);
2515
3250
  try {
2516
3251
  await navigator.clipboard.writeText(r);
2517
3252
  } catch (e) {
@@ -2537,7 +3272,7 @@ var J = {
2537
3272
  if (!this._activeCell) return;
2538
3273
  let e = await this._readClipboardText();
2539
3274
  if (e == null) return;
2540
- let t = O(e);
3275
+ let t = N(e);
2541
3276
  if (t.length === 0) return;
2542
3277
  let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
2543
3278
  if (r.length > 0 || n.length > 0) {
@@ -2595,7 +3330,7 @@ var J = {
2595
3330
  for (let a = 0; a < t[i].length; a++) {
2596
3331
  let s = e.col + a;
2597
3332
  if (s >= n.length) break;
2598
- let c = n[s], l = this.data[o][c.key], u = k(t[i][a], c);
3333
+ let c = n[s], l = this.data[o][c.key], u = P(t[i][a], c);
2599
3334
  this.data[o][c.key] = u, r.push({
2600
3335
  row: o,
2601
3336
  col: s,
@@ -2660,7 +3395,7 @@ var J = {
2660
3395
  for (let r = e.startCol + 1; r <= e.endCol; r++) {
2661
3396
  let e = t[r];
2662
3397
  if (!e || !this._isCellEditable(e)) continue;
2663
- let a = k(o == null ? "" : String(o), e);
3398
+ let a = P(o == null ? "" : String(o), e);
2664
3399
  n.push({
2665
3400
  row: i,
2666
3401
  key: e.key,
@@ -2819,7 +3554,7 @@ var J = {
2819
3554
  @click=${n ? (t) => this._onHeaderClick(t, e) : void 0}>
2820
3555
  ${x ? i`
2821
3556
  <button class="ft-hidden-col-indicator"
2822
- title="Show hidden column(s)"
3557
+ title=${k("showHiddenColumns")}
2823
3558
  @click=${(t) => {
2824
3559
  t.stopPropagation(), this._showHiddenBefore(e);
2825
3560
  }}>&#x276F;</button>
@@ -2827,34 +3562,39 @@ var J = {
2827
3562
  <span>${e.header}</span>
2828
3563
  ${r ? i`<span class="ft-sort-indicator">${r.direction === "asc" ? "▲" : "▼"}</span>` : ""}
2829
3564
  ${o >= 0 ? i`<span class="ft-sort-order">${o + 1}</span>` : ""}
2830
- ${this.showFilters ? i`
2831
- <button class="ft-filter-btn ${s ? "ft-filter-active" : ""}"
2832
- title="Filter"
2833
- aria-label=${`Filter ${e.header}`}
2834
- aria-expanded=${this._openFilterKey === e.key ? "true" : "false"}
2835
- @click=${(t) => this._onFilterBtnClick(t, e)}>
2836
- \u25BD
2837
- </button>
2838
- ` : ""}
3565
+ <button class="ft-column-menu-btn ${s ? "ft-filter-active" : ""}"
3566
+ type="button"
3567
+ title=${k("columnMenu")}
3568
+ aria-label=${`Column menu: ${e.header}`}
3569
+ aria-haspopup="menu"
3570
+ aria-expanded=${this._headerMenu?.key === e.key ? "true" : "false"}
3571
+ @mousedown=${(e) => e.stopPropagation()}
3572
+ @click=${(t) => this._onColumnMenuBtnClick(t, e)}>
3573
+ \u22EE
3574
+ </button>
2839
3575
  <div class="ft-resize-handle"
2840
3576
  @mousedown=${(e) => {
2841
3577
  e.stopPropagation(), this._wasHeaderDrag = !0, this._onResizeStart(e, t);
2842
3578
  }}
2843
- @dblclick=${(e) => this._onResizeAutoFit(e, t)}></div>
3579
+ @dblclick=${(t) => {
3580
+ t.preventDefault(), t.stopPropagation(), this._autoFitColumn(e.key);
3581
+ }}></div>
2844
3582
  </div>
2845
3583
  ${this._openFilterKey === e.key ? this._renderFilterDropdown(e) : ""}
2846
3584
  `;
2847
3585
  }
3586
+ _hiddenNeighbors(e) {
3587
+ let t = this.columns, n = t.findIndex((t) => t.key === e.key), r = [];
3588
+ for (let e = n - 1; e >= 0 && t[e].hidden; e--) r.push(t[e]);
3589
+ for (let e = n + 1; e < t.length && t[e].hidden; e++) r.push(t[e]);
3590
+ return r;
3591
+ }
2848
3592
  _onHeaderContextMenu(e, t) {
2849
- e.preventDefault();
2850
- let n = this.columns, r = n.findIndex((e) => e.key === t.key), i = [];
2851
- for (let e = r - 1; e >= 0 && n[e].hidden; e--) i.push(n[e]);
2852
- for (let e = r + 1; e < n.length && n[e].hidden; e++) i.push(n[e]);
2853
- this._headerMenu = {
3593
+ e.preventDefault(), this._openFilterKey = null, this._headerMenu = {
2854
3594
  key: t.key,
2855
3595
  x: e.clientX,
2856
3596
  y: e.clientY,
2857
- hiddenNeighbors: i
3597
+ hiddenNeighbors: this._hiddenNeighbors(t)
2858
3598
  }, this.dispatchEvent(new CustomEvent("header-context-menu", {
2859
3599
  detail: {
2860
3600
  key: t.key,
@@ -2868,118 +3608,139 @@ var J = {
2868
3608
  document.addEventListener("click", this._onDocumentClick, { once: !0 });
2869
3609
  });
2870
3610
  }
3611
+ _onColumnMenuBtnClick(e, t) {
3612
+ if (e.preventDefault(), e.stopPropagation(), this._headerMenu?.key === t.key) {
3613
+ this._headerMenu = null;
3614
+ return;
3615
+ }
3616
+ let n = e.currentTarget.getBoundingClientRect();
3617
+ this._openFilterKey = null, this._headerMenu = {
3618
+ key: t.key,
3619
+ x: n.left,
3620
+ y: n.bottom,
3621
+ hiddenNeighbors: this._hiddenNeighbors(t)
3622
+ }, requestAnimationFrame(() => {
3623
+ document.addEventListener("click", this._onDocumentClick, { once: !0 });
3624
+ }), this.updateComplete.then(() => this._menuItems()[0]?.focus());
3625
+ }
3626
+ _menuItems() {
3627
+ return Array.from(this.shadowRoot?.querySelectorAll(".ft-header-menu [role=\"menuitem\"]") ?? []);
3628
+ }
3629
+ _columnMenuButton(e) {
3630
+ let t = this.visibleColumns.findIndex((t) => t.key === e);
3631
+ return this.shadowRoot?.querySelector(`.ft-header-cell[data-col-index="${t}"] .ft-column-menu-btn`) ?? null;
3632
+ }
3633
+ _closeHeaderMenu(e) {
3634
+ let t = this._headerMenu?.key;
3635
+ this._headerMenu = null, e && t && this._columnMenuButton(t)?.focus();
3636
+ }
3637
+ _onHeaderMenuKeydown(e) {
3638
+ this._onMenuKeydown(e, ".ft-header-menu", (e) => this._closeHeaderMenu(e));
3639
+ }
3640
+ _onMenuKeydown(e, t, n) {
3641
+ let r = Array.from(this.shadowRoot?.querySelectorAll(`${t} [role="menuitem"]`) ?? []), i = r.indexOf(e.target), a = -1;
3642
+ switch (e.key) {
3643
+ case "ArrowDown":
3644
+ a = i < 0 ? 0 : (i + 1) % r.length;
3645
+ break;
3646
+ case "ArrowUp":
3647
+ a = i <= 0 ? r.length - 1 : i - 1;
3648
+ break;
3649
+ case "Home":
3650
+ a = 0;
3651
+ break;
3652
+ case "End":
3653
+ a = r.length - 1;
3654
+ break;
3655
+ case "Escape":
3656
+ e.preventDefault(), e.stopPropagation(), n(!0);
3657
+ return;
3658
+ case "Tab":
3659
+ n(!1);
3660
+ return;
3661
+ default: return;
3662
+ }
3663
+ e.preventDefault(), e.stopPropagation(), r[a]?.focus();
3664
+ }
3665
+ _openFilterFromMenu(e) {
3666
+ this._headerMenu = null, this._openFilterKey = e, requestAnimationFrame(() => {
3667
+ document.addEventListener("click", this._onDocumentClick, { once: !0 });
3668
+ }), this.updateComplete.then(() => {
3669
+ this.shadowRoot?.querySelector(".ft-filter-dropdown input, .ft-filter-dropdown select")?.focus();
3670
+ });
3671
+ }
2871
3672
  _showHiddenBefore(e) {
2872
3673
  let t = this.columns, n = t.findIndex((t) => t.key === e.key);
2873
3674
  for (let e = n - 1; e >= 0 && t[e].hidden; e--) this._setColumnHidden(t[e].key, !1);
2874
3675
  }
2875
3676
  _renderHeaderContextMenu() {
2876
3677
  if (!this._headerMenu) return a;
2877
- let { key: e, x: t, y: n, hiddenNeighbors: r } = this._headerMenu;
2878
- return this.columns.find((t) => t.key === e) ? i`
2879
- <div class="ft-header-menu" style="position: fixed; left: ${t}px; top: ${n}px; z-index: 200;"
2880
- @mousedown=${(e) => e.stopPropagation()}>
2881
- <div class="ft-header-menu-item"
2882
- @click=${() => {
2883
- this._setColumnHidden(e, !0), this._headerMenu = null;
2884
- }}>
2885
- Hide column
2886
- </div>
2887
- ${r.map((e) => i`
2888
- <div class="ft-header-menu-item"
2889
- @click=${() => {
2890
- this._setColumnHidden(e.key, !1), this._headerMenu = null;
2891
- }}>
2892
- Show: ${e.header}
2893
- </div>
2894
- `)}
3678
+ let { key: e, x: t, y: n, hiddenNeighbors: r } = this._headerMenu, o = this.columns.find((t) => t.key === e);
3679
+ if (!o) return a;
3680
+ let s = this._filters.some((t) => t.key === e), c = (e, t, n, r = !1) => i`
3681
+ <button type="button" role="menuitem" class="ft-header-menu-item" data-action=${e}
3682
+ @click=${(e) => {
3683
+ e.stopPropagation(), r || (this._headerMenu = null), n();
3684
+ }}>${t}</button>
3685
+ `;
3686
+ return i`
3687
+ <div class="ft-header-menu" role="menu" aria-label=${`${o.header} column`}
3688
+ style="position: fixed; left: ${t}px; top: ${n}px; z-index: 200;"
3689
+ @mousedown=${(e) => e.stopPropagation()}
3690
+ @keydown=${(e) => this._onHeaderMenuKeydown(e)}>
3691
+ ${o.sortable === !1 ? a : i`
3692
+ ${c("sort-asc", "Sort ascending", () => this._applySortFromMenu(e, "asc"))}
3693
+ ${c("sort-desc", "Sort descending", () => this._applySortFromMenu(e, "desc"))}
3694
+ <div class="ft-header-menu-separator" role="separator"></div>
3695
+ `}
3696
+ ${this.showFilters ? i`
3697
+ ${c("filter", "Filter…", () => this._openFilterFromMenu(e))}
3698
+ ${s ? c("clear-filter", "Clear filter", () => this._clearColumnFilter(e)) : a}
3699
+ <div class="ft-header-menu-separator" role="separator"></div>
3700
+ ` : a}
3701
+ ${c("hide", "Hide column", () => this._setColumnHidden(e, !0))}
3702
+ ${r.map((e) => c("show", i`Show: ${e.header}`, () => this._setColumnHidden(e.key, !1)))}
3703
+ <div class="ft-header-menu-separator" role="separator"></div>
3704
+ ${c("autofit", "Auto-fit width", () => this._autoFitColumn(e))}
3705
+ ${c("wider", "Wider", () => this._resizeColumnBy(e, X), !0)}
3706
+ ${c("narrower", "Narrower", () => this._resizeColumnBy(e, -20), !0)}
2895
3707
  </div>
2896
- ` : a;
3708
+ `;
2897
3709
  }
2898
3710
  _renderBodyContextMenu() {
2899
3711
  if (!this._bodyContextMenu) return a;
2900
3712
  let { colIndex: e, dataIndex: t, x: n, y: r } = this._bodyContextMenu, o = this.visibleColumns[e];
2901
3713
  if (!o) return a;
2902
- let s = this.data[t]?.[o.key], c = this._filters.some((e) => e.key === o.key), l = () => {
2903
- this._bodyContextMenu = null;
2904
- }, u = n + 200 > window.innerWidth ? n - 200 : n, d = r + 280 > window.innerHeight ? r - 280 : r;
3714
+ let s = this.data[t]?.[o.key], c = this._filters.some((e) => e.key === o.key), l = (e = !1) => {
3715
+ this._bodyContextMenu = null, e && this.focus();
3716
+ }, u = !!this.getComment(t, o.key), d = (e, t, n = !1) => i`
3717
+ <button type="button" role="menuitem"
3718
+ class="ft-context-menu-item ${n ? "ft-context-menu-danger" : ""}"
3719
+ @click=${() => {
3720
+ t(), l();
3721
+ }}>${e}</button>
3722
+ `, f = i`<div class="ft-context-menu-separator" role="separator"></div>`;
2905
3723
  return i`
2906
- <div class="ft-body-context-menu" style="position: fixed; left: ${u}px; top: ${d}px; z-index: 200;"
2907
- @mousedown=${(e) => e.stopPropagation()}>
2908
- <div class="ft-context-menu-item"
2909
- @click=${() => {
2910
- this._handleCopy(!1), l();
2911
- }}>
2912
- Copy
2913
- </div>
2914
- <div class="ft-context-menu-separator"></div>
2915
- <div class="ft-context-menu-item"
2916
- @click=${() => {
2917
- this.addRow(void 0, t), l();
2918
- }}>
2919
- Insert row above
2920
- </div>
2921
- <div class="ft-context-menu-item"
2922
- @click=${() => {
2923
- this.addRow(void 0, t + 1), l();
2924
- }}>
2925
- Insert row below
2926
- </div>
2927
- <div class="ft-context-menu-item ft-context-menu-danger"
2928
- @click=${() => {
2929
- this.deleteRows([t]), l();
2930
- }}>
2931
- Delete row
2932
- </div>
2933
- <div class="ft-context-menu-separator"></div>
2934
- <div class="ft-context-menu-item"
2935
- @click=${() => {
2936
- this._setColumnHidden(o.key, !0), l();
2937
- }}>
2938
- Hide column
2939
- </div>
2940
- <div class="ft-context-menu-separator"></div>
2941
- <div class="ft-context-menu-item"
2942
- @click=${() => {
2943
- this._applySortFromMenu(o.key, "asc"), l();
2944
- }}>
2945
- Sort ascending ↑
2946
- </div>
2947
- <div class="ft-context-menu-item"
2948
- @click=${() => {
2949
- this._applySortFromMenu(o.key, "desc"), l();
2950
- }}>
2951
- Sort descending ↓
2952
- </div>
2953
- <div class="ft-context-menu-separator"></div>
2954
- <div class="ft-context-menu-item"
2955
- @click=${() => {
2956
- this.setFilter(o.key, (e) => e === s), l();
2957
- }}>
2958
- Filter by this value
2959
- </div>
2960
- ${c ? i`
2961
- <div class="ft-context-menu-item"
2962
- @click=${() => {
2963
- this.removeFilter(o.key), l();
2964
- }}>
2965
- Clear filter
2966
- </div>
2967
- ` : ""}
2968
- <div class="ft-context-menu-separator"></div>
2969
- <div class="ft-context-menu-item"
2970
- @click=${() => {
2971
- this._openCommentPopup(t, o.key, n, r), l();
2972
- }}>
2973
- ${this.getComment(t, o.key) ? "Edit Comment" : "Add Comment"}
2974
- </div>
2975
- ${this.getComment(t, o.key) ? i`
2976
- <div class="ft-context-menu-item ft-context-menu-danger"
2977
- @click=${() => {
2978
- this.setComment(t, o.key, null), l();
2979
- }}>
2980
- Delete Comment
2981
- </div>
2982
- ` : ""}
3724
+ <div class="ft-body-context-menu" role="menu" aria-label=${k("cellActions")}
3725
+ style="position: fixed; left: ${n}px; top: ${r}px; z-index: 200;"
3726
+ @mousedown=${(e) => e.stopPropagation()}
3727
+ @keydown=${(e) => this._onMenuKeydown(e, ".ft-body-context-menu", l)}>
3728
+ ${d("Copy", () => this._handleCopy(!1))}
3729
+ ${f}
3730
+ ${d("Insert row above", () => this.addRow(void 0, t))}
3731
+ ${d("Insert row below", () => this.addRow(void 0, t + 1))}
3732
+ ${d("Delete row", () => this.deleteRows([t]), !0)}
3733
+ ${f}
3734
+ ${d("Hide column", () => this._setColumnHidden(o.key, !0))}
3735
+ ${f}
3736
+ ${d("Sort ascending ↑", () => this._applySortFromMenu(o.key, "asc"))}
3737
+ ${d("Sort descending ↓", () => this._applySortFromMenu(o.key, "desc"))}
3738
+ ${f}
3739
+ ${d("Filter by this value", () => this.setFilter(o.key, (e) => e === s))}
3740
+ ${c ? d("Clear filter", () => this.removeFilter(o.key)) : a}
3741
+ ${f}
3742
+ ${d(u ? "Edit Comment" : "Add Comment", () => this._openCommentPopup(t, o.key, n, r))}
3743
+ ${u ? d("Delete Comment", () => this.setComment(t, o.key, null), !0) : a}
2983
3744
  </div>
2984
3745
  `;
2985
3746
  }
@@ -3011,26 +3772,33 @@ var J = {
3011
3772
  @mousedown=${(e) => e.stopPropagation()}>
3012
3773
  <textarea class="ft-comment-popup-textarea"
3013
3774
  rows="4"
3014
- placeholder="Add a comment… (Ctrl+Enter to save)"
3775
+ placeholder=${k("addCommentPlaceholder")}
3015
3776
  @keydown=${(e) => {
3016
3777
  e.key === "Escape" && (e.preventDefault(), this._cancelCommentPopup()), e.key === "Enter" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this._commitCommentPopup());
3017
3778
  }}></textarea>
3018
3779
  <div class="ft-comment-popup-buttons">
3019
- <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>Cancel</button>
3020
- <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>Save</button>
3780
+ <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${k("cancel")}</button>
3781
+ <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${k("save")}</button>
3021
3782
  </div>
3022
3783
  </div>
3023
3784
  `;
3024
3785
  }
3025
- _applySortFromMenu(e, n) {
3026
- this.columns.find((t) => t.key === e) && (this._sortCriteria = [{
3786
+ _applySortFromMenu(e, t) {
3787
+ let n = this.columns.find((t) => t.key === e);
3788
+ n && n.sortable !== !1 && (this._sortCriteria = [{
3027
3789
  key: e,
3028
- direction: n
3029
- }], this._sortedIndices = t(this.data, this._sortCriteria, this.columns), this.dispatchEvent(new CustomEvent("sort-change", {
3030
- detail: { sortCriteria: [...this._sortCriteria] },
3790
+ direction: t
3791
+ }], this.dataMode !== "server" && this._recomputeView(), this.requestUpdate(), this.dispatchEvent(new CustomEvent("sort-change", {
3792
+ detail: { criteria: [...this._sortCriteria] },
3031
3793
  bubbles: !0,
3032
3794
  composed: !0
3033
- })), this.requestUpdate());
3795
+ })));
3796
+ }
3797
+ _keepMenuInView(e) {
3798
+ let t = this.shadowRoot?.querySelector(e);
3799
+ if (!t) return;
3800
+ let n = t.getBoundingClientRect(), r = document.documentElement.clientWidth, i = document.documentElement.clientHeight;
3801
+ n.right > r - 4 && (t.style.left = `${Math.max(4, r - n.width - 4)}px`), n.bottom > i - 4 && (t.style.top = `${Math.max(4, i - n.height - 4)}px`);
3034
3802
  }
3035
3803
  _adjustFilterDropdown() {
3036
3804
  if (!this._openFilterKey) return;
@@ -3040,20 +3808,13 @@ var J = {
3040
3808
  let t = e.getBoundingClientRect(), n = window.innerHeight;
3041
3809
  t.bottom > n && (e.style.top = "auto", e.style.bottom = "100%");
3042
3810
  }
3043
- _onFilterBtnClick(e, t) {
3044
- e.preventDefault(), e.stopPropagation();
3045
- let n = this._openFilterKey === t.key ? null : t.key;
3046
- this._openFilterKey = n, n && requestAnimationFrame(() => {
3047
- document.addEventListener("click", this._onDocumentClick, { once: !0 });
3048
- });
3049
- }
3050
3811
  _renderFilterDropdown(e) {
3051
3812
  let t = e.type ?? "text";
3052
3813
  return i`
3053
3814
  <div class="ft-filter-dropdown" @click=${(e) => e.stopPropagation()}>
3054
3815
  ${t === "boolean" ? this._renderBooleanFilter(e) : t === "number" ? this._renderNumberFilter(e) : t === "date" || t === "datetime" ? this._renderDateFilter(e) : this._renderTextFilter(e)}
3055
3816
  <div class="ft-filter-actions">
3056
- <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>Clear</button>
3817
+ <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${k("clear")}</button>
3057
3818
  </div>
3058
3819
  </div>
3059
3820
  `;
@@ -3086,7 +3847,7 @@ var J = {
3086
3847
  let n = this._emptyFilterState.get(e) ?? "";
3087
3848
  return i`
3088
3849
  <div class="ft-filter-empty-row">
3089
- <label>Blank cells</label>
3850
+ <label>${k("blankCells")}</label>
3090
3851
  <select class="ft-filter-mode-select"
3091
3852
  .value=${n}
3092
3853
  @change=${(n) => {
@@ -3096,9 +3857,9 @@ var J = {
3096
3857
  @keydown=${(e) => {
3097
3858
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3098
3859
  }}>
3099
- <option value="">— All —</option>
3100
- <option value="empty">Empty only</option>
3101
- <option value="non-empty">Non-empty only</option>
3860
+ <option value="">${k("blankAll")}</option>
3861
+ <option value="empty">${k("emptyOnly")}</option>
3862
+ <option value="non-empty">${k("nonEmptyOnly")}</option>
3102
3863
  </select>
3103
3864
  </div>
3104
3865
  `;
@@ -3174,13 +3935,13 @@ var J = {
3174
3935
  @keydown=${(e) => {
3175
3936
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3176
3937
  }}>
3177
- <option value="contains">Contains</option>
3178
- <option value="starts">Starts with</option>
3179
- <option value="ends">Ends with</option>
3180
- <option value="wildcard">Wildcard</option>
3938
+ <option value="contains">${k("contains")}</option>
3939
+ <option value="starts">${k("startsWith")}</option>
3940
+ <option value="ends">${k("endsWith")}</option>
3941
+ <option value="wildcard">${k("wildcard")}</option>
3181
3942
  </select>
3182
3943
  </div>
3183
- <input class="ft-filter-input" type="text" placeholder="Search..."
3944
+ <input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")}
3184
3945
  .value=${t.value}
3185
3946
  @input=${(t) => {
3186
3947
  let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
@@ -3229,9 +3990,9 @@ var J = {
3229
3990
  @keydown=${(e) => {
3230
3991
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3231
3992
  }}>
3232
- ${Object.keys(J).map((e) => i`<option value=${e}>${J[e]}</option>`)}
3993
+ ${Object.keys(q).map((e) => i`<option value=${e}>${q[e]}</option>`)}
3233
3994
  </select>
3234
- <input class="ft-filter-input ft-num-cond-input" type="number" placeholder="Value"
3995
+ <input class="ft-filter-input ft-num-cond-input" type="number" placeholder=${k("valuePlaceholder")}
3235
3996
  .value=${n.value == null ? "" : String(n.value)}
3236
3997
  @input=${(n) => {
3237
3998
  let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
@@ -3292,13 +4053,13 @@ var J = {
3292
4053
  let t = e.type === "datetime" ? "datetime-local" : "date", n = this._dateFilterState.get(e.key) ?? {};
3293
4054
  return i`
3294
4055
  <div class="ft-filter-range">
3295
- <input class="ft-filter-input" type=${t} placeholder="From"
4056
+ <input class="ft-filter-input" type=${t} placeholder=${k("fromPlaceholder")}
3296
4057
  .value=${n.from ?? ""}
3297
4058
  @input=${(t) => this._applyDateFilter(e.key, t, "from")}
3298
4059
  @keydown=${(e) => {
3299
4060
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3300
4061
  }}>
3301
- <input class="ft-filter-input" type=${t} placeholder="To"
4062
+ <input class="ft-filter-input" type=${t} placeholder=${k("toPlaceholder")}
3302
4063
  .value=${n.to ?? ""}
3303
4064
  @input=${(t) => this._applyDateFilter(e.key, t, "to")}
3304
4065
  @keydown=${(e) => {
@@ -3324,7 +4085,7 @@ var J = {
3324
4085
  @keydown=${(e) => {
3325
4086
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3326
4087
  }}>
3327
- <option value="all">All</option>
4088
+ <option value="all">${k("all")}</option>
3328
4089
  <option value="true">\u2714 True</option>
3329
4090
  <option value="false">\u2718 False</option>
3330
4091
  </select>
@@ -3334,13 +4095,12 @@ var J = {
3334
4095
  _clearColumnFilter(e) {
3335
4096
  this.removeFilter(e), this._textFilterState.delete(e), this._numberFilterState.delete(e), this._dateFilterState.delete(e), this._emptyFilterState.delete(e), this._openFilterKey = null;
3336
4097
  }
3337
- _onResizeAutoFit(e, t) {
3338
- e.preventDefault(), e.stopPropagation();
3339
- let n = this.visibleColumns[t];
4098
+ _autoFitColumn(e) {
4099
+ let t = this.visibleColumns.findIndex((t) => t.key === e), n = this.visibleColumns[t];
3340
4100
  if (!n) return;
3341
4101
  let r = this.shadowRoot?.querySelectorAll(`.ft-cell[data-col-index="${t}"]`), i = 0, a = this.shadowRoot?.querySelector(`.ft-header-cell[data-col-index="${t}"]`);
3342
4102
  if (a && (i = Math.max(i, a.scrollWidth)), r) for (let e of r) i = Math.max(i, e.scrollWidth);
3343
- let o = n.minWidth ?? X, s = Math.max(o, i + 8);
4103
+ let o = n.minWidth ?? Y, s = Math.max(o, i + 8);
3344
4104
  this._columnWidths.set(n.key, s), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
3345
4105
  detail: {
3346
4106
  key: n.key,
@@ -3353,7 +4113,7 @@ var J = {
3353
4113
  }
3354
4114
  _onResizeStart(e, t) {
3355
4115
  e.preventDefault(), e.stopPropagation();
3356
- let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? Y;
4116
+ let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? J;
3357
4117
  this._resizing = {
3358
4118
  colIndex: t,
3359
4119
  startX: e.clientX,
@@ -3361,13 +4121,13 @@ var J = {
3361
4121
  };
3362
4122
  let i = (e) => {
3363
4123
  if (!this._resizing) return;
3364
- let t = e.clientX - this._resizing.startX, r = n.minWidth ?? X, i = Math.max(r, this._resizing.startWidth + t);
4124
+ let t = e.clientX - this._resizing.startX, r = n.minWidth ?? Y, i = Math.max(r, this._resizing.startWidth + t);
3365
4125
  this._columnWidths.set(n.key, i), this.requestUpdate();
3366
4126
  }, a = () => {
3367
4127
  document.removeEventListener("mousemove", i), document.removeEventListener("mouseup", o), this._resizeCleanup = null;
3368
4128
  }, o = () => {
3369
4129
  if (a(), this._resizing) {
3370
- let e = this._columnWidths.get(n.key) ?? Y;
4130
+ let e = this._columnWidths.get(n.key) ?? J;
3371
4131
  this.dispatchEvent(new CustomEvent("column-resize", {
3372
4132
  detail: {
3373
4133
  key: n.key,
@@ -3747,31 +4507,31 @@ var J = {
3747
4507
  e.key === "Enter" && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
3748
4508
  }}>
3749
4509
  <div class="ft-find-row">
3750
- <input class="ft-find-input" type="text" placeholder="Find..."
4510
+ <input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")}
3751
4511
  .value=${t}
3752
4512
  @input=${(e) => {
3753
4513
  this._findState.query = e.target.value, this._findSearch();
3754
4514
  }}>
3755
4515
  <span class="ft-find-count">${c > 0 ? `${l}/${c}` : t ? "0 results" : ""}</span>
3756
- <button @click=${() => this._findPrev()} title="Previous (Shift+Enter)">◀</button>
3757
- <button @click=${() => this._findNext()} title="Next (Enter)">▶</button>
3758
- <label title="Match case"><input type="checkbox" ?checked=${r} @change=${(e) => {
4516
+ <button @click=${() => this._findPrev()} title=${k("findPrevious")}>◀</button>
4517
+ <button @click=${() => this._findNext()} title=${k("findNext")}>▶</button>
4518
+ <label title=${k("matchCase")}><input type="checkbox" ?checked=${r} @change=${(e) => {
3759
4519
  this._findState.matchCase = e.target.checked, this._findSearch();
3760
4520
  }}> Aa</label>
3761
- <label title="Whole cell"><input type="checkbox" ?checked=${a} @change=${(e) => {
4521
+ <label title=${k("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
3762
4522
  this._findState.wholeCell = e.target.checked, this._findSearch();
3763
4523
  }}> [ ]</label>
3764
- <button @click=${() => this._closeFindPanel()} title="Close (Escape)">✕</button>
4524
+ <button @click=${() => this._closeFindPanel()} title=${k("closeFind")}>✕</button>
3765
4525
  </div>
3766
4526
  ${e === "replace" ? i`
3767
4527
  <div class="ft-find-row">
3768
- <input class="ft-find-replace-input" type="text" placeholder="Replace with..."
4528
+ <input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")}
3769
4529
  .value=${n}
3770
4530
  @input=${(e) => {
3771
4531
  this._findState.replaceWith = e.target.value;
3772
4532
  }}>
3773
- <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>Replace</button>
3774
- <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>Replace All</button>
4533
+ <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${k("replace")}</button>
4534
+ <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${k("replaceAll")}</button>
3775
4535
  </div>
3776
4536
  ` : ""}
3777
4537
  </div>
@@ -3779,7 +4539,7 @@ var J = {
3779
4539
  }
3780
4540
  render() {
3781
4541
  let e = this.visibleColumns, t = this.importEnabled && this._isDragOver ? i`<div class="ft-import-overlay">Drop file to import (.xlsx / .csv)</div>` : a, n = this.loading ? i`<div class="ft-loading-overlay"></div>` : a;
3782
- if (e.length === 0) return i`${t}${n}<div class="ft-empty">No columns defined</div>`;
4542
+ if (e.length === 0) return i`${t}${n}<div class="ft-empty">${k("noColumnsDefined")}</div>`;
3783
4543
  let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
3784
4544
  for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
3785
4545
  let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
@@ -4032,60 +4792,60 @@ var J = {
4032
4792
  return isNaN(t.getTime()) ? "" : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}T${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
4033
4793
  }
4034
4794
  };
4035
- q([s({ type: Array })], $.prototype, "columns", void 0), q([s({
4795
+ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4036
4796
  type: Array,
4037
4797
  hasChanged: () => !0
4038
- })], $.prototype, "data", null), q([s({
4798
+ })], $.prototype, "data", null), K([s({
4039
4799
  type: Boolean,
4040
4800
  attribute: "clear-undo-on-data-change"
4041
- })], $.prototype, "clearUndoOnDataChange", void 0), q([s({
4801
+ })], $.prototype, "clearUndoOnDataChange", void 0), K([s({
4042
4802
  type: Boolean,
4043
4803
  attribute: "clear-selection-on-data-change"
4044
- })], $.prototype, "clearSelectionOnDataChange", void 0), q([s({
4804
+ })], $.prototype, "clearSelectionOnDataChange", void 0), K([s({
4045
4805
  type: Number,
4046
4806
  attribute: "row-height"
4047
- })], $.prototype, "rowHeight", null), q([s({
4807
+ })], $.prototype, "rowHeight", null), K([s({
4048
4808
  type: Boolean,
4049
4809
  attribute: "show-row-numbers"
4050
- })], $.prototype, "showRowNumbers", void 0), q([s({
4810
+ })], $.prototype, "showRowNumbers", void 0), K([s({
4051
4811
  type: String,
4052
4812
  reflect: !0
4053
- })], $.prototype, "theme", void 0), q([s({
4813
+ })], $.prototype, "theme", void 0), K([s({
4054
4814
  type: Number,
4055
4815
  attribute: "max-rows"
4056
- })], $.prototype, "maxRows", void 0), q([s({ type: Boolean })], $.prototype, "editable", void 0), q([s({
4816
+ })], $.prototype, "maxRows", void 0), K([s({ type: Boolean })], $.prototype, "editable", void 0), K([s({
4057
4817
  type: Boolean,
4058
4818
  attribute: "show-filters"
4059
- })], $.prototype, "showFilters", void 0), q([s({
4819
+ })], $.prototype, "showFilters", void 0), K([s({
4060
4820
  type: Boolean,
4061
4821
  attribute: "show-context-menu"
4062
- })], $.prototype, "showContextMenu", void 0), q([s({
4822
+ })], $.prototype, "showContextMenu", void 0), K([s({
4063
4823
  type: Number,
4064
4824
  attribute: "frozen-rows"
4065
- })], $.prototype, "frozenRows", void 0), q([s({
4825
+ })], $.prototype, "frozenRows", void 0), K([s({
4066
4826
  type: String,
4067
4827
  attribute: "empty-message"
4068
- })], $.prototype, "emptyMessage", void 0), q([s({
4828
+ })], $.prototype, "emptyMessage", void 0), K([s({
4069
4829
  type: String,
4070
4830
  attribute: "no-matching-message"
4071
- })], $.prototype, "noMatchingMessage", void 0), q([s({
4831
+ })], $.prototype, "noMatchingMessage", void 0), K([s({
4072
4832
  type: Boolean,
4073
4833
  reflect: !0
4074
- })], $.prototype, "loading", void 0), q([s({
4834
+ })], $.prototype, "loading", void 0), K([s({
4075
4835
  type: Boolean,
4076
4836
  attribute: "import-enabled"
4077
- })], $.prototype, "importEnabled", void 0), q([s({ type: Boolean })], $.prototype, "selectable", void 0), q([s({
4837
+ })], $.prototype, "importEnabled", void 0), K([s({ type: Boolean })], $.prototype, "selectable", void 0), K([s({
4078
4838
  type: String,
4079
4839
  attribute: "selection-mode"
4080
- })], $.prototype, "selectionMode", null), q([s({
4840
+ })], $.prototype, "selectionMode", null), K([s({
4081
4841
  type: String,
4082
4842
  attribute: "data-mode"
4083
- })], $.prototype, "dataMode", void 0), q([s({
4843
+ })], $.prototype, "dataMode", void 0), K([s({
4084
4844
  type: Object,
4085
4845
  attribute: "footer-data"
4086
- })], $.prototype, "footerData", void 0), q([s({ attribute: !1 })], $.prototype, "stylesheets", void 0), q([s({
4846
+ })], $.prototype, "footerData", void 0), K([s({ attribute: !1 })], $.prototype, "stylesheets", void 0), K([s({
4087
4847
  type: Number,
4088
4848
  attribute: "max-undo-size"
4089
- })], $.prototype, "maxUndoSize", null), q([c()], $.prototype, "_scrollTop", void 0), q([c()], $.prototype, "_scrollLeft", void 0), q([c()], $.prototype, "_viewportHeight", void 0), q([c()], $.prototype, "_viewportWidth", void 0), q([c()], $.prototype, "_activeCell", void 0), q([c()], $.prototype, "_editingCell", void 0), q([c()], $.prototype, "_sortCriteria", void 0), q([c()], $.prototype, "_openFilterKey", void 0), q([c()], $.prototype, "_rowSelectionVersion", void 0), q([c()], $.prototype, "_autocompleteState", void 0), q([c()], $.prototype, "_headerMenu", void 0), q([c()], $.prototype, "_bodyContextMenu", void 0), q([c()], $.prototype, "_commentPopup", void 0), q([c()], $.prototype, "_isDragOver", void 0), $ = q([o("flex-table")], $);
4849
+ })], $.prototype, "maxUndoSize", null), K([c()], $.prototype, "_scrollTop", void 0), K([c()], $.prototype, "_scrollLeft", void 0), K([c()], $.prototype, "_viewportHeight", void 0), K([c()], $.prototype, "_viewportWidth", void 0), K([c()], $.prototype, "_activeCell", void 0), K([c()], $.prototype, "_editingCell", void 0), K([c()], $.prototype, "_sortCriteria", void 0), K([c()], $.prototype, "_openFilterKey", void 0), K([c()], $.prototype, "_rowSelectionVersion", void 0), K([c()], $.prototype, "_autocompleteState", void 0), K([c()], $.prototype, "_headerMenu", void 0), K([c()], $.prototype, "_bodyContextMenu", void 0), K([c()], $.prototype, "_commentPopup", void 0), K([c()], $.prototype, "_isDragOver", void 0), $ = K([o("flex-table")], $);
4090
4850
  //#endregion
4091
- export { m as a, C as i, L as n, E as r, $ as t };
4851
+ export { O as a, A as i, H as n, m as o, M as r, $ as t };