@keepkit/ui 0.24.0 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -50,7 +50,8 @@ function useKeepUrlSync({
50
50
  ...decoded.search ? { search: decoded.search } : { search: void 0 },
51
51
  ...decoded.tags ? { tags: decoded.tags } : { tags: void 0 },
52
52
  ...decoded.sort ? { sort: decoded.sort } : {},
53
- ...decoded.pagination ? { pagination: { ...previousQuery.pagination, ...decoded.pagination } } : {}
53
+ ...decoded.pagination ? { pagination: { ...previousQuery.pagination, ...decoded.pagination } } : {},
54
+ ...decoded.archiveScope !== void 0 ? { archived: decoded.archived, archiveScope: decoded.archiveScope } : decoded.archived !== void 0 ? { archived: decoded.archived, archiveScope: void 0 } : { archived: void 0, archiveScope: void 0 }
54
55
  }));
55
56
  };
56
57
  read();
@@ -190,7 +191,16 @@ var DE_LABELS = {
190
191
  backupRecoveryDescription: "Wenn lokale Synchronisierungsdaten besch\xE4digt sind, stellen Sie ein g\xFCltiges JSON-Backup wieder her.",
191
192
  syncPending: "\xC4nderungen warten auf die Synchronisierung.",
192
193
  syncSynced: "Alle \xC4nderungen sind synchronisiert.",
193
- syncConflict: "Einige \xC4nderungen ben\xF6tigen eine Konfliktl\xF6sung."
194
+ syncConflict: "Einige \xC4nderungen ben\xF6tigen eine Konfliktl\xF6sung.",
195
+ archiveScope: "Archivbereich",
196
+ archiveScopeActive: "Aktiv",
197
+ archiveScopeArchived: "Archiviert",
198
+ archiveScopeAll: "Alle Elemente",
199
+ undoReorder: "Sortierung r\xFCckg\xE4ngig machen",
200
+ toolbarStart: "Sammlungsaktionen",
201
+ toolbarQuery: "Suchen und sortieren",
202
+ toolbarFilters: "Filter",
203
+ toolbarEnd: "Zus\xE4tzliche Aktionen"
194
204
  };
195
205
 
196
206
  // src/locales/en.ts
@@ -289,7 +299,16 @@ var EN_LABELS = {
289
299
  backupRecoveryDescription: "If local sync data is damaged, restore a known-good JSON backup.",
290
300
  syncPending: "Changes are waiting to sync.",
291
301
  syncSynced: "All changes are synced.",
292
- syncConflict: "Some changes need conflict resolution."
302
+ syncConflict: "Some changes need conflict resolution.",
303
+ archiveScope: "Archive scope",
304
+ archiveScopeActive: "Active",
305
+ archiveScopeArchived: "Archived",
306
+ archiveScopeAll: "All items",
307
+ undoReorder: "Undo reorder",
308
+ toolbarStart: "Collection actions",
309
+ toolbarQuery: "Search and sort",
310
+ toolbarFilters: "Filters",
311
+ toolbarEnd: "Additional actions"
293
312
  };
294
313
 
295
314
  // src/locales/es.ts
@@ -388,7 +407,16 @@ var ES_LABELS = {
388
407
  backupRecoveryDescription: "Si los datos locales est\xE1n da\xF1ados, restaura una copia JSON v\xE1lida.",
389
408
  syncPending: "Hay cambios pendientes de sincronizaci\xF3n.",
390
409
  syncSynced: "Todos los cambios est\xE1n sincronizados.",
391
- syncConflict: "Algunos cambios necesitan resolver un conflicto."
410
+ syncConflict: "Algunos cambios necesitan resolver un conflicto.",
411
+ archiveScope: "\xC1mbito del archivo",
412
+ archiveScopeActive: "Activos",
413
+ archiveScopeArchived: "Archivados",
414
+ archiveScopeAll: "Todos los elementos",
415
+ undoReorder: "Deshacer ordenaci\xF3n",
416
+ toolbarStart: "Acciones de la colecci\xF3n",
417
+ toolbarQuery: "Buscar y ordenar",
418
+ toolbarFilters: "Filtros",
419
+ toolbarEnd: "Acciones adicionales"
392
420
  };
393
421
 
394
422
  // src/locales/fil.ts
@@ -487,7 +515,16 @@ var FIL_LABELS = {
487
515
  backupRecoveryDescription: "Kung sira ang lokal na sync data, mag-restore ng gumaganang JSON backup.",
488
516
  syncPending: "May mga pagbabagong naghihintay ng sync.",
489
517
  syncSynced: "Naka-sync na ang lahat ng pagbabago.",
490
- syncConflict: "May mga pagbabagong kailangang ayusin ang conflict."
518
+ syncConflict: "May mga pagbabagong kailangang ayusin ang conflict.",
519
+ archiveScope: "Saklaw ng archive",
520
+ archiveScopeActive: "Aktibo",
521
+ archiveScopeArchived: "Naka-archive",
522
+ archiveScopeAll: "Lahat ng item",
523
+ undoReorder: "I-undo ang pag-aayos",
524
+ toolbarStart: "Mga aksyon ng koleksyon",
525
+ toolbarQuery: "Maghanap at mag-ayos",
526
+ toolbarFilters: "Mga filter",
527
+ toolbarEnd: "Mga karagdagang aksyon"
491
528
  };
492
529
 
493
530
  // src/locales/fr.ts
@@ -586,7 +623,16 @@ var FR_LABELS = {
586
623
  backupRecoveryDescription: "Si les donn\xE9es locales sont endommag\xE9es, restaurez une sauvegarde JSON valide.",
587
624
  syncPending: "Des modifications attendent la synchronisation.",
588
625
  syncSynced: "Toutes les modifications sont synchronis\xE9es.",
589
- syncConflict: "Certaines modifications n\xE9cessitent une r\xE9solution de conflit."
626
+ syncConflict: "Certaines modifications n\xE9cessitent une r\xE9solution de conflit.",
627
+ archiveScope: "P\xE9rim\xE8tre des archives",
628
+ archiveScopeActive: "Actifs",
629
+ archiveScopeArchived: "Archiv\xE9s",
630
+ archiveScopeAll: "Tous les \xE9l\xE9ments",
631
+ undoReorder: "Annuler le r\xE9ordonnancement",
632
+ toolbarStart: "Actions de la collection",
633
+ toolbarQuery: "Recherche et tri",
634
+ toolbarFilters: "Filtres",
635
+ toolbarEnd: "Actions suppl\xE9mentaires"
590
636
  };
591
637
 
592
638
  // src/locales/id.ts
@@ -685,7 +731,16 @@ var ID_LABELS = {
685
731
  backupRecoveryDescription: "Jika data sinkronisasi lokal rusak, pulihkan cadangan JSON yang valid.",
686
732
  syncPending: "Ada perubahan yang menunggu sinkronisasi.",
687
733
  syncSynced: "Semua perubahan telah disinkronkan.",
688
- syncConflict: "Beberapa perubahan memerlukan penyelesaian konflik."
734
+ syncConflict: "Beberapa perubahan memerlukan penyelesaian konflik.",
735
+ archiveScope: "Cakupan arsip",
736
+ archiveScopeActive: "Aktif",
737
+ archiveScopeArchived: "Diarsipkan",
738
+ archiveScopeAll: "Semua item",
739
+ undoReorder: "Batalkan pengurutan",
740
+ toolbarStart: "Tindakan koleksi",
741
+ toolbarQuery: "Cari dan urutkan",
742
+ toolbarFilters: "Filter",
743
+ toolbarEnd: "Tindakan tambahan"
689
744
  };
690
745
 
691
746
  // src/locales/it.ts
@@ -784,7 +839,16 @@ var IT_LABELS = {
784
839
  backupRecoveryDescription: "Se i dati locali sono danneggiati, ripristina un backup JSON valido.",
785
840
  syncPending: "Ci sono modifiche in attesa di sincronizzazione.",
786
841
  syncSynced: "Tutte le modifiche sono sincronizzate.",
787
- syncConflict: "Alcune modifiche richiedono la risoluzione di un conflitto."
842
+ syncConflict: "Alcune modifiche richiedono la risoluzione di un conflitto.",
843
+ archiveScope: "Ambito archivio",
844
+ archiveScopeActive: "Attivi",
845
+ archiveScopeArchived: "Archiviati",
846
+ archiveScopeAll: "Tutti gli elementi",
847
+ undoReorder: "Annulla riordinamento",
848
+ toolbarStart: "Azioni della raccolta",
849
+ toolbarQuery: "Cerca e ordina",
850
+ toolbarFilters: "Filtri",
851
+ toolbarEnd: "Azioni aggiuntive"
788
852
  };
789
853
 
790
854
  // src/locales/ja.ts
@@ -883,7 +947,16 @@ var JA_LABELS = {
883
947
  backupRecoveryDescription: "\u30ED\u30FC\u30AB\u30EB\u306E\u540C\u671F\u30C7\u30FC\u30BF\u304C\u7834\u640D\u3057\u305F\u5834\u5408\u306F\u3001\u6B63\u5E38\u306AJSON\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u304B\u3089\u5FA9\u5143\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
884
948
  syncPending: "\u540C\u671F\u5F85\u3061\u306E\u5909\u66F4\u304C\u3042\u308A\u307E\u3059\u3002",
885
949
  syncSynced: "\u3059\u3079\u3066\u306E\u5909\u66F4\u3092\u540C\u671F\u3057\u307E\u3057\u305F\u3002",
886
- syncConflict: "\u7AF6\u5408\u3057\u3066\u3044\u308B\u5909\u66F4\u304C\u3042\u308A\u307E\u3059\u3002\u89E3\u6C7A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
950
+ syncConflict: "\u7AF6\u5408\u3057\u3066\u3044\u308B\u5909\u66F4\u304C\u3042\u308A\u307E\u3059\u3002\u89E3\u6C7A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
951
+ archiveScope: "\u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u7BC4\u56F2",
952
+ archiveScopeActive: "\u4FDD\u5B58\u4E2D",
953
+ archiveScopeArchived: "\u30A2\u30FC\u30AB\u30A4\u30D6\u6E08\u307F",
954
+ archiveScopeAll: "\u3059\u3079\u3066",
955
+ undoReorder: "\u4E26\u3073\u66FF\u3048\u3092\u5143\u306B\u623B\u3059",
956
+ toolbarStart: "\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u306E\u64CD\u4F5C",
957
+ toolbarQuery: "\u691C\u7D22\u3068\u4E26\u3073\u66FF\u3048",
958
+ toolbarFilters: "\u7D5E\u308A\u8FBC\u307F",
959
+ toolbarEnd: "\u8FFD\u52A0\u306E\u64CD\u4F5C"
887
960
  };
888
961
 
889
962
  // src/locales/ko.ts
@@ -982,7 +1055,16 @@ var KO_LABELS = {
982
1055
  backupRecoveryDescription: "\uB85C\uCEEC \uB3D9\uAE30\uD654 \uB370\uC774\uD130\uAC00 \uC190\uC0C1\uB41C \uACBD\uC6B0 \uC815\uC0C1\uC801\uC778 JSON \uBC31\uC5C5\uC744 \uBCF5\uC6D0\uD558\uC138\uC694.",
983
1056
  syncPending: "\uB3D9\uAE30\uD654 \uB300\uAE30 \uC911\uC778 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC788\uC2B5\uB2C8\uB2E4.",
984
1057
  syncSynced: "\uBAA8\uB4E0 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uB3D9\uAE30\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",
985
- syncConflict: "\uCDA9\uB3CC\uC744 \uD574\uACB0\uD574\uC57C \uD558\uB294 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC788\uC2B5\uB2C8\uB2E4."
1058
+ syncConflict: "\uCDA9\uB3CC\uC744 \uD574\uACB0\uD574\uC57C \uD558\uB294 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC788\uC2B5\uB2C8\uB2E4.",
1059
+ archiveScope: "\uBCF4\uAD00 \uBC94\uC704",
1060
+ archiveScopeActive: "\uD65C\uC131",
1061
+ archiveScopeArchived: "\uBCF4\uAD00\uB428",
1062
+ archiveScopeAll: "\uBAA8\uB4E0 \uD56D\uBAA9",
1063
+ undoReorder: "\uC815\uB82C \uC2E4\uD589 \uCDE8\uC18C",
1064
+ toolbarStart: "\uCEEC\uB809\uC158 \uC791\uC5C5",
1065
+ toolbarQuery: "\uAC80\uC0C9 \uBC0F \uC815\uB82C",
1066
+ toolbarFilters: "\uD544\uD130",
1067
+ toolbarEnd: "\uCD94\uAC00 \uC791\uC5C5"
986
1068
  };
987
1069
 
988
1070
  // src/locales/ms.ts
@@ -1081,7 +1163,16 @@ var MS_LABELS = {
1081
1163
  backupRecoveryDescription: "Jika data penyegerakan setempat rosak, pulihkan sandaran JSON yang sah.",
1082
1164
  syncPending: "Terdapat perubahan yang menunggu penyegerakan.",
1083
1165
  syncSynced: "Semua perubahan telah disegerakkan.",
1084
- syncConflict: "Sesetengah perubahan memerlukan penyelesaian konflik."
1166
+ syncConflict: "Sesetengah perubahan memerlukan penyelesaian konflik.",
1167
+ archiveScope: "Skop arkib",
1168
+ archiveScopeActive: "Aktif",
1169
+ archiveScopeArchived: "Diarkibkan",
1170
+ archiveScopeAll: "Semua item",
1171
+ undoReorder: "Buat asal susunan",
1172
+ toolbarStart: "Tindakan koleksi",
1173
+ toolbarQuery: "Cari dan susun",
1174
+ toolbarFilters: "Penapis",
1175
+ toolbarEnd: "Tindakan tambahan"
1085
1176
  };
1086
1177
 
1087
1178
  // src/locales/pt-BR.ts
@@ -1180,7 +1271,16 @@ var PT_BR_LABELS = {
1180
1271
  backupRecoveryDescription: "Se os dados locais estiverem corrompidos, restaure um backup JSON v\xE1lido.",
1181
1272
  syncPending: "H\xE1 altera\xE7\xF5es aguardando sincroniza\xE7\xE3o.",
1182
1273
  syncSynced: "Todas as altera\xE7\xF5es foram sincronizadas.",
1183
- syncConflict: "Algumas altera\xE7\xF5es precisam de resolu\xE7\xE3o de conflito."
1274
+ syncConflict: "Algumas altera\xE7\xF5es precisam de resolu\xE7\xE3o de conflito.",
1275
+ archiveScope: "Escopo do arquivo",
1276
+ archiveScopeActive: "Ativos",
1277
+ archiveScopeArchived: "Arquivados",
1278
+ archiveScopeAll: "Todos os itens",
1279
+ undoReorder: "Desfazer reordena\xE7\xE3o",
1280
+ toolbarStart: "A\xE7\xF5es da cole\xE7\xE3o",
1281
+ toolbarQuery: "Pesquisar e ordenar",
1282
+ toolbarFilters: "Filtros",
1283
+ toolbarEnd: "A\xE7\xF5es adicionais"
1184
1284
  };
1185
1285
 
1186
1286
  // src/locales/ru.ts
@@ -1279,7 +1379,16 @@ var RU_LABELS = {
1279
1379
  backupRecoveryDescription: "\u0415\u0441\u043B\u0438 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0438 \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u044B, \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0440\u0430\u0431\u043E\u0447\u0443\u044E JSON-\u043A\u043E\u043F\u0438\u044E.",
1280
1380
  syncPending: "\u0415\u0441\u0442\u044C \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F, \u043E\u0436\u0438\u0434\u0430\u044E\u0449\u0438\u0435 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0438.",
1281
1381
  syncSynced: "\u0412\u0441\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u044B.",
1282
- syncConflict: "\u041D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0442\u0440\u0435\u0431\u0443\u044E\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u0430."
1382
+ syncConflict: "\u041D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0442\u0440\u0435\u0431\u0443\u044E\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u0430.",
1383
+ archiveScope: "\u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0430\u0440\u0445\u0438\u0432\u0430",
1384
+ archiveScopeActive: "\u0410\u043A\u0442\u0438\u0432\u043D\u044B\u0435",
1385
+ archiveScopeArchived: "\u0412 \u0430\u0440\u0445\u0438\u0432\u0435",
1386
+ archiveScopeAll: "\u0412\u0441\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B",
1387
+ undoReorder: "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0443",
1388
+ toolbarStart: "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u0438",
1389
+ toolbarQuery: "\u041F\u043E\u0438\u0441\u043A \u0438 \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0430",
1390
+ toolbarFilters: "\u0424\u0438\u043B\u044C\u0442\u0440\u044B",
1391
+ toolbarEnd: "\u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F"
1283
1392
  };
1284
1393
 
1285
1394
  // src/locales/th.ts
@@ -1378,7 +1487,16 @@ var TH_LABELS = {
1378
1487
  backupRecoveryDescription: "\u0E2B\u0E32\u0E01\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E0B\u0E34\u0E07\u0E04\u0E4C\u0E43\u0E19\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E40\u0E2A\u0E35\u0E22\u0E2B\u0E32\u0E22 \u0E43\u0E2B\u0E49\u0E01\u0E39\u0E49\u0E04\u0E37\u0E19\u0E08\u0E32\u0E01\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E33\u0E23\u0E2D\u0E07 JSON \u0E17\u0E35\u0E48\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E44\u0E14\u0E49",
1379
1488
  syncPending: "\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E35\u0E48\u0E23\u0E2D\u0E01\u0E32\u0E23\u0E0B\u0E34\u0E07\u0E04\u0E4C",
1380
1489
  syncSynced: "\u0E0B\u0E34\u0E07\u0E04\u0E4C\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14\u0E41\u0E25\u0E49\u0E27",
1381
- syncConflict: "\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E35\u0E48\u0E15\u0E49\u0E2D\u0E07\u0E41\u0E01\u0E49\u0E44\u0E02\u0E02\u0E49\u0E2D\u0E02\u0E31\u0E14\u0E41\u0E22\u0E49\u0E07"
1490
+ syncConflict: "\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E35\u0E48\u0E15\u0E49\u0E2D\u0E07\u0E41\u0E01\u0E49\u0E44\u0E02\u0E02\u0E49\u0E2D\u0E02\u0E31\u0E14\u0E41\u0E22\u0E49\u0E07",
1491
+ archiveScope: "\u0E02\u0E2D\u0E1A\u0E40\u0E02\u0E15\u0E01\u0E32\u0E23\u0E40\u0E01\u0E47\u0E1A\u0E16\u0E32\u0E27\u0E23",
1492
+ archiveScopeActive: "\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E2D\u0E22\u0E39\u0E48",
1493
+ archiveScopeArchived: "\u0E40\u0E01\u0E47\u0E1A\u0E16\u0E32\u0E27\u0E23\u0E41\u0E25\u0E49\u0E27",
1494
+ archiveScopeAll: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14",
1495
+ undoReorder: "\u0E40\u0E25\u0E34\u0E01\u0E17\u0E33\u0E01\u0E32\u0E23\u0E08\u0E31\u0E14\u0E40\u0E23\u0E35\u0E22\u0E07",
1496
+ toolbarStart: "\u0E01\u0E32\u0E23\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23\u0E02\u0E2D\u0E07\u0E04\u0E2D\u0E25\u0E40\u0E25\u0E01\u0E0A\u0E31\u0E19",
1497
+ toolbarQuery: "\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E41\u0E25\u0E30\u0E08\u0E31\u0E14\u0E40\u0E23\u0E35\u0E22\u0E07",
1498
+ toolbarFilters: "\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07",
1499
+ toolbarEnd: "\u0E01\u0E32\u0E23\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E40\u0E15\u0E34\u0E21"
1382
1500
  };
1383
1501
 
1384
1502
  // src/locales/vi.ts
