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.
@@ -1,9 +1,9 @@
1
1
  import { cx } from './chunk-T225J6LV.js';
2
- import { createContext, forwardRef, useState, useRef, useEffect, useMemo, Children, useCallback, useLayoutEffect, Fragment as Fragment$1, createElement, useContext, isValidElement, cloneElement, useSyncExternalStore } from 'react';
2
+ import { createContext, forwardRef, useState, useRef, useEffect, useMemo, Children, useCallback, useId, useLayoutEffect, isValidElement, cloneElement, Fragment as Fragment$1, createElement, useContext, useSyncExternalStore } from 'react';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCorners, useDroppable, closestCenter } from '@dnd-kit/core';
5
5
  import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
6
- import { CSS } from '@dnd-kit/utilities';
6
+ import { CSS as CSS$1 } from '@dnd-kit/utilities';
7
7
  import { createPortal } from 'react-dom';
8
8
  import { createRoot } from 'react-dom/client';
9
9
 
@@ -197,7 +197,7 @@ var enUS = {
197
197
  banner: { dismiss: "Dismiss" },
198
198
  toast: { dismiss: "Dismiss" },
199
199
  fileUpload: { clickToUpload: "Click to upload", orDragAndDrop: "or drag and drop" },
200
- imageUpload: { label: "Upload image", remove: "Remove" },
200
+ imageUpload: { label: "Upload image", remove: "Remove", hint: "PNG or JPG, up to 5MB" },
201
201
  passwordStrength: { weak: "Weak", fair: "Fair", good: "Good", strong: "Strong" },
202
202
  commandMenu: {
203
203
  placeholder: "Type a command or search\u2026",
@@ -265,7 +265,14 @@ var enUS = {
265
265
  perPage: "{size} / page",
266
266
  selectRow: "Select row",
267
267
  selectAll: "Select all rows"
268
- }
268
+ },
269
+ wizard: { back: "\u4E0A\u4E00\u6B65", next: "\u4E0B\u4E00\u6B65", finish: "\u5B8C\u6210" },
270
+ 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" },
271
+ richEditor: { placeholder: "Write something\u2026", editorLabel: "Rich text editor" },
272
+ copy: { label: "Copy" },
273
+ emojiPicker: { searchPlaceholder: "Search emoji", emptyText: "No emoji found", addReaction: "Add reaction" },
274
+ sidebar: { searchPlaceholder: "Search", primary: "Primary" },
275
+ imageViewer: { reset: "Reset", download: "Download" }
269
276
  };
