klun-ui 0.5.0 → 0.6.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.
@@ -199,7 +199,7 @@ var enUS = {
199
199
  banner: { dismiss: "Dismiss" },
200
200
  toast: { dismiss: "Dismiss" },
201
201
  fileUpload: { clickToUpload: "Click to upload", orDragAndDrop: "or drag and drop" },
202
- imageUpload: { label: "Upload image", remove: "Remove" },
202
+ imageUpload: { label: "Upload image", remove: "Remove", hint: "PNG or JPG, up to 5MB" },
203
203
  passwordStrength: { weak: "Weak", fair: "Fair", good: "Good", strong: "Strong" },
204
204
  commandMenu: {
205
205
  placeholder: "Type a command or search\u2026",
@@ -267,7 +267,14 @@ var enUS = {
267
267
  perPage: "{size} / page",
268
268
  selectRow: "Select row",
269
269
  selectAll: "Select all rows"
270
- }
270
+ },
271
+ wizard: { back: "\u4E0A\u4E00\u6B65", next: "\u4E0B\u4E00\u6B65", finish: "\u5B8C\u6210" },
272
+ a11y: { zoomIn: "Zoom in", zoomOut: "Zoom out", rotate: "Rotate", collapseStart: "Collapse start panel", collapseEnd: "Collapse end panel", bulkActions: "Bulk actions", clearSelection: "Clear selection", back: "Back" },
273
+ richEditor: { placeholder: "Write something\u2026", editorLabel: "Rich text editor" },
274
+ copy: { label: "Copy" },
275
+ emojiPicker: { searchPlaceholder: "Search emoji", emptyText: "No emoji found", addReaction: "Add reaction" },
276
+ sidebar: { searchPlaceholder: "Search", primary: "Primary" },
277
+ imageViewer: { reset: "Reset", download: "Download" }
271
278
  };
