@keepkit/ui 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -88,15 +88,25 @@ function getBrowserAdapter() {
88
88
  };
89
89
  }
90
90
 
91
- // src/features/actions/hooks/useKeepBackup.ts
92
- import { useKeepContext } from "@keepkit/core/react";
93
- import { useRef as useRef2, useState } from "react";
91
+ // src/features/actions/KeepArchiveButton.tsx
92
+ import { useKeepItem } from "@keepkit/core/react";
94
93
 
95
94
  // src/foundation/ui-context.tsx
96
95
  import { createContext, useCallback, useContext, useMemo } from "react";
97
96
 
98
97
  // src/locales/de.ts
99
98
  var DE_LABELS = {
99
+ archive: "Archivieren",
100
+ unarchive: "Archivierung aufheben",
101
+ archived: "Archiviert",
102
+ pin: "Anheften",
103
+ unpin: "Anheften l\xF6sen",
104
+ pinned: "Angeheftet",
105
+ collection: "Sammlung",
106
+ allCollections: "Alle Sammlungen",
107
+ filterCollections: "Nach Sammlung filtern",
108
+ uncategorized: "Nicht kategorisiert",
109
+ saveWithNote: "Mit Notiz speichern",
100
110
  save: "Speichern",
101
111
  saved: "Gespeichert",
102
112
  remove: "Entfernen",
@@ -183,6 +193,17 @@ var DE_LABELS = {
183
193
 
184
194
  // src/locales/en.ts
185
195
  var EN_LABELS = {
196
+ archive: "Archive",
197
+ unarchive: "Unarchive",
198
+ archived: "Archived",
199
+ pin: "Pin",
200
+ unpin: "Unpin",
201
+ pinned: "Pinned",
202
+ collection: "Collection",
203
+ allCollections: "All collections",
204
+ filterCollections: "Filter collections",
205
+ uncategorized: "Uncategorized",
206
+ saveWithNote: "Save with note",
186
207
  save: "Save",
187
208
  saved: "Saved",
188
209
  remove: "Remove",
@@ -269,6 +290,17 @@ var EN_LABELS = {
269
290
 
270
291
  // src/locales/es.ts
271
292
  var ES_LABELS = {
293
+ archive: "Archivar",
294
+ unarchive: "Desarchivar",
295
+ archived: "Archivado",
296
+ pin: "Fijar",
297
+ unpin: "Desfijar",
298
+ pinned: "Fijado",
299
+ collection: "Colecci\xF3n",
300
+ allCollections: "Todas las colecciones",
301
+ filterCollections: "Filtrar por colecci\xF3n",
302
+ uncategorized: "Sin categor\xEDa",
303
+ saveWithNote: "Guardar con nota",
272
304
  save: "Guardar",
273
305
  saved: "Guardado",
274
306
  remove: "Eliminar",
@@ -355,6 +387,17 @@ var ES_LABELS = {
355
387
 
356
388
  // src/locales/fil.ts
357
389
  var FIL_LABELS = {
390
+ archive: "I-archive",
391
+ unarchive: "Alisin sa archive",
392
+ archived: "Naka-archive",
393
+ pin: "I-pin",
394
+ unpin: "Alisin ang pin",
395
+ pinned: "Naka-pin",
396
+ collection: "Koleksyon",
397
+ allCollections: "Lahat ng koleksyon",
398
+ filterCollections: "I-filter ayon sa koleksyon",
399
+ uncategorized: "Walang kategorya",
400
+ saveWithNote: "I-save na may tala",
358
401
  save: "I-save",
359
402
  saved: "Nai-save",
360
403
  remove: "Alisin",
@@ -441,6 +484,17 @@ var FIL_LABELS = {
441
484
 
442
485
  // src/locales/fr.ts
443
486
  var FR_LABELS = {
487
+ archive: "Archiver",
488
+ unarchive: "D\xE9sarchiver",
489
+ archived: "Archiv\xE9",
490
+ pin: "\xC9pingler",
491
+ unpin: "D\xE9s\xE9pingler",
492
+ pinned: "\xC9pingl\xE9",
493
+ collection: "Collection",
494
+ allCollections: "Toutes les collections",
495
+ filterCollections: "Filtrer par collection",
496
+ uncategorized: "Non class\xE9",
497
+ saveWithNote: "Enregistrer avec une note",
444
498
  save: "Enregistrer",
445
499
  saved: "Enregistr\xE9",
446
500
  remove: "Supprimer",
@@ -527,6 +581,17 @@ var FR_LABELS = {
527
581
 
528
582
  // src/locales/id.ts
529
583
  var ID_LABELS = {
584
+ archive: "Arsipkan",
585
+ unarchive: "Batalkan arsip",
586
+ archived: "Diarsipkan",
587
+ pin: "Sematkan",
588
+ unpin: "Lepas sematan",
589
+ pinned: "Disematkan",
590
+ collection: "Koleksi",
591
+ allCollections: "Semua koleksi",
592
+ filterCollections: "Filter koleksi",
593
+ uncategorized: "Tanpa kategori",
594
+ saveWithNote: "Simpan dengan catatan",
530
595
  save: "Simpan",
531
596
  saved: "Tersimpan",
532
597
  remove: "Hapus",
@@ -613,6 +678,17 @@ var ID_LABELS = {
613
678
 
614
679
  // src/locales/it.ts
615
680
  var IT_LABELS = {
681
+ archive: "Archivia",
682
+ unarchive: "Rimuovi dall'archivio",
683
+ archived: "Archiviato",
684
+ pin: "Fissa",
685
+ unpin: "Rimuovi fissaggio",
686
+ pinned: "Fissato",
687
+ collection: "Raccolta",
688
+ allCollections: "Tutte le raccolte",
689
+ filterCollections: "Filtra per raccolta",
690
+ uncategorized: "Senza categoria",
691
+ saveWithNote: "Salva con nota",
616
692
  save: "Salva",
617
693
  saved: "Salvato",
618
694
  remove: "Rimuovi",
@@ -699,6 +775,17 @@ var IT_LABELS = {
699
775
 
700
776
  // src/locales/ja.ts
701
777
  var JA_LABELS = {
778
+ archive: "\u30A2\u30FC\u30AB\u30A4\u30D6",
779
+ unarchive: "\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u89E3\u9664",
780
+ archived: "\u30A2\u30FC\u30AB\u30A4\u30D6\u6E08\u307F",
781
+ pin: "\u30D4\u30F3\u7559\u3081",
782
+ unpin: "\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664",
783
+ pinned: "\u30D4\u30F3\u7559\u3081\u6E08\u307F",
784
+ collection: "\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3",
785
+ allCollections: "\u3059\u3079\u3066\u306E\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3",
786
+ filterCollections: "\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u3067\u7D5E\u308A\u8FBC\u3080",
787
+ uncategorized: "\u672A\u5206\u985E",
788
+ saveWithNote: "\u30E1\u30E2\u4ED8\u304D\u3067\u4FDD\u5B58",
702
789
  save: "\u4FDD\u5B58",
703
790
  saved: "\u4FDD\u5B58\u6E08\u307F",
704
791
  remove: "\u524A\u9664",
@@ -785,6 +872,17 @@ var JA_LABELS = {
785
872
 
786
873
  // src/locales/ko.ts
787
874
  var KO_LABELS = {
875
+ archive: "\uBCF4\uAD00",
876
+ unarchive: "\uBCF4\uAD00 \uD574\uC81C",
877
+ archived: "\uBCF4\uAD00\uB428",
878
+ pin: "\uACE0\uC815",
879
+ unpin: "\uACE0\uC815 \uD574\uC81C",
880
+ pinned: "\uACE0\uC815\uB428",
881
+ collection: "\uCEEC\uB809\uC158",
882
+ allCollections: "\uBAA8\uB4E0 \uCEEC\uB809\uC158",
883
+ filterCollections: "\uCEEC\uB809\uC158 \uD544\uD130",
884
+ uncategorized: "\uBBF8\uBD84\uB958",
885
+ saveWithNote: "\uBA54\uBAA8\uC640 \uD568\uAED8 \uC800\uC7A5",
788
886
  save: "\uC800\uC7A5",
789
887
  saved: "\uC800\uC7A5\uB428",
790
888
  remove: "\uC0AD\uC81C",
@@ -871,6 +969,17 @@ var KO_LABELS = {
871
969
 
872
970
  // src/locales/ms.ts
873
971
  var MS_LABELS = {
972
+ archive: "Arkibkan",
973
+ unarchive: "Nyaharkib",
974
+ archived: "Diarkibkan",
975
+ pin: "Pin",
976
+ unpin: "Nyahpin",
977
+ pinned: "Dipinkan",
978
+ collection: "Koleksi",
979
+ allCollections: "Semua koleksi",
980
+ filterCollections: "Tapis koleksi",
981
+ uncategorized: "Tiada kategori",
982
+ saveWithNote: "Simpan dengan nota",
874
983
  save: "Simpan",
875
984
  saved: "Disimpan",
876
985
  remove: "Buang",
@@ -957,6 +1066,17 @@ var MS_LABELS = {
957
1066
 
958
1067
  // src/locales/pt-BR.ts
959
1068
  var PT_BR_LABELS = {
1069
+ archive: "Arquivar",
1070
+ unarchive: "Desarquivar",
1071
+ archived: "Arquivado",
1072
+ pin: "Fixar",
1073
+ unpin: "Desafixar",
1074
+ pinned: "Fixado",
1075
+ collection: "Cole\xE7\xE3o",
1076
+ allCollections: "Todas as cole\xE7\xF5es",
1077
+ filterCollections: "Filtrar por cole\xE7\xE3o",
1078
+ uncategorized: "Sem categoria",
1079
+ saveWithNote: "Salvar com nota",
960
1080
  save: "Salvar",
961
1081
  saved: "Salvo",
962
1082
  remove: "Remover",
@@ -1043,6 +1163,17 @@ var PT_BR_LABELS = {
1043
1163
 
1044
1164
  // src/locales/ru.ts
1045
1165
  var RU_LABELS = {
1166
+ archive: "\u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
1167
+ unarchive: "\u0420\u0430\u0437\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
1168
+ archived: "\u0412 \u0430\u0440\u0445\u0438\u0432\u0435",
1169
+ pin: "\u0417\u0430\u043A\u0440\u0435\u043F\u0438\u0442\u044C",
1170
+ unpin: "\u041E\u0442\u043A\u0440\u0435\u043F\u0438\u0442\u044C",
1171
+ pinned: "\u0417\u0430\u043A\u0440\u0435\u043F\u043B\u0435\u043D\u043E",
1172
+ collection: "\u041A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u044F",
1173
+ allCollections: "\u0412\u0441\u0435 \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u0438",
1174
+ filterCollections: "\u0424\u0438\u043B\u044C\u0442\u0440 \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u0439",
1175
+ uncategorized: "\u0411\u0435\u0437 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438",
1176
+ saveWithNote: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0441 \u0437\u0430\u043C\u0435\u0442\u043A\u043E\u0439",
1046
1177
  save: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C",
1047
1178
  saved: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E",
1048
1179
  remove: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
@@ -1129,6 +1260,17 @@ var RU_LABELS = {
1129
1260
 
1130
1261
  // src/locales/th.ts
1131
1262
  var TH_LABELS = {
1263
+ archive: "\u0E40\u0E01\u0E47\u0E1A\u0E16\u0E32\u0E27\u0E23",
1264
+ unarchive: "\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01\u0E01\u0E32\u0E23\u0E40\u0E01\u0E47\u0E1A\u0E16\u0E32\u0E27\u0E23",
1265
+ archived: "\u0E40\u0E01\u0E47\u0E1A\u0E16\u0E32\u0E27\u0E23\u0E41\u0E25\u0E49\u0E27",
1266
+ pin: "\u0E1B\u0E31\u0E01\u0E2B\u0E21\u0E38\u0E14",
1267
+ unpin: "\u0E40\u0E25\u0E34\u0E01\u0E1B\u0E31\u0E01\u0E2B\u0E21\u0E38\u0E14",
1268
+ pinned: "\u0E1B\u0E31\u0E01\u0E2B\u0E21\u0E38\u0E14\u0E41\u0E25\u0E49\u0E27",
1269
+ collection: "\u0E04\u0E2D\u0E25\u0E40\u0E25\u0E01\u0E0A\u0E31\u0E19",
1270
+ allCollections: "\u0E04\u0E2D\u0E25\u0E40\u0E25\u0E01\u0E0A\u0E31\u0E19\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14",
1271
+ filterCollections: "\u0E01\u0E23\u0E2D\u0E07\u0E04\u0E2D\u0E25\u0E40\u0E25\u0E01\u0E0A\u0E31\u0E19",
1272
+ uncategorized: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E2B\u0E21\u0E27\u0E14\u0E2B\u0E21\u0E39\u0E48",
1273
+ saveWithNote: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E42\u0E19\u0E49\u0E15",
1132
1274
  save: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
1133
1275
  saved: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E41\u0E25\u0E49\u0E27",
1134
1276
  remove: "\u0E25\u0E1A",
@@ -1215,6 +1357,17 @@ var TH_LABELS = {
1215
1357
 
1216
1358
  // src/locales/vi.ts
1217
1359
  var VI_LABELS = {
1360
+ archive: "L\u01B0u tr\u1EEF",
1361
+ unarchive: "B\u1ECF l\u01B0u tr\u1EEF",
1362
+ archived: "\u0110\xE3 l\u01B0u tr\u1EEF",
1363
+ pin: "Ghim",
1364
+ unpin: "B\u1ECF ghim",
1365
+ pinned: "\u0110\xE3 ghim",
1366
+ collection: "B\u1ED9 s\u01B0u t\u1EADp",
1367
+ allCollections: "T\u1EA5t c\u1EA3 b\u1ED9 s\u01B0u t\u1EADp",
1368
+ filterCollections: "L\u1ECDc theo b\u1ED9 s\u01B0u t\u1EADp",
1369
+ uncategorized: "Ch\u01B0a ph\xE2n lo\u1EA1i",
1370
+ saveWithNote: "L\u01B0u k\xE8m ghi ch\xFA",
1218
1371
  save: "L\u01B0u",
1219
1372
  saved: "\u0110\xE3 l\u01B0u",
1220
1373
  remove: "X\xF3a",
@@ -1301,6 +1454,17 @@ var VI_LABELS = {
1301
1454
 
1302
1455
  // src/locales/zh-Hans.ts
1303
1456
  var ZH_HANS_LABELS = {
1457
+ archive: "\u5F52\u6863",
1458
+ unarchive: "\u53D6\u6D88\u5F52\u6863",
1459
+ archived: "\u5DF2\u5F52\u6863",
1460
+ pin: "\u7F6E\u9876",
1461
+ unpin: "\u53D6\u6D88\u7F6E\u9876",
1462
+ pinned: "\u5DF2\u7F6E\u9876",
1463
+ collection: "\u96C6\u5408",
1464
+ allCollections: "\u6240\u6709\u96C6\u5408",
1465
+ filterCollections: "\u6309\u96C6\u5408\u7B5B\u9009",
1466
+ uncategorized: "\u672A\u5206\u7C7B",
1467
+ saveWithNote: "\u4FDD\u5B58\u5E76\u6DFB\u52A0\u5907\u6CE8",
1304
1468
  save: "\u4FDD\u5B58",
1305
1469
  saved: "\u5DF2\u4FDD\u5B58",
1306
1470
  remove: "\u5220\u9664",
@@ -1387,6 +1551,17 @@ var ZH_HANS_LABELS = {
1387
1551
 
1388
1552
  // src/locales/zh-Hant.ts
1389
1553
  var ZH_HANT_LABELS = {
1554
+ archive: "\u5C01\u5B58",
1555
+ unarchive: "\u53D6\u6D88\u5C01\u5B58",
1556
+ archived: "\u5DF2\u5C01\u5B58",
1557
+ pin: "\u91D8\u9078",
1558
+ unpin: "\u53D6\u6D88\u91D8\u9078",
1559
+ pinned: "\u5DF2\u91D8\u9078",
1560
+ collection: "\u6536\u85CF\u96C6",
1561
+ allCollections: "\u6240\u6709\u6536\u85CF\u96C6",
1562
+ filterCollections: "\u4F9D\u6536\u85CF\u96C6\u7BE9\u9078",
1563
+ uncategorized: "\u672A\u5206\u985E",
1564
+ saveWithNote: "\u5132\u5B58\u4E26\u52A0\u5099\u8A3B",
1390
1565
  save: "\u5132\u5B58",
1391
1566
  saved: "\u5DF2\u5132\u5B58",
1392
1567
  remove: "\u522A\u9664",
@@ -1570,7 +1745,84 @@ function useKeepUiFeedback() {
1570
1745
  return useCallback((event) => emitFeedback(event), [emitFeedback]);
1571
1746
  }
1572
1747
 
1748
+ // src/features/actions/KeepArchiveButton.tsx
1749
+ import { jsxs } from "react/jsx-runtime";
1750
+ function KeepArchiveButton({
1751
+ item,
1752
+ children,
1753
+ archiveLabel,
1754
+ unarchiveLabel,
1755
+ onToggleError,
1756
+ disabled,
1757
+ ...props
1758
+ }) {
1759
+ const state = useKeepItem(item);
1760
+ const archive = useUiLabel("archive");
1761
+ const unarchive = useUiLabel("unarchive");
1762
+ const archivedLabel = useUiLabel("archived");
1763
+ const isArchived = state.item?.archived === true;
1764
+ const isDisabled = disabled ?? state.isMutating;
1765
+ return /* @__PURE__ */ jsxs(
1766
+ "button",
1767
+ {
1768
+ ...props,
1769
+ type: props.type ?? "button",
1770
+ disabled: isDisabled,
1771
+ "aria-pressed": isArchived,
1772
+ "data-archived": isArchived ? "true" : "false",
1773
+ "data-keep-action": "toggle-archive",
1774
+ onClick: () => void state.toggleArchive().catch((error) => onToggleError?.(error)),
1775
+ children: [
1776
+ typeof children === "function" ? children(state) : children ?? (isArchived ? unarchiveLabel ?? unarchive : archiveLabel ?? archive),
1777
+ isArchived && children === void 0 ? /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", children: [
1778
+ " (",
1779
+ archivedLabel,
1780
+ ")"
1781
+ ] }) : null
1782
+ ]
1783
+ }
1784
+ );
1785
+ }
1786
+ function KeepPinButton({
1787
+ item,
1788
+ children,
1789
+ pinLabel,
1790
+ unpinLabel,
1791
+ onToggleError,
1792
+ disabled,
1793
+ ...props
1794
+ }) {
1795
+ const state = useKeepItem(item);
1796
+ const pin = useUiLabel("pin");
1797
+ const unpin = useUiLabel("unpin");
1798
+ const pinnedLabel = useUiLabel("pinned");
1799
+ const isPinned = state.item?.pinned === true;
1800
+ const isDisabled = disabled ?? state.isMutating;
1801
+ return /* @__PURE__ */ jsxs(
1802
+ "button",
1803
+ {
1804
+ ...props,
1805
+ type: props.type ?? "button",
1806
+ disabled: isDisabled,
1807
+ "aria-pressed": isPinned,
1808
+ "data-pinned": isPinned ? "true" : "false",
1809
+ "data-keep-action": "toggle-pin",
1810
+ onClick: () => void state.togglePin().catch((error) => onToggleError?.(error)),
1811
+ children: [
1812
+ typeof children === "function" ? children(state) : children ?? (isPinned ? unpinLabel ?? unpin : pinLabel ?? pin),
1813
+ isPinned && children === void 0 ? /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", children: [
1814
+ " (",
1815
+ pinnedLabel,
1816
+ ")"
1817
+ ] }) : null
1818
+ ]
1819
+ }
1820
+ );
1821
+ }
1822
+
1573
1823
  // src/features/actions/hooks/useKeepBackup.ts
1824
+ import { useKeepContext } from "@keepkit/core/react";
1825
+ import { useRef as useRef2, useState } from "react";
1574
1826
  function useKeepBackup({ filename, onExport, onImported }) {
1575
1827
  const context = useKeepContext();
1576
1828
  const inputRef = useRef2(null);
@@ -1631,7 +1883,7 @@ function useKeepBackup({ filename, onExport, onImported }) {
1631
1883
  }
1632
1884
 
1633
1885
  // src/features/actions/KeepBackup.tsx
1634
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1886
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1635
1887
  function KeepBackup({
1636
1888
  filename = "keepkit-backup.json",
1637
1889
  onExport,
@@ -1639,7 +1891,7 @@ function KeepBackup({
1639
1891
  ...props
1640
1892
  }) {
1641
1893
  const view = useKeepBackup({ filename, onExport, onImported });
1642
- return /* @__PURE__ */ jsxs(
1894
+ return /* @__PURE__ */ jsxs2(
1643
1895
  "section",
1644
1896
  {
1645
1897
  ...props,
@@ -1657,9 +1909,9 @@ function KeepBackup({
1657
1909
  children: view.labels.export
1658
1910
  }
1659
1911
  ),
1660
- /* @__PURE__ */ jsxs("label", { children: [
1912
+ /* @__PURE__ */ jsxs2("label", { children: [
1661
1913
  view.labels.importMode,
1662
- /* @__PURE__ */ jsxs(
1914
+ /* @__PURE__ */ jsxs2(
1663
1915
  "select",
1664
1916
  {
1665
1917
  "data-keep-action": "select-import-mode",
@@ -1684,7 +1936,7 @@ function KeepBackup({
1684
1936
  onChange: (event) => void view.importBackup(event)
1685
1937
  }
1686
1938
  ),
1687
- view.result ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
1939
+ view.result ? /* @__PURE__ */ jsxs2("p", { role: "status", children: [
1688
1940
  view.result.imported,
1689
1941
  " ",
1690
1942
  view.labels.importedCount,
@@ -1763,7 +2015,10 @@ function toKeepButtonItem(item) {
1763
2015
  meta: item.meta,
1764
2016
  targetType: item.targetType,
1765
2017
  note: item.note,
1766
- tags: item.tags
2018
+ tags: item.tags,
2019
+ archived: item.archived,
2020
+ pinned: item.pinned,
2021
+ collectionId: item.collectionId
1767
2022
  };
1768
2023
  }
1769
2024
  function getMetaTitle(meta) {
@@ -1986,7 +2241,7 @@ function getItemLabel(item) {
1986
2241
  }
1987
2242
 
1988
2243
  // src/features/actions/KeepBulkActions.tsx
1989
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
2244
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1990
2245
  function KeepBulkActions({
1991
2246
  query,
1992
2247
  selectedIds: controlledSelectedIds,
@@ -2009,12 +2264,12 @@ function KeepBulkActions({
2009
2264
  controlledScope,
2010
2265
  onSelectionScopeChange
2011
2266
  });
2012
- const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs2(Fragment2, { children: [
2013
- /* @__PURE__ */ jsxs2("fieldset", { children: [
2267
+ const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs3(Fragment2, { children: [
2268
+ /* @__PURE__ */ jsxs3("fieldset", { children: [
2014
2269
  /* @__PURE__ */ jsx5("legend", { children: labels.selectItems }),
2015
- /* @__PURE__ */ jsxs2("label", { children: [
2270
+ /* @__PURE__ */ jsxs3("label", { children: [
2016
2271
  labels.selectionScope,
2017
- /* @__PURE__ */ jsxs2(
2272
+ /* @__PURE__ */ jsxs3(
2018
2273
  "select",
2019
2274
  {
2020
2275
  "data-keep-action": "select-scope",
@@ -2028,7 +2283,7 @@ function KeepBulkActions({
2028
2283
  }
2029
2284
  )
2030
2285
  ] }),
2031
- /* @__PURE__ */ jsxs2("label", { children: [
2286
+ /* @__PURE__ */ jsxs3("label", { children: [
2032
2287
  /* @__PURE__ */ jsx5(
2033
2288
  "input",
2034
2289
  {
@@ -2043,7 +2298,7 @@ function KeepBulkActions({
2043
2298
  " ",
2044
2299
  labels.selectedCount
2045
2300
  ] }),
2046
- state.items.map((item) => /* @__PURE__ */ jsxs2("span", { children: [
2301
+ state.items.map((item) => /* @__PURE__ */ jsxs3("span", { children: [
2047
2302
  /* @__PURE__ */ jsx5(
2048
2303
  KeepItemCheckbox,
2049
2304
  {
@@ -2065,7 +2320,7 @@ function KeepBulkActions({
2065
2320
  children: labels.deleteSelected
2066
2321
  }
2067
2322
  ),
2068
- /* @__PURE__ */ jsxs2("label", { children: [
2323
+ /* @__PURE__ */ jsxs3("label", { children: [
2069
2324
  labels.tags,
2070
2325
  /* @__PURE__ */ jsx5(
2071
2326
  "input",
@@ -2107,10 +2362,10 @@ import {
2107
2362
  import { createElement, useEffect as useEffect2, useRef as useRef3 } from "react";
2108
2363
 
2109
2364
  // src/features/actions/hooks/useKeepButton.ts
2110
- import { useKeepItem } from "@keepkit/core/react";
2365
+ import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
2111
2366
  function useKeepButton({ item, labels, icons, children }) {
2112
2367
  return {
2113
- buttonState: useKeepItem(item),
2368
+ buttonState: useKeepItem2(item),
2114
2369
  emitFeedback: useKeepUiFeedback(),
2115
2370
  customStateLabel: labels?.loading !== void 0 || labels?.error !== void 0 || icons !== void 0 && children === void 0,
2116
2371
  labels: {
@@ -2127,7 +2382,7 @@ function useKeepButton({ item, labels, icons, children }) {
2127
2382
  }
2128
2383
 
2129
2384
  // src/features/actions/KeepButton.tsx
2130
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
2385
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
2131
2386
  function KeepButton({
2132
2387
  labels,
2133
2388
  icons,
@@ -2172,7 +2427,7 @@ function KeepButton({
2172
2427
  const label = state.error ? labels?.error ?? view.labels.error : state.isMutating ? labels?.loading ?? view.labels.loading : state.isSaved ? labels?.saved ?? view.labels.saved : labels?.unsaved ?? view.labels.save;
2173
2428
  if (!icons) return label;
2174
2429
  const icon = state.error ? icons.error : state.isMutating ? icons.loading : state.isSaved ? icons.remove ?? icons.saved : icons.save;
2175
- return /* @__PURE__ */ jsxs3(Fragment3, { children: [
2430
+ return /* @__PURE__ */ jsxs4(Fragment3, { children: [
2176
2431
  renderIcon(icon, iconClassName),
2177
2432
  showLabel && !iconOnly ? label : null
2178
2433
  ] });
@@ -2207,16 +2462,259 @@ function renderIcon(icon, className) {
2207
2462
  return icon ?? null;
2208
2463
  }
2209
2464
 
2465
+ // src/features/actions/KeepSavePopover.tsx
2466
+ import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
2467
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef5, useState as useState4 } from "react";
2468
+
2469
+ // src/features/editor/KeepQuickEditor.tsx
2470
+ import { useKeepContext as useKeepContext2, useKeepItem as useKeepItem3 } from "@keepkit/core/react";
2471
+ import {
2472
+ useCallback as useCallback2,
2473
+ useEffect as useEffect3,
2474
+ useRef as useRef4,
2475
+ useState as useState3
2476
+ } from "react";
2477
+ import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2478
+ function useKeepQuickEditor(item, options = {}) {
2479
+ const { debounceMs = 300, onSaved, onSaveError } = options;
2480
+ const itemState = useKeepItem3(item);
2481
+ const { error, isMutating, moveToCollection, updateNote, updateTags } = itemState;
2482
+ const baseline = itemState.item ?? item;
2483
+ const [note, setNote] = useState3(baseline.note ?? "");
2484
+ const [tags, setTags] = useState3(baseline.tags ?? []);
2485
+ const [collectionId, setCollectionId] = useState3(baseline.collectionId);
2486
+ const baselineRef = useRef4({
2487
+ note: baseline.note ?? "",
2488
+ tags: baseline.tags ?? [],
2489
+ collectionId: baseline.collectionId
2490
+ });
2491
+ const draftRef = useRef4({ note, tags, collectionId });
2492
+ draftRef.current = { note, tags, collectionId };
2493
+ useEffect3(() => {
2494
+ if (draftRef.current.note === baselineRef.current.note && sameTags(draftRef.current.tags, baselineRef.current.tags) && draftRef.current.collectionId === baselineRef.current.collectionId) {
2495
+ setNote(baseline.note ?? "");
2496
+ setTags(baseline.tags ?? []);
2497
+ setCollectionId(baseline.collectionId);
2498
+ baselineRef.current = {
2499
+ note: baseline.note ?? "",
2500
+ tags: baseline.tags ?? [],
2501
+ collectionId: baseline.collectionId
2502
+ };
2503
+ }
2504
+ }, [baseline]);
2505
+ const isDirty = note !== baselineRef.current.note || !sameTags(tags, baselineRef.current.tags) || collectionId !== baselineRef.current.collectionId;
2506
+ const flush = useCallback2(async () => {
2507
+ const draft = draftRef.current;
2508
+ try {
2509
+ if (draft.note !== baselineRef.current.note) await updateNote(draft.note.trim() || void 0);
2510
+ if (!sameTags(draft.tags, baselineRef.current.tags)) await updateTags(draft.tags);
2511
+ if (draft.collectionId !== baselineRef.current.collectionId) await moveToCollection(draft.collectionId);
2512
+ baselineRef.current = { note: draft.note, tags: [...draft.tags], collectionId: draft.collectionId };
2513
+ const { collectionId: _oldCollectionId, ...withoutCollection } = baseline;
2514
+ onSaved?.({
2515
+ ...withoutCollection,
2516
+ note: draft.note.trim() || void 0,
2517
+ tags: draft.tags,
2518
+ ...draft.collectionId ? { collectionId: draft.collectionId } : {}
2519
+ });
2520
+ } catch (error2) {
2521
+ onSaveError?.(error2);
2522
+ throw error2;
2523
+ }
2524
+ }, [baseline, moveToCollection, onSaveError, onSaved, updateNote, updateTags]);
2525
+ useEffect3(() => {
2526
+ if (!isDirty || debounceMs <= 0) return;
2527
+ const timer = window.setTimeout(() => void flush().catch(() => void 0), debounceMs);
2528
+ return () => window.clearTimeout(timer);
2529
+ }, [debounceMs, flush, isDirty]);
2530
+ return {
2531
+ state: {
2532
+ item,
2533
+ note,
2534
+ tags,
2535
+ collectionId,
2536
+ setNote,
2537
+ setTags,
2538
+ setCollectionId,
2539
+ isDirty,
2540
+ isSaving: isMutating,
2541
+ error,
2542
+ flush
2543
+ }
2544
+ };
2545
+ }
2546
+ function KeepQuickEditor({
2547
+ item,
2548
+ debounceMs = 300,
2549
+ collectionIds,
2550
+ collectionLabels,
2551
+ children,
2552
+ onClose,
2553
+ onSaved,
2554
+ onSaveError,
2555
+ ...props
2556
+ }) {
2557
+ const view = useKeepQuickEditor(item, { debounceMs, onSaved, onSaveError });
2558
+ const context = useKeepContext2();
2559
+ const { state } = view;
2560
+ const rootRef = useRef4(null);
2561
+ const noteLabel = useUiLabel("note");
2562
+ const tagsLabel = useUiLabel("tags");
2563
+ const collectionLabel = useUiLabel("collection");
2564
+ const uncategorizedLabel = useUiLabel("uncategorized");
2565
+ const saveLabel = useUiLabel("saveWithNote");
2566
+ const closeLabel = useUiLabel("close");
2567
+ const submit = (event) => {
2568
+ event.preventDefault();
2569
+ void state.flush().catch(() => void 0);
2570
+ };
2571
+ const onKeyDown = (event) => {
2572
+ if (event.key === "Escape") {
2573
+ event.preventDefault();
2574
+ void state.flush().then(() => onClose?.()).catch(() => void 0);
2575
+ }
2576
+ if (event.key === "Tab") trapFocus(event, rootRef.current);
2577
+ };
2578
+ const body = typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
2579
+ /* @__PURE__ */ jsxs5("label", { children: [
2580
+ noteLabel,
2581
+ /* @__PURE__ */ jsx7("textarea", { value: state.note, onChange: (event) => state.setNote(event.currentTarget.value) })
2582
+ ] }),
2583
+ /* @__PURE__ */ jsxs5("label", { children: [
2584
+ tagsLabel,
2585
+ /* @__PURE__ */ jsx7(
2586
+ "input",
2587
+ {
2588
+ value: state.tags.join(", "),
2589
+ onChange: (event) => state.setTags(
2590
+ event.currentTarget.value.split(",").map((tag) => tag.trim()).filter(Boolean)
2591
+ )
2592
+ }
2593
+ )
2594
+ ] }),
2595
+ /* @__PURE__ */ jsxs5("label", { children: [
2596
+ collectionLabel,
2597
+ /* @__PURE__ */ jsxs5(
2598
+ "select",
2599
+ {
2600
+ value: state.collectionId ?? "",
2601
+ onChange: (event) => state.setCollectionId(event.currentTarget.value || void 0),
2602
+ children: [
2603
+ /* @__PURE__ */ jsx7("option", { value: "", children: uncategorizedLabel }),
2604
+ (collectionIds ?? [
2605
+ ...new Set(
2606
+ context.items.map((entry) => entry.collectionId).filter((id) => Boolean(id))
2607
+ )
2608
+ ].sort()).map((id) => /* @__PURE__ */ jsx7("option", { value: id, children: collectionLabels?.[id] ?? id }, id))
2609
+ ]
2610
+ }
2611
+ )
2612
+ ] }),
2613
+ /* @__PURE__ */ jsx7("button", { type: "submit", disabled: state.isSaving, "data-keep-action": "save-quick-edit", children: saveLabel }),
2614
+ /* @__PURE__ */ jsx7(
2615
+ "button",
2616
+ {
2617
+ type: "button",
2618
+ onClick: () => void state.flush().then(() => onClose?.()).catch(() => void 0),
2619
+ disabled: state.isSaving,
2620
+ "data-keep-action": "close-quick-edit",
2621
+ children: closeLabel
2622
+ }
2623
+ )
2624
+ ] });
2625
+ return /* @__PURE__ */ jsx7(
2626
+ "form",
2627
+ {
2628
+ ...props,
2629
+ ref: rootRef,
2630
+ onSubmit: submit,
2631
+ onKeyDown,
2632
+ "data-keepkit": "quick-editor",
2633
+ "data-state": state.isDirty ? "dirty" : "clean",
2634
+ "aria-busy": state.isSaving || props["aria-busy"],
2635
+ children: body
2636
+ }
2637
+ );
2638
+ }
2639
+ function sameTags(left, right) {
2640
+ return left.length === right.length && left.every((tag, index) => tag === right[index]);
2641
+ }
2642
+ function trapFocus(event, root) {
2643
+ if (!root) return;
2644
+ const elements = [
2645
+ ...root.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
2646
+ ].filter((element) => !element.hasAttribute("disabled"));
2647
+ if (elements.length === 0) return;
2648
+ const first = elements[0];
2649
+ const last = elements[elements.length - 1];
2650
+ if (event.shiftKey && document.activeElement === first) {
2651
+ event.preventDefault();
2652
+ last.focus();
2653
+ } else if (!event.shiftKey && document.activeElement === last) {
2654
+ event.preventDefault();
2655
+ first.focus();
2656
+ }
2657
+ }
2658
+
2659
+ // src/features/actions/KeepSavePopover.tsx
2660
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2661
+ function KeepSavePopover({
2662
+ item,
2663
+ open: controlledOpen,
2664
+ defaultOpen = false,
2665
+ onOpenChange,
2666
+ buttonProps,
2667
+ editorProps,
2668
+ children,
2669
+ ...props
2670
+ }) {
2671
+ const state = useKeepItem4(item);
2672
+ const [internalOpen, setInternalOpen] = useState4(defaultOpen);
2673
+ const isOpen = controlledOpen ?? internalOpen;
2674
+ const triggerRef = useRef5(null);
2675
+ const previousSaved = useRef5(state.isSaved);
2676
+ const observedHydration = useRef5(!state.isLoading);
2677
+ const closeLabel = useUiLabel("close");
2678
+ const { ref: _buttonRef, ...resolvedButtonProps } = buttonProps ?? {};
2679
+ const setOpen = useCallback3(
2680
+ (next) => {
2681
+ if (controlledOpen === void 0) setInternalOpen(next);
2682
+ onOpenChange?.(next);
2683
+ if (!next) window.setTimeout(() => triggerRef.current?.focus(), 0);
2684
+ },
2685
+ [controlledOpen, onOpenChange]
2686
+ );
2687
+ useEffect4(() => {
2688
+ if (!observedHydration.current) {
2689
+ if (state.isLoading) return;
2690
+ observedHydration.current = true;
2691
+ previousSaved.current = state.isSaved;
2692
+ return;
2693
+ }
2694
+ if (!previousSaved.current && state.isSaved) setOpen(true);
2695
+ previousSaved.current = state.isSaved;
2696
+ }, [setOpen, state.isLoading, state.isSaved]);
2697
+ const currentItem = state.item;
2698
+ return /* @__PURE__ */ jsxs6("div", { ...props, "data-keepkit": "save-popover", "data-open": isOpen ? "true" : "false", children: [
2699
+ /* @__PURE__ */ jsx8(KeepButton, { ...resolvedButtonProps, item, asChild: false, ref: triggerRef }),
2700
+ isOpen && currentItem ? /* @__PURE__ */ jsxs6("div", { role: "dialog", "aria-label": children ? void 0 : closeLabel, "data-keep-popover-panel": "true", children: [
2701
+ children,
2702
+ /* @__PURE__ */ jsx8(KeepQuickEditor, { ...editorProps, item: currentItem, onClose: () => setOpen(false) }),
2703
+ /* @__PURE__ */ jsx8("button", { type: "button", onClick: () => setOpen(false), "data-keep-action": "close-save-popover", children: closeLabel })
2704
+ ] }) : null
2705
+ ] });
2706
+ }
2707
+
2210
2708
  // src/features/actions/hooks/useKeepUndo.ts
2211
- import { useKeepContext as useKeepContext2 } from "@keepkit/core/react";
2212
- import { useEffect as useEffect3, useState as useState3 } from "react";
2709
+ import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
2710
+ import { useEffect as useEffect5, useState as useState5 } from "react";
2213
2711
  function useKeepUndo() {
2214
- const context = useKeepContext2();
2712
+ const context = useKeepContext3();
2215
2713
  const emitFeedback = useKeepUiFeedback();
2216
2714
  const restoredMessage = useUiLabel("restoredMessage");
2217
2715
  const { canUndo, startedAt, expiresAt } = context.undo;
2218
- const [now, setNow] = useState3(() => Date.now());
2219
- useEffect3(() => {
2716
+ const [now, setNow] = useState5(() => Date.now());
2717
+ useEffect5(() => {
2220
2718
  if (!canUndo || expiresAt === void 0) return;
2221
2719
  setNow(Date.now());
2222
2720
  const timer = setInterval(() => setNow(Date.now()), 250);
@@ -2245,17 +2743,17 @@ function useKeepUndo() {
2245
2743
  }
2246
2744
 
2247
2745
  // src/features/actions/KeepUndo.tsx
2248
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
2746
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2249
2747
  function KeepUndo({ children, label, ...props }) {
2250
2748
  const view = useKeepUndo();
2251
2749
  if (!view.canUndo) return null;
2252
- return /* @__PURE__ */ jsxs4("div", { ...props, role: "status", "aria-live": "polite", "data-keepkit": "undo", "data-state": "available", children: [
2253
- /* @__PURE__ */ jsx7("span", { "data-keepkit": "undo-message", children: children ?? view.message }),
2254
- /* @__PURE__ */ jsxs4("span", { "data-keepkit": "undo-countdown", "aria-hidden": "true", children: [
2750
+ return /* @__PURE__ */ jsxs7("div", { ...props, role: "status", "aria-live": "polite", "data-keepkit": "undo", "data-state": "available", children: [
2751
+ /* @__PURE__ */ jsx9("span", { "data-keepkit": "undo-message", children: children ?? view.message }),
2752
+ /* @__PURE__ */ jsxs7("span", { "data-keepkit": "undo-countdown", "aria-hidden": "true", children: [
2255
2753
  view.remainingSeconds,
2256
2754
  "s"
2257
2755
  ] }),
2258
- /* @__PURE__ */ jsx7(
2756
+ /* @__PURE__ */ jsx9(
2259
2757
  "progress",
2260
2758
  {
2261
2759
  "data-keepkit": "undo-progress",
@@ -2265,7 +2763,7 @@ function KeepUndo({ children, label, ...props }) {
2265
2763
  "aria-valuetext": `${view.remainingSeconds}s`
2266
2764
  }
2267
2765
  ),
2268
- /* @__PURE__ */ jsx7("button", { type: "button", "data-keep-action": "undo", onClick: () => void view.undo(), children: label ?? view.label })
2766
+ /* @__PURE__ */ jsx9("button", { type: "button", "data-keep-action": "undo", onClick: () => void view.undo(), children: label ?? view.label })
2269
2767
  ] });
2270
2768
  }
2271
2769
 
@@ -2275,9 +2773,9 @@ import { KeepErrorBoundary as KeepErrorBoundary2 } from "@keepkit/core/react";
2275
2773
  // src/features/query/KeepActiveFiltersSummary.tsx
2276
2774
  import {
2277
2775
  isValidElement as isValidElement2,
2278
- useRef as useRef4
2776
+ useRef as useRef6
2279
2777
  } from "react";
2280
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
2778
+ import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2281
2779
  function KeepActiveFiltersSummary({
2282
2780
  query,
2283
2781
  search: providedSearch,
@@ -2297,7 +2795,7 @@ function KeepActiveFiltersSummary({
2297
2795
  const clearAllLabel = useUiLabel("clearAllFilters");
2298
2796
  const clearLabel = useUiLabel("clearFilters");
2299
2797
  const removeLabel = useUiLabel("removeFilter");
2300
- const chipRefs = useRef4([]);
2798
+ const chipRefs = useRef6([]);
2301
2799
  const filterCount = Number(Boolean(search)) + tags.length;
2302
2800
  function focusChip(index) {
2303
2801
  chipRefs.current[index]?.focus();
@@ -2338,12 +2836,12 @@ function KeepActiveFiltersSummary({
2338
2836
  removeTag: (tag) => onTagChange?.(tag)
2339
2837
  };
2340
2838
  const contentChildren = asChild && isElement(children) ? void 0 : children;
2341
- const body = typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? (hasFilters ? /* @__PURE__ */ jsxs5(Fragment4, { children: [
2342
- /* @__PURE__ */ jsx8("span", { "data-active-filters-label": "true", children: activeFiltersLabel }),
2343
- /* @__PURE__ */ jsxs5("ul", { "data-active-filters-list": "true", children: [
2344
- search ? /* @__PURE__ */ jsxs5("li", { "data-filter-kind": "search", children: [
2345
- /* @__PURE__ */ jsx8("span", { "data-filter-value": "true", children: search }),
2346
- /* @__PURE__ */ jsx8(
2839
+ const body = typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? (hasFilters ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
2840
+ /* @__PURE__ */ jsx10("span", { "data-active-filters-label": "true", children: activeFiltersLabel }),
2841
+ /* @__PURE__ */ jsxs8("ul", { "data-active-filters-list": "true", children: [
2842
+ search ? /* @__PURE__ */ jsxs8("li", { "data-filter-kind": "search", children: [
2843
+ /* @__PURE__ */ jsx10("span", { "data-filter-value": "true", children: search }),
2844
+ /* @__PURE__ */ jsx10(
2347
2845
  "button",
2348
2846
  {
2349
2847
  type: "button",
@@ -2358,9 +2856,9 @@ function KeepActiveFiltersSummary({
2358
2856
  }
2359
2857
  )
2360
2858
  ] }) : null,
2361
- tags.map((tag, tagIndex) => /* @__PURE__ */ jsxs5("li", { "data-filter-kind": "tag", children: [
2362
- /* @__PURE__ */ jsx8("span", { "data-filter-value": "true", children: tag }),
2363
- /* @__PURE__ */ jsx8(
2859
+ tags.map((tag, tagIndex) => /* @__PURE__ */ jsxs8("li", { "data-filter-kind": "tag", children: [
2860
+ /* @__PURE__ */ jsx10("span", { "data-filter-value": "true", children: tag }),
2861
+ /* @__PURE__ */ jsx10(
2364
2862
  "button",
2365
2863
  {
2366
2864
  type: "button",
@@ -2376,7 +2874,7 @@ function KeepActiveFiltersSummary({
2376
2874
  )
2377
2875
  ] }, tag))
2378
2876
  ] }),
2379
- /* @__PURE__ */ jsx8("button", { type: "button", "data-keep-action": "clear-filters", onClick: state.clear, children: clearAllLabel || clearLabel })
2877
+ /* @__PURE__ */ jsx10("button", { type: "button", "data-keep-action": "clear-filters", onClick: state.clear, children: clearAllLabel || clearLabel })
2380
2878
  ] }) : null);
2381
2879
  if (!hasFilters && !asChild && contentChildren === void 0) return null;
2382
2880
  return renderRoot(
@@ -2417,21 +2915,113 @@ function focusFilterFallback(scope) {
2417
2915
  }
2418
2916
  }
2419
2917
 
2918
+ // src/features/query/KeepCollectionFilter.tsx
2919
+ import { useKeepContext as useKeepContext4 } from "@keepkit/core/react";
2920
+ import { useMemo as useMemo3, useState as useState6 } from "react";
2921
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2922
+ function useCollectionOptions(collectionLabels, items) {
2923
+ const ids = useMemo3(
2924
+ () => [...new Set((items ?? []).map((item) => item.collectionId).filter((id) => Boolean(id)))].sort(),
2925
+ [items]
2926
+ );
2927
+ return ids.map((id) => ({ id, label: collectionLabels?.[id] ?? id }));
2928
+ }
2929
+ function KeepCollectionSelect({
2930
+ item,
2931
+ value,
2932
+ defaultValue,
2933
+ onValueChange,
2934
+ onChange,
2935
+ collectionLabels,
2936
+ uncategorizedLabel,
2937
+ ...props
2938
+ }) {
2939
+ const context = useKeepContext4();
2940
+ const state = useState6(value ?? defaultValue ?? item.collectionId ?? "");
2941
+ const selected = value ?? state[0];
2942
+ const options = useCollectionOptions(collectionLabels, context.items);
2943
+ const defaultUncategorizedLabel = useUiLabel("uncategorized");
2944
+ const uncategorized = uncategorizedLabel ?? defaultUncategorizedLabel;
2945
+ const handleChange = (next) => {
2946
+ const resolved = next || void 0;
2947
+ if (value === void 0) state[1](next);
2948
+ onValueChange?.(resolved);
2949
+ onChange?.(resolved);
2950
+ void context.moveToCollection(item.id, resolved);
2951
+ };
2952
+ return /* @__PURE__ */ jsxs9(
2953
+ "select",
2954
+ {
2955
+ ...props,
2956
+ value: selected,
2957
+ onChange: (event) => handleChange(event.currentTarget.value),
2958
+ "data-keep-action": "move-collection",
2959
+ children: [
2960
+ /* @__PURE__ */ jsx11("option", { value: "", children: uncategorized }),
2961
+ options.map((option) => /* @__PURE__ */ jsx11("option", { value: option.id, children: option.label }, option.id))
2962
+ ]
2963
+ }
2964
+ );
2965
+ }
2966
+ function KeepCollectionFilter({
2967
+ value,
2968
+ defaultValue,
2969
+ onValueChange,
2970
+ onChange,
2971
+ collectionLabels,
2972
+ allLabel,
2973
+ uncategorizedLabel,
2974
+ ...props
2975
+ }) {
2976
+ const context = useKeepContext4();
2977
+ const [internalValue, setInternalValue] = useState6(value ?? defaultValue ?? "");
2978
+ const selected = value ?? internalValue;
2979
+ const options = useCollectionOptions(collectionLabels, context.items);
2980
+ const collectionLabel = useUiLabel("collection");
2981
+ const defaultAllLabel = useUiLabel("allCollections");
2982
+ const defaultUncategorizedLabel = useUiLabel("uncategorized");
2983
+ const all = allLabel ?? defaultAllLabel;
2984
+ const uncategorized = uncategorizedLabel ?? defaultUncategorizedLabel;
2985
+ const handleChange = (next) => {
2986
+ if (value === void 0) setInternalValue(next);
2987
+ const resolved = next || void 0;
2988
+ onValueChange?.(resolved);
2989
+ onChange?.(resolved);
2990
+ };
2991
+ return /* @__PURE__ */ jsxs9("label", { "data-keepkit": "collection-filter", children: [
2992
+ /* @__PURE__ */ jsx11("span", { children: collectionLabel }),
2993
+ /* @__PURE__ */ jsxs9(
2994
+ "select",
2995
+ {
2996
+ ...props,
2997
+ value: selected,
2998
+ onChange: (event) => handleChange(event.currentTarget.value),
2999
+ "data-keep-action": "filter-collection",
3000
+ children: [
3001
+ /* @__PURE__ */ jsx11("option", { value: "", children: all }),
3002
+ /* @__PURE__ */ jsx11("option", { value: "__uncategorized__", children: uncategorized }),
3003
+ options.map((option) => /* @__PURE__ */ jsx11("option", { value: option.id, children: option.label }, option.id))
3004
+ ]
3005
+ }
3006
+ )
3007
+ ] });
3008
+ }
3009
+
2420
3010
  // src/features/query/KeepTagFilter.tsx
2421
3011
  import { isValidElement as isValidElement3 } from "react";
2422
3012
 
2423
3013
  // src/features/query/hooks/useKeepTagFilter.ts
2424
3014
  import { useKeepList as useKeepList2 } from "@keepkit/core/react";
2425
- import { useCallback as useCallback2, useMemo as useMemo3, useState as useState4 } from "react";
3015
+ import { useCallback as useCallback4, useMemo as useMemo4, useState as useState7 } from "react";
2426
3016
  function useKeepTagFilter(options) {
2427
3017
  const { query, controlledValue, defaultValue, onChange, onValueChange } = options;
2428
- const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
3018
+ const [uncontrolledValue, setUncontrolledValue] = useState7(defaultValue);
2429
3019
  const resolvedValue = controlledValue ?? uncontrolledValue;
2430
3020
  const list = useKeepList2({
2431
3021
  ...query,
2432
3022
  tags: resolvedValue ? [...query?.tags ?? [], resolvedValue] : query?.tags
2433
3023
  });
2434
- const select = useCallback2(
3024
+ const select = useCallback4(
2435
3025
  (tag) => {
2436
3026
  if (controlledValue === void 0) setUncontrolledValue(tag);
2437
3027
  onChange?.(tag);
@@ -2439,7 +3029,7 @@ function useKeepTagFilter(options) {
2439
3029
  },
2440
3030
  [controlledValue, onChange, onValueChange]
2441
3031
  );
2442
- const state = useMemo3(
3032
+ const state = useMemo4(
2443
3033
  () => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),
2444
3034
  [list.tagCounts, list.tags, resolvedValue, select]
2445
3035
  );
@@ -2451,7 +3041,7 @@ function useKeepTagFilter(options) {
2451
3041
  }
2452
3042
 
2453
3043
  // src/features/query/KeepTagFilter.tsx
2454
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
3044
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2455
3045
  function KeepTagFilter({
2456
3046
  query,
2457
3047
  value: controlledValue,
@@ -2469,9 +3059,9 @@ function KeepTagFilter({
2469
3059
  }) {
2470
3060
  const view = useKeepTagFilter({ query, controlledValue, defaultValue, onChange, onValueChange });
2471
3061
  const contentChildren = asChild && isValidElement3(children) ? void 0 : children;
2472
- const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs6("fieldset", { children: [
2473
- /* @__PURE__ */ jsx9("legend", { children: ariaLabel ?? view.labels.aria }),
2474
- /* @__PURE__ */ jsx9(
3062
+ const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs10("fieldset", { children: [
3063
+ /* @__PURE__ */ jsx12("legend", { children: ariaLabel ?? view.labels.aria }),
3064
+ /* @__PURE__ */ jsx12(
2475
3065
  "button",
2476
3066
  {
2477
3067
  type: "button",
@@ -2481,7 +3071,7 @@ function KeepTagFilter({
2481
3071
  children: allLabel ?? view.labels.all
2482
3072
  }
2483
3073
  ),
2484
- view.state.tags.map((tag) => /* @__PURE__ */ jsxs6(
3074
+ view.state.tags.map((tag) => /* @__PURE__ */ jsxs10(
2485
3075
  "button",
2486
3076
  {
2487
3077
  type: "button",
@@ -2490,7 +3080,7 @@ function KeepTagFilter({
2490
3080
  onClick: () => view.state.select(tag),
2491
3081
  children: [
2492
3082
  renderTag ? renderTag(tag, view.state.tagCounts[tag] ?? 0, view.state.value === tag) : tag,
2493
- /* @__PURE__ */ jsxs6("span", { children: [
3083
+ /* @__PURE__ */ jsxs10("span", { children: [
2494
3084
  " (",
2495
3085
  view.state.tagCounts[tag] ?? 0,
2496
3086
  ")"
@@ -2516,12 +3106,12 @@ function KeepTagFilter({
2516
3106
  }
2517
3107
 
2518
3108
  // src/features/query/hooks/useQueryControls.ts
2519
- import { useEffect as useEffect4, useState as useState5 } from "react";
3109
+ import { useEffect as useEffect6, useState as useState8 } from "react";
2520
3110
  function useKeepSearchInput(options) {
2521
3111
  const { controlledValue, defaultValue, debounceMs, onValueChange } = options;
2522
- const [uncontrolledValue, setUncontrolledValue] = useState5(defaultValue);
3112
+ const [uncontrolledValue, setUncontrolledValue] = useState8(defaultValue);
2523
3113
  const value = controlledValue ?? uncontrolledValue;
2524
- useEffect4(() => {
3114
+ useEffect6(() => {
2525
3115
  if (!onValueChange) return;
2526
3116
  if (debounceMs <= 0) {
2527
3117
  onValueChange(value);
@@ -2540,7 +3130,7 @@ function useKeepSearchInput(options) {
2540
3130
  }
2541
3131
  function useKeepSortSelect(options) {
2542
3132
  const { controlledValue, defaultValue, onValueChange } = options;
2543
- const [uncontrolledValue, setUncontrolledValue] = useState5(defaultValue);
3133
+ const [uncontrolledValue, setUncontrolledValue] = useState8(defaultValue);
2544
3134
  const value = controlledValue ?? uncontrolledValue;
2545
3135
  return {
2546
3136
  value,
@@ -2588,7 +3178,7 @@ function getVisiblePages(currentPage, pageCount, maxPageButtons) {
2588
3178
  }
2589
3179
 
2590
3180
  // src/features/query/query-controls.tsx
2591
- import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
3181
+ import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2592
3182
  function KeepSearchInput({
2593
3183
  value: controlledValue,
2594
3184
  defaultValue = "",
@@ -2599,7 +3189,7 @@ function KeepSearchInput({
2599
3189
  ...props
2600
3190
  }) {
2601
3191
  const view = useKeepSearchInput({ controlledValue, defaultValue, debounceMs, onValueChange });
2602
- return /* @__PURE__ */ jsx10(
3192
+ return /* @__PURE__ */ jsx13(
2603
3193
  "input",
2604
3194
  {
2605
3195
  ...props,
@@ -2624,13 +3214,13 @@ function KeepSortSelect({
2624
3214
  ...props
2625
3215
  }) {
2626
3216
  const view = useKeepSortSelect({ controlledValue, defaultValue, onValueChange });
2627
- const options = children ?? /* @__PURE__ */ jsxs7(Fragment5, { children: [
2628
- /* @__PURE__ */ jsx10("option", { value: "updatedAt:desc", children: view.labels.updatedNewest }),
2629
- /* @__PURE__ */ jsx10("option", { value: "updatedAt:asc", children: view.labels.updatedOldest }),
2630
- /* @__PURE__ */ jsx10("option", { value: "savedAt:desc", children: view.labels.savedNewest }),
2631
- /* @__PURE__ */ jsx10("option", { value: "savedAt:asc", children: view.labels.savedOldest })
3217
+ const options = children ?? /* @__PURE__ */ jsxs11(Fragment6, { children: [
3218
+ /* @__PURE__ */ jsx13("option", { value: "updatedAt:desc", children: view.labels.updatedNewest }),
3219
+ /* @__PURE__ */ jsx13("option", { value: "updatedAt:asc", children: view.labels.updatedOldest }),
3220
+ /* @__PURE__ */ jsx13("option", { value: "savedAt:desc", children: view.labels.savedNewest }),
3221
+ /* @__PURE__ */ jsx13("option", { value: "savedAt:asc", children: view.labels.savedOldest })
2632
3222
  ] });
2633
- return /* @__PURE__ */ jsx10(
3223
+ return /* @__PURE__ */ jsx13(
2634
3224
  "select",
2635
3225
  {
2636
3226
  ...props,
@@ -2662,9 +3252,9 @@ function KeepPagination({
2662
3252
  "data-state": view.pageCount > 1 ? "active" : "idle"
2663
3253
  };
2664
3254
  if (render)
2665
- return /* @__PURE__ */ jsx10("nav", { ...navProps, children: render({ page: view.currentPage, pageCount: view.pageCount, goToPage: view.goToPage }) });
2666
- return /* @__PURE__ */ jsxs7("nav", { ...navProps, children: [
2667
- /* @__PURE__ */ jsx10(
3255
+ return /* @__PURE__ */ jsx13("nav", { ...navProps, children: render({ page: view.currentPage, pageCount: view.pageCount, goToPage: view.goToPage }) });
3256
+ return /* @__PURE__ */ jsxs11("nav", { ...navProps, children: [
3257
+ /* @__PURE__ */ jsx13(
2668
3258
  "button",
2669
3259
  {
2670
3260
  type: "button",
@@ -2674,7 +3264,7 @@ function KeepPagination({
2674
3264
  children: view.labels.previous
2675
3265
  }
2676
3266
  ),
2677
- view.visiblePages.map((nextPage) => /* @__PURE__ */ jsx10(
3267
+ view.visiblePages.map((nextPage) => /* @__PURE__ */ jsx13(
2678
3268
  "button",
2679
3269
  {
2680
3270
  type: "button",
@@ -2686,7 +3276,7 @@ function KeepPagination({
2686
3276
  },
2687
3277
  nextPage
2688
3278
  )),
2689
- /* @__PURE__ */ jsx10(
3279
+ /* @__PURE__ */ jsx13(
2690
3280
  "button",
2691
3281
  {
2692
3282
  type: "button",
@@ -2701,7 +3291,7 @@ function KeepPagination({
2701
3291
 
2702
3292
  // src/features/collection/hooks/useKeepCollection.ts
2703
3293
  import { useKeepList as useKeepList3 } from "@keepkit/core/react";
2704
- import { useMemo as useMemo4, useState as useState6 } from "react";
3294
+ import { useMemo as useMemo5, useState as useState9 } from "react";
2705
3295
  function useKeepCollection({
2706
3296
  query,
2707
3297
  pageSize,
@@ -2714,23 +3304,38 @@ function useKeepCollection({
2714
3304
  sort: true,
2715
3305
  pagination: true,
2716
3306
  tagFilter: false,
3307
+ collectionFilter: false,
2717
3308
  bulkActions: false,
2718
3309
  ...features
2719
3310
  };
2720
- const [searchValue, setSearchValue] = useState6(query.search?.query ?? "");
2721
- const [sort, setSort] = useState6(query.sort ?? { by: "updatedAt", direction: "desc" });
2722
- const [activeTags, setActiveTags] = useState6(query.tags ?? []);
2723
- const [page, setPage] = useState6(query.pagination?.page ?? 1);
3311
+ const [searchValue, setSearchValue] = useState9(query.search?.query ?? "");
3312
+ const [sort, setSort] = useState9(query.sort ?? { by: "updatedAt", direction: "desc" });
3313
+ const [activeTags, setActiveTags] = useState9(query.tags ?? []);
3314
+ const [activeCollection, setActiveCollection] = useState9(query.collectionId);
3315
+ const [page, setPage] = useState9(query.pagination?.page ?? 1);
2724
3316
  const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
2725
- const resolvedQuery = useMemo4(
3317
+ const resolvedQuery = useMemo5(
2726
3318
  () => ({
2727
3319
  ...query,
2728
3320
  search: enabled.search ? { ...query.search, query: searchValue } : query.search,
2729
3321
  sort: enabled.sort ? sort : query.sort,
2730
3322
  tags: activeTags.length > 0 ? activeTags : void 0,
3323
+ collectionId: activeCollection && activeCollection !== "__uncategorized__" ? activeCollection : void 0,
3324
+ filter: activeCollection === "__uncategorized__" ? (item) => item.collectionId === void 0 && (query.filter?.(item) ?? true) : query.filter,
2731
3325
  pagination: enabled.pagination ? { ...query.pagination, page, pageSize: resolvedPageSize } : query.pagination
2732
3326
  }),
2733
- [activeTags, enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort]
3327
+ [
3328
+ activeCollection,
3329
+ activeTags,
3330
+ enabled.pagination,
3331
+ enabled.search,
3332
+ enabled.sort,
3333
+ page,
3334
+ query,
3335
+ resolvedPageSize,
3336
+ searchValue,
3337
+ sort
3338
+ ]
2734
3339
  );
2735
3340
  useKeepUrlSync({
2736
3341
  enabled: Boolean(urlSync),
@@ -2740,6 +3345,7 @@ function useKeepCollection({
2740
3345
  setSearchValue(next.search?.query ?? "");
2741
3346
  setSort(next.sort ?? { by: "updatedAt", direction: "desc" });
2742
3347
  setActiveTags(next.tags ?? []);
3348
+ setActiveCollection(next.collectionId);
2743
3349
  setPage(next.pagination?.page ?? 1);
2744
3350
  },
2745
3351
  options: typeof urlSync === "object" ? urlSync : {},
@@ -2752,6 +3358,7 @@ function useKeepCollection({
2752
3358
  searchValue,
2753
3359
  sortValue: sortToValue(sort),
2754
3360
  activeTags,
3361
+ activeCollection,
2755
3362
  resolvedPageSize,
2756
3363
  resolvedQuery,
2757
3364
  list,
@@ -2768,6 +3375,10 @@ function useKeepCollection({
2768
3375
  setActiveTags(value ? [value] : []);
2769
3376
  setPage(1);
2770
3377
  },
3378
+ setCollection: (value) => {
3379
+ setActiveCollection(value);
3380
+ setPage(1);
3381
+ },
2771
3382
  removeTag: (tagToRemove) => {
2772
3383
  setActiveTags((current) => current.filter((tag) => tag !== tagToRemove));
2773
3384
  setPage(1);
@@ -2775,6 +3386,7 @@ function useKeepCollection({
2775
3386
  clearFilters: () => {
2776
3387
  setSearchValue("");
2777
3388
  setActiveTags([]);
3389
+ setActiveCollection(void 0);
2778
3390
  setPage(1);
2779
3391
  },
2780
3392
  setPage
@@ -2791,8 +3403,8 @@ import {
2791
3403
  createElement as createElement2,
2792
3404
  isValidElement as isValidElement4,
2793
3405
  useContext as useContext3,
2794
- useEffect as useEffect5,
2795
- useState as useState8
3406
+ useEffect as useEffect7,
3407
+ useState as useState11
2796
3408
  } from "react";
2797
3409
 
2798
3410
  // src/features/item/hooks/useKeepItemStatusBadge.ts
@@ -2835,10 +3447,10 @@ function getDisplayStatus(status) {
2835
3447
  }
2836
3448
 
2837
3449
  // src/features/item/KeepItemStatusBadge.tsx
2838
- import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
3450
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2839
3451
  function KeepItemStatusBadge({ status = "available", label, className, ...props }) {
2840
3452
  const view = useKeepItemStatusBadge(status);
2841
- return /* @__PURE__ */ jsxs8(
3453
+ return /* @__PURE__ */ jsxs12(
2842
3454
  "span",
2843
3455
  {
2844
3456
  ...props,
@@ -2849,14 +3461,14 @@ function KeepItemStatusBadge({ status = "available", label, className, ...props
2849
3461
  "data-status": status,
2850
3462
  "data-item-status": view.resolvedStatus,
2851
3463
  children: [
2852
- /* @__PURE__ */ jsx11(StatusIcon, { name: view.icon }),
2853
- /* @__PURE__ */ jsx11("span", { "data-status-label": "true", children: label ?? view.statusLabel })
3464
+ /* @__PURE__ */ jsx14(StatusIcon, { name: view.icon }),
3465
+ /* @__PURE__ */ jsx14("span", { "data-status-label": "true", children: label ?? view.statusLabel })
2854
3466
  ]
2855
3467
  }
2856
3468
  );
2857
3469
  }
2858
3470
  function StatusIcon({ name }) {
2859
- return /* @__PURE__ */ jsxs8(
3471
+ return /* @__PURE__ */ jsxs12(
2860
3472
  "svg",
2861
3473
  {
2862
3474
  "data-status-icon": name,
@@ -2871,18 +3483,18 @@ function StatusIcon({ name }) {
2871
3483
  "aria-hidden": "true",
2872
3484
  focusable: "false",
2873
3485
  children: [
2874
- name === "check" ? /* @__PURE__ */ jsx11("path", { d: "m5 12 4 4L19 6" }) : null,
2875
- name === "clock" ? /* @__PURE__ */ jsxs8(Fragment6, { children: [
2876
- /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "8" }),
2877
- /* @__PURE__ */ jsx11("path", { d: "M12 7v5l3 2" })
3486
+ name === "check" ? /* @__PURE__ */ jsx14("path", { d: "m5 12 4 4L19 6" }) : null,
3487
+ name === "clock" ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3488
+ /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "8" }),
3489
+ /* @__PURE__ */ jsx14("path", { d: "M12 7v5l3 2" })
2878
3490
  ] }) : null,
2879
- name === "ban" ? /* @__PURE__ */ jsxs8(Fragment6, { children: [
2880
- /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "8" }),
2881
- /* @__PURE__ */ jsx11("path", { d: "m6.5 6.5 11 11" })
3491
+ name === "ban" ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3492
+ /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "8" }),
3493
+ /* @__PURE__ */ jsx14("path", { d: "m6.5 6.5 11 11" })
2882
3494
  ] }) : null,
2883
- name === "lock" ? /* @__PURE__ */ jsxs8(Fragment6, { children: [
2884
- /* @__PURE__ */ jsx11("rect", { x: "5", y: "10", width: "14", height: "10", rx: "2" }),
2885
- /* @__PURE__ */ jsx11("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
3495
+ name === "lock" ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3496
+ /* @__PURE__ */ jsx14("rect", { x: "5", y: "10", width: "14", height: "10", rx: "2" }),
3497
+ /* @__PURE__ */ jsx14("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
2886
3498
  ] }) : null
2887
3499
  ]
2888
3500
  }
@@ -2890,16 +3502,16 @@ function StatusIcon({ name }) {
2890
3502
  }
2891
3503
 
2892
3504
  // src/features/status/hooks/useKeepStaleNotice.ts
2893
- import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
2894
- import { useState as useState7 } from "react";
3505
+ import { useKeepContext as useKeepContext5 } from "@keepkit/core/react";
3506
+ import { useState as useState10 } from "react";
2895
3507
  function useKeepStaleNotice({ item, onRetry, onRemoved }) {
2896
- const context = useKeepContext3();
3508
+ const context = useKeepContext5();
2897
3509
  const emitFeedback = useKeepUiFeedback();
2898
3510
  const removedMessage = useUiLabel("removedMessage");
2899
3511
  const restoredMessage = useUiLabel("restoredMessage");
2900
3512
  const undoLabel = useUiLabel("undo");
2901
- const [isRetrying, setIsRetrying] = useState7(false);
2902
- const [error, setError] = useState7(null);
3513
+ const [isRetrying, setIsRetrying] = useState10(false);
3514
+ const [error, setError] = useState10(null);
2903
3515
  async function retry() {
2904
3516
  setError(null);
2905
3517
  setIsRetrying(true);
@@ -2945,7 +3557,7 @@ function useKeepStaleNotice({ item, onRetry, onRemoved }) {
2945
3557
  };
2946
3558
  }
2947
3559
  function useKeepPruneStale({ statuses, onPruned }) {
2948
- const context = useKeepContext3();
3560
+ const context = useKeepContext5();
2949
3561
  const emitFeedback = useKeepUiFeedback();
2950
3562
  const staleItems = context.items.filter((item) => item.status && statuses.includes(item.status));
2951
3563
  const staleIds = staleItems.map((item) => item.id);
@@ -2979,7 +3591,7 @@ function useKeepPruneStale({ statuses, onPruned }) {
2979
3591
  }
2980
3592
 
2981
3593
  // src/features/status/KeepStaleNotice.tsx
2982
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
3594
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2983
3595
  function KeepStaleNotice({
2984
3596
  item,
2985
3597
  onRetry,
@@ -2991,11 +3603,11 @@ function KeepStaleNotice({
2991
3603
  ...props
2992
3604
  }) {
2993
3605
  const view = useKeepStaleNotice({ item, onRetry, onRemoved });
2994
- return /* @__PURE__ */ jsxs9("aside", { ...props, className, "data-keepkit": "stale-notice", "data-state": view.error ? "error" : "stale", children: [
2995
- /* @__PURE__ */ jsx12(KeepItemStatusBadge, { status: view.status }),
2996
- children ?? (item.statusReason ? /* @__PURE__ */ jsx12("p", { children: item.statusReason }) : null),
2997
- /* @__PURE__ */ jsxs9("div", { children: [
2998
- /* @__PURE__ */ jsx12(
3606
+ return /* @__PURE__ */ jsxs13("aside", { ...props, className, "data-keepkit": "stale-notice", "data-state": view.error ? "error" : "stale", children: [
3607
+ /* @__PURE__ */ jsx15(KeepItemStatusBadge, { status: view.status }),
3608
+ children ?? (item.statusReason ? /* @__PURE__ */ jsx15("p", { children: item.statusReason }) : null),
3609
+ /* @__PURE__ */ jsxs13("div", { children: [
3610
+ /* @__PURE__ */ jsx15(
2999
3611
  "button",
3000
3612
  {
3001
3613
  type: "button",
@@ -3005,7 +3617,7 @@ function KeepStaleNotice({
3005
3617
  children: retryLabel ?? view.labels.retry
3006
3618
  }
3007
3619
  ),
3008
- /* @__PURE__ */ jsx12(
3620
+ /* @__PURE__ */ jsx15(
3009
3621
  "button",
3010
3622
  {
3011
3623
  type: "button",
@@ -3016,7 +3628,7 @@ function KeepStaleNotice({
3016
3628
  }
3017
3629
  )
3018
3630
  ] }),
3019
- view.error ? /* @__PURE__ */ jsx12("p", { role: "alert", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
3631
+ view.error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
3020
3632
  ] });
3021
3633
  }
3022
3634
  function KeepPruneStaleButton({
@@ -3028,7 +3640,7 @@ function KeepPruneStaleButton({
3028
3640
  ...props
3029
3641
  }) {
3030
3642
  const view = useKeepPruneStale({ statuses, onPruned });
3031
- return /* @__PURE__ */ jsx12(
3643
+ return /* @__PURE__ */ jsx15(
3032
3644
  "button",
3033
3645
  {
3034
3646
  ...props,
@@ -3045,7 +3657,7 @@ function KeepPruneStaleButton({
3045
3657
  }
3046
3658
 
3047
3659
  // src/features/item/hooks/useKeepItemCard.ts
3048
- import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
3660
+ import { useKeepItem as useKeepItem5 } from "@keepkit/core/react";
3049
3661
  function useKeepItemCard(options) {
3050
3662
  const {
3051
3663
  item,
@@ -3058,7 +3670,7 @@ function useKeepItemCard(options) {
3058
3670
  onRemoveError,
3059
3671
  onRemoved
3060
3672
  } = options;
3061
- const itemState = useKeepItem2(item);
3673
+ const itemState = useKeepItem5(item);
3062
3674
  const emitFeedback = useKeepUiFeedback();
3063
3675
  const removedMessage = useUiLabel("removedMessage");
3064
3676
  const restoredMessage = useUiLabel("restoredMessage");
@@ -3141,7 +3753,7 @@ function getDisplayStatus2(status) {
3141
3753
  }
3142
3754
 
3143
3755
  // src/features/item/KeepItemCard.tsx
3144
- import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
3756
+ import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3145
3757
  var KeepItemCardContext = createContext3(null);
3146
3758
  function useKeepItemCardCompound(part) {
3147
3759
  const context = useContext3(KeepItemCardContext);
@@ -3158,6 +3770,7 @@ function KeepItemCardRoot({
3158
3770
  renderTags,
3159
3771
  showTags = true,
3160
3772
  showSavedAt = true,
3773
+ collectionLabels,
3161
3774
  imageAlt,
3162
3775
  render,
3163
3776
  children,
@@ -3201,17 +3814,17 @@ function KeepItemCardRoot({
3201
3814
  onClick: (event) => onOpen?.(item, event),
3202
3815
  children: content
3203
3816
  };
3204
- return LinkComponent ? /* @__PURE__ */ jsx13(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx13("a", { ...linkProps });
3817
+ return LinkComponent ? /* @__PURE__ */ jsx16(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx16("a", { ...linkProps });
3205
3818
  }
3206
3819
  function renderTitle(content) {
3207
3820
  if (linkTarget !== "title") return content;
3208
3821
  if (view.isAvailable) return renderLink(content);
3209
- return view.href ? /* @__PURE__ */ jsx13("span", { "aria-disabled": "true", "data-link-disabled": "true", children: content }) : content;
3822
+ return view.href ? /* @__PURE__ */ jsx16("span", { "aria-disabled": "true", "data-link-disabled": "true", children: content }) : content;
3210
3823
  }
3211
3824
  const resolvedImageProps = view.imageProps ? { ...view.imageProps, alt: imageAlt ?? view.imageProps.alt } : void 0;
3212
3825
  const imageSource = resolvedImageProps?.src;
3213
- const [imageStatus, setImageStatus] = useState8(imageSource ? "loading" : "error");
3214
- useEffect5(() => {
3826
+ const [imageStatus, setImageStatus] = useState11(imageSource ? "loading" : "error");
3827
+ useEffect7(() => {
3215
3828
  setImageStatus(imageSource ? "loading" : "error");
3216
3829
  }, [imageSource]);
3217
3830
  let image = null;
@@ -3229,21 +3842,21 @@ function KeepItemCardRoot({
3229
3842
  setImageStatus("error");
3230
3843
  }
3231
3844
  };
3232
- image = renderImage?.(imagePropsWithHandlers, item) ?? (ImageComponent ? /* @__PURE__ */ jsx13(ImageComponent, { ...imagePropsWithHandlers }) : /* @__PURE__ */ jsx13("img", { ...imagePropsWithHandlers, alt: imagePropsWithHandlers.alt }));
3845
+ image = renderImage?.(imagePropsWithHandlers, item) ?? (ImageComponent ? /* @__PURE__ */ jsx16(ImageComponent, { ...imagePropsWithHandlers }) : /* @__PURE__ */ jsx16("img", { ...imagePropsWithHandlers, alt: imagePropsWithHandlers.alt }));
3233
3846
  }
3234
3847
  const tags = showTags ? item.tags ?? [] : [];
3235
3848
  const renderedTags = showTags && tags.length > 0 ? renderTags?.(tags, item) ?? null : null;
3236
- const meta = showSavedAt ? /* @__PURE__ */ jsxs10("div", { "data-card-meta": true, children: [
3237
- /* @__PURE__ */ jsxs10("span", { children: [
3849
+ const meta = showSavedAt ? /* @__PURE__ */ jsxs14("div", { "data-card-meta": true, children: [
3850
+ /* @__PURE__ */ jsxs14("span", { children: [
3238
3851
  view.labels.savedAt,
3239
3852
  ":"
3240
3853
  ] }),
3241
3854
  " ",
3242
- /* @__PURE__ */ jsx13("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
3855
+ /* @__PURE__ */ jsx16("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
3243
3856
  ] }) : null;
3244
- const error = view.itemState.error ? /* @__PURE__ */ jsx13("p", { role: "alert", children: getErrorMessage2(view.itemState.error, view.labels.error) }) : null;
3245
- const actions = view.statusLabel ? /* @__PURE__ */ jsx13(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs10(Fragment7, { children: [
3246
- showSaveButton ? /* @__PURE__ */ jsx13(
3857
+ const error = view.itemState.error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: getErrorMessage2(view.itemState.error, view.labels.error) }) : null;
3858
+ const actions = view.statusLabel ? /* @__PURE__ */ jsx16(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs14(Fragment8, { children: [
3859
+ showSaveButton ? /* @__PURE__ */ jsx16(
3247
3860
  KeepButton,
3248
3861
  {
3249
3862
  item: toKeepButtonItem(item),
@@ -3251,7 +3864,7 @@ function KeepItemCardRoot({
3251
3864
  getAriaLabel: (buttonState) => `${buttonState.isSaved ? view.labels.remove : view.labels.save} ${String(view.resolvedTitle)}`
3252
3865
  }
3253
3866
  ) : null,
3254
- /* @__PURE__ */ jsx13(
3867
+ /* @__PURE__ */ jsx16(
3255
3868
  "button",
3256
3869
  {
3257
3870
  type: "button",
@@ -3263,6 +3876,8 @@ function KeepItemCardRoot({
3263
3876
  )
3264
3877
  ] });
3265
3878
  const compoundValue = {
3879
+ item,
3880
+ collectionLabel: item.collectionId ? collectionLabels?.[item.collectionId] ?? item.collectionId : void 0,
3266
3881
  resolvedTitle: view.resolvedTitle,
3267
3882
  renderTitle,
3268
3883
  image: imageStatus === "error" ? null : image,
@@ -3274,12 +3889,12 @@ function KeepItemCardRoot({
3274
3889
  meta,
3275
3890
  error,
3276
3891
  actions,
3277
- renderText: (content) => /* @__PURE__ */ jsx13(KeepHighlight, { query: searchQuery, children: content })
3892
+ renderText: (content) => /* @__PURE__ */ jsx16(KeepHighlight, { query: searchQuery, children: content })
3278
3893
  };
3279
- const defaultBody = /* @__PURE__ */ jsxs10(Fragment7, { children: [
3280
- /* @__PURE__ */ jsx13(KeepItemCardMedia, {}),
3281
- /* @__PURE__ */ jsx13(KeepItemCardContent, {}),
3282
- /* @__PURE__ */ jsx13(KeepItemCardActions, {})
3894
+ const defaultBody = /* @__PURE__ */ jsxs14(Fragment8, { children: [
3895
+ /* @__PURE__ */ jsx16(KeepItemCardMedia, {}),
3896
+ /* @__PURE__ */ jsx16(KeepItemCardContent, {}),
3897
+ /* @__PURE__ */ jsx16(KeepItemCardActions, {})
3283
3898
  ] });
3284
3899
  const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? defaultBody;
3285
3900
  const linkedBody = linkTarget === "card" && view.isAvailable ? renderLink(body) : body;
@@ -3300,18 +3915,18 @@ function KeepItemCardRoot({
3300
3915
  linkedBody,
3301
3916
  "KeepItemCard"
3302
3917
  );
3303
- return /* @__PURE__ */ jsx13(KeepItemCardContext.Provider, { value: compoundValue, children: root });
3918
+ return /* @__PURE__ */ jsx16(KeepItemCardContext.Provider, { value: compoundValue, children: root });
3304
3919
  }
3305
3920
  function KeepItemCardMedia({ children, fallback, ...props }) {
3306
3921
  const context = useKeepItemCardCompound("Media");
3307
- return /* @__PURE__ */ jsx13("div", { ...props, "data-keep-card-part": "media", "data-media-status": context.imageStatus, "data-aspect-ratio": "1/1", children: children ?? context.image ?? /* @__PURE__ */ jsx13("span", { role: "img", "aria-label": context.fallbackLabel, "data-keep-card-fallback": "true", children: fallback ?? /* @__PURE__ */ jsx13(KeepMediaPlaceholderIcon, {}) }) });
3922
+ 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, {}) }) });
3308
3923
  }
3309
3924
  function KeepItemCardContent({ children, ...props }) {
3310
3925
  const context = useKeepItemCardCompound("Content");
3311
- return /* @__PURE__ */ jsx13("div", { ...props, "data-keep-card-part": "content", children: children === void 0 ? /* @__PURE__ */ jsxs10(Fragment7, { children: [
3312
- /* @__PURE__ */ jsx13(KeepItemCardTitle, {}),
3926
+ return /* @__PURE__ */ jsx16("div", { ...props, "data-keep-card-part": "content", children: children === void 0 ? /* @__PURE__ */ jsxs14(Fragment8, { children: [
3927
+ /* @__PURE__ */ jsx16(KeepItemCardTitle, {}),
3313
3928
  context.meta,
3314
- /* @__PURE__ */ jsx13(KeepItemCardTags, {}),
3929
+ /* @__PURE__ */ jsx16(KeepItemCardTags, {}),
3315
3930
  context.error
3316
3931
  ] }) : context.renderText(children) });
3317
3932
  }
@@ -3324,8 +3939,8 @@ function KeepItemCardTitle({ as = "h3", children, ...props }) {
3324
3939
  );
3325
3940
  }
3326
3941
  function KeepMediaPlaceholderIcon() {
3327
- return /* @__PURE__ */ jsxs10("svg", { "data-media-fallback-icon": "true", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
3328
- /* @__PURE__ */ jsx13(
3942
+ return /* @__PURE__ */ jsxs14("svg", { "data-media-fallback-icon": "true", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
3943
+ /* @__PURE__ */ jsx16(
3329
3944
  "path",
3330
3945
  {
3331
3946
  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",
@@ -3333,34 +3948,53 @@ function KeepMediaPlaceholderIcon() {
3333
3948
  stroke: "currentColor"
3334
3949
  }
3335
3950
  ),
3336
- /* @__PURE__ */ jsx13("circle", { cx: "9", cy: "9", r: "1.5", fill: "currentColor" }),
3337
- /* @__PURE__ */ jsx13("path", { d: "m5.5 18 4.5-4.5 3 3 2-2L19 18", fill: "none", stroke: "currentColor" })
3951
+ /* @__PURE__ */ jsx16("circle", { cx: "9", cy: "9", r: "1.5", fill: "currentColor" }),
3952
+ /* @__PURE__ */ jsx16("path", { d: "m5.5 18 4.5-4.5 3 3 2-2L19 18", fill: "none", stroke: "currentColor" })
3338
3953
  ] });
3339
3954
  }
3340
3955
  function KeepItemCardTags({ children, ...props }) {
3341
3956
  const context = useKeepItemCardCompound("Tags");
3342
3957
  if (children === void 0 && context.renderedTags) return context.renderedTags;
3343
3958
  if (children === void 0 && context.tags.length === 0) return null;
3344
- return /* @__PURE__ */ jsx13("ul", { ...props, "aria-label": props["aria-label"] ?? context.tagsLabel, "data-keep-card-part": "tags", children: children ?? context.tags.map((tag) => /* @__PURE__ */ jsx13("li", { children: tag }, tag)) });
3959
+ 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)) });
3345
3960
  }
3346
3961
  function KeepItemCardActions({ children, ...props }) {
3347
3962
  const context = useKeepItemCardCompound("Actions");
3348
- return /* @__PURE__ */ jsx13("div", { ...props, "data-keep-card-part": "actions", children: children ?? context.actions });
3963
+ return /* @__PURE__ */ jsx16("div", { ...props, "data-keep-card-part": "actions", children: children ?? context.actions });
3964
+ }
3965
+ function KeepItemCardPin({ children, ...props }) {
3966
+ const context = useKeepItemCardCompound("Pin");
3967
+ return /* @__PURE__ */ jsx16(KeepPinButton, { ...props, item: context.item, children });
3968
+ }
3969
+ function KeepItemCardArchive({
3970
+ children,
3971
+ ...props
3972
+ }) {
3973
+ const context = useKeepItemCardCompound("Archive");
3974
+ return /* @__PURE__ */ jsx16(KeepArchiveButton, { ...props, item: context.item, children });
3975
+ }
3976
+ function KeepItemCardCollectionBadge({ children, ...props }) {
3977
+ const context = useKeepItemCardCompound("CollectionBadge");
3978
+ if (!context.item.collectionId) return null;
3979
+ return /* @__PURE__ */ jsx16("span", { ...props, "data-keep-card-part": "collection-badge", children: children ?? context.collectionLabel });
3349
3980
  }
3350
3981
  var KeepItemCard = Object.assign(KeepItemCardRoot, {
3351
3982
  Media: KeepItemCardMedia,
3352
3983
  Content: KeepItemCardContent,
3353
3984
  Title: KeepItemCardTitle,
3354
3985
  Tags: KeepItemCardTags,
3355
- Actions: KeepItemCardActions
3986
+ Actions: KeepItemCardActions,
3987
+ Pin: KeepItemCardPin,
3988
+ Archive: KeepItemCardArchive,
3989
+ CollectionBadge: KeepItemCardCollectionBadge
3356
3990
  });
3357
3991
  function KeepItemCardSkeleton({ layout = "list", ...props }) {
3358
- return /* @__PURE__ */ jsxs10("article", { ...props, "aria-hidden": "true", "data-keepkit": "card-skeleton", "data-layout": layout, "data-state": "loading", children: [
3359
- /* @__PURE__ */ jsx13("span", { "data-skeleton-part": "media" }),
3360
- /* @__PURE__ */ jsx13("span", { "data-skeleton-part": "title" }),
3361
- /* @__PURE__ */ jsx13("span", { "data-skeleton-part": "meta" }),
3362
- /* @__PURE__ */ jsx13("span", { "data-skeleton-part": "tag" }),
3363
- /* @__PURE__ */ jsx13("span", { "data-skeleton-part": "tag" })
3992
+ return /* @__PURE__ */ jsxs14("article", { ...props, "aria-hidden": "true", "data-keepkit": "card-skeleton", "data-layout": layout, "data-state": "loading", children: [
3993
+ /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "media" }),
3994
+ /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "title" }),
3995
+ /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "meta" }),
3996
+ /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "tag" }),
3997
+ /* @__PURE__ */ jsx16("span", { "data-skeleton-part": "tag" })
3364
3998
  ] });
3365
3999
  }
3366
4000
  function formatSavedAt(timestamp) {
@@ -3372,7 +4006,7 @@ function getErrorMessage2(error, fallback) {
3372
4006
 
3373
4007
  // src/features/status/KeepEmptyState.tsx
3374
4008
  import { isValidElement as isValidElement5 } from "react";
3375
- import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
4009
+ import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3376
4010
  function KeepEmptyState({
3377
4011
  title,
3378
4012
  description,
@@ -3391,10 +4025,10 @@ function KeepEmptyState({
3391
4025
  );
3392
4026
  const clearLabel = useUiLabel("clearFilters");
3393
4027
  const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
3394
- const body = contentChildren ?? /* @__PURE__ */ jsxs11(Fragment8, { children: [
3395
- /* @__PURE__ */ jsx14("h2", { children: title ?? defaultTitle }),
3396
- description ?? /* @__PURE__ */ jsx14("p", { children: defaultDescription }),
3397
- action ?? (resolvedVariant === "empty-filtered" && onClearFilters ? /* @__PURE__ */ jsx14("button", { type: "button", "data-keep-action": "clear-filters", onClick: onClearFilters, children: clearLabel }) : null)
4028
+ const body = contentChildren ?? /* @__PURE__ */ jsxs15(Fragment9, { children: [
4029
+ /* @__PURE__ */ jsx17("h2", { children: title ?? defaultTitle }),
4030
+ description ?? /* @__PURE__ */ jsx17("p", { children: defaultDescription }),
4031
+ action ?? (resolvedVariant === "empty-filtered" && onClearFilters ? /* @__PURE__ */ jsx17("button", { type: "button", "data-keep-action": "clear-filters", onClick: onClearFilters, children: clearLabel }) : null)
3398
4032
  ] });
3399
4033
  return renderRoot(
3400
4034
  asChild,
@@ -3420,17 +4054,17 @@ function useKeepListView(query) {
3420
4054
  }
3421
4055
 
3422
4056
  // src/features/collection/hooks/useRovingTabIndex.ts
3423
- import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5 } from "react";
4057
+ import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef7 } from "react";
3424
4058
  function useRovingTabIndex() {
3425
- const ref = useRef5(null);
3426
- const getItems = useCallback3(() => {
4059
+ const ref = useRef7(null);
4060
+ const getItems = useCallback5(() => {
3427
4061
  const root = ref.current;
3428
4062
  if (!root) return [];
3429
4063
  return Array.from(root.querySelectorAll('[data-keepkit="card"]')).filter(
3430
4064
  (item) => item.getAttribute("aria-hidden") !== "true" && item.getAttribute("data-roving-disabled") !== "true"
3431
4065
  );
3432
4066
  }, []);
3433
- const syncTabIndices = useCallback3(() => {
4067
+ const syncTabIndices = useCallback5(() => {
3434
4068
  const items = getItems();
3435
4069
  if (items.length === 0) return;
3436
4070
  const activeElement = document.activeElement;
@@ -3440,7 +4074,7 @@ function useRovingTabIndex() {
3440
4074
  item.tabIndex = index === activeIndex ? 0 : -1;
3441
4075
  });
3442
4076
  }, [getItems]);
3443
- useEffect6(() => {
4077
+ useEffect8(() => {
3444
4078
  const root = ref.current;
3445
4079
  if (!root) return;
3446
4080
  syncTabIndices();
@@ -3448,7 +4082,7 @@ function useRovingTabIndex() {
3448
4082
  observer.observe(root, { childList: true, subtree: true });
3449
4083
  return () => observer.disconnect();
3450
4084
  }, [syncTabIndices]);
3451
- const onFocusCapture = useCallback3(
4085
+ const onFocusCapture = useCallback5(
3452
4086
  (event) => {
3453
4087
  if (!(event.target instanceof HTMLElement)) return;
3454
4088
  const item = event.target.closest('[data-keepkit="card"]');
@@ -3459,7 +4093,7 @@ function useRovingTabIndex() {
3459
4093
  },
3460
4094
  [getItems]
3461
4095
  );
3462
- const onKeyDown = useCallback3(
4096
+ const onKeyDown = useCallback5(
3463
4097
  (event) => {
3464
4098
  if (event.defaultPrevented) return;
3465
4099
  const items = getItems();
@@ -3485,12 +4119,12 @@ function useRovingTabIndex() {
3485
4119
  }
3486
4120
 
3487
4121
  // src/features/collection/KeepList.tsx
3488
- import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
4122
+ import { Fragment as Fragment10, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
3489
4123
  function KeepList(props) {
3490
4124
  const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
3491
- const content = /* @__PURE__ */ jsx15(KeepListContent, { ...listProps });
4125
+ const content = /* @__PURE__ */ jsx18(KeepListContent, { ...listProps });
3492
4126
  if (fallback === void 0 && onBoundaryError === void 0) return content;
3493
- return /* @__PURE__ */ jsx15(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
4127
+ return /* @__PURE__ */ jsx18(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
3494
4128
  }
3495
4129
  function KeepListContent({
3496
4130
  query,
@@ -3550,7 +4184,7 @@ function KeepListContent({
3550
4184
  if (!event.defaultPrevented) roving.onFocusCapture(event);
3551
4185
  }
3552
4186
  },
3553
- /* @__PURE__ */ jsx15(KeepSearchQueryProvider, { query: query?.search?.query, children: body }),
4187
+ /* @__PURE__ */ jsx18(KeepSearchQueryProvider, { query: query?.search?.query, children: body }),
3554
4188
  "KeepList"
3555
4189
  );
3556
4190
  }
@@ -3565,17 +4199,17 @@ function getListBody(state, options) {
3565
4199
  if (state.isLoading && !state.isHydrated) {
3566
4200
  if (options.loading !== void 0) return resolveContent(options.loading, state);
3567
4201
  const count = Number.isFinite(options.loadingCount) ? Math.max(0, Math.floor(options.loadingCount)) : 6;
3568
- return /* @__PURE__ */ jsxs12(Fragment9, { children: [
3569
- /* @__PURE__ */ jsx15("span", { role: "status", "data-keepkit": "loading-label", children: options.loadingLabel }),
3570
- /* @__PURE__ */ jsx15("ul", { "data-keepkit": "skeleton-list", "data-layout": options.layout, children: Array.from({ length: count }, (_, index) => (
4202
+ return /* @__PURE__ */ jsxs16(Fragment10, { children: [
4203
+ /* @__PURE__ */ jsx18("span", { role: "status", "data-keepkit": "loading-label", children: options.loadingLabel }),
4204
+ /* @__PURE__ */ jsx18("ul", { "data-keepkit": "skeleton-list", "data-layout": options.layout, children: Array.from({ length: count }, (_, index) => (
3571
4205
  // biome-ignore lint/suspicious/noArrayIndexKey: Static loading placeholders never reorder.
3572
- /* @__PURE__ */ jsx15("li", { children: /* @__PURE__ */ jsx15(KeepItemCardSkeleton, { layout: options.layout }) }, index)
4206
+ /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(KeepItemCardSkeleton, { layout: options.layout }) }, index)
3573
4207
  )) })
3574
4208
  ] });
3575
4209
  }
3576
4210
  if (state.isHydrated && state.items.length === 0) {
3577
4211
  if (options.empty !== void 0) return resolveContent(options.empty, state);
3578
- return /* @__PURE__ */ jsx15(
4212
+ return /* @__PURE__ */ jsx18(
3579
4213
  KeepEmptyState,
3580
4214
  {
3581
4215
  variant: options.allItemCount > 0 && hasActiveQueryFilters(options.query) ? "empty-filtered" : "empty-storage",
@@ -3585,24 +4219,24 @@ function getListBody(state, options) {
3585
4219
  }
3586
4220
  if (typeof options.children === "function") return options.children(state);
3587
4221
  if (options.children !== void 0 && !isValidElement6(options.children)) return options.children;
3588
- return /* @__PURE__ */ jsx15("ul", { "data-layout": options.layout, children: state.items.map(
3589
- (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx15("li", { children: /* @__PURE__ */ jsx15(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
4222
+ return /* @__PURE__ */ jsx18("ul", { "data-layout": options.layout, children: state.items.map(
4223
+ (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
3590
4224
  ) });
3591
4225
  }
3592
4226
  function hasActiveQueryFilters(query) {
3593
4227
  if (!query) return false;
3594
4228
  return Boolean(
3595
- query.search?.query?.trim() || query.tags?.some((tag) => tag.trim()) || query.targetType || query.savedBetween || query.filter
4229
+ query.search?.query?.trim() || query.tags?.some((tag) => tag.trim()) || query.targetType || query.savedBetween || query.archived !== void 0 || query.collectionId || query.filter
3596
4230
  );
3597
4231
  }
3598
4232
 
3599
4233
  // src/features/collection/KeepCollection.tsx
3600
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
4234
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
3601
4235
  function KeepCollection(props) {
3602
4236
  const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
3603
- const content = /* @__PURE__ */ jsx16(KeepCollectionContent, { ...collectionProps });
4237
+ const content = /* @__PURE__ */ jsx19(KeepCollectionContent, { ...collectionProps });
3604
4238
  if (fallback === void 0 && onBoundaryError === void 0) return content;
3605
- return /* @__PURE__ */ jsx16(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
4239
+ return /* @__PURE__ */ jsx19(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
3606
4240
  }
3607
4241
  function KeepCollectionContent({
3608
4242
  query = {},
@@ -3611,6 +4245,7 @@ function KeepCollectionContent({
3611
4245
  urlSync = false,
3612
4246
  urlAdapter,
3613
4247
  features,
4248
+ collectionLabels,
3614
4249
  renderItem,
3615
4250
  itemCardProps,
3616
4251
  loading,
@@ -3623,7 +4258,7 @@ function KeepCollectionContent({
3623
4258
  ...rootProps
3624
4259
  }) {
3625
4260
  const view = useKeepCollection({ query, pageSize, urlSync, urlAdapter, features });
3626
- return /* @__PURE__ */ jsxs13(
4261
+ return /* @__PURE__ */ jsxs17(
3627
4262
  "section",
3628
4263
  {
3629
4264
  ...rootProps,
@@ -3634,12 +4269,20 @@ function KeepCollectionContent({
3634
4269
  "data-state": getCollectionState(view.list),
3635
4270
  "data-loading": view.list.isLoading || view.list.isMutating ? "true" : void 0,
3636
4271
  children: [
3637
- /* @__PURE__ */ jsxs13("div", { children: [
3638
- view.enabled.search ? /* @__PURE__ */ jsx16(KeepSearchInput, { value: view.searchValue, onValueChange: view.setSearchValue }) : null,
3639
- view.enabled.sort ? /* @__PURE__ */ jsx16(KeepSortSelect, { value: view.sortValue, onValueChange: view.setSortValue }) : null,
3640
- view.enabled.tagFilter ? /* @__PURE__ */ jsx16(KeepTagFilter, { query, value: view.activeTags[0], onValueChange: view.setTag }) : null
4272
+ /* @__PURE__ */ jsxs17("div", { children: [
4273
+ view.enabled.search ? /* @__PURE__ */ jsx19(KeepSearchInput, { value: view.searchValue, onValueChange: view.setSearchValue }) : null,
4274
+ view.enabled.sort ? /* @__PURE__ */ jsx19(KeepSortSelect, { value: view.sortValue, onValueChange: view.setSortValue }) : null,
4275
+ view.enabled.tagFilter ? /* @__PURE__ */ jsx19(KeepTagFilter, { query, value: view.activeTags[0], onValueChange: view.setTag }) : null,
4276
+ view.enabled.collectionFilter ? /* @__PURE__ */ jsx19(
4277
+ KeepCollectionFilter,
4278
+ {
4279
+ value: view.activeCollection,
4280
+ onValueChange: view.setCollection,
4281
+ collectionLabels
4282
+ }
4283
+ ) : null
3641
4284
  ] }),
3642
- activeFilters === void 0 ? /* @__PURE__ */ jsx16(
4285
+ activeFilters === void 0 ? /* @__PURE__ */ jsx19(
3643
4286
  KeepActiveFiltersSummary,
3644
4287
  {
3645
4288
  search: view.searchValue,
@@ -3649,7 +4292,7 @@ function KeepCollectionContent({
3649
4292
  onClear: view.clearFilters
3650
4293
  }
3651
4294
  ) : resolveContent(activeFilters, view.list),
3652
- /* @__PURE__ */ jsx16(
4295
+ /* @__PURE__ */ jsx19(
3653
4296
  KeepList,
3654
4297
  {
3655
4298
  query: view.resolvedQuery,
@@ -3664,7 +4307,7 @@ function KeepCollectionContent({
3664
4307
  error
3665
4308
  }
3666
4309
  ),
3667
- view.enabled.pagination ? /* @__PURE__ */ jsx16(
4310
+ view.enabled.pagination ? /* @__PURE__ */ jsx19(
3668
4311
  KeepPagination,
3669
4312
  {
3670
4313
  totalCount: view.list.totalCount,
@@ -3673,7 +4316,7 @@ function KeepCollectionContent({
3673
4316
  onPageChange: view.setPage
3674
4317
  }
3675
4318
  ) : null,
3676
- view.enabled.bulkActions ? /* @__PURE__ */ jsx16(KeepBulkActions, { query: view.resolvedQuery }) : null
4319
+ view.enabled.bulkActions ? /* @__PURE__ */ jsx19(KeepBulkActions, { query: view.resolvedQuery }) : null
3677
4320
  ]
3678
4321
  }
3679
4322
  );
@@ -3686,12 +4329,12 @@ function getCollectionState(list) {
3686
4329
  }
3687
4330
 
3688
4331
  // src/features/collection/KeepLayout.tsx
3689
- import { jsx as jsx17 } from "react/jsx-runtime";
4332
+ import { jsx as jsx20 } from "react/jsx-runtime";
3690
4333
  function KeepLayout({ layout = "list", children, onKeyDown, onFocusCapture, ...props }) {
3691
4334
  const roving = useRovingTabIndex();
3692
4335
  return (
3693
4336
  // biome-ignore lint/a11y/noStaticElementInteractions: The group manages keyboard focus for descendant cards.
3694
- /* @__PURE__ */ jsx17(
4337
+ /* @__PURE__ */ jsx20(
3695
4338
  "div",
3696
4339
  {
3697
4340
  ...props,
@@ -3715,8 +4358,8 @@ function KeepLayout({ layout = "list", children, onKeyDown, onFocusCapture, ...p
3715
4358
  }
3716
4359
 
3717
4360
  // src/features/collection/KeepReorderableList.tsx
3718
- import { useState as useState9 } from "react";
3719
- import { jsx as jsx18 } from "react/jsx-runtime";
4361
+ import { useState as useState12 } from "react";
4362
+ import { jsx as jsx21 } from "react/jsx-runtime";
3720
4363
  function KeepReorderableList({
3721
4364
  items,
3722
4365
  onReorder,
@@ -3724,8 +4367,8 @@ function KeepReorderableList({
3724
4367
  itemLabel = (_item, index) => `Move item ${index + 1}`,
3725
4368
  ...props
3726
4369
  }) {
3727
- const [draggedId, setDraggedId] = useState9(null);
3728
- const [dropTargetIndex, setDropTargetIndex] = useState9(null);
4370
+ const [draggedId, setDraggedId] = useState12(null);
4371
+ const [dropTargetIndex, setDropTargetIndex] = useState12(null);
3729
4372
  const ids = items.map((item) => item.id);
3730
4373
  function commit(nextIds) {
3731
4374
  void onReorder(nextIds);
@@ -3750,7 +4393,7 @@ function KeepReorderableList({
3750
4393
  if (next[index] === id) return;
3751
4394
  commit(next);
3752
4395
  }
3753
- return /* @__PURE__ */ jsx18("ul", { ...props, "data-keepkit": "reorderable-list", children: items.map((item, index) => {
4396
+ return /* @__PURE__ */ jsx21("ul", { ...props, "data-keepkit": "reorderable-list", children: items.map((item, index) => {
3754
4397
  const moveUp = () => move(index, index - 1);
3755
4398
  const moveDown = () => move(index, index + 1);
3756
4399
  const onHandleKeyDown = (event) => {
@@ -3785,7 +4428,7 @@ function KeepReorderableList({
3785
4428
  onKeyDown: onHandleKeyDown
3786
4429
  }
3787
4430
  };
3788
- return /* @__PURE__ */ jsx18(
4431
+ return /* @__PURE__ */ jsx21(
3789
4432
  "li",
3790
4433
  {
3791
4434
  "data-reorder-index": index,
@@ -3820,7 +4463,7 @@ function KeepReorderableList({
3820
4463
  import { isValidElement as isValidElement7 } from "react";
3821
4464
 
3822
4465
  // src/features/navigation/KeepShortcutHint.tsx
3823
- import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
4466
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
3824
4467
  function KeepShortcutHint({ shortcut, separator = "+", ...props }) {
3825
4468
  const keys = typeof shortcut === "string" ? shortcut.split("+") : [...shortcut];
3826
4469
  const occurrences = /* @__PURE__ */ new Map();
@@ -3829,24 +4472,24 @@ function KeepShortcutHint({ shortcut, separator = "+", ...props }) {
3829
4472
  occurrences.set(key, occurrence + 1);
3830
4473
  return { id: `${key}-${occurrence}`, value: key };
3831
4474
  });
3832
- return /* @__PURE__ */ jsx19("span", { ...props, "data-keepkit": "shortcut-hint", "aria-hidden": props["aria-hidden"] ?? true, children: keyedKeys.map((key, index) => /* @__PURE__ */ jsxs14("span", { children: [
3833
- index > 0 ? /* @__PURE__ */ jsx19("span", { "data-shortcut-separator": "true", children: separator }) : null,
3834
- /* @__PURE__ */ jsx19("kbd", { children: key.value.trim() })
4475
+ return /* @__PURE__ */ jsx22("span", { ...props, "data-keepkit": "shortcut-hint", "aria-hidden": props["aria-hidden"] ?? true, children: keyedKeys.map((key, index) => /* @__PURE__ */ jsxs18("span", { children: [
4476
+ index > 0 ? /* @__PURE__ */ jsx22("span", { "data-shortcut-separator": "true", children: separator }) : null,
4477
+ /* @__PURE__ */ jsx22("kbd", { children: key.value.trim() })
3835
4478
  ] }, key.id)) });
3836
4479
  }
3837
4480
 
3838
4481
  // src/features/editor/hooks/useKeepNoteEditor.ts
3839
- import { useKeepItem as useKeepItem3 } from "@keepkit/core/react";
3840
- import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef6, useState as useState10 } from "react";
4482
+ import { useKeepItem as useKeepItem6 } from "@keepkit/core/react";
4483
+ import { useCallback as useCallback6, useEffect as useEffect9, useRef as useRef8, useState as useState13 } from "react";
3841
4484
  function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
3842
- const itemState = useKeepItem3(item);
4485
+ const itemState = useKeepItem6(item);
3843
4486
  const { error, isMutating, item: savedItem, updateNote } = itemState;
3844
- const [note, setNote] = useState10(item.note ?? "");
4487
+ const [note, setNote] = useState13(item.note ?? "");
3845
4488
  const baselineNote = savedItem?.note ?? item.note ?? "";
3846
4489
  const isDirty = note !== baselineNote;
3847
- const lastSavedNoteRef = useRef6(void 0);
3848
- useEffect7(() => setNote(baselineNote), [baselineNote]);
3849
- const save = useCallback4(async () => {
4490
+ const lastSavedNoteRef = useRef8(void 0);
4491
+ useEffect9(() => setNote(baselineNote), [baselineNote]);
4492
+ const save = useCallback6(async () => {
3850
4493
  const nextNote = note.trim() || void 0;
3851
4494
  try {
3852
4495
  await updateNote(nextNote);
@@ -3857,7 +4500,7 @@ function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
3857
4500
  throw cause;
3858
4501
  }
3859
4502
  }, [note, onSaveError, onSaved, updateNote]);
3860
- useEffect7(() => {
4503
+ useEffect9(() => {
3861
4504
  if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;
3862
4505
  const timer = window.setTimeout(() => void save().catch(() => void 0), debounceMs);
3863
4506
  return () => window.clearTimeout(timer);
@@ -3892,7 +4535,7 @@ function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
3892
4535
  }
3893
4536
 
3894
4537
  // src/features/editor/KeepNoteEditor.tsx
3895
- import { Fragment as Fragment10, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
4538
+ import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
3896
4539
  function KeepNoteEditor({
3897
4540
  item,
3898
4541
  label,
@@ -3911,10 +4554,10 @@ function KeepNoteEditor({
3911
4554
  const view = useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError });
3912
4555
  const { error, isDirty, isSaving, note, setNote } = view.state;
3913
4556
  const contentChildren = asChild && isValidElement7(children) ? void 0 : children;
3914
- const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs15(Fragment10, { children: [
3915
- /* @__PURE__ */ jsxs15("label", { children: [
4557
+ const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs19(Fragment11, { children: [
4558
+ /* @__PURE__ */ jsxs19("label", { children: [
3916
4559
  label ?? view.labels.note,
3917
- /* @__PURE__ */ jsx20(
4560
+ /* @__PURE__ */ jsx23(
3918
4561
  "textarea",
3919
4562
  {
3920
4563
  "data-keep-action": "edit-note",
@@ -3926,13 +4569,13 @@ function KeepNoteEditor({
3926
4569
  }
3927
4570
  )
3928
4571
  ] }),
3929
- /* @__PURE__ */ jsxs15("button", { type: "submit", "data-keep-action": "save-note", disabled: isSaving, "aria-busy": isSaving, children: [
4572
+ /* @__PURE__ */ jsxs19("button", { type: "submit", "data-keep-action": "save-note", disabled: isSaving, "aria-busy": isSaving, children: [
3930
4573
  saveLabel ?? view.labels.save,
3931
- showShortcutHint ? /* @__PURE__ */ jsx20(KeepShortcutHint, { shortcut: "Ctrl+Enter" }) : null
4574
+ showShortcutHint ? /* @__PURE__ */ jsx23(KeepShortcutHint, { shortcut: "Ctrl+Enter" }) : null
3932
4575
  ] })
3933
4576
  ] });
3934
4577
  if (!asChild) {
3935
- return /* @__PURE__ */ jsxs15(
4578
+ return /* @__PURE__ */ jsxs19(
3936
4579
  "form",
3937
4580
  {
3938
4581
  ...formProps,
@@ -3945,7 +4588,7 @@ function KeepNoteEditor({
3945
4588
  "data-disabled": isSaving ? "true" : void 0,
3946
4589
  children: [
3947
4590
  body,
3948
- error ? /* @__PURE__ */ jsx20("p", { role: "alert", children: getErrorMessage3(error, view.labels.error) }) : null
4591
+ error ? /* @__PURE__ */ jsx23("p", { role: "alert", children: getErrorMessage3(error, view.labels.error) }) : null
3949
4592
  ]
3950
4593
  }
3951
4594
  );
@@ -3972,14 +4615,14 @@ function getErrorMessage3(error, fallback) {
3972
4615
  }
3973
4616
 
3974
4617
  // src/features/editor/hooks/useKeepTagEditor.ts
3975
- import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
3976
- import { useCallback as useCallback5, useEffect as useEffect8, useState as useState11 } from "react";
4618
+ import { useKeepItem as useKeepItem7 } from "@keepkit/core/react";
4619
+ import { useCallback as useCallback7, useEffect as useEffect10, useState as useState14 } from "react";
3977
4620
  function useKeepTagEditor({ item, onSaved, onSaveError }) {
3978
- const itemState = useKeepItem4(item);
3979
- const [tags, setTags] = useState11(item.tags ?? []);
3980
- const [input, setInput] = useState11("");
3981
- useEffect8(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
3982
- const save = useCallback5(async () => {
4621
+ const itemState = useKeepItem7(item);
4622
+ const [tags, setTags] = useState14(item.tags ?? []);
4623
+ const [input, setInput] = useState14("");
4624
+ useEffect10(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
4625
+ const save = useCallback7(async () => {
3983
4626
  const nextTags = normalizeUiTags(tags);
3984
4627
  try {
3985
4628
  await itemState.updateTags(nextTags);
@@ -4025,7 +4668,7 @@ function useKeepTagEditor({ item, onSaved, onSaveError }) {
4025
4668
  }
4026
4669
 
4027
4670
  // src/features/editor/KeepTagEditor.tsx
4028
- import { Fragment as Fragment11, jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
4671
+ import { Fragment as Fragment12, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
4029
4672
  function KeepTagEditor({
4030
4673
  item,
4031
4674
  availableTags = [],
@@ -4036,10 +4679,10 @@ function KeepTagEditor({
4036
4679
  }) {
4037
4680
  const view = useKeepTagEditor({ item, onSaved, onSaveError });
4038
4681
  const { isSaving, tags } = view.state;
4039
- const body = render ? render(view.state) : /* @__PURE__ */ jsxs16(Fragment11, { children: [
4040
- /* @__PURE__ */ jsxs16("label", { children: [
4682
+ const body = render ? render(view.state) : /* @__PURE__ */ jsxs20(Fragment12, { children: [
4683
+ /* @__PURE__ */ jsxs20("label", { children: [
4041
4684
  view.labels.tags,
4042
- /* @__PURE__ */ jsx21(
4685
+ /* @__PURE__ */ jsx24(
4043
4686
  "input",
4044
4687
  {
4045
4688
  "data-keep-action": "edit-tags",
@@ -4050,14 +4693,14 @@ function KeepTagEditor({
4050
4693
  }
4051
4694
  )
4052
4695
  ] }),
4053
- availableTags.length > 0 ? /* @__PURE__ */ jsx21("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx21("option", { value: tag }, tag)) }) : null,
4054
- /* @__PURE__ */ jsx21("ul", { "aria-label": view.labels.tags, children: tags.map((tag) => /* @__PURE__ */ jsxs16("li", { children: [
4696
+ availableTags.length > 0 ? /* @__PURE__ */ jsx24("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx24("option", { value: tag }, tag)) }) : null,
4697
+ /* @__PURE__ */ jsx24("ul", { "aria-label": view.labels.tags, children: tags.map((tag) => /* @__PURE__ */ jsxs20("li", { children: [
4055
4698
  tag,
4056
- /* @__PURE__ */ jsx21("button", { type: "button", "data-keep-action": "remove-tag", onClick: () => view.removeTag(tag), children: view.labels.remove })
4699
+ /* @__PURE__ */ jsx24("button", { type: "button", "data-keep-action": "remove-tag", onClick: () => view.removeTag(tag), children: view.labels.remove })
4057
4700
  ] }, tag)) }),
4058
- /* @__PURE__ */ jsx21("button", { type: "submit", "data-keep-action": "apply-tags", disabled: isSaving, "aria-busy": isSaving, children: view.labels.apply })
4701
+ /* @__PURE__ */ jsx24("button", { type: "submit", "data-keep-action": "apply-tags", disabled: isSaving, "aria-busy": isSaving, children: view.labels.apply })
4059
4702
  ] });
4060
- return /* @__PURE__ */ jsxs16(
4703
+ return /* @__PURE__ */ jsxs20(
4061
4704
  "form",
4062
4705
  {
4063
4706
  ...props,
@@ -4069,7 +4712,7 @@ function KeepTagEditor({
4069
4712
  "data-disabled": isSaving ? "true" : void 0,
4070
4713
  children: [
4071
4714
  body,
4072
- view.error ? /* @__PURE__ */ jsx21("p", { role: "alert", children: getErrorMessage4(view.error, view.labels.error) }) : null
4715
+ view.error ? /* @__PURE__ */ jsx24("p", { role: "alert", children: getErrorMessage4(view.error, view.labels.error) }) : null
4073
4716
  ]
4074
4717
  }
4075
4718
  );
@@ -4079,9 +4722,9 @@ function getErrorMessage4(error, fallback) {
4079
4722
  }
4080
4723
 
4081
4724
  // src/features/feedback/useKeepToastFeedback.ts
4082
- import { useCallback as useCallback6 } from "react";
4725
+ import { useCallback as useCallback8 } from "react";
4083
4726
  function useKeepToastFeedback(showToast) {
4084
- return useCallback6(
4727
+ return useCallback8(
4085
4728
  (event) => {
4086
4729
  if (!("undo" in event)) {
4087
4730
  showToast(event.message);
@@ -4103,7 +4746,7 @@ import { useKeepNavigator } from "@keepkit/core/react";
4103
4746
  import { useId } from "react";
4104
4747
 
4105
4748
  // src/features/navigation/hooks/useKeepTourShortcuts.ts
4106
- import { useEffect as useEffect9 } from "react";
4749
+ import { useEffect as useEffect11 } from "react";
4107
4750
  function useKeepTourShortcuts({
4108
4751
  onNext,
4109
4752
  onPrev,
@@ -4114,7 +4757,7 @@ function useKeepTourShortcuts({
4114
4757
  prevKeys = ["k", "["],
4115
4758
  onError
4116
4759
  }) {
4117
- useEffect9(() => {
4760
+ useEffect11(() => {
4118
4761
  if (!enabled) return;
4119
4762
  const handleKeyDown = (event) => {
4120
4763
  if (!allowInEditable && isEditableTarget(event.target)) return;
@@ -4135,7 +4778,7 @@ function isEditableTarget(target) {
4135
4778
  }
4136
4779
 
4137
4780
  // src/features/navigation/KeepTourBar.tsx
4138
- import { Fragment as Fragment12, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
4781
+ import { Fragment as Fragment13, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
4139
4782
  function KeepTourBar({
4140
4783
  navigation: providedNavigation,
4141
4784
  currentId,
@@ -4177,9 +4820,9 @@ function KeepTourBar({
4177
4820
  return resolvedPrev();
4178
4821
  }
4179
4822
  });
4180
- const body = /* @__PURE__ */ jsxs17(Fragment12, { children: [
4181
- showProgress ? /* @__PURE__ */ jsx22("span", { "data-keepkit": "tour-progress", "aria-live": "polite", children: progress ?? `${navigation.currentPosition ?? 0} / ${navigation.items.length}` }) : null,
4182
- /* @__PURE__ */ jsx22(
4823
+ const body = /* @__PURE__ */ jsxs21(Fragment13, { children: [
4824
+ showProgress ? /* @__PURE__ */ jsx25("span", { "data-keepkit": "tour-progress", "aria-live": "polite", children: progress ?? `${navigation.currentPosition ?? 0} / ${navigation.items.length}` }) : null,
4825
+ /* @__PURE__ */ jsx25(
4183
4826
  TourAction,
4184
4827
  {
4185
4828
  href: prevHref,
@@ -4187,7 +4830,7 @@ function KeepTourBar({
4187
4830
  onClick: prevHref ? onPrev : resolvedPrev,
4188
4831
  "data-keep-action": "tour-prev",
4189
4832
  shortcut: showShortcutHint ? shortcutOptions?.prevKeys?.[0] ?? "K" : void 0,
4190
- preview: navigation.prevItem ? /* @__PURE__ */ jsxs17(Fragment12, { children: [
4833
+ preview: navigation.prevItem ? /* @__PURE__ */ jsxs21(Fragment13, { children: [
4191
4834
  previousLabel,
4192
4835
  ": ",
4193
4836
  getItemTitle(navigation.prevItem)
@@ -4195,7 +4838,7 @@ function KeepTourBar({
4195
4838
  children: previousLabel
4196
4839
  }
4197
4840
  ),
4198
- /* @__PURE__ */ jsx22(
4841
+ /* @__PURE__ */ jsx25(
4199
4842
  TourAction,
4200
4843
  {
4201
4844
  href: nextHref,
@@ -4203,7 +4846,7 @@ function KeepTourBar({
4203
4846
  onClick: nextHref ? onNext : resolvedNext,
4204
4847
  "data-keep-action": "tour-next",
4205
4848
  shortcut: showShortcutHint ? shortcutOptions?.nextKeys?.[0] ?? "J" : void 0,
4206
- preview: navigation.nextItem ? /* @__PURE__ */ jsxs17(Fragment12, { children: [
4849
+ preview: navigation.nextItem ? /* @__PURE__ */ jsxs21(Fragment13, { children: [
4207
4850
  nextItemLabel,
4208
4851
  ": ",
4209
4852
  getItemTitle(navigation.nextItem)
@@ -4211,7 +4854,7 @@ function KeepTourBar({
4211
4854
  children: nextItemLabel
4212
4855
  }
4213
4856
  ),
4214
- backHref || onBack ? /* @__PURE__ */ jsx22(TourAction, { href: backHref, onClick: onBack, "data-keep-action": "tour-back", children: listLabel }) : null
4857
+ backHref || onBack ? /* @__PURE__ */ jsx25(TourAction, { href: backHref, onClick: onBack, "data-keep-action": "tour-back", children: listLabel }) : null
4215
4858
  ] });
4216
4859
  return renderRoot(
4217
4860
  asChild,
@@ -4223,13 +4866,13 @@ function KeepTourBar({
4223
4866
  }
4224
4867
  function TourAction({ href, disabled = false, onClick, children, preview, shortcut, ...props }) {
4225
4868
  const previewId = useId();
4226
- const content = /* @__PURE__ */ jsxs17(Fragment12, { children: [
4227
- /* @__PURE__ */ jsx22("span", { "data-tour-label": "true", children }),
4228
- shortcut ? /* @__PURE__ */ jsx22(KeepShortcutHint, { shortcut }) : null,
4229
- preview ? /* @__PURE__ */ jsx22("small", { id: previewId, "data-tour-preview": "true", children: preview }) : null
4869
+ const content = /* @__PURE__ */ jsxs21(Fragment13, { children: [
4870
+ /* @__PURE__ */ jsx25("span", { "data-tour-label": "true", children }),
4871
+ shortcut ? /* @__PURE__ */ jsx25(KeepShortcutHint, { shortcut }) : null,
4872
+ preview ? /* @__PURE__ */ jsx25("small", { id: previewId, "data-tour-preview": "true", children: preview }) : null
4230
4873
  ] });
4231
4874
  if (href && !disabled) {
4232
- return /* @__PURE__ */ jsx22(
4875
+ return /* @__PURE__ */ jsx25(
4233
4876
  "a",
4234
4877
  {
4235
4878
  ...props,
@@ -4241,7 +4884,7 @@ function TourAction({ href, disabled = false, onClick, children, preview, shortc
4241
4884
  }
4242
4885
  );
4243
4886
  }
4244
- return /* @__PURE__ */ jsx22(
4887
+ return /* @__PURE__ */ jsx25(
4245
4888
  "button",
4246
4889
  {
4247
4890
  ...props,
@@ -4264,10 +4907,10 @@ function navigateTo(item, href) {
4264
4907
  import { isValidElement as isValidElement8 } from "react";
4265
4908
 
4266
4909
  // src/features/status/hooks/useStatusViews.ts
4267
- import { useKeepContext as useKeepContext4 } from "@keepkit/core/react";
4268
- import { useEffect as useEffect10, useRef as useRef7, useState as useState12 } from "react";
4910
+ import { useKeepContext as useKeepContext6 } from "@keepkit/core/react";
4911
+ import { useEffect as useEffect12, useRef as useRef9, useState as useState15 } from "react";
4269
4912
  function useKeepStatus(status) {
4270
- const context = useKeepContext4();
4913
+ const context = useKeepContext6();
4271
4914
  const resolvedStatus = status ?? getDerivedStatus(context);
4272
4915
  const state = {
4273
4916
  status: resolvedStatus,
@@ -4278,13 +4921,13 @@ function useKeepStatus(status) {
4278
4921
  return { state, defaultLabel: useUiLabel(getStatusLabelKey3(resolvedStatus)) };
4279
4922
  }
4280
4923
  function useKeepAnnouncements(messages) {
4281
- const context = useKeepContext4();
4924
+ const context = useKeepContext6();
4282
4925
  const savedMessage = useUiLabel("savedMessage", messages?.save);
4283
4926
  const removedMessage = useUiLabel("removedMessage", messages?.remove);
4284
4927
  const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
4285
- const [message, setMessage] = useState12("");
4286
- const lastChangeRef = useRef7(void 0);
4287
- useEffect10(() => {
4928
+ const [message, setMessage] = useState15("");
4929
+ const lastChangeRef = useRef9(void 0);
4930
+ useEffect12(() => {
4288
4931
  const change = context.lastChange;
4289
4932
  if (!change || change === lastChangeRef.current) return;
4290
4933
  lastChangeRef.current = change;
@@ -4312,7 +4955,7 @@ function getStatusLabelKey3(status) {
4312
4955
  }
4313
4956
 
4314
4957
  // src/features/status/status.tsx
4315
- import { jsx as jsx23 } from "react/jsx-runtime";
4958
+ import { jsx as jsx26 } from "react/jsx-runtime";
4316
4959
  function KeepStatus({
4317
4960
  status,
4318
4961
  labels,
@@ -4344,7 +4987,7 @@ function KeepStatus({
4344
4987
  }
4345
4988
  function KeepAnnouncements({ messages, ...props }) {
4346
4989
  const message = useKeepAnnouncements(messages);
4347
- return /* @__PURE__ */ jsx23(
4990
+ return /* @__PURE__ */ jsx26(
4348
4991
  "div",
4349
4992
  {
4350
4993
  ...props,
@@ -4360,15 +5003,15 @@ function KeepAnnouncements({ messages, ...props }) {
4360
5003
  var KeepAnnouncer = KeepAnnouncements;
4361
5004
 
4362
5005
  // src/features/sync/hooks/useKeepSyncFeedback.ts
4363
- import { useKeepContext as useKeepContext5 } from "@keepkit/core/react";
4364
- import { useEffect as useEffect11, useRef as useRef8 } from "react";
5006
+ import { useKeepContext as useKeepContext7 } from "@keepkit/core/react";
5007
+ import { useEffect as useEffect13, useRef as useRef10 } from "react";
4365
5008
  function useKeepSyncFeedback() {
4366
- const { syncState } = useKeepContext5();
5009
+ const { syncState } = useKeepContext7();
4367
5010
  const emitFeedback = useKeepUiFeedback();
4368
5011
  const completedMessage = useUiLabel("syncSynced");
4369
5012
  const failedMessage = useUiLabel("syncFailedMessage");
4370
- const previousStatus = useRef8("idle");
4371
- useEffect11(() => {
5013
+ const previousStatus = useRef10("idle");
5014
+ useEffect13(() => {
4372
5015
  const previous = previousStatus.current;
4373
5016
  previousStatus.current = syncState.status;
4374
5017
  if (syncState.status === "error" && previous !== "error") {
@@ -4388,17 +5031,17 @@ function KeepSyncFeedbackObserver() {
4388
5031
  }
4389
5032
 
4390
5033
  // src/features/sync/hooks/useKeepSyncRecoveryDialog.ts
4391
- import { useKeepContext as useKeepContext6 } from "@keepkit/core/react";
4392
- import { useEffect as useEffect12, useState as useState13 } from "react";
5034
+ import { useKeepContext as useKeepContext8 } from "@keepkit/core/react";
5035
+ import { useEffect as useEffect14, useState as useState16 } from "react";
4393
5036
  function useKeepSyncRecoveryDialog(options) {
4394
5037
  const { open, onOpenChange, conflicts, onManualMerge } = options;
4395
- const context = useKeepContext6();
5038
+ const context = useKeepContext8();
4396
5039
  const conflictList = conflicts ?? context.syncState.conflicts ?? [];
4397
5040
  const hasRecovery = conflictList.length > 0 || context.syncState.status === "error" || Boolean(context.error);
4398
- const [dismissed, setDismissed] = useState13(false);
4399
- const [busyId, setBusyId] = useState13();
4400
- const [error, setError] = useState13();
4401
- useEffect12(() => {
5041
+ const [dismissed, setDismissed] = useState16(false);
5042
+ const [busyId, setBusyId] = useState16();
5043
+ const [error, setError] = useState16();
5044
+ useEffect14(() => {
4402
5045
  if (hasRecovery) setDismissed(false);
4403
5046
  }, [hasRecovery]);
4404
5047
  return {
@@ -4443,7 +5086,7 @@ function useKeepSyncRecoveryDialog(options) {
4443
5086
  }
4444
5087
 
4445
5088
  // src/features/sync/KeepSyncRecoveryDialog.tsx
4446
- import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
5089
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
4447
5090
  function KeepSyncRecoveryDialog({
4448
5091
  open,
4449
5092
  onOpenChange,
@@ -4458,7 +5101,7 @@ function KeepSyncRecoveryDialog({
4458
5101
  }) {
4459
5102
  const view = useKeepSyncRecoveryDialog({ open, onOpenChange, conflicts, onManualMerge });
4460
5103
  if (!view.isOpen) return null;
4461
- return /* @__PURE__ */ jsxs18(
5104
+ return /* @__PURE__ */ jsxs22(
4462
5105
  "section",
4463
5106
  {
4464
5107
  ...props,
@@ -4472,17 +5115,17 @@ function KeepSyncRecoveryDialog({
4472
5115
  "data-state": view.conflictList.length > 0 ? "conflict" : "error",
4473
5116
  "data-loading": view.busyId !== void 0 ? "true" : void 0,
4474
5117
  children: [
4475
- /* @__PURE__ */ jsxs18("header", { children: [
4476
- /* @__PURE__ */ jsx24("h2", { id: "keepkit-sync-recovery-title", children: title ?? view.labels.title }),
4477
- /* @__PURE__ */ jsx24("button", { type: "button", "data-keep-action": "close-dialog", onClick: view.close, "aria-label": view.labels.close, children: view.labels.close })
5118
+ /* @__PURE__ */ jsxs22("header", { children: [
5119
+ /* @__PURE__ */ jsx27("h2", { id: "keepkit-sync-recovery-title", children: title ?? view.labels.title }),
5120
+ /* @__PURE__ */ jsx27("button", { type: "button", "data-keep-action": "close-dialog", onClick: view.close, "aria-label": view.labels.close, children: view.labels.close })
4478
5121
  ] }),
4479
5122
  children,
4480
- view.conflictList.length > 0 ? /* @__PURE__ */ jsxs18("div", { children: [
4481
- /* @__PURE__ */ jsx24("p", { children: view.labels.conflict }),
4482
- view.conflictList.map((conflict) => /* @__PURE__ */ jsxs18("article", { "data-conflict-id": conflict.id, children: [
4483
- /* @__PURE__ */ jsx24("h3", { children: getMetaTitle(conflict.operation.item?.meta) ?? conflict.id }),
4484
- /* @__PURE__ */ jsxs18("div", { "data-conflict-preview": true, children: [
4485
- /* @__PURE__ */ jsx24(
5123
+ view.conflictList.length > 0 ? /* @__PURE__ */ jsxs22("div", { children: [
5124
+ /* @__PURE__ */ jsx27("p", { children: view.labels.conflict }),
5125
+ view.conflictList.map((conflict) => /* @__PURE__ */ jsxs22("article", { "data-conflict-id": conflict.id, children: [
5126
+ /* @__PURE__ */ jsx27("h3", { children: getMetaTitle(conflict.operation.item?.meta) ?? conflict.id }),
5127
+ /* @__PURE__ */ jsxs22("div", { "data-conflict-preview": true, children: [
5128
+ /* @__PURE__ */ jsx27(
4486
5129
  ConflictPreview,
4487
5130
  {
4488
5131
  item: conflict.operation.item,
@@ -4492,7 +5135,7 @@ function KeepSyncRecoveryDialog({
4492
5135
  side: "local"
4493
5136
  }
4494
5137
  ),
4495
- /* @__PURE__ */ jsx24(
5138
+ /* @__PURE__ */ jsx27(
4496
5139
  ConflictPreview,
4497
5140
  {
4498
5141
  item: conflict.remote,
@@ -4503,8 +5146,8 @@ function KeepSyncRecoveryDialog({
4503
5146
  }
4504
5147
  )
4505
5148
  ] }),
4506
- /* @__PURE__ */ jsxs18("div", { children: [
4507
- /* @__PURE__ */ jsx24(
5149
+ /* @__PURE__ */ jsxs22("div", { children: [
5150
+ /* @__PURE__ */ jsx27(
4508
5151
  "button",
4509
5152
  {
4510
5153
  type: "button",
@@ -4514,7 +5157,7 @@ function KeepSyncRecoveryDialog({
4514
5157
  children: view.labels.keepLocal
4515
5158
  }
4516
5159
  ),
4517
- /* @__PURE__ */ jsx24(
5160
+ /* @__PURE__ */ jsx27(
4518
5161
  "button",
4519
5162
  {
4520
5163
  type: "button",
@@ -4524,7 +5167,7 @@ function KeepSyncRecoveryDialog({
4524
5167
  children: view.labels.useServer
4525
5168
  }
4526
5169
  ),
4527
- /* @__PURE__ */ jsx24(
5170
+ /* @__PURE__ */ jsx27(
4528
5171
  "button",
4529
5172
  {
4530
5173
  type: "button",
@@ -4537,12 +5180,12 @@ function KeepSyncRecoveryDialog({
4537
5180
  ] })
4538
5181
  ] }, conflict.id))
4539
5182
  ] }) : null,
4540
- view.showBackupRecovery ? /* @__PURE__ */ jsxs18("section", { "data-recovery": "backup", children: [
4541
- /* @__PURE__ */ jsx24("h3", { children: view.labels.backupRecovery }),
4542
- /* @__PURE__ */ jsx24("p", { children: view.labels.backupRecoveryDescription }),
4543
- backup ?? (showBackupControls ? /* @__PURE__ */ jsx24(KeepBackup, {}) : null)
5183
+ view.showBackupRecovery ? /* @__PURE__ */ jsxs22("section", { "data-recovery": "backup", children: [
5184
+ /* @__PURE__ */ jsx27("h3", { children: view.labels.backupRecovery }),
5185
+ /* @__PURE__ */ jsx27("p", { children: view.labels.backupRecoveryDescription }),
5186
+ backup ?? (showBackupControls ? /* @__PURE__ */ jsx27(KeepBackup, {}) : null)
4544
5187
  ] }) : null,
4545
- view.error ? /* @__PURE__ */ jsx24("p", { id: "keepkit-sync-recovery-error", role: "alert", "aria-live": "assertive", children: view.error instanceof Error ? view.error.message : view.labels.error }) : null
5188
+ 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
4546
5189
  ]
4547
5190
  }
4548
5191
  );
@@ -4554,16 +5197,16 @@ function ConflictPreview({
4554
5197
  noteLabel,
4555
5198
  side
4556
5199
  }) {
4557
- return /* @__PURE__ */ jsxs18("article", { "data-conflict-version": side, "aria-label": heading, children: [
4558
- /* @__PURE__ */ jsx24("h4", { children: heading }),
4559
- /* @__PURE__ */ jsxs18("dl", { children: [
4560
- /* @__PURE__ */ jsxs18("div", { children: [
4561
- /* @__PURE__ */ jsx24("dt", { children: updatedAtLabel }),
4562
- /* @__PURE__ */ jsx24("dd", { children: item ? /* @__PURE__ */ jsx24("time", { dateTime: new Date(item.updatedAt).toISOString(), children: formatConflictDate(item.updatedAt) }) : "\u2014" })
5200
+ return /* @__PURE__ */ jsxs22("article", { "data-conflict-version": side, "aria-label": heading, children: [
5201
+ /* @__PURE__ */ jsx27("h4", { children: heading }),
5202
+ /* @__PURE__ */ jsxs22("dl", { children: [
5203
+ /* @__PURE__ */ jsxs22("div", { children: [
5204
+ /* @__PURE__ */ jsx27("dt", { children: updatedAtLabel }),
5205
+ /* @__PURE__ */ jsx27("dd", { children: item ? /* @__PURE__ */ jsx27("time", { dateTime: new Date(item.updatedAt).toISOString(), children: formatConflictDate(item.updatedAt) }) : "\u2014" })
4563
5206
  ] }),
4564
- /* @__PURE__ */ jsxs18("div", { children: [
4565
- /* @__PURE__ */ jsx24("dt", { children: noteLabel }),
4566
- /* @__PURE__ */ jsx24("dd", { children: item?.note || "\u2014" })
5207
+ /* @__PURE__ */ jsxs22("div", { children: [
5208
+ /* @__PURE__ */ jsx27("dt", { children: noteLabel }),
5209
+ /* @__PURE__ */ jsx27("dd", { children: item?.note || "\u2014" })
4567
5210
  ] })
4568
5211
  ] })
4569
5212
  ] });
@@ -4573,9 +5216,9 @@ function formatConflictDate(timestamp) {
4573
5216
  }
4574
5217
 
4575
5218
  // src/features/sync/hooks/useKeepSyncStatusBanner.ts
4576
- import { useKeepContext as useKeepContext7 } from "@keepkit/core/react";
5219
+ import { useKeepContext as useKeepContext9 } from "@keepkit/core/react";
4577
5220
  function useKeepSyncStatusBanner({ onRetry, children }) {
4578
- const context = useKeepContext7();
5221
+ const context = useKeepContext9();
4579
5222
  const retryLabel = useUiLabel("retrySync");
4580
5223
  const resolveLabel = useUiLabel("resolveSync");
4581
5224
  const conflictLabel = useUiLabel("syncConflict");
@@ -4607,7 +5250,7 @@ function getErrorMessage5(error) {
4607
5250
  }
4608
5251
 
4609
5252
  // src/features/sync/KeepSyncStatusBanner.tsx
4610
- import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
5253
+ import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
4611
5254
  function KeepSyncStatusBanner({
4612
5255
  onRetry,
4613
5256
  onResolveConflicts,
@@ -4617,7 +5260,7 @@ function KeepSyncStatusBanner({
4617
5260
  }) {
4618
5261
  const view = useKeepSyncStatusBanner({ onRetry, children });
4619
5262
  if (view.status === "idle" && !view.hasConflicts) return null;
4620
- return /* @__PURE__ */ jsxs19(
5263
+ return /* @__PURE__ */ jsxs23(
4621
5264
  "aside",
4622
5265
  {
4623
5266
  ...props,
@@ -4627,8 +5270,8 @@ function KeepSyncStatusBanner({
4627
5270
  "data-keepkit": "sync-status",
4628
5271
  "data-state": view.status,
4629
5272
  children: [
4630
- /* @__PURE__ */ jsx25("p", { children: view.message }),
4631
- view.showRetry ? /* @__PURE__ */ jsx25(
5273
+ /* @__PURE__ */ jsx28("p", { children: view.message }),
5274
+ view.showRetry ? /* @__PURE__ */ jsx28(
4632
5275
  "button",
4633
5276
  {
4634
5277
  type: "button",
@@ -4638,7 +5281,7 @@ function KeepSyncStatusBanner({
4638
5281
  children: view.retryLabel
4639
5282
  }
4640
5283
  ) : null,
4641
- view.hasConflicts ? /* @__PURE__ */ jsx25(
5284
+ view.hasConflicts ? /* @__PURE__ */ jsx28(
4642
5285
  "button",
4643
5286
  {
4644
5287
  type: "button",
@@ -4655,7 +5298,7 @@ function KeepSyncStatusBanner({
4655
5298
 
4656
5299
  // src/foundation/theme.tsx
4657
5300
  import { isValidElement as isValidElement9 } from "react";
4658
- import { jsx as jsx26 } from "react/jsx-runtime";
5301
+ import { jsx as jsx29 } from "react/jsx-runtime";
4659
5302
  var keepThemeNames = [
4660
5303
  "default",
4661
5304
  "ocean",
@@ -4714,7 +5357,7 @@ function KeepThemeProvider({
4714
5357
  throw new Error("KeepThemeProvider with asChild requires a single React element child.");
4715
5358
  return createSlot(children, rootProps);
4716
5359
  }
4717
- return /* @__PURE__ */ jsx26("div", { ...rootProps, children });
5360
+ return /* @__PURE__ */ jsx29("div", { ...rootProps, children });
4718
5361
  }
4719
5362
 
4720
5363
  // src/index.tsx
@@ -4722,8 +5365,8 @@ import { createAuthenticatedSyncKit } from "@keepkit/core/core";
4722
5365
  import {
4723
5366
  KeepErrorBoundary as KeepErrorBoundary3,
4724
5367
  KeepProvider,
4725
- useKeepContext as useKeepContext8,
4726
- useKeepItem as useKeepItem5,
5368
+ useKeepContext as useKeepContext10,
5369
+ useKeepItem as useKeepItem8,
4727
5370
  useKeepList as useKeepList5,
4728
5371
  useKeepNavigator as useKeepNavigator2,
4729
5372
  useKeepShortcut
@@ -4738,7 +5381,7 @@ import {
4738
5381
  LocalStorageSyncQueueAdapter,
4739
5382
  SyncStorageAdapter
4740
5383
  } from "@keepkit/core/storage";
4741
- import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
5384
+ import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
4742
5385
  function KeepKitProvider({
4743
5386
  labels,
4744
5387
  locale,
@@ -4758,7 +5401,7 @@ function KeepKitProvider({
4758
5401
  children,
4759
5402
  ...providerProps
4760
5403
  }) {
4761
- return /* @__PURE__ */ jsx27(KeepUiProvider, { labels, locale, labelResolver, onFeedback, children: /* @__PURE__ */ jsx27(
5404
+ return /* @__PURE__ */ jsx30(KeepUiProvider, { labels, locale, labelResolver, onFeedback, children: /* @__PURE__ */ jsx30(
4762
5405
  KeepThemeProvider,
4763
5406
  {
4764
5407
  theme,
@@ -4772,10 +5415,10 @@ function KeepKitProvider({
4772
5415
  className: themeClassName,
4773
5416
  style: themeStyle,
4774
5417
  asChild: themeAsChild,
4775
- children: /* @__PURE__ */ jsxs20(CoreKeepProvider, { ...providerProps, children: [
4776
- /* @__PURE__ */ jsx27(KeepSyncFeedbackObserver, {}),
5418
+ children: /* @__PURE__ */ jsxs24(CoreKeepProvider, { ...providerProps, children: [
5419
+ /* @__PURE__ */ jsx30(KeepSyncFeedbackObserver, {}),
4777
5420
  children,
4778
- /* @__PURE__ */ jsx27(KeepAnnouncements, {})
5421
+ /* @__PURE__ */ jsx30(KeepAnnouncements, {})
4779
5422
  ] })
4780
5423
  }
4781
5424
  ) });
@@ -4802,7 +5445,7 @@ function createKeepKit(options = {}) {
4802
5445
  } = options;
4803
5446
  const coreKit = createCoreKeepKit(coreOptions);
4804
5447
  return {
4805
- Provider: (props) => /* @__PURE__ */ jsx27(
5448
+ Provider: (props) => /* @__PURE__ */ jsx30(
4806
5449
  KeepKitProvider,
4807
5450
  {
4808
5451
  ...coreOptions,
@@ -4823,9 +5466,9 @@ function createKeepKit(options = {}) {
4823
5466
  ...props
4824
5467
  }
4825
5468
  ),
4826
- Button: (props) => /* @__PURE__ */ jsx27(KeepButton, { ...props }),
4827
- Backup: (props) => /* @__PURE__ */ jsx27(KeepBackup, { ...props }),
4828
- Collection: (props) => /* @__PURE__ */ jsx27(
5469
+ Button: (props) => /* @__PURE__ */ jsx30(KeepButton, { ...props }),
5470
+ Backup: (props) => /* @__PURE__ */ jsx30(KeepBackup, { ...props }),
5471
+ Collection: (props) => /* @__PURE__ */ jsx30(
4829
5472
  KeepCollection,
4830
5473
  {
4831
5474
  ...props,
@@ -4850,10 +5493,13 @@ export {
4850
5493
  KeepActiveFiltersSummary,
4851
5494
  KeepAnnouncements,
4852
5495
  KeepAnnouncer,
5496
+ KeepArchiveButton,
4853
5497
  KeepBackup,
4854
5498
  KeepBulkActions,
4855
5499
  KeepButton,
4856
5500
  KeepCollection,
5501
+ KeepCollectionFilter,
5502
+ KeepCollectionSelect,
4857
5503
  KeepEmptyState,
4858
5504
  KeepErrorBoundary3 as KeepErrorBoundary,
4859
5505
  KeepHighlight,
@@ -4867,9 +5513,12 @@ export {
4867
5513
  KeepNavigator,
4868
5514
  KeepNoteEditor,
4869
5515
  KeepPagination,
5516
+ KeepPinButton,
4870
5517
  KeepProvider,
4871
5518
  KeepPruneStaleButton,
5519
+ KeepQuickEditor,
4872
5520
  KeepReorderableList,
5521
+ KeepSavePopover,
4873
5522
  KeepSearchInput,
4874
5523
  KeepShortcutHint,
4875
5524
  KeepSortSelect,
@@ -4900,10 +5549,11 @@ export {
4900
5549
  keepThemeNames,
4901
5550
  mergeProps,
4902
5551
  toggleSelectAll,
4903
- useKeepContext8 as useKeepContext,
4904
- useKeepItem5 as useKeepItem,
5552
+ useKeepContext10 as useKeepContext,
5553
+ useKeepItem8 as useKeepItem,
4905
5554
  useKeepList5 as useKeepList,
4906
5555
  useKeepNavigator2 as useKeepNavigator,
5556
+ useKeepQuickEditor,
4907
5557
  useKeepShortcut,
4908
5558
  useKeepToastFeedback,
4909
5559
  useKeepTourShortcuts,