@@ -1477,7 +1595,16 @@ var VI_LABELS = {
1477
1595
  backupRecoveryDescription: "N\u1EBFu d\u1EEF li\u1EC7u \u0111\u1ED3ng b\u1ED9 c\u1EE5c b\u1ED9 b\u1ECB h\u1ECFng, h\xE3y kh\xF4i ph\u1EE5c b\u1EA3n sao l\u01B0u JSON h\u1EE3p l\u1EC7.",
1478
1596
  syncPending: "C\xF3 thay \u0111\u1ED5i \u0111ang ch\u1EDD \u0111\u1ED3ng b\u1ED9.",
1479
1597
  syncSynced: "T\u1EA5t c\u1EA3 thay \u0111\u1ED5i \u0111\xE3 \u0111\u01B0\u1EE3c \u0111\u1ED3ng b\u1ED9.",
1480
- syncConflict: "M\u1ED9t s\u1ED1 thay \u0111\u1ED5i c\u1EA7n gi\u1EA3i quy\u1EBFt xung \u0111\u1ED9t."
1598
+ syncConflict: "M\u1ED9t s\u1ED1 thay \u0111\u1ED5i c\u1EA7n gi\u1EA3i quy\u1EBFt xung \u0111\u1ED9t.",
1599
+ archiveScope: "Ph\u1EA1m vi l\u01B0u tr\u1EEF",
1600
+ archiveScopeActive: "\u0110ang ho\u1EA1t \u0111\u1ED9ng",
1601
+ archiveScopeArchived: "\u0110\xE3 l\u01B0u tr\u1EEF",
1602
+ archiveScopeAll: "T\u1EA5t c\u1EA3 m\u1EE5c",
1603
+ undoReorder: "Ho\xE0n t\xE1c s\u1EAFp x\u1EBFp",
1604
+ toolbarStart: "Thao t\xE1c b\u1ED9 s\u01B0u t\u1EADp",
1605
+ toolbarQuery: "T\xECm ki\u1EBFm v\xE0 s\u1EAFp x\u1EBFp",
1606
+ toolbarFilters: "B\u1ED9 l\u1ECDc",
1607
+ toolbarEnd: "Thao t\xE1c b\u1ED5 sung"
1481
1608
  };
1482
1609
 
1483
1610
  // src/locales/zh-Hans.ts
@@ -1576,7 +1703,16 @@ var ZH_HANS_LABELS = {
1576
1703
  backupRecoveryDescription: "\u5982\u679C\u672C\u5730\u540C\u6B65\u6570\u636E\u635F\u574F\uFF0C\u8BF7\u6062\u590D\u53EF\u7528\u7684 JSON \u5907\u4EFD\u3002",
1577
1704
  syncPending: "\u6709\u66F4\u6539\u7B49\u5F85\u540C\u6B65\u3002",
1578
1705
  syncSynced: "\u6240\u6709\u66F4\u6539\u5747\u5DF2\u540C\u6B65\u3002",
1579
- syncConflict: "\u6709\u4E9B\u66F4\u6539\u9700\u8981\u89E3\u51B3\u51B2\u7A81\u3002"
1706
+ syncConflict: "\u6709\u4E9B\u66F4\u6539\u9700\u8981\u89E3\u51B3\u51B2\u7A81\u3002",
1707
+ archiveScope: "\u5F52\u6863\u8303\u56F4",
1708
+ archiveScopeActive: "\u4FDD\u5B58\u4E2D",
1709
+ archiveScopeArchived: "\u5DF2\u5F52\u6863",
1710
+ archiveScopeAll: "\u5168\u90E8\u9879\u76EE",
1711
+ undoReorder: "\u64A4\u9500\u6392\u5E8F",
1712
+ toolbarStart: "\u96C6\u5408\u64CD\u4F5C",
1713
+ toolbarQuery: "\u641C\u7D22\u548C\u6392\u5E8F",
1714
+ toolbarFilters: "\u7B5B\u9009",
1715
+ toolbarEnd: "\u5176\u4ED6\u64CD\u4F5C"
1580
1716
  };
1581
1717
 
1582
1718
  // src/locales/zh-Hant.ts
@@ -1675,7 +1811,16 @@ var ZH_HANT_LABELS = {
1675
1811
  backupRecoveryDescription: "\u5982\u679C\u672C\u6A5F\u540C\u6B65\u8CC7\u6599\u640D\u6BC0\uFF0C\u8ACB\u9084\u539F\u53EF\u7528\u7684 JSON \u5099\u4EFD\u3002",
1676
1812
  syncPending: "\u6709\u8B8A\u66F4\u7B49\u5F85\u540C\u6B65\u3002",
1677
1813
  syncSynced: "\u6240\u6709\u8B8A\u66F4\u90FD\u5DF2\u540C\u6B65\u3002",
1678
- syncConflict: "\u6709\u4E9B\u8B8A\u66F4\u9700\u8981\u89E3\u6C7A\u885D\u7A81\u3002"
1814
+ syncConflict: "\u6709\u4E9B\u8B8A\u66F4\u9700\u8981\u89E3\u6C7A\u885D\u7A81\u3002",
1815
+ archiveScope: "\u5C01\u5B58\u7BC4\u570D",
1816
+ archiveScopeActive: "\u4FDD\u5B58\u4E2D",
1817
+ archiveScopeArchived: "\u5DF2\u5C01\u5B58",
1818
+ archiveScopeAll: "\u6240\u6709\u9805\u76EE",
1819
+ undoReorder: "\u5FA9\u539F\u6392\u5E8F",
1820
+ toolbarStart: "\u96C6\u5408\u64CD\u4F5C",
1821
+ toolbarQuery: "\u641C\u5C0B\u8207\u6392\u5E8F",
1822
+ toolbarFilters: "\u7BE9\u9078",
1823
+ toolbarEnd: "\u5176\u4ED6\u64CD\u4F5C"
1679
1824
  };
1680
1825
 
1681
1826
  // src/locales/index.ts
@@ -2505,7 +2650,7 @@ import {
2505
2650
  } from "react";
2506
2651
 
2507
2652
  // src/features/editor/KeepQuickEditor.tsx