272
279
  var zhCN = {
273
280
  locale: "zh-CN",
@@ -297,7 +304,7 @@ var zhCN = {
297
304
  banner: { dismiss: "\u5173\u95ED" },
298
305
  toast: { dismiss: "\u5173\u95ED" },
299
306
  fileUpload: { clickToUpload: "\u70B9\u51FB\u4E0A\u4F20", orDragAndDrop: "\u6216\u62D6\u62FD\u5230\u6B64\u5904" },
300
- imageUpload: { label: "\u4E0A\u4F20\u56FE\u7247", remove: "\u79FB\u9664" },
307
+ imageUpload: { label: "\u4E0A\u4F20\u56FE\u7247", remove: "\u79FB\u9664", hint: "\u652F\u6301 PNG \u6216 JPG\uFF0C\u6700\u5927 5MB" },
301
308
  passwordStrength: { weak: "\u5F31", fair: "\u4E00\u822C", good: "\u826F\u597D", strong: "\u5F3A" },
302
309
  commandMenu: {
303
310
  placeholder: "\u8F93\u5165\u547D\u4EE4\u6216\u641C\u7D22\u2026",
@@ -365,7 +372,14 @@ var zhCN = {
365
372
  perPage: "{size} / \u9875",
366
373
  selectRow: "\u9009\u62E9\u672C\u884C",
367
374
  selectAll: "\u5168\u9009"
368
- }
375
+ },
376
+ wizard: { back: "\u4E0A\u4E00\u6B65", next: "\u4E0B\u4E00\u6B65", finish: "\u5B8C\u6210" },
377
+ a11y: { zoomIn: "\u653E\u5927", zoomOut: "\u7F29\u5C0F", rotate: "\u65CB\u8F6C", collapseStart: "\u6536\u8D77\u8D77\u59CB\u9762\u677F", collapseEnd: "\u6536\u8D77\u7ED3\u675F\u9762\u677F", bulkActions: "\u6279\u91CF\u64CD\u4F5C", clearSelection: "\u6E05\u9664\u9009\u62E9", back: "\u8FD4\u56DE" },
378
+ richEditor: { placeholder: "\u8BF7\u8F93\u5165\u5185\u5BB9\u2026", editorLabel: "\u5BCC\u6587\u672C\u7F16\u8F91\u5668" },
379
+ copy: { label: "\u590D\u5236" },
380
+ emojiPicker: { searchPlaceholder: "\u641C\u7D22\u8868\u60C5", emptyText: "\u6CA1\u6709\u627E\u5230\u8868\u60C5", addReaction: "\u6DFB\u52A0\u8868\u60C5" },
381
+ sidebar: { searchPlaceholder: "\u641C\u7D22", primary: "\u4E3B\u5BFC\u822A" },
382
+ imageViewer: { reset: "\u91CD\u7F6E", download: "\u4E0B\u8F7D" }
369
383
  };
370
384
  var zhTW = {
371
385
  locale: "zh-TW",
@@ -389,13 +403,13 @@ var zhTW = {
389
403
  },
390
404
  timePicker: { am: "\u4E0A\u5348", pm: "\u4E0B\u5348" },
391
405
  pagination: { previous: "\u4E0A\u4E00\u9801", next: "\u4E0B\u4E00\u9801" },
392
- modal: { close: "\u95DC\u9589" },
406
+ modal: { close: "\u95DC\u9589", maximize: "\u6700\u5927\u5316", restore: "\u9084\u539F" },
393
407
  drawer: { close: "\u95DC\u9589" },
394
408
  alert: { dismiss: "\u95DC\u9589" },
395
409
  banner: { dismiss: "\u95DC\u9589" },
396
410
  toast: { dismiss: "\u95DC\u9589" },
397
411
  fileUpload: { clickToUpload: "\u9EDE\u64CA\u4E0A\u50B3", orDragAndDrop: "\u6216\u62D6\u66F3\u5230\u6B64\u8655" },
398
- imageUpload: { label: "\u4E0A\u50B3\u5716\u7247", remove: "\u79FB\u9664" },
412
+ imageUpload: { label: "\u4E0A\u50B3\u5716\u7247", remove: "\u79FB\u9664", hint: "\u652F\u63F4 PNG \u6216 JPG\uFF0C\u6700\u5927 5MB" },
399
413
  passwordStrength: { weak: "\u5F31", fair: "\u4E00\u822C", good: "\u826F\u597D", strong: "\u5F37" },
400
414
  commandMenu: {
401
415
  placeholder: "\u8F38\u5165\u547D\u4EE4\u6216\u641C\u5C0B\u2026",
@@ -463,7 +477,14 @@ var zhTW = {
463
477
  perPage: "{size} / \u9801",
464
478
  selectRow: "\u9078\u64C7\u672C\u884C",
465
479
  selectAll: "\u5168\u9078"
466
- }
480
+ },
481
+ wizard: { back: "\u623B\u308B", next: "\u6B21\u3078", finish: "\u5B8C\u4E86" },
482
+ a11y: { zoomIn: "\u653E\u5927", zoomOut: "\u7E2E\u5C0F", rotate: "\u65CB\u8F49", collapseStart: "\u6536\u5408\u8D77\u59CB\u9762\u677F", collapseEnd: "\u6536\u5408\u7D50\u675F\u9762\u677F", bulkActions: "\u6279\u6B21\u64CD\u4F5C", clearSelection: "\u6E05\u9664\u9078\u53D6", back: "\u8FD4\u56DE" },
483
+ richEditor: { placeholder: "\u8ACB\u8F38\u5165\u5167\u5BB9\u2026", editorLabel: "\u5BCC\u6587\u5B57\u7DE8\u8F2F\u5668" },
484
+ copy: { label: "\u8907\u88FD" },
485
+ emojiPicker: { searchPlaceholder: "\u641C\u5C0B\u8868\u60C5", emptyText: "\u627E\u4E0D\u5230\u8868\u60C5", addReaction: "\u65B0\u589E\u8868\u60C5" },
486
+ sidebar: { searchPlaceholder: "\u641C\u5C0B", primary: "\u4E3B\u5C0E\u89BD" },
487
+ imageViewer: { reset: "\u91CD\u8A2D", download: "\u4E0B\u8F09" }
467
488
  };
468
489
  var jaJP = {
469
490
  locale: "ja-JP",
@@ -487,13 +508,15 @@ var jaJP = {
487
508
  },
488
509
  timePicker: { am: "\u5348\u524D", pm: "\u5348\u5F8C" },
489
510
  pagination: { previous: "\u524D\u3078", next: "\u6B21\u3078" },
490
- modal: { close: "\u9589\u3058\u308B" },
511
+ modal: { close: "\u9589\u3058\u308B", maximize: "\u6700\u5927\u5316", restore: "\u5143\u306B\u623B\u3059" },
512
+ select: { placeholder: "\u9078\u629E" },
513
+ counterInput: { decrease: "\u6E1B\u3089\u3059", increase: "\u5897\u3084\u3059" },
491
514
  drawer: { close: "\u9589\u3058\u308B" },
492
515
  alert: { dismiss: "\u9589\u3058\u308B" },
493
516
  banner: { dismiss: "\u9589\u3058\u308B" },
494
517
  toast: { dismiss: "\u9589\u3058\u308B" },
495
518
  fileUpload: { clickToUpload: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9", orDragAndDrop: "\u307E\u305F\u306F\u30C9\u30E9\u30C3\u30B0\uFF06\u30C9\u30ED\u30C3\u30D7" },
496
- imageUpload: { label: "\u753B\u50CF\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9", remove: "\u524A\u9664" },
519
+ imageUpload: { label: "\u753B\u50CF\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9", remove: "\u524A\u9664", hint: "PNG \u307E\u305F\u306F JPG\u3001\u6700\u5927 5MB" },
497
520
  passwordStrength: { weak: "\u5F31\u3044", fair: "\u666E\u901A", good: "\u826F\u3044", strong: "\u5F37\u3044" },
498
521
  commandMenu: {
499
522
  placeholder: "\u30B3\u30DE\u30F3\u30C9\u3092\u5165\u529B\u307E\u305F\u306F\u691C\u7D22\u2026",
@@ -556,8 +579,17 @@ var jaJP = {
556
579
  previous: "\u524D\u3078",
557
580
  next: "\u6B21\u3078",
558
581
  pageRange: "{total} \u4EF6\u4E2D {from}\u2013{to}",
559
- perPage: "{size} \u4EF6 / \u30DA\u30FC\u30B8"
560
- }
582
+ perPage: "{size} \u4EF6 / \u30DA\u30FC\u30B8",
583
+ selectRow: "\u884C\u3092\u9078\u629E",
584
+ selectAll: "\u3059\u3079\u3066\u9078\u629E"
585
+ },
586
+ wizard: { back: "\uC774\uC804", next: "\uB2E4\uC74C", finish: "\uC644\uB8CC" },
587
+ a11y: { zoomIn: "\u62E1\u5927", zoomOut: "\u7E2E\u5C0F", rotate: "\u56DE\u8EE2", collapseStart: "\u958B\u59CB\u30D1\u30CD\u30EB\u3092\u6298\u308A\u305F\u305F\u3080", collapseEnd: "\u7D42\u4E86\u30D1\u30CD\u30EB\u3092\u6298\u308A\u305F\u305F\u3080", bulkActions: "\u4E00\u62EC\u64CD\u4F5C", clearSelection: "\u9078\u629E\u3092\u89E3\u9664", back: "\u623B\u308B" },
588
+ richEditor: { placeholder: "\u5185\u5BB9\u3092\u5165\u529B\u2026", editorLabel: "\u30EA\u30C3\u30C1\u30C6\u30AD\u30B9\u30C8\u30A8\u30C7\u30A3\u30BF\u30FC" },
589
+ copy: { label: "\u30B3\u30D4\u30FC" },
590
+ emojiPicker: { searchPlaceholder: "\u7D75\u6587\u5B57\u3092\u691C\u7D22", emptyText: "\u7D75\u6587\u5B57\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093", addReaction: "\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u8FFD\u52A0" },
591
+ sidebar: { searchPlaceholder: "\u691C\u7D22", primary: "\u30E1\u30A4\u30F3\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3" },
592
+ imageViewer: { reset: "\u30EA\u30BB\u30C3\u30C8", download: "\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9" }
561
593
  };
562
594
  var koKR = {
563
595
  locale: "ko-KR",
@@ -581,13 +613,15 @@ var koKR = {
581
613
  },
582
614
  timePicker: { am: "\uC624\uC804", pm: "\uC624\uD6C4" },
583
615
  pagination: { previous: "\uC774\uC804", next: "\uB2E4\uC74C" },
584
- modal: { close: "\uB2EB\uAE30" },
616
+ modal: { close: "\uB2EB\uAE30", maximize: "\uCD5C\uB300\uD654", restore: "\uBCF5\uC6D0" },
617
+ select: { placeholder: "\uC120\uD0DD" },
618
+ counterInput: { decrease: "\uAC10\uC18C", increase: "\uC99D\uAC00" },
585
619
  drawer: { close: "\uB2EB\uAE30" },
586
620
  alert: { dismiss: "\uB2EB\uAE30" },
587
621
  banner: { dismiss: "\uB2EB\uAE30" },
588
622
  toast: { dismiss: "\uB2EB\uAE30" },
589
623
  fileUpload: { clickToUpload: "\uD074\uB9AD\uD558\uC5EC \uC5C5\uB85C\uB4DC", orDragAndDrop: "\uB610\uB294 \uB4DC\uB798\uADF8 \uC564 \uB4DC\uB86D" },
590
- imageUpload: { label: "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC", remove: "\uC81C\uAC70" },
624
+ imageUpload: { label: "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC", remove: "\uC81C\uAC70", hint: "PNG \uB610\uB294 JPG, \uCD5C\uB300 5MB" },
591
625
  passwordStrength: { weak: "\uC57D\uD568", fair: "\uBCF4\uD1B5", good: "\uC591\uD638", strong: "\uAC15\uD568" },
592
626
  commandMenu: {
593
627
  placeholder: "\uBA85\uB839\uC5B4 \uC785\uB825 \uB610\uB294 \uAC80\uC0C9\u2026",
@@ -650,8 +684,17 @@ var koKR = {
650
684
  previous: "\uC774\uC804",
651
685
  next: "\uB2E4\uC74C",
652
686
  pageRange: "{total}\uAC1C \uC911 {from}\u2013{to}",
653
- perPage: "{size}\uAC1C / \uD398\uC774\uC9C0"
654
- }
687
+ perPage: "{size}\uAC1C / \uD398\uC774\uC9C0",
688
+ selectRow: "\uD589 \uC120\uD0DD",
689
+ selectAll: "\uC804\uCCB4 \uC120\uD0DD"
690
+ },
691
+ wizard: { back: "Retour", next: "Suivant", finish: "Terminer" },
692
+ a11y: { zoomIn: "\uD655\uB300", zoomOut: "\uCD95\uC18C", rotate: "\uD68C\uC804", collapseStart: "\uC2DC\uC791 \uD328\uB110 \uC811\uAE30", collapseEnd: "\uB05D \uD328\uB110 \uC811\uAE30", bulkActions: "\uC77C\uAD04 \uC791\uC5C5", clearSelection: "\uC120\uD0DD \uD574\uC81C", back: "\uB4A4\uB85C" },
693
+ richEditor: { placeholder: "\uB0B4\uC6A9\uC744 \uC785\uB825\u2026", editorLabel: "\uB9AC\uCE58 \uD14D\uC2A4\uD2B8 \uD3B8\uC9D1\uAE30" },
694
+ copy: { label: "\uBCF5\uC0AC" },
695
+ emojiPicker: { searchPlaceholder: "\uC774\uBAA8\uC9C0 \uAC80\uC0C9", emptyText: "\uC774\uBAA8\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C", addReaction: "\uBC18\uC751 \uCD94\uAC00" },
696
+ sidebar: { searchPlaceholder: "\uAC80\uC0C9", primary: "\uAE30\uBCF8 \uD0D0\uC0C9" },
697
+ imageViewer: { reset: "\uC7AC\uC124\uC815", download: "\uB2E4\uC6B4\uB85C\uB4DC" }
655
698
  };
656
699
  var frFR = {
657
700
  locale: "fr-FR",
@@ -675,13 +718,15 @@ var frFR = {
675
718
  },
676
719
  timePicker: { am: "AM", pm: "PM" },
677
720
  pagination: { previous: "Pr\xE9c\xE9dent", next: "Suivant" },
678
- modal: { close: "Fermer" },
721
+ modal: { close: "Fermer", maximize: "Agrandir", restore: "Restaurer" },
722
+ select: { placeholder: "S\xE9lectionner" },
723
+ counterInput: { decrease: "Diminuer", increase: "Augmenter" },
679
724
  drawer: { close: "Fermer" },
680
725
  alert: { dismiss: "Fermer" },
681
726
  banner: { dismiss: "Fermer" },
682
727
  toast: { dismiss: "Fermer" },
683
728
  fileUpload: { clickToUpload: "Cliquez pour t\xE9l\xE9verser", orDragAndDrop: "ou glissez-d\xE9posez" },
684
- imageUpload: { label: "T\xE9l\xE9verser une image", remove: "Supprimer" },
729
+ imageUpload: { label: "T\xE9l\xE9verser une image", remove: "Supprimer", hint: "PNG ou JPG, jusqu'\xE0 5 Mo" },
685
730
  passwordStrength: { weak: "Faible", fair: "Moyen", good: "Bon", strong: "Fort" },
686
731
  commandMenu: {
687
732
  placeholder: "Tapez une commande ou recherchez\u2026",
@@ -744,8 +789,17 @@ var frFR = {
744
789
  previous: "Pr\xE9c\xE9dent",
745
790
  next: "Suivant",
746
791
  pageRange: "{from}\u2013{to} sur {total}",
747
- perPage: "{size} / page"
748
- }
792
+ perPage: "{size} / page",
793
+ selectRow: "S\xE9lectionner la ligne",
794
+ selectAll: "Tout s\xE9lectionner"
795
+ },
796
+ wizard: { back: "Zur\xFCck", next: "Weiter", finish: "Fertig" },
797
+ a11y: { zoomIn: "Zoom avant", zoomOut: "Zoom arri\xE8re", rotate: "Pivoter", collapseStart: "R\xE9duire le panneau de d\xE9but", collapseEnd: "R\xE9duire le panneau de fin", bulkActions: "Actions group\xE9es", clearSelection: "Effacer la s\xE9lection", back: "Retour" },
798
+ richEditor: { placeholder: "\xC9crivez quelque chose\u2026", editorLabel: "\xC9diteur de texte enrichi" },
799
+ copy: { label: "Copier" },
800
+ emojiPicker: { searchPlaceholder: "Rechercher un emoji", emptyText: "Aucun emoji trouv\xE9", addReaction: "Ajouter une r\xE9action" },
801
+ sidebar: { searchPlaceholder: "Rechercher", primary: "Navigation principale" },
802
+ imageViewer: { reset: "R\xE9initialiser", download: "T\xE9l\xE9charger" }
749
803
  };
750
804
  var deDE = {
751
805
  locale: "de-DE",
@@ -769,13 +823,15 @@ var deDE = {
769
823
  },
770
824
  timePicker: { am: "AM", pm: "PM" },
771
825
  pagination: { previous: "Zur\xFCck", next: "Weiter" },
772
- modal: { close: "Schlie\xDFen" },
826
+ modal: { close: "Schlie\xDFen", maximize: "Maximieren", restore: "Wiederherstellen" },
827
+ select: { placeholder: "Ausw\xE4hlen" },
828
+ counterInput: { decrease: "Verringern", increase: "Erh\xF6hen" },
773
829
  drawer: { close: "Schlie\xDFen" },
774
830
  alert: { dismiss: "Schlie\xDFen" },
775
831
  banner: { dismiss: "Schlie\xDFen" },
776
832
  toast: { dismiss: "Schlie\xDFen" },
777
833
  fileUpload: { clickToUpload: "Zum Hochladen klicken", orDragAndDrop: "oder per Drag & Drop" },
778
- imageUpload: { label: "Bild hochladen", remove: "Entfernen" },
834
+ imageUpload: { label: "Bild hochladen", remove: "Entfernen", hint: "PNG oder JPG, bis zu 5 MB" },
779
835
  passwordStrength: { weak: "Schwach", fair: "Mittel", good: "Gut", strong: "Stark" },
780
836
  commandMenu: {
781
837
  placeholder: "Befehl eingeben oder suchen\u2026",
@@ -838,8 +894,17 @@ var deDE = {
838
894
  previous: "Zur\xFCck",
839
895
  next: "Weiter",
840
896
  pageRange: "{from}\u2013{to} von {total}",
841
- perPage: "{size} / Seite"
842
- }
897
+ perPage: "{size} / Seite",
898
+ selectRow: "Zeile ausw\xE4hlen",
899
+ selectAll: "Alle ausw\xE4hlen"
900
+ },
901
+ wizard: { back: "Atr\xE1s", next: "Siguiente", finish: "Finalizar" },
902
+ a11y: { zoomIn: "Vergr\xF6\xDFern", zoomOut: "Verkleinern", rotate: "Drehen", collapseStart: "Startbereich einklappen", collapseEnd: "Endbereich einklappen", bulkActions: "Mehrfachaktionen", clearSelection: "Auswahl aufheben", back: "Zur\xFCck" },
903
+ richEditor: { placeholder: "Etwas eingeben\u2026", editorLabel: "Rich-Text-Editor" },
904
+ copy: { label: "Kopieren" },
905
+ emojiPicker: { searchPlaceholder: "Emoji suchen", emptyText: "Kein Emoji gefunden", addReaction: "Reaktion hinzuf\xFCgen" },
906
+ sidebar: { searchPlaceholder: "Suchen", primary: "Hauptnavigation" },
907
+ imageViewer: { reset: "Zur\xFCcksetzen", download: "Herunterladen" }
843
908
  };
844
909
  var esES = {
845
910
  locale: "es-ES",
@@ -863,13 +928,15 @@ var esES = {
863
928
  },
864
929
  timePicker: { am: "AM", pm: "PM" },
865
930
  pagination: { previous: "Anterior", next: "Siguiente" },
866
- modal: { close: "Cerrar" },
931
+ modal: { close: "Cerrar", maximize: "Maximizar", restore: "Restaurar" },
932
+ select: { placeholder: "Seleccionar" },
933
+ counterInput: { decrease: "Disminuir", increase: "Aumentar" },
867
934
  drawer: { close: "Cerrar" },
868
935
  alert: { dismiss: "Cerrar" },
869
936
  banner: { dismiss: "Cerrar" },
870
937
  toast: { dismiss: "Cerrar" },
871
938
  fileUpload: { clickToUpload: "Haz clic para subir", orDragAndDrop: "o arrastra y suelta" },
872
- imageUpload: { label: "Subir imagen", remove: "Eliminar" },
939
+ imageUpload: { label: "Subir imagen", remove: "Eliminar", hint: "PNG o JPG, hasta 5 MB" },
873
940
  passwordStrength: { weak: "D\xE9bil", fair: "Regular", good: "Buena", strong: "Fuerte" },
874
941
  commandMenu: {
875
942
  placeholder: "Escribe un comando o busca\u2026",
@@ -932,8 +999,17 @@ var esES = {
932
999
  previous: "Anterior",
933
1000
  next: "Siguiente",
934
1001
  pageRange: "{from}\u2013{to} de {total}",
935
- perPage: "{size} / p\xE1gina"
936
- }
1002
+ perPage: "{size} / p\xE1gina",
1003
+ selectRow: "Seleccionar fila",
1004
+ selectAll: "Seleccionar todo"
1005
+ },
1006
+ wizard: { back: "Voltar", next: "Avan\xE7ar", finish: "Concluir" },
1007
+ a11y: { zoomIn: "Acercar", zoomOut: "Alejar", rotate: "Girar", collapseStart: "Contraer panel inicial", collapseEnd: "Contraer panel final", bulkActions: "Acciones masivas", clearSelection: "Borrar selecci\xF3n", back: "Atr\xE1s" },
1008
+ richEditor: { placeholder: "Escribe algo\u2026", editorLabel: "Editor de texto enriquecido" },
1009
+ copy: { label: "Copiar" },
1010
+ emojiPicker: { searchPlaceholder: "Buscar emoji", emptyText: "No se encontraron emojis", addReaction: "A\xF1adir reacci\xF3n" },
1011
+ sidebar: { searchPlaceholder: "Buscar", primary: "Navegaci\xF3n principal" },
1012
+ imageViewer: { reset: "Restablecer", download: "Descargar" }
937
1013
  };
938
1014
  var ptBR = {
939
1015
  locale: "pt-BR",
@@ -957,13 +1033,15 @@ var ptBR = {
957
1033
  },
958
1034
  timePicker: { am: "AM", pm: "PM" },
959
1035
  pagination: { previous: "Anterior", next: "Pr\xF3ximo" },
960
- modal: { close: "Fechar" },
1036
+ modal: { close: "Fechar", maximize: "Maximizar", restore: "Restaurar" },
1037
+ select: { placeholder: "Selecionar" },
1038
+ counterInput: { decrease: "Diminuir", increase: "Aumentar" },
961
1039
  drawer: { close: "Fechar" },
962
1040
  alert: { dismiss: "Fechar" },
963
1041
  banner: { dismiss: "Fechar" },
964
1042
  toast: { dismiss: "Fechar" },
965
1043
  fileUpload: { clickToUpload: "Clique para enviar", orDragAndDrop: "ou arraste e solte" },
966
- imageUpload: { label: "Enviar imagem", remove: "Remover" },
1044
+ imageUpload: { label: "Enviar imagem", remove: "Remover", hint: "PNG ou JPG, at\xE9 5 MB" },
967
1045
  passwordStrength: { weak: "Fraca", fair: "Razo\xE1vel", good: "Boa", strong: "Forte" },
968
1046
  commandMenu: {
969
1047
  placeholder: "Digite um comando ou pesquise\u2026",
@@ -1026,8 +1104,17 @@ var ptBR = {
1026
1104
  previous: "Anterior",
1027
1105
  next: "Pr\xF3ximo",
1028
1106
  pageRange: "{from}\u2013{to} de {total}",
1029
- perPage: "{size} / p\xE1gina"
1030
- }
1107
+ perPage: "{size} / p\xE1gina",
1108
+ selectRow: "Selecionar linha",
1109
+ selectAll: "Selecionar tudo"
1110
+ },
1111
+ wizard: { back: "\u041D\u0430\u0437\u0430\u0434", next: "\u0414\u0430\u043B\u0435\u0435", finish: "\u0413\u043E\u0442\u043E\u0432\u043E" },
1112
+ a11y: { zoomIn: "Ampliar", zoomOut: "Reduzir", rotate: "Girar", collapseStart: "Recolher painel inicial", collapseEnd: "Recolher painel final", bulkActions: "A\xE7\xF5es em massa", clearSelection: "Limpar sele\xE7\xE3o", back: "Voltar" },
1113
+ richEditor: { placeholder: "Escreva algo\u2026", editorLabel: "Editor de texto rico" },
1114
+ copy: { label: "Copiar" },
1115
+ emojiPicker: { searchPlaceholder: "Pesquisar emoji", emptyText: "Nenhum emoji encontrado", addReaction: "Adicionar rea\xE7\xE3o" },
1116
+ sidebar: { searchPlaceholder: "Pesquisar", primary: "Navega\xE7\xE3o principal" },
1117
+ imageViewer: { reset: "Redefinir", download: "Baixar" }
1031
1118
  };
1032
1119
  var ruRU = {
1033
1120
  locale: "ru-RU",
@@ -1051,13 +1138,15 @@ var ruRU = {
1051
1138
  },
1052
1139
  timePicker: { am: "AM", pm: "PM" },
1053
1140
  pagination: { previous: "\u041D\u0430\u0437\u0430\u0434", next: "\u0412\u043F\u0435\u0440\u0451\u0434" },
1054
- modal: { close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1141
+ modal: { close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C", maximize: "\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C", restore: "\u0412\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C" },
1142
+ select: { placeholder: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C" },
1143
+ counterInput: { decrease: "\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u0442\u044C", increase: "\u0423\u0432\u0435\u043B\u0438\u0447\u0438\u0442\u044C" },
1055
1144
  drawer: { close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1056
1145
  alert: { dismiss: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1057
1146
  banner: { dismiss: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1058
1147
  toast: { dismiss: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1059
1148
  fileUpload: { clickToUpload: "\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438", orDragAndDrop: "\u0438\u043B\u0438 \u043F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435" },
1060
- imageUpload: { label: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435", remove: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" },
1149
+ imageUpload: { label: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435", remove: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C", hint: "PNG \u0438\u043B\u0438 JPG, \u0434\u043E 5 \u041C\u0411" },
1061
1150
  passwordStrength: { weak: "\u0421\u043B\u0430\u0431\u044B\u0439", fair: "\u0421\u0440\u0435\u0434\u043D\u0438\u0439", good: "\u0425\u043E\u0440\u043E\u0448\u0438\u0439", strong: "\u041D\u0430\u0434\u0451\u0436\u043D\u044B\u0439" },
1062
1151
  commandMenu: {
1063
1152
  placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043A\u043E\u043C\u0430\u043D\u0434\u0443 \u0438\u043B\u0438 \u043F\u043E\u0438\u0441\u043A\u2026",
@@ -1120,8 +1209,17 @@ var ruRU = {
1120
1209
  previous: "\u041D\u0430\u0437\u0430\u0434",
1121
1210
  next: "\u0412\u043F\u0435\u0440\u0451\u0434",
1122
1211
  pageRange: "{from}\u2013{to} \u0438\u0437 {total}",
1123
- perPage: "{size} / \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430"
1124
- }
1212
+ perPage: "{size} / \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
1213
+ selectRow: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0441\u0442\u0440\u043E\u043A\u0443",
1214
+ selectAll: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u0441\u0435"
1215
+ },
1216
+ wizard: { back: "\u0631\u062C\u0648\u0639", next: "\u0627\u0644\u062A\u0627\u0644\u064A", finish: "\u0625\u0646\u0647\u0627\u0621" },
1217
+ a11y: { zoomIn: "\u0423\u0432\u0435\u043B\u0438\u0447\u0438\u0442\u044C", zoomOut: "\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u0442\u044C", rotate: "\u041F\u043E\u0432\u0435\u0440\u043D\u0443\u0442\u044C", collapseStart: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u043D\u0430\u0447\u0430\u043B\u044C\u043D\u0443\u044E \u043F\u0430\u043D\u0435\u043B\u044C", collapseEnd: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u043A\u043E\u043D\u0435\u0447\u043D\u0443\u044E \u043F\u0430\u043D\u0435\u043B\u044C", bulkActions: "\u041C\u0430\u0441\u0441\u043E\u0432\u044B\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F", clearSelection: "\u0421\u043D\u044F\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435", back: "\u041D\u0430\u0437\u0430\u0434" },
1218
+ richEditor: { placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\u2026", editorLabel: "\u0420\u0435\u0434\u0430\u043A\u0442\u043E\u0440 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E \u0442\u0435\u043A\u0441\u0442\u0430" },
1219
+ copy: { label: "\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C" },
1220
+ emojiPicker: { searchPlaceholder: "\u041F\u043E\u0438\u0441\u043A \u044D\u043C\u043E\u0434\u0437\u0438", emptyText: "\u042D\u043C\u043E\u0434\u0437\u0438 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u044B", addReaction: "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0440\u0435\u0430\u043A\u0446\u0438\u044E" },
1221
+ sidebar: { searchPlaceholder: "\u041F\u043E\u0438\u0441\u043A", primary: "\u041E\u0441\u043D\u043E\u0432\u043D\u0430\u044F \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044F" },
1222
+ imageViewer: { reset: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C", download: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C" }
1125
1223
  };
1126
1224
  var arSA = {
1127
1225
  locale: "ar-SA",
@@ -1145,13 +1243,15 @@ var arSA = {
1145
1243
  },
1146
1244
  timePicker: { am: "\u0635", pm: "\u0645" },
1147
1245
  pagination: { previous: "\u0627\u0644\u0633\u0627\u0628\u0642", next: "\u0627\u0644\u062A\u0627\u0644\u064A" },
1148
- modal: { close: "\u0625\u063A\u0644\u0627\u0642" },
1246
+ modal: { close: "\u0625\u063A\u0644\u0627\u0642", maximize: "\u062A\u0643\u0628\u064A\u0631", restore: "\u0627\u0633\u062A\u0639\u0627\u062F\u0629" },
1247
+ select: { placeholder: "\u062A\u062D\u062F\u064A\u062F" },
1248
+ counterInput: { decrease: "\u062A\u0642\u0644\u064A\u0644", increase: "\u0632\u064A\u0627\u062F\u0629" },
1149
1249
  drawer: { close: "\u0625\u063A\u0644\u0627\u0642" },
1150
1250
  alert: { dismiss: "\u0625\u063A\u0644\u0627\u0642" },
1151
1251
  banner: { dismiss: "\u0625\u063A\u0644\u0627\u0642" },
1152
1252
  toast: { dismiss: "\u0625\u063A\u0644\u0627\u0642" },
1153
1253
  fileUpload: { clickToUpload: "\u0627\u0646\u0642\u0631 \u0644\u0644\u0631\u0641\u0639", orDragAndDrop: "\u0623\u0648 \u0627\u0633\u062D\u0628 \u0648\u0623\u0641\u0644\u062A" },
1154
- imageUpload: { label: "\u0631\u0641\u0639 \u0635\u0648\u0631\u0629", remove: "\u0625\u0632\u0627\u0644\u0629" },
1254
+ imageUpload: { label: "\u0631\u0641\u0639 \u0635\u0648\u0631\u0629", remove: "\u0625\u0632\u0627\u0644\u0629", hint: "PNG \u0623\u0648 JPG\u060C \u062D\u062A\u0649 5 \u0645\u064A\u062C\u0627\u0628\u0627\u064A\u062A" },
1155
1255
  passwordStrength: { weak: "\u0636\u0639\u064A\u0641", fair: "\u0645\u0642\u0628\u0648\u0644", good: "\u062C\u064A\u062F", strong: "\u0642\u0648\u064A" },
1156
1256
  commandMenu: {
1157
1257
  placeholder: "\u0627\u0643\u062A\u0628 \u0623\u0645\u0631\u064B\u0627 \u0623\u0648 \u0627\u0628\u062D\u062B\u2026",
@@ -1214,8 +1314,17 @@ var arSA = {
1214
1314
  previous: "\u0627\u0644\u0633\u0627\u0628\u0642",
1215
1315
  next: "\u0627\u0644\u062A\u0627\u0644\u064A",
1216
1316
  pageRange: "{from}\u2013{to} \u0645\u0646 {total}",
1217
- perPage: "{size} / \u0635\u0641\u062D\u0629"
1218
- }
1317
+ perPage: "{size} / \u0635\u0641\u062D\u0629",
1318
+ selectRow: "\u062A\u062D\u062F\u064A\u062F \u0627\u0644\u0635\u0641",
1319
+ selectAll: "\u062A\u062D\u062F\u064A\u062F \u0627\u0644\u0643\u0644"
1320
+ },
1321
+ wizard: { back: "Indietro", next: "Avanti", finish: "Fine" },
1322
+ a11y: { zoomIn: "\u062A\u0643\u0628\u064A\u0631", zoomOut: "\u062A\u0635\u063A\u064A\u0631", rotate: "\u062A\u062F\u0648\u064A\u0631", collapseStart: "\u0637\u064A \u0627\u0644\u0644\u0648\u062D\u0629 \u0627\u0644\u0623\u0648\u0644\u0649", collapseEnd: "\u0637\u064A \u0627\u0644\u0644\u0648\u062D\u0629 \u0627\u0644\u0623\u062E\u064A\u0631\u0629", bulkActions: "\u0625\u062C\u0631\u0627\u0621\u0627\u062A \u062C\u0645\u0627\u0639\u064A\u0629", clearSelection: "\u0625\u0644\u063A\u0627\u0621 \u0627\u0644\u062A\u062D\u062F\u064A\u062F", back: "\u0631\u062C\u0648\u0639" },
1323
+ richEditor: { placeholder: "\u0627\u0643\u062A\u0628 \u0634\u064A\u0626\u064B\u0627\u2026", editorLabel: "\u0645\u062D\u0631\u0631 \u0646\u0635 \u0645\u0646\u0633\u0642" },
1324
+ copy: { label: "\u0646\u0633\u062E" },
1325
+ emojiPicker: { searchPlaceholder: "\u0627\u0644\u0628\u062D\u062B \u0639\u0646 \u0631\u0645\u0632 \u062A\u0639\u0628\u064A\u0631\u064A", emptyText: "\u0644\u0645 \u064A\u062A\u0645 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0631\u0645\u0648\u0632", addReaction: "\u0625\u0636\u0627\u0641\u0629 \u062A\u0641\u0627\u0639\u0644" },
1326
+ sidebar: { searchPlaceholder: "\u0628\u062D\u062B", primary: "\u0627\u0644\u062A\u0646\u0642\u0644 \u0627\u0644\u0631\u0626\u064A\u0633\u064A" },
1327
+ imageViewer: { reset: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646", download: "\u062A\u0646\u0632\u064A\u0644" }
1219
1328
  };
1220
1329
  var itIT = {
1221
1330
  locale: "it-IT",
@@ -1239,13 +1348,15 @@ var itIT = {
1239
1348
  },
1240
1349
  timePicker: { am: "AM", pm: "PM" },
1241
1350
  pagination: { previous: "Precedente", next: "Successivo" },
1242
- modal: { close: "Chiudi" },
1351
+ modal: { close: "Chiudi", maximize: "Ingrandisci", restore: "Ripristina" },
1352
+ select: { placeholder: "Seleziona" },
1353
+ counterInput: { decrease: "Diminuisci", increase: "Aumenta" },
1243
1354
  drawer: { close: "Chiudi" },
1244
1355
  alert: { dismiss: "Chiudi" },
1245
1356
  banner: { dismiss: "Chiudi" },
1246
1357
  toast: { dismiss: "Chiudi" },
1247
1358
  fileUpload: { clickToUpload: "Clicca per caricare", orDragAndDrop: "o trascina qui" },
1248
- imageUpload: { label: "Carica immagine", remove: "Rimuovi" },
1359
+ imageUpload: { label: "Carica immagine", remove: "Rimuovi", hint: "PNG o JPG, fino a 5 MB" },
1249
1360
  passwordStrength: { weak: "Debole", fair: "Discreta", good: "Buona", strong: "Forte" },
1250
1361
  commandMenu: {
1251
1362
  placeholder: "Digita un comando o cerca\u2026",
@@ -1308,8 +1419,17 @@ var itIT = {
1308
1419
  previous: "Precedente",
1309
1420
  next: "Successivo",
1310
1421
  pageRange: "{from}\u2013{to} di {total}",
1311
- perPage: "{size} / pagina"
1312
- }
1422
+ perPage: "{size} / pagina",
1423
+ selectRow: "Seleziona riga",
1424
+ selectAll: "Seleziona tutto"
1425
+ },
1426
+ wizard: { back: "Terug", next: "Volgende", finish: "Voltooien" },
1427
+ a11y: { zoomIn: "Ingrandisci", zoomOut: "Riduci", rotate: "Ruota", collapseStart: "Comprimi pannello iniziale", collapseEnd: "Comprimi pannello finale", bulkActions: "Azioni multiple", clearSelection: "Cancella selezione", back: "Indietro" },
1428
+ richEditor: { placeholder: "Scrivi qualcosa\u2026", editorLabel: "Editor di testo formattato" },
1429
+ copy: { label: "Copia" },
1430
+ emojiPicker: { searchPlaceholder: "Cerca emoji", emptyText: "Nessun emoji trovato", addReaction: "Aggiungi reazione" },
1431
+ sidebar: { searchPlaceholder: "Cerca", primary: "Navigazione principale" },
1432
+ imageViewer: { reset: "Reimposta", download: "Scarica" }
1313
1433
  };
1314
1434
  var nlNL = {
1315
1435
  locale: "nl-NL",
@@ -1333,13 +1453,15 @@ var nlNL = {
1333
1453
  },
1334
1454
  timePicker: { am: "AM", pm: "PM" },
1335
1455
  pagination: { previous: "Vorige", next: "Volgende" },
1336
- modal: { close: "Sluiten" },
1456
+ modal: { close: "Sluiten", maximize: "maximaliseren", restore: "Herstellen" },
1457
+ select: { placeholder: "Selecteren" },
1458
+ counterInput: { decrease: "Verlagen", increase: "Verhogen" },
1337
1459
  drawer: { close: "Sluiten" },
1338
1460
  alert: { dismiss: "Sluiten" },
1339
1461
  banner: { dismiss: "Sluiten" },
1340
1462
  toast: { dismiss: "Sluiten" },
1341
1463
  fileUpload: { clickToUpload: "Klik om te uploaden", orDragAndDrop: "of sleep hierheen" },
1342
- imageUpload: { label: "Afbeelding uploaden", remove: "Verwijderen" },
1464
+ imageUpload: { label: "Afbeelding uploaden", remove: "Verwijderen", hint: "PNG of JPG, max. 5 MB" },
1343
1465
  passwordStrength: { weak: "Zwak", fair: "Redelijk", good: "Goed", strong: "Sterk" },
1344
1466
  commandMenu: {
1345
1467
  placeholder: "Typ een opdracht of zoek\u2026",
@@ -1402,8 +1524,17 @@ var nlNL = {
1402
1524
  previous: "Vorige",
1403
1525
  next: "Volgende",
1404
1526
  pageRange: "{from}\u2013{to} van {total}",
1405
- perPage: "{size} / pagina"
1406
- }
1527
+ perPage: "{size} / pagina",
1528
+ selectRow: "Rij selecteren",
1529
+ selectAll: "Alles selecteren"
1530
+ },
1531
+ wizard: { back: "Wstecz", next: "Dalej", finish: "Zako\u0144cz" },
1532
+ a11y: { zoomIn: "Inzoomen", zoomOut: "Uitzoomen", rotate: "Roteren", collapseStart: "Startpaneel samenvouwen", collapseEnd: "Eindpaneel samenvouwen", bulkActions: "Bulkacties", clearSelection: "Selectie wissen", back: "Terug" },
1533
+ richEditor: { placeholder: "Schrijf iets\u2026", editorLabel: "Rich text-editor" },
1534
+ copy: { label: "Kopi\xEBren" },
1535
+ emojiPicker: { searchPlaceholder: "Emoji zoeken", emptyText: "Geen emoji gevonden", addReaction: "Reactie toevoegen" },
1536
+ sidebar: { searchPlaceholder: "Zoeken", primary: "Hoofdnavigatie" },
1537
+ imageViewer: { reset: "Herstellen", download: "Downloaden" }
1407
1538
  };
1408
1539
  var plPL = {
1409
1540
  locale: "pl-PL",
@@ -1427,13 +1558,15 @@ var plPL = {
1427
1558
  },
1428
1559
  timePicker: { am: "AM", pm: "PM" },
1429
1560
  pagination: { previous: "Poprzednia", next: "Nast\u0119pna" },
1430
- modal: { close: "Zamknij" },
1561
+ modal: { close: "Zamknij", maximize: "Maksymalizuj", restore: "Przywr\xF3\u0107" },
1562
+ select: { placeholder: "Wybierz" },
1563
+ counterInput: { decrease: "Zmniejsz", increase: "Zwi\u0119ksz" },
1431
1564
  drawer: { close: "Zamknij" },
1432
1565
  alert: { dismiss: "Zamknij" },
1433
1566
  banner: { dismiss: "Zamknij" },
1434
1567
  toast: { dismiss: "Zamknij" },
1435
1568
  fileUpload: { clickToUpload: "Kliknij, aby przes\u0142a\u0107", orDragAndDrop: "lub przeci\u0105gnij i upu\u015B\u0107" },
1436
- imageUpload: { label: "Prze\u015Blij obraz", remove: "Usu\u0144" },
1569
+ imageUpload: { label: "Prze\u015Blij obraz", remove: "Usu\u0144", hint: "PNG lub JPG, do 5 MB" },
1437
1570
  passwordStrength: { weak: "S\u0142abe", fair: "\u015Arednie", good: "Dobre", strong: "Silne" },
1438
1571
  commandMenu: {
1439
1572
  placeholder: "Wpisz polecenie lub szukaj\u2026",
@@ -1496,8 +1629,17 @@ var plPL = {
1496
1629
  previous: "Poprzednia",
1497
1630
  next: "Nast\u0119pna",
1498
1631
  pageRange: "{from}\u2013{to} z {total}",
1499
- perPage: "{size} / strona"
1500
- }
1632
+ perPage: "{size} / strona",
1633
+ selectRow: "Zaznacz wiersz",
1634
+ selectAll: "Zaznacz wszystko"
1635
+ },
1636
+ wizard: { back: "Geri", next: "\u0130leri", finish: "Bitir" },
1637
+ a11y: { zoomIn: "Powi\u0119ksz", zoomOut: "Pomniejsz", rotate: "Obr\xF3\u0107", collapseStart: "Zwi\u0144 panel pocz\u0105tkowy", collapseEnd: "Zwi\u0144 panel ko\u0144cowy", bulkActions: "Akcje zbiorcze", clearSelection: "Wyczy\u015B\u0107 zaznaczenie", back: "Wstecz" },
1638
+ richEditor: { placeholder: "Wpisz co\u015B\u2026", editorLabel: "Edytor tekstu sformatowanego" },
1639
+ copy: { label: "Kopiuj" },
1640
+ emojiPicker: { searchPlaceholder: "Szukaj emoji", emptyText: "Nie znaleziono emoji", addReaction: "Dodaj reakcj\u0119" },
1641
+ sidebar: { searchPlaceholder: "Szukaj", primary: "Nawigacja g\u0142\xF3wna" },
1642
+ imageViewer: { reset: "Resetuj", download: "Pobierz" }
1501
1643
  };
1502
1644
  var trTR = {
1503
1645
  locale: "tr-TR",
@@ -1521,13 +1663,15 @@ var trTR = {
1521
1663
  },
1522
1664
  timePicker: { am: "\xD6\xD6", pm: "\xD6S" },
1523
1665
  pagination: { previous: "\xD6nceki", next: "Sonraki" },
1524
- modal: { close: "Kapat" },
1666
+ modal: { close: "Kapat", maximize: "Ekran\u0131 kapla", restore: "Geri y\xFCkle" },
1667
+ select: { placeholder: "Se\xE7" },
1668
+ counterInput: { decrease: "Azalt", increase: "Art\u0131r" },
1525
1669
  drawer: { close: "Kapat" },
1526
1670
  alert: { dismiss: "Kapat" },
1527
1671
  banner: { dismiss: "Kapat" },
1528
1672
  toast: { dismiss: "Kapat" },
1529
1673
  fileUpload: { clickToUpload: "Y\xFCklemek i\xE7in t\u0131klay\u0131n", orDragAndDrop: "veya s\xFCr\xFCkleyip b\u0131rak\u0131n" },
1530
- imageUpload: { label: "G\xF6rsel y\xFCkle", remove: "Kald\u0131r" },
1674
+ imageUpload: { label: "G\xF6rsel y\xFCkle", remove: "Kald\u0131r", hint: "PNG veya JPG, en fazla 5 MB" },
1531
1675
  passwordStrength: { weak: "Zay\u0131f", fair: "Orta", good: "\u0130yi", strong: "G\xFC\xE7l\xFC" },
1532
1676
  commandMenu: {
1533
1677
  placeholder: "Bir komut yaz\u0131n veya aray\u0131n\u2026",
@@ -1590,8 +1734,17 @@ var trTR = {
1590
1734
  previous: "\xD6nceki",
1591
1735
  next: "Sonraki",
1592
1736
  pageRange: "{total} \xF6\u011Feden {from}\u2013{to}",
1593
- perPage: "{size} / sayfa"
1594
- }
1737
+ perPage: "{size} / sayfa",
1738
+ selectRow: "Sat\u0131r\u0131 se\xE7",
1739
+ selectAll: "T\xFCm\xFCn\xFC se\xE7"
1740
+ },
1741
+ wizard: { back: "Quay l\u1EA1i", next: "Ti\u1EBFp theo", finish: "Ho\xE0n t\u1EA5t" },
1742
+ a11y: { zoomIn: "Yak\u0131nla\u015Ft\u0131r", zoomOut: "Uzakla\u015Ft\u0131r", rotate: "D\xF6nd\xFCr", collapseStart: "Ba\u015Flang\u0131\xE7 panelini daralt", collapseEnd: "Biti\u015F panelini daralt", bulkActions: "Toplu i\u015Flemler", clearSelection: "Se\xE7imi temizle", back: "Geri" },
1743
+ richEditor: { placeholder: "Bir \u015Feyler yaz\u0131n\u2026", editorLabel: "Zengin metin d\xFCzenleyici" },
1744
+ copy: { label: "Kopyala" },
1745
+ emojiPicker: { searchPlaceholder: "Emoji ara", emptyText: "Emoji bulunamad\u0131", addReaction: "Tepki ekle" },
1746
+ sidebar: { searchPlaceholder: "Ara", primary: "Ana gezinme" },
1747
+ imageViewer: { reset: "S\u0131f\u0131rla", download: "\u0130ndir" }
1595
1748
  };
1596
1749
  var viVN = {
1597
1750
  locale: "vi-VN",
@@ -1615,13 +1768,15 @@ var viVN = {
1615
1768
  },
1616
1769
  timePicker: { am: "SA", pm: "CH" },
1617
1770
  pagination: { previous: "Tr\u01B0\u1EDBc", next: "Sau" },
1618
- modal: { close: "\u0110\xF3ng" },
1771
+ modal: { close: "\u0110\xF3ng", maximize: "Ph\xF3ng to", restore: "Kh\xF4i ph\u1EE5c" },
1772
+ select: { placeholder: "Ch\u1ECDn" },
1773
+ counterInput: { decrease: "Gi\u1EA3m", increase: "T\u0103ng" },
1619
1774
  drawer: { close: "\u0110\xF3ng" },
1620
1775
  alert: { dismiss: "\u0110\xF3ng" },
1621
1776
  banner: { dismiss: "\u0110\xF3ng" },
1622
1777
  toast: { dismiss: "\u0110\xF3ng" },
1623
1778
  fileUpload: { clickToUpload: "Nh\u1EA5p \u0111\u1EC3 t\u1EA3i l\xEAn", orDragAndDrop: "ho\u1EB7c k\xE9o v\xE0 th\u1EA3" },
1624
- imageUpload: { label: "T\u1EA3i \u1EA3nh l\xEAn", remove: "X\xF3a" },
1779
+ imageUpload: { label: "T\u1EA3i \u1EA3nh l\xEAn", remove: "X\xF3a", hint: "PNG ho\u1EB7c JPG, t\u1ED1i \u0111a 5MB" },
1625
1780
  passwordStrength: { weak: "Y\u1EBFu", fair: "Trung b\xECnh", good: "T\u1ED1t", strong: "M\u1EA1nh" },
1626
1781
  commandMenu: {
1627
1782
  placeholder: "Nh\u1EADp l\u1EC7nh ho\u1EB7c t\xECm ki\u1EBFm\u2026",
@@ -1684,8 +1839,17 @@ var viVN = {
1684
1839
  previous: "Tr\u01B0\u1EDBc",
1685
1840
  next: "Sau",
1686
1841
  pageRange: "{from}\u2013{to} trong {total}",
1687
- perPage: "{size} / trang"
1688
- }
1842
+ perPage: "{size} / trang",
1843
+ selectRow: "Ch\u1ECDn h\xE0ng",
1844
+ selectAll: "Ch\u1ECDn t\u1EA5t c\u1EA3"
1845
+ },
1846
+ wizard: { back: "Kembali", next: "Berikutnya", finish: "Selesai" },
1847
+ a11y: { zoomIn: "Ph\xF3ng to", zoomOut: "Thu nh\u1ECF", rotate: "Xoay", collapseStart: "Thu g\u1ECDn b\u1EA3ng \u0111\u1EA7u", collapseEnd: "Thu g\u1ECDn b\u1EA3ng cu\u1ED1i", bulkActions: "Thao t\xE1c h\xE0ng lo\u1EA1t", clearSelection: "B\u1ECF ch\u1ECDn", back: "Quay l\u1EA1i" },
1848
+ richEditor: { placeholder: "Vi\u1EBFt n\u1ED9i dung\u2026", editorLabel: "Tr\xECnh so\u1EA1n th\u1EA3o v\u0103n b\u1EA3n" },
1849
+ copy: { label: "Sao ch\xE9p" },
1850
+ emojiPicker: { searchPlaceholder: "T\xECm emoji", emptyText: "Kh\xF4ng t\xECm th\u1EA5y emoji", addReaction: "Th\xEAm c\u1EA3m x\xFAc" },
1851
+ sidebar: { searchPlaceholder: "T\xECm ki\u1EBFm", primary: "\u0110i\u1EC1u h\u01B0\u1EDBng ch\xEDnh" },
1852
+ imageViewer: { reset: "\u0110\u1EB7t l\u1EA1i", download: "T\u1EA3i xu\u1ED1ng" }
1689
1853
  };
1690
1854
  var idID = {
1691
1855
  locale: "id-ID",
@@ -1709,13 +1873,15 @@ var idID = {
1709
1873
  },
1710
1874
  timePicker: { am: "AM", pm: "PM" },
1711
1875
  pagination: { previous: "Sebelumnya", next: "Berikutnya" },
1712
- modal: { close: "Tutup" },
1876
+ modal: { close: "Tutup", maximize: "Maksimalkan", restore: "Pulihkan" },
1877
+ select: { placeholder: "Pilih" },
1878
+ counterInput: { decrease: "Kurangi", increase: "Tambah" },
1713
1879
  drawer: { close: "Tutup" },
1714
1880
  alert: { dismiss: "Tutup" },
1715
1881
  banner: { dismiss: "Tutup" },
1716
1882
  toast: { dismiss: "Tutup" },
1717
1883
  fileUpload: { clickToUpload: "Klik untuk mengunggah", orDragAndDrop: "atau seret dan lepas" },
1718
- imageUpload: { label: "Unggah gambar", remove: "Hapus" },
1884
+ imageUpload: { label: "Unggah gambar", remove: "Hapus", hint: "PNG atau JPG, maks. 5 MB" },
1719
1885
  passwordStrength: { weak: "Lemah", fair: "Cukup", good: "Baik", strong: "Kuat" },
1720
1886
  commandMenu: {
1721
1887
  placeholder: "Ketik perintah atau cari\u2026",
@@ -1778,8 +1944,17 @@ var idID = {
1778
1944
  previous: "Sebelumnya",
1779
1945
  next: "Berikutnya",
1780
1946
  pageRange: "{from}\u2013{to} dari {total}",
1781
- perPage: "{size} / halaman"
1782
- }
1947
+ perPage: "{size} / halaman",
1948
+ selectRow: "Pilih baris",
1949
+ selectAll: "Pilih semua"
1950
+ },
1951
+ wizard: { back: "Kembali", next: "Berikutnya", finish: "Selesai" },
1952
+ a11y: { zoomIn: "Perbesar", zoomOut: "Perkecil", rotate: "Putar", collapseStart: "Ciutkan panel awal", collapseEnd: "Ciutkan panel akhir", bulkActions: "Tindakan massal", clearSelection: "Hapus pilihan", back: "Kembali" },
1953
+ richEditor: { placeholder: "Tulis sesuatu\u2026", editorLabel: "Editor teks kaya" },
1954
+ copy: { label: "Salin" },
1955
+ emojiPicker: { searchPlaceholder: "Cari emoji", emptyText: "Emoji tidak ditemukan", addReaction: "Tambahkan reaksi" },
1956
+ sidebar: { searchPlaceholder: "Cari", primary: "Navigasi utama" },
1957
+ imageViewer: { reset: "Setel ulang", download: "Unduh" }
1783
1958
  };
1784
1959
  var locales = {
1785
1960
  enUS,
@@ -1875,6 +2050,7 @@ function ConfigProvider({
1875
2050
  {
1876
2051
  className: "klun-config",
1877
2052
  dir: value.dir,
2053
+ lang: (value.locale ?? enUS).locale,
1878
2054
  "data-theme": value.theme,
1879
2055
  "data-mode": value.accent,
1880
2056
  "data-radius": value.radius && value.radius !== "default" ? value.radius : void 0,
@@ -1955,15 +2131,14 @@ var Button = react.forwardRef(function Button2(props, ref) {
1955
2131
  size: _s2,
1956
2132
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1957
2133
  loading: _l2,
1958
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1959
- type: _t,
2134
+ type: type2 = "button",
1960
2135
  ...rest2
1961
2136
  } = props;
1962
2137
  return /* @__PURE__ */ jsxRuntime.jsxs(
1963
2138
  "button",
1964
2139
  {
1965
2140
  ref,
1966
- type: "button",
2141
+ type: type2,
1967
2142
  disabled: disabled2 || loading,
1968
2143
  "aria-busy": loading || void 0,
1969
2144
  className: chunkTPGAXYFU_cjs.cx(
@@ -2020,7 +2195,7 @@ var Button = react.forwardRef(function Button2(props, ref) {
2020
2195
  ...rest2,
2021
2196
  children: [
2022
2197
  loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-compact-button__icon", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: "klun-compact-button__spinner" }) }) : icon2 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-compact-button__icon", children: icon2 }) : null,
2023
- loading ? null : children2
2198
+ loading ? children2 != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-compact-button__label-sr", children: children2 }) : null : children2
2024
2199
  ]
2025
2200
  }
2026
2201
  );
@@ -2202,11 +2377,13 @@ var CopyButton = react.forwardRef(
2202
2377
  variant = "ghost",
2203
2378
  copyIcon = "ri-file-copy-line",
2204
2379
  doneIcon = "ri-check-line",
2205
- title = "Copy",
2380
+ title: titleProp,
2206
2381
  onClick,
2207
2382
  className,
2208
2383
  ...props
2209
2384
  }, ref) {
2385
+ const { copy: localeCopy } = useLocale();
2386
+ const title = titleProp ?? localeCopy.label;
2210
2387
  const [done, setDone] = react.useState(false);
2211
2388
  const timer = react.useRef(null);
2212
2389
  react.useEffect(() => () => clearTimeout(timer.current ?? void 0), []);
@@ -2583,6 +2760,7 @@ var BulkActionBar = react.forwardRef(
2583
2760
  className,
2584
2761
  ...props
2585
2762
  }, ref) {
2763
+ const { a11y } = useLocale();
2586
2764
  const visible = open != null ? open : count > 0;
2587
2765
  const [mounted, setMounted] = react.useState(visible);
2588
2766
  const [show, setShow] = react.useState(visible);
@@ -2603,7 +2781,7 @@ var BulkActionBar = react.forwardRef(
2603
2781
  {
2604
2782
  ref,
2605
2783
  role: "toolbar",
2606
- "aria-label": "Bulk actions",
2784
+ "aria-label": a11y.bulkActions,
2607
2785
  "data-show": show ? "" : void 0,
2608
2786
  className: chunkTPGAXYFU_cjs.cx(
2609
2787
  "klun-bulk-action-bar",
@@ -2624,8 +2802,8 @@ var BulkActionBar = react.forwardRef(
2624
2802
  {
2625
2803
  type: "button",
2626
2804
  onClick: onClear,
2627
- "aria-label": "Clear selection",
2628
- title: "Clear selection",
2805
+ "aria-label": a11y.clearSelection,
2806
+ title: a11y.clearSelection,
2629
2807
  className: "klun-bulk-action-bar__clear",
2630
2808
  children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-close-line", "aria-hidden": true })
2631
2809
  }
@@ -2669,6 +2847,16 @@ var Carousel = react.forwardRef(function Carousel2({
2669
2847
  const { carousel } = useLocale();
2670
2848
  const slides = react.Children.toArray(children);
2671
2849
  const count = slides.length;
2850
+ const rootRef = react.useRef(null);
2851
+ const hadFocusInside = react.useRef(false);
2852
+ const attachRootRef = react.useCallback(
2853
+ (el) => {
2854
+ rootRef.current = el;
2855
+ if (typeof ref === "function") ref(el);
2856
+ else if (ref) ref.current = el;
2857
+ },
2858
+ [ref]
2859
+ );
2672
2860
  const [inner, setInner] = react.useState(defaultIndex);
2673
2861
  const cur = index !== void 0 ? index : inner;
2674
2862
  const [hover, setHover] = react.useState(false);
@@ -2687,6 +2875,12 @@ var Carousel = react.forwardRef(function Carousel2({
2687
2875
  const id = setInterval(() => go(cur + 1), interval);
2688
2876
  return () => clearInterval(id);
2689
2877
  }, [autoplay, hover, cur, interval, count, go]);
2878
+ react.useEffect(() => {
2879
+ const root = rootRef.current;
2880
+ if (!root || !hadFocusInside.current) return;
2881
+ const active = document.activeElement;
2882
+ if (active && !root.contains(active)) root.focus();
2883
+ }, [cur]);
2690
2884
  const arrowBtn = (dir) => /* @__PURE__ */ jsxRuntime.jsx(
2691
2885
  "button",
2692
2886
  {
@@ -2700,11 +2894,20 @@ var Carousel = react.forwardRef(function Carousel2({
2700
2894
  return /* @__PURE__ */ jsxRuntime.jsxs(
2701
2895
  "div",
2702
2896
  {
2703
- ref,
2897
+ ref: attachRootRef,
2704
2898
  onMouseEnter: () => setHover(true),
2705
2899
  onMouseLeave: () => setHover(false),
2900
+ onFocus: () => {
2901
+ hadFocusInside.current = true;
2902
+ },
2903
+ onBlur: (e) => {
2904
+ if (e.relatedTarget) {
2905
+ hadFocusInside.current = rootRef.current?.contains(e.relatedTarget) ?? false;
2906
+ }
2907
+ },
2706
2908
  className: chunkTPGAXYFU_cjs.cx("klun-carousel", className),
2707
2909
  style: { height, ...style },
2910
+ tabIndex: -1,
2708
2911
  ...props,
2709
2912
  children: [
2710
2913
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2712,7 +2915,20 @@ var Carousel = react.forwardRef(function Carousel2({
2712
2915
  {
2713
2916
  className: "klun-carousel__track",
2714
2917
  style: { transform: `translateX(-${cur * 100}%)` },
2715
- children: slides.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-carousel__slide", children: s }, i))
2918
+ children: slides.map((s, i) => {
2919
+ const active = i === cur;
2920
+ return /* @__PURE__ */ jsxRuntime.jsx(
2921
+ "div",
2922
+ {
2923
+ className: "klun-carousel__slide",
2924
+ "data-active": active || void 0,
2925
+ ...!active ? { inert: "" } : {},
2926
+ "aria-hidden": !active || void 0,
2927
+ children: s
2928
+ },
2929
+ i
2930
+ );
2931
+ })
2716
2932
  }
2717
2933
  ),
2718
2934
  arrows && count > 1 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -3111,7 +3327,9 @@ function useTick(ms) {
3111
3327
  return () => clearInterval(id);
3112
3328
  }, [ms]);
3113
3329
  }
3114
- var RelativeTime = react.forwardRef(function RelativeTime2({ date, locale, live = true, every = 6e4, absolute, className, ...props }, ref) {
3330
+ var RelativeTime = react.forwardRef(function RelativeTime2({ date, locale: localeProp, live = true, every = 6e4, absolute, className, ...props }, ref) {
3331
+ const { locale: ctxLocaleName } = useLocale();
3332
+ const locale = localeProp ?? ctxLocaleName;
3115
3333
  useTick(live ? every : 0);
3116
3334
  const rel = Format.relTime(date, { locale });
3117
3335
  const title = Format.absTime(date, { locale });
@@ -4325,7 +4543,7 @@ var Money = react.forwardRef(function Money2({
4325
4543
  value,
4326
4544
  cents = false,
4327
4545
  currency = "USD",
4328
- locale,
4546
+ locale: localeProp,
4329
4547
  period,
4330
4548
  periodLabels,
4331
4549
  minimumFractionDigits,
@@ -4339,6 +4557,8 @@ var Money = react.forwardRef(function Money2({
4339
4557
  className,
4340
4558
  ...props
4341
4559
  }, ref) {
4560
+ const { locale: ctxLocaleName } = useLocale();
4561
+ const locale = localeProp ?? ctxLocaleName;
4342
4562
  const { text, period: periodSuffix } = Format.money(value, {
4343
4563
  currency,
4344
4564
  cents,
@@ -4386,7 +4606,9 @@ function Digit({ value }) {
4386
4606
  ) });
4387
4607
  }
4388
4608
  var NumberFlow = react.forwardRef(
4389
- function NumberFlow2({ value, locales: locales2, format, prefix, suffix, label, className, ...props }, ref) {
4609
+ function NumberFlow2({ value, locales: localesProp, format, prefix, suffix, label, className, ...props }, ref) {
4610
+ const { locale: ctxLocaleName } = useLocale();
4611
+ const locales2 = localesProp ?? ctxLocaleName;
4390
4612
  const text = new Intl.NumberFormat(locales2, {
4391
4613
  minimumFractionDigits: format?.minimumFractionDigits,
4392
4614
  maximumFractionDigits: format?.maximumFractionDigits,
@@ -4521,14 +4743,66 @@ var Rating = react.forwardRef(function Rating2({ value = 0, max = 5, onChange, r
4521
4743
  )) });
4522
4744
  });
4523
4745
  Rating.displayName = "Rating";
4524
- var Popover = react.forwardRef(function Popover2({ trigger, children, align = "left", width = 280, className, ...props }, ref) {
4525
- const [open, setOpen] = react.useState(false);
4746
+ var FOCUSABLE = [
4747
+ "a[href]",
4748
+ "button:not([disabled])",
4749
+ "input:not([disabled]):not([type='hidden'])",
4750
+ "select:not([disabled])",
4751
+ "textarea:not([disabled])",
4752
+ "[tabindex]:not([tabindex='-1'])"
4753
+ ].join(",");
4754
+ var ACTIVATABLE = [
4755
+ "button",
4756
+ "a[href]",
4757
+ "input[type='button']",
4758
+ "input[type='submit']",
4759
+ "input[type='reset']",
4760
+ "input[type='checkbox']",
4761
+ "input[type='radio']",
4762
+ "summary",
4763
+ "[role='button']",
4764
+ "[role='link']"
4765
+ ].join(",");
4766
+ var Popover = react.forwardRef(function Popover2({
4767
+ trigger,
4768
+ children,
4769
+ align = "start",
4770
+ width = 280,
4771
+ className,
4772
+ open,
4773
+ defaultOpen = false,
4774
+ onOpenChange,
4775
+ panelId,
4776
+ ...props
4777
+ }, ref) {
4778
+ const [internalOpen, setInternalOpen] = react.useState(defaultOpen);
4779
+ const controlled = open !== void 0;
4780
+ const isOpen = controlled ? Boolean(open) : internalOpen;
4781
+ const onOpenChangeRef = react.useRef(onOpenChange);
4782
+ onOpenChangeRef.current = onOpenChange;
4783
+ const setOpen = react.useCallback(
4784
+ (next) => {
4785
+ if (!controlled) setInternalOpen(next);
4786
+ onOpenChangeRef.current?.(next);
4787
+ },
4788
+ [controlled]
4789
+ );
4526
4790
  const wrapRef = react.useRef(null);
4791
+ const triggerRef = react.useRef(null);
4527
4792
  const panelRef = react.useRef(null);
4528
4793
  const portal = typeof document !== "undefined";
4529
4794
  const [pos, setPos] = react.useState(null);
4795
+ const generatedId = react.useId();
4796
+ const resolvedPanelId = panelId ?? `klun-popover-${generatedId}`;
4797
+ const [hasFocusableChild, setHasFocusableChild] = react.useState(false);
4530
4798
  react.useEffect(() => {
4531
- if (!open) return;
4799
+ const root = triggerRef.current;
4800
+ if (!root) return;
4801
+ setHasFocusableChild(root.querySelector(FOCUSABLE) != null);
4802
+ }, [trigger]);
4803
+ const openedByKeyboard = react.useRef(false);
4804
+ react.useEffect(() => {
4805
+ if (!isOpen) return;
4532
4806
  const h = (e) => {
4533
4807
  const t = e.target;
4534
4808
  if (wrapRef.current?.contains(t)) return;
@@ -4537,9 +4811,9 @@ var Popover = react.forwardRef(function Popover2({ trigger, children, align = "l
4537
4811
  };
4538
4812
  document.addEventListener("mousedown", h);
4539
4813
  return () => document.removeEventListener("mousedown", h);
4540
- }, [open]);
4814
+ }, [isOpen, setOpen]);
4541
4815
  react.useLayoutEffect(() => {
4542
- if (!open || !portal) return;
4816
+ if (!isOpen || !portal) return;
4543
4817
  const anchor = wrapRef.current;
4544
4818
  const panel2 = panelRef.current;
4545
4819
  if (!anchor || !panel2) return;
@@ -4552,7 +4826,9 @@ var Popover = react.forwardRef(function Popover2({ trigger, children, align = "l
4552
4826
  const below = window.innerHeight - a.bottom;
4553
4827
  const openUp = below < ph + gap && a.top > below;
4554
4828
  const top = openUp ? Math.max(margin, a.top - gap - ph) : Math.min(a.bottom + gap, window.innerHeight - margin - ph);
4555
- let left = align === "right" ? a.right - pw : a.left;
4829
+ const rtl = getComputedStyle(anchor).direction === "rtl";
4830
+ const side = align === "start" ? rtl ? "right" : "left" : align === "end" ? rtl ? "left" : "right" : align;
4831
+ let left = side === "right" ? a.right - pw : a.left;
4556
4832
  if (left + pw > window.innerWidth - margin) left = window.innerWidth - margin - pw;
4557
4833
  if (left < margin) left = margin;
4558
4834
  setPos({ left, top });
@@ -4564,10 +4840,58 @@ var Popover = react.forwardRef(function Popover2({ trigger, children, align = "l
4564
4840
  window.removeEventListener("scroll", place2, true);
4565
4841
  window.removeEventListener("resize", place2);
4566
4842
  };
4567
- }, [open, portal, align, width]);
4843
+ }, [isOpen, portal, align, width]);
4568
4844
  react.useEffect(() => {
4569
- if (!open) setPos(null);
4570
- }, [open]);
4845
+ if (!isOpen) setPos(null);
4846
+ }, [isOpen]);
4847
+ react.useLayoutEffect(() => {
4848
+ if (!isOpen || !openedByKeyboard.current) return;
4849
+ if (!pos) return;
4850
+ openedByKeyboard.current = false;
4851
+ const panel2 = panelRef.current;
4852
+ if (!panel2) return;
4853
+ const first = panel2.querySelector(FOCUSABLE);
4854
+ (first ?? panel2).focus?.();
4855
+ }, [isOpen, pos]);
4856
+ const focusTrigger = react.useCallback(() => {
4857
+ const root = triggerRef.current;
4858
+ if (!root) return;
4859
+ const inner = root.querySelector(FOCUSABLE);
4860
+ (inner ?? root).focus?.();
4861
+ }, []);
4862
+ const onPanelKeyDown = (e) => {
4863
+ if (e.key !== "Escape") return;
4864
+ e.stopPropagation();
4865
+ setOpen(false);
4866
+ focusTrigger();
4867
+ };
4868
+ const onTriggerKeyDown = (e) => {
4869
+ if (e.key === "Escape") {
4870
+ if (!isOpen) return;
4871
+ e.stopPropagation();
4872
+ setOpen(false);
4873
+ focusTrigger();
4874
+ return;
4875
+ }
4876
+ if (e.key === "ArrowDown") {
4877
+ e.preventDefault();
4878
+ if (!isOpen) {
4879
+ openedByKeyboard.current = true;
4880
+ setOpen(true);
4881
+ }
4882
+ return;
4883
+ }
4884
+ if (e.key === "Enter" || e.key === " ") {
4885
+ const target = e.target;
4886
+ const nativeActivation = target != null && target !== triggerRef.current && target.closest?.(ACTIVATABLE) != null;
4887
+ if (nativeActivation) return;
4888
+ if (!isOpen) {
4889
+ e.preventDefault();
4890
+ openedByKeyboard.current = true;
4891
+ setOpen(true);
4892
+ }
4893
+ }
4894
+ };
4571
4895
  const setRefs = (node) => {
4572
4896
  wrapRef.current = node;
4573
4897
  if (typeof ref === "function") ref(node);
@@ -4583,11 +4907,14 @@ var Popover = react.forwardRef(function Popover2({ trigger, children, align = "l
4583
4907
  // keep hidden until measured to avoid a flash at the top-left corner
4584
4908
  visibility: pos ? "visible" : "hidden"
4585
4909
  };
4586
- const panel = open ? /* @__PURE__ */ jsxRuntime.jsx(
4910
+ const panel = isOpen ? /* @__PURE__ */ jsxRuntime.jsx(
4587
4911
  "div",
4588
4912
  {
4589
4913
  ref: panelRef,
4914
+ id: resolvedPanelId,
4590
4915
  role: "dialog",
4916
+ tabIndex: -1,
4917
+ onKeyDown: onPanelKeyDown,
4591
4918
  className: chunkTPGAXYFU_cjs.cx(
4592
4919
  "klun-popover__panel",
4593
4920
  // in-flow fallback keeps the legacy left/right anchoring classes
@@ -4597,8 +4924,25 @@ var Popover = react.forwardRef(function Popover2({ trigger, children, align = "l
4597
4924
  children: content
4598
4925
  }
4599
4926
  ) : null;
4927
+ const triggerAria = {
4928
+ "aria-haspopup": "dialog",
4929
+ "aria-expanded": isOpen,
4930
+ ...isOpen ? { "aria-controls": resolvedPanelId } : null
4931
+ };
4932
+ const triggerNode = react.isValidElement(trigger) ? react.cloneElement(trigger, triggerAria) : trigger;
4933
+ const wrapperIsTrigger = !hasFocusableChild;
4600
4934
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { ref: setRefs, className: chunkTPGAXYFU_cjs.cx("klun-popover", className), ...props, children: [
4601
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-popover__trigger", onClick: () => setOpen((o) => !o), children: trigger }),
4935
+ /* @__PURE__ */ jsxRuntime.jsx(
4936
+ "span",
4937
+ {
4938
+ ref: triggerRef,
4939
+ className: "klun-popover__trigger",
4940
+ onClick: () => setOpen(!isOpen),
4941
+ onKeyDown: onTriggerKeyDown,
4942
+ ...wrapperIsTrigger ? { role: "button", tabIndex: 0, ...triggerAria } : !react.isValidElement(trigger) ? triggerAria : null,
4943
+ children: triggerNode
4944
+ }
4945
+ ),
4602
4946
  portal ? panel && reactDom.createPortal(panel, document.body) : panel
4603
4947
  ] });
4604
4948
  });
@@ -4961,11 +5305,14 @@ var EmojiPicker = react.forwardRef(
4961
5305
  groups = EMOJI_GROUPS,
4962
5306
  columns = 8,
4963
5307
  searchable = true,
4964
- searchPlaceholder = "Search emoji",
4965
- emptyText = "No emoji found",
5308
+ searchPlaceholder: searchPlaceholderProp,
5309
+ emptyText: emptyTextProp,
4966
5310
  className,
4967
5311
  ...props
4968
5312
  }, ref) {
5313
+ const { emojiPicker } = useLocale();
5314
+ const searchPlaceholder = searchPlaceholderProp ?? emojiPicker.searchPlaceholder;
5315
+ const emptyText = emptyTextProp ?? emojiPicker.emptyText;
4969
5316
  const [query, setQuery] = react.useState("");
4970
5317
  const q = query.trim().toLowerCase();
4971
5318
  const results = react.useMemo(() => {
@@ -5010,7 +5357,9 @@ var EmojiPicker = react.forwardRef(
5010
5357
  EmojiPicker.displayName = "EmojiPicker";
5011
5358
  var QUICK_EMOJIS = ["\u{1F44D}", "\u{1F44C}", "\u2764\uFE0F", "\u2705", "\u{1F389}", "\u{1F615}", "\u{1F680}", "\u{1F440}"];
5012
5359
  var QuickEmojiPicker = react.forwardRef(
5013
- function QuickEmojiPicker2({ onSelect, emojis = QUICK_EMOJIS, align = "left", label = "Add reaction", className }, ref) {
5360
+ function QuickEmojiPicker2({ onSelect, emojis = QUICK_EMOJIS, align = "left", label: labelProp, className }, ref) {
5361
+ const { emojiPicker } = useLocale();
5362
+ const label = labelProp ?? emojiPicker.addReaction;
5014
5363
  return /* @__PURE__ */ jsxRuntime.jsx(
5015
5364
  Popover,
5016
5365
  {
@@ -5155,6 +5504,16 @@ var Tooltip = react.forwardRef(function Tooltip2({ content, side = "top", delay
5155
5504
  transform: "none",
5156
5505
  visibility: pos ? "visible" : "hidden"
5157
5506
  };
5507
+ const tooltipId = `${react.useId()}tooltip`;
5508
+ const describedBy = open && content && !disabled ? tooltipId : void 0;
5509
+ const childProps = react.isValidElement(children) ? children.props : null;
5510
+ const triggerNode = childProps != null ? react.cloneElement(
5511
+ children,
5512
+ // 合并而非覆盖调用方已有的 aria-describedby
5513
+ {
5514
+ "aria-describedby": [childProps["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
5515
+ }
5516
+ ) : children;
5158
5517
  return /* @__PURE__ */ jsxRuntime.jsxs(
5159
5518
  "span",
5160
5519
  {
@@ -5164,13 +5523,15 @@ var Tooltip = react.forwardRef(function Tooltip2({ content, side = "top", delay
5164
5523
  onMouseLeave: hide,
5165
5524
  onFocus: show,
5166
5525
  onBlur: hide,
5526
+ ...childProps == null ? { "aria-describedby": describedBy } : null,
5167
5527
  children: [
5168
- children,
5528
+ triggerNode,
5169
5529
  open && content && typeof document !== "undefined" ? reactDom.createPortal(
5170
5530
  /* @__PURE__ */ jsxRuntime.jsx(
5171
5531
  "span",
5172
5532
  {
5173
5533
  ref: bubbleRef,
5534
+ id: tooltipId,
5174
5535
  role: "tooltip",
5175
5536
  className: chunkTPGAXYFU_cjs.cx("klun-tooltip__bubble", `klun-tooltip__bubble--${side}`),
5176
5537
  style: bubbleStyle,
@@ -5650,7 +6011,7 @@ function TableToolbar({
5650
6011
  selectedRows,
5651
6012
  clearSelection
5652
6013
  }) {
5653
- const { table } = useLocale();
6014
+ const { table, a11y } = useLocale();
5654
6015
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5655
6016
  showToolbar ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-table__toolbar", children: [
5656
6017
  title != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-table__title", children: title }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-table__title-spacer" }),
@@ -5673,7 +6034,7 @@ function TableToolbar({
5673
6034
  {
5674
6035
  type: "button",
5675
6036
  onClick: clearSelection,
5676
- "aria-label": "Clear selection",
6037
+ "aria-label": a11y.clearSelection,
5677
6038
  className: "klun-table__selbar-clear",
5678
6039
  children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-close-line" })
5679
6040
  }
@@ -5851,9 +6212,44 @@ function TableHead({
5851
6212
  setSort,
5852
6213
  activeFilters,
5853
6214
  setFilter,
5854
- startResize
6215
+ startResize,
6216
+ setColumnWidth
5855
6217
  }) {
5856
6218
  const { table } = useLocale();
6219
+ const [resizerW, setResizerW] = react.useState({});
6220
+ const widthForA11y = (c) => {
6221
+ const w = widthOf(c);
6222
+ if (typeof w === "number") return w;
6223
+ if (typeof c.width === "number") return c.width;
6224
+ return resizerW[c.key] ?? (c.minWidth || 64);
6225
+ };
6226
+ const onResizerKeyDown = (e, c) => {
6227
+ const min = c.minWidth || 64;
6228
+ const step = e.shiftKey ? 32 : 8;
6229
+ const current = resizerW[c.key] ?? widthForA11y(c);
6230
+ let next = null;
6231
+ switch (e.key) {
6232
+ case "ArrowLeft":
6233
+ next = current - step;
6234
+ break;
6235
+ case "ArrowRight":
6236
+ next = current + step;
6237
+ break;
6238
+ case "Home":
6239
+ next = min;
6240
+ break;
6241
+ // 这里没有真正的"最大值"(列宽不受限),因此用 Enter 代表"恢复声明宽度"
6242
+ case "Enter":
6243
+ next = typeof c.width === "number" ? c.width : current;
6244
+ break;
6245
+ default:
6246
+ return;
6247
+ }
6248
+ e.preventDefault();
6249
+ e.stopPropagation();
6250
+ const applied = setColumnWidth(c, next);
6251
+ setResizerW((m) => ({ ...m, [c.key]: applied }));
6252
+ };
5857
6253
  return /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
5858
6254
  dragCol ? /* @__PURE__ */ jsxRuntime.jsx("th", { className: "klun-table__th klun-table__th--util" }) : null,
5859
6255
  expandCol ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -5916,8 +6312,21 @@ function TableHead({
5916
6312
  justifyContent: c.align === "right" ? "flex-end" : c.align === "center" ? "center" : "flex-start"
5917
6313
  },
5918
6314
  children: [
5919
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: c.ellipsis ? "klun-table__ellipsis" : void 0, children: c.headerRender ? c.headerRender() : c.header }),
5920
- isSort ? /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { dir }) : null,
6315
+ isSort ? /* @__PURE__ */ jsxRuntime.jsxs(
6316
+ "button",
6317
+ {
6318
+ type: "button",
6319
+ className: "klun-table__sort",
6320
+ onClick: (e) => {
6321
+ e.stopPropagation();
6322
+ setSort(c.key);
6323
+ },
6324
+ children: [
6325
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: c.ellipsis ? "klun-table__ellipsis" : void 0, children: c.headerRender ? c.headerRender() : c.header }),
6326
+ /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { dir })
6327
+ ]
6328
+ }
6329
+ ) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: c.ellipsis ? "klun-table__ellipsis" : void 0, children: c.headerRender ? c.headerRender() : c.header }) }),
5921
6330
  hasFilter ? /* @__PURE__ */ jsxRuntime.jsx(
5922
6331
  FilterMenu,
5923
6332
  {
@@ -5935,7 +6344,19 @@ function TableHead({
5935
6344
  {
5936
6345
  role: "separator",
5937
6346
  "aria-orientation": "vertical",
6347
+ tabIndex: 0,
6348
+ "aria-label": `${table.dragToResize}: ${typeof c.header === "string" ? c.header : c.key}`,
6349
+ "aria-valuemin": c.minWidth || 64,
6350
+ "aria-valuenow": widthForA11y(c),
6351
+ "aria-valuetext": `${widthForA11y(c)}px`,
5938
6352
  title: table.dragToResize,
6353
+ onFocus: (e) => {
6354
+ const th = e.currentTarget.closest("th");
6355
+ if (!th) return;
6356
+ const measured = Math.round(th.getBoundingClientRect().width);
6357
+ if (measured > 0) setResizerW((m) => ({ ...m, [c.key]: measured }));
6358
+ },
6359
+ onKeyDown: (e) => onResizerKeyDown(e, c),
5939
6360
  onMouseDown: (e) => startResize(e, c),
5940
6361
  onClick: (e) => e.stopPropagation(),
5941
6362
  className: "klun-table__resizer",
@@ -5949,6 +6370,14 @@ function TableHead({
5949
6370
  })
5950
6371
  ] }) });
5951
6372
  }
6373
+ function isCoarsePointer() {
6374
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
6375
+ try {
6376
+ return window.matchMedia("(pointer: coarse)").matches;
6377
+ } catch {
6378
+ return false;
6379
+ }
6380
+ }
5952
6381
  function TableRow(props) {
5953
6382
  if (!props.dragCol) return /* @__PURE__ */ jsxRuntime.jsx(RowBase, { ...props });
5954
6383
  return /* @__PURE__ */ jsxRuntime.jsx(SortableRow, { ...props });
@@ -6052,7 +6481,15 @@ function RowBase({
6052
6481
  clickable && "klun-table__row--clickable",
6053
6482
  sortable?.isDragging && "klun-table__row--dragging"
6054
6483
  ),
6055
- onClick: clickable ? () => rowHref ? window.location.href = rowHref(row) : onRowClick(row) : void 0,
6484
+ onClick: clickable ? (e) => {
6485
+ if (rowHref) {
6486
+ const target = e.target;
6487
+ if (target?.closest?.("a[href]")) return;
6488
+ window.location.href = rowHref(row);
6489
+ return;
6490
+ }
6491
+ onRowClick?.(row);
6492
+ } : void 0,
6056
6493
  onContextMenu: contextMenu || copyable ? (e) => {
6057
6494
  const custom = contextMenu ? contextMenu(row, { copyRow, copyText }) : null;
6058
6495
  const items2 = custom && custom.length ? custom : [
@@ -6227,6 +6664,8 @@ function RowBase({
6227
6664
  style: { textAlign: c.align || "left" }
6228
6665
  }
6229
6666
  ) : null;
6667
+ const linkHref = rowHref && ci === 0 && !c.render && !c.editable ? rowHref(row) : null;
6668
+ const body = linkHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "klun-table__rowlink", href: linkHref, children: inner }) : inner;
6230
6669
  return /* @__PURE__ */ jsxRuntime.jsx(
6231
6670
  "td",
6232
6671
  {
@@ -6234,6 +6673,18 @@ function RowBase({
6234
6673
  e.stopPropagation();
6235
6674
  startEdit(id, c, row);
6236
6675
  } : void 0,
6676
+ onClick: c.editable && !isEditing && isCoarsePointer() ? (e) => {
6677
+ e.stopPropagation();
6678
+ startEdit(id, c, row);
6679
+ } : void 0,
6680
+ tabIndex: c.editable && !isEditing ? 0 : void 0,
6681
+ onKeyDown: c.editable && !isEditing ? (e) => {
6682
+ if (e.key === "Enter" || e.key === "F2") {
6683
+ e.preventDefault();
6684
+ e.stopPropagation();
6685
+ startEdit(id, c, row);
6686
+ }
6687
+ } : void 0,
6237
6688
  className: chunkTPGAXYFU_cjs.cx(
6238
6689
  "klun-table__td",
6239
6690
  tdBorder,
@@ -6281,8 +6732,8 @@ function RowBase({
6281
6732
  )
6282
6733
  }
6283
6734
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-table__tree-spacer" }),
6284
- inner
6285
- ] }) : inner
6735
+ body
6736
+ ] }) : body
6286
6737
  },
6287
6738
  c.key
6288
6739
  );
@@ -6376,6 +6827,11 @@ function useColumnResize(columns) {
6376
6827
  const [colW, setColW] = react.useState({});
6377
6828
  const resizeRef = react.useRef(null);
6378
6829
  const widthOf = (c) => colW[c.key] ?? (typeof c.width === "number" ? c.width : void 0);
6830
+ const setColumnWidth = (c, next) => {
6831
+ const w = Math.max(c.minWidth || 64, Math.round(next));
6832
+ setColW((m) => ({ ...m, [c.key]: w }));
6833
+ return w;
6834
+ };
6379
6835
  const startResize = (e, c) => {
6380
6836
  e.preventDefault();
6381
6837
  e.stopPropagation();
@@ -6387,7 +6843,7 @@ function useColumnResize(columns) {
6387
6843
  const r = resizeRef.current;
6388
6844
  if (!r) return;
6389
6845
  const w = Math.max(c.minWidth || 64, r.startW + (ev.clientX - r.startX));
6390
- setColW((m) => ({ ...m, [r.key]: w }));
6846
+ setColW((m) => ({ ...m, [r.key]: Math.round(w) }));
6391
6847
  };
6392
6848
  const up = () => {
6393
6849
  resizeRef.current = null;
@@ -6401,7 +6857,7 @@ function useColumnResize(columns) {
6401
6857
  document.body.style.cursor = "col-resize";
6402
6858
  document.body.style.userSelect = "none";
6403
6859
  };
6404
- return { colW, widthOf, startResize };
6860
+ return { colW, widthOf, startResize, setColumnWidth };
6405
6861
  }
6406
6862
  function useColumnVisibility(columns) {
6407
6863
  const [hiddenCols, setHiddenCols] = react.useState(
@@ -6605,7 +7061,7 @@ function Table({
6605
7061
  onFiltersChange,
6606
7062
  pagination = false,
6607
7063
  expandable,
6608
- density = "comfortable",
7064
+ density: densityProp,
6609
7065
  zebra = false,
6610
7066
  stickyHeader = false,
6611
7067
  hover = true,
@@ -6640,9 +7096,11 @@ function Table({
6640
7096
  style,
6641
7097
  ...props
6642
7098
  }) {
7099
+ const providerDensity = useConfig().density;
7100
+ const density = densityProp ?? (providerDensity === "compact" ? "compact" : "comfortable");
6643
7101
  const densityClass = DENSITY[density] || DENSITY.comfortable;
6644
7102
  const { menu, setMenu } = useTableContextMenu();
6645
- const { colW, widthOf, startResize } = useColumnResize();
7103
+ const { colW, widthOf, startResize, setColumnWidth } = useColumnResize();
6646
7104
  const { hiddenCols, visibleColumns, toggleColumn } = useColumnVisibility(columns);
6647
7105
  const dragCol = rowDraggable && !tree;
6648
7106
  const rowToText = (row) => columns.map((c) => {
@@ -6834,7 +7292,8 @@ function Table({
6834
7292
  setSort,
6835
7293
  activeFilters,
6836
7294
  setFilter,
6837
- startResize
7295
+ startResize,
7296
+ setColumnWidth
6838
7297
  }
6839
7298
  ),
6840
7299
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7017,6 +7476,7 @@ var Tree = react.forwardRef(function Tree2({
7017
7476
  showLine = false,
7018
7477
  blockNode = true,
7019
7478
  className,
7479
+ onKeyDown: onKeyDownProp,
7020
7480
  ...props
7021
7481
  }, ref) {
7022
7482
  const [innerExpanded, setInnerExpanded] = react.useState(defaultExpandedKeys);
@@ -7044,14 +7504,105 @@ var Tree = react.forwardRef(function Tree2({
7044
7504
  else next = Array.from(/* @__PURE__ */ new Set([...checkedKeys, ...all]));
7045
7505
  onCheck(next);
7046
7506
  };
7507
+ const visible = rows.filter((r) => !r.hidden);
7508
+ const rootRef = react.useRef(null);
7509
+ const setRoots = (node) => {
7510
+ rootRef.current = node;
7511
+ if (typeof ref === "function") ref(node);
7512
+ else if (ref && "current" in ref) ref.current = node;
7513
+ };
7514
+ const firstEnabledKey = () => {
7515
+ const hit = visible.find((r) => !r.node.disabled) ?? visible[0];
7516
+ return hit?.node.key ?? null;
7517
+ };
7518
+ const [focusedKey, setFocusedKey] = react.useState(null);
7519
+ const rovingKey = (() => {
7520
+ if (focusedKey && visible.some((r) => r.node.key === focusedKey)) return focusedKey;
7521
+ if (selectedKey && visible.some((r) => r.node.key === selectedKey)) return selectedKey;
7522
+ return firstEnabledKey();
7523
+ })();
7524
+ const focusKey = react.useCallback((key) => {
7525
+ if (!key) return;
7526
+ setFocusedKey(key);
7527
+ const el = rootRef.current?.querySelector(`[data-tree-key="${CSS.escape(key)}"]`);
7528
+ el?.focus?.();
7529
+ }, []);
7530
+ const onKeyDown = (e) => {
7531
+ if (visible.length === 0) return;
7532
+ const activeKey = rootRef.current?.ownerDocument?.activeElement?.getAttribute?.(
7533
+ "data-tree-key"
7534
+ ) ?? null;
7535
+ const currentKey = activeKey ?? rovingKey;
7536
+ const idx = Math.max(0, visible.findIndex((r) => r.node.key === currentKey));
7537
+ const cur = visible[idx];
7538
+ if (!cur) return;
7539
+ const hasChildren2 = !!(cur.node.children && cur.node.children.length);
7540
+ const isExpanded = exp.includes(cur.node.key);
7541
+ const parentKey = (() => {
7542
+ for (let i = idx - 1; i >= 0; i--) {
7543
+ if (visible[i].level < cur.level) return visible[i].node.key;
7544
+ }
7545
+ return null;
7546
+ })();
7547
+ switch (e.key) {
7548
+ case "ArrowDown":
7549
+ e.preventDefault();
7550
+ focusKey(visible[Math.min(idx + 1, visible.length - 1)]?.node.key ?? null);
7551
+ return;
7552
+ case "ArrowUp":
7553
+ e.preventDefault();
7554
+ focusKey(visible[Math.max(idx - 1, 0)]?.node.key ?? null);
7555
+ return;
7556
+ case "Home":
7557
+ e.preventDefault();
7558
+ focusKey(visible[0]?.node.key ?? null);
7559
+ return;
7560
+ case "End":
7561
+ e.preventDefault();
7562
+ focusKey(visible[visible.length - 1]?.node.key ?? null);
7563
+ return;
7564
+ case "ArrowRight":
7565
+ e.preventDefault();
7566
+ if (cur.node.disabled) return;
7567
+ if (hasChildren2 && !isExpanded) toggle(cur.node.key);
7568
+ else if (hasChildren2 && isExpanded) focusKey(visible[idx + 1]?.node.key ?? null);
7569
+ return;
7570
+ case "ArrowLeft":
7571
+ e.preventDefault();
7572
+ if (hasChildren2 && isExpanded) toggle(cur.node.key);
7573
+ else if (parentKey) focusKey(parentKey);
7574
+ return;
7575
+ case "Enter":
7576
+ e.preventDefault();
7577
+ if (cur.node.disabled) return;
7578
+ if (checkable) onCheckNode(cur.node);
7579
+ else onSelect?.(cur.node.key, cur.node);
7580
+ return;
7581
+ case " ":
7582
+ e.preventDefault();
7583
+ if (cur.node.disabled) return;
7584
+ if (checkable) onCheckNode(cur.node);
7585
+ else onSelect?.(cur.node.key, cur.node);
7586
+ return;
7587
+ default:
7588
+ return;
7589
+ }
7590
+ };
7591
+ const onKeyDownComposed = (e) => {
7592
+ onKeyDownProp?.(e);
7593
+ if (e.defaultPrevented) return;
7594
+ onKeyDown(e);
7595
+ };
7047
7596
  return /* @__PURE__ */ jsxRuntime.jsx(
7048
7597
  "div",
7049
7598
  {
7050
- ref,
7599
+ ref: setRoots,
7051
7600
  role: "tree",
7601
+ "aria-multiselectable": checkable || void 0,
7052
7602
  className: chunkTPGAXYFU_cjs.cx("klun-tree", showLine && "klun-tree--line", className),
7603
+ onKeyDown: onKeyDownComposed,
7053
7604
  ...props,
7054
- children: rows.filter((r) => !r.hidden).map(({ node, level }) => {
7605
+ children: visible.map(({ node, level }) => {
7055
7606
  const hasChildren2 = !!(node.children && node.children.length);
7056
7607
  const isExpanded = exp.includes(node.key);
7057
7608
  const selected = selectedKey === node.key;
@@ -7060,17 +7611,24 @@ var Tree = react.forwardRef(function Tree2({
7060
7611
  "div",
7061
7612
  {
7062
7613
  role: "treeitem",
7614
+ "data-tree-key": node.key,
7615
+ tabIndex: rovingKey === node.key ? 0 : -1,
7616
+ "aria-level": level + 1,
7063
7617
  "aria-expanded": hasChildren2 ? isExpanded : void 0,
7064
7618
  "aria-selected": selected,
7619
+ "aria-disabled": node.disabled || void 0,
7620
+ "aria-checked": checkable ? cs === "all" ? true : cs === "some" ? "mixed" : false : void 0,
7065
7621
  className: chunkTPGAXYFU_cjs.cx(
7066
7622
  "klun-tree__item",
7067
7623
  selected && "klun-tree__item--selected",
7068
7624
  node.disabled && "klun-tree__item--disabled",
7069
- blockNode && "klun-tree__item--block"
7625
+ blockNode && "klun-tree__item--block",
7626
+ rovingKey === node.key && "klun-tree__item--focused"
7070
7627
  ),
7071
7628
  style: { ["--klun-tree-indent"]: `${6 + level * 20}px` },
7072
7629
  onClick: () => {
7073
7630
  if (node.disabled) return;
7631
+ setFocusedKey(node.key);
7074
7632
  if (!checkable) onSelect && onSelect(node.key, node);
7075
7633
  },
7076
7634
  children: [
@@ -7082,6 +7640,7 @@ var Tree = react.forwardRef(function Tree2({
7082
7640
  hasChildren2 && isExpanded && "klun-tree__caret--expanded"
7083
7641
  ),
7084
7642
  "data-leaf": hasChildren2 ? void 0 : "",
7643
+ "aria-hidden": "true",
7085
7644
  onClick: (e) => {
7086
7645
  e.stopPropagation();
7087
7646
  if (hasChildren2) toggle(node.key);
@@ -7093,6 +7652,7 @@ var Tree = react.forwardRef(function Tree2({
7093
7652
  "span",
7094
7653
  {
7095
7654
  className: chunkTPGAXYFU_cjs.cx("klun-tree__checkbox", `klun-tree__checkbox--${cs}`),
7655
+ "aria-hidden": "true",
7096
7656
  onClick: (e) => {
7097
7657
  e.stopPropagation();
7098
7658
  if (!node.disabled) onCheckNode(node);
@@ -8335,7 +8895,14 @@ var AutoComplete = react.forwardRef(
8335
8895
  leadingIcon,
8336
8896
  emptyText: emptyTextProp,
8337
8897
  maxVisible = 6,
8898
+ error = false,
8338
8899
  className,
8900
+ inputProps,
8901
+ // 下面这些属性属于**真实输入框**,不能落在 wrapper 上:
8902
+ // 落在 wrapper 上时 `<label for={id}>` 指不到控件、`aria-label` 对输入框无效。
8903
+ // 其余属性仍然透传给根节点,保持既有行为。
8904
+ id,
8905
+ inputMode,
8339
8906
  ...props
8340
8907
  }, ref) {
8341
8908
  const size = useSize(sizeProp);
@@ -8344,6 +8911,17 @@ var AutoComplete = react.forwardRef(
8344
8911
  const [open, setOpen] = react.useState(false);
8345
8912
  const [hi, setHi] = react.useState(-1);
8346
8913
  const rootRef = react.useRef(null);
8914
+ const generatedId = react.useId();
8915
+ const listboxId = `${generatedId}listbox`;
8916
+ const optionId = (index) => `${listboxId}-option-${index}`;
8917
+ const {
8918
+ "aria-label": ariaLabel,
8919
+ "aria-labelledby": ariaLabelledBy,
8920
+ "aria-describedby": ariaDescribedBy,
8921
+ "aria-invalid": ariaInvalid,
8922
+ "aria-required": ariaRequired,
8923
+ ...rootProps
8924
+ } = props;
8347
8925
  const norm2 = options.map(
8348
8926
  (o) => typeof o === "string" ? { value: o, label: o } : o
8349
8927
  );
@@ -8388,13 +8966,14 @@ var AutoComplete = react.forwardRef(
8388
8966
  {
8389
8967
  ref: rootRef,
8390
8968
  className: chunkTPGAXYFU_cjs.cx("klun-autocomplete", `klun-autocomplete--${size}`, className),
8391
- ...props,
8969
+ ...rootProps,
8392
8970
  children: [
8393
8971
  /* @__PURE__ */ jsxRuntime.jsxs(
8394
8972
  "div",
8395
8973
  {
8396
8974
  className: chunkTPGAXYFU_cjs.cx(
8397
8975
  "klun-autocomplete__field",
8976
+ error && "klun-autocomplete__field--error",
8398
8977
  disabled && "klun-autocomplete__field--disabled"
8399
8978
  ),
8400
8979
  "data-open": open ? "" : void 0,
@@ -8403,11 +8982,25 @@ var AutoComplete = react.forwardRef(
8403
8982
  /* @__PURE__ */ jsxRuntime.jsx(
8404
8983
  "input",
8405
8984
  {
8985
+ ...inputProps,
8406
8986
  ref,
8407
- className: "klun-autocomplete__input",
8987
+ id: id ?? inputProps?.id,
8988
+ autoComplete: inputProps?.autoComplete,
8989
+ inputMode: inputMode ?? inputProps?.inputMode,
8990
+ className: chunkTPGAXYFU_cjs.cx("klun-autocomplete__input", inputProps?.className),
8408
8991
  value,
8409
8992
  disabled,
8410
8993
  placeholder,
8994
+ role: "combobox",
8995
+ "aria-expanded": open,
8996
+ "aria-controls": open ? listboxId : void 0,
8997
+ "aria-activedescendant": open && hi >= 0 ? optionId(hi) : void 0,
8998
+ "aria-autocomplete": "list",
8999
+ "aria-label": ariaLabel,
9000
+ "aria-labelledby": ariaLabelledBy,
9001
+ "aria-describedby": ariaDescribedBy,
9002
+ "aria-invalid": ariaInvalid,
9003
+ "aria-required": ariaRequired,
8411
9004
  onChange: (e) => {
8412
9005
  onChange?.(e.target.value);
8413
9006
  setOpen(true);
@@ -8420,9 +9013,10 @@ var AutoComplete = react.forwardRef(
8420
9013
  ]
8421
9014
  }
8422
9015
  ),
8423
- open ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-autocomplete__list", role: "listbox", children: shown.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-autocomplete__empty", children: emptyText }) : shown.map((o, i) => /* @__PURE__ */ jsxRuntime.jsxs(
9016
+ open ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-autocomplete__list", id: listboxId, role: "listbox", children: shown.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-autocomplete__empty", children: emptyText }) : shown.map((o, i) => /* @__PURE__ */ jsxRuntime.jsxs(
8424
9017
  "button",
8425
9018
  {
9019
+ id: optionId(i),
8426
9020
  type: "button",
8427
9021
  role: "option",
8428
9022
  "aria-selected": i === hi,
@@ -8472,6 +9066,8 @@ var Cascader = react.forwardRef(function Cascader2({
8472
9066
  const [open, setOpen] = react.useState(false);
8473
9067
  const [active, setActive] = react.useState(current);
8474
9068
  const rootRef = react.useRef(null);
9069
+ const triggerRef = react.useRef(null);
9070
+ const panelRef = react.useRef(null);
8475
9071
  react.useEffect(() => {
8476
9072
  setActive(current);
8477
9073
  }, [open]);
@@ -8481,7 +9077,11 @@ var Cascader = react.forwardRef(function Cascader2({
8481
9077
  if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
8482
9078
  };
8483
9079
  const k2 = (e) => {
8484
- if (e.key === "Escape") setOpen(false);
9080
+ if (e.key !== "Escape") return;
9081
+ setOpen(false);
9082
+ if (rootRef.current && rootRef.current.contains(document.activeElement)) {
9083
+ triggerRef.current?.focus();
9084
+ }
8485
9085
  };
8486
9086
  document.addEventListener("mousedown", h);
8487
9087
  document.addEventListener("keydown", k2);
@@ -8490,6 +9090,15 @@ var Cascader = react.forwardRef(function Cascader2({
8490
9090
  document.removeEventListener("keydown", k2);
8491
9091
  };
8492
9092
  }, [open]);
9093
+ react.useEffect(() => {
9094
+ if (!open) return;
9095
+ const id = requestAnimationFrame(() => {
9096
+ const cols = panelRef.current?.querySelectorAll(".klun-cascader__column");
9097
+ const last = cols && cols.length ? cols[cols.length - 1] : null;
9098
+ last?.querySelector(".klun-cascader__option:not([disabled])")?.focus();
9099
+ });
9100
+ return () => cancelAnimationFrame(id);
9101
+ }, [open]);
8493
9102
  const columns = [];
8494
9103
  let level = options;
8495
9104
  columns.push(level);
@@ -8519,6 +9128,62 @@ var Cascader = react.forwardRef(function Cascader2({
8519
9128
  if (leaf) setOpen(false);
8520
9129
  }
8521
9130
  };
9131
+ const onPanelKeyDown = (e) => {
9132
+ const target = e.target;
9133
+ const option = target.closest(".klun-cascader__option");
9134
+ if (!option) return;
9135
+ const column = option.closest(".klun-cascader__column");
9136
+ if (!column) return;
9137
+ const all = Array.from(column.querySelectorAll(".klun-cascader__option"));
9138
+ const enabled = all.filter((el) => !el.disabled);
9139
+ const i = enabled.indexOf(option);
9140
+ const colIdx = Array.from(
9141
+ panelRef.current?.querySelectorAll(".klun-cascader__column") ?? []
9142
+ ).indexOf(column);
9143
+ const focusIntoColumn = (n) => {
9144
+ const cols = panelRef.current?.querySelectorAll(".klun-cascader__column");
9145
+ cols?.[n]?.querySelector(".klun-cascader__option:not([disabled])")?.focus();
9146
+ };
9147
+ switch (e.key) {
9148
+ case "ArrowDown":
9149
+ e.preventDefault();
9150
+ enabled[(i + 1) % enabled.length]?.focus();
9151
+ break;
9152
+ case "ArrowUp":
9153
+ e.preventDefault();
9154
+ enabled[(i - 1 + enabled.length) % enabled.length]?.focus();
9155
+ break;
9156
+ case "Home":
9157
+ e.preventDefault();
9158
+ enabled[0]?.focus();
9159
+ break;
9160
+ case "End":
9161
+ e.preventDefault();
9162
+ enabled[enabled.length - 1]?.focus();
9163
+ break;
9164
+ case "ArrowRight": {
9165
+ e.preventDefault();
9166
+ const opt = columns[colIdx]?.[all.indexOf(option)];
9167
+ if (opt && opt.children && opt.children.length) {
9168
+ pick(colIdx, opt);
9169
+ requestAnimationFrame(() => focusIntoColumn(colIdx + 1));
9170
+ }
9171
+ break;
9172
+ }
9173
+ case "ArrowLeft":
9174
+ e.preventDefault();
9175
+ if (colIdx > 0) focusIntoColumn(colIdx - 1);
9176
+ break;
9177
+ case "Escape":
9178
+ e.preventDefault();
9179
+ setOpen(false);
9180
+ triggerRef.current?.focus();
9181
+ break;
9182
+ case "Tab":
9183
+ setOpen(false);
9184
+ break;
9185
+ }
9186
+ };
8522
9187
  const clear = () => {
8523
9188
  if (value === void 0) setInner([]);
8524
9189
  setActive([]);
@@ -8541,11 +9206,12 @@ var Cascader = react.forwardRef(function Cascader2({
8541
9206
  /* @__PURE__ */ jsxRuntime.jsxs(
8542
9207
  "button",
8543
9208
  {
9209
+ ref: triggerRef,
8544
9210
  type: "button",
8545
9211
  className: "klun-cascader__trigger",
8546
9212
  disabled,
8547
9213
  onClick: () => setOpen((o) => !o),
8548
- "aria-haspopup": "true",
9214
+ "aria-haspopup": "menu",
8549
9215
  "aria-expanded": open,
8550
9216
  "data-empty": labelPath.length ? void 0 : "",
8551
9217
  children: [
@@ -8591,9 +9257,11 @@ var Cascader = react.forwardRef(function Cascader2({
8591
9257
  ]
8592
9258
  }
8593
9259
  ),
8594
- open ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-cascader__panel", role: "menu", children: columns.map((col, ci) => /* @__PURE__ */ jsxRuntime.jsx(
9260
+ open ? /* @__PURE__ */ jsxRuntime.jsx("div", { ref: panelRef, className: "klun-cascader__panel", role: "menu", onKeyDown: onPanelKeyDown, children: columns.map((col, ci) => /* @__PURE__ */ jsxRuntime.jsx(
8595
9261
  "div",
8596
9262
  {
9263
+ role: "group",
9264
+ "aria-label": ci === 0 ? cascader.placeholder : String(active[ci - 1] ?? ""),
8597
9265
  className: chunkTPGAXYFU_cjs.cx(
8598
9266
  "klun-cascader__column",
8599
9267
  ci < columns.length - 1 && "klun-cascader__column--divided"
@@ -8605,11 +9273,11 @@ var Cascader = react.forwardRef(function Cascader2({
8605
9273
  "button",
8606
9274
  {
8607
9275
  type: "button",
8608
- role: "menuitem",
9276
+ role: "menuitemradio",
8609
9277
  className: "klun-cascader__option",
8610
9278
  disabled: opt.disabled,
8611
9279
  onClick: () => pick(ci, opt),
8612
- "aria-selected": selected,
9280
+ "aria-checked": selected,
8613
9281
  "data-selected": selected || void 0,
8614
9282
  children: [
8615
9283
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-cascader__option-label", children: renderOption ? renderOption(opt, ci) : opt.label }),
@@ -9114,7 +9782,9 @@ function SelectListbox({
9114
9782
  onActivate,
9115
9783
  onPick,
9116
9784
  className,
9117
- anchorRef
9785
+ anchorRef,
9786
+ id,
9787
+ optionId
9118
9788
  }) {
9119
9789
  const portal = !!anchorRef && typeof document !== "undefined";
9120
9790
  const panelRef = react.useRef(null);
@@ -9162,12 +9832,14 @@ function SelectListbox({
9162
9832
  "div",
9163
9833
  {
9164
9834
  ref: panelRef,
9835
+ id,
9165
9836
  role: "listbox",
9166
9837
  className: className ? `klun-select-listbox ${className}` : "klun-select-listbox",
9167
9838
  style: portalStyle,
9168
9839
  children: options.map((o, i) => /* @__PURE__ */ jsxRuntime.jsxs(
9169
9840
  "button",
9170
9841
  {
9842
+ id: optionId?.(i),
9171
9843
  type: "button",
9172
9844
  role: "option",
9173
9845
  "aria-selected": o.value === current,
@@ -9715,7 +10387,7 @@ var DEFAULT_FORMAT = {
9715
10387
  day: "numeric"
9716
10388
  };
9717
10389
  var Calendar = react.forwardRef(function Calendar2({ value, onPick, className, style }, ref) {
9718
- const { datePicker } = useLocale();
10390
+ const { datePicker, pagination, locale } = useLocale();
9719
10391
  const initial = value ? new Date(value) : /* @__PURE__ */ new Date();
9720
10392
  const [view, setView] = react.useState(new Date(initial.getFullYear(), initial.getMonth(), 1));
9721
10393
  const sel = value ? new Date(value) : null;
@@ -9728,34 +10400,69 @@ var Calendar = react.forwardRef(function Calendar2({ value, onPick, className, s
9728
10400
  const cells = [];
9729
10401
  for (let i = 0; i < firstDay; i++) cells.push(null);
9730
10402
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(y, m, d));
9731
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: chunkTPGAXYFU_cjs.cx("klun-date-picker", className), style, children: [
9732
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-date-picker__header", children: [
9733
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-date-picker__nav", onClick: () => setView(new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 6l-4 4 4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
9734
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-date-picker__title", children: fmt(datePicker.title, { month: datePicker.months[m], year: y }) }),
9735
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-date-picker__nav", onClick: () => setView(new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 6l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
9736
- ] }),
9737
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-date-picker__grid", children: [
9738
- datePicker.weekdaysShort.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-date-picker__weekday", children: d }, i)),
9739
- cells.map((date, i) => {
9740
- if (!date) return /* @__PURE__ */ jsxRuntime.jsx("span", {}, i);
9741
- return /* @__PURE__ */ jsxRuntime.jsx(
9742
- "button",
9743
- {
9744
- type: "button",
9745
- className: "klun-date-picker__day",
9746
- "data-selected": same(date, sel) || void 0,
9747
- "data-today": same(date, today) || void 0,
9748
- onClick: () => onPick(date),
9749
- children: date.getDate()
9750
- },
9751
- i
9752
- );
9753
- })
9754
- ] })
9755
- ] });
10403
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10404
+ "div",
10405
+ {
10406
+ ref,
10407
+ className: chunkTPGAXYFU_cjs.cx("klun-date-picker", className),
10408
+ style,
10409
+ role: "group",
10410
+ "aria-label": fmt(datePicker.title, { month: datePicker.months[m], year: y }),
10411
+ children: [
10412
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-date-picker__header", children: [
10413
+ /* @__PURE__ */ jsxRuntime.jsx(
10414
+ "button",
10415
+ {
10416
+ type: "button",
10417
+ className: "klun-date-picker__nav",
10418
+ "aria-label": pagination.previous,
10419
+ onClick: () => setView(new Date(y, m - 1, 1)),
10420
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 6l-4 4 4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
10421
+ }
10422
+ ),
10423
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-date-picker__title", children: fmt(datePicker.title, { month: datePicker.months[m], year: y }) }),
10424
+ /* @__PURE__ */ jsxRuntime.jsx(
10425
+ "button",
10426
+ {
10427
+ type: "button",
10428
+ className: "klun-date-picker__nav",
10429
+ "aria-label": pagination.next,
10430
+ onClick: () => setView(new Date(y, m + 1, 1)),
10431
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 6l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
10432
+ }
10433
+ )
10434
+ ] }),
10435
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-date-picker__grid", children: [
10436
+ datePicker.weekdaysShort.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-date-picker__weekday", children: d }, i)),
10437
+ cells.map((date, i) => {
10438
+ if (!date) return /* @__PURE__ */ jsxRuntime.jsx("span", {}, i);
10439
+ return /* @__PURE__ */ jsxRuntime.jsx(
10440
+ "button",
10441
+ {
10442
+ type: "button",
10443
+ className: "klun-date-picker__day",
10444
+ "data-selected": same(date, sel) || void 0,
10445
+ "data-today": same(date, today) || void 0,
10446
+ "aria-label": date.toLocaleDateString(locale, {
10447
+ weekday: "long",
10448
+ year: "numeric",
10449
+ month: "long",
10450
+ day: "numeric"
10451
+ }),
10452
+ "aria-current": same(date, today) ? "date" : void 0,
10453
+ onClick: () => onPick(date),
10454
+ children: date.getDate()
10455
+ },
10456
+ i
10457
+ );
10458
+ })
10459
+ ] })
10460
+ ]
10461
+ }
10462
+ );
9756
10463
  });
9757
10464
  var DatePicker = react.forwardRef(
9758
- function DatePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT, align = "left", disabled, className, style, ...props }, ref) {
10465
+ function DatePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT, align = "start", disabled, className, style, ...props }, ref) {
9759
10466
  if (inline2) {
9760
10467
  return /* @__PURE__ */ jsxRuntime.jsx(Calendar, { ref, value, onPick: (d) => onChange?.(d), className, style });
9761
10468
  }
@@ -9853,7 +10560,7 @@ var RangeCalendar = react.forwardRef(function RangeCalendar2({ start, end, onPic
9853
10560
  ] });
9854
10561
  });
9855
10562
  var DateRangePicker = react.forwardRef(
9856
- function DateRangePicker2({ start, end, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT2, align = "left", disabled, className, style, ...props }, ref) {
10563
+ function DateRangePicker2({ start, end, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT2, align = "start", disabled, className, style, ...props }, ref) {
9857
10564
  if (inline2) {
9858
10565
  return /* @__PURE__ */ jsxRuntime.jsx(
9859
10566
  RangeCalendar,
@@ -10131,7 +10838,7 @@ function DateTimePanel({ value, onChange }) {
10131
10838
  ] });
10132
10839
  }
10133
10840
  var DateTimePicker = react.forwardRef(
10134
- function DateTimePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT3, align = "left", disabled, className, style, ...props }, ref) {
10841
+ function DateTimePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT3, align = "start", disabled, className, style, ...props }, ref) {
10135
10842
  const date = value ? new Date(value) : null;
10136
10843
  if (inline2) {
10137
10844
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: chunkTPGAXYFU_cjs.cx("klun-date-time-picker", className), style, ...props, children: /* @__PURE__ */ jsxRuntime.jsx(DateTimePanel, { value: date, onChange: (d) => onChange?.(d) }) });
@@ -10262,13 +10969,24 @@ var FileUpload = react.forwardRef(function FileUpload2({ onFiles, hint = "SVG, P
10262
10969
  const { fileUpload } = useLocale();
10263
10970
  const [over, setOver] = react.useState(false);
10264
10971
  const inputRef = react.useRef(null);
10972
+ const openPicker = () => inputRef.current?.click();
10973
+ const dropzoneLabel = `${fileUpload.clickToUpload} ${fileUpload.orDragAndDrop}`;
10265
10974
  return /* @__PURE__ */ jsxRuntime.jsxs(
10266
10975
  "div",
10267
10976
  {
10268
10977
  ref,
10269
10978
  className: chunkTPGAXYFU_cjs.cx("klun-file-upload", className),
10979
+ role: "button",
10980
+ tabIndex: 0,
10981
+ "aria-label": dropzoneLabel,
10270
10982
  "data-dragover": over || void 0,
10271
- onClick: () => inputRef.current?.click(),
10983
+ onClick: openPicker,
10984
+ onKeyDown: (e) => {
10985
+ if (e.key === "Enter" || e.key === " ") {
10986
+ e.preventDefault();
10987
+ openPicker();
10988
+ }
10989
+ },
10272
10990
  onDragOver: (e) => {
10273
10991
  e.preventDefault();
10274
10992
  setOver(true);
@@ -10288,6 +11006,7 @@ var FileUpload = react.forwardRef(function FileUpload2({ onFiles, hint = "SVG, P
10288
11006
  type: "file",
10289
11007
  multiple: true,
10290
11008
  hidden: true,
11009
+ tabIndex: -1,
10291
11010
  onChange: (e) => onFiles?.([...e.target.files ?? []])
10292
11011
  }
10293
11012
  ),
@@ -10385,9 +11104,6 @@ function useForm(opts = {}) {
10385
11104
  const unregisterField = react.useCallback((key) => {
10386
11105
  delete fields.current[key];
10387
11106
  }, []);
10388
- const registerRules = react.useCallback((name, rules) => {
10389
- fields.current[pathKey(name)] = { name, rules: rules || [] };
10390
- }, []);
10391
11107
  const getFieldValue = react.useCallback((name) => getIn(valuesRef.current, name), []);
10392
11108
  const getFieldsValue = react.useCallback(() => valuesRef.current, []);
10393
11109
  const validateField = react.useCallback(async (name) => {
@@ -10506,7 +11222,6 @@ function useForm(opts = {}) {
10506
11222
  setValues,
10507
11223
  getFieldValue,
10508
11224
  getFieldsValue,
10509
- registerRules,
10510
11225
  registerField,
10511
11226
  unregisterField,
10512
11227
  validate,
@@ -10579,22 +11294,35 @@ function FormItem({
10579
11294
  const error = form && key ? form.touched[key] && form.errors[key] : null;
10580
11295
  const ruleArr = typeof rules === "function" ? [] : rules || [];
10581
11296
  const isRequired = required || ruleArr.some((r) => r.required);
11297
+ const autoId = react.useId();
11298
+ const childIsElement = react.isValidElement(children);
11299
+ const childProps = childIsElement ? children.props : {};
11300
+ const controlId = childIsElement ? childProps.id ?? `${autoId}control` : void 0;
11301
+ const errorId = controlId ? `${controlId}-error` : void 0;
11302
+ const helpId = controlId ? `${controlId}-help` : void 0;
11303
+ const hasError = Boolean(error);
11304
+ const descriptionId = hasError ? errorId : help ? helpId : void 0;
10582
11305
  let control = children;
10583
- if (form && fullName != null && react.isValidElement(children)) {
10584
- const childProps = children.props;
10585
- control = react.cloneElement(children, {
10586
- value: form._getIn(form.values, fullName) ?? childProps.value ?? "",
10587
- error: !!error,
10588
- onChange: (e) => {
11306
+ if (childIsElement) {
11307
+ const merged = { id: controlId };
11308
+ if (form && fullName != null) {
11309
+ merged.value = form._getIn(form.values, fullName) ?? childProps.value ?? "";
11310
+ merged.error = hasError ? true : void 0;
11311
+ merged.onChange = (e) => {
10589
11312
  const v = e && e.target ? childProps.type === "checkbox" ? e.target.checked : e.target.value : e;
10590
11313
  form.setFieldValue(fullName, v);
10591
11314
  childProps.onChange?.(e);
10592
- },
10593
- onBlur: (e) => {
11315
+ };
11316
+ merged.onBlur = (e) => {
10594
11317
  form.setFieldTouched(fullName);
10595
11318
  childProps.onBlur?.(e);
10596
- }
10597
- });
11319
+ };
11320
+ }
11321
+ if (hasError) merged["aria-invalid"] = true;
11322
+ if (isRequired) merged["aria-required"] = true;
11323
+ const describedBy = [childProps["aria-describedby"], descriptionId].filter(Boolean).join(" ");
11324
+ if (describedBy) merged["aria-describedby"] = describedBy;
11325
+ control = react.cloneElement(children, merged);
10598
11326
  }
10599
11327
  return /* @__PURE__ */ jsxRuntime.jsxs(
10600
11328
  "div",
@@ -10603,13 +11331,13 @@ function FormItem({
10603
11331
  className: chunkTPGAXYFU_cjs.cx("klun-form-item", horizontal && "klun-form-item--horizontal", className),
10604
11332
  ...props,
10605
11333
  children: [
10606
- label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "klun-form-item__label", children: [
11334
+ label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "klun-form-item__label", htmlFor: controlId, children: [
10607
11335
  label,
10608
- isRequired ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-form-item__required", children: "*" }) : null
11336
+ isRequired ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-form-item__required", "aria-hidden": "true", children: "*" }) : null
10609
11337
  ] }) : null,
10610
11338
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-form-item__control", children: [
10611
11339
  control,
10612
- error ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-form-item__error", children: error }) : help ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-form-item__help", children: help }) : null
11340
+ hasError ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: errorId, className: "klun-form-item__error", children: error }) : help ? /* @__PURE__ */ jsxRuntime.jsx("span", { id: helpId, className: "klun-form-item__help", children: help }) : null
10613
11341
  ] })
10614
11342
  ]
10615
11343
  }
@@ -10670,6 +11398,228 @@ var Hint = react.forwardRef(function Hint2({ children, error = false, icon, clas
10670
11398
  );
10671
11399
  });
10672
11400
  Hint.displayName = "Hint";
11401
+
11402
+ // src/components/overlays/overlayStack.ts
11403
+ var OVERLAY_LAYER = {
11404
+ modalRoot: 1e3,
11405
+ modalStep: 100};
11406
+ var stack = [];
11407
+ var scopeRoots = /* @__PURE__ */ new Map();
11408
+ var scrollLockCount = 0;
11409
+ var savedOverflow = null;
11410
+ var canUseDOM = () => typeof document !== "undefined";
11411
+ function pushOverlay() {
11412
+ const id = /* @__PURE__ */ Symbol("klun-overlay");
11413
+ stack.push(id);
11414
+ scopeRoots.set(id, /* @__PURE__ */ new Set());
11415
+ lockScroll();
11416
+ return id;
11417
+ }
11418
+ function popOverlay(id) {
11419
+ const i = stack.indexOf(id);
11420
+ if (i === -1) return;
11421
+ stack.splice(i, 1);
11422
+ scopeRoots.delete(id);
11423
+ unlockScroll();
11424
+ }
11425
+ function isTopOverlay(id) {
11426
+ return stack.length > 0 && stack[stack.length - 1] === id;
11427
+ }
11428
+ function overlayDepth(id) {
11429
+ return stack.indexOf(id);
11430
+ }
11431
+ function layerBaseFor(id) {
11432
+ const depth = Math.max(0, overlayDepth(id));
11433
+ return OVERLAY_LAYER.modalRoot + depth * OVERLAY_LAYER.modalStep;
11434
+ }
11435
+ function registerScopeRoot(id, el) {
11436
+ const set = scopeRoots.get(id);
11437
+ if (!set || !el) return;
11438
+ set.add(el);
11439
+ }
11440
+ function unregisterScopeRoot(id, el) {
11441
+ if (!el) return;
11442
+ scopeRoots.get(id)?.delete(el);
11443
+ }
11444
+ function getScopeRoots(id) {
11445
+ const set = scopeRoots.get(id);
11446
+ if (!set) return [];
11447
+ return [...set].filter((el) => el.isConnected);
11448
+ }
11449
+ function lockScroll() {
11450
+ if (!canUseDOM()) return;
11451
+ if (scrollLockCount === 0) {
11452
+ savedOverflow = document.body.style.overflow;
11453
+ document.body.style.overflow = "hidden";
11454
+ }
11455
+ scrollLockCount += 1;
11456
+ }
11457
+ function unlockScroll() {
11458
+ if (!canUseDOM()) return;
11459
+ scrollLockCount = Math.max(0, scrollLockCount - 1);
11460
+ if (scrollLockCount === 0) {
11461
+ document.body.style.overflow = savedOverflow ?? "";
11462
+ savedOverflow = null;
11463
+ }
11464
+ }
11465
+ var inertedByUs = /* @__PURE__ */ new WeakMap();
11466
+ function applyBackgroundInert(roots) {
11467
+ if (!canUseDOM() || roots.length === 0) return;
11468
+ for (const root of roots) {
11469
+ let node = root;
11470
+ while (node && node.parentElement) {
11471
+ const parent = node.parentElement;
11472
+ for (const sibling of Array.from(parent.children)) {
11473
+ if (sibling === node) continue;
11474
+ if (!(sibling instanceof HTMLElement)) continue;
11475
+ if (roots.some((r) => sibling.contains(r))) continue;
11476
+ if (!sibling.hasAttribute("inert") && !inertedByUs.has(sibling)) {
11477
+ sibling.setAttribute("inert", "");
11478
+ inertedByUs.set(sibling, true);
11479
+ }
11480
+ }
11481
+ node = parent;
11482
+ if (node === document.body) break;
11483
+ }
11484
+ }
11485
+ }
11486
+ function releaseBackgroundInert() {
11487
+ if (!canUseDOM()) return;
11488
+ for (const el of document.querySelectorAll("[inert]")) {
11489
+ if (inertedByUs.get(el)) {
11490
+ el.removeAttribute("inert");
11491
+ inertedByUs.delete(el);
11492
+ }
11493
+ }
11494
+ }
11495
+ function isFocusable(el) {
11496
+ if (el.hasAttribute("disabled")) return false;
11497
+ if (el.getAttribute("aria-hidden") === "true") return false;
11498
+ if (el.hasAttribute("hidden")) return false;
11499
+ if (typeof getComputedStyle === "function") {
11500
+ const cs = getComputedStyle(el);
11501
+ if (cs.display === "none" || cs.visibility === "hidden") return false;
11502
+ }
11503
+ if (el.getAttribute("tabindex") === "-1") return false;
11504
+ return true;
11505
+ }
11506
+ var FOCUSABLE_SELECTOR = [
11507
+ "a[href]",
11508
+ "button",
11509
+ "input:not([type='hidden'])",
11510
+ "select",
11511
+ "textarea",
11512
+ "[tabindex]",
11513
+ "audio[controls]",
11514
+ "video[controls]",
11515
+ "[contenteditable]:not([contenteditable='false'])"
11516
+ ].join(",");
11517
+ function focusablesIn(roots) {
11518
+ const out = [];
11519
+ for (const root of roots) {
11520
+ for (const el of Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR))) {
11521
+ if (isFocusable(el)) out.push(el);
11522
+ }
11523
+ }
11524
+ return out;
11525
+ }
11526
+ function useOverlayScope({
11527
+ active,
11528
+ onEscape,
11529
+ escapeEnabled = true,
11530
+ autoFocus = true,
11531
+ restoreFocus = true,
11532
+ inertBackground = true
11533
+ }) {
11534
+ const [scopeId, setScopeId] = react.useState(null);
11535
+ const nodeRef = react.useRef(null);
11536
+ const restoreTo = react.useRef(null);
11537
+ const onEscapeRef = react.useRef(onEscape);
11538
+ onEscapeRef.current = onEscape;
11539
+ react.useEffect(() => {
11540
+ if (!active) {
11541
+ setScopeId(null);
11542
+ return;
11543
+ }
11544
+ const id = pushOverlay();
11545
+ setScopeId(id);
11546
+ return () => {
11547
+ popOverlay(id);
11548
+ };
11549
+ }, [active]);
11550
+ react.useEffect(() => {
11551
+ if (!active || !scopeId) return;
11552
+ const container = nodeRef.current;
11553
+ registerScopeRoot(scopeId, container);
11554
+ if (restoreFocus) {
11555
+ restoreTo.current = document.activeElement ?? null;
11556
+ }
11557
+ if (autoFocus) {
11558
+ const items2 = focusablesIn(getScopeRoots(scopeId));
11559
+ const target = items2[0] ?? container;
11560
+ target?.focus?.();
11561
+ }
11562
+ if (inertBackground) applyBackgroundInert(getScopeRoots(scopeId));
11563
+ return () => {
11564
+ unregisterScopeRoot(scopeId, container);
11565
+ if (inertBackground) releaseBackgroundInert();
11566
+ if (restoreFocus) {
11567
+ const to = restoreTo.current;
11568
+ restoreTo.current = null;
11569
+ if (to && to.isConnected) to.focus?.();
11570
+ }
11571
+ };
11572
+ }, [active, scopeId]);
11573
+ react.useEffect(() => {
11574
+ if (!active || !scopeId) return;
11575
+ const onKeyDown = (e) => {
11576
+ if (e.key === "Escape") {
11577
+ if (!escapeEnabled) return;
11578
+ if (!isTopOverlay(scopeId)) {
11579
+ e.stopPropagation();
11580
+ return;
11581
+ }
11582
+ onEscapeRef.current?.();
11583
+ return;
11584
+ }
11585
+ if (e.key !== "Tab") return;
11586
+ if (!isTopOverlay(scopeId)) {
11587
+ e.preventDefault();
11588
+ return;
11589
+ }
11590
+ const items2 = focusablesIn(getScopeRoots(scopeId));
11591
+ if (items2.length === 0) {
11592
+ e.preventDefault();
11593
+ nodeRef.current?.focus?.();
11594
+ return;
11595
+ }
11596
+ const first = items2[0];
11597
+ const last = items2[items2.length - 1];
11598
+ const current = document.activeElement;
11599
+ const inside = current ? items2.includes(current) : false;
11600
+ if (e.shiftKey) {
11601
+ if (!inside || current === first) {
11602
+ e.preventDefault();
11603
+ last.focus();
11604
+ }
11605
+ } else if (!inside || current === last) {
11606
+ e.preventDefault();
11607
+ first.focus();
11608
+ }
11609
+ };
11610
+ document.addEventListener("keydown", onKeyDown, true);
11611
+ return () => document.removeEventListener("keydown", onKeyDown, true);
11612
+ }, [active, scopeId, escapeEnabled]);
11613
+ const setNode = react.useCallback((el) => {
11614
+ nodeRef.current = el;
11615
+ }, []);
11616
+ return {
11617
+ ref: setNode,
11618
+ scopeId,
11619
+ layerBase: scopeId ? layerBaseFor(scopeId) : OVERLAY_LAYER.modalRoot
11620
+ };
11621
+ }
11622
+ react.createContext(null);
10673
11623
  var Modal = react.forwardRef(function Modal2({
10674
11624
  open,
10675
11625
  onClose,
@@ -10710,19 +11660,21 @@ var Modal = react.forwardRef(function Modal2({
10710
11660
  const [maximized, setMaximized] = react.useState(defaultMaximized);
10711
11661
  const drag = react.useRef(null);
10712
11662
  const prevOpen = react.useRef(open);
10713
- react.useEffect(() => {
10714
- if (!open) return;
10715
- const onKey = (e) => {
10716
- if (e.key === "Escape" && keyboard && closable) cancel?.();
10717
- };
10718
- document.addEventListener("keydown", onKey);
10719
- const prevOverflow = document.body.style.overflow;
10720
- document.body.style.overflow = "hidden";
10721
- return () => {
10722
- document.removeEventListener("keydown", onKey);
10723
- document.body.style.overflow = prevOverflow;
10724
- };
10725
- }, [open, keyboard, closable, cancel]);
11663
+ const scope = useOverlayScope({
11664
+ active: open,
11665
+ escapeEnabled: keyboard && closable,
11666
+ onEscape: cancel
11667
+ });
11668
+ const scopeRef = scope.ref;
11669
+ const titleId = `${react.useId()}title`;
11670
+ const attachDialogRef = react.useCallback(
11671
+ (el) => {
11672
+ scopeRef(el);
11673
+ if (typeof ref === "function") ref(el);
11674
+ else if (ref) ref.current = el;
11675
+ },
11676
+ [ref, scopeRef]
11677
+ );
10726
11678
  react.useEffect(() => {
10727
11679
  if (open) {
10728
11680
  setPos({ x: 0, y: 0 });
@@ -10773,9 +11725,11 @@ var Modal = react.forwardRef(function Modal2({
10773
11725
  children: /* @__PURE__ */ jsxRuntime.jsxs(
10774
11726
  "div",
10775
11727
  {
10776
- ref,
11728
+ ref: attachDialogRef,
10777
11729
  role: "dialog",
10778
11730
  "aria-modal": "true",
11731
+ "aria-labelledby": title ? titleId : void 0,
11732
+ tabIndex: -1,
10779
11733
  onClick: (e) => e.stopPropagation(),
10780
11734
  className: chunkTPGAXYFU_cjs.cx("klun-modal__dialog", maximized && "klun-modal__dialog--maximized", className),
10781
11735
  style: dialogStyle,
@@ -10789,7 +11743,7 @@ var Modal = react.forwardRef(function Modal2({
10789
11743
  children: [
10790
11744
  icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-modal__icon", children: icon }) : null,
10791
11745
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-modal__heading", children: [
10792
- title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-modal__title", children: title }) : null,
11746
+ title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-modal__title", id: titleId, children: title }) : null,
10793
11747
  description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-modal__description", children: description }) : null
10794
11748
  ] }),
10795
11749
  maximizable || closable ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-modal__actions", children: [
@@ -11057,7 +12011,7 @@ var ImageUpload = react.forwardRef(function ImageUpload2({
11057
12011
  shape = "circle",
11058
12012
  size = 96,
11059
12013
  label,
11060
- hint = "PNG or JPG, up to 5MB",
12014
+ hint: hintProp,
11061
12015
  onPick,
11062
12016
  onRemove,
11063
12017
  disabled = false,
@@ -11066,6 +12020,7 @@ var ImageUpload = react.forwardRef(function ImageUpload2({
11066
12020
  ...props
11067
12021
  }, ref) {
11068
12022
  const { imageUpload } = useLocale();
12023
+ const hint = hintProp ?? imageUpload.hint;
11069
12024
  const [over, setOver] = react.useState(false);
11070
12025
  const inputRef = react.useRef(null);
11071
12026
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: chunkTPGAXYFU_cjs.cx("klun-image-upload", className), style, ...props, children: [
@@ -11673,17 +12628,20 @@ var RichEditor = react.forwardRef(function RichEditor2({
11673
12628
  value,
11674
12629
  defaultValue = "",
11675
12630
  onChange,
11676
- placeholder = "Write something\u2026",
12631
+ placeholder: placeholderProp,
11677
12632
  disabled = false,
11678
12633
  hideToolbar = false,
11679
12634
  minHeight = 160,
11680
12635
  maxHeight,
11681
12636
  allowSource = true,
11682
- editorLabel = "Rich text editor",
12637
+ editorLabel: editorLabelProp,
11683
12638
  className,
11684
12639
  style,
11685
12640
  ...props
11686
12641
  }, ref) {
12642
+ const { richEditor: localeRich } = useLocale();
12643
+ const placeholder = placeholderProp ?? localeRich.placeholder;
12644
+ const editorLabel = editorLabelProp ?? localeRich.editorLabel;
11687
12645
  const editorRef = react.useRef(null);
11688
12646
  const [active, setActive] = react.useState([]);
11689
12647
  const [source, setSource] = react.useState(false);
@@ -11804,7 +12762,10 @@ var Select = react.forwardRef(function Select2({
11804
12762
  const rootRef = react.useRef(null);
11805
12763
  const s = useSelect({ children, value, defaultValue, disabled: disabled || loading, rootRef });
11806
12764
  const { select: selectLocale } = useLocale();
11807
- const fallbackLabel = !ariaLabel && !ariaLabelledBy && !s.selected && !placeholder ? selectLocale?.placeholder ?? "Select" : void 0;
12765
+ const generatedId = react.useId();
12766
+ const listboxId = `${generatedId}listbox`;
12767
+ const optionId = (index) => `${listboxId}-option-${index}`;
12768
+ const fallbackLabel = !ariaLabel && !ariaLabelledBy ? placeholder || selectLocale?.placeholder || "Select" : void 0;
11808
12769
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: chunkTPGAXYFU_cjs.cx("klun-select", `klun-select--${size}`, className), style, children: [
11809
12770
  /* @__PURE__ */ jsxRuntime.jsxs(
11810
12771
  "button",
@@ -11814,8 +12775,11 @@ var Select = react.forwardRef(function Select2({
11814
12775
  disabled,
11815
12776
  onClick: s.toggle,
11816
12777
  onKeyDown: s.triggerKeyDown,
12778
+ role: "combobox",
11817
12779
  "aria-haspopup": "listbox",
11818
12780
  "aria-expanded": s.open,
12781
+ "aria-controls": s.open ? listboxId : void 0,
12782
+ "aria-activedescendant": s.open && s.active >= 0 ? optionId(s.active) : void 0,
11819
12783
  "aria-label": ariaLabel ?? fallbackLabel,
11820
12784
  "aria-labelledby": ariaLabelledBy,
11821
12785
  "data-open": s.open || void 0,
@@ -11855,6 +12819,8 @@ var Select = react.forwardRef(function Select2({
11855
12819
  s.open ? /* @__PURE__ */ jsxRuntime.jsx(
11856
12820
  SelectListbox,
11857
12821
  {
12822
+ id: listboxId,
12823
+ optionId,
11858
12824
  anchorRef: s.triggerRef,
11859
12825
  options: s.options,
11860
12826
  current: s.current,
@@ -11876,7 +12842,7 @@ var SelectMenu = react.forwardRef(
11876
12842
  leadingIcon,
11877
12843
  error = false,
11878
12844
  disabled = false,
11879
- align = "left",
12845
+ align = "start",
11880
12846
  className,
11881
12847
  style,
11882
12848
  ...props
@@ -12556,6 +13522,7 @@ function computeSizes(panels, containerPx) {
12556
13522
  return sizes;
12557
13523
  }
12558
13524
  var SplitterRoot = react.forwardRef(function Splitter({ layout = "horizontal", onResize, onResizeEnd, className, children, ...props }, forwardedRef) {
13525
+ const { a11y } = useLocale();
12559
13526
  const containerRef = react.useRef(null);
12560
13527
  const setRefs = react.useCallback(
12561
13528
  (node) => {
@@ -12774,7 +13741,7 @@ var SplitterRoot = react.forwardRef(function Splitter({ layout = "horizontal", o
12774
13741
  {
12775
13742
  type: "button",
12776
13743
  className: "klun-splitter__collapse klun-splitter__collapse--start",
12777
- "aria-label": "Collapse start panel",
13744
+ "aria-label": a11y.collapseStart,
12778
13745
  tabIndex: -1,
12779
13746
  onPointerDown: (e) => e.stopPropagation(),
12780
13747
  onClick: () => collapseToggle(i, i),
@@ -12786,7 +13753,7 @@ var SplitterRoot = react.forwardRef(function Splitter({ layout = "horizontal", o
12786
13753
  {
12787
13754
  type: "button",
12788
13755
  className: "klun-splitter__collapse klun-splitter__collapse--end",
12789
- "aria-label": "Collapse end panel",
13756
+ "aria-label": a11y.collapseEnd,
12790
13757
  tabIndex: -1,
12791
13758
  onPointerDown: (e) => e.stopPropagation(),
12792
13759
  onClick: () => collapseToggle(i, i + 1),
@@ -13018,6 +13985,7 @@ var PageHeader = react.forwardRef(function PageHeader2({
13018
13985
  children,
13019
13986
  ...props
13020
13987
  }, ref) {
13988
+ const { a11y } = useLocale();
13021
13989
  return /* @__PURE__ */ jsxRuntime.jsxs(
13022
13990
  "header",
13023
13991
  {
@@ -13039,7 +14007,7 @@ var PageHeader = react.forwardRef(function PageHeader2({
13039
14007
  appearance: "ghost",
13040
14008
  variant: "neutral",
13041
14009
  size: "small",
13042
- "aria-label": "Back",
14010
+ "aria-label": a11y.back,
13043
14011
  className: "klun-page-header__back",
13044
14012
  icon: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-arrow-left-line", "aria-hidden": true }),
13045
14013
  onClick: onBack
@@ -13231,7 +14199,7 @@ var Sidebar = react.forwardRef(function Sidebar2({
13231
14199
  onSelect,
13232
14200
  defaultExpandedKeys = [],
13233
14201
  searchable = false,
13234
- searchPlaceholder = "Search",
14202
+ searchPlaceholder: searchPlaceholderProp,
13235
14203
  onSearch,
13236
14204
  collapsed: collapsedProp,
13237
14205
  defaultCollapsed = false,
@@ -13239,6 +14207,8 @@ var Sidebar = react.forwardRef(function Sidebar2({
13239
14207
  className,
13240
14208
  ...props
13241
14209
  }, ref) {
14210
+ const { sidebar: localeSidebar } = useLocale();
14211
+ const searchPlaceholder = searchPlaceholderProp ?? localeSidebar.searchPlaceholder;
13242
14212
  const [internalNav, setInternalNav] = react.useState(defaultNavKey);
13243
14213
  const [internalCollapsed, setInternalCollapsed] = react.useState(defaultCollapsed);
13244
14214
  const [expandedKeys, setExpandedKeys] = react.useState(
@@ -13274,7 +14244,7 @@ var Sidebar = react.forwardRef(function Sidebar2({
13274
14244
  "data-collapsed": collapsed ? "" : void 0,
13275
14245
  ...props,
13276
14246
  children: [
13277
- /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "klun-sidebar__rail", "aria-label": "Primary", children: [
14247
+ /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "klun-sidebar__rail", "aria-label": localeSidebar.primary, children: [
13278
14248
  brand != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-sidebar__brand", children: brand }),
13279
14249
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-sidebar__nav", children: navItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
13280
14250
  RailButton,
@@ -13321,6 +14291,7 @@ var Sidebar = react.forwardRef(function Sidebar2({
13321
14291
  type: "text",
13322
14292
  className: "klun-sidebar__search-input",
13323
14293
  placeholder: searchPlaceholder,
14294
+ "aria-label": searchPlaceholder,
13324
14295
  value: query,
13325
14296
  tabIndex: collapsed ? -1 : 0,
13326
14297
  onChange: (e) => {
@@ -13690,6 +14661,7 @@ var Wizard = react.forwardRef(function Wizard2({
13690
14661
  className,
13691
14662
  ...props
13692
14663
  }, ref) {
14664
+ const { wizard } = useLocale();
13693
14665
  const isControlled = current !== void 0;
13694
14666
  const [internal, setInternal] = react.useState(defaultCurrent);
13695
14667
  const idx = isControlled ? current : internal;
@@ -13734,7 +14706,7 @@ var Wizard = react.forwardRef(function Wizard2({
13734
14706
  className: "klun-wizard__nav",
13735
14707
  onClick: () => go(idx - 1),
13736
14708
  disabled: idx === 0,
13737
- children: "Back"
14709
+ children: wizard.back
13738
14710
  }
13739
14711
  ),
13740
14712
  !isLast ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -13743,7 +14715,7 @@ var Wizard = react.forwardRef(function Wizard2({
13743
14715
  type: "button",
13744
14716
  className: "klun-wizard__nav klun-wizard__nav--primary",
13745
14717
  onClick: () => go(idx + 1),
13746
- children: "Next"
14718
+ children: wizard.next
13747
14719
  }
13748
14720
  ) : /* @__PURE__ */ jsxRuntime.jsx(
13749
14721
  "button",
@@ -13751,7 +14723,7 @@ var Wizard = react.forwardRef(function Wizard2({
13751
14723
  type: "button",
13752
14724
  className: "klun-wizard__nav klun-wizard__nav--primary",
13753
14725
  onClick: () => onFinish?.(),
13754
- children: "Finish"
14726
+ children: wizard.finish
13755
14727
  }
13756
14728
  )
13757
14729
  ] })
@@ -13838,13 +14810,14 @@ var INTENT_ICON = {
13838
14810
  warning: "ri-alert-line"
13839
14811
  };
13840
14812
  function ConfirmDialog({ opts, onClose }) {
14813
+ const { popconfirm } = useLocale();
13841
14814
  const {
13842
- title = "Are you sure?",
14815
+ title = popconfirm.title,
13843
14816
  description,
13844
14817
  icon,
13845
14818
  intent = "primary",
13846
- confirmText = "Confirm",
13847
- cancelText = "Cancel",
14819
+ confirmText = popconfirm.confirm,
14820
+ cancelText = popconfirm.cancel,
13848
14821
  requireInput,
13849
14822
  onConfirm
13850
14823
  } = opts;
@@ -13984,7 +14957,11 @@ function place(w, h, opts) {
13984
14957
  let top;
13985
14958
  if (opts.rect) {
13986
14959
  const r = opts.rect;
13987
- left = r.right - 4 + w > vw - GAP3 ? r.left - w + 4 : r.right - 4;
14960
+ if (opts.rtl) {
14961
+ left = r.left - w + 4 < GAP3 ? r.right - 4 : r.left - w + 4;
14962
+ } else {
14963
+ left = r.right - 4 + w > vw - GAP3 ? r.left - w + 4 : r.right - 4;
14964
+ }
13988
14965
  top = r.top - 4;
13989
14966
  } else {
13990
14967
  const p = opts.point ?? { x: 0, y: 0 };
@@ -14006,7 +14983,9 @@ function MenuPanel({ items: items2, width, className, point, anchorEl, autoActiv
14006
14983
  const el = ref.current;
14007
14984
  const w = el?.offsetWidth ?? width;
14008
14985
  const h = el?.offsetHeight ?? 0;
14009
- setPos(place(w, h, anchorEl ? { rect: anchorEl.getBoundingClientRect() } : { point }));
14986
+ const dirHost = anchorEl ?? ref.current ?? document.body;
14987
+ const rtl = getComputedStyle(dirHost).direction === "rtl";
14988
+ setPos(place(w, h, anchorEl ? { rect: anchorEl.getBoundingClientRect(), rtl } : { point }));
14010
14989
  }, [width, point?.x, point?.y, anchorEl, items2]);
14011
14990
  const move = react.useCallback(
14012
14991
  (dir) => {
@@ -14176,7 +15155,6 @@ var Drawer = react.forwardRef(function Drawer2({
14176
15155
  onClose,
14177
15156
  title,
14178
15157
  placement,
14179
- side,
14180
15158
  width = "50%",
14181
15159
  height = "50%",
14182
15160
  size = "default",
@@ -14194,22 +15172,24 @@ var Drawer = react.forwardRef(function Drawer2({
14194
15172
  ...props
14195
15173
  }, ref) {
14196
15174
  const { drawer } = useLocale();
14197
- const place2 = placement ?? side ?? "right";
15175
+ const place2 = placement ?? "right";
14198
15176
  const horizontal = place2 === "left" || place2 === "right";
14199
15177
  const prevOpen = react.useRef(open);
14200
- react.useEffect(() => {
14201
- if (!open) return;
14202
- const onKey = (e) => {
14203
- if (e.key === "Escape" && keyboard && closable) onClose?.();
14204
- };
14205
- document.addEventListener("keydown", onKey);
14206
- const prevOverflow = document.body.style.overflow;
14207
- document.body.style.overflow = "hidden";
14208
- return () => {
14209
- document.removeEventListener("keydown", onKey);
14210
- document.body.style.overflow = prevOverflow;
14211
- };
14212
- }, [open, keyboard, closable, onClose]);
15178
+ const scope = useOverlayScope({
15179
+ active: open,
15180
+ escapeEnabled: keyboard && closable,
15181
+ onEscape: onClose
15182
+ });
15183
+ const scopeRef = scope.ref;
15184
+ const titleId = `${react.useId()}title`;
15185
+ const attachPanelRef = react.useCallback(
15186
+ (el) => {
15187
+ scopeRef(el);
15188
+ if (typeof ref === "function") ref(el);
15189
+ else if (ref) ref.current = el;
15190
+ },
15191
+ [ref, scopeRef]
15192
+ );
14213
15193
  react.useEffect(() => {
14214
15194
  if (prevOpen.current !== open) {
14215
15195
  afterOpenChange?.(open);
@@ -14228,16 +15208,18 @@ var Drawer = react.forwardRef(function Drawer2({
14228
15208
  children: /* @__PURE__ */ jsxRuntime.jsxs(
14229
15209
  "div",
14230
15210
  {
14231
- ref,
15211
+ ref: attachPanelRef,
14232
15212
  role: "dialog",
14233
15213
  "aria-modal": "true",
15214
+ "aria-labelledby": title ? titleId : void 0,
15215
+ tabIndex: -1,
14234
15216
  onClick: (e) => e.stopPropagation(),
14235
15217
  className: chunkTPGAXYFU_cjs.cx("klun-drawer__panel", className),
14236
15218
  style: panelStyle,
14237
15219
  ...props,
14238
15220
  children: [
14239
15221
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-drawer__header", children: [
14240
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-drawer__title", children: title }),
15222
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-drawer__title", id: title ? titleId : void 0, children: title }),
14241
15223
  extra ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-drawer__extra", children: extra }) : null,
14242
15224
  closable ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onClose, "aria-label": drawer.close, className: "klun-drawer__close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 5l10 10M15 5L5 15", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) }) : null
14243
15225
  ] }),
@@ -14250,7 +15232,7 @@ var Drawer = react.forwardRef(function Drawer2({
14250
15232
  );
14251
15233
  });
14252
15234
  Drawer.displayName = "Drawer";
14253
- var Dropdown = react.forwardRef(function Dropdown2({ trigger, items: items2 = [], align = "left", width = 220, className, ...props }, ref) {
15235
+ var Dropdown = react.forwardRef(function Dropdown2({ trigger, items: items2 = [], align = "start", width = 220, className, ...props }, ref) {
14254
15236
  const [open, setOpen] = react.useState(false);
14255
15237
  const innerRef = react.useRef(null);
14256
15238
  react.useEffect(() => {
@@ -14525,6 +15507,7 @@ function ImageViewer({
14525
15507
  closeOnBackdrop = true,
14526
15508
  className
14527
15509
  }) {
15510
+ const { a11y, imageViewer, modal, pagination } = useLocale();
14528
15511
  const gallery = items2 && items2.length > 0 ? items2 : src != null ? [{ src, alt }] : [];
14529
15512
  const [innerIndex, setInnerIndex] = react.useState(0);
14530
15513
  const idx = index ?? innerIndex;
@@ -14613,20 +15596,20 @@ function ImageViewer({
14613
15596
  ] }),
14614
15597
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-image-viewer__tools", children: [
14615
15598
  zoomable ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14616
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Zoom out", onClick: () => setScale((s) => clampScale(s - 0.25)), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-zoom-out-line" }) }),
15599
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": a11y.zoomOut, onClick: () => setScale((s) => clampScale(s - 0.25)), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-zoom-out-line" }) }),
14617
15600
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "klun-image-viewer__zoom", children: [
14618
15601
  Math.round(scale * 100),
14619
15602
  "%"
14620
15603
  ] }),
14621
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Zoom in", onClick: () => setScale((s) => clampScale(s + 0.25)), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-zoom-in-line" }) })
15604
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": a11y.zoomIn, onClick: () => setScale((s) => clampScale(s + 0.25)), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-zoom-in-line" }) })
14622
15605
  ] }) : null,
14623
- rotatable ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Rotate", onClick: () => setRot((r) => (r + 90) % 360), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-anticlockwise-line" }) }) : null,
14624
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Reset", onClick: reset, children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-aspect-ratio-line" }) }),
14625
- onDownload ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Download", onClick: () => onDownload(current, safeIdx), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-download-2-line" }) }) : null,
14626
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-close-line" }) })
15606
+ rotatable ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": a11y.rotate, onClick: () => setRot((r) => (r + 90) % 360), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-anticlockwise-line" }) }) : null,
15607
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": imageViewer.reset, onClick: reset, children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-aspect-ratio-line" }) }),
15608
+ onDownload ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": imageViewer.download, onClick: () => onDownload(current, safeIdx), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-download-2-line" }) }) : null,
15609
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": modal.close, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-close-line" }) })
14627
15610
  ] })
14628
15611
  ] }),
14629
- gallery.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__nav klun-image-viewer__nav--prev", "aria-label": "Previous", onMouseDown: (e) => e.stopPropagation(), onClick: () => goTo(safeIdx - 1), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-arrow-left-s-line" }) }) : null,
15612
+ gallery.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__nav klun-image-viewer__nav--prev", "aria-label": pagination.previous, onMouseDown: (e) => e.stopPropagation(), onClick: () => goTo(safeIdx - 1), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-arrow-left-s-line" }) }) : null,
14630
15613
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-image-viewer__stage", onMouseDown: (e) => e.stopPropagation(), onWheel, children: /* @__PURE__ */ jsxRuntime.jsx(
14631
15614
  "img",
14632
15615
  {
@@ -14639,7 +15622,7 @@ function ImageViewer({
14639
15622
  style: { transform: `translate(${pan.x}px, ${pan.y}px) scale(${scale}) rotate(${rot}deg)` }
14640
15623
  }
14641
15624
  ) }),
14642
- gallery.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__nav klun-image-viewer__nav--next", "aria-label": "Next", onMouseDown: (e) => e.stopPropagation(), onClick: () => goTo(safeIdx + 1), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-arrow-right-s-line" }) }) : null
15625
+ gallery.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "klun-image-viewer__nav klun-image-viewer__nav--next", "aria-label": pagination.next, onMouseDown: (e) => e.stopPropagation(), onClick: () => goTo(safeIdx + 1), children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-arrow-right-s-line" }) }) : null
14643
15626
  ]
14644
15627
  }
14645
15628
  ),
@@ -15056,5 +16039,5 @@ exports.useStepper = useStepper;
15056
16039
  exports.viVN = viVN;
15057
16040
  exports.zhCN = zhCN;
15058
16041
  exports.zhTW = zhTW;
15059
- //# sourceMappingURL=chunk-ODVX2AVA.cjs.map
15060
- //# sourceMappingURL=chunk-ODVX2AVA.cjs.map
16042
+ //# sourceMappingURL=chunk-GDPWRDDU.cjs.map
16043
+ //# sourceMappingURL=chunk-GDPWRDDU.cjs.map