270
277
  var zhCN = {
271
278
  locale: "zh-CN",
@@ -295,7 +302,7 @@ var zhCN = {
295
302
  banner: { dismiss: "\u5173\u95ED" },
296
303
  toast: { dismiss: "\u5173\u95ED" },
297
304
  fileUpload: { clickToUpload: "\u70B9\u51FB\u4E0A\u4F20", orDragAndDrop: "\u6216\u62D6\u62FD\u5230\u6B64\u5904" },
298
- imageUpload: { label: "\u4E0A\u4F20\u56FE\u7247", remove: "\u79FB\u9664" },
305
+ imageUpload: { label: "\u4E0A\u4F20\u56FE\u7247", remove: "\u79FB\u9664", hint: "\u652F\u6301 PNG \u6216 JPG\uFF0C\u6700\u5927 5MB" },
299
306
  passwordStrength: { weak: "\u5F31", fair: "\u4E00\u822C", good: "\u826F\u597D", strong: "\u5F3A" },
300
307
  commandMenu: {
301
308
  placeholder: "\u8F93\u5165\u547D\u4EE4\u6216\u641C\u7D22\u2026",
@@ -363,7 +370,14 @@ var zhCN = {
363
370
  perPage: "{size} / \u9875",
364
371
  selectRow: "\u9009\u62E9\u672C\u884C",
365
372
  selectAll: "\u5168\u9009"
366
- }
373
+ },
374
+ wizard: { back: "\u4E0A\u4E00\u6B65", next: "\u4E0B\u4E00\u6B65", finish: "\u5B8C\u6210" },
375
+ 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" },
376
+ richEditor: { placeholder: "\u8BF7\u8F93\u5165\u5185\u5BB9\u2026", editorLabel: "\u5BCC\u6587\u672C\u7F16\u8F91\u5668" },
377
+ copy: { label: "\u590D\u5236" },
378
+ emojiPicker: { searchPlaceholder: "\u641C\u7D22\u8868\u60C5", emptyText: "\u6CA1\u6709\u627E\u5230\u8868\u60C5", addReaction: "\u6DFB\u52A0\u8868\u60C5" },
379
+ sidebar: { searchPlaceholder: "\u641C\u7D22", primary: "\u4E3B\u5BFC\u822A" },
380
+ imageViewer: { reset: "\u91CD\u7F6E", download: "\u4E0B\u8F7D" }
367
381
  };
368
382
  var zhTW = {
369
383
  locale: "zh-TW",
@@ -387,13 +401,13 @@ var zhTW = {
387
401
  },
388
402
  timePicker: { am: "\u4E0A\u5348", pm: "\u4E0B\u5348" },
389
403
  pagination: { previous: "\u4E0A\u4E00\u9801", next: "\u4E0B\u4E00\u9801" },
390
- modal: { close: "\u95DC\u9589" },
404
+ modal: { close: "\u95DC\u9589", maximize: "\u6700\u5927\u5316", restore: "\u9084\u539F" },
391
405
  drawer: { close: "\u95DC\u9589" },
392
406
  alert: { dismiss: "\u95DC\u9589" },
393
407
  banner: { dismiss: "\u95DC\u9589" },
394
408
  toast: { dismiss: "\u95DC\u9589" },
395
409
  fileUpload: { clickToUpload: "\u9EDE\u64CA\u4E0A\u50B3", orDragAndDrop: "\u6216\u62D6\u66F3\u5230\u6B64\u8655" },
396
- imageUpload: { label: "\u4E0A\u50B3\u5716\u7247", remove: "\u79FB\u9664" },
410
+ imageUpload: { label: "\u4E0A\u50B3\u5716\u7247", remove: "\u79FB\u9664", hint: "\u652F\u63F4 PNG \u6216 JPG\uFF0C\u6700\u5927 5MB" },
397
411
  passwordStrength: { weak: "\u5F31", fair: "\u4E00\u822C", good: "\u826F\u597D", strong: "\u5F37" },
398
412
  commandMenu: {
399
413
  placeholder: "\u8F38\u5165\u547D\u4EE4\u6216\u641C\u5C0B\u2026",
@@ -461,7 +475,14 @@ var zhTW = {
461
475
  perPage: "{size} / \u9801",
462
476
  selectRow: "\u9078\u64C7\u672C\u884C",
463
477
  selectAll: "\u5168\u9078"
464
- }
478
+ },
479
+ wizard: { back: "\u623B\u308B", next: "\u6B21\u3078", finish: "\u5B8C\u4E86" },
480
+ 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" },
481
+ richEditor: { placeholder: "\u8ACB\u8F38\u5165\u5167\u5BB9\u2026", editorLabel: "\u5BCC\u6587\u5B57\u7DE8\u8F2F\u5668" },
482
+ copy: { label: "\u8907\u88FD" },
483
+ emojiPicker: { searchPlaceholder: "\u641C\u5C0B\u8868\u60C5", emptyText: "\u627E\u4E0D\u5230\u8868\u60C5", addReaction: "\u65B0\u589E\u8868\u60C5" },
484
+ sidebar: { searchPlaceholder: "\u641C\u5C0B", primary: "\u4E3B\u5C0E\u89BD" },
485
+ imageViewer: { reset: "\u91CD\u8A2D", download: "\u4E0B\u8F09" }
465
486
  };
466
487
  var jaJP = {
467
488
  locale: "ja-JP",
@@ -485,13 +506,15 @@ var jaJP = {
485
506
  },
486
507
  timePicker: { am: "\u5348\u524D", pm: "\u5348\u5F8C" },
487
508
  pagination: { previous: "\u524D\u3078", next: "\u6B21\u3078" },
488
- modal: { close: "\u9589\u3058\u308B" },
509
+ modal: { close: "\u9589\u3058\u308B", maximize: "\u6700\u5927\u5316", restore: "\u5143\u306B\u623B\u3059" },
510
+ select: { placeholder: "\u9078\u629E" },
511
+ counterInput: { decrease: "\u6E1B\u3089\u3059", increase: "\u5897\u3084\u3059" },
489
512
  drawer: { close: "\u9589\u3058\u308B" },
490
513
  alert: { dismiss: "\u9589\u3058\u308B" },
491
514
  banner: { dismiss: "\u9589\u3058\u308B" },
492
515
  toast: { dismiss: "\u9589\u3058\u308B" },
493
516
  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" },
494
- imageUpload: { label: "\u753B\u50CF\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9", remove: "\u524A\u9664" },
517
+ imageUpload: { label: "\u753B\u50CF\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9", remove: "\u524A\u9664", hint: "PNG \u307E\u305F\u306F JPG\u3001\u6700\u5927 5MB" },
495
518
  passwordStrength: { weak: "\u5F31\u3044", fair: "\u666E\u901A", good: "\u826F\u3044", strong: "\u5F37\u3044" },
496
519
  commandMenu: {
497
520
  placeholder: "\u30B3\u30DE\u30F3\u30C9\u3092\u5165\u529B\u307E\u305F\u306F\u691C\u7D22\u2026",
@@ -554,8 +577,17 @@ var jaJP = {
554
577
  previous: "\u524D\u3078",
555
578
  next: "\u6B21\u3078",
556
579
  pageRange: "{total} \u4EF6\u4E2D {from}\u2013{to}",
557
- perPage: "{size} \u4EF6 / \u30DA\u30FC\u30B8"
558
- }
580
+ perPage: "{size} \u4EF6 / \u30DA\u30FC\u30B8",
581
+ selectRow: "\u884C\u3092\u9078\u629E",
582
+ selectAll: "\u3059\u3079\u3066\u9078\u629E"
583
+ },
584
+ wizard: { back: "\uC774\uC804", next: "\uB2E4\uC74C", finish: "\uC644\uB8CC" },
585
+ 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" },
586
+ richEditor: { placeholder: "\u5185\u5BB9\u3092\u5165\u529B\u2026", editorLabel: "\u30EA\u30C3\u30C1\u30C6\u30AD\u30B9\u30C8\u30A8\u30C7\u30A3\u30BF\u30FC" },
587
+ copy: { label: "\u30B3\u30D4\u30FC" },
588
+ 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" },
589
+ sidebar: { searchPlaceholder: "\u691C\u7D22", primary: "\u30E1\u30A4\u30F3\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3" },
590
+ imageViewer: { reset: "\u30EA\u30BB\u30C3\u30C8", download: "\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9" }
559
591
  };
560
592
  var koKR = {
561
593
  locale: "ko-KR",
@@ -579,13 +611,15 @@ var koKR = {
579
611
  },
580
612
  timePicker: { am: "\uC624\uC804", pm: "\uC624\uD6C4" },
581
613
  pagination: { previous: "\uC774\uC804", next: "\uB2E4\uC74C" },
582
- modal: { close: "\uB2EB\uAE30" },
614
+ modal: { close: "\uB2EB\uAE30", maximize: "\uCD5C\uB300\uD654", restore: "\uBCF5\uC6D0" },
615
+ select: { placeholder: "\uC120\uD0DD" },
616
+ counterInput: { decrease: "\uAC10\uC18C", increase: "\uC99D\uAC00" },
583
617
  drawer: { close: "\uB2EB\uAE30" },
584
618
  alert: { dismiss: "\uB2EB\uAE30" },
585
619
  banner: { dismiss: "\uB2EB\uAE30" },
586
620
  toast: { dismiss: "\uB2EB\uAE30" },
587
621
  fileUpload: { clickToUpload: "\uD074\uB9AD\uD558\uC5EC \uC5C5\uB85C\uB4DC", orDragAndDrop: "\uB610\uB294 \uB4DC\uB798\uADF8 \uC564 \uB4DC\uB86D" },
588
- imageUpload: { label: "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC", remove: "\uC81C\uAC70" },
622
+ imageUpload: { label: "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC", remove: "\uC81C\uAC70", hint: "PNG \uB610\uB294 JPG, \uCD5C\uB300 5MB" },
589
623
  passwordStrength: { weak: "\uC57D\uD568", fair: "\uBCF4\uD1B5", good: "\uC591\uD638", strong: "\uAC15\uD568" },
590
624
  commandMenu: {
591
625
  placeholder: "\uBA85\uB839\uC5B4 \uC785\uB825 \uB610\uB294 \uAC80\uC0C9\u2026",
@@ -648,8 +682,17 @@ var koKR = {
648
682
  previous: "\uC774\uC804",
649
683
  next: "\uB2E4\uC74C",
650
684
  pageRange: "{total}\uAC1C \uC911 {from}\u2013{to}",
651
- perPage: "{size}\uAC1C / \uD398\uC774\uC9C0"
652
- }
685
+ perPage: "{size}\uAC1C / \uD398\uC774\uC9C0",
686
+ selectRow: "\uD589 \uC120\uD0DD",
687
+ selectAll: "\uC804\uCCB4 \uC120\uD0DD"
688
+ },
689
+ wizard: { back: "Retour", next: "Suivant", finish: "Terminer" },
690
+ 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" },
691
+ richEditor: { placeholder: "\uB0B4\uC6A9\uC744 \uC785\uB825\u2026", editorLabel: "\uB9AC\uCE58 \uD14D\uC2A4\uD2B8 \uD3B8\uC9D1\uAE30" },
692
+ copy: { label: "\uBCF5\uC0AC" },
693
+ emojiPicker: { searchPlaceholder: "\uC774\uBAA8\uC9C0 \uAC80\uC0C9", emptyText: "\uC774\uBAA8\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C", addReaction: "\uBC18\uC751 \uCD94\uAC00" },
694
+ sidebar: { searchPlaceholder: "\uAC80\uC0C9", primary: "\uAE30\uBCF8 \uD0D0\uC0C9" },
695
+ imageViewer: { reset: "\uC7AC\uC124\uC815", download: "\uB2E4\uC6B4\uB85C\uB4DC" }
653
696
  };
654
697
  var frFR = {
655
698
  locale: "fr-FR",
@@ -673,13 +716,15 @@ var frFR = {
673
716
  },
674
717
  timePicker: { am: "AM", pm: "PM" },
675
718
  pagination: { previous: "Pr\xE9c\xE9dent", next: "Suivant" },
676
- modal: { close: "Fermer" },
719
+ modal: { close: "Fermer", maximize: "Agrandir", restore: "Restaurer" },
720
+ select: { placeholder: "S\xE9lectionner" },
721
+ counterInput: { decrease: "Diminuer", increase: "Augmenter" },
677
722
  drawer: { close: "Fermer" },
678
723
  alert: { dismiss: "Fermer" },
679
724
  banner: { dismiss: "Fermer" },
680
725
  toast: { dismiss: "Fermer" },
681
726
  fileUpload: { clickToUpload: "Cliquez pour t\xE9l\xE9verser", orDragAndDrop: "ou glissez-d\xE9posez" },
682
- imageUpload: { label: "T\xE9l\xE9verser une image", remove: "Supprimer" },
727
+ imageUpload: { label: "T\xE9l\xE9verser une image", remove: "Supprimer", hint: "PNG ou JPG, jusqu'\xE0 5 Mo" },
683
728
  passwordStrength: { weak: "Faible", fair: "Moyen", good: "Bon", strong: "Fort" },
684
729
  commandMenu: {
685
730
  placeholder: "Tapez une commande ou recherchez\u2026",
@@ -742,8 +787,17 @@ var frFR = {
742
787
  previous: "Pr\xE9c\xE9dent",
743
788
  next: "Suivant",
744
789
  pageRange: "{from}\u2013{to} sur {total}",
745
- perPage: "{size} / page"
746
- }
790
+ perPage: "{size} / page",
791
+ selectRow: "S\xE9lectionner la ligne",
792
+ selectAll: "Tout s\xE9lectionner"
793
+ },
794
+ wizard: { back: "Zur\xFCck", next: "Weiter", finish: "Fertig" },
795
+ 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" },
796
+ richEditor: { placeholder: "\xC9crivez quelque chose\u2026", editorLabel: "\xC9diteur de texte enrichi" },
797
+ copy: { label: "Copier" },
798
+ emojiPicker: { searchPlaceholder: "Rechercher un emoji", emptyText: "Aucun emoji trouv\xE9", addReaction: "Ajouter une r\xE9action" },
799
+ sidebar: { searchPlaceholder: "Rechercher", primary: "Navigation principale" },
800
+ imageViewer: { reset: "R\xE9initialiser", download: "T\xE9l\xE9charger" }
747
801
  };
748
802
  var deDE = {
749
803
  locale: "de-DE",
@@ -767,13 +821,15 @@ var deDE = {
767
821
  },
768
822
  timePicker: { am: "AM", pm: "PM" },
769
823
  pagination: { previous: "Zur\xFCck", next: "Weiter" },
770
- modal: { close: "Schlie\xDFen" },
824
+ modal: { close: "Schlie\xDFen", maximize: "Maximieren", restore: "Wiederherstellen" },
825
+ select: { placeholder: "Ausw\xE4hlen" },
826
+ counterInput: { decrease: "Verringern", increase: "Erh\xF6hen" },
771
827
  drawer: { close: "Schlie\xDFen" },
772
828
  alert: { dismiss: "Schlie\xDFen" },
773
829
  banner: { dismiss: "Schlie\xDFen" },
774
830
  toast: { dismiss: "Schlie\xDFen" },
775
831
  fileUpload: { clickToUpload: "Zum Hochladen klicken", orDragAndDrop: "oder per Drag & Drop" },
776
- imageUpload: { label: "Bild hochladen", remove: "Entfernen" },
832
+ imageUpload: { label: "Bild hochladen", remove: "Entfernen", hint: "PNG oder JPG, bis zu 5 MB" },
777
833
  passwordStrength: { weak: "Schwach", fair: "Mittel", good: "Gut", strong: "Stark" },
778
834
  commandMenu: {
779
835
  placeholder: "Befehl eingeben oder suchen\u2026",
@@ -836,8 +892,17 @@ var deDE = {
836
892
  previous: "Zur\xFCck",
837
893
  next: "Weiter",
838
894
  pageRange: "{from}\u2013{to} von {total}",
839
- perPage: "{size} / Seite"
840
- }
895
+ perPage: "{size} / Seite",
896
+ selectRow: "Zeile ausw\xE4hlen",
897
+ selectAll: "Alle ausw\xE4hlen"
898
+ },
899
+ wizard: { back: "Atr\xE1s", next: "Siguiente", finish: "Finalizar" },
900
+ a11y: { zoomIn: "Vergr\xF6\xDFern", zoomOut: "Verkleinern", rotate: "Drehen", collapseStart: "Startbereich einklappen", collapseEnd: "Endbereich einklappen", bulkActions: "Mehrfachaktionen", clearSelection: "Auswahl aufheben", back: "Zur\xFCck" },
901
+ richEditor: { placeholder: "Etwas eingeben\u2026", editorLabel: "Rich-Text-Editor" },
902
+ copy: { label: "Kopieren" },
903
+ emojiPicker: { searchPlaceholder: "Emoji suchen", emptyText: "Kein Emoji gefunden", addReaction: "Reaktion hinzuf\xFCgen" },
904
+ sidebar: { searchPlaceholder: "Suchen", primary: "Hauptnavigation" },
905
+ imageViewer: { reset: "Zur\xFCcksetzen", download: "Herunterladen" }
841
906
  };
842
907
  var esES = {
843
908
  locale: "es-ES",
@@ -861,13 +926,15 @@ var esES = {
861
926
  },
862
927
  timePicker: { am: "AM", pm: "PM" },
863
928
  pagination: { previous: "Anterior", next: "Siguiente" },
864
- modal: { close: "Cerrar" },
929
+ modal: { close: "Cerrar", maximize: "Maximizar", restore: "Restaurar" },
930
+ select: { placeholder: "Seleccionar" },
931
+ counterInput: { decrease: "Disminuir", increase: "Aumentar" },
865
932
  drawer: { close: "Cerrar" },
866
933
  alert: { dismiss: "Cerrar" },
867
934
  banner: { dismiss: "Cerrar" },
868
935
  toast: { dismiss: "Cerrar" },
869
936
  fileUpload: { clickToUpload: "Haz clic para subir", orDragAndDrop: "o arrastra y suelta" },
870
- imageUpload: { label: "Subir imagen", remove: "Eliminar" },
937
+ imageUpload: { label: "Subir imagen", remove: "Eliminar", hint: "PNG o JPG, hasta 5 MB" },
871
938
  passwordStrength: { weak: "D\xE9bil", fair: "Regular", good: "Buena", strong: "Fuerte" },
872
939
  commandMenu: {
873
940
  placeholder: "Escribe un comando o busca\u2026",
@@ -930,8 +997,17 @@ var esES = {
930
997
  previous: "Anterior",
931
998
  next: "Siguiente",
932
999
  pageRange: "{from}\u2013{to} de {total}",
933
- perPage: "{size} / p\xE1gina"
934
- }
1000
+ perPage: "{size} / p\xE1gina",
1001
+ selectRow: "Seleccionar fila",
1002
+ selectAll: "Seleccionar todo"
1003
+ },
1004
+ wizard: { back: "Voltar", next: "Avan\xE7ar", finish: "Concluir" },
1005
+ 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" },
1006
+ richEditor: { placeholder: "Escribe algo\u2026", editorLabel: "Editor de texto enriquecido" },
1007
+ copy: { label: "Copiar" },
1008
+ emojiPicker: { searchPlaceholder: "Buscar emoji", emptyText: "No se encontraron emojis", addReaction: "A\xF1adir reacci\xF3n" },
1009
+ sidebar: { searchPlaceholder: "Buscar", primary: "Navegaci\xF3n principal" },
1010
+ imageViewer: { reset: "Restablecer", download: "Descargar" }
935
1011
  };
936
1012
  var ptBR = {
937
1013
  locale: "pt-BR",
@@ -955,13 +1031,15 @@ var ptBR = {
955
1031
  },
956
1032
  timePicker: { am: "AM", pm: "PM" },
957
1033
  pagination: { previous: "Anterior", next: "Pr\xF3ximo" },
958
- modal: { close: "Fechar" },
1034
+ modal: { close: "Fechar", maximize: "Maximizar", restore: "Restaurar" },
1035
+ select: { placeholder: "Selecionar" },
1036
+ counterInput: { decrease: "Diminuir", increase: "Aumentar" },
959
1037
  drawer: { close: "Fechar" },
960
1038
  alert: { dismiss: "Fechar" },
961
1039
  banner: { dismiss: "Fechar" },
962
1040
  toast: { dismiss: "Fechar" },
963
1041
  fileUpload: { clickToUpload: "Clique para enviar", orDragAndDrop: "ou arraste e solte" },
964
- imageUpload: { label: "Enviar imagem", remove: "Remover" },
1042
+ imageUpload: { label: "Enviar imagem", remove: "Remover", hint: "PNG ou JPG, at\xE9 5 MB" },
965
1043
  passwordStrength: { weak: "Fraca", fair: "Razo\xE1vel", good: "Boa", strong: "Forte" },
966
1044
  commandMenu: {
967
1045
  placeholder: "Digite um comando ou pesquise\u2026",
@@ -1024,8 +1102,17 @@ var ptBR = {
1024
1102
  previous: "Anterior",
1025
1103
  next: "Pr\xF3ximo",
1026
1104
  pageRange: "{from}\u2013{to} de {total}",
1027
- perPage: "{size} / p\xE1gina"
1028
- }
1105
+ perPage: "{size} / p\xE1gina",
1106
+ selectRow: "Selecionar linha",
1107
+ selectAll: "Selecionar tudo"
1108
+ },
1109
+ wizard: { back: "\u041D\u0430\u0437\u0430\u0434", next: "\u0414\u0430\u043B\u0435\u0435", finish: "\u0413\u043E\u0442\u043E\u0432\u043E" },
1110
+ 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" },
1111
+ richEditor: { placeholder: "Escreva algo\u2026", editorLabel: "Editor de texto rico" },
1112
+ copy: { label: "Copiar" },
1113
+ emojiPicker: { searchPlaceholder: "Pesquisar emoji", emptyText: "Nenhum emoji encontrado", addReaction: "Adicionar rea\xE7\xE3o" },
1114
+ sidebar: { searchPlaceholder: "Pesquisar", primary: "Navega\xE7\xE3o principal" },
1115
+ imageViewer: { reset: "Redefinir", download: "Baixar" }
1029
1116
  };
1030
1117
  var ruRU = {
1031
1118
  locale: "ru-RU",
@@ -1049,13 +1136,15 @@ var ruRU = {
1049
1136
  },
1050
1137
  timePicker: { am: "AM", pm: "PM" },
1051
1138
  pagination: { previous: "\u041D\u0430\u0437\u0430\u0434", next: "\u0412\u043F\u0435\u0440\u0451\u0434" },
1052
- modal: { close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1139
+ 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" },
1140
+ select: { placeholder: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C" },
1141
+ counterInput: { decrease: "\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u0442\u044C", increase: "\u0423\u0432\u0435\u043B\u0438\u0447\u0438\u0442\u044C" },
1053
1142
  drawer: { close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1054
1143
  alert: { dismiss: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1055
1144
  banner: { dismiss: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1056
1145
  toast: { dismiss: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" },
1057
1146
  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" },
1058
- 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" },
1147
+ 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" },
1059
1148
  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" },
1060
1149
  commandMenu: {
1061
1150
  placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043A\u043E\u043C\u0430\u043D\u0434\u0443 \u0438\u043B\u0438 \u043F\u043E\u0438\u0441\u043A\u2026",
@@ -1118,8 +1207,17 @@ var ruRU = {
1118
1207
  previous: "\u041D\u0430\u0437\u0430\u0434",
1119
1208
  next: "\u0412\u043F\u0435\u0440\u0451\u0434",
1120
1209
  pageRange: "{from}\u2013{to} \u0438\u0437 {total}",
1121
- perPage: "{size} / \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430"
1122
- }
1210
+ perPage: "{size} / \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
1211
+ selectRow: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0441\u0442\u0440\u043E\u043A\u0443",
1212
+ selectAll: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u0441\u0435"
1213
+ },
1214
+ wizard: { back: "\u0631\u062C\u0648\u0639", next: "\u0627\u0644\u062A\u0627\u0644\u064A", finish: "\u0625\u0646\u0647\u0627\u0621" },
1215
+ 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" },
1216
+ 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" },
1217
+ copy: { label: "\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C" },
1218
+ 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" },
1219
+ 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" },
1220
+ imageViewer: { reset: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C", download: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C" }
1123
1221
  };
1124
1222
  var arSA = {
1125
1223
  locale: "ar-SA",
@@ -1143,13 +1241,15 @@ var arSA = {
1143
1241
  },
1144
1242
  timePicker: { am: "\u0635", pm: "\u0645" },
1145
1243
  pagination: { previous: "\u0627\u0644\u0633\u0627\u0628\u0642", next: "\u0627\u0644\u062A\u0627\u0644\u064A" },
1146
- modal: { close: "\u0625\u063A\u0644\u0627\u0642" },
1244
+ modal: { close: "\u0625\u063A\u0644\u0627\u0642", maximize: "\u062A\u0643\u0628\u064A\u0631", restore: "\u0627\u0633\u062A\u0639\u0627\u062F\u0629" },
1245
+ select: { placeholder: "\u062A\u062D\u062F\u064A\u062F" },
1246
+ counterInput: { decrease: "\u062A\u0642\u0644\u064A\u0644", increase: "\u0632\u064A\u0627\u062F\u0629" },
1147
1247
  drawer: { close: "\u0625\u063A\u0644\u0627\u0642" },
1148
1248
  alert: { dismiss: "\u0625\u063A\u0644\u0627\u0642" },
1149
1249
  banner: { dismiss: "\u0625\u063A\u0644\u0627\u0642" },
1150
1250
  toast: { dismiss: "\u0625\u063A\u0644\u0627\u0642" },
1151
1251
  fileUpload: { clickToUpload: "\u0627\u0646\u0642\u0631 \u0644\u0644\u0631\u0641\u0639", orDragAndDrop: "\u0623\u0648 \u0627\u0633\u062D\u0628 \u0648\u0623\u0641\u0644\u062A" },
1152
- imageUpload: { label: "\u0631\u0641\u0639 \u0635\u0648\u0631\u0629", remove: "\u0625\u0632\u0627\u0644\u0629" },
1252
+ 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" },
1153
1253
  passwordStrength: { weak: "\u0636\u0639\u064A\u0641", fair: "\u0645\u0642\u0628\u0648\u0644", good: "\u062C\u064A\u062F", strong: "\u0642\u0648\u064A" },
1154
1254
  commandMenu: {
1155
1255
  placeholder: "\u0627\u0643\u062A\u0628 \u0623\u0645\u0631\u064B\u0627 \u0623\u0648 \u0627\u0628\u062D\u062B\u2026",
@@ -1212,8 +1312,17 @@ var arSA = {
1212
1312
  previous: "\u0627\u0644\u0633\u0627\u0628\u0642",
1213
1313
  next: "\u0627\u0644\u062A\u0627\u0644\u064A",
1214
1314
  pageRange: "{from}\u2013{to} \u0645\u0646 {total}",
1215
- perPage: "{size} / \u0635\u0641\u062D\u0629"
1216
- }
1315
+ perPage: "{size} / \u0635\u0641\u062D\u0629",
1316
+ selectRow: "\u062A\u062D\u062F\u064A\u062F \u0627\u0644\u0635\u0641",
1317
+ selectAll: "\u062A\u062D\u062F\u064A\u062F \u0627\u0644\u0643\u0644"
1318
+ },
1319
+ wizard: { back: "Indietro", next: "Avanti", finish: "Fine" },
1320
+ 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" },
1321
+ richEditor: { placeholder: "\u0627\u0643\u062A\u0628 \u0634\u064A\u0626\u064B\u0627\u2026", editorLabel: "\u0645\u062D\u0631\u0631 \u0646\u0635 \u0645\u0646\u0633\u0642" },
1322
+ copy: { label: "\u0646\u0633\u062E" },
1323
+ 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" },
1324
+ sidebar: { searchPlaceholder: "\u0628\u062D\u062B", primary: "\u0627\u0644\u062A\u0646\u0642\u0644 \u0627\u0644\u0631\u0626\u064A\u0633\u064A" },
1325
+ imageViewer: { reset: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646", download: "\u062A\u0646\u0632\u064A\u0644" }
1217
1326
  };
1218
1327
  var itIT = {
1219
1328
  locale: "it-IT",
@@ -1237,13 +1346,15 @@ var itIT = {
1237
1346
  },
1238
1347
  timePicker: { am: "AM", pm: "PM" },
1239
1348
  pagination: { previous: "Precedente", next: "Successivo" },
1240
- modal: { close: "Chiudi" },
1349
+ modal: { close: "Chiudi", maximize: "Ingrandisci", restore: "Ripristina" },
1350
+ select: { placeholder: "Seleziona" },
1351
+ counterInput: { decrease: "Diminuisci", increase: "Aumenta" },
1241
1352
  drawer: { close: "Chiudi" },
1242
1353
  alert: { dismiss: "Chiudi" },
1243
1354
  banner: { dismiss: "Chiudi" },
1244
1355
  toast: { dismiss: "Chiudi" },
1245
1356
  fileUpload: { clickToUpload: "Clicca per caricare", orDragAndDrop: "o trascina qui" },
1246
- imageUpload: { label: "Carica immagine", remove: "Rimuovi" },
1357
+ imageUpload: { label: "Carica immagine", remove: "Rimuovi", hint: "PNG o JPG, fino a 5 MB" },
1247
1358
  passwordStrength: { weak: "Debole", fair: "Discreta", good: "Buona", strong: "Forte" },
1248
1359
  commandMenu: {
1249
1360
  placeholder: "Digita un comando o cerca\u2026",
@@ -1306,8 +1417,17 @@ var itIT = {
1306
1417
  previous: "Precedente",
1307
1418
  next: "Successivo",
1308
1419
  pageRange: "{from}\u2013{to} di {total}",
1309
- perPage: "{size} / pagina"
1310
- }
1420
+ perPage: "{size} / pagina",
1421
+ selectRow: "Seleziona riga",
1422
+ selectAll: "Seleziona tutto"
1423
+ },
1424
+ wizard: { back: "Terug", next: "Volgende", finish: "Voltooien" },
1425
+ a11y: { zoomIn: "Ingrandisci", zoomOut: "Riduci", rotate: "Ruota", collapseStart: "Comprimi pannello iniziale", collapseEnd: "Comprimi pannello finale", bulkActions: "Azioni multiple", clearSelection: "Cancella selezione", back: "Indietro" },
1426
+ richEditor: { placeholder: "Scrivi qualcosa\u2026", editorLabel: "Editor di testo formattato" },
1427
+ copy: { label: "Copia" },
1428
+ emojiPicker: { searchPlaceholder: "Cerca emoji", emptyText: "Nessun emoji trovato", addReaction: "Aggiungi reazione" },
1429
+ sidebar: { searchPlaceholder: "Cerca", primary: "Navigazione principale" },
1430
+ imageViewer: { reset: "Reimposta", download: "Scarica" }
1311
1431
  };
1312
1432
  var nlNL = {
1313
1433
  locale: "nl-NL",
@@ -1331,13 +1451,15 @@ var nlNL = {
1331
1451
  },
1332
1452
  timePicker: { am: "AM", pm: "PM" },
1333
1453
  pagination: { previous: "Vorige", next: "Volgende" },
1334
- modal: { close: "Sluiten" },
1454
+ modal: { close: "Sluiten", maximize: "maximaliseren", restore: "Herstellen" },
1455
+ select: { placeholder: "Selecteren" },
1456
+ counterInput: { decrease: "Verlagen", increase: "Verhogen" },
1335
1457
  drawer: { close: "Sluiten" },
1336
1458
  alert: { dismiss: "Sluiten" },
1337
1459
  banner: { dismiss: "Sluiten" },
1338
1460
  toast: { dismiss: "Sluiten" },
1339
1461
  fileUpload: { clickToUpload: "Klik om te uploaden", orDragAndDrop: "of sleep hierheen" },
1340
- imageUpload: { label: "Afbeelding uploaden", remove: "Verwijderen" },
1462
+ imageUpload: { label: "Afbeelding uploaden", remove: "Verwijderen", hint: "PNG of JPG, max. 5 MB" },
1341
1463
  passwordStrength: { weak: "Zwak", fair: "Redelijk", good: "Goed", strong: "Sterk" },
1342
1464
  commandMenu: {
1343
1465
  placeholder: "Typ een opdracht of zoek\u2026",
@@ -1400,8 +1522,17 @@ var nlNL = {
1400
1522
  previous: "Vorige",
1401
1523
  next: "Volgende",
1402
1524
  pageRange: "{from}\u2013{to} van {total}",
1403
- perPage: "{size} / pagina"
1404
- }
1525
+ perPage: "{size} / pagina",
1526
+ selectRow: "Rij selecteren",
1527
+ selectAll: "Alles selecteren"
1528
+ },
1529
+ wizard: { back: "Wstecz", next: "Dalej", finish: "Zako\u0144cz" },
1530
+ a11y: { zoomIn: "Inzoomen", zoomOut: "Uitzoomen", rotate: "Roteren", collapseStart: "Startpaneel samenvouwen", collapseEnd: "Eindpaneel samenvouwen", bulkActions: "Bulkacties", clearSelection: "Selectie wissen", back: "Terug" },
1531
+ richEditor: { placeholder: "Schrijf iets\u2026", editorLabel: "Rich text-editor" },
1532
+ copy: { label: "Kopi\xEBren" },
1533
+ emojiPicker: { searchPlaceholder: "Emoji zoeken", emptyText: "Geen emoji gevonden", addReaction: "Reactie toevoegen" },
1534
+ sidebar: { searchPlaceholder: "Zoeken", primary: "Hoofdnavigatie" },
1535
+ imageViewer: { reset: "Herstellen", download: "Downloaden" }
1405
1536
  };
1406
1537
  var plPL = {
1407
1538
  locale: "pl-PL",
@@ -1425,13 +1556,15 @@ var plPL = {
1425
1556
  },
1426
1557
  timePicker: { am: "AM", pm: "PM" },
1427
1558
  pagination: { previous: "Poprzednia", next: "Nast\u0119pna" },
1428
- modal: { close: "Zamknij" },
1559
+ modal: { close: "Zamknij", maximize: "Maksymalizuj", restore: "Przywr\xF3\u0107" },
1560
+ select: { placeholder: "Wybierz" },
1561
+ counterInput: { decrease: "Zmniejsz", increase: "Zwi\u0119ksz" },
1429
1562
  drawer: { close: "Zamknij" },
1430
1563
  alert: { dismiss: "Zamknij" },
1431
1564
  banner: { dismiss: "Zamknij" },
1432
1565
  toast: { dismiss: "Zamknij" },
1433
1566
  fileUpload: { clickToUpload: "Kliknij, aby przes\u0142a\u0107", orDragAndDrop: "lub przeci\u0105gnij i upu\u015B\u0107" },
1434
- imageUpload: { label: "Prze\u015Blij obraz", remove: "Usu\u0144" },
1567
+ imageUpload: { label: "Prze\u015Blij obraz", remove: "Usu\u0144", hint: "PNG lub JPG, do 5 MB" },
1435
1568
  passwordStrength: { weak: "S\u0142abe", fair: "\u015Arednie", good: "Dobre", strong: "Silne" },
1436
1569
  commandMenu: {
1437
1570
  placeholder: "Wpisz polecenie lub szukaj\u2026",
@@ -1494,8 +1627,17 @@ var plPL = {
1494
1627
  previous: "Poprzednia",
1495
1628
  next: "Nast\u0119pna",
1496
1629
  pageRange: "{from}\u2013{to} z {total}",
1497
- perPage: "{size} / strona"
1498
- }
1630
+ perPage: "{size} / strona",
1631
+ selectRow: "Zaznacz wiersz",
1632
+ selectAll: "Zaznacz wszystko"
1633
+ },
1634
+ wizard: { back: "Geri", next: "\u0130leri", finish: "Bitir" },
1635
+ 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" },
1636
+ richEditor: { placeholder: "Wpisz co\u015B\u2026", editorLabel: "Edytor tekstu sformatowanego" },
1637
+ copy: { label: "Kopiuj" },
1638
+ emojiPicker: { searchPlaceholder: "Szukaj emoji", emptyText: "Nie znaleziono emoji", addReaction: "Dodaj reakcj\u0119" },
1639
+ sidebar: { searchPlaceholder: "Szukaj", primary: "Nawigacja g\u0142\xF3wna" },
1640
+ imageViewer: { reset: "Resetuj", download: "Pobierz" }
1499
1641
  };
1500
1642
  var trTR = {
1501
1643
  locale: "tr-TR",
@@ -1519,13 +1661,15 @@ var trTR = {
1519
1661
  },
1520
1662
  timePicker: { am: "\xD6\xD6", pm: "\xD6S" },
1521
1663
  pagination: { previous: "\xD6nceki", next: "Sonraki" },
1522
- modal: { close: "Kapat" },
1664
+ modal: { close: "Kapat", maximize: "Ekran\u0131 kapla", restore: "Geri y\xFCkle" },
1665
+ select: { placeholder: "Se\xE7" },
1666
+ counterInput: { decrease: "Azalt", increase: "Art\u0131r" },
1523
1667
  drawer: { close: "Kapat" },
1524
1668
  alert: { dismiss: "Kapat" },
1525
1669
  banner: { dismiss: "Kapat" },
1526
1670
  toast: { dismiss: "Kapat" },
1527
1671
  fileUpload: { clickToUpload: "Y\xFCklemek i\xE7in t\u0131klay\u0131n", orDragAndDrop: "veya s\xFCr\xFCkleyip b\u0131rak\u0131n" },
1528
- imageUpload: { label: "G\xF6rsel y\xFCkle", remove: "Kald\u0131r" },
1672
+ imageUpload: { label: "G\xF6rsel y\xFCkle", remove: "Kald\u0131r", hint: "PNG veya JPG, en fazla 5 MB" },
1529
1673
  passwordStrength: { weak: "Zay\u0131f", fair: "Orta", good: "\u0130yi", strong: "G\xFC\xE7l\xFC" },
1530
1674
  commandMenu: {
1531
1675
  placeholder: "Bir komut yaz\u0131n veya aray\u0131n\u2026",
@@ -1588,8 +1732,17 @@ var trTR = {
1588
1732
  previous: "\xD6nceki",
1589
1733
  next: "Sonraki",
1590
1734
  pageRange: "{total} \xF6\u011Feden {from}\u2013{to}",
1591
- perPage: "{size} / sayfa"
1592
- }
1735
+ perPage: "{size} / sayfa",
1736
+ selectRow: "Sat\u0131r\u0131 se\xE7",
1737
+ selectAll: "T\xFCm\xFCn\xFC se\xE7"
1738
+ },
1739
+ wizard: { back: "Quay l\u1EA1i", next: "Ti\u1EBFp theo", finish: "Ho\xE0n t\u1EA5t" },
1740
+ 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" },
1741
+ richEditor: { placeholder: "Bir \u015Feyler yaz\u0131n\u2026", editorLabel: "Zengin metin d\xFCzenleyici" },
1742
+ copy: { label: "Kopyala" },
1743
+ emojiPicker: { searchPlaceholder: "Emoji ara", emptyText: "Emoji bulunamad\u0131", addReaction: "Tepki ekle" },
1744
+ sidebar: { searchPlaceholder: "Ara", primary: "Ana gezinme" },
1745
+ imageViewer: { reset: "S\u0131f\u0131rla", download: "\u0130ndir" }
1593
1746
  };
1594
1747
  var viVN = {
1595
1748
  locale: "vi-VN",
@@ -1613,13 +1766,15 @@ var viVN = {
1613
1766
  },
1614
1767
  timePicker: { am: "SA", pm: "CH" },
1615
1768
  pagination: { previous: "Tr\u01B0\u1EDBc", next: "Sau" },
1616
- modal: { close: "\u0110\xF3ng" },
1769
+ modal: { close: "\u0110\xF3ng", maximize: "Ph\xF3ng to", restore: "Kh\xF4i ph\u1EE5c" },
1770
+ select: { placeholder: "Ch\u1ECDn" },
1771
+ counterInput: { decrease: "Gi\u1EA3m", increase: "T\u0103ng" },
1617
1772
  drawer: { close: "\u0110\xF3ng" },
1618
1773
  alert: { dismiss: "\u0110\xF3ng" },
1619
1774
  banner: { dismiss: "\u0110\xF3ng" },
1620
1775
  toast: { dismiss: "\u0110\xF3ng" },
1621
1776
  fileUpload: { clickToUpload: "Nh\u1EA5p \u0111\u1EC3 t\u1EA3i l\xEAn", orDragAndDrop: "ho\u1EB7c k\xE9o v\xE0 th\u1EA3" },
1622
- imageUpload: { label: "T\u1EA3i \u1EA3nh l\xEAn", remove: "X\xF3a" },
1777
+ imageUpload: { label: "T\u1EA3i \u1EA3nh l\xEAn", remove: "X\xF3a", hint: "PNG ho\u1EB7c JPG, t\u1ED1i \u0111a 5MB" },
1623
1778
  passwordStrength: { weak: "Y\u1EBFu", fair: "Trung b\xECnh", good: "T\u1ED1t", strong: "M\u1EA1nh" },
1624
1779
  commandMenu: {
1625
1780
  placeholder: "Nh\u1EADp l\u1EC7nh ho\u1EB7c t\xECm ki\u1EBFm\u2026",
@@ -1682,8 +1837,17 @@ var viVN = {
1682
1837
  previous: "Tr\u01B0\u1EDBc",
1683
1838
  next: "Sau",
1684
1839
  pageRange: "{from}\u2013{to} trong {total}",
1685
- perPage: "{size} / trang"
1686
- }
1840
+ perPage: "{size} / trang",
1841
+ selectRow: "Ch\u1ECDn h\xE0ng",
1842
+ selectAll: "Ch\u1ECDn t\u1EA5t c\u1EA3"
1843
+ },
1844
+ wizard: { back: "Kembali", next: "Berikutnya", finish: "Selesai" },
1845
+ 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" },
1846
+ richEditor: { placeholder: "Vi\u1EBFt n\u1ED9i dung\u2026", editorLabel: "Tr\xECnh so\u1EA1n th\u1EA3o v\u0103n b\u1EA3n" },
1847
+ copy: { label: "Sao ch\xE9p" },
1848
+ emojiPicker: { searchPlaceholder: "T\xECm emoji", emptyText: "Kh\xF4ng t\xECm th\u1EA5y emoji", addReaction: "Th\xEAm c\u1EA3m x\xFAc" },
1849
+ sidebar: { searchPlaceholder: "T\xECm ki\u1EBFm", primary: "\u0110i\u1EC1u h\u01B0\u1EDBng ch\xEDnh" },
1850
+ imageViewer: { reset: "\u0110\u1EB7t l\u1EA1i", download: "T\u1EA3i xu\u1ED1ng" }
1687
1851
  };
1688
1852
  var idID = {
1689
1853
  locale: "id-ID",
@@ -1707,13 +1871,15 @@ var idID = {
1707
1871
  },
1708
1872
  timePicker: { am: "AM", pm: "PM" },
1709
1873
  pagination: { previous: "Sebelumnya", next: "Berikutnya" },
1710
- modal: { close: "Tutup" },
1874
+ modal: { close: "Tutup", maximize: "Maksimalkan", restore: "Pulihkan" },
1875
+ select: { placeholder: "Pilih" },
1876
+ counterInput: { decrease: "Kurangi", increase: "Tambah" },
1711
1877
  drawer: { close: "Tutup" },
1712
1878
  alert: { dismiss: "Tutup" },
1713
1879
  banner: { dismiss: "Tutup" },
1714
1880
  toast: { dismiss: "Tutup" },
1715
1881
  fileUpload: { clickToUpload: "Klik untuk mengunggah", orDragAndDrop: "atau seret dan lepas" },
1716
- imageUpload: { label: "Unggah gambar", remove: "Hapus" },
1882
+ imageUpload: { label: "Unggah gambar", remove: "Hapus", hint: "PNG atau JPG, maks. 5 MB" },
1717
1883
  passwordStrength: { weak: "Lemah", fair: "Cukup", good: "Baik", strong: "Kuat" },
1718
1884
  commandMenu: {
1719
1885
  placeholder: "Ketik perintah atau cari\u2026",
@@ -1776,8 +1942,17 @@ var idID = {
1776
1942
  previous: "Sebelumnya",
1777
1943
  next: "Berikutnya",
1778
1944
  pageRange: "{from}\u2013{to} dari {total}",
1779
- perPage: "{size} / halaman"
1780
- }
1945
+ perPage: "{size} / halaman",
1946
+ selectRow: "Pilih baris",
1947
+ selectAll: "Pilih semua"
1948
+ },
1949
+ wizard: { back: "Kembali", next: "Berikutnya", finish: "Selesai" },
1950
+ a11y: { zoomIn: "Perbesar", zoomOut: "Perkecil", rotate: "Putar", collapseStart: "Ciutkan panel awal", collapseEnd: "Ciutkan panel akhir", bulkActions: "Tindakan massal", clearSelection: "Hapus pilihan", back: "Kembali" },
1951
+ richEditor: { placeholder: "Tulis sesuatu\u2026", editorLabel: "Editor teks kaya" },
1952
+ copy: { label: "Salin" },
1953
+ emojiPicker: { searchPlaceholder: "Cari emoji", emptyText: "Emoji tidak ditemukan", addReaction: "Tambahkan reaksi" },
1954
+ sidebar: { searchPlaceholder: "Cari", primary: "Navigasi utama" },
1955
+ imageViewer: { reset: "Setel ulang", download: "Unduh" }
1781
1956
  };
1782
1957
  var locales = {
1783
1958
  enUS,
@@ -1873,6 +2048,7 @@ function ConfigProvider({
1873
2048
  {
1874
2049
  className: "klun-config",
1875
2050
  dir: value.dir,
2051
+ lang: (value.locale ?? enUS).locale,
1876
2052
  "data-theme": value.theme,
1877
2053
  "data-mode": value.accent,
1878
2054
  "data-radius": value.radius && value.radius !== "default" ? value.radius : void 0,
@@ -1953,15 +2129,14 @@ var Button = forwardRef(function Button2(props, ref) {
1953
2129
  size: _s2,
1954
2130
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1955
2131
  loading: _l2,
1956
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1957
- type: _t,
2132
+ type: type2 = "button",
1958
2133
  ...rest2
1959
2134
  } = props;
1960
2135
  return /* @__PURE__ */ jsxs(
1961
2136
  "button",
1962
2137
  {
1963
2138
  ref,
1964
- type: "button",
2139
+ type: type2,
1965
2140
  disabled: disabled2 || loading,
1966
2141
  "aria-busy": loading || void 0,
1967
2142
  className: cx(
@@ -2018,7 +2193,7 @@ var Button = forwardRef(function Button2(props, ref) {
2018
2193
  ...rest2,
2019
2194
  children: [
2020
2195
  loading ? /* @__PURE__ */ jsx("span", { className: "klun-compact-button__icon", children: /* @__PURE__ */ jsx(Spinner, { className: "klun-compact-button__spinner" }) }) : icon2 ? /* @__PURE__ */ jsx("span", { className: "klun-compact-button__icon", children: icon2 }) : null,
2021
- loading ? null : children2
2196
+ loading ? children2 != null ? /* @__PURE__ */ jsx("span", { className: "klun-compact-button__label-sr", children: children2 }) : null : children2
2022
2197
  ]
2023
2198
  }
2024
2199
  );
@@ -2200,11 +2375,13 @@ var CopyButton = forwardRef(
2200
2375
  variant = "ghost",
2201
2376
  copyIcon = "ri-file-copy-line",
2202
2377
  doneIcon = "ri-check-line",
2203
- title = "Copy",
2378
+ title: titleProp,
2204
2379
  onClick,
2205
2380
  className,
2206
2381
  ...props
2207
2382
  }, ref) {
2383
+ const { copy: localeCopy } = useLocale();
2384
+ const title = titleProp ?? localeCopy.label;
2208
2385
  const [done, setDone] = useState(false);
2209
2386
  const timer = useRef(null);
2210
2387
  useEffect(() => () => clearTimeout(timer.current ?? void 0), []);
@@ -2581,6 +2758,7 @@ var BulkActionBar = forwardRef(
2581
2758
  className,
2582
2759
  ...props
2583
2760
  }, ref) {
2761
+ const { a11y } = useLocale();
2584
2762
  const visible = open != null ? open : count > 0;
2585
2763
  const [mounted, setMounted] = useState(visible);
2586
2764
  const [show, setShow] = useState(visible);
@@ -2601,7 +2779,7 @@ var BulkActionBar = forwardRef(
2601
2779
  {
2602
2780
  ref,
2603
2781
  role: "toolbar",
2604
- "aria-label": "Bulk actions",
2782
+ "aria-label": a11y.bulkActions,
2605
2783
  "data-show": show ? "" : void 0,
2606
2784
  className: cx(
2607
2785
  "klun-bulk-action-bar",
@@ -2622,8 +2800,8 @@ var BulkActionBar = forwardRef(
2622
2800
  {
2623
2801
  type: "button",
2624
2802
  onClick: onClear,
2625
- "aria-label": "Clear selection",
2626
- title: "Clear selection",
2803
+ "aria-label": a11y.clearSelection,
2804
+ title: a11y.clearSelection,
2627
2805
  className: "klun-bulk-action-bar__clear",
2628
2806
  children: /* @__PURE__ */ jsx("i", { className: "ri-close-line", "aria-hidden": true })
2629
2807
  }
@@ -2667,6 +2845,16 @@ var Carousel = forwardRef(function Carousel2({
2667
2845
  const { carousel } = useLocale();
2668
2846
  const slides = Children.toArray(children);
2669
2847
  const count = slides.length;
2848
+ const rootRef = useRef(null);
2849
+ const hadFocusInside = useRef(false);
2850
+ const attachRootRef = useCallback(
2851
+ (el) => {
2852
+ rootRef.current = el;
2853
+ if (typeof ref === "function") ref(el);
2854
+ else if (ref) ref.current = el;
2855
+ },
2856
+ [ref]
2857
+ );
2670
2858
  const [inner, setInner] = useState(defaultIndex);
2671
2859
  const cur = index !== void 0 ? index : inner;
2672
2860
  const [hover, setHover] = useState(false);
@@ -2685,6 +2873,12 @@ var Carousel = forwardRef(function Carousel2({
2685
2873
  const id = setInterval(() => go(cur + 1), interval);
2686
2874
  return () => clearInterval(id);
2687
2875
  }, [autoplay, hover, cur, interval, count, go]);
2876
+ useEffect(() => {
2877
+ const root = rootRef.current;
2878
+ if (!root || !hadFocusInside.current) return;
2879
+ const active = document.activeElement;
2880
+ if (active && !root.contains(active)) root.focus();
2881
+ }, [cur]);
2688
2882
  const arrowBtn = (dir) => /* @__PURE__ */ jsx(
2689
2883
  "button",
2690
2884
  {
@@ -2698,11 +2892,20 @@ var Carousel = forwardRef(function Carousel2({
2698
2892
  return /* @__PURE__ */ jsxs(
2699
2893
  "div",
2700
2894
  {
2701
- ref,
2895
+ ref: attachRootRef,
2702
2896
  onMouseEnter: () => setHover(true),
2703
2897
  onMouseLeave: () => setHover(false),
2898
+ onFocus: () => {
2899
+ hadFocusInside.current = true;
2900
+ },
2901
+ onBlur: (e) => {
2902
+ if (e.relatedTarget) {
2903
+ hadFocusInside.current = rootRef.current?.contains(e.relatedTarget) ?? false;
2904
+ }
2905
+ },
2704
2906
  className: cx("klun-carousel", className),
2705
2907
  style: { height, ...style },
2908
+ tabIndex: -1,
2706
2909
  ...props,
2707
2910
  children: [
2708
2911
  /* @__PURE__ */ jsx(
@@ -2710,7 +2913,20 @@ var Carousel = forwardRef(function Carousel2({
2710
2913
  {
2711
2914
  className: "klun-carousel__track",
2712
2915
  style: { transform: `translateX(-${cur * 100}%)` },
2713
- children: slides.map((s, i) => /* @__PURE__ */ jsx("div", { className: "klun-carousel__slide", children: s }, i))
2916
+ children: slides.map((s, i) => {
2917
+ const active = i === cur;
2918
+ return /* @__PURE__ */ jsx(
2919
+ "div",
2920
+ {
2921
+ className: "klun-carousel__slide",
2922
+ "data-active": active || void 0,
2923
+ ...!active ? { inert: "" } : {},
2924
+ "aria-hidden": !active || void 0,
2925
+ children: s
2926
+ },
2927
+ i
2928
+ );
2929
+ })
2714
2930
  }
2715
2931
  ),
2716
2932
  arrows && count > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -3109,7 +3325,9 @@ function useTick(ms) {
3109
3325
  return () => clearInterval(id);
3110
3326
  }, [ms]);
3111
3327
  }
3112
- var RelativeTime = forwardRef(function RelativeTime2({ date, locale, live = true, every = 6e4, absolute, className, ...props }, ref) {
3328
+ var RelativeTime = forwardRef(function RelativeTime2({ date, locale: localeProp, live = true, every = 6e4, absolute, className, ...props }, ref) {
3329
+ const { locale: ctxLocaleName } = useLocale();
3330
+ const locale = localeProp ?? ctxLocaleName;
3113
3331
  useTick(live ? every : 0);
3114
3332
  const rel = Format.relTime(date, { locale });
3115
3333
  const title = Format.absTime(date, { locale });
@@ -3889,7 +4107,7 @@ function KanbanCardView({
3889
4107
  dropAfter && "klun-kanban__card--dropafter"
3890
4108
  ),
3891
4109
  style: {
3892
- transform: CSS.Transform.toString(transform),
4110
+ transform: CSS$1.Transform.toString(transform),
3893
4111
  transition,
3894
4112
  ...card.accent ? { boxShadow: `inset 3px 0 0 ${card.accent}` } : null
3895
4113
  },
@@ -4323,7 +4541,7 @@ var Money = forwardRef(function Money2({
4323
4541
  value,
4324
4542
  cents = false,
4325
4543
  currency = "USD",
4326
- locale,
4544
+ locale: localeProp,
4327
4545
  period,
4328
4546
  periodLabels,
4329
4547
  minimumFractionDigits,
@@ -4337,6 +4555,8 @@ var Money = forwardRef(function Money2({
4337
4555
  className,
4338
4556
  ...props
4339
4557
  }, ref) {
4558
+ const { locale: ctxLocaleName } = useLocale();
4559
+ const locale = localeProp ?? ctxLocaleName;
4340
4560
  const { text, period: periodSuffix } = Format.money(value, {
4341
4561
  currency,
4342
4562
  cents,
@@ -4384,7 +4604,9 @@ function Digit({ value }) {
4384
4604
  ) });
4385
4605
  }
4386
4606
  var NumberFlow = forwardRef(
4387
- function NumberFlow2({ value, locales: locales2, format, prefix, suffix, label, className, ...props }, ref) {
4607
+ function NumberFlow2({ value, locales: localesProp, format, prefix, suffix, label, className, ...props }, ref) {
4608
+ const { locale: ctxLocaleName } = useLocale();
4609
+ const locales2 = localesProp ?? ctxLocaleName;
4388
4610
  const text = new Intl.NumberFormat(locales2, {
4389
4611
  minimumFractionDigits: format?.minimumFractionDigits,
4390
4612
  maximumFractionDigits: format?.maximumFractionDigits,
@@ -4519,14 +4741,66 @@ var Rating = forwardRef(function Rating2({ value = 0, max = 5, onChange, readOnl
4519
4741
  )) });
4520
4742
  });
4521
4743
  Rating.displayName = "Rating";
4522
- var Popover = forwardRef(function Popover2({ trigger, children, align = "left", width = 280, className, ...props }, ref) {
4523
- const [open, setOpen] = useState(false);
4744
+ var FOCUSABLE = [
4745
+ "a[href]",
4746
+ "button:not([disabled])",
4747
+ "input:not([disabled]):not([type='hidden'])",
4748
+ "select:not([disabled])",
4749
+ "textarea:not([disabled])",
4750
+ "[tabindex]:not([tabindex='-1'])"
4751
+ ].join(",");
4752
+ var ACTIVATABLE = [
4753
+ "button",
4754
+ "a[href]",
4755
+ "input[type='button']",
4756
+ "input[type='submit']",
4757
+ "input[type='reset']",
4758
+ "input[type='checkbox']",
4759
+ "input[type='radio']",
4760
+ "summary",
4761
+ "[role='button']",
4762
+ "[role='link']"
4763
+ ].join(",");
4764
+ var Popover = forwardRef(function Popover2({
4765
+ trigger,
4766
+ children,
4767
+ align = "start",
4768
+ width = 280,
4769
+ className,
4770
+ open,
4771
+ defaultOpen = false,
4772
+ onOpenChange,
4773
+ panelId,
4774
+ ...props
4775
+ }, ref) {
4776
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
4777
+ const controlled = open !== void 0;
4778
+ const isOpen = controlled ? Boolean(open) : internalOpen;
4779
+ const onOpenChangeRef = useRef(onOpenChange);
4780
+ onOpenChangeRef.current = onOpenChange;
4781
+ const setOpen = useCallback(
4782
+ (next) => {
4783
+ if (!controlled) setInternalOpen(next);
4784
+ onOpenChangeRef.current?.(next);
4785
+ },
4786
+ [controlled]
4787
+ );
4524
4788
  const wrapRef = useRef(null);
4789
+ const triggerRef = useRef(null);
4525
4790
  const panelRef = useRef(null);
4526
4791
  const portal = typeof document !== "undefined";
4527
4792
  const [pos, setPos] = useState(null);
4793
+ const generatedId = useId();
4794
+ const resolvedPanelId = panelId ?? `klun-popover-${generatedId}`;
4795
+ const [hasFocusableChild, setHasFocusableChild] = useState(false);
4528
4796
  useEffect(() => {
4529
- if (!open) return;
4797
+ const root = triggerRef.current;
4798
+ if (!root) return;
4799
+ setHasFocusableChild(root.querySelector(FOCUSABLE) != null);
4800
+ }, [trigger]);
4801
+ const openedByKeyboard = useRef(false);
4802
+ useEffect(() => {
4803
+ if (!isOpen) return;
4530
4804
  const h = (e) => {
4531
4805
  const t = e.target;
4532
4806
  if (wrapRef.current?.contains(t)) return;
@@ -4535,9 +4809,9 @@ var Popover = forwardRef(function Popover2({ trigger, children, align = "left",
4535
4809
  };
4536
4810
  document.addEventListener("mousedown", h);
4537
4811
  return () => document.removeEventListener("mousedown", h);
4538
- }, [open]);
4812
+ }, [isOpen, setOpen]);
4539
4813
  useLayoutEffect(() => {
4540
- if (!open || !portal) return;
4814
+ if (!isOpen || !portal) return;
4541
4815
  const anchor = wrapRef.current;
4542
4816
  const panel2 = panelRef.current;
4543
4817
  if (!anchor || !panel2) return;
@@ -4550,7 +4824,9 @@ var Popover = forwardRef(function Popover2({ trigger, children, align = "left",
4550
4824
  const below = window.innerHeight - a.bottom;
4551
4825
  const openUp = below < ph + gap && a.top > below;
4552
4826
  const top = openUp ? Math.max(margin, a.top - gap - ph) : Math.min(a.bottom + gap, window.innerHeight - margin - ph);
4553
- let left = align === "right" ? a.right - pw : a.left;
4827
+ const rtl = getComputedStyle(anchor).direction === "rtl";
4828
+ const side = align === "start" ? rtl ? "right" : "left" : align === "end" ? rtl ? "left" : "right" : align;
4829
+ let left = side === "right" ? a.right - pw : a.left;
4554
4830
  if (left + pw > window.innerWidth - margin) left = window.innerWidth - margin - pw;
4555
4831
  if (left < margin) left = margin;
4556
4832
  setPos({ left, top });
@@ -4562,10 +4838,58 @@ var Popover = forwardRef(function Popover2({ trigger, children, align = "left",
4562
4838
  window.removeEventListener("scroll", place2, true);
4563
4839
  window.removeEventListener("resize", place2);
4564
4840
  };
4565
- }, [open, portal, align, width]);
4841
+ }, [isOpen, portal, align, width]);
4566
4842
  useEffect(() => {
4567
- if (!open) setPos(null);
4568
- }, [open]);
4843
+ if (!isOpen) setPos(null);
4844
+ }, [isOpen]);
4845
+ useLayoutEffect(() => {
4846
+ if (!isOpen || !openedByKeyboard.current) return;
4847
+ if (!pos) return;
4848
+ openedByKeyboard.current = false;
4849
+ const panel2 = panelRef.current;
4850
+ if (!panel2) return;
4851
+ const first = panel2.querySelector(FOCUSABLE);
4852
+ (first ?? panel2).focus?.();
4853
+ }, [isOpen, pos]);
4854
+ const focusTrigger = useCallback(() => {
4855
+ const root = triggerRef.current;
4856
+ if (!root) return;
4857
+ const inner = root.querySelector(FOCUSABLE);
4858
+ (inner ?? root).focus?.();
4859
+ }, []);
4860
+ const onPanelKeyDown = (e) => {
4861
+ if (e.key !== "Escape") return;
4862
+ e.stopPropagation();
4863
+ setOpen(false);
4864
+ focusTrigger();
4865
+ };
4866
+ const onTriggerKeyDown = (e) => {
4867
+ if (e.key === "Escape") {
4868
+ if (!isOpen) return;
4869
+ e.stopPropagation();
4870
+ setOpen(false);
4871
+ focusTrigger();
4872
+ return;
4873
+ }
4874
+ if (e.key === "ArrowDown") {
4875
+ e.preventDefault();
4876
+ if (!isOpen) {
4877
+ openedByKeyboard.current = true;
4878
+ setOpen(true);
4879
+ }
4880
+ return;
4881
+ }
4882
+ if (e.key === "Enter" || e.key === " ") {
4883
+ const target = e.target;
4884
+ const nativeActivation = target != null && target !== triggerRef.current && target.closest?.(ACTIVATABLE) != null;
4885
+ if (nativeActivation) return;
4886
+ if (!isOpen) {
4887
+ e.preventDefault();
4888
+ openedByKeyboard.current = true;
4889
+ setOpen(true);
4890
+ }
4891
+ }
4892
+ };
4569
4893
  const setRefs = (node) => {
4570
4894
  wrapRef.current = node;
4571
4895
  if (typeof ref === "function") ref(node);
@@ -4581,11 +4905,14 @@ var Popover = forwardRef(function Popover2({ trigger, children, align = "left",
4581
4905
  // keep hidden until measured to avoid a flash at the top-left corner
4582
4906
  visibility: pos ? "visible" : "hidden"
4583
4907
  };
4584
- const panel = open ? /* @__PURE__ */ jsx(
4908
+ const panel = isOpen ? /* @__PURE__ */ jsx(
4585
4909
  "div",
4586
4910
  {
4587
4911
  ref: panelRef,
4912
+ id: resolvedPanelId,
4588
4913
  role: "dialog",
4914
+ tabIndex: -1,
4915
+ onKeyDown: onPanelKeyDown,
4589
4916
  className: cx(
4590
4917
  "klun-popover__panel",
4591
4918
  // in-flow fallback keeps the legacy left/right anchoring classes
@@ -4595,8 +4922,25 @@ var Popover = forwardRef(function Popover2({ trigger, children, align = "left",
4595
4922
  children: content
4596
4923
  }
4597
4924
  ) : null;
4925
+ const triggerAria = {
4926
+ "aria-haspopup": "dialog",
4927
+ "aria-expanded": isOpen,
4928
+ ...isOpen ? { "aria-controls": resolvedPanelId } : null
4929
+ };
4930
+ const triggerNode = isValidElement(trigger) ? cloneElement(trigger, triggerAria) : trigger;
4931
+ const wrapperIsTrigger = !hasFocusableChild;
4598
4932
  return /* @__PURE__ */ jsxs("span", { ref: setRefs, className: cx("klun-popover", className), ...props, children: [
4599
- /* @__PURE__ */ jsx("span", { className: "klun-popover__trigger", onClick: () => setOpen((o) => !o), children: trigger }),
4933
+ /* @__PURE__ */ jsx(
4934
+ "span",
4935
+ {
4936
+ ref: triggerRef,
4937
+ className: "klun-popover__trigger",
4938
+ onClick: () => setOpen(!isOpen),
4939
+ onKeyDown: onTriggerKeyDown,
4940
+ ...wrapperIsTrigger ? { role: "button", tabIndex: 0, ...triggerAria } : !isValidElement(trigger) ? triggerAria : null,
4941
+ children: triggerNode
4942
+ }
4943
+ ),
4600
4944
  portal ? panel && createPortal(panel, document.body) : panel
4601
4945
  ] });
4602
4946
  });
@@ -4959,11 +5303,14 @@ var EmojiPicker = forwardRef(
4959
5303
  groups = EMOJI_GROUPS,
4960
5304
  columns = 8,
4961
5305
  searchable = true,
4962
- searchPlaceholder = "Search emoji",
4963
- emptyText = "No emoji found",
5306
+ searchPlaceholder: searchPlaceholderProp,
5307
+ emptyText: emptyTextProp,
4964
5308
  className,
4965
5309
  ...props
4966
5310
  }, ref) {
5311
+ const { emojiPicker } = useLocale();
5312
+ const searchPlaceholder = searchPlaceholderProp ?? emojiPicker.searchPlaceholder;
5313
+ const emptyText = emptyTextProp ?? emojiPicker.emptyText;
4967
5314
  const [query, setQuery] = useState("");
4968
5315
  const q = query.trim().toLowerCase();
4969
5316
  const results = useMemo(() => {
@@ -5008,7 +5355,9 @@ var EmojiPicker = forwardRef(
5008
5355
  EmojiPicker.displayName = "EmojiPicker";
5009
5356
  var QUICK_EMOJIS = ["\u{1F44D}", "\u{1F44C}", "\u2764\uFE0F", "\u2705", "\u{1F389}", "\u{1F615}", "\u{1F680}", "\u{1F440}"];
5010
5357
  var QuickEmojiPicker = forwardRef(
5011
- function QuickEmojiPicker2({ onSelect, emojis = QUICK_EMOJIS, align = "left", label = "Add reaction", className }, ref) {
5358
+ function QuickEmojiPicker2({ onSelect, emojis = QUICK_EMOJIS, align = "left", label: labelProp, className }, ref) {
5359
+ const { emojiPicker } = useLocale();
5360
+ const label = labelProp ?? emojiPicker.addReaction;
5012
5361
  return /* @__PURE__ */ jsx(
5013
5362
  Popover,
5014
5363
  {
@@ -5153,6 +5502,16 @@ var Tooltip = forwardRef(function Tooltip2({ content, side = "top", delay = 200,
5153
5502
  transform: "none",
5154
5503
  visibility: pos ? "visible" : "hidden"
5155
5504
  };
5505
+ const tooltipId = `${useId()}tooltip`;
5506
+ const describedBy = open && content && !disabled ? tooltipId : void 0;
5507
+ const childProps = isValidElement(children) ? children.props : null;
5508
+ const triggerNode = childProps != null ? cloneElement(
5509
+ children,
5510
+ // 合并而非覆盖调用方已有的 aria-describedby
5511
+ {
5512
+ "aria-describedby": [childProps["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
5513
+ }
5514
+ ) : children;
5156
5515
  return /* @__PURE__ */ jsxs(
5157
5516
  "span",
5158
5517
  {
@@ -5162,13 +5521,15 @@ var Tooltip = forwardRef(function Tooltip2({ content, side = "top", delay = 200,
5162
5521
  onMouseLeave: hide,
5163
5522
  onFocus: show,
5164
5523
  onBlur: hide,
5524
+ ...childProps == null ? { "aria-describedby": describedBy } : null,
5165
5525
  children: [
5166
- children,
5526
+ triggerNode,
5167
5527
  open && content && typeof document !== "undefined" ? createPortal(
5168
5528
  /* @__PURE__ */ jsx(
5169
5529
  "span",
5170
5530
  {
5171
5531
  ref: bubbleRef,
5532
+ id: tooltipId,
5172
5533
  role: "tooltip",
5173
5534
  className: cx("klun-tooltip__bubble", `klun-tooltip__bubble--${side}`),
5174
5535
  style: bubbleStyle,
@@ -5648,7 +6009,7 @@ function TableToolbar({
5648
6009
  selectedRows,
5649
6010
  clearSelection
5650
6011
  }) {
5651
- const { table } = useLocale();
6012
+ const { table, a11y } = useLocale();
5652
6013
  return /* @__PURE__ */ jsxs(Fragment, { children: [
5653
6014
  showToolbar ? /* @__PURE__ */ jsxs("div", { className: "klun-table__toolbar", children: [
5654
6015
  title != null ? /* @__PURE__ */ jsx("span", { className: "klun-table__title", children: title }) : /* @__PURE__ */ jsx("span", { className: "klun-table__title-spacer" }),
@@ -5671,7 +6032,7 @@ function TableToolbar({
5671
6032
  {
5672
6033
  type: "button",
5673
6034
  onClick: clearSelection,
5674
- "aria-label": "Clear selection",
6035
+ "aria-label": a11y.clearSelection,
5675
6036
  className: "klun-table__selbar-clear",
5676
6037
  children: /* @__PURE__ */ jsx("i", { className: "ri-close-line" })
5677
6038
  }
@@ -5849,9 +6210,44 @@ function TableHead({
5849
6210
  setSort,
5850
6211
  activeFilters,
5851
6212
  setFilter,
5852
- startResize
6213
+ startResize,
6214
+ setColumnWidth
5853
6215
  }) {
5854
6216
  const { table } = useLocale();
6217
+ const [resizerW, setResizerW] = useState({});
6218
+ const widthForA11y = (c) => {
6219
+ const w = widthOf(c);
6220
+ if (typeof w === "number") return w;
6221
+ if (typeof c.width === "number") return c.width;
6222
+ return resizerW[c.key] ?? (c.minWidth || 64);
6223
+ };
6224
+ const onResizerKeyDown = (e, c) => {
6225
+ const min = c.minWidth || 64;
6226
+ const step = e.shiftKey ? 32 : 8;
6227
+ const current = resizerW[c.key] ?? widthForA11y(c);
6228
+ let next = null;
6229
+ switch (e.key) {
6230
+ case "ArrowLeft":
6231
+ next = current - step;
6232
+ break;
6233
+ case "ArrowRight":
6234
+ next = current + step;
6235
+ break;
6236
+ case "Home":
6237
+ next = min;
6238
+ break;
6239
+ // 这里没有真正的"最大值"(列宽不受限),因此用 Enter 代表"恢复声明宽度"
6240
+ case "Enter":
6241
+ next = typeof c.width === "number" ? c.width : current;
6242
+ break;
6243
+ default:
6244
+ return;
6245
+ }
6246
+ e.preventDefault();
6247
+ e.stopPropagation();
6248
+ const applied = setColumnWidth(c, next);
6249
+ setResizerW((m) => ({ ...m, [c.key]: applied }));
6250
+ };
5855
6251
  return /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
5856
6252
  dragCol ? /* @__PURE__ */ jsx("th", { className: "klun-table__th klun-table__th--util" }) : null,
5857
6253
  expandCol ? /* @__PURE__ */ jsx(
@@ -5914,8 +6310,21 @@ function TableHead({
5914
6310
  justifyContent: c.align === "right" ? "flex-end" : c.align === "center" ? "center" : "flex-start"
5915
6311
  },
5916
6312
  children: [
5917
- /* @__PURE__ */ jsx("span", { className: c.ellipsis ? "klun-table__ellipsis" : void 0, children: c.headerRender ? c.headerRender() : c.header }),
5918
- isSort ? /* @__PURE__ */ jsx(SortIcon, { dir }) : null,
6313
+ isSort ? /* @__PURE__ */ jsxs(
6314
+ "button",
6315
+ {
6316
+ type: "button",
6317
+ className: "klun-table__sort",
6318
+ onClick: (e) => {
6319
+ e.stopPropagation();
6320
+ setSort(c.key);
6321
+ },
6322
+ children: [
6323
+ /* @__PURE__ */ jsx("span", { className: c.ellipsis ? "klun-table__ellipsis" : void 0, children: c.headerRender ? c.headerRender() : c.header }),
6324
+ /* @__PURE__ */ jsx(SortIcon, { dir })
6325
+ ]
6326
+ }
6327
+ ) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("span", { className: c.ellipsis ? "klun-table__ellipsis" : void 0, children: c.headerRender ? c.headerRender() : c.header }) }),
5919
6328
  hasFilter ? /* @__PURE__ */ jsx(
5920
6329
  FilterMenu,
5921
6330
  {
@@ -5933,7 +6342,19 @@ function TableHead({
5933
6342
  {
5934
6343
  role: "separator",
5935
6344
  "aria-orientation": "vertical",
6345
+ tabIndex: 0,
6346
+ "aria-label": `${table.dragToResize}: ${typeof c.header === "string" ? c.header : c.key}`,
6347
+ "aria-valuemin": c.minWidth || 64,
6348
+ "aria-valuenow": widthForA11y(c),
6349
+ "aria-valuetext": `${widthForA11y(c)}px`,
5936
6350
  title: table.dragToResize,
6351
+ onFocus: (e) => {
6352
+ const th = e.currentTarget.closest("th");
6353
+ if (!th) return;
6354
+ const measured = Math.round(th.getBoundingClientRect().width);
6355
+ if (measured > 0) setResizerW((m) => ({ ...m, [c.key]: measured }));
6356
+ },
6357
+ onKeyDown: (e) => onResizerKeyDown(e, c),
5937
6358
  onMouseDown: (e) => startResize(e, c),
5938
6359
  onClick: (e) => e.stopPropagation(),
5939
6360
  className: "klun-table__resizer",
@@ -5947,6 +6368,14 @@ function TableHead({
5947
6368
  })
5948
6369
  ] }) });
5949
6370
  }
6371
+ function isCoarsePointer() {
6372
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
6373
+ try {
6374
+ return window.matchMedia("(pointer: coarse)").matches;
6375
+ } catch {
6376
+ return false;
6377
+ }
6378
+ }
5950
6379
  function TableRow(props) {
5951
6380
  if (!props.dragCol) return /* @__PURE__ */ jsx(RowBase, { ...props });
5952
6381
  return /* @__PURE__ */ jsx(SortableRow, { ...props });
@@ -5971,7 +6400,7 @@ function SortableRow(props) {
5971
6400
  setNodeRef,
5972
6401
  setActivatorNodeRef,
5973
6402
  isDragging,
5974
- style: { transform: CSS.Transform.toString(transform), transition }
6403
+ style: { transform: CSS$1.Transform.toString(transform), transition }
5975
6404
  }
5976
6405
  }
5977
6406
  );
@@ -6050,7 +6479,15 @@ function RowBase({
6050
6479
  clickable && "klun-table__row--clickable",
6051
6480
  sortable?.isDragging && "klun-table__row--dragging"
6052
6481
  ),
6053
- onClick: clickable ? () => rowHref ? window.location.href = rowHref(row) : onRowClick(row) : void 0,
6482
+ onClick: clickable ? (e) => {
6483
+ if (rowHref) {
6484
+ const target = e.target;
6485
+ if (target?.closest?.("a[href]")) return;
6486
+ window.location.href = rowHref(row);
6487
+ return;
6488
+ }
6489
+ onRowClick?.(row);
6490
+ } : void 0,
6054
6491
  onContextMenu: contextMenu || copyable ? (e) => {
6055
6492
  const custom = contextMenu ? contextMenu(row, { copyRow, copyText }) : null;
6056
6493
  const items2 = custom && custom.length ? custom : [
@@ -6225,6 +6662,8 @@ function RowBase({
6225
6662
  style: { textAlign: c.align || "left" }
6226
6663
  }
6227
6664
  ) : null;
6665
+ const linkHref = rowHref && ci === 0 && !c.render && !c.editable ? rowHref(row) : null;
6666
+ const body = linkHref ? /* @__PURE__ */ jsx("a", { className: "klun-table__rowlink", href: linkHref, children: inner }) : inner;
6228
6667
  return /* @__PURE__ */ jsx(
6229
6668
  "td",
6230
6669
  {
@@ -6232,6 +6671,18 @@ function RowBase({
6232
6671
  e.stopPropagation();
6233
6672
  startEdit(id, c, row);
6234
6673
  } : void 0,
6674
+ onClick: c.editable && !isEditing && isCoarsePointer() ? (e) => {
6675
+ e.stopPropagation();
6676
+ startEdit(id, c, row);
6677
+ } : void 0,
6678
+ tabIndex: c.editable && !isEditing ? 0 : void 0,
6679
+ onKeyDown: c.editable && !isEditing ? (e) => {
6680
+ if (e.key === "Enter" || e.key === "F2") {
6681
+ e.preventDefault();
6682
+ e.stopPropagation();
6683
+ startEdit(id, c, row);
6684
+ }
6685
+ } : void 0,
6235
6686
  className: cx(
6236
6687
  "klun-table__td",
6237
6688
  tdBorder,
@@ -6279,8 +6730,8 @@ function RowBase({
6279
6730
  )
6280
6731
  }
6281
6732
  ) : /* @__PURE__ */ jsx("span", { className: "klun-table__tree-spacer" }),
6282
- inner
6283
- ] }) : inner
6733
+ body
6734
+ ] }) : body
6284
6735
  },
6285
6736
  c.key
6286
6737
  );
@@ -6374,6 +6825,11 @@ function useColumnResize(columns) {
6374
6825
  const [colW, setColW] = useState({});
6375
6826
  const resizeRef = useRef(null);
6376
6827
  const widthOf = (c) => colW[c.key] ?? (typeof c.width === "number" ? c.width : void 0);
6828
+ const setColumnWidth = (c, next) => {
6829
+ const w = Math.max(c.minWidth || 64, Math.round(next));
6830
+ setColW((m) => ({ ...m, [c.key]: w }));
6831
+ return w;
6832
+ };
6377
6833
  const startResize = (e, c) => {
6378
6834
  e.preventDefault();
6379
6835
  e.stopPropagation();
@@ -6385,7 +6841,7 @@ function useColumnResize(columns) {
6385
6841
  const r = resizeRef.current;
6386
6842
  if (!r) return;
6387
6843
  const w = Math.max(c.minWidth || 64, r.startW + (ev.clientX - r.startX));
6388
- setColW((m) => ({ ...m, [r.key]: w }));
6844
+ setColW((m) => ({ ...m, [r.key]: Math.round(w) }));
6389
6845
  };
6390
6846
  const up = () => {
6391
6847
  resizeRef.current = null;
@@ -6399,7 +6855,7 @@ function useColumnResize(columns) {
6399
6855
  document.body.style.cursor = "col-resize";
6400
6856
  document.body.style.userSelect = "none";
6401
6857
  };
6402
- return { colW, widthOf, startResize };
6858
+ return { colW, widthOf, startResize, setColumnWidth };
6403
6859
  }
6404
6860
  function useColumnVisibility(columns) {
6405
6861
  const [hiddenCols, setHiddenCols] = useState(
@@ -6603,7 +7059,7 @@ function Table({
6603
7059
  onFiltersChange,
6604
7060
  pagination = false,
6605
7061
  expandable,
6606
- density = "comfortable",
7062
+ density: densityProp,
6607
7063
  zebra = false,
6608
7064
  stickyHeader = false,
6609
7065
  hover = true,
@@ -6638,9 +7094,11 @@ function Table({
6638
7094
  style,
6639
7095
  ...props
6640
7096
  }) {
7097
+ const providerDensity = useConfig().density;
7098
+ const density = densityProp ?? (providerDensity === "compact" ? "compact" : "comfortable");
6641
7099
  const densityClass = DENSITY[density] || DENSITY.comfortable;
6642
7100
  const { menu, setMenu } = useTableContextMenu();
6643
- const { colW, widthOf, startResize } = useColumnResize();
7101
+ const { colW, widthOf, startResize, setColumnWidth } = useColumnResize();
6644
7102
  const { hiddenCols, visibleColumns, toggleColumn } = useColumnVisibility(columns);
6645
7103
  const dragCol = rowDraggable && !tree;
6646
7104
  const rowToText = (row) => columns.map((c) => {
@@ -6832,7 +7290,8 @@ function Table({
6832
7290
  setSort,
6833
7291
  activeFilters,
6834
7292
  setFilter,
6835
- startResize
7293
+ startResize,
7294
+ setColumnWidth
6836
7295
  }
6837
7296
  ),
6838
7297
  /* @__PURE__ */ jsx(
@@ -7015,6 +7474,7 @@ var Tree = forwardRef(function Tree2({
7015
7474
  showLine = false,
7016
7475
  blockNode = true,
7017
7476
  className,
7477
+ onKeyDown: onKeyDownProp,
7018
7478
  ...props
7019
7479
  }, ref) {
7020
7480
  const [innerExpanded, setInnerExpanded] = useState(defaultExpandedKeys);
@@ -7042,14 +7502,105 @@ var Tree = forwardRef(function Tree2({
7042
7502
  else next = Array.from(/* @__PURE__ */ new Set([...checkedKeys, ...all]));
7043
7503
  onCheck(next);
7044
7504
  };
7505
+ const visible = rows.filter((r) => !r.hidden);
7506
+ const rootRef = useRef(null);
7507
+ const setRoots = (node) => {
7508
+ rootRef.current = node;
7509
+ if (typeof ref === "function") ref(node);
7510
+ else if (ref && "current" in ref) ref.current = node;
7511
+ };
7512
+ const firstEnabledKey = () => {
7513
+ const hit = visible.find((r) => !r.node.disabled) ?? visible[0];
7514
+ return hit?.node.key ?? null;
7515
+ };
7516
+ const [focusedKey, setFocusedKey] = useState(null);
7517
+ const rovingKey = (() => {
7518
+ if (focusedKey && visible.some((r) => r.node.key === focusedKey)) return focusedKey;
7519
+ if (selectedKey && visible.some((r) => r.node.key === selectedKey)) return selectedKey;
7520
+ return firstEnabledKey();
7521
+ })();
7522
+ const focusKey = useCallback((key) => {
7523
+ if (!key) return;
7524
+ setFocusedKey(key);
7525
+ const el = rootRef.current?.querySelector(`[data-tree-key="${CSS.escape(key)}"]`);
7526
+ el?.focus?.();
7527
+ }, []);
7528
+ const onKeyDown = (e) => {
7529
+ if (visible.length === 0) return;
7530
+ const activeKey = rootRef.current?.ownerDocument?.activeElement?.getAttribute?.(
7531
+ "data-tree-key"
7532
+ ) ?? null;
7533
+ const currentKey = activeKey ?? rovingKey;
7534
+ const idx = Math.max(0, visible.findIndex((r) => r.node.key === currentKey));
7535
+ const cur = visible[idx];
7536
+ if (!cur) return;
7537
+ const hasChildren2 = !!(cur.node.children && cur.node.children.length);
7538
+ const isExpanded = exp.includes(cur.node.key);
7539
+ const parentKey = (() => {
7540
+ for (let i = idx - 1; i >= 0; i--) {
7541
+ if (visible[i].level < cur.level) return visible[i].node.key;
7542
+ }
7543
+ return null;
7544
+ })();
7545
+ switch (e.key) {
7546
+ case "ArrowDown":
7547
+ e.preventDefault();
7548
+ focusKey(visible[Math.min(idx + 1, visible.length - 1)]?.node.key ?? null);
7549
+ return;
7550
+ case "ArrowUp":
7551
+ e.preventDefault();
7552
+ focusKey(visible[Math.max(idx - 1, 0)]?.node.key ?? null);
7553
+ return;
7554
+ case "Home":
7555
+ e.preventDefault();
7556
+ focusKey(visible[0]?.node.key ?? null);
7557
+ return;
7558
+ case "End":
7559
+ e.preventDefault();
7560
+ focusKey(visible[visible.length - 1]?.node.key ?? null);
7561
+ return;
7562
+ case "ArrowRight":
7563
+ e.preventDefault();
7564
+ if (cur.node.disabled) return;
7565
+ if (hasChildren2 && !isExpanded) toggle(cur.node.key);
7566
+ else if (hasChildren2 && isExpanded) focusKey(visible[idx + 1]?.node.key ?? null);
7567
+ return;
7568
+ case "ArrowLeft":
7569
+ e.preventDefault();
7570
+ if (hasChildren2 && isExpanded) toggle(cur.node.key);
7571
+ else if (parentKey) focusKey(parentKey);
7572
+ return;
7573
+ case "Enter":
7574
+ e.preventDefault();
7575
+ if (cur.node.disabled) return;
7576
+ if (checkable) onCheckNode(cur.node);
7577
+ else onSelect?.(cur.node.key, cur.node);
7578
+ return;
7579
+ case " ":
7580
+ e.preventDefault();
7581
+ if (cur.node.disabled) return;
7582
+ if (checkable) onCheckNode(cur.node);
7583
+ else onSelect?.(cur.node.key, cur.node);
7584
+ return;
7585
+ default:
7586
+ return;
7587
+ }
7588
+ };
7589
+ const onKeyDownComposed = (e) => {
7590
+ onKeyDownProp?.(e);
7591
+ if (e.defaultPrevented) return;
7592
+ onKeyDown(e);
7593
+ };
7045
7594
  return /* @__PURE__ */ jsx(
7046
7595
  "div",
7047
7596
  {
7048
- ref,
7597
+ ref: setRoots,
7049
7598
  role: "tree",
7599
+ "aria-multiselectable": checkable || void 0,
7050
7600
  className: cx("klun-tree", showLine && "klun-tree--line", className),
7601
+ onKeyDown: onKeyDownComposed,
7051
7602
  ...props,
7052
- children: rows.filter((r) => !r.hidden).map(({ node, level }) => {
7603
+ children: visible.map(({ node, level }) => {
7053
7604
  const hasChildren2 = !!(node.children && node.children.length);
7054
7605
  const isExpanded = exp.includes(node.key);
7055
7606
  const selected = selectedKey === node.key;
@@ -7058,17 +7609,24 @@ var Tree = forwardRef(function Tree2({
7058
7609
  "div",
7059
7610
  {
7060
7611
  role: "treeitem",
7612
+ "data-tree-key": node.key,
7613
+ tabIndex: rovingKey === node.key ? 0 : -1,
7614
+ "aria-level": level + 1,
7061
7615
  "aria-expanded": hasChildren2 ? isExpanded : void 0,
7062
7616
  "aria-selected": selected,
7617
+ "aria-disabled": node.disabled || void 0,
7618
+ "aria-checked": checkable ? cs === "all" ? true : cs === "some" ? "mixed" : false : void 0,
7063
7619
  className: cx(
7064
7620
  "klun-tree__item",
7065
7621
  selected && "klun-tree__item--selected",
7066
7622
  node.disabled && "klun-tree__item--disabled",
7067
- blockNode && "klun-tree__item--block"
7623
+ blockNode && "klun-tree__item--block",
7624
+ rovingKey === node.key && "klun-tree__item--focused"
7068
7625
  ),
7069
7626
  style: { ["--klun-tree-indent"]: `${6 + level * 20}px` },
7070
7627
  onClick: () => {
7071
7628
  if (node.disabled) return;
7629
+ setFocusedKey(node.key);
7072
7630
  if (!checkable) onSelect && onSelect(node.key, node);
7073
7631
  },
7074
7632
  children: [
@@ -7080,6 +7638,7 @@ var Tree = forwardRef(function Tree2({
7080
7638
  hasChildren2 && isExpanded && "klun-tree__caret--expanded"
7081
7639
  ),
7082
7640
  "data-leaf": hasChildren2 ? void 0 : "",
7641
+ "aria-hidden": "true",
7083
7642
  onClick: (e) => {
7084
7643
  e.stopPropagation();
7085
7644
  if (hasChildren2) toggle(node.key);
@@ -7091,6 +7650,7 @@ var Tree = forwardRef(function Tree2({
7091
7650
  "span",
7092
7651
  {
7093
7652
  className: cx("klun-tree__checkbox", `klun-tree__checkbox--${cs}`),
7653
+ "aria-hidden": "true",
7094
7654
  onClick: (e) => {
7095
7655
  e.stopPropagation();
7096
7656
  if (!node.disabled) onCheckNode(node);
@@ -8333,7 +8893,14 @@ var AutoComplete = forwardRef(
8333
8893
  leadingIcon,
8334
8894
  emptyText: emptyTextProp,
8335
8895
  maxVisible = 6,
8896
+ error = false,
8336
8897
  className,
8898
+ inputProps,
8899
+ // 下面这些属性属于**真实输入框**,不能落在 wrapper 上:
8900
+ // 落在 wrapper 上时 `<label for={id}>` 指不到控件、`aria-label` 对输入框无效。
8901
+ // 其余属性仍然透传给根节点,保持既有行为。
8902
+ id,
8903
+ inputMode,
8337
8904
  ...props
8338
8905
  }, ref) {
8339
8906
  const size = useSize(sizeProp);
@@ -8342,6 +8909,17 @@ var AutoComplete = forwardRef(
8342
8909
  const [open, setOpen] = useState(false);
8343
8910
  const [hi, setHi] = useState(-1);
8344
8911
  const rootRef = useRef(null);
8912
+ const generatedId = useId();
8913
+ const listboxId = `${generatedId}listbox`;
8914
+ const optionId = (index) => `${listboxId}-option-${index}`;
8915
+ const {
8916
+ "aria-label": ariaLabel,
8917
+ "aria-labelledby": ariaLabelledBy,
8918
+ "aria-describedby": ariaDescribedBy,
8919
+ "aria-invalid": ariaInvalid,
8920
+ "aria-required": ariaRequired,
8921
+ ...rootProps
8922
+ } = props;
8345
8923
  const norm2 = options.map(
8346
8924
  (o) => typeof o === "string" ? { value: o, label: o } : o
8347
8925
  );
@@ -8386,13 +8964,14 @@ var AutoComplete = forwardRef(
8386
8964
  {
8387
8965
  ref: rootRef,
8388
8966
  className: cx("klun-autocomplete", `klun-autocomplete--${size}`, className),
8389
- ...props,
8967
+ ...rootProps,
8390
8968
  children: [
8391
8969
  /* @__PURE__ */ jsxs(
8392
8970
  "div",
8393
8971
  {
8394
8972
  className: cx(
8395
8973
  "klun-autocomplete__field",
8974
+ error && "klun-autocomplete__field--error",
8396
8975
  disabled && "klun-autocomplete__field--disabled"
8397
8976
  ),
8398
8977
  "data-open": open ? "" : void 0,
@@ -8401,11 +8980,25 @@ var AutoComplete = forwardRef(
8401
8980
  /* @__PURE__ */ jsx(
8402
8981
  "input",
8403
8982
  {
8983
+ ...inputProps,
8404
8984
  ref,
8405
- className: "klun-autocomplete__input",
8985
+ id: id ?? inputProps?.id,
8986
+ autoComplete: inputProps?.autoComplete,
8987
+ inputMode: inputMode ?? inputProps?.inputMode,
8988
+ className: cx("klun-autocomplete__input", inputProps?.className),
8406
8989
  value,
8407
8990
  disabled,
8408
8991
  placeholder,
8992
+ role: "combobox",
8993
+ "aria-expanded": open,
8994
+ "aria-controls": open ? listboxId : void 0,
8995
+ "aria-activedescendant": open && hi >= 0 ? optionId(hi) : void 0,
8996
+ "aria-autocomplete": "list",
8997
+ "aria-label": ariaLabel,
8998
+ "aria-labelledby": ariaLabelledBy,
8999
+ "aria-describedby": ariaDescribedBy,
9000
+ "aria-invalid": ariaInvalid,
9001
+ "aria-required": ariaRequired,
8409
9002
  onChange: (e) => {
8410
9003
  onChange?.(e.target.value);
8411
9004
  setOpen(true);
@@ -8418,9 +9011,10 @@ var AutoComplete = forwardRef(
8418
9011
  ]
8419
9012
  }
8420
9013
  ),
8421
- open ? /* @__PURE__ */ jsx("div", { className: "klun-autocomplete__list", role: "listbox", children: shown.length === 0 ? /* @__PURE__ */ jsx("div", { className: "klun-autocomplete__empty", children: emptyText }) : shown.map((o, i) => /* @__PURE__ */ jsxs(
9014
+ open ? /* @__PURE__ */ jsx("div", { className: "klun-autocomplete__list", id: listboxId, role: "listbox", children: shown.length === 0 ? /* @__PURE__ */ jsx("div", { className: "klun-autocomplete__empty", children: emptyText }) : shown.map((o, i) => /* @__PURE__ */ jsxs(
8422
9015
  "button",
8423
9016
  {
9017
+ id: optionId(i),
8424
9018
  type: "button",
8425
9019
  role: "option",
8426
9020
  "aria-selected": i === hi,
@@ -8470,6 +9064,8 @@ var Cascader = forwardRef(function Cascader2({
8470
9064
  const [open, setOpen] = useState(false);
8471
9065
  const [active, setActive] = useState(current);
8472
9066
  const rootRef = useRef(null);
9067
+ const triggerRef = useRef(null);
9068
+ const panelRef = useRef(null);
8473
9069
  useEffect(() => {
8474
9070
  setActive(current);
8475
9071
  }, [open]);
@@ -8479,7 +9075,11 @@ var Cascader = forwardRef(function Cascader2({
8479
9075
  if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
8480
9076
  };
8481
9077
  const k2 = (e) => {
8482
- if (e.key === "Escape") setOpen(false);
9078
+ if (e.key !== "Escape") return;
9079
+ setOpen(false);
9080
+ if (rootRef.current && rootRef.current.contains(document.activeElement)) {
9081
+ triggerRef.current?.focus();
9082
+ }
8483
9083
  };
8484
9084
  document.addEventListener("mousedown", h);
8485
9085
  document.addEventListener("keydown", k2);
@@ -8488,6 +9088,15 @@ var Cascader = forwardRef(function Cascader2({
8488
9088
  document.removeEventListener("keydown", k2);
8489
9089
  };
8490
9090
  }, [open]);
9091
+ useEffect(() => {
9092
+ if (!open) return;
9093
+ const id = requestAnimationFrame(() => {
9094
+ const cols = panelRef.current?.querySelectorAll(".klun-cascader__column");
9095
+ const last = cols && cols.length ? cols[cols.length - 1] : null;
9096
+ last?.querySelector(".klun-cascader__option:not([disabled])")?.focus();
9097
+ });
9098
+ return () => cancelAnimationFrame(id);
9099
+ }, [open]);
8491
9100
  const columns = [];
8492
9101
  let level = options;
8493
9102
  columns.push(level);
@@ -8517,6 +9126,62 @@ var Cascader = forwardRef(function Cascader2({
8517
9126
  if (leaf) setOpen(false);
8518
9127
  }
8519
9128
  };
9129
+ const onPanelKeyDown = (e) => {
9130
+ const target = e.target;
9131
+ const option = target.closest(".klun-cascader__option");
9132
+ if (!option) return;
9133
+ const column = option.closest(".klun-cascader__column");
9134
+ if (!column) return;
9135
+ const all = Array.from(column.querySelectorAll(".klun-cascader__option"));
9136
+ const enabled = all.filter((el) => !el.disabled);
9137
+ const i = enabled.indexOf(option);
9138
+ const colIdx = Array.from(
9139
+ panelRef.current?.querySelectorAll(".klun-cascader__column") ?? []
9140
+ ).indexOf(column);
9141
+ const focusIntoColumn = (n) => {
9142
+ const cols = panelRef.current?.querySelectorAll(".klun-cascader__column");
9143
+ cols?.[n]?.querySelector(".klun-cascader__option:not([disabled])")?.focus();
9144
+ };
9145
+ switch (e.key) {
9146
+ case "ArrowDown":
9147
+ e.preventDefault();
9148
+ enabled[(i + 1) % enabled.length]?.focus();
9149
+ break;
9150
+ case "ArrowUp":
9151
+ e.preventDefault();
9152
+ enabled[(i - 1 + enabled.length) % enabled.length]?.focus();
9153
+ break;
9154
+ case "Home":
9155
+ e.preventDefault();
9156
+ enabled[0]?.focus();
9157
+ break;
9158
+ case "End":
9159
+ e.preventDefault();
9160
+ enabled[enabled.length - 1]?.focus();
9161
+ break;
9162
+ case "ArrowRight": {
9163
+ e.preventDefault();
9164
+ const opt = columns[colIdx]?.[all.indexOf(option)];
9165
+ if (opt && opt.children && opt.children.length) {
9166
+ pick(colIdx, opt);
9167
+ requestAnimationFrame(() => focusIntoColumn(colIdx + 1));
9168
+ }
9169
+ break;
9170
+ }
9171
+ case "ArrowLeft":
9172
+ e.preventDefault();
9173
+ if (colIdx > 0) focusIntoColumn(colIdx - 1);
9174
+ break;
9175
+ case "Escape":
9176
+ e.preventDefault();
9177
+ setOpen(false);
9178
+ triggerRef.current?.focus();
9179
+ break;
9180
+ case "Tab":
9181
+ setOpen(false);
9182
+ break;
9183
+ }
9184
+ };
8520
9185
  const clear = () => {
8521
9186
  if (value === void 0) setInner([]);
8522
9187
  setActive([]);
@@ -8539,11 +9204,12 @@ var Cascader = forwardRef(function Cascader2({
8539
9204
  /* @__PURE__ */ jsxs(
8540
9205
  "button",
8541
9206
  {
9207
+ ref: triggerRef,
8542
9208
  type: "button",
8543
9209
  className: "klun-cascader__trigger",
8544
9210
  disabled,
8545
9211
  onClick: () => setOpen((o) => !o),
8546
- "aria-haspopup": "true",
9212
+ "aria-haspopup": "menu",
8547
9213
  "aria-expanded": open,
8548
9214
  "data-empty": labelPath.length ? void 0 : "",
8549
9215
  children: [
@@ -8589,9 +9255,11 @@ var Cascader = forwardRef(function Cascader2({
8589
9255
  ]
8590
9256
  }
8591
9257
  ),
8592
- open ? /* @__PURE__ */ jsx("div", { className: "klun-cascader__panel", role: "menu", children: columns.map((col, ci) => /* @__PURE__ */ jsx(
9258
+ open ? /* @__PURE__ */ jsx("div", { ref: panelRef, className: "klun-cascader__panel", role: "menu", onKeyDown: onPanelKeyDown, children: columns.map((col, ci) => /* @__PURE__ */ jsx(
8593
9259
  "div",
8594
9260
  {
9261
+ role: "group",
9262
+ "aria-label": ci === 0 ? cascader.placeholder : String(active[ci - 1] ?? ""),
8595
9263
  className: cx(
8596
9264
  "klun-cascader__column",
8597
9265
  ci < columns.length - 1 && "klun-cascader__column--divided"
@@ -8603,11 +9271,11 @@ var Cascader = forwardRef(function Cascader2({
8603
9271
  "button",
8604
9272
  {
8605
9273
  type: "button",
8606
- role: "menuitem",
9274
+ role: "menuitemradio",
8607
9275
  className: "klun-cascader__option",
8608
9276
  disabled: opt.disabled,
8609
9277
  onClick: () => pick(ci, opt),
8610
- "aria-selected": selected,
9278
+ "aria-checked": selected,
8611
9279
  "data-selected": selected || void 0,
8612
9280
  children: [
8613
9281
  /* @__PURE__ */ jsx("span", { className: "klun-cascader__option-label", children: renderOption ? renderOption(opt, ci) : opt.label }),
@@ -9112,7 +9780,9 @@ function SelectListbox({
9112
9780
  onActivate,
9113
9781
  onPick,
9114
9782
  className,
9115
- anchorRef
9783
+ anchorRef,
9784
+ id,
9785
+ optionId
9116
9786
  }) {
9117
9787
  const portal = !!anchorRef && typeof document !== "undefined";
9118
9788
  const panelRef = useRef(null);
@@ -9160,12 +9830,14 @@ function SelectListbox({
9160
9830
  "div",
9161
9831
  {
9162
9832
  ref: panelRef,
9833
+ id,
9163
9834
  role: "listbox",
9164
9835
  className: className ? `klun-select-listbox ${className}` : "klun-select-listbox",
9165
9836
  style: portalStyle,
9166
9837
  children: options.map((o, i) => /* @__PURE__ */ jsxs(
9167
9838
  "button",
9168
9839
  {
9840
+ id: optionId?.(i),
9169
9841
  type: "button",
9170
9842
  role: "option",
9171
9843
  "aria-selected": o.value === current,
@@ -9713,7 +10385,7 @@ var DEFAULT_FORMAT = {
9713
10385
  day: "numeric"
9714
10386
  };
9715
10387
  var Calendar = forwardRef(function Calendar2({ value, onPick, className, style }, ref) {
9716
- const { datePicker } = useLocale();
10388
+ const { datePicker, pagination, locale } = useLocale();
9717
10389
  const initial = value ? new Date(value) : /* @__PURE__ */ new Date();
9718
10390
  const [view, setView] = useState(new Date(initial.getFullYear(), initial.getMonth(), 1));
9719
10391
  const sel = value ? new Date(value) : null;
@@ -9726,34 +10398,69 @@ var Calendar = forwardRef(function Calendar2({ value, onPick, className, style }
9726
10398
  const cells = [];
9727
10399
  for (let i = 0; i < firstDay; i++) cells.push(null);
9728
10400
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(y, m, d));
9729
- return /* @__PURE__ */ jsxs("div", { ref, className: cx("klun-date-picker", className), style, children: [
9730
- /* @__PURE__ */ jsxs("div", { className: "klun-date-picker__header", children: [
9731
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-date-picker__nav", onClick: () => setView(new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M12 6l-4 4 4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
9732
- /* @__PURE__ */ jsx("span", { className: "klun-date-picker__title", children: fmt(datePicker.title, { month: datePicker.months[m], year: y }) }),
9733
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-date-picker__nav", onClick: () => setView(new Date(y, m + 1, 1)), children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M8 6l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
9734
- ] }),
9735
- /* @__PURE__ */ jsxs("div", { className: "klun-date-picker__grid", children: [
9736
- datePicker.weekdaysShort.map((d, i) => /* @__PURE__ */ jsx("div", { className: "klun-date-picker__weekday", children: d }, i)),
9737
- cells.map((date, i) => {
9738
- if (!date) return /* @__PURE__ */ jsx("span", {}, i);
9739
- return /* @__PURE__ */ jsx(
9740
- "button",
9741
- {
9742
- type: "button",
9743
- className: "klun-date-picker__day",
9744
- "data-selected": same(date, sel) || void 0,
9745
- "data-today": same(date, today) || void 0,
9746
- onClick: () => onPick(date),
9747
- children: date.getDate()
9748
- },
9749
- i
9750
- );
9751
- })
9752
- ] })
9753
- ] });
10401
+ return /* @__PURE__ */ jsxs(
10402
+ "div",
10403
+ {
10404
+ ref,
10405
+ className: cx("klun-date-picker", className),
10406
+ style,
10407
+ role: "group",
10408
+ "aria-label": fmt(datePicker.title, { month: datePicker.months[m], year: y }),
10409
+ children: [
10410
+ /* @__PURE__ */ jsxs("div", { className: "klun-date-picker__header", children: [
10411
+ /* @__PURE__ */ jsx(
10412
+ "button",
10413
+ {
10414
+ type: "button",
10415
+ className: "klun-date-picker__nav",
10416
+ "aria-label": pagination.previous,
10417
+ onClick: () => setView(new Date(y, m - 1, 1)),
10418
+ children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M12 6l-4 4 4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
10419
+ }
10420
+ ),
10421
+ /* @__PURE__ */ jsx("span", { className: "klun-date-picker__title", children: fmt(datePicker.title, { month: datePicker.months[m], year: y }) }),
10422
+ /* @__PURE__ */ jsx(
10423
+ "button",
10424
+ {
10425
+ type: "button",
10426
+ className: "klun-date-picker__nav",
10427
+ "aria-label": pagination.next,
10428
+ onClick: () => setView(new Date(y, m + 1, 1)),
10429
+ children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M8 6l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
10430
+ }
10431
+ )
10432
+ ] }),
10433
+ /* @__PURE__ */ jsxs("div", { className: "klun-date-picker__grid", children: [
10434
+ datePicker.weekdaysShort.map((d, i) => /* @__PURE__ */ jsx("div", { className: "klun-date-picker__weekday", children: d }, i)),
10435
+ cells.map((date, i) => {
10436
+ if (!date) return /* @__PURE__ */ jsx("span", {}, i);
10437
+ return /* @__PURE__ */ jsx(
10438
+ "button",
10439
+ {
10440
+ type: "button",
10441
+ className: "klun-date-picker__day",
10442
+ "data-selected": same(date, sel) || void 0,
10443
+ "data-today": same(date, today) || void 0,
10444
+ "aria-label": date.toLocaleDateString(locale, {
10445
+ weekday: "long",
10446
+ year: "numeric",
10447
+ month: "long",
10448
+ day: "numeric"
10449
+ }),
10450
+ "aria-current": same(date, today) ? "date" : void 0,
10451
+ onClick: () => onPick(date),
10452
+ children: date.getDate()
10453
+ },
10454
+ i
10455
+ );
10456
+ })
10457
+ ] })
10458
+ ]
10459
+ }
10460
+ );
9754
10461
  });
9755
10462
  var DatePicker = forwardRef(
9756
- function DatePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT, align = "left", disabled, className, style, ...props }, ref) {
10463
+ function DatePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT, align = "start", disabled, className, style, ...props }, ref) {
9757
10464
  if (inline2) {
9758
10465
  return /* @__PURE__ */ jsx(Calendar, { ref, value, onPick: (d) => onChange?.(d), className, style });
9759
10466
  }
@@ -9851,7 +10558,7 @@ var RangeCalendar = forwardRef(function RangeCalendar2({ start, end, onPick, cla
9851
10558
  ] });
9852
10559
  });
9853
10560
  var DateRangePicker = forwardRef(
9854
- function DateRangePicker2({ start, end, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT2, align = "left", disabled, className, style, ...props }, ref) {
10561
+ function DateRangePicker2({ start, end, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT2, align = "start", disabled, className, style, ...props }, ref) {
9855
10562
  if (inline2) {
9856
10563
  return /* @__PURE__ */ jsx(
9857
10564
  RangeCalendar,
@@ -10129,7 +10836,7 @@ function DateTimePanel({ value, onChange }) {
10129
10836
  ] });
10130
10837
  }
10131
10838
  var DateTimePicker = forwardRef(
10132
- function DateTimePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT3, align = "left", disabled, className, style, ...props }, ref) {
10839
+ function DateTimePicker2({ value, onChange, inline: inline2, placeholder, format = DEFAULT_FORMAT3, align = "start", disabled, className, style, ...props }, ref) {
10133
10840
  const date = value ? new Date(value) : null;
10134
10841
  if (inline2) {
10135
10842
  return /* @__PURE__ */ jsx("div", { ref, className: cx("klun-date-time-picker", className), style, ...props, children: /* @__PURE__ */ jsx(DateTimePanel, { value: date, onChange: (d) => onChange?.(d) }) });
@@ -10260,13 +10967,24 @@ var FileUpload = forwardRef(function FileUpload2({ onFiles, hint = "SVG, PNG, JP
10260
10967
  const { fileUpload } = useLocale();
10261
10968
  const [over, setOver] = useState(false);
10262
10969
  const inputRef = useRef(null);
10970
+ const openPicker = () => inputRef.current?.click();
10971
+ const dropzoneLabel = `${fileUpload.clickToUpload} ${fileUpload.orDragAndDrop}`;
10263
10972
  return /* @__PURE__ */ jsxs(
10264
10973
  "div",
10265
10974
  {
10266
10975
  ref,
10267
10976
  className: cx("klun-file-upload", className),
10977
+ role: "button",
10978
+ tabIndex: 0,
10979
+ "aria-label": dropzoneLabel,
10268
10980
  "data-dragover": over || void 0,
10269
- onClick: () => inputRef.current?.click(),
10981
+ onClick: openPicker,
10982
+ onKeyDown: (e) => {
10983
+ if (e.key === "Enter" || e.key === " ") {
10984
+ e.preventDefault();
10985
+ openPicker();
10986
+ }
10987
+ },
10270
10988
  onDragOver: (e) => {
10271
10989
  e.preventDefault();
10272
10990
  setOver(true);
@@ -10286,6 +11004,7 @@ var FileUpload = forwardRef(function FileUpload2({ onFiles, hint = "SVG, PNG, JP
10286
11004
  type: "file",
10287
11005
  multiple: true,
10288
11006
  hidden: true,
11007
+ tabIndex: -1,
10289
11008
  onChange: (e) => onFiles?.([...e.target.files ?? []])
10290
11009
  }
10291
11010
  ),
@@ -10383,9 +11102,6 @@ function useForm(opts = {}) {
10383
11102
  const unregisterField = useCallback((key) => {
10384
11103
  delete fields.current[key];
10385
11104
  }, []);
10386
- const registerRules = useCallback((name, rules) => {
10387
- fields.current[pathKey(name)] = { name, rules: rules || [] };
10388
- }, []);
10389
11105
  const getFieldValue = useCallback((name) => getIn(valuesRef.current, name), []);
10390
11106
  const getFieldsValue = useCallback(() => valuesRef.current, []);
10391
11107
  const validateField = useCallback(async (name) => {
@@ -10504,7 +11220,6 @@ function useForm(opts = {}) {
10504
11220
  setValues,
10505
11221
  getFieldValue,
10506
11222
  getFieldsValue,
10507
- registerRules,
10508
11223
  registerField,
10509
11224
  unregisterField,
10510
11225
  validate,
@@ -10577,22 +11292,35 @@ function FormItem({
10577
11292
  const error = form && key ? form.touched[key] && form.errors[key] : null;
10578
11293
  const ruleArr = typeof rules === "function" ? [] : rules || [];
10579
11294
  const isRequired = required || ruleArr.some((r) => r.required);
11295
+ const autoId = useId();
11296
+ const childIsElement = isValidElement(children);
11297
+ const childProps = childIsElement ? children.props : {};
11298
+ const controlId = childIsElement ? childProps.id ?? `${autoId}control` : void 0;
11299
+ const errorId = controlId ? `${controlId}-error` : void 0;
11300
+ const helpId = controlId ? `${controlId}-help` : void 0;
11301
+ const hasError = Boolean(error);
11302
+ const descriptionId = hasError ? errorId : help ? helpId : void 0;
10580
11303
  let control = children;
10581
- if (form && fullName != null && isValidElement(children)) {
10582
- const childProps = children.props;
10583
- control = cloneElement(children, {
10584
- value: form._getIn(form.values, fullName) ?? childProps.value ?? "",
10585
- error: !!error,
10586
- onChange: (e) => {
11304
+ if (childIsElement) {
11305
+ const merged = { id: controlId };
11306
+ if (form && fullName != null) {
11307
+ merged.value = form._getIn(form.values, fullName) ?? childProps.value ?? "";
11308
+ merged.error = hasError ? true : void 0;
11309
+ merged.onChange = (e) => {
10587
11310
  const v = e && e.target ? childProps.type === "checkbox" ? e.target.checked : e.target.value : e;
10588
11311
  form.setFieldValue(fullName, v);
10589
11312
  childProps.onChange?.(e);
10590
- },
10591
- onBlur: (e) => {
11313
+ };
11314
+ merged.onBlur = (e) => {
10592
11315
  form.setFieldTouched(fullName);
10593
11316
  childProps.onBlur?.(e);
10594
- }
10595
- });
11317
+ };
11318
+ }
11319
+ if (hasError) merged["aria-invalid"] = true;
11320
+ if (isRequired) merged["aria-required"] = true;
11321
+ const describedBy = [childProps["aria-describedby"], descriptionId].filter(Boolean).join(" ");
11322
+ if (describedBy) merged["aria-describedby"] = describedBy;
11323
+ control = cloneElement(children, merged);
10596
11324
  }
10597
11325
  return /* @__PURE__ */ jsxs(
10598
11326
  "div",
@@ -10601,13 +11329,13 @@ function FormItem({
10601
11329
  className: cx("klun-form-item", horizontal && "klun-form-item--horizontal", className),
10602
11330
  ...props,
10603
11331
  children: [
10604
- label ? /* @__PURE__ */ jsxs("label", { className: "klun-form-item__label", children: [
11332
+ label ? /* @__PURE__ */ jsxs("label", { className: "klun-form-item__label", htmlFor: controlId, children: [
10605
11333
  label,
10606
- isRequired ? /* @__PURE__ */ jsx("span", { className: "klun-form-item__required", children: "*" }) : null
11334
+ isRequired ? /* @__PURE__ */ jsx("span", { className: "klun-form-item__required", "aria-hidden": "true", children: "*" }) : null
10607
11335
  ] }) : null,
10608
11336
  /* @__PURE__ */ jsxs("div", { className: "klun-form-item__control", children: [
10609
11337
  control,
10610
- error ? /* @__PURE__ */ jsx("span", { className: "klun-form-item__error", children: error }) : help ? /* @__PURE__ */ jsx("span", { className: "klun-form-item__help", children: help }) : null
11338
+ hasError ? /* @__PURE__ */ jsx("span", { id: errorId, className: "klun-form-item__error", children: error }) : help ? /* @__PURE__ */ jsx("span", { id: helpId, className: "klun-form-item__help", children: help }) : null
10611
11339
  ] })
10612
11340
  ]
10613
11341
  }
@@ -10668,6 +11396,228 @@ var Hint = forwardRef(function Hint2({ children, error = false, icon, className,
10668
11396
  );
10669
11397
  });
10670
11398
  Hint.displayName = "Hint";
11399
+
11400
+ // src/components/overlays/overlayStack.ts
11401
+ var OVERLAY_LAYER = {
11402
+ modalRoot: 1e3,
11403
+ modalStep: 100};
11404
+ var stack = [];
11405
+ var scopeRoots = /* @__PURE__ */ new Map();
11406
+ var scrollLockCount = 0;
11407
+ var savedOverflow = null;
11408
+ var canUseDOM = () => typeof document !== "undefined";
11409
+ function pushOverlay() {
11410
+ const id = /* @__PURE__ */ Symbol("klun-overlay");
11411
+ stack.push(id);
11412
+ scopeRoots.set(id, /* @__PURE__ */ new Set());
11413
+ lockScroll();
11414
+ return id;
11415
+ }
11416
+ function popOverlay(id) {
11417
+ const i = stack.indexOf(id);
11418
+ if (i === -1) return;
11419
+ stack.splice(i, 1);
11420
+ scopeRoots.delete(id);
11421
+ unlockScroll();
11422
+ }
11423
+ function isTopOverlay(id) {
11424
+ return stack.length > 0 && stack[stack.length - 1] === id;
11425
+ }
11426
+ function overlayDepth(id) {
11427
+ return stack.indexOf(id);
11428
+ }
11429
+ function layerBaseFor(id) {
11430
+ const depth = Math.max(0, overlayDepth(id));
11431
+ return OVERLAY_LAYER.modalRoot + depth * OVERLAY_LAYER.modalStep;
11432
+ }
11433
+ function registerScopeRoot(id, el) {
11434
+ const set = scopeRoots.get(id);
11435
+ if (!set || !el) return;
11436
+ set.add(el);
11437
+ }
11438
+ function unregisterScopeRoot(id, el) {
11439
+ if (!el) return;
11440
+ scopeRoots.get(id)?.delete(el);
11441
+ }
11442
+ function getScopeRoots(id) {
11443
+ const set = scopeRoots.get(id);
11444
+ if (!set) return [];
11445
+ return [...set].filter((el) => el.isConnected);
11446
+ }
11447
+ function lockScroll() {
11448
+ if (!canUseDOM()) return;
11449
+ if (scrollLockCount === 0) {
11450
+ savedOverflow = document.body.style.overflow;
11451
+ document.body.style.overflow = "hidden";
11452
+ }
11453
+ scrollLockCount += 1;
11454
+ }
11455
+ function unlockScroll() {
11456
+ if (!canUseDOM()) return;
11457
+ scrollLockCount = Math.max(0, scrollLockCount - 1);
11458
+ if (scrollLockCount === 0) {
11459
+ document.body.style.overflow = savedOverflow ?? "";
11460
+ savedOverflow = null;
11461
+ }
11462
+ }
11463
+ var inertedByUs = /* @__PURE__ */ new WeakMap();
11464
+ function applyBackgroundInert(roots) {
11465
+ if (!canUseDOM() || roots.length === 0) return;
11466
+ for (const root of roots) {
11467
+ let node = root;
11468
+ while (node && node.parentElement) {
11469
+ const parent = node.parentElement;
11470
+ for (const sibling of Array.from(parent.children)) {
11471
+ if (sibling === node) continue;
11472
+ if (!(sibling instanceof HTMLElement)) continue;
11473
+ if (roots.some((r) => sibling.contains(r))) continue;
11474
+ if (!sibling.hasAttribute("inert") && !inertedByUs.has(sibling)) {
11475
+ sibling.setAttribute("inert", "");
11476
+ inertedByUs.set(sibling, true);
11477
+ }
11478
+ }
11479
+ node = parent;
11480
+ if (node === document.body) break;
11481
+ }
11482
+ }
11483
+ }
11484
+ function releaseBackgroundInert() {
11485
+ if (!canUseDOM()) return;
11486
+ for (const el of document.querySelectorAll("[inert]")) {
11487
+ if (inertedByUs.get(el)) {
11488
+ el.removeAttribute("inert");
11489
+ inertedByUs.delete(el);
11490
+ }
11491
+ }
11492
+ }
11493
+ function isFocusable(el) {
11494
+ if (el.hasAttribute("disabled")) return false;
11495
+ if (el.getAttribute("aria-hidden") === "true") return false;
11496
+ if (el.hasAttribute("hidden")) return false;
11497
+ if (typeof getComputedStyle === "function") {
11498
+ const cs = getComputedStyle(el);
11499
+ if (cs.display === "none" || cs.visibility === "hidden") return false;
11500
+ }
11501
+ if (el.getAttribute("tabindex") === "-1") return false;
11502
+ return true;
11503
+ }
11504
+ var FOCUSABLE_SELECTOR = [
11505
+ "a[href]",
11506
+ "button",
11507
+ "input:not([type='hidden'])",
11508
+ "select",
11509
+ "textarea",
11510
+ "[tabindex]",
11511
+ "audio[controls]",
11512
+ "video[controls]",
11513
+ "[contenteditable]:not([contenteditable='false'])"
11514
+ ].join(",");
11515
+ function focusablesIn(roots) {
11516
+ const out = [];
11517
+ for (const root of roots) {
11518
+ for (const el of Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR))) {
11519
+ if (isFocusable(el)) out.push(el);
11520
+ }
11521
+ }
11522
+ return out;
11523
+ }
11524
+ function useOverlayScope({
11525
+ active,
11526
+ onEscape,
11527
+ escapeEnabled = true,
11528
+ autoFocus = true,
11529
+ restoreFocus = true,
11530
+ inertBackground = true
11531
+ }) {
11532
+ const [scopeId, setScopeId] = useState(null);
11533
+ const nodeRef = useRef(null);
11534
+ const restoreTo = useRef(null);
11535
+ const onEscapeRef = useRef(onEscape);
11536
+ onEscapeRef.current = onEscape;
11537
+ useEffect(() => {
11538
+ if (!active) {
11539
+ setScopeId(null);
11540
+ return;
11541
+ }
11542
+ const id = pushOverlay();
11543
+ setScopeId(id);
11544
+ return () => {
11545
+ popOverlay(id);
11546
+ };
11547
+ }, [active]);
11548
+ useEffect(() => {
11549
+ if (!active || !scopeId) return;
11550
+ const container = nodeRef.current;
11551
+ registerScopeRoot(scopeId, container);
11552
+ if (restoreFocus) {
11553
+ restoreTo.current = document.activeElement ?? null;
11554
+ }
11555
+ if (autoFocus) {
11556
+ const items2 = focusablesIn(getScopeRoots(scopeId));
11557
+ const target = items2[0] ?? container;
11558
+ target?.focus?.();
11559
+ }
11560
+ if (inertBackground) applyBackgroundInert(getScopeRoots(scopeId));
11561
+ return () => {
11562
+ unregisterScopeRoot(scopeId, container);
11563
+ if (inertBackground) releaseBackgroundInert();
11564
+ if (restoreFocus) {
11565
+ const to = restoreTo.current;
11566
+ restoreTo.current = null;
11567
+ if (to && to.isConnected) to.focus?.();
11568
+ }
11569
+ };
11570
+ }, [active, scopeId]);
11571
+ useEffect(() => {
11572
+ if (!active || !scopeId) return;
11573
+ const onKeyDown = (e) => {
11574
+ if (e.key === "Escape") {
11575
+ if (!escapeEnabled) return;
11576
+ if (!isTopOverlay(scopeId)) {
11577
+ e.stopPropagation();
11578
+ return;
11579
+ }
11580
+ onEscapeRef.current?.();
11581
+ return;
11582
+ }
11583
+ if (e.key !== "Tab") return;
11584
+ if (!isTopOverlay(scopeId)) {
11585
+ e.preventDefault();
11586
+ return;
11587
+ }
11588
+ const items2 = focusablesIn(getScopeRoots(scopeId));
11589
+ if (items2.length === 0) {
11590
+ e.preventDefault();
11591
+ nodeRef.current?.focus?.();
11592
+ return;
11593
+ }
11594
+ const first = items2[0];
11595
+ const last = items2[items2.length - 1];
11596
+ const current = document.activeElement;
11597
+ const inside = current ? items2.includes(current) : false;
11598
+ if (e.shiftKey) {
11599
+ if (!inside || current === first) {
11600
+ e.preventDefault();
11601
+ last.focus();
11602
+ }
11603
+ } else if (!inside || current === last) {
11604
+ e.preventDefault();
11605
+ first.focus();
11606
+ }
11607
+ };
11608
+ document.addEventListener("keydown", onKeyDown, true);
11609
+ return () => document.removeEventListener("keydown", onKeyDown, true);
11610
+ }, [active, scopeId, escapeEnabled]);
11611
+ const setNode = useCallback((el) => {
11612
+ nodeRef.current = el;
11613
+ }, []);
11614
+ return {
11615
+ ref: setNode,
11616
+ scopeId,
11617
+ layerBase: scopeId ? layerBaseFor(scopeId) : OVERLAY_LAYER.modalRoot
11618
+ };
11619
+ }
11620
+ createContext(null);
10671
11621
  var Modal = forwardRef(function Modal2({
10672
11622
  open,
10673
11623
  onClose,
@@ -10708,19 +11658,21 @@ var Modal = forwardRef(function Modal2({
10708
11658
  const [maximized, setMaximized] = useState(defaultMaximized);
10709
11659
  const drag = useRef(null);
10710
11660
  const prevOpen = useRef(open);
10711
- useEffect(() => {
10712
- if (!open) return;
10713
- const onKey = (e) => {
10714
- if (e.key === "Escape" && keyboard && closable) cancel?.();
10715
- };
10716
- document.addEventListener("keydown", onKey);
10717
- const prevOverflow = document.body.style.overflow;
10718
- document.body.style.overflow = "hidden";
10719
- return () => {
10720
- document.removeEventListener("keydown", onKey);
10721
- document.body.style.overflow = prevOverflow;
10722
- };
10723
- }, [open, keyboard, closable, cancel]);
11661
+ const scope = useOverlayScope({
11662
+ active: open,
11663
+ escapeEnabled: keyboard && closable,
11664
+ onEscape: cancel
11665
+ });
11666
+ const scopeRef = scope.ref;
11667
+ const titleId = `${useId()}title`;
11668
+ const attachDialogRef = useCallback(
11669
+ (el) => {
11670
+ scopeRef(el);
11671
+ if (typeof ref === "function") ref(el);
11672
+ else if (ref) ref.current = el;
11673
+ },
11674
+ [ref, scopeRef]
11675
+ );
10724
11676
  useEffect(() => {
10725
11677
  if (open) {
10726
11678
  setPos({ x: 0, y: 0 });
@@ -10771,9 +11723,11 @@ var Modal = forwardRef(function Modal2({
10771
11723
  children: /* @__PURE__ */ jsxs(
10772
11724
  "div",
10773
11725
  {
10774
- ref,
11726
+ ref: attachDialogRef,
10775
11727
  role: "dialog",
10776
11728
  "aria-modal": "true",
11729
+ "aria-labelledby": title ? titleId : void 0,
11730
+ tabIndex: -1,
10777
11731
  onClick: (e) => e.stopPropagation(),
10778
11732
  className: cx("klun-modal__dialog", maximized && "klun-modal__dialog--maximized", className),
10779
11733
  style: dialogStyle,
@@ -10787,7 +11741,7 @@ var Modal = forwardRef(function Modal2({
10787
11741
  children: [
10788
11742
  icon ? /* @__PURE__ */ jsx("div", { className: "klun-modal__icon", children: icon }) : null,
10789
11743
  /* @__PURE__ */ jsxs("div", { className: "klun-modal__heading", children: [
10790
- title ? /* @__PURE__ */ jsx("div", { className: "klun-modal__title", children: title }) : null,
11744
+ title ? /* @__PURE__ */ jsx("div", { className: "klun-modal__title", id: titleId, children: title }) : null,
10791
11745
  description ? /* @__PURE__ */ jsx("div", { className: "klun-modal__description", children: description }) : null
10792
11746
  ] }),
10793
11747
  maximizable || closable ? /* @__PURE__ */ jsxs("div", { className: "klun-modal__actions", children: [
@@ -11055,7 +12009,7 @@ var ImageUpload = forwardRef(function ImageUpload2({
11055
12009
  shape = "circle",
11056
12010
  size = 96,
11057
12011
  label,
11058
- hint = "PNG or JPG, up to 5MB",
12012
+ hint: hintProp,
11059
12013
  onPick,
11060
12014
  onRemove,
11061
12015
  disabled = false,
@@ -11064,6 +12018,7 @@ var ImageUpload = forwardRef(function ImageUpload2({
11064
12018
  ...props
11065
12019
  }, ref) {
11066
12020
  const { imageUpload } = useLocale();
12021
+ const hint = hintProp ?? imageUpload.hint;
11067
12022
  const [over, setOver] = useState(false);
11068
12023
  const inputRef = useRef(null);
11069
12024
  return /* @__PURE__ */ jsxs("div", { ref, className: cx("klun-image-upload", className), style, ...props, children: [
@@ -11671,17 +12626,20 @@ var RichEditor = forwardRef(function RichEditor2({
11671
12626
  value,
11672
12627
  defaultValue = "",
11673
12628
  onChange,
11674
- placeholder = "Write something\u2026",
12629
+ placeholder: placeholderProp,
11675
12630
  disabled = false,
11676
12631
  hideToolbar = false,
11677
12632
  minHeight = 160,
11678
12633
  maxHeight,
11679
12634
  allowSource = true,
11680
- editorLabel = "Rich text editor",
12635
+ editorLabel: editorLabelProp,
11681
12636
  className,
11682
12637
  style,
11683
12638
  ...props
11684
12639
  }, ref) {
12640
+ const { richEditor: localeRich } = useLocale();
12641
+ const placeholder = placeholderProp ?? localeRich.placeholder;
12642
+ const editorLabel = editorLabelProp ?? localeRich.editorLabel;
11685
12643
  const editorRef = useRef(null);
11686
12644
  const [active, setActive] = useState([]);
11687
12645
  const [source, setSource] = useState(false);
@@ -11802,7 +12760,10 @@ var Select = forwardRef(function Select2({
11802
12760
  const rootRef = useRef(null);
11803
12761
  const s = useSelect({ children, value, defaultValue, disabled: disabled || loading, rootRef });
11804
12762
  const { select: selectLocale } = useLocale();
11805
- const fallbackLabel = !ariaLabel && !ariaLabelledBy && !s.selected && !placeholder ? selectLocale?.placeholder ?? "Select" : void 0;
12763
+ const generatedId = useId();
12764
+ const listboxId = `${generatedId}listbox`;
12765
+ const optionId = (index) => `${listboxId}-option-${index}`;
12766
+ const fallbackLabel = !ariaLabel && !ariaLabelledBy ? placeholder || selectLocale?.placeholder || "Select" : void 0;
11806
12767
  return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cx("klun-select", `klun-select--${size}`, className), style, children: [
11807
12768
  /* @__PURE__ */ jsxs(
11808
12769
  "button",
@@ -11812,8 +12773,11 @@ var Select = forwardRef(function Select2({
11812
12773
  disabled,
11813
12774
  onClick: s.toggle,
11814
12775
  onKeyDown: s.triggerKeyDown,
12776
+ role: "combobox",
11815
12777
  "aria-haspopup": "listbox",
11816
12778
  "aria-expanded": s.open,
12779
+ "aria-controls": s.open ? listboxId : void 0,
12780
+ "aria-activedescendant": s.open && s.active >= 0 ? optionId(s.active) : void 0,
11817
12781
  "aria-label": ariaLabel ?? fallbackLabel,
11818
12782
  "aria-labelledby": ariaLabelledBy,
11819
12783
  "data-open": s.open || void 0,
@@ -11853,6 +12817,8 @@ var Select = forwardRef(function Select2({
11853
12817
  s.open ? /* @__PURE__ */ jsx(
11854
12818
  SelectListbox,
11855
12819
  {
12820
+ id: listboxId,
12821
+ optionId,
11856
12822
  anchorRef: s.triggerRef,
11857
12823
  options: s.options,
11858
12824
  current: s.current,
@@ -11874,7 +12840,7 @@ var SelectMenu = forwardRef(
11874
12840
  leadingIcon,
11875
12841
  error = false,
11876
12842
  disabled = false,
11877
- align = "left",
12843
+ align = "start",
11878
12844
  className,
11879
12845
  style,
11880
12846
  ...props
@@ -12554,6 +13520,7 @@ function computeSizes(panels, containerPx) {
12554
13520
  return sizes;
12555
13521
  }
12556
13522
  var SplitterRoot = forwardRef(function Splitter({ layout = "horizontal", onResize, onResizeEnd, className, children, ...props }, forwardedRef) {
13523
+ const { a11y } = useLocale();
12557
13524
  const containerRef = useRef(null);
12558
13525
  const setRefs = useCallback(
12559
13526
  (node) => {
@@ -12772,7 +13739,7 @@ var SplitterRoot = forwardRef(function Splitter({ layout = "horizontal", onResiz
12772
13739
  {
12773
13740
  type: "button",
12774
13741
  className: "klun-splitter__collapse klun-splitter__collapse--start",
12775
- "aria-label": "Collapse start panel",
13742
+ "aria-label": a11y.collapseStart,
12776
13743
  tabIndex: -1,
12777
13744
  onPointerDown: (e) => e.stopPropagation(),
12778
13745
  onClick: () => collapseToggle(i, i),
@@ -12784,7 +13751,7 @@ var SplitterRoot = forwardRef(function Splitter({ layout = "horizontal", onResiz
12784
13751
  {
12785
13752
  type: "button",
12786
13753
  className: "klun-splitter__collapse klun-splitter__collapse--end",
12787
- "aria-label": "Collapse end panel",
13754
+ "aria-label": a11y.collapseEnd,
12788
13755
  tabIndex: -1,
12789
13756
  onPointerDown: (e) => e.stopPropagation(),
12790
13757
  onClick: () => collapseToggle(i, i + 1),
@@ -13016,6 +13983,7 @@ var PageHeader = forwardRef(function PageHeader2({
13016
13983
  children,
13017
13984
  ...props
13018
13985
  }, ref) {
13986
+ const { a11y } = useLocale();
13019
13987
  return /* @__PURE__ */ jsxs(
13020
13988
  "header",
13021
13989
  {
@@ -13037,7 +14005,7 @@ var PageHeader = forwardRef(function PageHeader2({
13037
14005
  appearance: "ghost",
13038
14006
  variant: "neutral",
13039
14007
  size: "small",
13040
- "aria-label": "Back",
14008
+ "aria-label": a11y.back,
13041
14009
  className: "klun-page-header__back",
13042
14010
  icon: /* @__PURE__ */ jsx("i", { className: "ri-arrow-left-line", "aria-hidden": true }),
13043
14011
  onClick: onBack
@@ -13229,7 +14197,7 @@ var Sidebar = forwardRef(function Sidebar2({
13229
14197
  onSelect,
13230
14198
  defaultExpandedKeys = [],
13231
14199
  searchable = false,
13232
- searchPlaceholder = "Search",
14200
+ searchPlaceholder: searchPlaceholderProp,
13233
14201
  onSearch,
13234
14202
  collapsed: collapsedProp,
13235
14203
  defaultCollapsed = false,
@@ -13237,6 +14205,8 @@ var Sidebar = forwardRef(function Sidebar2({
13237
14205
  className,
13238
14206
  ...props
13239
14207
  }, ref) {
14208
+ const { sidebar: localeSidebar } = useLocale();
14209
+ const searchPlaceholder = searchPlaceholderProp ?? localeSidebar.searchPlaceholder;
13240
14210
  const [internalNav, setInternalNav] = useState(defaultNavKey);
13241
14211
  const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
13242
14212
  const [expandedKeys, setExpandedKeys] = useState(
@@ -13272,7 +14242,7 @@ var Sidebar = forwardRef(function Sidebar2({
13272
14242
  "data-collapsed": collapsed ? "" : void 0,
13273
14243
  ...props,
13274
14244
  children: [
13275
- /* @__PURE__ */ jsxs("nav", { className: "klun-sidebar__rail", "aria-label": "Primary", children: [
14245
+ /* @__PURE__ */ jsxs("nav", { className: "klun-sidebar__rail", "aria-label": localeSidebar.primary, children: [
13276
14246
  brand != null && /* @__PURE__ */ jsx("div", { className: "klun-sidebar__brand", children: brand }),
13277
14247
  /* @__PURE__ */ jsx("div", { className: "klun-sidebar__nav", children: navItems.map((item) => /* @__PURE__ */ jsx(
13278
14248
  RailButton,
@@ -13319,6 +14289,7 @@ var Sidebar = forwardRef(function Sidebar2({
13319
14289
  type: "text",
13320
14290
  className: "klun-sidebar__search-input",
13321
14291
  placeholder: searchPlaceholder,
14292
+ "aria-label": searchPlaceholder,
13322
14293
  value: query,
13323
14294
  tabIndex: collapsed ? -1 : 0,
13324
14295
  onChange: (e) => {
@@ -13688,6 +14659,7 @@ var Wizard = forwardRef(function Wizard2({
13688
14659
  className,
13689
14660
  ...props
13690
14661
  }, ref) {
14662
+ const { wizard } = useLocale();
13691
14663
  const isControlled = current !== void 0;
13692
14664
  const [internal, setInternal] = useState(defaultCurrent);
13693
14665
  const idx = isControlled ? current : internal;
@@ -13732,7 +14704,7 @@ var Wizard = forwardRef(function Wizard2({
13732
14704
  className: "klun-wizard__nav",
13733
14705
  onClick: () => go(idx - 1),
13734
14706
  disabled: idx === 0,
13735
- children: "Back"
14707
+ children: wizard.back
13736
14708
  }
13737
14709
  ),
13738
14710
  !isLast ? /* @__PURE__ */ jsx(
@@ -13741,7 +14713,7 @@ var Wizard = forwardRef(function Wizard2({
13741
14713
  type: "button",
13742
14714
  className: "klun-wizard__nav klun-wizard__nav--primary",
13743
14715
  onClick: () => go(idx + 1),
13744
- children: "Next"
14716
+ children: wizard.next
13745
14717
  }
13746
14718
  ) : /* @__PURE__ */ jsx(
13747
14719
  "button",
@@ -13749,7 +14721,7 @@ var Wizard = forwardRef(function Wizard2({
13749
14721
  type: "button",
13750
14722
  className: "klun-wizard__nav klun-wizard__nav--primary",
13751
14723
  onClick: () => onFinish?.(),
13752
- children: "Finish"
14724
+ children: wizard.finish
13753
14725
  }
13754
14726
  )
13755
14727
  ] })
@@ -13836,13 +14808,14 @@ var INTENT_ICON = {
13836
14808
  warning: "ri-alert-line"
13837
14809
  };
13838
14810
  function ConfirmDialog({ opts, onClose }) {
14811
+ const { popconfirm } = useLocale();
13839
14812
  const {
13840
- title = "Are you sure?",
14813
+ title = popconfirm.title,
13841
14814
  description,
13842
14815
  icon,
13843
14816
  intent = "primary",
13844
- confirmText = "Confirm",
13845
- cancelText = "Cancel",
14817
+ confirmText = popconfirm.confirm,
14818
+ cancelText = popconfirm.cancel,
13846
14819
  requireInput,
13847
14820
  onConfirm
13848
14821
  } = opts;
@@ -13982,7 +14955,11 @@ function place(w, h, opts) {
13982
14955
  let top;
13983
14956
  if (opts.rect) {
13984
14957
  const r = opts.rect;
13985
- left = r.right - 4 + w > vw - GAP3 ? r.left - w + 4 : r.right - 4;
14958
+ if (opts.rtl) {
14959
+ left = r.left - w + 4 < GAP3 ? r.right - 4 : r.left - w + 4;
14960
+ } else {
14961
+ left = r.right - 4 + w > vw - GAP3 ? r.left - w + 4 : r.right - 4;
14962
+ }
13986
14963
  top = r.top - 4;
13987
14964
  } else {
13988
14965
  const p = opts.point ?? { x: 0, y: 0 };
@@ -14004,7 +14981,9 @@ function MenuPanel({ items: items2, width, className, point, anchorEl, autoActiv
14004
14981
  const el = ref.current;
14005
14982
  const w = el?.offsetWidth ?? width;
14006
14983
  const h = el?.offsetHeight ?? 0;
14007
- setPos(place(w, h, anchorEl ? { rect: anchorEl.getBoundingClientRect() } : { point }));
14984
+ const dirHost = anchorEl ?? ref.current ?? document.body;
14985
+ const rtl = getComputedStyle(dirHost).direction === "rtl";
14986
+ setPos(place(w, h, anchorEl ? { rect: anchorEl.getBoundingClientRect(), rtl } : { point }));
14008
14987
  }, [width, point?.x, point?.y, anchorEl, items2]);
14009
14988
  const move = useCallback(
14010
14989
  (dir) => {
@@ -14174,7 +15153,6 @@ var Drawer = forwardRef(function Drawer2({
14174
15153
  onClose,
14175
15154
  title,
14176
15155
  placement,
14177
- side,
14178
15156
  width = "50%",
14179
15157
  height = "50%",
14180
15158
  size = "default",
@@ -14192,22 +15170,24 @@ var Drawer = forwardRef(function Drawer2({
14192
15170
  ...props
14193
15171
  }, ref) {
14194
15172
  const { drawer } = useLocale();
14195
- const place2 = placement ?? side ?? "right";
15173
+ const place2 = placement ?? "right";
14196
15174
  const horizontal = place2 === "left" || place2 === "right";
14197
15175
  const prevOpen = useRef(open);
14198
- useEffect(() => {
14199
- if (!open) return;
14200
- const onKey = (e) => {
14201
- if (e.key === "Escape" && keyboard && closable) onClose?.();
14202
- };
14203
- document.addEventListener("keydown", onKey);
14204
- const prevOverflow = document.body.style.overflow;
14205
- document.body.style.overflow = "hidden";
14206
- return () => {
14207
- document.removeEventListener("keydown", onKey);
14208
- document.body.style.overflow = prevOverflow;
14209
- };
14210
- }, [open, keyboard, closable, onClose]);
15176
+ const scope = useOverlayScope({
15177
+ active: open,
15178
+ escapeEnabled: keyboard && closable,
15179
+ onEscape: onClose
15180
+ });
15181
+ const scopeRef = scope.ref;
15182
+ const titleId = `${useId()}title`;
15183
+ const attachPanelRef = useCallback(
15184
+ (el) => {
15185
+ scopeRef(el);
15186
+ if (typeof ref === "function") ref(el);
15187
+ else if (ref) ref.current = el;
15188
+ },
15189
+ [ref, scopeRef]
15190
+ );
14211
15191
  useEffect(() => {
14212
15192
  if (prevOpen.current !== open) {
14213
15193
  afterOpenChange?.(open);
@@ -14226,16 +15206,18 @@ var Drawer = forwardRef(function Drawer2({
14226
15206
  children: /* @__PURE__ */ jsxs(
14227
15207
  "div",
14228
15208
  {
14229
- ref,
15209
+ ref: attachPanelRef,
14230
15210
  role: "dialog",
14231
15211
  "aria-modal": "true",
15212
+ "aria-labelledby": title ? titleId : void 0,
15213
+ tabIndex: -1,
14232
15214
  onClick: (e) => e.stopPropagation(),
14233
15215
  className: cx("klun-drawer__panel", className),
14234
15216
  style: panelStyle,
14235
15217
  ...props,
14236
15218
  children: [
14237
15219
  /* @__PURE__ */ jsxs("div", { className: "klun-drawer__header", children: [
14238
- /* @__PURE__ */ jsx("div", { className: "klun-drawer__title", children: title }),
15220
+ /* @__PURE__ */ jsx("div", { className: "klun-drawer__title", id: title ? titleId : void 0, children: title }),
14239
15221
  extra ? /* @__PURE__ */ jsx("div", { className: "klun-drawer__extra", children: extra }) : null,
14240
15222
  closable ? /* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, "aria-label": drawer.close, className: "klun-drawer__close", children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M5 5l10 10M15 5L5 15", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) }) : null
14241
15223
  ] }),
@@ -14248,7 +15230,7 @@ var Drawer = forwardRef(function Drawer2({
14248
15230
  );
14249
15231
  });
14250
15232
  Drawer.displayName = "Drawer";
14251
- var Dropdown = forwardRef(function Dropdown2({ trigger, items: items2 = [], align = "left", width = 220, className, ...props }, ref) {
15233
+ var Dropdown = forwardRef(function Dropdown2({ trigger, items: items2 = [], align = "start", width = 220, className, ...props }, ref) {
14252
15234
  const [open, setOpen] = useState(false);
14253
15235
  const innerRef = useRef(null);
14254
15236
  useEffect(() => {
@@ -14523,6 +15505,7 @@ function ImageViewer({
14523
15505
  closeOnBackdrop = true,
14524
15506
  className
14525
15507
  }) {
15508
+ const { a11y, imageViewer, modal, pagination } = useLocale();
14526
15509
  const gallery = items2 && items2.length > 0 ? items2 : src != null ? [{ src, alt }] : [];
14527
15510
  const [innerIndex, setInnerIndex] = useState(0);
14528
15511
  const idx = index ?? innerIndex;
@@ -14611,20 +15594,20 @@ function ImageViewer({
14611
15594
  ] }),
14612
15595
  /* @__PURE__ */ jsxs("div", { className: "klun-image-viewer__tools", children: [
14613
15596
  zoomable ? /* @__PURE__ */ jsxs(Fragment, { children: [
14614
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Zoom out", onClick: () => setScale((s) => clampScale(s - 0.25)), children: /* @__PURE__ */ jsx("i", { className: "ri-zoom-out-line" }) }),
15597
+ /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": a11y.zoomOut, onClick: () => setScale((s) => clampScale(s - 0.25)), children: /* @__PURE__ */ jsx("i", { className: "ri-zoom-out-line" }) }),
14615
15598
  /* @__PURE__ */ jsxs("span", { className: "klun-image-viewer__zoom", children: [
14616
15599
  Math.round(scale * 100),
14617
15600
  "%"
14618
15601
  ] }),
14619
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Zoom in", onClick: () => setScale((s) => clampScale(s + 0.25)), children: /* @__PURE__ */ jsx("i", { className: "ri-zoom-in-line" }) })
15602
+ /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": a11y.zoomIn, onClick: () => setScale((s) => clampScale(s + 0.25)), children: /* @__PURE__ */ jsx("i", { className: "ri-zoom-in-line" }) })
14620
15603
  ] }) : null,
14621
- rotatable ? /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Rotate", onClick: () => setRot((r) => (r + 90) % 360), children: /* @__PURE__ */ jsx("i", { className: "ri-anticlockwise-line" }) }) : null,
14622
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Reset", onClick: reset, children: /* @__PURE__ */ jsx("i", { className: "ri-aspect-ratio-line" }) }),
14623
- onDownload ? /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Download", onClick: () => onDownload(current, safeIdx), children: /* @__PURE__ */ jsx("i", { className: "ri-download-2-line" }) }) : null,
14624
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx("i", { className: "ri-close-line" }) })
15604
+ rotatable ? /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": a11y.rotate, onClick: () => setRot((r) => (r + 90) % 360), children: /* @__PURE__ */ jsx("i", { className: "ri-anticlockwise-line" }) }) : null,
15605
+ /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": imageViewer.reset, onClick: reset, children: /* @__PURE__ */ jsx("i", { className: "ri-aspect-ratio-line" }) }),
15606
+ onDownload ? /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": imageViewer.download, onClick: () => onDownload(current, safeIdx), children: /* @__PURE__ */ jsx("i", { className: "ri-download-2-line" }) }) : null,
15607
+ /* @__PURE__ */ jsx("button", { type: "button", className: "klun-image-viewer__btn", "aria-label": modal.close, onClick: onClose, children: /* @__PURE__ */ jsx("i", { className: "ri-close-line" }) })
14625
15608
  ] })
14626
15609
  ] }),
14627
- gallery.length > 1 ? /* @__PURE__ */ 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__ */ jsx("i", { className: "ri-arrow-left-s-line" }) }) : null,
15610
+ gallery.length > 1 ? /* @__PURE__ */ 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__ */ jsx("i", { className: "ri-arrow-left-s-line" }) }) : null,
14628
15611
  /* @__PURE__ */ jsx("div", { className: "klun-image-viewer__stage", onMouseDown: (e) => e.stopPropagation(), onWheel, children: /* @__PURE__ */ jsx(
14629
15612
  "img",
14630
15613
  {
@@ -14637,7 +15620,7 @@ function ImageViewer({
14637
15620
  style: { transform: `translate(${pan.x}px, ${pan.y}px) scale(${scale}) rotate(${rot}deg)` }
14638
15621
  }
14639
15622
  ) }),
14640
- gallery.length > 1 ? /* @__PURE__ */ 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__ */ jsx("i", { className: "ri-arrow-right-s-line" }) }) : null
15623
+ gallery.length > 1 ? /* @__PURE__ */ 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__ */ jsx("i", { className: "ri-arrow-right-s-line" }) }) : null
14641
15624
  ]
14642
15625
  }
14643
15626
  ),
@@ -14820,5 +15803,5 @@ var Popconfirm = forwardRef(function Popconfirm2({
14820
15803
  Popconfirm.displayName = "Popconfirm";
14821
15804
 
14822
15805
  export { Accordion, ActivityHeatmap, ActorAvatar, Alert, AutoComplete, Avatar, AvatarGroup, Badge, Banner, BorderBeam, Breadcrumb, BulkAction, BulkActionBar, Button, ButtonGroup, CRON_PRESETS, CapabilityBanner, CappedNumberFlow, Card, Carousel, Cascader, CharacterCounter, ChartLegend, ChartTooltip, Checkbox, CheckboxCard, CheckboxGroup, Chip, CircularProgress, CodeViewer, Col, Collapse, ColorDot, ColorPicker, ColorSlider, CommandMenu, CompactNumberFlow, CompactSelect, CompactSelectForInput, ConfigProvider, Confirm, ContentLabel, ContextMenu2 as ContextMenu, CopyButton, CounterInput, CronEditor, CrossRefBadge, CurrencyNumberFlow, DatePicker, DateRangePicker, DateTimePicker, Descriptions, DiffViewer, DigitInput, Divider, DotSphere, Drawer, Dropdown, EmojiPicker, EmptyState, ExpiryCountdown, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldTitle, FileUpload, Flex, Form, FormItem, FormList, Format, GaugeBar, Grid, Hint, HorizontalFilter, HoverCard, HoverCardContent, HoverCardTrigger, ICON_GROUPS, IconPicker, ImageUpload, ImageViewer, InlineInput, InlineSelect, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kanban, Kbd, KeyIcon, LIST_GRID_BOTTOM_CLEARANCE, Label, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, List, ListGrid, ListGridBody, ListGridCell, ListGridHeader, ListGridHeaderCell, ListGridRow, ListItem, LiveDot, LogViewer, Markdown, Masonry, Menu, Message, Modal, Money, NavigationProgress, Notification, NumberFlow, PageHeader, Pagination, PasswordStrength, Popconfirm, Popover, ProgressBar, QUICK_EMOJIS, QuickEmojiPicker, Radio, RadioCard, RangeSlider, Rating, ReactionBar, RelativeTime, Result, RichEditor, RichEditorToolbar, Row, SegmentedControl, SegmentedProgress, Select, SelectMenu, ShimmerText, Sidebar, Skeleton, Slider, Space, Spinner2 as Spinner, Splitter2 as Splitter, SplitterPanel, StatCard, Statistic, StatusBadge, StatusDot, StepIndicator, Stepper, StepperContent, StepperDescription, StepperIndicator, StepperItem, StepperNav, StepperPanel, StepperSeparator, StepperTitle, StepperTrigger, Switch, Table, Tabs, Tag, Textarea, TimePicker, Timeline, Toast, Toaster, Toggle, Tooltip, Tree, UnicodeSpinner, VirtualTable, Wizard, arSA, buildHeatmapGrid, deDE, describeCron, enUS, esES, fmt, formatAvatarEmoji, frFR, groupReactions, idID, itIT, jaJP, koKR, localTodayIso, locales, nlNL, parseAvatarEmoji, parsePatch, plPL, primaryColorVars, ptBR, renderMarkdown, reorderRows, resolveMove, ruRU, summarizeHeatmap, toast, trTR, useBreakpoint, useConfig, useContextMenu, useForm, useLocale, useMappedSize, useMessage, useNotification, useSize, useStepItem, useStepper, viVN, zhCN, zhTW };
14823
- //# sourceMappingURL=chunk-WONPY7ZX.js.map
14824
- //# sourceMappingURL=chunk-WONPY7ZX.js.map
15806
+ //# sourceMappingURL=chunk-K5GUNGCR.js.map
15807
+ //# sourceMappingURL=chunk-K5GUNGCR.js.map