@keepkit/ui 0.21.0 → 0.23.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/README.md +24 -9
- package/dist/index.d.ts +21 -7
- package/dist/index.js +305 -69
- package/dist/index.js.map +1 -1
- package/dist/styles/base.css +19 -1
- package/dist/styles/collection.css +105 -0
- package/dist/tailwind.css +44 -19
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -107,6 +107,8 @@ var DE_LABELS = {
|
|
|
107
107
|
filterCollections: "Nach Sammlung filtern",
|
|
108
108
|
uncategorized: "Nicht kategorisiert",
|
|
109
109
|
saveWithNote: "Mit Notiz speichern",
|
|
110
|
+
editSavedItem: "Gespeichertes Element bearbeiten",
|
|
111
|
+
unsavedChanges: "Nicht gespeicherte \xC4nderungen",
|
|
110
112
|
save: "Speichern",
|
|
111
113
|
saved: "Gespeichert",
|
|
112
114
|
remove: "Entfernen",
|
|
@@ -204,6 +206,8 @@ var EN_LABELS = {
|
|
|
204
206
|
filterCollections: "Filter collections",
|
|
205
207
|
uncategorized: "Uncategorized",
|
|
206
208
|
saveWithNote: "Save with note",
|
|
209
|
+
editSavedItem: "Edit saved item",
|
|
210
|
+
unsavedChanges: "Unsaved changes",
|
|
207
211
|
save: "Save",
|
|
208
212
|
saved: "Saved",
|
|
209
213
|
remove: "Remove",
|
|
@@ -301,6 +305,8 @@ var ES_LABELS = {
|
|
|
301
305
|
filterCollections: "Filtrar por colecci\xF3n",
|
|
302
306
|
uncategorized: "Sin categor\xEDa",
|
|
303
307
|
saveWithNote: "Guardar con nota",
|
|
308
|
+
editSavedItem: "Editar elemento guardado",
|
|
309
|
+
unsavedChanges: "Cambios sin guardar",
|
|
304
310
|
save: "Guardar",
|
|
305
311
|
saved: "Guardado",
|
|
306
312
|
remove: "Eliminar",
|
|
@@ -398,6 +404,8 @@ var FIL_LABELS = {
|
|
|
398
404
|
filterCollections: "I-filter ayon sa koleksyon",
|
|
399
405
|
uncategorized: "Walang kategorya",
|
|
400
406
|
saveWithNote: "I-save na may tala",
|
|
407
|
+
editSavedItem: "I-edit ang naka-save na item",
|
|
408
|
+
unsavedChanges: "Mga hindi pa nai-save na pagbabago",
|
|
401
409
|
save: "I-save",
|
|
402
410
|
saved: "Nai-save",
|
|
403
411
|
remove: "Alisin",
|
|
@@ -495,6 +503,8 @@ var FR_LABELS = {
|
|
|
495
503
|
filterCollections: "Filtrer par collection",
|
|
496
504
|
uncategorized: "Non class\xE9",
|
|
497
505
|
saveWithNote: "Enregistrer avec une note",
|
|
506
|
+
editSavedItem: "Modifier l\u2019\xE9l\xE9ment enregistr\xE9",
|
|
507
|
+
unsavedChanges: "Modifications non enregistr\xE9es",
|
|
498
508
|
save: "Enregistrer",
|
|
499
509
|
saved: "Enregistr\xE9",
|
|
500
510
|
remove: "Supprimer",
|
|
@@ -592,6 +602,8 @@ var ID_LABELS = {
|
|
|
592
602
|
filterCollections: "Filter koleksi",
|
|
593
603
|
uncategorized: "Tanpa kategori",
|
|
594
604
|
saveWithNote: "Simpan dengan catatan",
|
|
605
|
+
editSavedItem: "Edit item tersimpan",
|
|
606
|
+
unsavedChanges: "Perubahan belum disimpan",
|
|
595
607
|
save: "Simpan",
|
|
596
608
|
saved: "Tersimpan",
|
|
597
609
|
remove: "Hapus",
|
|
@@ -689,6 +701,8 @@ var IT_LABELS = {
|
|
|
689
701
|
filterCollections: "Filtra per raccolta",
|
|
690
702
|
uncategorized: "Senza categoria",
|
|
691
703
|
saveWithNote: "Salva con nota",
|
|
704
|
+
editSavedItem: "Modifica elemento salvato",
|
|
705
|
+
unsavedChanges: "Modifiche non salvate",
|
|
692
706
|
save: "Salva",
|
|
693
707
|
saved: "Salvato",
|
|
694
708
|
remove: "Rimuovi",
|
|
@@ -786,6 +800,8 @@ var JA_LABELS = {
|
|
|
786
800
|
filterCollections: "\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u3067\u7D5E\u308A\u8FBC\u3080",
|
|
787
801
|
uncategorized: "\u672A\u5206\u985E",
|
|
788
802
|
saveWithNote: "\u30E1\u30E2\u4ED8\u304D\u3067\u4FDD\u5B58",
|
|
803
|
+
editSavedItem: "\u4FDD\u5B58\u3057\u305F\u30A2\u30A4\u30C6\u30E0\u3092\u7DE8\u96C6",
|
|
804
|
+
unsavedChanges: "\u672A\u4FDD\u5B58\u306E\u5909\u66F4\u304C\u3042\u308A\u307E\u3059",
|
|
789
805
|
save: "\u4FDD\u5B58",
|
|
790
806
|
saved: "\u4FDD\u5B58\u6E08\u307F",
|
|
791
807
|
remove: "\u524A\u9664",
|
|
@@ -883,6 +899,8 @@ var KO_LABELS = {
|
|
|
883
899
|
filterCollections: "\uCEEC\uB809\uC158 \uD544\uD130",
|
|
884
900
|
uncategorized: "\uBBF8\uBD84\uB958",
|
|
885
901
|
saveWithNote: "\uBA54\uBAA8\uC640 \uD568\uAED8 \uC800\uC7A5",
|
|
902
|
+
editSavedItem: "\uC800\uC7A5\uB41C \uD56D\uBAA9 \uD3B8\uC9D1",
|
|
903
|
+
unsavedChanges: "\uC800\uC7A5\uB418\uC9C0 \uC54A\uC740 \uBCC0\uACBD \uC0AC\uD56D",
|
|
886
904
|
save: "\uC800\uC7A5",
|
|
887
905
|
saved: "\uC800\uC7A5\uB428",
|
|
888
906
|
remove: "\uC0AD\uC81C",
|
|
@@ -980,6 +998,8 @@ var MS_LABELS = {
|
|
|
980
998
|
filterCollections: "Tapis koleksi",
|
|
981
999
|
uncategorized: "Tiada kategori",
|
|
982
1000
|
saveWithNote: "Simpan dengan nota",
|
|
1001
|
+
editSavedItem: "Edit item yang disimpan",
|
|
1002
|
+
unsavedChanges: "Perubahan belum disimpan",
|
|
983
1003
|
save: "Simpan",
|
|
984
1004
|
saved: "Disimpan",
|
|
985
1005
|
remove: "Buang",
|
|
@@ -1077,6 +1097,8 @@ var PT_BR_LABELS = {
|
|
|
1077
1097
|
filterCollections: "Filtrar por cole\xE7\xE3o",
|
|
1078
1098
|
uncategorized: "Sem categoria",
|
|
1079
1099
|
saveWithNote: "Salvar com nota",
|
|
1100
|
+
editSavedItem: "Editar item salvo",
|
|
1101
|
+
unsavedChanges: "Altera\xE7\xF5es n\xE3o salvas",
|
|
1080
1102
|
save: "Salvar",
|
|
1081
1103
|
saved: "Salvo",
|
|
1082
1104
|
remove: "Remover",
|
|
@@ -1174,6 +1196,8 @@ var RU_LABELS = {
|
|
|
1174
1196
|
filterCollections: "\u0424\u0438\u043B\u044C\u0442\u0440 \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u0439",
|
|
1175
1197
|
uncategorized: "\u0411\u0435\u0437 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438",
|
|
1176
1198
|
saveWithNote: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0441 \u0437\u0430\u043C\u0435\u0442\u043A\u043E\u0439",
|
|
1199
|
+
editSavedItem: "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442",
|
|
1200
|
+
unsavedChanges: "\u041D\u0435\u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F",
|
|
1177
1201
|
save: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C",
|
|
1178
1202
|
saved: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E",
|
|
1179
1203
|
remove: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
|
|
@@ -1271,6 +1295,8 @@ var TH_LABELS = {
|
|
|
1271
1295
|
filterCollections: "\u0E01\u0E23\u0E2D\u0E07\u0E04\u0E2D\u0E25\u0E40\u0E25\u0E01\u0E0A\u0E31\u0E19",
|
|
1272
1296
|
uncategorized: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E2B\u0E21\u0E27\u0E14\u0E2B\u0E21\u0E39\u0E48",
|
|
1273
1297
|
saveWithNote: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E42\u0E19\u0E49\u0E15",
|
|
1298
|
+
editSavedItem: "\u0E41\u0E01\u0E49\u0E44\u0E02\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E44\u0E27\u0E49",
|
|
1299
|
+
unsavedChanges: "\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E35\u0E48\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
|
|
1274
1300
|
save: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
|
|
1275
1301
|
saved: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E41\u0E25\u0E49\u0E27",
|
|
1276
1302
|
remove: "\u0E25\u0E1A",
|
|
@@ -1368,6 +1394,8 @@ var VI_LABELS = {
|
|
|
1368
1394
|
filterCollections: "L\u1ECDc theo b\u1ED9 s\u01B0u t\u1EADp",
|
|
1369
1395
|
uncategorized: "Ch\u01B0a ph\xE2n lo\u1EA1i",
|
|
1370
1396
|
saveWithNote: "L\u01B0u k\xE8m ghi ch\xFA",
|
|
1397
|
+
editSavedItem: "Ch\u1EC9nh s\u1EEDa m\u1EE5c \u0111\xE3 l\u01B0u",
|
|
1398
|
+
unsavedChanges: "Thay \u0111\u1ED5i ch\u01B0a \u0111\u01B0\u1EE3c l\u01B0u",
|
|
1371
1399
|
save: "L\u01B0u",
|
|
1372
1400
|
saved: "\u0110\xE3 l\u01B0u",
|
|
1373
1401
|
remove: "X\xF3a",
|
|
@@ -1465,6 +1493,8 @@ var ZH_HANS_LABELS = {
|
|
|
1465
1493
|
filterCollections: "\u6309\u96C6\u5408\u7B5B\u9009",
|
|
1466
1494
|
uncategorized: "\u672A\u5206\u7C7B",
|
|
1467
1495
|
saveWithNote: "\u4FDD\u5B58\u5E76\u6DFB\u52A0\u5907\u6CE8",
|
|
1496
|
+
editSavedItem: "\u7F16\u8F91\u5DF2\u4FDD\u5B58\u9879\u76EE",
|
|
1497
|
+
unsavedChanges: "\u6709\u672A\u4FDD\u5B58\u7684\u66F4\u6539",
|
|
1468
1498
|
save: "\u4FDD\u5B58",
|
|
1469
1499
|
saved: "\u5DF2\u4FDD\u5B58",
|
|
1470
1500
|
remove: "\u5220\u9664",
|
|
@@ -1562,6 +1592,8 @@ var ZH_HANT_LABELS = {
|
|
|
1562
1592
|
filterCollections: "\u4F9D\u6536\u85CF\u96C6\u7BE9\u9078",
|
|
1563
1593
|
uncategorized: "\u672A\u5206\u985E",
|
|
1564
1594
|
saveWithNote: "\u5132\u5B58\u4E26\u52A0\u5099\u8A3B",
|
|
1595
|
+
editSavedItem: "\u7DE8\u8F2F\u5DF2\u5132\u5B58\u9805\u76EE",
|
|
1596
|
+
unsavedChanges: "\u6709\u672A\u5132\u5B58\u7684\u8B8A\u66F4",
|
|
1565
1597
|
save: "\u5132\u5B58",
|
|
1566
1598
|
saved: "\u5DF2\u5132\u5B58",
|
|
1567
1599
|
remove: "\u522A\u9664",
|
|
@@ -2464,7 +2496,13 @@ function renderIcon(icon, className) {
|
|
|
2464
2496
|
|
|
2465
2497
|
// src/features/actions/KeepSavePopover.tsx
|
|
2466
2498
|
import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
|
|
2467
|
-
import {
|
|
2499
|
+
import {
|
|
2500
|
+
useCallback as useCallback3,
|
|
2501
|
+
useEffect as useEffect4,
|
|
2502
|
+
useId,
|
|
2503
|
+
useRef as useRef5,
|
|
2504
|
+
useState as useState4
|
|
2505
|
+
} from "react";
|
|
2468
2506
|
|
|
2469
2507
|
// src/features/editor/KeepQuickEditor.tsx
|
|
2470
2508
|
import { useKeepContext as useKeepContext2, useKeepItem as useKeepItem3 } from "@keepkit/core/react";
|
|
@@ -2483,12 +2521,16 @@ function useKeepQuickEditor(item, options = {}) {
|
|
|
2483
2521
|
const [note, setNote] = useState3(baseline.note ?? "");
|
|
2484
2522
|
const [tags, setTags] = useState3(baseline.tags ?? []);
|
|
2485
2523
|
const [collectionId, setCollectionId] = useState3(baseline.collectionId);
|
|
2524
|
+
const [saveStatus, setSaveStatus] = useState3("idle");
|
|
2525
|
+
const [saveError, setSaveError] = useState3(null);
|
|
2486
2526
|
const baselineRef = useRef4({
|
|
2487
2527
|
note: baseline.note ?? "",
|
|
2488
2528
|
tags: baseline.tags ?? [],
|
|
2489
2529
|
collectionId: baseline.collectionId
|
|
2490
2530
|
});
|
|
2491
2531
|
const draftRef = useRef4({ note, tags, collectionId });
|
|
2532
|
+
const flushRequestedRef = useRef4(false);
|
|
2533
|
+
const flushPromiseRef = useRef4(null);
|
|
2492
2534
|
draftRef.current = { note, tags, collectionId };
|
|
2493
2535
|
useEffect3(() => {
|
|
2494
2536
|
if (draftRef.current.note === baselineRef.current.note && sameTags(draftRef.current.tags, baselineRef.current.tags) && draftRef.current.collectionId === baselineRef.current.collectionId) {
|
|
@@ -2503,24 +2545,49 @@ function useKeepQuickEditor(item, options = {}) {
|
|
|
2503
2545
|
}
|
|
2504
2546
|
}, [baseline]);
|
|
2505
2547
|
const isDirty = note !== baselineRef.current.note || !sameTags(tags, baselineRef.current.tags) || collectionId !== baselineRef.current.collectionId;
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2548
|
+
useEffect3(() => {
|
|
2549
|
+
if (!isDirty && saveStatus === "dirty" && !flushPromiseRef.current) setSaveStatus("idle");
|
|
2550
|
+
}, [isDirty, saveStatus]);
|
|
2551
|
+
const flush = useCallback2(() => {
|
|
2552
|
+
flushRequestedRef.current = true;
|
|
2553
|
+
if (flushPromiseRef.current) return flushPromiseRef.current;
|
|
2554
|
+
const run = async () => {
|
|
2555
|
+
let saved = false;
|
|
2556
|
+
while (flushRequestedRef.current || !sameDraft(draftRef.current, baselineRef.current)) {
|
|
2557
|
+
flushRequestedRef.current = false;
|
|
2558
|
+
const draft = { ...draftRef.current, tags: [...draftRef.current.tags] };
|
|
2559
|
+
const previous = baselineRef.current;
|
|
2560
|
+
if (sameDraft(draft, previous)) continue;
|
|
2561
|
+
setSaveError(null);
|
|
2562
|
+
setSaveStatus("saving");
|
|
2563
|
+
try {
|
|
2564
|
+
if (draft.note !== previous.note) await updateNote(draft.note.trim() || void 0);
|
|
2565
|
+
if (!sameTags(draft.tags, previous.tags)) await updateTags(draft.tags);
|
|
2566
|
+
if (draft.collectionId !== previous.collectionId) await moveToCollection(draft.collectionId);
|
|
2567
|
+
} catch (error2) {
|
|
2568
|
+
setSaveError(error2);
|
|
2569
|
+
setSaveStatus("error");
|
|
2570
|
+
onSaveError?.(error2);
|
|
2571
|
+
throw error2;
|
|
2572
|
+
}
|
|
2573
|
+
baselineRef.current = draft;
|
|
2574
|
+
saved = true;
|
|
2575
|
+
const { collectionId: _oldCollectionId, ...withoutCollection } = baseline;
|
|
2576
|
+
onSaved?.({
|
|
2577
|
+
...withoutCollection,
|
|
2578
|
+
note: draft.note.trim() || void 0,
|
|
2579
|
+
tags: draft.tags,
|
|
2580
|
+
...draft.collectionId ? { collectionId: draft.collectionId } : {}
|
|
2581
|
+
});
|
|
2582
|
+
if (!sameDraft(draftRef.current, baselineRef.current)) flushRequestedRef.current = true;
|
|
2583
|
+
}
|
|
2584
|
+
if (saved) setSaveStatus("saved");
|
|
2585
|
+
};
|
|
2586
|
+
const promise = run().finally(() => {
|
|
2587
|
+
flushPromiseRef.current = null;
|
|
2588
|
+
});
|
|
2589
|
+
flushPromiseRef.current = promise;
|
|
2590
|
+
return promise;
|
|
2524
2591
|
}, [baseline, moveToCollection, onSaveError, onSaved, updateNote, updateTags]);
|
|
2525
2592
|
useEffect3(() => {
|
|
2526
2593
|
if (!isDirty || debounceMs <= 0) return;
|
|
@@ -2533,12 +2600,25 @@ function useKeepQuickEditor(item, options = {}) {
|
|
|
2533
2600
|
note,
|
|
2534
2601
|
tags,
|
|
2535
2602
|
collectionId,
|
|
2536
|
-
setNote
|
|
2537
|
-
|
|
2538
|
-
|
|
2603
|
+
setNote: (value) => {
|
|
2604
|
+
setSaveError(null);
|
|
2605
|
+
setSaveStatus("dirty");
|
|
2606
|
+
setNote(value);
|
|
2607
|
+
},
|
|
2608
|
+
setTags: (value) => {
|
|
2609
|
+
setSaveError(null);
|
|
2610
|
+
setSaveStatus("dirty");
|
|
2611
|
+
setTags(value);
|
|
2612
|
+
},
|
|
2613
|
+
setCollectionId: (value) => {
|
|
2614
|
+
setSaveError(null);
|
|
2615
|
+
setSaveStatus("dirty");
|
|
2616
|
+
setCollectionId(value);
|
|
2617
|
+
},
|
|
2539
2618
|
isDirty,
|
|
2540
|
-
isSaving: isMutating,
|
|
2541
|
-
|
|
2619
|
+
isSaving: isMutating || saveStatus === "saving",
|
|
2620
|
+
saveStatus,
|
|
2621
|
+
error: saveError ?? error,
|
|
2542
2622
|
flush
|
|
2543
2623
|
}
|
|
2544
2624
|
};
|
|
@@ -2546,17 +2626,24 @@ function useKeepQuickEditor(item, options = {}) {
|
|
|
2546
2626
|
function KeepQuickEditor({
|
|
2547
2627
|
item,
|
|
2548
2628
|
debounceMs = 300,
|
|
2629
|
+
onSaved,
|
|
2630
|
+
onSaveError,
|
|
2631
|
+
...props
|
|
2632
|
+
}) {
|
|
2633
|
+
const view = useKeepQuickEditor(item, { debounceMs, onSaved, onSaveError });
|
|
2634
|
+
return /* @__PURE__ */ jsx7(KeepQuickEditorView, { ...props, state: view.state });
|
|
2635
|
+
}
|
|
2636
|
+
function KeepQuickEditorView({
|
|
2637
|
+
state,
|
|
2549
2638
|
collectionIds,
|
|
2550
2639
|
collectionLabels,
|
|
2640
|
+
showSaveButton = true,
|
|
2551
2641
|
children,
|
|
2552
2642
|
onClose,
|
|
2553
|
-
|
|
2554
|
-
onSaveError,
|
|
2643
|
+
focusScopeRef,
|
|
2555
2644
|
...props
|
|
2556
2645
|
}) {
|
|
2557
|
-
const view = useKeepQuickEditor(item, { debounceMs, onSaved, onSaveError });
|
|
2558
2646
|
const context = useKeepContext2();
|
|
2559
|
-
const { state } = view;
|
|
2560
2647
|
const rootRef = useRef4(null);
|
|
2561
2648
|
const noteLabel = useUiLabel("note");
|
|
2562
2649
|
const tagsLabel = useUiLabel("tags");
|
|
@@ -2564,17 +2651,24 @@ function KeepQuickEditor({
|
|
|
2564
2651
|
const uncategorizedLabel = useUiLabel("uncategorized");
|
|
2565
2652
|
const saveLabel = useUiLabel("saveWithNote");
|
|
2566
2653
|
const closeLabel = useUiLabel("close");
|
|
2654
|
+
const unsavedChangesLabel = useUiLabel("unsavedChanges");
|
|
2655
|
+
const savingLabel = useUiLabel("saving");
|
|
2656
|
+
const savedLabel = useUiLabel("saved");
|
|
2657
|
+
const errorLabel = useUiLabel("error");
|
|
2567
2658
|
const submit = (event) => {
|
|
2568
2659
|
event.preventDefault();
|
|
2569
2660
|
void state.flush().catch(() => void 0);
|
|
2570
2661
|
};
|
|
2571
2662
|
const onKeyDown = (event) => {
|
|
2663
|
+
props.onKeyDown?.(event);
|
|
2664
|
+
if (event.defaultPrevented) return;
|
|
2572
2665
|
if (event.key === "Escape") {
|
|
2573
2666
|
event.preventDefault();
|
|
2574
2667
|
void state.flush().then(() => onClose?.()).catch(() => void 0);
|
|
2575
2668
|
}
|
|
2576
|
-
if (event.key === "Tab") trapFocus(event, rootRef.current);
|
|
2669
|
+
if (event.key === "Tab") trapFocus(event, focusScopeRef?.current ?? rootRef.current);
|
|
2577
2670
|
};
|
|
2671
|
+
const statusMessage = state.saveStatus === "dirty" ? unsavedChangesLabel : state.saveStatus === "saving" ? savingLabel : state.saveStatus === "saved" ? savedLabel : state.saveStatus === "error" ? getErrorMessage2(state.error, errorLabel) : null;
|
|
2578
2672
|
const body = typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
2579
2673
|
/* @__PURE__ */ jsxs5("label", { children: [
|
|
2580
2674
|
noteLabel,
|
|
@@ -2610,17 +2704,28 @@ function KeepQuickEditor({
|
|
|
2610
2704
|
}
|
|
2611
2705
|
)
|
|
2612
2706
|
] }),
|
|
2613
|
-
/* @__PURE__ */ jsx7(
|
|
2614
|
-
|
|
2707
|
+
statusMessage ? /* @__PURE__ */ jsx7(
|
|
2708
|
+
"p",
|
|
2709
|
+
{
|
|
2710
|
+
role: state.saveStatus === "error" ? "alert" : "status",
|
|
2711
|
+
"aria-live": state.saveStatus === "error" ? "assertive" : "polite",
|
|
2712
|
+
tabIndex: state.saveStatus === "error" ? -1 : void 0,
|
|
2713
|
+
"data-keep-editor-status": "true",
|
|
2714
|
+
"data-state": state.saveStatus,
|
|
2715
|
+
children: statusMessage
|
|
2716
|
+
}
|
|
2717
|
+
) : null,
|
|
2718
|
+
showSaveButton ? /* @__PURE__ */ jsx7("button", { type: "submit", disabled: state.isSaving, "data-keep-action": "save-quick-edit", children: saveLabel }) : null,
|
|
2719
|
+
onClose ? /* @__PURE__ */ jsx7(
|
|
2615
2720
|
"button",
|
|
2616
2721
|
{
|
|
2617
2722
|
type: "button",
|
|
2618
|
-
onClick: () => void state.flush().then(
|
|
2723
|
+
onClick: () => void state.flush().then(onClose).catch(() => void 0),
|
|
2619
2724
|
disabled: state.isSaving,
|
|
2620
2725
|
"data-keep-action": "close-quick-edit",
|
|
2621
2726
|
children: closeLabel
|
|
2622
2727
|
}
|
|
2623
|
-
)
|
|
2728
|
+
) : null
|
|
2624
2729
|
] });
|
|
2625
2730
|
return /* @__PURE__ */ jsx7(
|
|
2626
2731
|
"form",
|
|
@@ -2631,11 +2736,18 @@ function KeepQuickEditor({
|
|
|
2631
2736
|
onKeyDown,
|
|
2632
2737
|
"data-keepkit": "quick-editor",
|
|
2633
2738
|
"data-state": state.isDirty ? "dirty" : "clean",
|
|
2739
|
+
"data-save-status": state.saveStatus,
|
|
2634
2740
|
"aria-busy": state.isSaving || props["aria-busy"],
|
|
2635
2741
|
children: body
|
|
2636
2742
|
}
|
|
2637
2743
|
);
|
|
2638
2744
|
}
|
|
2745
|
+
function sameDraft(left, right) {
|
|
2746
|
+
return left.note === right.note && sameTags(left.tags, right.tags) && left.collectionId === right.collectionId;
|
|
2747
|
+
}
|
|
2748
|
+
function getErrorMessage2(error, fallback) {
|
|
2749
|
+
return error instanceof Error ? error.message : fallback;
|
|
2750
|
+
}
|
|
2639
2751
|
function sameTags(left, right) {
|
|
2640
2752
|
return left.length === right.length && left.every((tag, index) => tag === right[index]);
|
|
2641
2753
|
}
|
|
@@ -2663,6 +2775,7 @@ function KeepSavePopover({
|
|
|
2663
2775
|
open: controlledOpen,
|
|
2664
2776
|
defaultOpen = false,
|
|
2665
2777
|
onOpenChange,
|
|
2778
|
+
dialogLabel,
|
|
2666
2779
|
buttonProps,
|
|
2667
2780
|
editorProps,
|
|
2668
2781
|
children,
|
|
@@ -2672,18 +2785,24 @@ function KeepSavePopover({
|
|
|
2672
2785
|
const [internalOpen, setInternalOpen] = useState4(defaultOpen);
|
|
2673
2786
|
const isOpen = controlledOpen ?? internalOpen;
|
|
2674
2787
|
const triggerRef = useRef5(null);
|
|
2788
|
+
const wasOpenRef = useRef5(isOpen);
|
|
2675
2789
|
const previousSaved = useRef5(state.isSaved);
|
|
2676
2790
|
const observedHydration = useRef5(!state.isLoading);
|
|
2677
|
-
const
|
|
2791
|
+
const panelId = useId();
|
|
2792
|
+
const titleId = `${panelId}-title`;
|
|
2793
|
+
const editSavedItemLabel = useUiLabel("editSavedItem");
|
|
2678
2794
|
const { ref: _buttonRef, ...resolvedButtonProps } = buttonProps ?? {};
|
|
2679
2795
|
const setOpen = useCallback3(
|
|
2680
2796
|
(next) => {
|
|
2681
2797
|
if (controlledOpen === void 0) setInternalOpen(next);
|
|
2682
2798
|
onOpenChange?.(next);
|
|
2683
|
-
if (!next) window.setTimeout(() => triggerRef.current?.focus(), 0);
|
|
2684
2799
|
},
|
|
2685
2800
|
[controlledOpen, onOpenChange]
|
|
2686
2801
|
);
|
|
2802
|
+
useEffect4(() => {
|
|
2803
|
+
if (wasOpenRef.current && !isOpen) window.setTimeout(() => triggerRef.current?.focus(), 0);
|
|
2804
|
+
wasOpenRef.current = isOpen;
|
|
2805
|
+
}, [isOpen]);
|
|
2687
2806
|
useEffect4(() => {
|
|
2688
2807
|
if (!observedHydration.current) {
|
|
2689
2808
|
if (state.isLoading) return;
|
|
@@ -2694,16 +2813,112 @@ function KeepSavePopover({
|
|
|
2694
2813
|
if (!previousSaved.current && state.isSaved) setOpen(true);
|
|
2695
2814
|
previousSaved.current = state.isSaved;
|
|
2696
2815
|
}, [setOpen, state.isLoading, state.isSaved]);
|
|
2816
|
+
useEffect4(() => {
|
|
2817
|
+
if (isOpen && observedHydration.current && !state.isSaved) setOpen(false);
|
|
2818
|
+
}, [isOpen, setOpen, state.isSaved]);
|
|
2697
2819
|
const currentItem = state.item;
|
|
2698
2820
|
return /* @__PURE__ */ jsxs6("div", { ...props, "data-keepkit": "save-popover", "data-open": isOpen ? "true" : "false", children: [
|
|
2699
|
-
/* @__PURE__ */ jsx8(
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2821
|
+
/* @__PURE__ */ jsx8(
|
|
2822
|
+
KeepButton,
|
|
2823
|
+
{
|
|
2824
|
+
...resolvedButtonProps,
|
|
2825
|
+
item,
|
|
2826
|
+
asChild: false,
|
|
2827
|
+
ref: triggerRef,
|
|
2828
|
+
"aria-haspopup": "dialog",
|
|
2829
|
+
"aria-expanded": isOpen,
|
|
2830
|
+
"aria-controls": panelId
|
|
2831
|
+
}
|
|
2832
|
+
),
|
|
2833
|
+
isOpen && currentItem ? /* @__PURE__ */ jsx8(
|
|
2834
|
+
KeepSavePopoverPanel,
|
|
2835
|
+
{
|
|
2836
|
+
id: panelId,
|
|
2837
|
+
titleId,
|
|
2838
|
+
dialogLabel: dialogLabel ?? editSavedItemLabel,
|
|
2839
|
+
item: currentItem,
|
|
2840
|
+
editorProps,
|
|
2841
|
+
triggerRef,
|
|
2842
|
+
onClose: () => setOpen(false),
|
|
2843
|
+
children
|
|
2844
|
+
}
|
|
2845
|
+
) : null
|
|
2705
2846
|
] });
|
|
2706
2847
|
}
|
|
2848
|
+
function KeepSavePopoverPanel({
|
|
2849
|
+
id,
|
|
2850
|
+
titleId,
|
|
2851
|
+
dialogLabel,
|
|
2852
|
+
item,
|
|
2853
|
+
editorProps,
|
|
2854
|
+
triggerRef,
|
|
2855
|
+
onClose,
|
|
2856
|
+
children
|
|
2857
|
+
}) {
|
|
2858
|
+
const { debounceMs, onSaved, onSaveError, ...editorViewProps } = editorProps ?? {};
|
|
2859
|
+
const { state } = useKeepQuickEditor(item, { debounceMs, onSaved, onSaveError });
|
|
2860
|
+
const panelRef = useRef5(null);
|
|
2861
|
+
const closingRef = useRef5(null);
|
|
2862
|
+
const closeLabel = useUiLabel("close");
|
|
2863
|
+
const requestClose = useCallback3(() => {
|
|
2864
|
+
if (closingRef.current) return closingRef.current;
|
|
2865
|
+
const promise = state.flush().then(onClose).catch(() => {
|
|
2866
|
+
window.setTimeout(() => panelRef.current?.querySelector('[role="alert"]')?.focus(), 0);
|
|
2867
|
+
}).finally(() => {
|
|
2868
|
+
closingRef.current = null;
|
|
2869
|
+
});
|
|
2870
|
+
closingRef.current = promise;
|
|
2871
|
+
return promise;
|
|
2872
|
+
}, [onClose, state]);
|
|
2873
|
+
useEffect4(() => {
|
|
2874
|
+
const frame = window.requestAnimationFrame(() => {
|
|
2875
|
+
panelRef.current?.querySelector('[data-keepkit="quick-editor"] :is(textarea, input, select, button)')?.focus();
|
|
2876
|
+
});
|
|
2877
|
+
return () => window.cancelAnimationFrame(frame);
|
|
2878
|
+
}, []);
|
|
2879
|
+
useEffect4(() => {
|
|
2880
|
+
const closeFromOutside = (event) => {
|
|
2881
|
+
const target = event.target;
|
|
2882
|
+
if (!(target instanceof Node) || panelRef.current?.contains(target) || triggerRef.current?.contains(target))
|
|
2883
|
+
return;
|
|
2884
|
+
void requestClose();
|
|
2885
|
+
};
|
|
2886
|
+
document.addEventListener("pointerdown", closeFromOutside);
|
|
2887
|
+
return () => document.removeEventListener("pointerdown", closeFromOutside);
|
|
2888
|
+
}, [requestClose, triggerRef]);
|
|
2889
|
+
return /* @__PURE__ */ jsxs6(
|
|
2890
|
+
"div",
|
|
2891
|
+
{
|
|
2892
|
+
ref: panelRef,
|
|
2893
|
+
id,
|
|
2894
|
+
role: "dialog",
|
|
2895
|
+
"aria-labelledby": titleId,
|
|
2896
|
+
"data-keep-popover-panel": "true",
|
|
2897
|
+
"data-save-status": state.saveStatus,
|
|
2898
|
+
onKeyDownCapture: (event) => {
|
|
2899
|
+
if (event.key !== "Escape") return;
|
|
2900
|
+
event.preventDefault();
|
|
2901
|
+
event.stopPropagation();
|
|
2902
|
+
void requestClose();
|
|
2903
|
+
},
|
|
2904
|
+
children: [
|
|
2905
|
+
/* @__PURE__ */ jsx8("h2", { id: titleId, "data-keep-popover-title": "true", children: dialogLabel }),
|
|
2906
|
+
children,
|
|
2907
|
+
/* @__PURE__ */ jsx8(KeepQuickEditorView, { ...editorViewProps, state, focusScopeRef: panelRef }),
|
|
2908
|
+
/* @__PURE__ */ jsx8(
|
|
2909
|
+
"button",
|
|
2910
|
+
{
|
|
2911
|
+
type: "button",
|
|
2912
|
+
onClick: () => void requestClose(),
|
|
2913
|
+
disabled: state.isSaving,
|
|
2914
|
+
"data-keep-action": "close-save-popover",
|
|
2915
|
+
children: closeLabel
|
|
2916
|
+
}
|
|
2917
|
+
)
|
|
2918
|
+
]
|
|
2919
|
+
}
|
|
2920
|
+
);
|
|
2921
|
+
}
|
|
2707
2922
|
|
|
2708
2923
|
// src/features/actions/hooks/useKeepUndo.ts
|
|
2709
2924
|
import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
|
|
@@ -3854,26 +4069,10 @@ function KeepItemCardRoot({
|
|
|
3854
4069
|
" ",
|
|
3855
4070
|
/* @__PURE__ */ jsx16("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
|
|
3856
4071
|
] }) : null;
|
|
3857
|
-
const error = view.itemState.error ? /* @__PURE__ */ jsx16("p", { role: "alert", children:
|
|
4072
|
+
const error = view.itemState.error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: getErrorMessage3(view.itemState.error, view.labels.error) }) : null;
|
|
3858
4073
|
const actions = view.statusLabel ? /* @__PURE__ */ jsx16(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
3859
|
-
showSaveButton ? /* @__PURE__ */ jsx16(
|
|
3860
|
-
|
|
3861
|
-
{
|
|
3862
|
-
item: toKeepButtonItem(item),
|
|
3863
|
-
labels: saveButtonLabels,
|
|
3864
|
-
getAriaLabel: (buttonState) => `${buttonState.isSaved ? view.labels.remove : view.labels.save} ${String(view.resolvedTitle)}`
|
|
3865
|
-
}
|
|
3866
|
-
) : null,
|
|
3867
|
-
/* @__PURE__ */ jsx16(
|
|
3868
|
-
"button",
|
|
3869
|
-
{
|
|
3870
|
-
type: "button",
|
|
3871
|
-
"data-keep-action": "remove-item",
|
|
3872
|
-
onClick: () => void view.remove(),
|
|
3873
|
-
disabled: view.itemState.isMutating,
|
|
3874
|
-
children: removeLabel ?? view.labels.remove
|
|
3875
|
-
}
|
|
3876
|
-
)
|
|
4074
|
+
showSaveButton ? /* @__PURE__ */ jsx16(KeepItemCardSave, {}) : null,
|
|
4075
|
+
/* @__PURE__ */ jsx16(KeepItemCardRemove, {})
|
|
3877
4076
|
] });
|
|
3878
4077
|
const compoundValue = {
|
|
3879
4078
|
item,
|
|
@@ -3889,6 +4088,11 @@ function KeepItemCardRoot({
|
|
|
3889
4088
|
meta,
|
|
3890
4089
|
error,
|
|
3891
4090
|
actions,
|
|
4091
|
+
saveButtonLabels,
|
|
4092
|
+
removeLabel: removeLabel ?? view.labels.remove,
|
|
4093
|
+
remove: view.remove,
|
|
4094
|
+
isMutating: view.itemState.isMutating,
|
|
4095
|
+
saveAriaLabel: `${view.labels.remove} ${String(view.resolvedTitle)}`,
|
|
3892
4096
|
renderText: (content) => /* @__PURE__ */ jsx16(KeepHighlight, { query: searchQuery, children: content })
|
|
3893
4097
|
};
|
|
3894
4098
|
const defaultBody = /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
@@ -3962,6 +4166,36 @@ function KeepItemCardActions({ children, ...props }) {
|
|
|
3962
4166
|
const context = useKeepItemCardCompound("Actions");
|
|
3963
4167
|
return /* @__PURE__ */ jsx16("div", { ...props, "data-keep-card-part": "actions", children: children ?? context.actions });
|
|
3964
4168
|
}
|
|
4169
|
+
function KeepItemCardSave({ labels, getAriaLabel, ...props }) {
|
|
4170
|
+
const context = useKeepItemCardCompound("Save");
|
|
4171
|
+
return /* @__PURE__ */ jsx16(
|
|
4172
|
+
KeepButton,
|
|
4173
|
+
{
|
|
4174
|
+
...props,
|
|
4175
|
+
item: toKeepButtonItem(context.item),
|
|
4176
|
+
asChild: false,
|
|
4177
|
+
labels: labels ?? context.saveButtonLabels,
|
|
4178
|
+
getAriaLabel: getAriaLabel ?? (() => context.saveAriaLabel)
|
|
4179
|
+
}
|
|
4180
|
+
);
|
|
4181
|
+
}
|
|
4182
|
+
function KeepItemCardRemove({ children, disabled, onClick, ...props }) {
|
|
4183
|
+
const context = useKeepItemCardCompound("Remove");
|
|
4184
|
+
return /* @__PURE__ */ jsx16(
|
|
4185
|
+
"button",
|
|
4186
|
+
{
|
|
4187
|
+
...props,
|
|
4188
|
+
type: props.type ?? "button",
|
|
4189
|
+
"data-keep-action": "remove-item",
|
|
4190
|
+
disabled: disabled ?? context.isMutating,
|
|
4191
|
+
onClick: (event) => {
|
|
4192
|
+
onClick?.(event);
|
|
4193
|
+
if (!event.defaultPrevented) void context.remove();
|
|
4194
|
+
},
|
|
4195
|
+
children: children ?? context.removeLabel
|
|
4196
|
+
}
|
|
4197
|
+
);
|
|
4198
|
+
}
|
|
3965
4199
|
function KeepItemCardPin({ children, ...props }) {
|
|
3966
4200
|
const context = useKeepItemCardCompound("Pin");
|
|
3967
4201
|
return /* @__PURE__ */ jsx16(KeepPinButton, { ...props, item: context.item, children });
|
|
@@ -3984,6 +4218,8 @@ var KeepItemCard = Object.assign(KeepItemCardRoot, {
|
|
|
3984
4218
|
Title: KeepItemCardTitle,
|
|
3985
4219
|
Tags: KeepItemCardTags,
|
|
3986
4220
|
Actions: KeepItemCardActions,
|
|
4221
|
+
Save: KeepItemCardSave,
|
|
4222
|
+
Remove: KeepItemCardRemove,
|
|
3987
4223
|
Pin: KeepItemCardPin,
|
|
3988
4224
|
Archive: KeepItemCardArchive,
|
|
3989
4225
|
CollectionBadge: KeepItemCardCollectionBadge
|
|
@@ -4000,7 +4236,7 @@ function KeepItemCardSkeleton({ layout = "list", ...props }) {
|
|
|
4000
4236
|
function formatSavedAt(timestamp) {
|
|
4001
4237
|
return new Date(timestamp).toISOString().slice(0, 10);
|
|
4002
4238
|
}
|
|
4003
|
-
function
|
|
4239
|
+
function getErrorMessage3(error, fallback) {
|
|
4004
4240
|
return error instanceof Error ? error.message : fallback;
|
|
4005
4241
|
}
|
|
4006
4242
|
|
|
@@ -4588,7 +4824,7 @@ function KeepNoteEditor({
|
|
|
4588
4824
|
"data-disabled": isSaving ? "true" : void 0,
|
|
4589
4825
|
children: [
|
|
4590
4826
|
body,
|
|
4591
|
-
error ? /* @__PURE__ */ jsx23("p", { role: "alert", children:
|
|
4827
|
+
error ? /* @__PURE__ */ jsx23("p", { role: "alert", children: getErrorMessage4(error, view.labels.error) }) : null
|
|
4592
4828
|
]
|
|
4593
4829
|
}
|
|
4594
4830
|
);
|
|
@@ -4610,7 +4846,7 @@ function KeepNoteEditor({
|
|
|
4610
4846
|
"KeepNoteEditor"
|
|
4611
4847
|
);
|
|
4612
4848
|
}
|
|
4613
|
-
function
|
|
4849
|
+
function getErrorMessage4(error, fallback) {
|
|
4614
4850
|
return error instanceof Error ? error.message : fallback;
|
|
4615
4851
|
}
|
|
4616
4852
|
|
|
@@ -4712,12 +4948,12 @@ function KeepTagEditor({
|
|
|
4712
4948
|
"data-disabled": isSaving ? "true" : void 0,
|
|
4713
4949
|
children: [
|
|
4714
4950
|
body,
|
|
4715
|
-
view.error ? /* @__PURE__ */ jsx24("p", { role: "alert", children:
|
|
4951
|
+
view.error ? /* @__PURE__ */ jsx24("p", { role: "alert", children: getErrorMessage5(view.error, view.labels.error) }) : null
|
|
4716
4952
|
]
|
|
4717
4953
|
}
|
|
4718
4954
|
);
|
|
4719
4955
|
}
|
|
4720
|
-
function
|
|
4956
|
+
function getErrorMessage5(error, fallback) {
|
|
4721
4957
|
return error instanceof Error ? error.message : fallback;
|
|
4722
4958
|
}
|
|
4723
4959
|
|
|
@@ -4743,7 +4979,7 @@ function useKeepToastFeedback(showToast) {
|
|
|
4743
4979
|
|
|
4744
4980
|
// src/features/navigation/KeepTourBar.tsx
|
|
4745
4981
|
import { useKeepNavigator } from "@keepkit/core/react";
|
|
4746
|
-
import { useId } from "react";
|
|
4982
|
+
import { useId as useId2 } from "react";
|
|
4747
4983
|
|
|
4748
4984
|
// src/features/navigation/hooks/useKeepTourShortcuts.ts
|
|
4749
4985
|
import { useEffect as useEffect11 } from "react";
|
|
@@ -4865,7 +5101,7 @@ function KeepTourBar({
|
|
|
4865
5101
|
);
|
|
4866
5102
|
}
|
|
4867
5103
|
function TourAction({ href, disabled = false, onClick, children, preview, shortcut, ...props }) {
|
|
4868
|
-
const previewId =
|
|
5104
|
+
const previewId = useId2();
|
|
4869
5105
|
const content = /* @__PURE__ */ jsxs21(Fragment13, { children: [
|
|
4870
5106
|
/* @__PURE__ */ jsx25("span", { "data-tour-label": "true", children }),
|
|
4871
5107
|
shortcut ? /* @__PURE__ */ jsx25(KeepShortcutHint, { shortcut }) : null,
|
|
@@ -5226,7 +5462,7 @@ function useKeepSyncStatusBanner({ onRetry, children }) {
|
|
|
5226
5462
|
const syncedLabel = useUiLabel("syncSynced");
|
|
5227
5463
|
const status = context.syncState.status;
|
|
5228
5464
|
const hasConflicts = (context.syncState.conflicts?.length ?? 0) > 0 || context.syncState.conflictIds.length > 0;
|
|
5229
|
-
const message = children ?? (status === "error" ?
|
|
5465
|
+
const message = children ?? (status === "error" ? getErrorMessage6(context.syncState.error) : status === "conflict" || hasConflicts ? conflictLabel : status === "pending" || status === "syncing" ? pendingLabel : syncedLabel);
|
|
5230
5466
|
return {
|
|
5231
5467
|
status,
|
|
5232
5468
|
hasConflicts,
|
|
@@ -5245,7 +5481,7 @@ function useKeepSyncStatusBanner({ onRetry, children }) {
|
|
|
5245
5481
|
}
|
|
5246
5482
|
};
|
|
5247
5483
|
}
|
|
5248
|
-
function
|
|
5484
|
+
function getErrorMessage6(error) {
|
|
5249
5485
|
return error instanceof Error ? error.message : "Sync failed.";
|
|
5250
5486
|
}
|
|
5251
5487
|
|