2508
- import { useKeepContext as useKeepContext2, useKeepItem as useKeepItem3 } from "@keepkit/core/react";
2653
+ import { useKeepCollections, useKeepItem as useKeepItem3 } from "@keepkit/core/react";
2509
2654
  import {
2510
2655
  useCallback as useCallback2,
2511
2656
  useEffect as useEffect3,
@@ -2643,7 +2788,7 @@ function KeepQuickEditorView({
2643
2788
  focusScopeRef,
2644
2789
  ...props
2645
2790
  }) {
2646
- const context = useKeepContext2();
2791
+ const collections = useKeepCollections({ targetType: state.item.targetType, orderBy: "name" });
2647
2792
  const rootRef = useRef4(null);
2648
2793
  const noteLabel = useUiLabel("note");
2649
2794
  const tagsLabel = useUiLabel("tags");
@@ -2695,11 +2840,7 @@ function KeepQuickEditorView({
2695
2840
  onChange: (event) => state.setCollectionId(event.currentTarget.value || void 0),
2696
2841
  children: [
2697
2842
  /* @__PURE__ */ jsx7("option", { value: "", children: uncategorizedLabel }),
2698
- (collectionIds ?? [
2699
- ...new Set(
2700
- context.items.map((entry) => entry.collectionId).filter((id) => Boolean(id))
2701
- )
2702
- ].sort()).map((id) => /* @__PURE__ */ jsx7("option", { value: id, children: collectionLabels?.[id] ?? id }, id))
2843
+ (collectionIds ?? collections.map((collection) => collection.id)).map((id) => /* @__PURE__ */ jsx7("option", { value: id, children: collectionLabels?.[id] ?? id }, id))
2703
2844
  ]
2704
2845
  }
2705
2846
  )
@@ -2921,10 +3062,10 @@ function KeepSavePopoverPanel({
2921
3062
  }
2922
3063
 
2923
3064
  // src/features/actions/hooks/useKeepUndo.ts
2924
- import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
3065
+ import { useKeepContext as useKeepContext2 } from "@keepkit/core/react";
2925
3066
  import { useEffect as useEffect5, useState as useState5 } from "react";
2926
3067
  function useKeepUndo() {
2927
- const context = useKeepContext3();
3068
+ const context = useKeepContext2();
2928
3069
  const emitFeedback = useKeepUiFeedback();
2929
3070
  const restoredMessage = useUiLabel("restoredMessage");
2930
3071
  const { canUndo, startedAt, expiresAt } = context.undo;
@@ -2984,6 +3125,7 @@ function KeepUndo({ children, label, ...props }) {
2984
3125
 
2985
3126
  // src/features/collection/KeepCollection.tsx
2986
3127
  import { KeepErrorBoundary as KeepErrorBoundary2 } from "@keepkit/core/react";
3128
+ import { useEffect as useEffect10, useId as useId3, useState as useState14 } from "react";
2987
3129
 
2988
3130
  // src/features/query/KeepActiveFiltersSummary.tsx
2989
3131
  import {
@@ -3130,16 +3272,56 @@ function focusFilterFallback(scope) {
3130
3272
  }
3131
3273
  }
3132
3274
 
3133
- // src/features/query/KeepCollectionFilter.tsx
3134
- import { useKeepContext as useKeepContext4 } from "@keepkit/core/react";
3135
- import { useMemo as useMemo3, useState as useState6 } from "react";
3275
+ // src/features/query/KeepArchiveScopeSelect.tsx
3276
+ import { useState as useState6 } from "react";
3136
3277
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
3137
- function useCollectionOptions(collectionLabels, items) {
3138
- const ids = useMemo3(
3139
- () => [...new Set((items ?? []).map((item) => item.collectionId).filter((id) => Boolean(id)))].sort(),
3140
- [items]
3141
- );
3142
- return ids.map((id) => ({ id, label: collectionLabels?.[id] ?? id }));
3278
+ function KeepArchiveScopeSelect({
3279
+ value: controlledValue,
3280
+ defaultValue = "active",
3281
+ onValueChange,
3282
+ "aria-label": ariaLabel,
3283
+ ...props
3284
+ }) {
3285
+ const [internalValue, setInternalValue] = useState6(controlledValue ?? defaultValue);
3286
+ const value = controlledValue ?? internalValue;
3287
+ const label = useUiLabel("archiveScope");
3288
+ const activeLabel = useUiLabel("archiveScopeActive");
3289
+ const archivedLabel = useUiLabel("archiveScopeArchived");
3290
+ const allLabel = useUiLabel("archiveScopeAll");
3291
+ const handleChange = (next) => {
3292
+ if (next !== "active" && next !== "archived" && next !== "all") return;
3293
+ if (controlledValue === void 0) setInternalValue(next);
3294
+ onValueChange?.(next);
3295
+ };
3296
+ return /* @__PURE__ */ jsxs9("label", { "data-keepkit": "archive-scope", children: [
3297
+ /* @__PURE__ */ jsx11("span", { children: label }),
3298
+ /* @__PURE__ */ jsxs9(
3299
+ "select",
3300
+ {
3301
+ ...props,
3302
+ value,
3303
+ "aria-label": ariaLabel ?? label,
3304
+ "data-keep-action": "archive-scope",
3305
+ onChange: (event) => handleChange(event.currentTarget.value),
3306
+ children: [
3307
+ /* @__PURE__ */ jsx11("option", { value: "active", children: activeLabel }),
3308
+ /* @__PURE__ */ jsx11("option", { value: "archived", children: archivedLabel }),
3309
+ /* @__PURE__ */ jsx11("option", { value: "all", children: allLabel })
3310
+ ]
3311
+ }
3312
+ )
3313
+ ] });
3314
+ }
3315
+
3316
+ // src/features/query/KeepCollectionFilter.tsx
3317
+ import { useKeepCollections as useKeepCollections2, useKeepContext as useKeepContext3 } from "@keepkit/core/react";
3318
+ import { useState as useState7 } from "react";
3319
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
3320
+ function useCollectionOptions(collectionLabels, collections) {
3321
+ return collections.map((collection) => ({
3322
+ id: collection.id,
3323
+ label: collectionLabels?.[collection.id] ?? collection.name
3324
+ }));
3143
3325
  }
3144
3326
  function KeepCollectionSelect({
3145
3327
  item,
@@ -3151,10 +3333,11 @@ function KeepCollectionSelect({
3151
3333
  uncategorizedLabel,
3152
3334
  ...props
3153
3335
  }) {
3154
- const context = useKeepContext4();
3155
- const state = useState6(value ?? defaultValue ?? item.collectionId ?? "");
3336
+ const context = useKeepContext3();
3337
+ const state = useState7(value ?? defaultValue ?? item.collectionId ?? "");
3156
3338
  const selected = value ?? state[0];
3157
- const options = useCollectionOptions(collectionLabels, context.items);
3339
+ const collections = useKeepCollections2({ targetType: item.targetType, orderBy: "name" });
3340
+ const options = useCollectionOptions(collectionLabels, collections);
3158
3341
  const defaultUncategorizedLabel = useUiLabel("uncategorized");
3159
3342
  const uncategorized = uncategorizedLabel ?? defaultUncategorizedLabel;
3160
3343
  const handleChange = (next) => {
@@ -3164,7 +3347,7 @@ function KeepCollectionSelect({
3164
3347
  onChange?.(resolved);
3165
3348
  void context.moveToCollection(item.id, resolved);
3166
3349
  };
3167
- return /* @__PURE__ */ jsxs9(
3350
+ return /* @__PURE__ */ jsxs10(
3168
3351
  "select",
3169
3352
  {
3170
3353
  ...props,
@@ -3172,8 +3355,8 @@ function KeepCollectionSelect({
3172
3355
  onChange: (event) => handleChange(event.currentTarget.value),
3173
3356
  "data-keep-action": "move-collection",
3174
3357
  children: [
3175
- /* @__PURE__ */ jsx11("option", { value: "", children: uncategorized }),
3176
- options.map((option) => /* @__PURE__ */ jsx11("option", { value: option.id, children: option.label }, option.id))
3358
+ /* @__PURE__ */ jsx12("option", { value: "", children: uncategorized }),
3359
+ options.map((option) => /* @__PURE__ */ jsx12("option", { value: option.id, children: option.label }, option.id))
3177
3360
  ]
3178
3361
  }
3179
3362
  );
@@ -3188,10 +3371,10 @@ function KeepCollectionFilter({
3188
3371
  uncategorizedLabel,
3189
3372
  ...props
3190
3373
  }) {
3191
- const context = useKeepContext4();
3192
- const [internalValue, setInternalValue] = useState6(value ?? defaultValue ?? "");
3374
+ const [internalValue, setInternalValue] = useState7(value ?? defaultValue ?? "");
3193
3375
  const selected = value ?? internalValue;
3194
- const options = useCollectionOptions(collectionLabels, context.items);
3376
+ const collections = useKeepCollections2({ orderBy: "name" });
3377
+ const options = useCollectionOptions(collectionLabels, collections);
3195
3378
  const collectionLabel = useUiLabel("collection");
3196
3379
  const defaultAllLabel = useUiLabel("allCollections");
3197
3380
  const defaultUncategorizedLabel = useUiLabel("uncategorized");
@@ -3203,9 +3386,9 @@ function KeepCollectionFilter({
3203
3386
  onValueChange?.(resolved);
3204
3387
  onChange?.(resolved);
3205
3388
  };
3206
- return /* @__PURE__ */ jsxs9("label", { "data-keepkit": "collection-filter", children: [
3207
- /* @__PURE__ */ jsx11("span", { children: collectionLabel }),
3208
- /* @__PURE__ */ jsxs9(
3389
+ return /* @__PURE__ */ jsxs10("label", { "data-keepkit": "collection-filter", children: [
3390
+ /* @__PURE__ */ jsx12("span", { children: collectionLabel }),
3391
+ /* @__PURE__ */ jsxs10(
3209
3392
  "select",
3210
3393
  {
3211
3394
  ...props,
@@ -3213,9 +3396,9 @@ function KeepCollectionFilter({
3213
3396
  onChange: (event) => handleChange(event.currentTarget.value),
3214
3397
  "data-keep-action": "filter-collection",
3215
3398
  children: [
3216
- /* @__PURE__ */ jsx11("option", { value: "", children: all }),
3217
- /* @__PURE__ */ jsx11("option", { value: "__uncategorized__", children: uncategorized }),
3218
- options.map((option) => /* @__PURE__ */ jsx11("option", { value: option.id, children: option.label }, option.id))
3399
+ /* @__PURE__ */ jsx12("option", { value: "", children: all }),
3400
+ /* @__PURE__ */ jsx12("option", { value: "__uncategorized__", children: uncategorized }),
3401
+ options.map((option) => /* @__PURE__ */ jsx12("option", { value: option.id, children: option.label }, option.id))
3219
3402
  ]
3220
3403
  }
3221
3404
  )
@@ -3227,10 +3410,10 @@ import { isValidElement as isValidElement3 } from "react";
3227
3410
 
3228
3411
  // src/features/query/hooks/useKeepTagFilter.ts
3229
3412
  import { useKeepList as useKeepList2 } from "@keepkit/core/react";
3230
- import { useCallback as useCallback4, useMemo as useMemo4, useState as useState7 } from "react";
3413
+ import { useCallback as useCallback4, useMemo as useMemo3, useState as useState8 } from "react";
3231
3414
  function useKeepTagFilter(options) {
3232
3415
  const { query, controlledValue, defaultValue, onChange, onValueChange } = options;
3233
- const [uncontrolledValue, setUncontrolledValue] = useState7(defaultValue);
3416
+ const [uncontrolledValue, setUncontrolledValue] = useState8(defaultValue);
3234
3417
  const resolvedValue = controlledValue ?? uncontrolledValue;
3235
3418
  const list = useKeepList2({
3236
3419
  ...query,
@@ -3244,7 +3427,7 @@ function useKeepTagFilter(options) {
3244
3427
  },
3245
3428
  [controlledValue, onChange, onValueChange]
3246
3429
  );
3247
- const state = useMemo4(
3430
+ const state = useMemo3(
3248
3431
  () => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),
3249
3432
  [list.tagCounts, list.tags, resolvedValue, select]
3250
3433
  );
@@ -3256,7 +3439,7 @@ function useKeepTagFilter(options) {
3256
3439
  }
3257
3440
 
3258
3441
  // src/features/query/KeepTagFilter.tsx
3259
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
3442
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3260
3443
  function KeepTagFilter({
3261
3444
  query,
3262
3445
  value: controlledValue,
@@ -3274,9 +3457,9 @@ function KeepTagFilter({
3274
3457
  }) {
3275
3458
  const view = useKeepTagFilter({ query, controlledValue, defaultValue, onChange, onValueChange });
3276
3459
  const contentChildren = asChild && isValidElement3(children) ? void 0 : children;
3277
- const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs10("fieldset", { children: [
3278
- /* @__PURE__ */ jsx12("legend", { children: ariaLabel ?? view.labels.aria }),
3279
- /* @__PURE__ */ jsx12(
3460
+ const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs11("fieldset", { children: [
3461
+ /* @__PURE__ */ jsx13("legend", { children: ariaLabel ?? view.labels.aria }),
3462
+ /* @__PURE__ */ jsx13(
3280
3463
  "button",
3281
3464
  {
3282
3465
  type: "button",
@@ -3286,7 +3469,7 @@ function KeepTagFilter({
3286
3469
  children: allLabel ?? view.labels.all
3287
3470
  }
3288
3471
  ),
3289
- view.state.tags.map((tag) => /* @__PURE__ */ jsxs10(
3472
+ view.state.tags.map((tag) => /* @__PURE__ */ jsxs11(
3290
3473
  "button",
3291
3474
  {
3292
3475
  type: "button",
@@ -3295,7 +3478,7 @@ function KeepTagFilter({
3295
3478
  onClick: () => view.state.select(tag),
3296
3479
  children: [
3297
3480
  renderTag ? renderTag(tag, view.state.tagCounts[tag] ?? 0, view.state.value === tag) : tag,
3298
- /* @__PURE__ */ jsxs10("span", { children: [
3481
+ /* @__PURE__ */ jsxs11("span", { children: [
3299
3482
  " (",
3300
3483
  view.state.tagCounts[tag] ?? 0,
3301
3484
  ")"
@@ -3321,10 +3504,10 @@ function KeepTagFilter({
3321
3504
  }
3322
3505
 
3323
3506
  // src/features/query/hooks/useQueryControls.ts
3324
- import { useEffect as useEffect6, useState as useState8 } from "react";
3507
+ import { useEffect as useEffect6, useState as useState9 } from "react";
3325
3508
  function useKeepSearchInput(options) {
3326
3509
  const { controlledValue, defaultValue, debounceMs, onValueChange } = options;
3327
- const [uncontrolledValue, setUncontrolledValue] = useState8(defaultValue);
3510
+ const [uncontrolledValue, setUncontrolledValue] = useState9(defaultValue);
3328
3511
  const value = controlledValue ?? uncontrolledValue;
3329
3512
  useEffect6(() => {
3330
3513
  if (!onValueChange) return;
@@ -3345,7 +3528,7 @@ function useKeepSearchInput(options) {
3345
3528
  }
3346
3529
  function useKeepSortSelect(options) {
3347
3530
  const { controlledValue, defaultValue, onValueChange } = options;
3348
- const [uncontrolledValue, setUncontrolledValue] = useState8(defaultValue);
3531
+ const [uncontrolledValue, setUncontrolledValue] = useState9(defaultValue);
3349
3532
  const value = controlledValue ?? uncontrolledValue;
3350
3533
  return {
3351
3534
  value,
@@ -3393,7 +3576,7 @@ function getVisiblePages(currentPage, pageCount, maxPageButtons) {
3393
3576
  }
3394
3577
 
3395
3578
  // src/features/query/query-controls.tsx
3396
- import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3579
+ import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3397
3580
  function KeepSearchInput({
3398
3581
  value: controlledValue,
3399
3582
  defaultValue = "",
@@ -3404,7 +3587,7 @@ function KeepSearchInput({
3404
3587
  ...props
3405
3588
  }) {
3406
3589
  const view = useKeepSearchInput({ controlledValue, defaultValue, debounceMs, onValueChange });
3407
- return /* @__PURE__ */ jsx13(
3590
+ return /* @__PURE__ */ jsx14(
3408
3591
  "input",
3409
3592
  {
3410
3593
  ...props,
@@ -3429,13 +3612,13 @@ function KeepSortSelect({
3429
3612
  ...props
3430
3613
  }) {
3431
3614
  const view = useKeepSortSelect({ controlledValue, defaultValue, onValueChange });
3432
- const options = children ?? /* @__PURE__ */ jsxs11(Fragment6, { children: [
3433
- /* @__PURE__ */ jsx13("option", { value: "updatedAt:desc", children: view.labels.updatedNewest }),
3434
- /* @__PURE__ */ jsx13("option", { value: "updatedAt:asc", children: view.labels.updatedOldest }),
3435
- /* @__PURE__ */ jsx13("option", { value: "savedAt:desc", children: view.labels.savedNewest }),
3436
- /* @__PURE__ */ jsx13("option", { value: "savedAt:asc", children: view.labels.savedOldest })
3615
+ const options = children ?? /* @__PURE__ */ jsxs12(Fragment6, { children: [
3616
+ /* @__PURE__ */ jsx14("option", { value: "updatedAt:desc", children: view.labels.updatedNewest }),
3617
+ /* @__PURE__ */ jsx14("option", { value: "updatedAt:asc", children: view.labels.updatedOldest }),
3618
+ /* @__PURE__ */ jsx14("option", { value: "savedAt:desc", children: view.labels.savedNewest }),
3619
+ /* @__PURE__ */ jsx14("option", { value: "savedAt:asc", children: view.labels.savedOldest })
3437
3620
  ] });
3438
- return /* @__PURE__ */ jsx13(
3621
+ return /* @__PURE__ */ jsx14(
3439
3622
  "select",
3440
3623
  {
3441
3624
  ...props,
@@ -3467,9 +3650,9 @@ function KeepPagination({
3467
3650
  "data-state": view.pageCount > 1 ? "active" : "idle"
3468
3651
  };
3469
3652
  if (render)
3470
- return /* @__PURE__ */ jsx13("nav", { ...navProps, children: render({ page: view.currentPage, pageCount: view.pageCount, goToPage: view.goToPage }) });
3471
- return /* @__PURE__ */ jsxs11("nav", { ...navProps, children: [
3472
- /* @__PURE__ */ jsx13(
3653
+ return /* @__PURE__ */ jsx14("nav", { ...navProps, children: render({ page: view.currentPage, pageCount: view.pageCount, goToPage: view.goToPage }) });
3654
+ return /* @__PURE__ */ jsxs12("nav", { ...navProps, children: [
3655
+ /* @__PURE__ */ jsx14(
3473
3656
  "button",
3474
3657
  {
3475
3658
  type: "button",
@@ -3479,7 +3662,7 @@ function KeepPagination({
3479
3662
  children: view.labels.previous
3480
3663
  }
3481
3664
  ),
3482
- view.visiblePages.map((nextPage) => /* @__PURE__ */ jsx13(
3665
+ view.visiblePages.map((nextPage) => /* @__PURE__ */ jsx14(
3483
3666
  "button",
3484
3667
  {
3485
3668
  type: "button",
@@ -3491,7 +3674,7 @@ function KeepPagination({
3491
3674
  },
3492
3675
  nextPage
3493
3676
  )),
3494
- /* @__PURE__ */ jsx13(
3677
+ /* @__PURE__ */ jsx14(
3495
3678
  "button",
3496
3679
  {
3497
3680
  type: "button",
@@ -3506,13 +3689,14 @@ function KeepPagination({
3506
3689
 
3507
3690
  // src/features/collection/hooks/useKeepCollection.ts
3508
3691
  import { useKeepList as useKeepList3 } from "@keepkit/core/react";
3509
- import { useMemo as useMemo5, useState as useState9 } from "react";
3692
+ import { useEffect as useEffect7, useMemo as useMemo4, useState as useState10 } from "react";
3510
3693
  function useKeepCollection({
3511
3694
  query,
3512
3695
  pageSize,
3513
3696
  urlSync,
3514
3697
  urlAdapter,
3515
- features
3698
+ features,
3699
+ archiveScope
3516
3700
  }) {
3517
3701
  const enabled = {
3518
3702
  search: true,
@@ -3526,15 +3710,23 @@ function useKeepCollection({
3526
3710
  archive: false,
3527
3711
  ...features
3528
3712
  };
3529
- const [searchValue, setSearchValue] = useState9(query.search?.query ?? "");
3530
- const [sort, setSort] = useState9(query.sort ?? { by: "updatedAt", direction: "desc" });
3531
- const [activeTags, setActiveTags] = useState9(query.tags ?? []);
3532
- const [activeCollection, setActiveCollection] = useState9(query.collectionId);
3533
- const [page, setPage] = useState9(query.pagination?.page ?? 1);
3713
+ const [searchValue, setSearchValue] = useState10(query.search?.query ?? "");
3714
+ const [sort, setSort] = useState10(query.sort ?? { by: "updatedAt", direction: "desc" });
3715
+ const [activeTags, setActiveTags] = useState10(query.tags ?? []);
3716
+ const [activeCollection, setActiveCollection] = useState10(query.collectionId);
3717
+ const [page, setPage] = useState10(query.pagination?.page ?? 1);
3718
+ const [activeArchiveScope, setActiveArchiveScope] = useState10(
3719
+ archiveScope ?? query.archiveScope ?? scopeFromArchived(query.archived)
3720
+ );
3721
+ useEffect7(() => {
3722
+ if (archiveScope !== void 0) setActiveArchiveScope(archiveScope);
3723
+ }, [archiveScope]);
3534
3724
  const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
3535
- const resolvedQuery = useMemo5(
3725
+ const resolvedQuery = useMemo4(
3536
3726
  () => ({
3537
3727
  ...query,
3728
+ archiveScope: activeArchiveScope,
3729
+ archived: activeArchiveScope === "active" ? false : activeArchiveScope === "archived" ? true : void 0,
3538
3730
  search: enabled.search ? { ...query.search, query: searchValue } : query.search,
3539
3731
  sort: enabled.sort ? sort : query.sort,
3540
3732
  tags: activeTags.length > 0 ? activeTags : void 0,
@@ -3552,7 +3744,8 @@ function useKeepCollection({
3552
3744
  query,
3553
3745
  resolvedPageSize,
3554
3746
  searchValue,
3555
- sort
3747
+ sort,
3748
+ activeArchiveScope
3556
3749
  ]
3557
3750
  );
3558
3751
  useKeepUrlSync({
@@ -3564,19 +3757,21 @@ function useKeepCollection({
3564
3757
  setSort(next.sort ?? { by: "updatedAt", direction: "desc" });
3565
3758
  setActiveTags(next.tags ?? []);
3566
3759
  setActiveCollection(next.collectionId);
3760
+ setActiveArchiveScope(next.archiveScope ?? scopeFromArchived(next.archived));
3567
3761
  setPage(next.pagination?.page ?? 1);
3568
3762
  },
3569
3763
  options: typeof urlSync === "object" ? urlSync : {},
3570
3764
  adapter: urlAdapter
3571
3765
  });
3572
3766
  const list = useKeepList3(resolvedQuery);
3573
- const allState = useKeepList3({});
3767
+ const allState = useKeepList3({ archiveScope: "all" });
3574
3768
  return {
3575
3769
  enabled,
3576
3770
  searchValue,
3577
3771
  sortValue: sortToValue(sort),
3578
3772
  activeTags,
3579
3773
  activeCollection,
3774
+ archiveScope: activeArchiveScope,
3580
3775
  resolvedPageSize,
3581
3776
  resolvedQuery,
3582
3777
  list,
@@ -3597,6 +3792,10 @@ function useKeepCollection({
3597
3792
  setActiveCollection(value);
3598
3793
  setPage(1);
3599
3794
  },
3795
+ setArchiveScope: (value) => {
3796
+ setActiveArchiveScope(value);
3797
+ setPage(1);
3798
+ },
3600
3799
  removeTag: (tagToRemove) => {
3601
3800
  setActiveTags((current) => current.filter((tag) => tag !== tagToRemove));
3602
3801
  setPage(1);
@@ -3610,6 +3809,9 @@ function useKeepCollection({
3610
3809
  setPage
3611
3810
  };
3612
3811
  }
3812
+ function scopeFromArchived(archived) {
3813
+ return archived === true ? "archived" : "active";
3814
+ }
3613
3815
 
3614
3816
  // src/features/collection/KeepList.tsx
3615
3817
  import { KeepErrorBoundary } from "@keepkit/core/react";
@@ -3621,8 +3823,10 @@ import {
3621
3823
  createElement as createElement2,
3622
3824
  isValidElement as isValidElement4,
3623
3825
  useContext as useContext3,
3624
- useEffect as useEffect7,
3625
- useState as useState11
3826
+ useEffect as useEffect8,
3827
+ useId as useId2,
3828
+ useRef as useRef7,
3829
+ useState as useState12
3626
3830
  } from "react";
3627
3831
 
3628
3832
  // src/features/item/hooks/useKeepItemStatusBadge.ts
@@ -3665,10 +3869,10 @@ function getDisplayStatus(status) {
3665
3869
  }
3666
3870
 
3667
3871
  // src/features/item/KeepItemStatusBadge.tsx
3668
- import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3872
+ import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3669
3873
  function KeepItemStatusBadge({ status = "available", label, className, ...props }) {
3670
3874
  const view = useKeepItemStatusBadge(status);
3671
- return /* @__PURE__ */ jsxs12(
3875
+ return /* @__PURE__ */ jsxs13(
3672
3876
  "span",
3673
3877
  {
3674
3878
  ...props,
@@ -3679,14 +3883,14 @@ function KeepItemStatusBadge({ status = "available", label, className, ...props
3679
3883
  "data-status": status,
3680
3884
  "data-item-status": view.resolvedStatus,
3681
3885
  children: [
3682
- /* @__PURE__ */ jsx14(StatusIcon, { name: view.icon }),
3683
- /* @__PURE__ */ jsx14("span", { "data-status-label": "true", children: label ?? view.statusLabel })
3886
+ /* @__PURE__ */ jsx15(StatusIcon, { name: view.icon }),
3887
+ /* @__PURE__ */ jsx15("span", { "data-status-label": "true", children: label ?? view.statusLabel })
3684
3888
  ]
3685
3889
  }
3686
3890
  );
3687
3891
  }
3688
3892
  function StatusIcon({ name }) {
3689
- return /* @__PURE__ */ jsxs12(
3893
+ return /* @__PURE__ */ jsxs13(
3690
3894
  "svg",
3691
3895
  {
3692
3896
  "data-status-icon": name,
@@ -3701,18 +3905,18 @@ function StatusIcon({ name }) {
3701
3905
  "aria-hidden": "true",
3702
3906
  focusable: "false",
3703
3907
  children: [
3704
- name === "check" ? /* @__PURE__ */ jsx14("path", { d: "m5 12 4 4L19 6" }) : null,
3705
- name === "clock" ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3706
- /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "8" }),
3707
- /* @__PURE__ */ jsx14("path", { d: "M12 7v5l3 2" })
3908
+ name === "check" ? /* @__PURE__ */ jsx15("path", { d: "m5 12 4 4L19 6" }) : null,
3909
+ name === "clock" ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
3910
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "8" }),
3911
+ /* @__PURE__ */ jsx15("path", { d: "M12 7v5l3 2" })
3708
3912
  ] }) : null,
3709
- name === "ban" ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3710
- /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "8" }),
3711
- /* @__PURE__ */ jsx14("path", { d: "m6.5 6.5 11 11" })
3913
+ name === "ban" ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
3914
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "8" }),
3915
+ /* @__PURE__ */ jsx15("path", { d: "m6.5 6.5 11 11" })
3712
3916
  ] }) : null,
3713
- name === "lock" ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3714
- /* @__PURE__ */ jsx14("rect", { x: "5", y: "10", width: "14", height: "10", rx: "2" }),
3715
- /* @__PURE__ */ jsx14("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
3917
+ name === "lock" ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
3918
+ /* @__PURE__ */ jsx15("rect", { x: "5", y: "10", width: "14", height: "10", rx: "2" }),
3919
+ /* @__PURE__ */ jsx15("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
3716
3920
  ] }) : null
3717
3921
  ]
3718
3922
  }
@@ -3720,16 +3924,16 @@ function StatusIcon({ name }) {
3720
3924
  }
3721
3925
 
3722
3926
  // src/features/status/hooks/useKeepStaleNotice.ts
3723
- import { useKeepContext as useKeepContext5 } from "@keepkit/core/react";
3724
- import { useState as useState10 } from "react";
3927
+ import { useKeepContext as useKeepContext4 } from "@keepkit/core/react";
3928
+ import { useState as useState11 } from "react";
3725
3929
  function useKeepStaleNotice({ item, onRetry, onRemoved }) {
3726
- const context = useKeepContext5();
3930
+ const context = useKeepContext4();
3727
3931
  const emitFeedback = useKeepUiFeedback();
3728
3932
  const removedMessage = useUiLabel("removedMessage");
3729
3933
  const restoredMessage = useUiLabel("restoredMessage");
3730
3934
  const undoLabel = useUiLabel("undo");
3731
- const [isRetrying, setIsRetrying] = useState10(false);
3732
- const [error, setError] = useState10(null);
3935
+ const [isRetrying, setIsRetrying] = useState11(false);
3936
+ const [error, setError] = useState11(null);
3733
3937
  async function retry() {
3734
3938
  setError(null);
3735
3939
  setIsRetrying(true);
@@ -3775,7 +3979,7 @@ function useKeepStaleNotice({ item, onRetry, onRemoved }) {
3775
3979
  };
3776
3980
  }
3777
3981
  function useKeepPruneStale({ statuses, onPruned }) {
3778
- const context = useKeepContext5();
3982
+ const context = useKeepContext4();
3779
3983
  const emitFeedback = useKeepUiFeedback();
3780
3984
  const staleItems = context.items.filter((item) => item.status && statuses.includes(item.status));
3781
3985
  const staleIds = staleItems.map((item) => item.id);
@@ -3809,7 +4013,7 @@ function useKeepPruneStale({ statuses, onPruned }) {
3809
4013
  }
3810
4014
 
3811
4015
  // src/features/status/KeepStaleNotice.tsx
3812
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
4016
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3813
4017
  function KeepStaleNotice({
3814
4018
  item,
3815
4019
  onRetry,
@@ -3821,11 +4025,11 @@ function KeepStaleNotice({
3821
4025
  ...props
3822
4026
  }) {
3823
4027
  const view = useKeepStaleNotice({ item, onRetry, onRemoved });
3824
- return /* @__PURE__ */ jsxs13("aside", { ...props, className, "data-keepkit": "stale-notice", "data-state": view.error ? "error" : "stale", children: [
3825
- /* @__PURE__ */ jsx15(KeepItemStatusBadge, { status: view.status }),
3826
- children ?? (item.statusReason ? /* @__PURE__ */ jsx15("p", { children: item.statusReason }) : null),
3827
- /* @__PURE__ */ jsxs13("div", { children: [
3828
- /* @__PURE__ */ jsx15(
4028
+ return /* @__PURE__ */ jsxs14("aside", { ...props, className, "data-keepkit": "stale-notice", "data-state": view.error ? "error" : "stale", children: [
4029
+ /* @__PURE__ */ jsx16(KeepItemStatusBadge, { status: view.status }),
4030
+ children ?? (item.statusReason ? /* @__PURE__ */ jsx16("p", { children: item.statusReason }) : null),
4031
+ /* @__PURE__ */ jsxs14("div", { children: [
4032
+ /* @__PURE__ */ jsx16(
3829
4033
  "button",
3830
4034
  {
3831
4035
  type: "button",
@@ -3835,7 +4039,7 @@ function KeepStaleNotice({
3835
4039
  children: retryLabel ?? view.labels.retry
3836
4040
  }
3837
4041
  ),
3838
- /* @__PURE__ */ jsx15(
4042
+ /* @__PURE__ */ jsx16(
3839
4043
  "button",
3840
4044
  {
3841
4045
  type: "button",
@@ -3846,7 +4050,7 @@ function KeepStaleNotice({
3846
4050
  }
3847
4051
  )
3848
4052
  ] }),
3849
- view.error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
4053
+ view.error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
3850
4054
  ] });
3851
4055
  }
3852
4056
  function KeepPruneStaleButton({
@@ -3858,7 +4062,7 @@ function KeepPruneStaleButton({
3858
4062
  ...props
3859
4063
  }) {
3860
4064
  const view = useKeepPruneStale({ statuses, onPruned });
3861
- return /* @__PURE__ */ jsx15(
4065
+ return /* @__PURE__ */ jsx16(
3862
4066
  "button",
3863
4067
  {
3864
4068
  ...props,
@@ -3971,7 +4175,7 @@ function getDisplayStatus2(status) {
3971
4175
  }
3972
4176
 
3973
4177
  // src/features/item/KeepItemCard.tsx
3974
- import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
4178
+ import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3975
4179
  var KeepItemCardContext = createContext3(null);
3976
4180
  function useKeepItemCardCompound(part) {
3977
4181
  const context = useContext3(KeepItemCardContext);
@@ -3999,6 +4203,9 @@ function KeepItemCardRoot({
3999
4203
  showSaveButton = true,
4000
4204
  showPinButton = false,
4001
4205
  showArchiveButton = false,
4206
+ showEditButton = false,
4207
+ onEdit,
4208
+ editSlot,
4002
4209
  saveButtonLabels,
4003
4210
  asChild = false,
4004
4211
  href: hrefOption,
@@ -4008,6 +4215,7 @@ function KeepItemCardRoot({
4008
4215
  linkTargetAttribute,
4009
4216
  linkRel,
4010
4217
  highlightQuery,
4218
+ cardVariant = "outlined",
4011
4219
  className,
4012
4220
  ...rootProps
4013
4221
  }) {
@@ -4025,6 +4233,14 @@ function KeepItemCardRoot({
4025
4233
  const contextQuery = useKeepSearchQuery();
4026
4234
  const searchQuery = highlightQuery ?? contextQuery;
4027
4235
  const contentChildren = asChild && isValidElement4(children) ? void 0 : children;
4236
+ const [isEditOpen, setEditOpen] = useState12(false);
4237
+ const editTriggerRef = useRef7(null);
4238
+ const editPanelId = useId2();
4239
+ const editLabel = useUiLabel("editSavedItem");
4240
+ const closeEdit = () => setEditOpen(false);
4241
+ useEffect8(() => {
4242
+ if (!isEditOpen) editTriggerRef.current?.focus();
4243
+ }, [isEditOpen]);
4028
4244
  function renderLink(content) {
4029
4245
  if (!view.href || !view.isAvailable) return content;
4030
4246
  const linkProps = {
@@ -4034,17 +4250,17 @@ function KeepItemCardRoot({
4034
4250
  onClick: (event) => onOpen?.(item, event),
4035
4251
  children: content
4036
4252
  };
4037
- return LinkComponent ? /* @__PURE__ */ jsx16(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx16("a", { ...linkProps });
4253
+ return LinkComponent ? /* @__PURE__ */ jsx17(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx17("a", { ...linkProps });
4038
4254
  }
4039
4255
  function renderTitle(content) {
4040
4256
  if (linkTarget !== "title") return content;
4041
4257
  if (view.isAvailable) return renderLink(content);
4042
- return view.href ? /* @__PURE__ */ jsx16("span", { "aria-disabled": "true", "data-link-disabled": "true", children: content }) : content;
4258
+ return view.href ? /* @__PURE__ */ jsx17("span", { "aria-disabled": "true", "data-link-disabled": "true", children: content }) : content;
4043
4259
  }
4044
4260
  const resolvedImageProps = view.imageProps ? { ...view.imageProps, alt: imageAlt ?? view.imageProps.alt } : void 0;
4045
4261
  const imageSource = resolvedImageProps?.src;
4046
- const [imageStatus, setImageStatus] = useState11(imageSource ? "loading" : "error");
4047
- useEffect7(() => {
4262
+ const [imageStatus, setImageStatus] = useState12(imageSource ? "loading" : "error");
4263
+ useEffect8(() => {
4048
4264
  setImageStatus(imageSource ? "loading" : "error");
4049
4265
  }, [imageSource]);
4050
4266
  let image = null;
@@ -4062,24 +4278,44 @@ function KeepItemCardRoot({
4062
4278
  setImageStatus("error");
4063
4279
  }
4064
4280
  };
4065
- image = renderImage?.(imagePropsWithHandlers, item) ?? (ImageComponent ? /* @__PURE__ */ jsx16(ImageComponent, { ...imagePropsWithHandlers }) : /* @__PURE__ */ jsx16("img", { ...imagePropsWithHandlers, alt: imagePropsWithHandlers.alt }));
4281
+ image = renderImage?.(imagePropsWithHandlers, item) ?? (ImageComponent ? /* @__PURE__ */ jsx17(ImageComponent, { ...imagePropsWithHandlers }) : /* @__PURE__ */ jsx17("img", { ...imagePropsWithHandlers, alt: imagePropsWithHandlers.alt }));
4066
4282
  }
4067
4283
  const tags = showTags ? item.tags ?? [] : [];
4068
4284
  const renderedTags = showTags && tags.length > 0 ? renderTags?.(tags, item) ?? null : null;
4069
- const meta = showSavedAt ? /* @__PURE__ */ jsxs14("div", { "data-card-meta": true, children: [
4070
- /* @__PURE__ */ jsxs14("span", { children: [
4285
+ const meta = showSavedAt ? /* @__PURE__ */ jsxs15("div", { "data-card-meta": true, children: [
4286
+ /* @__PURE__ */ jsxs15("span", { children: [
4071
4287
  view.labels.savedAt,
4072
4288
  ":"
4073
4289
  ] }),
4074
4290
  " ",
4075
- /* @__PURE__ */ jsx16("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
4291
+ /* @__PURE__ */ jsx17("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
4076
4292
  ] }) : null;
4077
- const error = view.itemState.error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: getErrorMessage3(view.itemState.error, view.labels.error) }) : null;
4078
- const actions = view.statusLabel ? /* @__PURE__ */ jsx16(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs14(Fragment8, { children: [
4079
- showSaveButton ? /* @__PURE__ */ jsx16(KeepItemCardSave, {}) : null,
4080
- showPinButton ? /* @__PURE__ */ jsx16(KeepItemCardPin, {}) : null,
4081
- showArchiveButton ? /* @__PURE__ */ jsx16(KeepItemCardArchive, {}) : null,
4082
- /* @__PURE__ */ jsx16(KeepItemCardRemove, {})
4293
+ const error = view.itemState.error ? /* @__PURE__ */ jsx17("p", { role: "alert", children: getErrorMessage3(view.itemState.error, view.labels.error) }) : null;
4294
+ const actions = view.statusLabel ? /* @__PURE__ */ jsx17(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs15(Fragment8, { children: [
4295
+ showEditButton ? /* @__PURE__ */ jsxs15(Fragment8, { children: [
4296
+ /* @__PURE__ */ jsx17(
4297
+ "button",
4298
+ {
4299
+ ref: editTriggerRef,
4300
+ type: "button",
4301
+ "data-keep-action": "edit",
4302
+ "aria-label": editLabel,
4303
+ "aria-haspopup": "dialog",
4304
+ "aria-expanded": isEditOpen,
4305
+ "aria-controls": editPanelId,
4306
+ onClick: () => {
4307
+ onEdit?.(item);
4308
+ setEditOpen(true);
4309
+ },
4310
+ children: editLabel
4311
+ }
4312
+ ),
4313
+ isEditOpen ? /* @__PURE__ */ jsx17("div", { id: editPanelId, role: "dialog", "aria-label": editLabel, "data-keepkit": "item-edit-dialog", children: editSlot ? editSlot(item, closeEdit) : /* @__PURE__ */ jsx17(KeepQuickEditor, { item: view.itemState.item ?? item, onClose: closeEdit }) }) : null
4314
+ ] }) : null,
4315
+ showSaveButton ? /* @__PURE__ */ jsx17(KeepItemCardSave, {}) : null,
4316
+ showPinButton ? /* @__PURE__ */ jsx17(KeepItemCardPin, {}) : null,
4317
+ showArchiveButton ? /* @__PURE__ */ jsx17(KeepItemCardArchive, {}) : null,
4318
+ /* @__PURE__ */ jsx17(KeepItemCardRemove, {})
4083
4319
  ] });
4084
4320
  const compoundValue = {
4085
4321
  item,
@@ -4100,12 +4336,12 @@ function KeepItemCardRoot({
4100
4336
  remove: view.remove,
4101
4337
  isMutating: view.itemState.isMutating,
4102
4338
  saveAriaLabel: `${view.labels.remove} ${String(view.resolvedTitle)}`,
4103
- renderText: (content) => /* @__PURE__ */ jsx16(KeepHighlight, { query: searchQuery, children: content })
4339
+ renderText: (content) => /* @__PURE__ */ jsx17(KeepHighlight, { query: searchQuery, children: content })
4104
4340
  };
4105
- const defaultBody = /* @__PURE__ */ jsxs14(Fragment8, { children: [
4106
- /* @__PURE__ */ jsx16(KeepItemCardMedia, {}),
4107
- /* @__PURE__ */ jsx16(KeepItemCardContent, {}),
4108
- /* @__PURE__ */ jsx16(KeepItemCardActions, {})
4341
+ const defaultBody = /* @__PURE__ */ jsxs15(Fragment8, { children: [
4342
+ /* @__PURE__ */ jsx17(KeepItemCardMedia, {}),
4343
+ /* @__PURE__ */ jsx17(KeepItemCardContent, {}),
4344
+ /* @__PURE__ */ jsx17(KeepItemCardActions, {})
4109
4345
  ] });
4110
4346
  const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? defaultBody;
4111
4347
  const linkedBody = linkTarget === "card" && view.isAvailable ? renderLink(body) : body;
@@ -4121,23 +4357,24 @@ function KeepItemCardRoot({
4121
4357
  "data-state": view.itemState.error ? "error" : view.itemState.isSaved ? "saved" : "unsaved",
4122
4358
  "data-status": item.status ?? "available",
4123
4359
  "data-item-status": view.displayStatus,
4360
+ "data-card-variant": cardVariant !== "outlined" ? cardVariant : void 0,
4124
4361
  "data-loading": view.itemState.isMutating ? "true" : void 0
4125
4362
  },
4126
4363
  linkedBody,
4127
4364
  "KeepItemCard"
4128
4365
  );
4129
- return /* @__PURE__ */ jsx16(KeepItemCardContext.Provider, { value: compoundValue, children: root });
4366
+ return /* @__PURE__ */ jsx17(KeepItemCardContext.Provider, { value: compoundValue, children: root });
4130
4367
  }
4131
4368
  function KeepItemCardMedia({ children, fallback, ...props }) {
4132
4369
  const context = useKeepItemCardCompound("Media");
4133
- return /* @__PURE__ */ jsx16("div", { ...props, "data-keep-card-part": "media", "data-media-status": context.imageStatus, "data-aspect-ratio": "1/1", children: children ?? context.image ?? /* @__PURE__ */ jsx16("span", { role: "img", "aria-label": context.fallbackLabel, "data-keep-card-fallback": "true", children: fallback ?? /* @__PURE__ */ jsx16(KeepMediaPlaceholderIcon, {}) }) });
4370
+ return /* @__PURE__ */ jsx17("div", { ...props, "data-keep-card-part": "media", "data-media-status": context.imageStatus, "data-aspect-ratio": "1/1", children: children ?? context.image ?? /* @__PURE__ */ jsx17("span", { role: "img", "aria-label": context.fallbackLabel, "data-keep-card-fallback": "true", children: fallback ?? /* @__PURE__ */ jsx17(KeepMediaPlaceholderIcon, {}) }) });
4134
4371
  }
4135
4372
  function KeepItemCardContent({ children, ...props }) {
4136
4373
  const context = useKeepItemCardCompound("Content");
4137
- return /* @__PURE__ */ jsx16("div", { ...props, "data-keep-card-part": "content", children: children === void 0 ? /* @__PURE__ */ jsxs14(Fragment8, { children: [
4138
- /* @__PURE__ */ jsx16(KeepItemCardTitle, {}),
4374
+ return /* @__PURE__ */ jsx17("div", { ...props, "data-keep-card-part": "content", children: children === void 0 ? /* @__PURE__ */ jsxs15(Fragment8, { children: [
4375
+ /* @__PURE__ */ jsx17(KeepItemCardTitle, {}),
4139
4376
  context.meta,
4140
- /* @__PURE__ */ jsx16(KeepItemCardTags, {}),
4377
+ /* @__PURE__ */ jsx17(KeepItemCardTags, {}),
4141
4378
  context.error
4142
4379
  ] }) : context.renderText(children) });
4143
4380
  }
@@ -4150,8 +4387,8 @@ function KeepItemCardTitle({ as = "h3", children, ...props }) {
4150
4387
  );
4151
4388
  }
4152
4389
  function KeepMediaPlaceholderIcon() {
4153
- return /* @__PURE__ */ jsxs14("svg", { "data-media-fallback-icon": "true", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
4154
- /* @__PURE__ */ jsx16(
4390
+ return /* @__PURE__ */ jsxs15("svg", { "data-media-fallback-icon": "true", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
4391
+ /* @__PURE__ */ jsx17(
4155
4392
  "path",
4156
4393
  {
4157
4394
  d: "M4 5.5A1.5 1.5 0 0 1 5.5 4h13A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5h-13A1.5 1.5 0 0 1 4 18.5v-13Z",
@@ -4159,23 +4396,23 @@ function KeepMediaPlaceholderIcon() {
4159
4396
  stroke: "currentColor"
4160
4397
  }
4161
4398
  ),
4162
- /* @__PURE__ */ jsx16("circle", { cx: "9", cy: "9", r: "1.5", fill: "currentColor" }),
4163
- /* @__PURE__ */ jsx16("path", { d: "m5.5 18 4.5-4.5 3 3 2-2L19 18", fill: "none", stroke: "currentColor" })
4399
+ /* @__PURE__ */ jsx17("circle", { cx: "9", cy: "9", r: "1.5", fill: "currentColor" }),
4400
+ /* @__PURE__ */ jsx17("path", { d: "m5.5 18 4.5-4.5 3 3 2-2L19 18", fill: "none", stroke: "currentColor" })
4164
4401
  ] });
4165
4402
  }
4166
4403
  function KeepItemCardTags({ children, ...props }) {
4167
4404
  const context = useKeepItemCardCompound("Tags");
4168
4405
  if (children === void 0 && context.renderedTags) return context.renderedTags;
4169
4406
  if (children === void 0 && context.tags.length === 0) return null;
4170
- return /* @__PURE__ */ jsx16("ul", { ...props, "aria-label": props["aria-label"] ?? context.tagsLabel, "data-keep-card-part": "tags", children: children ?? context.tags.map((tag) => /* @__PURE__ */ jsx16("li", { children: tag }, tag)) });
4407
+ return /* @__PURE__ */ jsx17("ul", { ...props, "aria-label": props["aria-label"] ?? context.tagsLabel, "data-keep-card-part": "tags", children: children ?? context.tags.map((tag) => /* @__PURE__ */ jsx17("li", { children: tag }, tag)) });
4171
4408
  }
4172
4409
  function KeepItemCardActions({ children, ...props }) {
4173
4410
  const context = useKeepItemCardCompound("Actions");
4174
- return /* @__PURE__ */ jsx16("div", { ...props, "data-keep-card-part": "actions", children: children ?? context.actions });
4411
+ return /* @__PURE__ */ jsx17("div", { ...props, "data-keep-card-part": "actions", children: children ?? context.actions });
4175
4412
  }
4176
4413
  function KeepItemCardSave({ labels, getAriaLabel, ...props }) {
4177
4414
  const context = useKeepItemCardCompound("Save");
4178
- return /* @__PURE__ */ jsx16(
4415
+ return /* @__PURE__ */ jsx17(
4179
4416
  KeepButton,
4180
4417
  {
4181
4418
  ...props,
@@ -4188,7 +4425,7 @@ function KeepItemCardSave({ labels, getAriaLabel, ...props }) {
4188
4425
  }
4189
4426
  function KeepItemCardRemove({ children, disabled, onClick, ...props }) {
4190
4427
  const context = useKeepItemCardCompound("Remove");
4191
- return /* @__PURE__ */ jsx16(
4428
+ return /* @__PURE__ */ jsx17(
4192
4429
  "button",
4193
4430
  {
4194
4431
  ...props,
@@ -4205,19 +4442,19 @@ function KeepItemCardRemove({ children, disabled, onClick, ...props }) {
4205
4442
  }
4206
4443
  function KeepItemCardPin({ children, ...props }) {
4207
4444
  const context = useKeepItemCardCompound("Pin");
4208
- return /* @__PURE__ */ jsx16(KeepPinButton, { ...props, item: context.item, children });
4445
+ return /* @__PURE__ */ jsx17(KeepPinButton, { ...props, item: context.item, children });
4209
4446
  }
4210
4447
  function KeepItemCardArchive({
4211
4448
  children,
4212
4449
  ...props
4213
4450
  }) {
4214
4451
  const context = useKeepItemCardCompound("Archive");
4215
- return /* @__PURE__ */ jsx16(KeepArchiveButton, { ...props, item: context.item, children });
4452
+ return /* @__PURE__ */ jsx17(KeepArchiveButton, { ...props, item: context.item, children });
4216
4453
  }
4217
4454
  function KeepItemCardCollectionBadge({ children, ...props }) {
4218
4455
  const context = useKeepItemCardCompound("CollectionBadge");
4219
4456
  if (!context.item.collectionId) return null;
4220
- return /* @__PURE__ */ jsx16("span", { ...props, "data-keep-card-part": "collection-badge", children: children ?? context.collectionLabel });
4457
+ return /* @__PURE__ */ jsx17("span", { ...props, "data-keep-card-part": "collection-badge", children: children ?? context.collectionLabel });
4221
4458
  }
4222
4459
  var KeepItemCard = Object.assign(KeepItemCardRoot, {
4223
4460
  Media: KeepItemCardMedia,
@@ -4232,12 +4469,12 @@ var KeepItemCard = Object.assign(KeepItemCardRoot, {
4232
4469
  CollectionBadge: KeepItemCardCollectionBadge
4233
4470
  });
4234
4471
  function KeepItemCardSkeleton({ layout = "list", ...props }) {
4235
- return /* @__PURE__ */ jsxs14("article", { ...props, "aria-hidden": "true", "data-keepkit": "card-skeleton", "data-layout": layout, "data-state": "loading", children: [
4236
- /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "media" }),
4237
- /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "title" }),
4238
- /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "meta" }),
4239
- /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "tag" }),
4240
- /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "tag" })
4472
+ return /* @__PURE__ */ jsxs15("article", { ...props, "aria-hidden": "true", "data-keepkit": "card-skeleton", "data-layout": layout, "data-state": "loading", children: [
4473
+ /* @__PURE__ */ jsx17("span", { "data-skeleton-part": "media" }),
4474
+ /* @__PURE__ */ jsx17("span", { "data-skeleton-part": "title" }),
4475
+ /* @__PURE__ */ jsx17("span", { "data-skeleton-part": "meta" }),
4476
+ /* @__PURE__ */ jsx17("span", { "data-skeleton-part": "tag" }),
4477
+ /* @__PURE__ */ jsx17("span", { "data-skeleton-part": "tag" })
4241
4478
  ] });
4242
4479
  }
4243
4480
  function formatSavedAt(timestamp) {
@@ -4249,7 +4486,7 @@ function getErrorMessage3(error, fallback) {
4249
4486
 
4250
4487
  // src/features/status/KeepEmptyState.tsx
4251
4488
  import { isValidElement as isValidElement5 } from "react";
4252
- import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4489
+ import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4253
4490
  function KeepEmptyState({
4254
4491
  title,
4255
4492
  description,
@@ -4268,10 +4505,10 @@ function KeepEmptyState({
4268
4505
  );
4269
4506
  const clearLabel = useUiLabel("clearFilters");
4270
4507
  const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
4271
- const body = contentChildren ?? /* @__PURE__ */ jsxs15(Fragment9, { children: [
4272
- /* @__PURE__ */ jsx17("h2", { children: title ?? defaultTitle }),
4273
- description ?? /* @__PURE__ */ jsx17("p", { children: defaultDescription }),
4274
- action ?? (resolvedVariant === "empty-filtered" && onClearFilters ? /* @__PURE__ */ jsx17("button", { type: "button", "data-keep-action": "clear-filters", onClick: onClearFilters, children: clearLabel }) : null)
4508
+ const body = contentChildren ?? /* @__PURE__ */ jsxs16(Fragment9, { children: [
4509
+ /* @__PURE__ */ jsx18("h2", { children: title ?? defaultTitle }),
4510
+ description ?? /* @__PURE__ */ jsx18("p", { children: defaultDescription }),
4511
+ action ?? (resolvedVariant === "empty-filtered" && onClearFilters ? /* @__PURE__ */ jsx18("button", { type: "button", "data-keep-action": "clear-filters", onClick: onClearFilters, children: clearLabel }) : null)
4275
4512
  ] });
4276
4513
  return renderRoot(
4277
4514
  asChild,
@@ -4297,9 +4534,9 @@ function useKeepListView(query) {
4297
4534
  }
4298
4535
 
4299
4536
  // src/features/collection/hooks/useRovingTabIndex.ts
4300
- import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef7 } from "react";
4537
+ import { useCallback as useCallback5, useEffect as useEffect9, useRef as useRef8 } from "react";
4301
4538
  function useRovingTabIndex() {
4302
- const ref = useRef7(null);
4539
+ const ref = useRef8(null);
4303
4540
  const getItems = useCallback5(() => {
4304
4541
  const root = ref.current;
4305
4542
  if (!root) return [];
@@ -4317,7 +4554,7 @@ function useRovingTabIndex() {
4317
4554
  item.tabIndex = index === activeIndex ? 0 : -1;
4318
4555
  });
4319
4556
  }, [getItems]);
4320
- useEffect8(() => {
4557
+ useEffect9(() => {
4321
4558
  const root = ref.current;
4322
4559
  if (!root) return;
4323
4560
  syncTabIndices();
@@ -4361,13 +4598,124 @@ function useRovingTabIndex() {
4361
4598
  return { ref, onKeyDown, onFocusCapture };
4362
4599
  }
4363
4600
 
4601
+ // src/features/collection/KeepReorderableList.tsx
4602
+ import { useState as useState13 } from "react";
4603
+ import { jsx as jsx19 } from "react/jsx-runtime";
4604
+ function KeepReorderableList({
4605
+ items,
4606
+ onReorder,
4607
+ renderItem,
4608
+ itemLabel = (_item, index) => `Move item ${index + 1}`,
4609
+ ...props
4610
+ }) {
4611
+ const [draggedId, setDraggedId] = useState13(null);
4612
+ const [dropTargetIndex, setDropTargetIndex] = useState13(null);
4613
+ const ids = items.map((item) => item.id);
4614
+ function commit(nextIds) {
4615
+ void onReorder(nextIds);
4616
+ }
4617
+ function move(index, targetIndex) {
4618
+ if (targetIndex < 0 || targetIndex >= ids.length || targetIndex === index) return;
4619
+ const next = [...ids];
4620
+ const [id] = next.splice(index, 1);
4621
+ if (id === void 0) return;
4622
+ next.splice(targetIndex, 0, id);
4623
+ commit(next);
4624
+ }
4625
+ function moveToInsertion(index, insertionIndex) {
4626
+ const next = [...ids];
4627
+ const [id] = next.splice(index, 1);
4628
+ if (id === void 0) return;
4629
+ const targetIndex = Math.min(
4630
+ Math.max(0, insertionIndex > index ? insertionIndex - 1 : insertionIndex),
4631
+ next.length
4632
+ );
4633
+ next.splice(targetIndex, 0, id);
4634
+ if (next[index] === id) return;
4635
+ commit(next);
4636
+ }
4637
+ return /* @__PURE__ */ jsx19("ul", { ...props, "data-keepkit": "reorderable-list", children: items.map((item, index) => {
4638
+ const moveUp = () => move(index, index - 1);
4639
+ const moveDown = () => move(index, index + 1);
4640
+ const onHandleKeyDown = (event) => {
4641
+ if (event.key === " ") {
4642
+ event.preventDefault();
4643
+ if (draggedId === item.id) {
4644
+ setDraggedId(null);
4645
+ setDropTargetIndex(null);
4646
+ } else {
4647
+ setDraggedId(item.id);
4648
+ setDropTargetIndex(index);
4649
+ }
4650
+ } else if (event.key === "ArrowUp") {
4651
+ event.preventDefault();
4652
+ moveUp();
4653
+ } else if (event.key === "ArrowDown") {
4654
+ event.preventDefault();
4655
+ moveDown();
4656
+ }
4657
+ };
4658
+ const state = {
4659
+ index,
4660
+ isDragging: draggedId === item.id,
4661
+ moveUp,
4662
+ moveDown,
4663
+ dragHandleProps: {
4664
+ role: "button",
4665
+ tabIndex: 0,
4666
+ draggable: true,
4667
+ "data-drag-handle": "true",
4668
+ "aria-label": itemLabel(item, index),
4669
+ "aria-grabbed": draggedId === item.id,
4670
+ onDragStart: () => {
4671
+ setDraggedId(item.id);
4672
+ setDropTargetIndex(index);
4673
+ },
4674
+ onDragEnd: () => {
4675
+ setDraggedId(null);
4676
+ setDropTargetIndex(null);
4677
+ },
4678
+ onKeyDown: onHandleKeyDown
4679
+ }
4680
+ };
4681
+ return /* @__PURE__ */ jsx19(
4682
+ "li",
4683
+ {
4684
+ "data-reorder-index": index,
4685
+ "data-dragging": draggedId === item.id ? "true" : void 0,
4686
+ "data-drop-target": draggedId && draggedId !== item.id ? dropTargetIndex === index ? "before" : dropTargetIndex === index + 1 ? "after" : void 0 : void 0,
4687
+ onDragOver: (event) => {
4688
+ if (!draggedId || draggedId === item.id) return;
4689
+ event.preventDefault();
4690
+ const bounds = event.currentTarget.getBoundingClientRect();
4691
+ const insertionIndex = event.clientY > bounds.top + bounds.height / 2 ? index + 1 : index;
4692
+ setDropTargetIndex(insertionIndex);
4693
+ },
4694
+ onDragLeave: (event) => {
4695
+ if (event.currentTarget === event.target) setDropTargetIndex(null);
4696
+ },
4697
+ onDrop: (event) => {
4698
+ event.preventDefault();
4699
+ if (!draggedId || draggedId === item.id) return;
4700
+ const sourceIndex = ids.indexOf(draggedId);
4701
+ setDraggedId(null);
4702
+ setDropTargetIndex(null);
4703
+ moveToInsertion(sourceIndex, dropTargetIndex ?? index);
4704
+ },
4705
+ children: renderItem(item, state)
4706
+ },
4707
+ item.id
4708
+ );
4709
+ }) });
4710
+ }
4711
+
4364
4712
  // src/features/collection/KeepList.tsx
4365
- import { Fragment as Fragment10, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4713
+ import { Fragment as Fragment10, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
4366
4714
  function KeepList(props) {
4367
4715
  const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
4368
- const content = /* @__PURE__ */ jsx18(KeepListContent, { ...listProps });
4716
+ const content = /* @__PURE__ */ jsx20(KeepListContent, { ...listProps });
4369
4717
  if (fallback === void 0 && onBoundaryError === void 0) return content;
4370
- return /* @__PURE__ */ jsx18(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
4718
+ return /* @__PURE__ */ jsx20(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
4371
4719
  }
4372
4720
  function KeepListContent({
4373
4721
  query,
@@ -4381,6 +4729,8 @@ function KeepListContent({
4381
4729
  onClearFilters,
4382
4730
  itemCardProps,
4383
4731
  layout = "list",
4732
+ reorderable = false,
4733
+ onReorder,
4384
4734
  asChild = false,
4385
4735
  onKeyDown,
4386
4736
  onFocusCapture,
@@ -4402,7 +4752,10 @@ function KeepListContent({
4402
4752
  allItemCount: view.allState.totalCount,
4403
4753
  query,
4404
4754
  itemCardProps,
4405
- layout
4755
+ layout,
4756
+ reorderable,
4757
+ onReorder,
4758
+ reorder: state.reorder
4406
4759
  });
4407
4760
  return renderRoot(
4408
4761
  asChild,
@@ -4427,7 +4780,7 @@ function KeepListContent({
4427
4780
  if (!event.defaultPrevented) roving.onFocusCapture(event);
4428
4781
  }
4429
4782
  },
4430
- /* @__PURE__ */ jsx18(KeepSearchQueryProvider, { query: query?.search?.query, children: body }),
4783
+ /* @__PURE__ */ jsx20(KeepSearchQueryProvider, { query: query?.search?.query, children: body }),
4431
4784
  "KeepList"
4432
4785
  );
4433
4786
  }
@@ -4442,17 +4795,17 @@ function getListBody(state, options) {
4442
4795
  if (state.isLoading && !state.isHydrated) {
4443
4796
  if (options.loading !== void 0) return resolveContent(options.loading, state);
4444
4797
  const count = Number.isFinite(options.loadingCount) ? Math.max(0, Math.floor(options.loadingCount)) : 6;
4445
- return /* @__PURE__ */ jsxs16(Fragment10, { children: [
4446
- /* @__PURE__ */ jsx18("span", { role: "status", "data-keepkit": "loading-label", children: options.loadingLabel }),
4447
- /* @__PURE__ */ jsx18("ul", { "data-keepkit": "skeleton-list", "data-layout": options.layout, children: Array.from({ length: count }, (_, index) => (
4798
+ return /* @__PURE__ */ jsxs17(Fragment10, { children: [
4799
+ /* @__PURE__ */ jsx20("span", { role: "status", "data-keepkit": "loading-label", children: options.loadingLabel }),
4800
+ /* @__PURE__ */ jsx20("ul", { "data-keepkit": "skeleton-list", "data-layout": options.layout, children: Array.from({ length: count }, (_, index) => (
4448
4801
  // biome-ignore lint/suspicious/noArrayIndexKey: Static loading placeholders never reorder.
4449
- /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(KeepItemCardSkeleton, { layout: options.layout }) }, index)
4802
+ /* @__PURE__ */ jsx20("li", { children: /* @__PURE__ */ jsx20(KeepItemCardSkeleton, { layout: options.layout }) }, index)
4450
4803
  )) })
4451
4804
  ] });
4452
4805
  }
4453
4806
  if (state.isHydrated && state.items.length === 0) {
4454
4807
  if (options.empty !== void 0) return resolveContent(options.empty, state);
4455
- return /* @__PURE__ */ jsx18(
4808
+ return /* @__PURE__ */ jsx20(
4456
4809
  KeepEmptyState,
4457
4810
  {
4458
4811
  variant: options.allItemCount > 0 && hasActiveQueryFilters(options.query) ? "empty-filtered" : "empty-storage",
@@ -4462,32 +4815,56 @@ function getListBody(state, options) {
4462
4815
  }
4463
4816
  if (typeof options.children === "function") return options.children(state);
4464
4817
  if (options.children !== void 0 && !isValidElement6(options.children)) return options.children;
4465
- return /* @__PURE__ */ jsx18("ul", { "data-layout": options.layout, children: state.items.map(
4466
- (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
4818
+ if (options.reorderable) {
4819
+ return /* @__PURE__ */ jsx20(
4820
+ KeepReorderableList,
4821
+ {
4822
+ items: state.items,
4823
+ onReorder: async (orderedIds) => {
4824
+ await options.reorder(orderedIds);
4825
+ await options.onReorder?.(orderedIds);
4826
+ },
4827
+ renderItem: (item, reorderState) => /* @__PURE__ */ jsxs17(Fragment10, { children: [
4828
+ /* @__PURE__ */ jsx20("button", { type: "button", ...reorderState.dragHandleProps, children: "\u2195" }),
4829
+ options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx20(KeepItemCard, { item, ...options.itemCardProps })
4830
+ ] }),
4831
+ "data-layout": options.layout
4832
+ }
4833
+ );
4834
+ }
4835
+ return /* @__PURE__ */ jsx20("ul", { "data-layout": options.layout, children: state.items.map(
4836
+ (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx20("li", { children: /* @__PURE__ */ jsx20(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
4467
4837
  ) });
4468
4838
  }
4469
4839
  function hasActiveQueryFilters(query) {
4470
4840
  if (!query) return false;
4471
4841
  return Boolean(
4472
- query.search?.query?.trim() || query.tags?.some((tag) => tag.trim()) || query.targetType || query.savedBetween || query.archived !== void 0 || query.collectionId || query.filter
4842
+ query.search?.query?.trim() || query.tags?.some((tag) => tag.trim()) || query.targetType || query.savedBetween || query.archiveScope !== void 0 && query.archiveScope !== "active" || query.collectionId || query.filter
4473
4843
  );
4474
4844
  }
4475
4845
 
4476
4846
  // src/features/collection/KeepCollection.tsx
4477
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
4847
+ import { Fragment as Fragment11, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
4478
4848
  function KeepCollection(props) {
4479
4849
  const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
4480
- const content = /* @__PURE__ */ jsx19(KeepCollectionContent, { ...collectionProps });
4850
+ const content = /* @__PURE__ */ jsx21(KeepCollectionContent, { ...collectionProps });
4481
4851
  if (fallback === void 0 && onBoundaryError === void 0) return content;
4482
- return /* @__PURE__ */ jsx19(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
4852
+ return /* @__PURE__ */ jsx21(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
4483
4853
  }
4484
4854
  function KeepCollectionContent({
4485
4855
  query = {},
4486
4856
  pageSize = 20,
4487
4857
  layout = "list",
4858
+ toolbarVariant = "plain",
4859
+ toolbarLayout = "flat",
4488
4860
  urlSync = false,
4489
4861
  urlAdapter,
4862
+ archiveScope,
4863
+ onArchiveScopeChange,
4864
+ reorderable = false,
4865
+ onReorder,
4490
4866
  features,
4867
+ slots,
4491
4868
  collectionLabels,
4492
4869
  renderItem,
4493
4870
  itemCardProps,
@@ -4500,38 +4877,105 @@ function KeepCollectionContent({
4500
4877
  className,
4501
4878
  ...rootProps
4502
4879
  }) {
4503
- const view = useKeepCollection({ query, pageSize, urlSync, urlAdapter, features });
4880
+ const view = useKeepCollection({ query, pageSize, urlSync, urlAdapter, features, archiveScope });
4881
+ const [reorderUndoIds, setReorderUndoIds] = useState14(null);
4882
+ const reorderUndoLabel = useUiLabel("undoReorder");
4883
+ const handleReorder = async (orderedIds) => {
4884
+ const previousIds = view.list.items.map((item) => item.id);
4885
+ await view.list.reorder(orderedIds);
4886
+ const itemsById = new Map(view.list.items.map((item) => [item.id, item]));
4887
+ const orderedItems = orderedIds.flatMap((id) => {
4888
+ const item = itemsById.get(id);
4889
+ return item ? [item] : [];
4890
+ });
4891
+ setReorderUndoIds(previousIds);
4892
+ await onReorder?.(orderedItems);
4893
+ };
4894
+ useEffect10(() => {
4895
+ if (!reorderUndoIds) return;
4896
+ const timer = window.setTimeout(() => setReorderUndoIds(null), 5e3);
4897
+ return () => window.clearTimeout(timer);
4898
+ }, [reorderUndoIds]);
4899
+ const undoReorder = async () => {
4900
+ if (!reorderUndoIds) return;
4901
+ const previous = reorderUndoIds;
4902
+ setReorderUndoIds(null);
4903
+ await view.list.reorder(previous);
4904
+ };
4504
4905
  const resolvedItemCardProps = {
4505
4906
  ...itemCardProps,
4506
4907
  showTags: itemCardProps?.showTags ?? view.enabled.tags,
4507
4908
  showPinButton: itemCardProps?.showPinButton ?? view.enabled.pin,
4508
4909
  showArchiveButton: itemCardProps?.showArchiveButton ?? view.enabled.archive
4509
4910
  };
4510
- return /* @__PURE__ */ jsxs17(
4911
+ const toolbarId = useId3();
4912
+ const structuredToolbar = toolbarLayout === "grouped" || toolbarVariant === "panel" || slots?.toolbarStart !== void 0 || slots?.toolbarEnd !== void 0;
4913
+ const hasQueryControls = view.enabled.search || view.enabled.sort;
4914
+ const hasFilterControls = view.enabled.tagFilter || view.enabled.collectionFilter || archiveScope !== void 0;
4915
+ const queryControls = hasQueryControls ? /* @__PURE__ */ jsxs18(Fragment11, { children: [
4916
+ view.enabled.search ? /* @__PURE__ */ jsx21(KeepSearchInput, { value: view.searchValue, onValueChange: view.setSearchValue }) : null,
4917
+ view.enabled.sort ? /* @__PURE__ */ jsx21(KeepSortSelect, { value: view.sortValue, onValueChange: view.setSortValue }) : null
4918
+ ] }) : null;
4919
+ const filterControls = hasFilterControls ? /* @__PURE__ */ jsxs18(Fragment11, { children: [
4920
+ view.enabled.tagFilter ? /* @__PURE__ */ jsx21(KeepTagFilter, { query, value: view.activeTags[0], onValueChange: view.setTag }) : null,
4921
+ view.enabled.collectionFilter ? /* @__PURE__ */ jsx21(
4922
+ KeepCollectionFilter,
4923
+ {
4924
+ value: view.activeCollection,
4925
+ onValueChange: view.setCollection,
4926
+ collectionLabels
4927
+ }
4928
+ ) : null,
4929
+ archiveScope !== void 0 ? /* @__PURE__ */ jsx21(
4930
+ KeepArchiveScopeSelect,
4931
+ {
4932
+ value: view.archiveScope,
4933
+ onValueChange: (next) => {
4934
+ view.setArchiveScope(next);
4935
+ onArchiveScopeChange?.(next);
4936
+ }
4937
+ }
4938
+ ) : null
4939
+ ] }) : null;
4940
+ const toolbarStartLabel = useUiLabel("toolbarStart");
4941
+ const toolbarQueryLabel = useUiLabel("toolbarQuery");
4942
+ const toolbarFiltersLabel = useUiLabel("toolbarFilters");
4943
+ const toolbarEndLabel = useUiLabel("toolbarEnd");
4944
+ const toolbarStartContent = slots?.toolbarStart === void 0 ? null : resolveContent(slots.toolbarStart, view.list);
4945
+ const toolbarEndContent = slots?.toolbarEnd === void 0 ? null : resolveContent(slots.toolbarEnd, view.list);
4946
+ const hasToolbarContent = hasQueryControls || hasFilterControls || hasRenderableContent(toolbarStartContent) || hasRenderableContent(toolbarEndContent);
4947
+ const renderToolbarGroup = (group, content, label) => {
4948
+ if (!hasRenderableContent(content)) return null;
4949
+ const labelId = `${toolbarId}-${group}`;
4950
+ return /* @__PURE__ */ jsxs18("fieldset", { "data-keepkit": "collection-toolbar-group", "data-group": group, "aria-labelledby": labelId, children: [
4951
+ /* @__PURE__ */ jsx21("legend", { id: labelId, "data-keepkit": "collection-toolbar-label", children: label }),
4952
+ /* @__PURE__ */ jsx21("div", { "data-keepkit": "collection-toolbar-content", children: content })
4953
+ ] });
4954
+ };
4955
+ const toolbar = !structuredToolbar ? /* @__PURE__ */ jsxs18("div", { children: [
4956
+ queryControls,
4957
+ filterControls
4958
+ ] }) : !hasToolbarContent ? null : /* @__PURE__ */ jsxs18("div", { "data-keepkit": "collection-toolbar", "data-variant": toolbarVariant, "data-layout": toolbarLayout, children: [
4959
+ renderToolbarGroup("toolbarStart", toolbarStartContent, toolbarStartLabel),
4960
+ renderToolbarGroup("query", queryControls, toolbarQueryLabel),
4961
+ renderToolbarGroup("filters", filterControls, toolbarFiltersLabel),
4962
+ renderToolbarGroup("toolbarEnd", toolbarEndContent, toolbarEndLabel)
4963
+ ] });
4964
+ return /* @__PURE__ */ jsxs18(
4511
4965
  "section",
4512
4966
  {
4513
4967
  ...rootProps,
4514
4968
  className,
4515
4969
  "data-keepkit": "collection",
4516
4970
  "data-layout": layout,
4971
+ "data-toolbar-variant": toolbarVariant !== "plain" ? toolbarVariant : void 0,
4972
+ "data-toolbar-layout": toolbarLayout !== "flat" ? toolbarLayout : void 0,
4517
4973
  "aria-busy": view.list.isLoading || view.list.isMutating || rootProps["aria-busy"],
4518
4974
  "data-state": getCollectionState(view.list),
4519
4975
  "data-loading": view.list.isLoading || view.list.isMutating ? "true" : void 0,
4520
4976
  children: [
4521
- /* @__PURE__ */ jsxs17("div", { children: [
4522
- view.enabled.search ? /* @__PURE__ */ jsx19(KeepSearchInput, { value: view.searchValue, onValueChange: view.setSearchValue }) : null,
4523
- view.enabled.sort ? /* @__PURE__ */ jsx19(KeepSortSelect, { value: view.sortValue, onValueChange: view.setSortValue }) : null,
4524
- view.enabled.tagFilter ? /* @__PURE__ */ jsx19(KeepTagFilter, { query, value: view.activeTags[0], onValueChange: view.setTag }) : null,
4525
- view.enabled.collectionFilter ? /* @__PURE__ */ jsx19(
4526
- KeepCollectionFilter,
4527
- {
4528
- value: view.activeCollection,
4529
- onValueChange: view.setCollection,
4530
- collectionLabels
4531
- }
4532
- ) : null
4533
- ] }),
4534
- activeFilters === void 0 ? /* @__PURE__ */ jsx19(
4977
+ toolbar,
4978
+ activeFilters === void 0 ? /* @__PURE__ */ jsx21(
4535
4979
  KeepActiveFiltersSummary,
4536
4980
  {
4537
4981
  search: view.searchValue,
@@ -4541,7 +4985,7 @@ function KeepCollectionContent({
4541
4985
  onClear: view.clearFilters
4542
4986
  }
4543
4987
  ) : resolveContent(activeFilters, view.list),
4544
- /* @__PURE__ */ jsx19(
4988
+ /* @__PURE__ */ jsx21(
4545
4989
  KeepList,
4546
4990
  {
4547
4991
  query: view.resolvedQuery,
@@ -4552,11 +4996,13 @@ function KeepCollectionContent({
4552
4996
  renderLoading,
4553
4997
  loadingCount,
4554
4998
  onClearFilters: view.clearFilters,
4999
+ reorderable,
5000
+ onReorder: reorderable ? handleReorder : void 0,
4555
5001
  empty: view.list.totalCount === 0 && view.allState.totalCount > 0 ? void 0 : empty,
4556
5002
  error
4557
5003
  }
4558
5004
  ),
4559
- view.enabled.pagination ? /* @__PURE__ */ jsx19(
5005
+ view.enabled.pagination ? /* @__PURE__ */ jsx21(
4560
5006
  KeepPagination,
4561
5007
  {
4562
5008
  totalCount: view.list.totalCount,
@@ -4565,7 +5011,8 @@ function KeepCollectionContent({
4565
5011
  onPageChange: view.setPage
4566
5012
  }
4567
5013
  ) : null,
4568
- view.enabled.bulkActions ? /* @__PURE__ */ jsx19(KeepBulkActions, { query: view.resolvedQuery }) : null
5014
+ view.enabled.bulkActions ? /* @__PURE__ */ jsx21(KeepBulkActions, { query: view.resolvedQuery }) : null,
5015
+ reorderable && reorderUndoIds ? /* @__PURE__ */ jsx21("div", { "data-keepkit": "reorder-feedback", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx21("button", { type: "button", "data-keep-action": "undo-reorder", onClick: () => void undoReorder(), children: reorderUndoLabel }) }) : null
4569
5016
  ]
4570
5017
  }
4571
5018
  );
@@ -4576,14 +5023,17 @@ function getCollectionState(list) {
4576
5023
  if (list.isHydrated && list.items.length === 0) return "empty";
4577
5024
  return "ready";
4578
5025
  }
5026
+ function hasRenderableContent(content) {
5027
+ return content !== null && content !== void 0 && content !== false && content !== true && content !== "";
5028
+ }
4579
5029
 
4580
5030
  // src/features/collection/KeepLayout.tsx
4581
- import { jsx as jsx20 } from "react/jsx-runtime";
5031
+ import { jsx as jsx22 } from "react/jsx-runtime";
4582
5032
  function KeepLayout({ layout = "list", children, onKeyDown, onFocusCapture, ...props }) {
4583
5033
  const roving = useRovingTabIndex();
4584
5034
  return (
4585
5035
  // biome-ignore lint/a11y/noStaticElementInteractions: The group manages keyboard focus for descendant cards.
4586
- /* @__PURE__ */ jsx20(
5036
+ /* @__PURE__ */ jsx22(
4587
5037
  "div",
4588
5038
  {
4589
5039
  ...props,
@@ -4606,113 +5056,11 @@ function KeepLayout({ layout = "list", children, onKeyDown, onFocusCapture, ...p
4606
5056
  );
4607
5057
  }
4608
5058
 
4609
- // src/features/collection/KeepReorderableList.tsx
4610
- import { useState as useState12 } from "react";
4611
- import { jsx as jsx21 } from "react/jsx-runtime";
4612
- function KeepReorderableList({
4613
- items,
4614
- onReorder,
4615
- renderItem,
4616
- itemLabel = (_item, index) => `Move item ${index + 1}`,
4617
- ...props
4618
- }) {
4619
- const [draggedId, setDraggedId] = useState12(null);
4620
- const [dropTargetIndex, setDropTargetIndex] = useState12(null);
4621
- const ids = items.map((item) => item.id);
4622
- function commit(nextIds) {
4623
- void onReorder(nextIds);
4624
- }
4625
- function move(index, targetIndex) {
4626
- if (targetIndex < 0 || targetIndex >= ids.length || targetIndex === index) return;
4627
- const next = [...ids];
4628
- const [id] = next.splice(index, 1);
4629
- if (id === void 0) return;
4630
- next.splice(targetIndex, 0, id);
4631
- commit(next);
4632
- }
4633
- function moveToInsertion(index, insertionIndex) {
4634
- const next = [...ids];
4635
- const [id] = next.splice(index, 1);
4636
- if (id === void 0) return;
4637
- const targetIndex = Math.min(
4638
- Math.max(0, insertionIndex > index ? insertionIndex - 1 : insertionIndex),
4639
- next.length
4640
- );
4641
- next.splice(targetIndex, 0, id);
4642
- if (next[index] === id) return;
4643
- commit(next);
4644
- }
4645
- return /* @__PURE__ */ jsx21("ul", { ...props, "data-keepkit": "reorderable-list", children: items.map((item, index) => {
4646
- const moveUp = () => move(index, index - 1);
4647
- const moveDown = () => move(index, index + 1);
4648
- const onHandleKeyDown = (event) => {
4649
- if (event.key === "ArrowUp") {
4650
- event.preventDefault();
4651
- moveUp();
4652
- } else if (event.key === "ArrowDown") {
4653
- event.preventDefault();
4654
- moveDown();
4655
- }
4656
- };
4657
- const state = {
4658
- index,
4659
- isDragging: draggedId === item.id,
4660
- moveUp,
4661
- moveDown,
4662
- dragHandleProps: {
4663
- role: "button",
4664
- tabIndex: 0,
4665
- draggable: true,
4666
- "data-drag-handle": "true",
4667
- "aria-label": itemLabel(item, index),
4668
- "aria-grabbed": draggedId === item.id,
4669
- onDragStart: () => {
4670
- setDraggedId(item.id);
4671
- setDropTargetIndex(index);
4672
- },
4673
- onDragEnd: () => {
4674
- setDraggedId(null);
4675
- setDropTargetIndex(null);
4676
- },
4677
- onKeyDown: onHandleKeyDown
4678
- }
4679
- };
4680
- return /* @__PURE__ */ jsx21(
4681
- "li",
4682
- {
4683
- "data-reorder-index": index,
4684
- "data-dragging": draggedId === item.id ? "true" : void 0,
4685
- "data-drop-target": draggedId && draggedId !== item.id ? dropTargetIndex === index ? "before" : dropTargetIndex === index + 1 ? "after" : void 0 : void 0,
4686
- onDragOver: (event) => {
4687
- if (!draggedId || draggedId === item.id) return;
4688
- event.preventDefault();
4689
- const bounds = event.currentTarget.getBoundingClientRect();
4690
- const insertionIndex = event.clientY > bounds.top + bounds.height / 2 ? index + 1 : index;
4691
- setDropTargetIndex(insertionIndex);
4692
- },
4693
- onDragLeave: (event) => {
4694
- if (event.currentTarget === event.target) setDropTargetIndex(null);
4695
- },
4696
- onDrop: (event) => {
4697
- event.preventDefault();
4698
- if (!draggedId || draggedId === item.id) return;
4699
- const sourceIndex = ids.indexOf(draggedId);
4700
- setDraggedId(null);
4701
- setDropTargetIndex(null);
4702
- moveToInsertion(sourceIndex, dropTargetIndex ?? index);
4703
- },
4704
- children: renderItem(item, state)
4705
- },
4706
- item.id
4707
- );
4708
- }) });
4709
- }
4710
-
4711
5059
  // src/features/editor/KeepNoteEditor.tsx
4712
5060
  import { isValidElement as isValidElement7 } from "react";
4713
5061
 
4714
5062
  // src/features/navigation/KeepShortcutHint.tsx
4715
- import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
5063
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
4716
5064
  function KeepShortcutHint({ shortcut, separator = "+", ...props }) {
4717
5065
  const keys = typeof shortcut === "string" ? shortcut.split("+") : [...shortcut];
4718
5066
  const occurrences = /* @__PURE__ */ new Map();
@@ -4721,23 +5069,23 @@ function KeepShortcutHint({ shortcut, separator = "+", ...props }) {
4721
5069
  occurrences.set(key, occurrence + 1);
4722
5070
  return { id: `${key}-${occurrence}`, value: key };
4723
5071
  });
4724
- return /* @__PURE__ */ jsx22("span", { ...props, "data-keepkit": "shortcut-hint", "aria-hidden": props["aria-hidden"] ?? true, children: keyedKeys.map((key, index) => /* @__PURE__ */ jsxs18("span", { children: [
4725
- index > 0 ? /* @__PURE__ */ jsx22("span", { "data-shortcut-separator": "true", children: separator }) : null,
4726
- /* @__PURE__ */ jsx22("kbd", { children: key.value.trim() })
5072
+ return /* @__PURE__ */ jsx23("span", { ...props, "data-keepkit": "shortcut-hint", "aria-hidden": props["aria-hidden"] ?? true, children: keyedKeys.map((key, index) => /* @__PURE__ */ jsxs19("span", { children: [
5073
+ index > 0 ? /* @__PURE__ */ jsx23("span", { "data-shortcut-separator": "true", children: separator }) : null,
5074
+ /* @__PURE__ */ jsx23("kbd", { children: key.value.trim() })
4727
5075
  ] }, key.id)) });
4728
5076
  }
4729
5077
 
4730
5078
  // src/features/editor/hooks/useKeepNoteEditor.ts
4731
5079
  import { useKeepItem as useKeepItem6 } from "@keepkit/core/react";
4732
- import { useCallback as useCallback6, useEffect as useEffect9, useRef as useRef8, useState as useState13 } from "react";
5080
+ import { useCallback as useCallback6, useEffect as useEffect11, useRef as useRef9, useState as useState15 } from "react";
4733
5081
  function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
4734
5082
  const itemState = useKeepItem6(item);
4735
5083
  const { error, isMutating, item: savedItem, updateNote } = itemState;
4736
- const [note, setNote] = useState13(item.note ?? "");
5084
+ const [note, setNote] = useState15(item.note ?? "");
4737
5085
  const baselineNote = savedItem?.note ?? item.note ?? "";
4738
5086
  const isDirty = note !== baselineNote;
4739
- const lastSavedNoteRef = useRef8(void 0);
4740
- useEffect9(() => setNote(baselineNote), [baselineNote]);
5087
+ const lastSavedNoteRef = useRef9(void 0);
5088
+ useEffect11(() => setNote(baselineNote), [baselineNote]);
4741
5089
  const save = useCallback6(async () => {
4742
5090
  const nextNote = note.trim() || void 0;
4743
5091
  try {
@@ -4749,7 +5097,7 @@ function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
4749
5097
  throw cause;
4750
5098
  }
4751
5099
  }, [note, onSaveError, onSaved, updateNote]);
4752
- useEffect9(() => {
5100
+ useEffect11(() => {
4753
5101
  if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;
4754
5102
  const timer = window.setTimeout(() => void save().catch(() => void 0), debounceMs);
4755
5103
  return () => window.clearTimeout(timer);
@@ -4784,7 +5132,7 @@ function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
4784
5132
  }
4785
5133
 
4786
5134
  // src/features/editor/KeepNoteEditor.tsx
4787
- import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
5135
+ import { Fragment as Fragment12, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
4788
5136
  function KeepNoteEditor({
4789
5137
  item,
4790
5138
  label,
@@ -4803,10 +5151,10 @@ function KeepNoteEditor({
4803
5151
  const view = useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError });
4804
5152
  const { error, isDirty, isSaving, note, setNote } = view.state;
4805
5153
  const contentChildren = asChild && isValidElement7(children) ? void 0 : children;
4806
- const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs19(Fragment11, { children: [
4807
- /* @__PURE__ */ jsxs19("label", { children: [
5154
+ const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs20(Fragment12, { children: [
5155
+ /* @__PURE__ */ jsxs20("label", { children: [
4808
5156
  label ?? view.labels.note,
4809
- /* @__PURE__ */ jsx23(
5157
+ /* @__PURE__ */ jsx24(
4810
5158
  "textarea",
4811
5159
  {
4812
5160
  "data-keep-action": "edit-note",
@@ -4818,13 +5166,13 @@ function KeepNoteEditor({
4818
5166
  }
4819
5167
  )
4820
5168
  ] }),
4821
- /* @__PURE__ */ jsxs19("button", { type: "submit", "data-keep-action": "save-note", disabled: isSaving, "aria-busy": isSaving, children: [
5169
+ /* @__PURE__ */ jsxs20("button", { type: "submit", "data-keep-action": "save-note", disabled: isSaving, "aria-busy": isSaving, children: [
4822
5170
  saveLabel ?? view.labels.save,
4823
- showShortcutHint ? /* @__PURE__ */ jsx23(KeepShortcutHint, { shortcut: "Ctrl+Enter" }) : null
5171
+ showShortcutHint ? /* @__PURE__ */ jsx24(KeepShortcutHint, { shortcut: "Ctrl+Enter" }) : null
4824
5172
  ] })
4825
5173
  ] });
4826
5174
  if (!asChild) {
4827
- return /* @__PURE__ */ jsxs19(
5175
+ return /* @__PURE__ */ jsxs20(
4828
5176
  "form",
4829
5177
  {
4830
5178
  ...formProps,
@@ -4837,7 +5185,7 @@ function KeepNoteEditor({
4837
5185
  "data-disabled": isSaving ? "true" : void 0,
4838
5186
  children: [
4839
5187
  body,
4840
- error ? /* @__PURE__ */ jsx23("p", { role: "alert", children: getErrorMessage4(error, view.labels.error) }) : null
5188
+ error ? /* @__PURE__ */ jsx24("p", { role: "alert", children: getErrorMessage4(error, view.labels.error) }) : null
4841
5189
  ]
4842
5190
  }
4843
5191
  );
@@ -4865,12 +5213,12 @@ function getErrorMessage4(error, fallback) {
4865
5213
 
4866
5214
  // src/features/editor/hooks/useKeepTagEditor.ts
4867
5215
  import { useKeepItem as useKeepItem7 } from "@keepkit/core/react";
4868
- import { useCallback as useCallback7, useEffect as useEffect10, useState as useState14 } from "react";
5216
+ import { useCallback as useCallback7, useEffect as useEffect12, useState as useState16 } from "react";
4869
5217
  function useKeepTagEditor({ item, onSaved, onSaveError }) {
4870
5218
  const itemState = useKeepItem7(item);
4871
- const [tags, setTags] = useState14(item.tags ?? []);
4872
- const [input, setInput] = useState14("");
4873
- useEffect10(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
5219
+ const [tags, setTags] = useState16(item.tags ?? []);
5220
+ const [input, setInput] = useState16("");
5221
+ useEffect12(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
4874
5222
  const save = useCallback7(async () => {
4875
5223
  const nextTags = normalizeUiTags(tags);
4876
5224
  try {
@@ -4917,7 +5265,7 @@ function useKeepTagEditor({ item, onSaved, onSaveError }) {
4917
5265
  }
4918
5266
 
4919
5267
  // src/features/editor/KeepTagEditor.tsx
4920
- import { Fragment as Fragment12, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5268
+ import { Fragment as Fragment13, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
4921
5269
  function KeepTagEditor({
4922
5270
  item,
4923
5271
  availableTags = [],
@@ -4928,10 +5276,10 @@ function KeepTagEditor({
4928
5276
  }) {
4929
5277
  const view = useKeepTagEditor({ item, onSaved, onSaveError });
4930
5278
  const { isSaving, tags } = view.state;
4931
- const body = render ? render(view.state) : /* @__PURE__ */ jsxs20(Fragment12, { children: [
4932
- /* @__PURE__ */ jsxs20("label", { children: [
5279
+ const body = render ? render(view.state) : /* @__PURE__ */ jsxs21(Fragment13, { children: [
5280
+ /* @__PURE__ */ jsxs21("label", { children: [
4933
5281
  view.labels.tags,
4934
- /* @__PURE__ */ jsx24(
5282
+ /* @__PURE__ */ jsx25(
4935
5283
  "input",
4936
5284
  {
4937
5285
  "data-keep-action": "edit-tags",
@@ -4942,14 +5290,14 @@ function KeepTagEditor({
4942
5290
  }
4943
5291
  )
4944
5292
  ] }),
4945
- availableTags.length > 0 ? /* @__PURE__ */ jsx24("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx24("option", { value: tag }, tag)) }) : null,
4946
- /* @__PURE__ */ jsx24("ul", { "aria-label": view.labels.tags, children: tags.map((tag) => /* @__PURE__ */ jsxs20("li", { children: [
5293
+ availableTags.length > 0 ? /* @__PURE__ */ jsx25("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx25("option", { value: tag }, tag)) }) : null,
5294
+ /* @__PURE__ */ jsx25("ul", { "aria-label": view.labels.tags, children: tags.map((tag) => /* @__PURE__ */ jsxs21("li", { children: [
4947
5295
  tag,
4948
- /* @__PURE__ */ jsx24("button", { type: "button", "data-keep-action": "remove-tag", onClick: () => view.removeTag(tag), children: view.labels.remove })
5296
+ /* @__PURE__ */ jsx25("button", { type: "button", "data-keep-action": "remove-tag", onClick: () => view.removeTag(tag), children: view.labels.remove })
4949
5297
  ] }, tag)) }),
4950
- /* @__PURE__ */ jsx24("button", { type: "submit", "data-keep-action": "apply-tags", disabled: isSaving, "aria-busy": isSaving, children: view.labels.apply })
5298
+ /* @__PURE__ */ jsx25("button", { type: "submit", "data-keep-action": "apply-tags", disabled: isSaving, "aria-busy": isSaving, children: view.labels.apply })
4951
5299
  ] });
4952
- return /* @__PURE__ */ jsxs20(
5300
+ return /* @__PURE__ */ jsxs21(
4953
5301
  "form",
4954
5302
  {
4955
5303
  ...props,
@@ -4961,7 +5309,7 @@ function KeepTagEditor({
4961
5309
  "data-disabled": isSaving ? "true" : void 0,
4962
5310
  children: [
4963
5311
  body,
4964
- view.error ? /* @__PURE__ */ jsx24("p", { role: "alert", children: getErrorMessage5(view.error, view.labels.error) }) : null
5312
+ view.error ? /* @__PURE__ */ jsx25("p", { role: "alert", children: getErrorMessage5(view.error, view.labels.error) }) : null
4965
5313
  ]
4966
5314
  }
4967
5315
  );
@@ -4992,10 +5340,10 @@ function useKeepToastFeedback(showToast) {
4992
5340
 
4993
5341
  // src/features/navigation/KeepTourBar.tsx
4994
5342
  import { useKeepNavigator } from "@keepkit/core/react";
4995
- import { useId as useId2 } from "react";
5343
+ import { useId as useId4 } from "react";
4996
5344
 
4997
5345
  // src/features/navigation/hooks/useKeepTourShortcuts.ts
4998
- import { useEffect as useEffect11 } from "react";
5346
+ import { useEffect as useEffect13 } from "react";
4999
5347
  function useKeepTourShortcuts({
5000
5348
  onNext,
5001
5349
  onPrev,
@@ -5006,7 +5354,7 @@ function useKeepTourShortcuts({
5006
5354
  prevKeys = ["k", "["],
5007
5355
  onError
5008
5356
  }) {
5009
- useEffect11(() => {
5357
+ useEffect13(() => {
5010
5358
  if (!enabled) return;
5011
5359
  const handleKeyDown = (event) => {
5012
5360
  if (!allowInEditable && isEditableTarget(event.target)) return;
@@ -5027,7 +5375,7 @@ function isEditableTarget(target) {
5027
5375
  }
5028
5376
 
5029
5377
  // src/features/navigation/KeepTourBar.tsx
5030
- import { Fragment as Fragment13, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
5378
+ import { Fragment as Fragment14, jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
5031
5379
  function KeepTourBar({
5032
5380
  navigation: providedNavigation,
5033
5381
  currentId,
@@ -5036,6 +5384,9 @@ function KeepTourBar({
5036
5384
  prevHref,
5037
5385
  nextHref,
5038
5386
  backHref,
5387
+ getItemHref,
5388
+ getBackHref,
5389
+ onNavigate,
5039
5390
  onPrev,
5040
5391
  onNext,
5041
5392
  onBack,
@@ -5057,8 +5408,33 @@ function KeepTourBar({
5057
5408
  const nextItemLabel = useUiLabel("nextPage", nextLabel);
5058
5409
  const listLabel = useUiLabel("allItems", backLabel);
5059
5410
  const { labels } = useKeepUiLabels();
5060
- const resolvedPrev = onPrev ?? (() => navigateTo(navigation.goToPrev(), prevHref));
5061
- const resolvedNext = onNext ?? (() => navigateTo(navigation.goToNext(), nextHref));
5411
+ const resolvedPrevHref = prevHref ?? (navigation.prevItem ? getItemHref?.(navigation.prevItem) : void 0);
5412
+ const resolvedNextHref = nextHref ?? (navigation.nextItem ? getItemHref?.(navigation.nextItem) : void 0);
5413
+ const resolvedBackHref = backHref ?? getBackHref?.();
5414
+ const navigateByKeyboard = (direction) => {
5415
+ const item = direction === "prev" ? navigation.goToPrev() : navigation.goToNext();
5416
+ if (!item) return;
5417
+ onNavigate?.(direction, item);
5418
+ const handler = direction === "prev" ? onPrev : onNext;
5419
+ if (handler) return handler();
5420
+ navigateTo(item, direction === "prev" ? resolvedPrevHref : resolvedNextHref);
5421
+ };
5422
+ const resolvedPrev = () => navigateByKeyboard("prev");
5423
+ const resolvedNext = () => navigateByKeyboard("next");
5424
+ const notifyPrevNavigation = () => {
5425
+ const item = navigation.prevItem;
5426
+ if (!item) return;
5427
+ navigation.goToPrev();
5428
+ onNavigate?.("prev", item);
5429
+ void onPrev?.();
5430
+ };
5431
+ const notifyNextNavigation = () => {
5432
+ const item = navigation.nextItem;
5433
+ if (!item) return;
5434
+ navigation.goToNext();
5435
+ onNavigate?.("next", item);
5436
+ void onNext?.();
5437
+ };
5062
5438
  useKeepTourShortcuts({
5063
5439
  ...shortcutOptions,
5064
5440
  enabled: keyboardShortcuts && (shortcutOptions?.enabled ?? true),
@@ -5069,17 +5445,17 @@ function KeepTourBar({
5069
5445
  return resolvedPrev();
5070
5446
  }
5071
5447
  });
5072
- const body = /* @__PURE__ */ jsxs21(Fragment13, { children: [
5073
- showProgress ? /* @__PURE__ */ jsx25("span", { "data-keepkit": "tour-progress", "aria-live": "polite", children: progress ?? `${navigation.currentPosition ?? 0} / ${navigation.items.length}` }) : null,
5074
- /* @__PURE__ */ jsx25(
5448
+ const body = /* @__PURE__ */ jsxs22(Fragment14, { children: [
5449
+ showProgress ? /* @__PURE__ */ jsx26("span", { "data-keepkit": "tour-progress", "aria-live": "polite", children: progress ?? `${navigation.currentPosition ?? 0} / ${navigation.items.length}` }) : null,
5450
+ /* @__PURE__ */ jsx26(
5075
5451
  TourAction,
5076
5452
  {
5077
- href: prevHref,
5453
+ href: resolvedPrevHref,
5078
5454
  disabled: !navigation.hasPrev,
5079
- onClick: prevHref ? onPrev : resolvedPrev,
5455
+ onClick: resolvedPrevHref ? notifyPrevNavigation : resolvedPrev,
5080
5456
  "data-keep-action": "tour-prev",
5081
5457
  shortcut: showShortcutHint ? shortcutOptions?.prevKeys?.[0] ?? "K" : void 0,
5082
- preview: navigation.prevItem ? /* @__PURE__ */ jsxs21(Fragment13, { children: [
5458
+ preview: navigation.prevItem ? /* @__PURE__ */ jsxs22(Fragment14, { children: [
5083
5459
  previousLabel,
5084
5460
  ": ",
5085
5461
  getItemTitle(navigation.prevItem)
@@ -5087,15 +5463,15 @@ function KeepTourBar({
5087
5463
  children: previousLabel
5088
5464
  }
5089
5465
  ),
5090
- /* @__PURE__ */ jsx25(
5466
+ /* @__PURE__ */ jsx26(
5091
5467
  TourAction,
5092
5468
  {
5093
- href: nextHref,
5469
+ href: resolvedNextHref,
5094
5470
  disabled: !navigation.hasNext,
5095
- onClick: nextHref ? onNext : resolvedNext,
5471
+ onClick: resolvedNextHref ? notifyNextNavigation : resolvedNext,
5096
5472
  "data-keep-action": "tour-next",
5097
5473
  shortcut: showShortcutHint ? shortcutOptions?.nextKeys?.[0] ?? "J" : void 0,
5098
- preview: navigation.nextItem ? /* @__PURE__ */ jsxs21(Fragment13, { children: [
5474
+ preview: navigation.nextItem ? /* @__PURE__ */ jsxs22(Fragment14, { children: [
5099
5475
  nextItemLabel,
5100
5476
  ": ",
5101
5477
  getItemTitle(navigation.nextItem)
@@ -5103,7 +5479,7 @@ function KeepTourBar({
5103
5479
  children: nextItemLabel
5104
5480
  }
5105
5481
  ),
5106
- backHref || onBack ? /* @__PURE__ */ jsx25(TourAction, { href: backHref, onClick: onBack, "data-keep-action": "tour-back", children: listLabel }) : null
5482
+ resolvedBackHref || onBack ? /* @__PURE__ */ jsx26(TourAction, { href: resolvedBackHref, onClick: onBack, "data-keep-action": "tour-back", children: listLabel }) : null
5107
5483
  ] });
5108
5484
  return renderRoot(
5109
5485
  asChild,
@@ -5114,14 +5490,14 @@ function KeepTourBar({
5114
5490
  );
5115
5491
  }
5116
5492
  function TourAction({ href, disabled = false, onClick, children, preview, shortcut, ...props }) {
5117
- const previewId = useId2();
5118
- const content = /* @__PURE__ */ jsxs21(Fragment13, { children: [
5119
- /* @__PURE__ */ jsx25("span", { "data-tour-label": "true", children }),
5120
- shortcut ? /* @__PURE__ */ jsx25(KeepShortcutHint, { shortcut }) : null,
5121
- preview ? /* @__PURE__ */ jsx25("small", { id: previewId, "data-tour-preview": "true", children: preview }) : null
5493
+ const previewId = useId4();
5494
+ const content = /* @__PURE__ */ jsxs22(Fragment14, { children: [
5495
+ /* @__PURE__ */ jsx26("span", { "data-tour-label": "true", children }),
5496
+ shortcut ? /* @__PURE__ */ jsx26(KeepShortcutHint, { shortcut }) : null,
5497
+ preview ? /* @__PURE__ */ jsx26("small", { id: previewId, "data-tour-preview": "true", children: preview }) : null
5122
5498
  ] });
5123
5499
  if (href && !disabled) {
5124
- return /* @__PURE__ */ jsx25(
5500
+ return /* @__PURE__ */ jsx26(
5125
5501
  "a",
5126
5502
  {
5127
5503
  ...props,
@@ -5133,7 +5509,7 @@ function TourAction({ href, disabled = false, onClick, children, preview, shortc
5133
5509
  }
5134
5510
  );
5135
5511
  }
5136
- return /* @__PURE__ */ jsx25(
5512
+ return /* @__PURE__ */ jsx26(
5137
5513
  "button",
5138
5514
  {
5139
5515
  ...props,
@@ -5156,10 +5532,10 @@ function navigateTo(item, href) {
5156
5532
  import { isValidElement as isValidElement8 } from "react";
5157
5533
 
5158
5534
  // src/features/status/hooks/useStatusViews.ts
5159
- import { useKeepContext as useKeepContext6 } from "@keepkit/core/react";
5160
- import { useEffect as useEffect12, useRef as useRef9, useState as useState15 } from "react";
5535
+ import { useKeepContext as useKeepContext5 } from "@keepkit/core/react";
5536
+ import { useEffect as useEffect14, useRef as useRef10, useState as useState17 } from "react";
5161
5537
  function useKeepStatus(status) {
5162
- const context = useKeepContext6();
5538
+ const context = useKeepContext5();
5163
5539
  const resolvedStatus = status ?? getDerivedStatus(context);
5164
5540
  const state = {
5165
5541
  status: resolvedStatus,
@@ -5170,13 +5546,13 @@ function useKeepStatus(status) {
5170
5546
  return { state, defaultLabel: useUiLabel(getStatusLabelKey3(resolvedStatus)) };
5171
5547
  }
5172
5548
  function useKeepAnnouncements(messages) {
5173
- const context = useKeepContext6();
5549
+ const context = useKeepContext5();
5174
5550
  const savedMessage = useUiLabel("savedMessage", messages?.save);
5175
5551
  const removedMessage = useUiLabel("removedMessage", messages?.remove);
5176
5552
  const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
5177
- const [message, setMessage] = useState15("");
5178
- const lastChangeRef = useRef9(void 0);
5179
- useEffect12(() => {
5553
+ const [message, setMessage] = useState17("");
5554
+ const lastChangeRef = useRef10(void 0);
5555
+ useEffect14(() => {
5180
5556
  const change = context.lastChange;
5181
5557
  if (!change || change === lastChangeRef.current) return;
5182
5558
  lastChangeRef.current = change;
@@ -5204,7 +5580,7 @@ function getStatusLabelKey3(status) {
5204
5580
  }
5205
5581
 
5206
5582
  // src/features/status/status.tsx
5207
- import { jsx as jsx26 } from "react/jsx-runtime";
5583
+ import { jsx as jsx27 } from "react/jsx-runtime";
5208
5584
  function KeepStatus({
5209
5585
  status,
5210
5586
  labels,
@@ -5236,7 +5612,7 @@ function KeepStatus({
5236
5612
  }
5237
5613
  function KeepAnnouncements({ messages, ...props }) {
5238
5614
  const message = useKeepAnnouncements(messages);
5239
- return /* @__PURE__ */ jsx26(
5615
+ return /* @__PURE__ */ jsx27(
5240
5616
  "div",
5241
5617
  {
5242
5618
  ...props,
@@ -5252,15 +5628,15 @@ function KeepAnnouncements({ messages, ...props }) {
5252
5628
  var KeepAnnouncer = KeepAnnouncements;
5253
5629
 
5254
5630
  // src/features/sync/hooks/useKeepSyncFeedback.ts
5255
- import { useKeepContext as useKeepContext7 } from "@keepkit/core/react";
5256
- import { useEffect as useEffect13, useRef as useRef10 } from "react";
5631
+ import { useKeepContext as useKeepContext6 } from "@keepkit/core/react";
5632
+ import { useEffect as useEffect15, useRef as useRef11 } from "react";
5257
5633
  function useKeepSyncFeedback() {
5258
- const { syncState } = useKeepContext7();
5634
+ const { syncState } = useKeepContext6();
5259
5635
  const emitFeedback = useKeepUiFeedback();
5260
5636
  const completedMessage = useUiLabel("syncSynced");
5261
5637
  const failedMessage = useUiLabel("syncFailedMessage");
5262
- const previousStatus = useRef10("idle");
5263
- useEffect13(() => {
5638
+ const previousStatus = useRef11("idle");
5639
+ useEffect15(() => {
5264
5640
  const previous = previousStatus.current;
5265
5641
  previousStatus.current = syncState.status;
5266
5642
  if (syncState.status === "error" && previous !== "error") {
@@ -5280,17 +5656,17 @@ function KeepSyncFeedbackObserver() {
5280
5656
  }
5281
5657
 
5282
5658
  // src/features/sync/hooks/useKeepSyncRecoveryDialog.ts
5283
- import { useKeepContext as useKeepContext8 } from "@keepkit/core/react";
5284
- import { useEffect as useEffect14, useState as useState16 } from "react";
5659
+ import { useKeepContext as useKeepContext7 } from "@keepkit/core/react";
5660
+ import { useEffect as useEffect16, useState as useState18 } from "react";
5285
5661
  function useKeepSyncRecoveryDialog(options) {
5286
5662
  const { open, onOpenChange, conflicts, onManualMerge } = options;
5287
- const context = useKeepContext8();
5663
+ const context = useKeepContext7();
5288
5664
  const conflictList = conflicts ?? context.syncState.conflicts ?? [];
5289
5665
  const hasRecovery = conflictList.length > 0 || context.syncState.status === "error" || Boolean(context.error);
5290
- const [dismissed, setDismissed] = useState16(false);
5291
- const [busyId, setBusyId] = useState16();
5292
- const [error, setError] = useState16();
5293
- useEffect14(() => {
5666
+ const [dismissed, setDismissed] = useState18(false);
5667
+ const [busyId, setBusyId] = useState18();
5668
+ const [error, setError] = useState18();
5669
+ useEffect16(() => {
5294
5670
  if (hasRecovery) setDismissed(false);
5295
5671
  }, [hasRecovery]);
5296
5672
  return {
@@ -5335,7 +5711,7 @@ function useKeepSyncRecoveryDialog(options) {
5335
5711
  }
5336
5712
 
5337
5713
  // src/features/sync/KeepSyncRecoveryDialog.tsx
5338
- import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
5714
+ import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
5339
5715
  function KeepSyncRecoveryDialog({
5340
5716
  open,
5341
5717
  onOpenChange,
@@ -5350,7 +5726,7 @@ function KeepSyncRecoveryDialog({
5350
5726
  }) {
5351
5727
  const view = useKeepSyncRecoveryDialog({ open, onOpenChange, conflicts, onManualMerge });
5352
5728
  if (!view.isOpen) return null;
5353
- return /* @__PURE__ */ jsxs22(
5729
+ return /* @__PURE__ */ jsxs23(
5354
5730
  "section",
5355
5731
  {
5356
5732
  ...props,
@@ -5364,17 +5740,17 @@ function KeepSyncRecoveryDialog({
5364
5740
  "data-state": view.conflictList.length > 0 ? "conflict" : "error",
5365
5741
  "data-loading": view.busyId !== void 0 ? "true" : void 0,
5366
5742
  children: [
5367
- /* @__PURE__ */ jsxs22("header", { children: [
5368
- /* @__PURE__ */ jsx27("h2", { id: "keepkit-sync-recovery-title", children: title ?? view.labels.title }),
5369
- /* @__PURE__ */ jsx27("button", { type: "button", "data-keep-action": "close-dialog", onClick: view.close, "aria-label": view.labels.close, children: view.labels.close })
5743
+ /* @__PURE__ */ jsxs23("header", { children: [
5744
+ /* @__PURE__ */ jsx28("h2", { id: "keepkit-sync-recovery-title", children: title ?? view.labels.title }),
5745
+ /* @__PURE__ */ jsx28("button", { type: "button", "data-keep-action": "close-dialog", onClick: view.close, "aria-label": view.labels.close, children: view.labels.close })
5370
5746
  ] }),
5371
5747
  children,
5372
- view.conflictList.length > 0 ? /* @__PURE__ */ jsxs22("div", { children: [
5373
- /* @__PURE__ */ jsx27("p", { children: view.labels.conflict }),
5374
- view.conflictList.map((conflict) => /* @__PURE__ */ jsxs22("article", { "data-conflict-id": conflict.id, children: [
5375
- /* @__PURE__ */ jsx27("h3", { children: getMetaTitle(conflict.operation.item?.meta) ?? conflict.id }),
5376
- /* @__PURE__ */ jsxs22("div", { "data-conflict-preview": true, children: [
5377
- /* @__PURE__ */ jsx27(
5748
+ view.conflictList.length > 0 ? /* @__PURE__ */ jsxs23("div", { children: [
5749
+ /* @__PURE__ */ jsx28("p", { children: view.labels.conflict }),
5750
+ view.conflictList.map((conflict) => /* @__PURE__ */ jsxs23("article", { "data-conflict-id": conflict.id, children: [
5751
+ /* @__PURE__ */ jsx28("h3", { children: getMetaTitle(conflict.operation.item?.meta) ?? conflict.id }),
5752
+ /* @__PURE__ */ jsxs23("div", { "data-conflict-preview": true, children: [
5753
+ /* @__PURE__ */ jsx28(
5378
5754
  ConflictPreview,
5379
5755
  {
5380
5756
  item: conflict.operation.item,
@@ -5384,7 +5760,7 @@ function KeepSyncRecoveryDialog({
5384
5760
  side: "local"
5385
5761
  }
5386
5762
  ),
5387
- /* @__PURE__ */ jsx27(
5763
+ /* @__PURE__ */ jsx28(
5388
5764
  ConflictPreview,
5389
5765
  {
5390
5766
  item: conflict.remote,
@@ -5395,8 +5771,8 @@ function KeepSyncRecoveryDialog({
5395
5771
  }
5396
5772
  )
5397
5773
  ] }),
5398
- /* @__PURE__ */ jsxs22("div", { children: [
5399
- /* @__PURE__ */ jsx27(
5774
+ /* @__PURE__ */ jsxs23("div", { children: [
5775
+ /* @__PURE__ */ jsx28(
5400
5776
  "button",
5401
5777
  {
5402
5778
  type: "button",
@@ -5406,7 +5782,7 @@ function KeepSyncRecoveryDialog({
5406
5782
  children: view.labels.keepLocal
5407
5783
  }
5408
5784
  ),
5409
- /* @__PURE__ */ jsx27(
5785
+ /* @__PURE__ */ jsx28(
5410
5786
  "button",
5411
5787
  {
5412
5788
  type: "button",
@@ -5416,7 +5792,7 @@ function KeepSyncRecoveryDialog({
5416
5792
  children: view.labels.useServer
5417
5793
  }
5418
5794
  ),
5419
- /* @__PURE__ */ jsx27(
5795
+ /* @__PURE__ */ jsx28(
5420
5796
  "button",
5421
5797
  {
5422
5798
  type: "button",
@@ -5429,12 +5805,12 @@ function KeepSyncRecoveryDialog({
5429
5805
  ] })
5430
5806
  ] }, conflict.id))
5431
5807
  ] }) : null,
5432
- view.showBackupRecovery ? /* @__PURE__ */ jsxs22("section", { "data-recovery": "backup", children: [
5433
- /* @__PURE__ */ jsx27("h3", { children: view.labels.backupRecovery }),
5434
- /* @__PURE__ */ jsx27("p", { children: view.labels.backupRecoveryDescription }),
5435
- backup ?? (showBackupControls ? /* @__PURE__ */ jsx27(KeepBackup, {}) : null)
5808
+ view.showBackupRecovery ? /* @__PURE__ */ jsxs23("section", { "data-recovery": "backup", children: [
5809
+ /* @__PURE__ */ jsx28("h3", { children: view.labels.backupRecovery }),
5810
+ /* @__PURE__ */ jsx28("p", { children: view.labels.backupRecoveryDescription }),
5811
+ backup ?? (showBackupControls ? /* @__PURE__ */ jsx28(KeepBackup, {}) : null)
5436
5812
  ] }) : null,
5437
- view.error ? /* @__PURE__ */ jsx27("p", { id: "keepkit-sync-recovery-error", role: "alert", "aria-live": "assertive", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
5813
+ view.error ? /* @__PURE__ */ jsx28("p", { id: "keepkit-sync-recovery-error", role: "alert", "aria-live": "assertive", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
5438
5814
  ]
5439
5815
  }
5440
5816
  );
@@ -5446,16 +5822,16 @@ function ConflictPreview({
5446
5822
  noteLabel,
5447
5823
  side
5448
5824
  }) {
5449
- return /* @__PURE__ */ jsxs22("article", { "data-conflict-version": side, "aria-label": heading, children: [
5450
- /* @__PURE__ */ jsx27("h4", { children: heading }),
5451
- /* @__PURE__ */ jsxs22("dl", { children: [
5452
- /* @__PURE__ */ jsxs22("div", { children: [
5453
- /* @__PURE__ */ jsx27("dt", { children: updatedAtLabel }),
5454
- /* @__PURE__ */ jsx27("dd", { children: item ? /* @__PURE__ */ jsx27("time", { dateTime: new Date(item.updatedAt).toISOString(), children: formatConflictDate(item.updatedAt) }) : "\u2014" })
5825
+ return /* @__PURE__ */ jsxs23("article", { "data-conflict-version": side, "aria-label": heading, children: [
5826
+ /* @__PURE__ */ jsx28("h4", { children: heading }),
5827
+ /* @__PURE__ */ jsxs23("dl", { children: [
5828
+ /* @__PURE__ */ jsxs23("div", { children: [
5829
+ /* @__PURE__ */ jsx28("dt", { children: updatedAtLabel }),
5830
+ /* @__PURE__ */ jsx28("dd", { children: item ? /* @__PURE__ */ jsx28("time", { dateTime: new Date(item.updatedAt).toISOString(), children: formatConflictDate(item.updatedAt) }) : "\u2014" })
5455
5831
  ] }),
5456
- /* @__PURE__ */ jsxs22("div", { children: [
5457
- /* @__PURE__ */ jsx27("dt", { children: noteLabel }),
5458
- /* @__PURE__ */ jsx27("dd", { children: item?.note || "\u2014" })
5832
+ /* @__PURE__ */ jsxs23("div", { children: [
5833
+ /* @__PURE__ */ jsx28("dt", { children: noteLabel }),
5834
+ /* @__PURE__ */ jsx28("dd", { children: item?.note || "\u2014" })
5459
5835
  ] })
5460
5836
  ] })
5461
5837
  ] });
@@ -5465,9 +5841,9 @@ function formatConflictDate(timestamp) {
5465
5841
  }
5466
5842
 
5467
5843
  // src/features/sync/hooks/useKeepSyncStatusBanner.ts
5468
- import { useKeepContext as useKeepContext9 } from "@keepkit/core/react";
5844
+ import { useKeepContext as useKeepContext8 } from "@keepkit/core/react";
5469
5845
  function useKeepSyncStatusBanner({ onRetry, children }) {
5470
- const context = useKeepContext9();
5846
+ const context = useKeepContext8();
5471
5847
  const retryLabel = useUiLabel("retrySync");
5472
5848
  const resolveLabel = useUiLabel("resolveSync");
5473
5849
  const conflictLabel = useUiLabel("syncConflict");
@@ -5499,7 +5875,7 @@ function getErrorMessage6(error) {
5499
5875
  }
5500
5876
 
5501
5877
  // src/features/sync/KeepSyncStatusBanner.tsx
5502
- import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
5878
+ import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
5503
5879
  function KeepSyncStatusBanner({
5504
5880
  onRetry,
5505
5881
  onResolveConflicts,
@@ -5509,7 +5885,7 @@ function KeepSyncStatusBanner({
5509
5885
  }) {
5510
5886
  const view = useKeepSyncStatusBanner({ onRetry, children });
5511
5887
  if (view.status === "idle" && !view.hasConflicts) return null;
5512
- return /* @__PURE__ */ jsxs23(
5888
+ return /* @__PURE__ */ jsxs24(
5513
5889
  "aside",
5514
5890
  {
5515
5891
  ...props,
@@ -5519,8 +5895,8 @@ function KeepSyncStatusBanner({
5519
5895
  "data-keepkit": "sync-status",
5520
5896
  "data-state": view.status,
5521
5897
  children: [
5522
- /* @__PURE__ */ jsx28("p", { children: view.message }),
5523
- view.showRetry ? /* @__PURE__ */ jsx28(
5898
+ /* @__PURE__ */ jsx29("p", { children: view.message }),
5899
+ view.showRetry ? /* @__PURE__ */ jsx29(
5524
5900
  "button",
5525
5901
  {
5526
5902
  type: "button",
@@ -5530,7 +5906,7 @@ function KeepSyncStatusBanner({
5530
5906
  children: view.retryLabel
5531
5907
  }
5532
5908
  ) : null,
5533
- view.hasConflicts ? /* @__PURE__ */ jsx28(
5909
+ view.hasConflicts ? /* @__PURE__ */ jsx29(
5534
5910
  "button",
5535
5911
  {
5536
5912
  type: "button",
@@ -5546,7 +5922,7 @@ function KeepSyncStatusBanner({
5546
5922
  }
5547
5923
 
5548
5924
  // src/features/workspace/hooks/useKeepWorkspace.ts
5549
- import { useCallback as useCallback9, useState as useState17 } from "react";
5925
+ import { useCallback as useCallback9, useState as useState19 } from "react";
5550
5926
  var PRESET_MODULES = {
5551
5927
  basic: { syncStatus: false, undo: false, recovery: false, backup: false, stalePrune: false },
5552
5928
  standard: { syncStatus: false, undo: true, recovery: false, backup: false, stalePrune: false },
@@ -5566,7 +5942,7 @@ function useKeepWorkspace({
5566
5942
  onRecoveryOpenChange,
5567
5943
  onResolveConflicts
5568
5944
  }) {
5569
- const [internalRecoveryOpen, setInternalRecoveryOpen] = useState17(false);
5945
+ const [internalRecoveryOpen, setInternalRecoveryOpen] = useState19(false);
5570
5946
  const resolvedModules = { ...PRESET_MODULES[preset], ...modules };
5571
5947
  const setRecoveryOpen = useCallback9(
5572
5948
  (open) => {
@@ -5590,10 +5966,12 @@ function useKeepWorkspace({
5590
5966
  }
5591
5967
 
5592
5968
  // src/features/workspace/KeepWorkspace.tsx
5593
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
5969
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
5594
5970
  function KeepWorkspace({
5595
5971
  preset = "standard",
5596
5972
  modules,
5973
+ surface,
5974
+ sectionGap,
5597
5975
  collectionProps,
5598
5976
  syncStatusProps,
5599
5977
  recoveryProps,
@@ -5622,38 +6000,64 @@ function KeepWorkspace({
5622
6000
  ...collectionProps,
5623
6001
  features: { ...view.collectionFeatures, ...collectionProps?.features }
5624
6002
  };
5625
- return /* @__PURE__ */ jsxs24("section", { ...props, className, "data-keepkit": "workspace", "data-preset": preset, children: [
5626
- resolveOptionalSlot(slots?.before, state),
5627
- view.modules.syncStatus ? resolveSlot(
5628
- slots?.syncStatus,
5629
- /* @__PURE__ */ jsx29(KeepSyncStatusBanner, { ...syncStatusProps, onResolveConflicts: view.openRecovery }),
5630
- state
5631
- ) : null,
5632
- resolveSlot(slots?.collection, /* @__PURE__ */ jsx29(KeepCollection, { ...resolvedCollectionProps }), state),
5633
- view.modules.backup || view.modules.stalePrune ? resolveSlot(
5634
- slots?.actions,
5635
- /* @__PURE__ */ jsxs24("div", { "data-keepkit": "workspace-actions", children: [
5636
- view.modules.stalePrune ? /* @__PURE__ */ jsx29(KeepPruneStaleButton, { ...stalePruneProps }) : null,
5637
- view.modules.backup ? /* @__PURE__ */ jsx29(KeepBackup, { ...backupProps }) : null
5638
- ] }),
5639
- state
5640
- ) : null,
5641
- view.modules.undo ? resolveSlot(slots?.undo, /* @__PURE__ */ jsx29(KeepUndo, { ...undoProps }), state) : null,
5642
- view.modules.recovery ? resolveSlot(
5643
- slots?.recovery,
5644
- /* @__PURE__ */ jsx29(
5645
- KeepSyncRecoveryDialog,
5646
- {
5647
- ...recoveryProps,
5648
- open: view.recoveryOpen,
5649
- onOpenChange: view.setRecoveryOpen
5650
- }
5651
- ),
5652
- state
5653
- ) : null,
5654
- resolveOptionalSlot(children, state),
5655
- resolveOptionalSlot(slots?.after, state)
5656
- ] });
6003
+ const structuredRegions = surface !== void 0 && surface !== "plain";
6004
+ const region = (name, content) => {
6005
+ if (!structuredRegions) return content;
6006
+ if (content === null || content === void 0 || content === false) return null;
6007
+ const resolvedSurface = typeof surface === "string" ? surface : surface[name] ?? "plain";
6008
+ return /* @__PURE__ */ jsx30("div", { "data-keepkit": "workspace-region", "data-region": name, "data-surface": resolvedSurface, children: content });
6009
+ };
6010
+ const before = resolveOptionalSlot(slots?.before, state);
6011
+ const syncStatus = view.modules.syncStatus ? resolveSlot(
6012
+ slots?.syncStatus,
6013
+ /* @__PURE__ */ jsx30(KeepSyncStatusBanner, { ...syncStatusProps, onResolveConflicts: view.openRecovery }),
6014
+ state
6015
+ ) : null;
6016
+ const collection = resolveSlot(slots?.collection, /* @__PURE__ */ jsx30(KeepCollection, { ...resolvedCollectionProps }), state);
6017
+ const actions = view.modules.backup || view.modules.stalePrune ? resolveSlot(
6018
+ slots?.actions,
6019
+ /* @__PURE__ */ jsxs25("div", { "data-keepkit": "workspace-actions", children: [
6020
+ view.modules.stalePrune ? /* @__PURE__ */ jsx30(KeepPruneStaleButton, { ...stalePruneProps }) : null,
6021
+ view.modules.backup ? /* @__PURE__ */ jsx30(KeepBackup, { ...backupProps }) : null
6022
+ ] }),
6023
+ state
6024
+ ) : null;
6025
+ const undo = view.modules.undo ? resolveSlot(slots?.undo, /* @__PURE__ */ jsx30(KeepUndo, { ...undoProps }), state) : null;
6026
+ const recovery = view.modules.recovery ? resolveSlot(
6027
+ slots?.recovery,
6028
+ /* @__PURE__ */ jsx30(
6029
+ KeepSyncRecoveryDialog,
6030
+ {
6031
+ ...recoveryProps,
6032
+ open: view.recoveryOpen,
6033
+ onOpenChange: view.setRecoveryOpen
6034
+ }
6035
+ ),
6036
+ state
6037
+ ) : null;
6038
+ const additionalContent = resolveOptionalSlot(children, state);
6039
+ const after = resolveOptionalSlot(slots?.after, state);
6040
+ return /* @__PURE__ */ jsxs25(
6041
+ "section",
6042
+ {
6043
+ ...props,
6044
+ className,
6045
+ "data-keepkit": "workspace",
6046
+ "data-preset": preset,
6047
+ "data-surface": surface !== void 0 ? typeof surface === "string" ? surface : "custom" : void 0,
6048
+ "data-section-gap": sectionGap,
6049
+ children: [
6050
+ region("before", before),
6051
+ region("syncStatus", syncStatus),
6052
+ region("collection", collection),
6053
+ region("actions", actions),
6054
+ region("undo", undo),
6055
+ region("recovery", recovery),
6056
+ region("children", additionalContent),
6057
+ region("after", after)
6058
+ ]
6059
+ }
6060
+ );
5657
6061
  }
5658
6062
  function resolveSlot(slot, fallback, state) {
5659
6063
  if (slot === void 0) return fallback;
@@ -5666,7 +6070,7 @@ function resolveOptionalSlot(slot, state) {
5666
6070
 
5667
6071
  // src/foundation/theme.tsx
5668
6072
  import { isValidElement as isValidElement9 } from "react";
5669
- import { jsx as jsx30 } from "react/jsx-runtime";
6073
+ import { jsx as jsx31 } from "react/jsx-runtime";
5670
6074
  var keepThemeNames = [
5671
6075
  "default",
5672
6076
  "ocean",
@@ -5725,7 +6129,7 @@ function KeepThemeProvider({
5725
6129
  throw new Error("KeepThemeProvider with asChild requires a single React element child.");
5726
6130
  return createSlot(children, rootProps);
5727
6131
  }
5728
- return /* @__PURE__ */ jsx30("div", { ...rootProps, children });
6132
+ return /* @__PURE__ */ jsx31("div", { ...rootProps, children });
5729
6133
  }
5730
6134
 
5731
6135
  // src/index.tsx
@@ -5733,7 +6137,8 @@ import { createAuthenticatedSyncKit } from "@keepkit/core/core";
5733
6137
  import {
5734
6138
  KeepErrorBoundary as KeepErrorBoundary3,
5735
6139
  KeepProvider,
5736
- useKeepContext as useKeepContext10,
6140
+ useKeepCollections as useKeepCollections3,
6141
+ useKeepContext as useKeepContext9,
5737
6142
  useKeepItem as useKeepItem8,
5738
6143
  useKeepList as useKeepList5,
5739
6144
  useKeepNavigator as useKeepNavigator2,
@@ -5749,7 +6154,7 @@ import {
5749
6154
  LocalStorageSyncQueueAdapter,
5750
6155
  SyncStorageAdapter
5751
6156
  } from "@keepkit/core/storage";
5752
- import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
6157
+ import { jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
5753
6158
  function KeepKitProvider({
5754
6159
  labels,
5755
6160
  locale,
@@ -5769,7 +6174,7 @@ function KeepKitProvider({
5769
6174
  children,
5770
6175
  ...providerProps
5771
6176
  }) {
5772
- return /* @__PURE__ */ jsx31(KeepUiProvider, { labels, locale, labelResolver, onFeedback, children: /* @__PURE__ */ jsx31(
6177
+ return /* @__PURE__ */ jsx32(KeepUiProvider, { labels, locale, labelResolver, onFeedback, children: /* @__PURE__ */ jsx32(
5773
6178
  KeepThemeProvider,
5774
6179
  {
5775
6180
  theme,
@@ -5783,10 +6188,10 @@ function KeepKitProvider({
5783
6188
  className: themeClassName,
5784
6189
  style: themeStyle,
5785
6190
  asChild: themeAsChild,
5786
- children: /* @__PURE__ */ jsxs25(CoreKeepProvider, { ...providerProps, children: [
5787
- /* @__PURE__ */ jsx31(KeepSyncFeedbackObserver, {}),
6191
+ children: /* @__PURE__ */ jsxs26(CoreKeepProvider, { ...providerProps, children: [
6192
+ /* @__PURE__ */ jsx32(KeepSyncFeedbackObserver, {}),
5788
6193
  children,
5789
- /* @__PURE__ */ jsx31(KeepAnnouncements, {})
6194
+ /* @__PURE__ */ jsx32(KeepAnnouncements, {})
5790
6195
  ] })
5791
6196
  }
5792
6197
  ) });
@@ -5813,7 +6218,7 @@ function createKeepKit(options = {}) {
5813
6218
  } = options;
5814
6219
  const coreKit = createCoreKeepKit(coreOptions);
5815
6220
  return {
5816
- Provider: (props) => /* @__PURE__ */ jsx31(
6221
+ Provider: (props) => /* @__PURE__ */ jsx32(
5817
6222
  KeepKitProvider,
5818
6223
  {
5819
6224
  ...coreOptions,
@@ -5834,9 +6239,9 @@ function createKeepKit(options = {}) {
5834
6239
  ...props
5835
6240
  }
5836
6241
  ),
5837
- Button: (props) => /* @__PURE__ */ jsx31(KeepButton, { ...props }),
5838
- Backup: (props) => /* @__PURE__ */ jsx31(KeepBackup, { ...props }),
5839
- Collection: (props) => /* @__PURE__ */ jsx31(
6242
+ Button: (props) => /* @__PURE__ */ jsx32(KeepButton, { ...props }),
6243
+ Backup: (props) => /* @__PURE__ */ jsx32(KeepBackup, { ...props }),
6244
+ Collection: (props) => /* @__PURE__ */ jsx32(
5840
6245
  KeepCollection,
5841
6246
  {
5842
6247
  ...props,
@@ -5847,7 +6252,7 @@ function createKeepKit(options = {}) {
5847
6252
  }
5848
6253
  }
5849
6254
  ),
5850
- Workspace: (props) => /* @__PURE__ */ jsx31(
6255
+ Workspace: (props) => /* @__PURE__ */ jsx32(
5851
6256
  KeepWorkspace,
5852
6257
  {
5853
6258
  ...props,
@@ -5864,6 +6269,7 @@ function createKeepKit(options = {}) {
5864
6269
  useContext: () => coreKit.useContext(),
5865
6270
  useItem: (item) => coreKit.useItem(item),
5866
6271
  useList: (query) => coreKit.useList(query),
6272
+ useCollections: (collectionsOptions) => coreKit.useCollections(collectionsOptions),
5867
6273
  useNavigator: (navigatorOptions) => coreKit.useNavigator(navigatorOptions),
5868
6274
  useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions)
5869
6275
  };
@@ -5876,6 +6282,7 @@ export {
5876
6282
  KeepAnnouncements,
5877
6283
  KeepAnnouncer,
5878
6284
  KeepArchiveButton,
6285
+ KeepArchiveScopeSelect,
5879
6286
  KeepBackup,
5880
6287
  KeepBulkActions,
5881
6288
  KeepButton,
@@ -5932,7 +6339,8 @@ export {
5932
6339
  keepThemeNames,
5933
6340
  mergeProps,
5934
6341
  toggleSelectAll,
5935
- useKeepContext10 as useKeepContext,
6342
+ useKeepCollections3 as useKeepCollections,
6343
+ useKeepContext9 as useKeepContext,
5936
6344
  useKeepItem8 as useKeepItem,
5937
6345
  useKeepList5 as useKeepList,
5938
6346
  useKeepNavigator2 as useKeepNavigator,