@keepkit/ui 0.11.0 → 0.13.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
@@ -12,8 +12,82 @@ import { useRef, useState } from "react";
12
12
 
13
13
  // src/ui-context.tsx
14
14
  import { createContext, useContext, useMemo } from "react";
15
- import { jsx } from "react/jsx-runtime";
16
- var DEFAULT_LABELS = {
15
+
16
+ // src/locales/de.ts
17
+ var DE_LABELS = {
18
+ save: "Speichern",
19
+ saved: "Gespeichert",
20
+ remove: "Entfernen",
21
+ loading: "Wird geladen\u2026",
22
+ saving: "Wird gespeichert\u2026",
23
+ syncing: "Wird synchronisiert\u2026",
24
+ error: "Ein Fehler ist aufgetreten.",
25
+ allTags: "Alle",
26
+ tags: "Tags",
27
+ filterTags: "Gespeicherte Elemente nach Tag filtern",
28
+ note: "Notiz",
29
+ saveNote: "Notiz speichern",
30
+ noItems: "Keine gespeicherten Elemente.",
31
+ loadingItems: "Gespeicherte Elemente werden geladen\u2026",
32
+ errorItems: "Gespeicherte Elemente konnten nicht geladen werden.",
33
+ search: "Gespeicherte Elemente durchsuchen",
34
+ sort: "Gespeicherte Elemente sortieren",
35
+ newest: "Neueste zuerst",
36
+ oldest: "\xC4lteste zuerst",
37
+ savedNewest: "Zuletzt gespeichert zuerst",
38
+ savedOldest: "Am l\xE4ngsten gespeichert zuerst",
39
+ updatedNewest: "Zuletzt aktualisiert zuerst",
40
+ updatedOldest: "Am l\xE4ngsten nicht aktualisiert zuerst",
41
+ previousPage: "Vorherige Seite",
42
+ nextPage: "N\xE4chste Seite",
43
+ pagination: "Seitennavigation",
44
+ page: "Seite",
45
+ selectItems: "Gespeicherte Elemente ausw\xE4hlen",
46
+ selectedCount: "ausgew\xE4hlt",
47
+ deleteSelected: "Auswahl l\xF6schen",
48
+ tagsToApply: "Anzuwendende Tags",
49
+ applyTags: "Tags anwenden",
50
+ savedMessage: "Element gespeichert.",
51
+ removedMessage: "Element entfernt.",
52
+ undo: "R\xFCckg\xE4ngig",
53
+ undoAvailable: "Element entfernt. R\xFCckg\xE4ngig machen?",
54
+ selectionScope: "Auswahlbereich",
55
+ currentPage: "Aktuelle Seite",
56
+ searchResults: "Aktuelle Suchergebnisse",
57
+ allItems: "Alle gespeicherten Elemente",
58
+ statusAvailable: "Verf\xFCgbar",
59
+ noteSavedMessage: "Notiz gespeichert.",
60
+ exportData: "JSON exportieren",
61
+ importData: "JSON importieren",
62
+ importMode: "Importmodus",
63
+ merge: "Zusammenf\xFChren",
64
+ replace: "Ersetzen",
65
+ importedCount: "Elemente importiert",
66
+ failedCount: "Elemente fehlgeschlagen",
67
+ storageQuotaError: "Der Speicher ist voll. Schaffen Sie Speicherplatz und versuchen Sie es erneut.",
68
+ statusExpired: "Abgelaufen",
69
+ statusRemoved: "Entfernt",
70
+ statusDeleted: "Gel\xF6scht",
71
+ statusPrivate: "Privat",
72
+ statusUnknown: "Nicht verf\xFCgbar",
73
+ retry: "Erneut versuchen",
74
+ removeFromList: "Aus Liste entfernen",
75
+ pruneStale: "Nicht verf\xFCgbare Elemente entfernen",
76
+ retrySync: "Synchronisierung erneut versuchen",
77
+ resolveSync: "Konflikte l\xF6sen",
78
+ keepLocal: "Lokale Version behalten",
79
+ useServer: "Serverversion verwenden",
80
+ manualMerge: "Manuell zusammenf\xFChren",
81
+ close: "Schlie\xDFen",
82
+ backupRecovery: "Aus Backup wiederherstellen",
83
+ backupRecoveryDescription: "Wenn lokale Synchronisierungsdaten besch\xE4digt sind, stellen Sie ein g\xFCltiges JSON-Backup wieder her.",
84
+ syncPending: "\xC4nderungen warten auf die Synchronisierung.",
85
+ syncSynced: "Alle \xC4nderungen sind synchronisiert.",
86
+ syncConflict: "Einige \xC4nderungen ben\xF6tigen eine Konfliktl\xF6sung."
87
+ };
88
+
89
+ // src/locales/en.ts
90
+ var EN_LABELS = {
17
91
  save: "Save",
18
92
  saved: "Saved",
19
93
  remove: "Remove",
@@ -68,122 +142,1114 @@ var DEFAULT_LABELS = {
68
142
  statusRemoved: "Removed",
69
143
  statusDeleted: "Deleted",
70
144
  statusPrivate: "Private",
71
- statusUnknown: "Unavailable"
145
+ statusUnknown: "Unavailable",
146
+ retry: "Retry",
147
+ removeFromList: "Remove from list",
148
+ pruneStale: "Remove unavailable items",
149
+ retrySync: "Retry sync",
150
+ resolveSync: "Resolve conflicts",
151
+ keepLocal: "Keep local",
152
+ useServer: "Use server",
153
+ manualMerge: "Manual merge",
154
+ close: "Close",
155
+ backupRecovery: "Restore from backup",
156
+ backupRecoveryDescription: "If local sync data is damaged, restore a known-good JSON backup.",
157
+ syncPending: "Changes are waiting to sync.",
158
+ syncSynced: "All changes are synced.",
159
+ syncConflict: "Some changes need conflict resolution."
160
+ };
161
+
162
+ // src/locales/es.ts
163
+ var ES_LABELS = {
164
+ save: "Guardar",
165
+ saved: "Guardado",
166
+ remove: "Eliminar",
167
+ loading: "Cargando\u2026",
168
+ saving: "Guardando\u2026",
169
+ syncing: "Sincronizando\u2026",
170
+ error: "Se produjo un error.",
171
+ allTags: "Todos",
172
+ tags: "Etiquetas",
173
+ filterTags: "Filtrar elementos guardados por etiqueta",
174
+ note: "Nota",
175
+ saveNote: "Guardar nota",
176
+ noItems: "No hay elementos guardados.",
177
+ loadingItems: "Cargando elementos guardados\u2026",
178
+ errorItems: "No se pudieron cargar los elementos guardados.",
179
+ search: "Buscar elementos guardados",
180
+ sort: "Ordenar elementos guardados",
181
+ newest: "M\xE1s recientes primero",
182
+ oldest: "M\xE1s antiguos primero",
183
+ savedNewest: "Guardados m\xE1s recientemente primero",
184
+ savedOldest: "Guardados m\xE1s antiguos primero",
185
+ updatedNewest: "Actualizados m\xE1s recientemente primero",
186
+ updatedOldest: "Actualizados m\xE1s antiguos primero",
187
+ previousPage: "P\xE1gina anterior",
188
+ nextPage: "P\xE1gina siguiente",
189
+ pagination: "Paginaci\xF3n",
190
+ page: "P\xE1gina",
191
+ selectItems: "Seleccionar elementos guardados",
192
+ selectedCount: "seleccionados",
193
+ deleteSelected: "Eliminar seleccionados",
194
+ tagsToApply: "Etiquetas que aplicar",
195
+ applyTags: "Aplicar etiquetas",
196
+ savedMessage: "Elemento guardado.",
197
+ removedMessage: "Elemento eliminado.",
198
+ undo: "Deshacer",
199
+ undoAvailable: "Elemento eliminado. \xBFDeshacer?",
200
+ selectionScope: "\xC1mbito de selecci\xF3n",
201
+ currentPage: "P\xE1gina actual",
202
+ searchResults: "Resultados de b\xFAsqueda actuales",
203
+ allItems: "Todos los elementos guardados",
204
+ statusAvailable: "Disponible",
205
+ noteSavedMessage: "Nota guardada.",
206
+ exportData: "Exportar JSON",
207
+ importData: "Importar JSON",
208
+ importMode: "Modo de importaci\xF3n",
209
+ merge: "Combinar",
210
+ replace: "Reemplazar",
211
+ importedCount: "elementos importados",
212
+ failedCount: "elementos fallidos",
213
+ storageQuotaError: "El almacenamiento est\xE1 lleno. Libere espacio y vuelva a intentarlo.",
214
+ statusExpired: "Caducado",
215
+ statusRemoved: "Eliminado",
216
+ statusDeleted: "Borrado",
217
+ statusPrivate: "Privado",
218
+ statusUnknown: "No disponible",
219
+ retry: "Reintentar",
220
+ removeFromList: "Quitar de la lista",
221
+ pruneStale: "Quitar elementos no disponibles",
222
+ retrySync: "Reintentar sincronizaci\xF3n",
223
+ resolveSync: "Resolver conflictos",
224
+ keepLocal: "Conservar versi\xF3n local",
225
+ useServer: "Usar versi\xF3n del servidor",
226
+ manualMerge: "Combinar manualmente",
227
+ close: "Cerrar",
228
+ backupRecovery: "Restaurar desde copia de seguridad",
229
+ backupRecoveryDescription: "Si los datos locales est\xE1n da\xF1ados, restaura una copia JSON v\xE1lida.",
230
+ syncPending: "Hay cambios pendientes de sincronizaci\xF3n.",
231
+ syncSynced: "Todos los cambios est\xE1n sincronizados.",
232
+ syncConflict: "Algunos cambios necesitan resolver un conflicto."
233
+ };
234
+
235
+ // src/locales/fil.ts
236
+ var FIL_LABELS = {
237
+ save: "I-save",
238
+ saved: "Nai-save",
239
+ remove: "Alisin",
240
+ loading: "Naglo-load\u2026",
241
+ saving: "Sini-save\u2026",
242
+ syncing: "Sini-sync\u2026",
243
+ error: "May naganap na error.",
244
+ allTags: "Lahat",
245
+ tags: "Mga tag",
246
+ filterTags: "I-filter ang mga naka-save na item ayon sa tag",
247
+ note: "Tala",
248
+ saveNote: "I-save ang tala",
249
+ noItems: "Walang naka-save na item.",
250
+ loadingItems: "Nilo-load ang mga naka-save na item\u2026",
251
+ errorItems: "Hindi ma-load ang mga naka-save na item.",
252
+ search: "Maghanap ng naka-save na item",
253
+ sort: "Ayusin ang mga naka-save na item",
254
+ newest: "Pinakabago muna",
255
+ oldest: "Pinakaluma muna",
256
+ savedNewest: "Pinakabagong na-save muna",
257
+ savedOldest: "Pinakamatagal na naka-save muna",
258
+ updatedNewest: "Pinakabagong na-update muna",
259
+ updatedOldest: "Pinakamatagal na hindi na-update muna",
260
+ previousPage: "Nakaraang pahina",
261
+ nextPage: "Susunod na pahina",
262
+ pagination: "Pagpapa-pahina",
263
+ page: "Pahina",
264
+ selectItems: "Pumili ng naka-save na item",
265
+ selectedCount: "napili",
266
+ deleteSelected: "Tanggalin ang napili",
267
+ tagsToApply: "Mga tag na ilalapat",
268
+ applyTags: "Ilapat ang mga tag",
269
+ savedMessage: "Na-save ang item.",
270
+ removedMessage: "Inalis ang item.",
271
+ undo: "I-undo",
272
+ undoAvailable: "Inalis ang item. I-undo?",
273
+ selectionScope: "Saklaw ng pagpili",
274
+ currentPage: "Kasalukuyang pahina",
275
+ searchResults: "Kasalukuyang resulta ng paghahanap",
276
+ allItems: "Lahat ng naka-save na item",
277
+ statusAvailable: "Available",
278
+ noteSavedMessage: "Na-save ang tala.",
279
+ exportData: "I-export ang JSON",
280
+ importData: "I-import ang JSON",
281
+ importMode: "Mode ng pag-import",
282
+ merge: "Pagsamahin",
283
+ replace: "Palitan",
284
+ importedCount: "item ang na-import",
285
+ failedCount: "item ang nabigo",
286
+ storageQuotaError: "Puno na ang storage. Magbakante ng espasyo at subukan muli.",
287
+ statusExpired: "Nag-expire",
288
+ statusRemoved: "Inalis",
289
+ statusDeleted: "Tinanggal",
290
+ statusPrivate: "Pribado",
291
+ statusUnknown: "Hindi available",
292
+ retry: "Subukan muli",
293
+ removeFromList: "Alisin sa listahan",
294
+ pruneStale: "Alisin ang hindi available na item",
295
+ retrySync: "Subukan muli ang sync",
296
+ resolveSync: "Ayusin ang mga conflict",
297
+ keepLocal: "Panatilihin ang lokal",
298
+ useServer: "Gamitin ang server",
299
+ manualMerge: "Manwal na pagsamahin",
300
+ close: "Isara",
301
+ backupRecovery: "I-restore mula sa backup",
302
+ backupRecoveryDescription: "Kung sira ang lokal na sync data, mag-restore ng gumaganang JSON backup.",
303
+ syncPending: "May mga pagbabagong naghihintay ng sync.",
304
+ syncSynced: "Naka-sync na ang lahat ng pagbabago.",
305
+ syncConflict: "May mga pagbabagong kailangang ayusin ang conflict."
306
+ };
307
+
308
+ // src/locales/fr.ts
309
+ var FR_LABELS = {
310
+ save: "Enregistrer",
311
+ saved: "Enregistr\xE9",
312
+ remove: "Supprimer",
313
+ loading: "Chargement\u2026",
314
+ saving: "Enregistrement\u2026",
315
+ syncing: "Synchronisation\u2026",
316
+ error: "Une erreur s\u2019est produite.",
317
+ allTags: "Tous",
318
+ tags: "\xC9tiquettes",
319
+ filterTags: "Filtrer les \xE9l\xE9ments enregistr\xE9s par \xE9tiquette",
320
+ note: "Note",
321
+ saveNote: "Enregistrer la note",
322
+ noItems: "Aucun \xE9l\xE9ment enregistr\xE9.",
323
+ loadingItems: "Chargement des \xE9l\xE9ments enregistr\xE9s\u2026",
324
+ errorItems: "Impossible de charger les \xE9l\xE9ments enregistr\xE9s.",
325
+ search: "Rechercher des \xE9l\xE9ments enregistr\xE9s",
326
+ sort: "Trier les \xE9l\xE9ments enregistr\xE9s",
327
+ newest: "Plus r\xE9cent d\u2019abord",
328
+ oldest: "Plus ancien d\u2019abord",
329
+ savedNewest: "Enregistrement le plus r\xE9cent d\u2019abord",
330
+ savedOldest: "Enregistrement le plus ancien d\u2019abord",
331
+ updatedNewest: "Mise \xE0 jour la plus r\xE9cente d\u2019abord",
332
+ updatedOldest: "Mise \xE0 jour la plus ancienne d\u2019abord",
333
+ previousPage: "Page pr\xE9c\xE9dente",
334
+ nextPage: "Page suivante",
335
+ pagination: "Pagination",
336
+ page: "Page",
337
+ selectItems: "S\xE9lectionner les \xE9l\xE9ments enregistr\xE9s",
338
+ selectedCount: "s\xE9lectionn\xE9s",
339
+ deleteSelected: "Supprimer la s\xE9lection",
340
+ tagsToApply: "\xC9tiquettes \xE0 appliquer",
341
+ applyTags: "Appliquer les \xE9tiquettes",
342
+ savedMessage: "\xC9l\xE9ment enregistr\xE9.",
343
+ removedMessage: "\xC9l\xE9ment supprim\xE9.",
344
+ undo: "Annuler",
345
+ undoAvailable: "\xC9l\xE9ment supprim\xE9. Annuler ?",
346
+ selectionScope: "Port\xE9e de la s\xE9lection",
347
+ currentPage: "Page actuelle",
348
+ searchResults: "R\xE9sultats de recherche actuels",
349
+ allItems: "Tous les \xE9l\xE9ments enregistr\xE9s",
350
+ statusAvailable: "Disponible",
351
+ noteSavedMessage: "Note enregistr\xE9e.",
352
+ exportData: "Exporter JSON",
353
+ importData: "Importer JSON",
354
+ importMode: "Mode d\u2019importation",
355
+ merge: "Fusionner",
356
+ replace: "Remplacer",
357
+ importedCount: "\xE9l\xE9ments import\xE9s",
358
+ failedCount: "\xE9l\xE9ments en \xE9chec",
359
+ storageQuotaError: "Le stockage est plein. Lib\xE9rez de l\u2019espace et r\xE9essayez.",
360
+ statusExpired: "Expir\xE9",
361
+ statusRemoved: "Supprim\xE9",
362
+ statusDeleted: "Effac\xE9",
363
+ statusPrivate: "Priv\xE9",
364
+ statusUnknown: "Indisponible",
365
+ retry: "R\xE9essayer",
366
+ removeFromList: "Retirer de la liste",
367
+ pruneStale: "Retirer les \xE9l\xE9ments indisponibles",
368
+ retrySync: "R\xE9essayer la synchronisation",
369
+ resolveSync: "R\xE9soudre les conflits",
370
+ keepLocal: "Garder la version locale",
371
+ useServer: "Utiliser la version serveur",
372
+ manualMerge: "Fusion manuelle",
373
+ close: "Fermer",
374
+ backupRecovery: "Restaurer depuis une sauvegarde",
375
+ backupRecoveryDescription: "Si les donn\xE9es locales sont endommag\xE9es, restaurez une sauvegarde JSON valide.",
376
+ syncPending: "Des modifications attendent la synchronisation.",
377
+ syncSynced: "Toutes les modifications sont synchronis\xE9es.",
378
+ syncConflict: "Certaines modifications n\xE9cessitent une r\xE9solution de conflit."
379
+ };
380
+
381
+ // src/locales/id.ts
382
+ var ID_LABELS = {
383
+ save: "Simpan",
384
+ saved: "Tersimpan",
385
+ remove: "Hapus",
386
+ loading: "Memuat\u2026",
387
+ saving: "Menyimpan\u2026",
388
+ syncing: "Menyinkronkan\u2026",
389
+ error: "Terjadi kesalahan.",
390
+ allTags: "Semua",
391
+ tags: "Tag",
392
+ filterTags: "Filter item tersimpan berdasarkan tag",
393
+ note: "Catatan",
394
+ saveNote: "Simpan catatan",
395
+ noItems: "Belum ada item tersimpan.",
396
+ loadingItems: "Memuat item tersimpan\u2026",
397
+ errorItems: "Tidak dapat memuat item tersimpan.",
398
+ search: "Cari item tersimpan",
399
+ sort: "Urutkan item tersimpan",
400
+ newest: "Terbaru dahulu",
401
+ oldest: "Terlama dahulu",
402
+ savedNewest: "Paling baru disimpan dahulu",
403
+ savedOldest: "Paling lama disimpan dahulu",
404
+ updatedNewest: "Paling baru diperbarui dahulu",
405
+ updatedOldest: "Paling lama diperbarui dahulu",
406
+ previousPage: "Halaman sebelumnya",
407
+ nextPage: "Halaman berikutnya",
408
+ pagination: "Paginasi",
409
+ page: "Halaman",
410
+ selectItems: "Pilih item tersimpan",
411
+ selectedCount: "dipilih",
412
+ deleteSelected: "Hapus yang dipilih",
413
+ tagsToApply: "Tag yang akan diterapkan",
414
+ applyTags: "Terapkan tag",
415
+ savedMessage: "Item tersimpan.",
416
+ removedMessage: "Item dihapus.",
417
+ undo: "Urungkan",
418
+ undoAvailable: "Item dihapus. Urungkan?",
419
+ selectionScope: "Cakupan pilihan",
420
+ currentPage: "Halaman saat ini",
421
+ searchResults: "Hasil pencarian saat ini",
422
+ allItems: "Semua item tersimpan",
423
+ statusAvailable: "Tersedia",
424
+ noteSavedMessage: "Catatan tersimpan.",
425
+ exportData: "Ekspor JSON",
426
+ importData: "Impor JSON",
427
+ importMode: "Mode impor",
428
+ merge: "Gabungkan",
429
+ replace: "Ganti",
430
+ importedCount: "item diimpor",
431
+ failedCount: "item gagal",
432
+ storageQuotaError: "Penyimpanan penuh. Kosongkan ruang lalu coba lagi.",
433
+ statusExpired: "Kedaluwarsa",
434
+ statusRemoved: "Dihapus",
435
+ statusDeleted: "Terhapus",
436
+ statusPrivate: "Pribadi",
437
+ statusUnknown: "Tidak tersedia",
438
+ retry: "Coba lagi",
439
+ removeFromList: "Hapus dari daftar",
440
+ pruneStale: "Hapus item yang tidak tersedia",
441
+ retrySync: "Coba sinkronisasi lagi",
442
+ resolveSync: "Selesaikan konflik",
443
+ keepLocal: "Pertahankan versi lokal",
444
+ useServer: "Gunakan versi server",
445
+ manualMerge: "Gabungkan manual",
446
+ close: "Tutup",
447
+ backupRecovery: "Pulihkan dari cadangan",
448
+ backupRecoveryDescription: "Jika data sinkronisasi lokal rusak, pulihkan cadangan JSON yang valid.",
449
+ syncPending: "Ada perubahan yang menunggu sinkronisasi.",
450
+ syncSynced: "Semua perubahan telah disinkronkan.",
451
+ syncConflict: "Beberapa perubahan memerlukan penyelesaian konflik."
452
+ };
453
+
454
+ // src/locales/it.ts
455
+ var IT_LABELS = {
456
+ save: "Salva",
457
+ saved: "Salvato",
458
+ remove: "Rimuovi",
459
+ loading: "Caricamento\u2026",
460
+ saving: "Salvataggio\u2026",
461
+ syncing: "Sincronizzazione\u2026",
462
+ error: "Si \xE8 verificato un errore.",
463
+ allTags: "Tutti",
464
+ tags: "Tag",
465
+ filterTags: "Filtra gli elementi salvati per tag",
466
+ note: "Nota",
467
+ saveNote: "Salva nota",
468
+ noItems: "Nessun elemento salvato.",
469
+ loadingItems: "Caricamento degli elementi salvati\u2026",
470
+ errorItems: "Impossibile caricare gli elementi salvati.",
471
+ search: "Cerca elementi salvati",
472
+ sort: "Ordina elementi salvati",
473
+ newest: "Pi\xF9 recenti prima",
474
+ oldest: "Pi\xF9 vecchi prima",
475
+ savedNewest: "Salvati pi\xF9 di recente prima",
476
+ savedOldest: "Salvati meno di recente prima",
477
+ updatedNewest: "Aggiornati pi\xF9 di recente prima",
478
+ updatedOldest: "Aggiornati meno di recente prima",
479
+ previousPage: "Pagina precedente",
480
+ nextPage: "Pagina successiva",
481
+ pagination: "Paginazione",
482
+ page: "Pagina",
483
+ selectItems: "Seleziona elementi salvati",
484
+ selectedCount: "selezionati",
485
+ deleteSelected: "Elimina selezionati",
486
+ tagsToApply: "Tag da applicare",
487
+ applyTags: "Applica tag",
488
+ savedMessage: "Elemento salvato.",
489
+ removedMessage: "Elemento rimosso.",
490
+ undo: "Annulla",
491
+ undoAvailable: "Elemento rimosso. Annullare?",
492
+ selectionScope: "Ambito della selezione",
493
+ currentPage: "Pagina corrente",
494
+ searchResults: "Risultati di ricerca correnti",
495
+ allItems: "Tutti gli elementi salvati",
496
+ statusAvailable: "Disponibile",
497
+ noteSavedMessage: "Nota salvata.",
498
+ exportData: "Esporta JSON",
499
+ importData: "Importa JSON",
500
+ importMode: "Modalit\xE0 di importazione",
501
+ merge: "Unisci",
502
+ replace: "Sostituisci",
503
+ importedCount: "elementi importati",
504
+ failedCount: "elementi non riusciti",
505
+ storageQuotaError: "Lo spazio di archiviazione \xE8 pieno. Libera spazio e riprova.",
506
+ statusExpired: "Scaduto",
507
+ statusRemoved: "Rimosso",
508
+ statusDeleted: "Eliminato",
509
+ statusPrivate: "Privato",
510
+ statusUnknown: "Non disponibile",
511
+ retry: "Riprova",
512
+ removeFromList: "Rimuovi dall'elenco",
513
+ pruneStale: "Rimuovi elementi non disponibili",
514
+ retrySync: "Riprova sincronizzazione",
515
+ resolveSync: "Risolvi conflitti",
516
+ keepLocal: "Mantieni versione locale",
517
+ useServer: "Usa versione del server",
518
+ manualMerge: "Unione manuale",
519
+ close: "Chiudi",
520
+ backupRecovery: "Ripristina dal backup",
521
+ backupRecoveryDescription: "Se i dati locali sono danneggiati, ripristina un backup JSON valido.",
522
+ syncPending: "Ci sono modifiche in attesa di sincronizzazione.",
523
+ syncSynced: "Tutte le modifiche sono sincronizzate.",
524
+ syncConflict: "Alcune modifiche richiedono la risoluzione di un conflitto."
525
+ };
526
+
527
+ // src/locales/ja.ts
528
+ var JA_LABELS = {
529
+ save: "\u4FDD\u5B58",
530
+ saved: "\u4FDD\u5B58\u6E08\u307F",
531
+ remove: "\u524A\u9664",
532
+ loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026",
533
+ saving: "\u4FDD\u5B58\u4E2D\u2026",
534
+ syncing: "\u540C\u671F\u4E2D\u2026",
535
+ error: "\u554F\u984C\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002",
536
+ allTags: "\u3059\u3079\u3066",
537
+ tags: "\u30BF\u30B0",
538
+ filterTags: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u30BF\u30B0\u3067\u7D5E\u308A\u8FBC\u3080",
539
+ note: "\u30E1\u30E2",
540
+ saveNote: "\u30E1\u30E2\u3092\u4FDD\u5B58",
541
+ noItems: "\u4FDD\u5B58\u3055\u308C\u305F\u30A2\u30A4\u30C6\u30E0\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
542
+ loadingItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026",
543
+ errorItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
544
+ search: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u691C\u7D22",
545
+ sort: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u4E26\u3079\u66FF\u3048",
546
+ newest: "\u65B0\u3057\u3044\u9806",
547
+ oldest: "\u53E4\u3044\u9806",
548
+ savedNewest: "\u4FDD\u5B58\u65E5\u6642\u306E\u65B0\u3057\u3044\u9806",
549
+ savedOldest: "\u4FDD\u5B58\u65E5\u6642\u306E\u53E4\u3044\u9806",
550
+ updatedNewest: "\u66F4\u65B0\u65E5\u6642\u306E\u65B0\u3057\u3044\u9806",
551
+ updatedOldest: "\u66F4\u65B0\u65E5\u6642\u306E\u53E4\u3044\u9806",
552
+ previousPage: "\u524D\u306E\u30DA\u30FC\u30B8",
553
+ nextPage: "\u6B21\u306E\u30DA\u30FC\u30B8",
554
+ pagination: "\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3",
555
+ page: "\u30DA\u30FC\u30B8",
556
+ selectItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u9078\u629E",
557
+ selectedCount: "\u4EF6\u3092\u9078\u629E\u4E2D",
558
+ deleteSelected: "\u9078\u629E\u9805\u76EE\u3092\u524A\u9664",
559
+ tagsToApply: "\u9069\u7528\u3059\u308B\u30BF\u30B0",
560
+ applyTags: "\u30BF\u30B0\u3092\u9069\u7528",
561
+ savedMessage: "\u30A2\u30A4\u30C6\u30E0\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002",
562
+ removedMessage: "\u30A2\u30A4\u30C6\u30E0\u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002",
563
+ undo: "\u5143\u306B\u623B\u3059",
564
+ undoAvailable: "\u30A2\u30A4\u30C6\u30E0\u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002\u5143\u306B\u623B\u3057\u307E\u3059\u304B\uFF1F",
565
+ selectionScope: "\u9078\u629E\u7BC4\u56F2",
566
+ currentPage: "\u8868\u793A\u4E2D\u306E\u30DA\u30FC\u30B8",
567
+ searchResults: "\u73FE\u5728\u306E\u691C\u7D22\u7D50\u679C\u5168\u4F53",
568
+ allItems: "\u3059\u3079\u3066\u306E\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0",
569
+ statusAvailable: "\u5229\u7528\u53EF\u80FD",
570
+ noteSavedMessage: "\u30E1\u30E2\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002",
571
+ exportData: "JSON\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8",
572
+ importData: "JSON\u3092\u30A4\u30F3\u30DD\u30FC\u30C8",
573
+ importMode: "\u30A4\u30F3\u30DD\u30FC\u30C8\u65B9\u6CD5",
574
+ merge: "\u7D71\u5408",
575
+ replace: "\u7F6E\u304D\u63DB\u3048",
576
+ importedCount: "\u4EF6\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u307E\u3057\u305F",
577
+ failedCount: "\u4EF6\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
578
+ storageQuotaError: "\u4FDD\u5B58\u5BB9\u91CF\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002\u7A7A\u304D\u5BB9\u91CF\u3092\u78BA\u4FDD\u3057\u3066\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
579
+ statusExpired: "\u671F\u9650\u5207\u308C",
580
+ statusRemoved: "\u524A\u9664\u6E08\u307F",
581
+ statusDeleted: "\u524A\u9664\u6E08\u307F",
582
+ statusPrivate: "\u975E\u516C\u958B",
583
+ statusUnknown: "\u5229\u7528\u4E0D\u53EF",
584
+ retry: "\u518D\u53D6\u5F97",
585
+ removeFromList: "\u4E00\u89A7\u304B\u3089\u524A\u9664",
586
+ pruneStale: "\u5229\u7528\u3067\u304D\u306A\u3044\u9805\u76EE\u3092\u524A\u9664",
587
+ retrySync: "\u540C\u671F\u3092\u518D\u8A66\u884C",
588
+ resolveSync: "\u7AF6\u5408\u3092\u89E3\u6C7A",
589
+ keepLocal: "\u30ED\u30FC\u30AB\u30EB\u3092\u512A\u5148",
590
+ useServer: "\u30B5\u30FC\u30D0\u30FC\u3092\u512A\u5148",
591
+ manualMerge: "\u624B\u52D5\u3067\u7D71\u5408",
592
+ close: "\u9589\u3058\u308B",
593
+ backupRecovery: "\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u304B\u3089\u5FA9\u5143",
594
+ backupRecoveryDescription: "\u30ED\u30FC\u30AB\u30EB\u306E\u540C\u671F\u30C7\u30FC\u30BF\u304C\u7834\u640D\u3057\u305F\u5834\u5408\u306F\u3001\u6B63\u5E38\u306AJSON\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u304B\u3089\u5FA9\u5143\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
595
+ syncPending: "\u540C\u671F\u5F85\u3061\u306E\u5909\u66F4\u304C\u3042\u308A\u307E\u3059\u3002",
596
+ syncSynced: "\u3059\u3079\u3066\u306E\u5909\u66F4\u3092\u540C\u671F\u3057\u307E\u3057\u305F\u3002",
597
+ syncConflict: "\u7AF6\u5408\u3057\u3066\u3044\u308B\u5909\u66F4\u304C\u3042\u308A\u307E\u3059\u3002\u89E3\u6C7A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
72
598
  };
599
+
600
+ // src/locales/ko.ts
601
+ var KO_LABELS = {
602
+ save: "\uC800\uC7A5",
603
+ saved: "\uC800\uC7A5\uB428",
604
+ remove: "\uC0AD\uC81C",
605
+ loading: "\uB85C\uB4DC \uC911\u2026",
606
+ saving: "\uC800\uC7A5 \uC911\u2026",
607
+ syncing: "\uB3D9\uAE30\uD654 \uC911\u2026",
608
+ error: "\uBB38\uC81C\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.",
609
+ allTags: "\uBAA8\uB450",
610
+ tags: "\uD0DC\uADF8",
611
+ filterTags: "\uD0DC\uADF8\uB85C \uC800\uC7A5 \uD56D\uBAA9 \uD544\uD130\uB9C1",
612
+ note: "\uBA54\uBAA8",
613
+ saveNote: "\uBA54\uBAA8 \uC800\uC7A5",
614
+ noItems: "\uC800\uC7A5\uB41C \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
615
+ loadingItems: "\uC800\uC7A5 \uD56D\uBAA9\uC744 \uBD88\uB7EC\uC624\uB294 \uC911\u2026",
616
+ errorItems: "\uC800\uC7A5 \uD56D\uBAA9\uC744 \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
617
+ search: "\uC800\uC7A5 \uD56D\uBAA9 \uAC80\uC0C9",
618
+ sort: "\uC800\uC7A5 \uD56D\uBAA9 \uC815\uB82C",
619
+ newest: "\uCD5C\uC2E0\uC21C",
620
+ oldest: "\uC624\uB798\uB41C\uC21C",
621
+ savedNewest: "\uC800\uC7A5\uC77C \uCD5C\uC2E0\uC21C",
622
+ savedOldest: "\uC800\uC7A5\uC77C \uC624\uB798\uB41C\uC21C",
623
+ updatedNewest: "\uC218\uC815\uC77C \uCD5C\uC2E0\uC21C",
624
+ updatedOldest: "\uC218\uC815\uC77C \uC624\uB798\uB41C\uC21C",
625
+ previousPage: "\uC774\uC804 \uD398\uC774\uC9C0",
626
+ nextPage: "\uB2E4\uC74C \uD398\uC774\uC9C0",
627
+ pagination: "\uD398\uC774\uC9C0 \uB9E4\uAE40",
628
+ page: "\uD398\uC774\uC9C0",
629
+ selectItems: "\uC800\uC7A5 \uD56D\uBAA9 \uC120\uD0DD",
630
+ selectedCount: "\uAC1C \uC120\uD0DD\uB428",
631
+ deleteSelected: "\uC120\uD0DD \uD56D\uBAA9 \uC0AD\uC81C",
632
+ tagsToApply: "\uC801\uC6A9\uD560 \uD0DC\uADF8",
633
+ applyTags: "\uD0DC\uADF8 \uC801\uC6A9",
634
+ savedMessage: "\uD56D\uBAA9\uC744 \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.",
635
+ removedMessage: "\uD56D\uBAA9\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4.",
636
+ undo: "\uC2E4\uD589 \uCDE8\uC18C",
637
+ undoAvailable: "\uD56D\uBAA9\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4. \uC2E4\uD589 \uCDE8\uC18C\uD560\uAE4C\uC694?",
638
+ selectionScope: "\uC120\uD0DD \uBC94\uC704",
639
+ currentPage: "\uD604\uC7AC \uD398\uC774\uC9C0",
640
+ searchResults: "\uD604\uC7AC \uAC80\uC0C9 \uACB0\uACFC \uC804\uCCB4",
641
+ allItems: "\uBAA8\uB4E0 \uC800\uC7A5 \uD56D\uBAA9",
642
+ statusAvailable: "\uC0AC\uC6A9 \uAC00\uB2A5",
643
+ noteSavedMessage: "\uBA54\uBAA8\uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.",
644
+ exportData: "JSON \uB0B4\uBCF4\uB0B4\uAE30",
645
+ importData: "JSON \uAC00\uC838\uC624\uAE30",
646
+ importMode: "\uAC00\uC838\uC624\uAE30 \uBC29\uC2DD",
647
+ merge: "\uBCD1\uD569",
648
+ replace: "\uAD50\uCCB4",
649
+ importedCount: "\uAC1C \uAC00\uC838\uC634",
650
+ failedCount: "\uAC1C \uC2E4\uD328",
651
+ storageQuotaError: "\uC800\uC7A5 \uACF5\uAC04\uC774 \uBD80\uC871\uD569\uB2C8\uB2E4. \uACF5\uAC04\uC744 \uD655\uBCF4\uD55C \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.",
652
+ statusExpired: "\uB9CC\uB8CC\uB428",
653
+ statusRemoved: "\uC81C\uAC70\uB428",
654
+ statusDeleted: "\uC0AD\uC81C\uB428",
655
+ statusPrivate: "\uBE44\uACF5\uAC1C",
656
+ statusUnknown: "\uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC74C",
657
+ retry: "\uB2E4\uC2DC \uC2DC\uB3C4",
658
+ removeFromList: "\uBAA9\uB85D\uC5D0\uC11C \uC0AD\uC81C",
659
+ pruneStale: "\uC0AC\uC6A9\uD560 \uC218 \uC5C6\uB294 \uD56D\uBAA9 \uC0AD\uC81C",
660
+ retrySync: "\uB3D9\uAE30\uD654 \uB2E4\uC2DC \uC2DC\uB3C4",
661
+ resolveSync: "\uCDA9\uB3CC \uD574\uACB0",
662
+ keepLocal: "\uB85C\uCEEC \uBC84\uC804 \uC720\uC9C0",
663
+ useServer: "\uC11C\uBC84 \uBC84\uC804 \uC0AC\uC6A9",
664
+ manualMerge: "\uC218\uB3D9 \uBCD1\uD569",
665
+ close: "\uB2EB\uAE30",
666
+ backupRecovery: "\uBC31\uC5C5\uC5D0\uC11C \uBCF5\uC6D0",
667
+ backupRecoveryDescription: "\uB85C\uCEEC \uB3D9\uAE30\uD654 \uB370\uC774\uD130\uAC00 \uC190\uC0C1\uB41C \uACBD\uC6B0 \uC815\uC0C1\uC801\uC778 JSON \uBC31\uC5C5\uC744 \uBCF5\uC6D0\uD558\uC138\uC694.",
668
+ syncPending: "\uB3D9\uAE30\uD654 \uB300\uAE30 \uC911\uC778 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC788\uC2B5\uB2C8\uB2E4.",
669
+ syncSynced: "\uBAA8\uB4E0 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uB3D9\uAE30\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",
670
+ syncConflict: "\uCDA9\uB3CC\uC744 \uD574\uACB0\uD574\uC57C \uD558\uB294 \uBCC0\uACBD \uC0AC\uD56D\uC774 \uC788\uC2B5\uB2C8\uB2E4."
671
+ };
672
+
673
+ // src/locales/ms.ts
674
+ var MS_LABELS = {
675
+ save: "Simpan",
676
+ saved: "Disimpan",
677
+ remove: "Buang",
678
+ loading: "Memuatkan\u2026",
679
+ saving: "Menyimpan\u2026",
680
+ syncing: "Menyegerakkan\u2026",
681
+ error: "Ralat telah berlaku.",
682
+ allTags: "Semua",
683
+ tags: "Tag",
684
+ filterTags: "Tapis item yang disimpan mengikut tag",
685
+ note: "Nota",
686
+ saveNote: "Simpan nota",
687
+ noItems: "Tiada item disimpan.",
688
+ loadingItems: "Memuatkan item yang disimpan\u2026",
689
+ errorItems: "Tidak dapat memuatkan item yang disimpan.",
690
+ search: "Cari item yang disimpan",
691
+ sort: "Isih item yang disimpan",
692
+ newest: "Terbaharu dahulu",
693
+ oldest: "Terlama dahulu",
694
+ savedNewest: "Disimpan paling baharu dahulu",
695
+ savedOldest: "Disimpan paling lama dahulu",
696
+ updatedNewest: "Dikemas kini paling baharu dahulu",
697
+ updatedOldest: "Dikemas kini paling lama dahulu",
698
+ previousPage: "Halaman sebelumnya",
699
+ nextPage: "Halaman seterusnya",
700
+ pagination: "Penomboran halaman",
701
+ page: "Halaman",
702
+ selectItems: "Pilih item yang disimpan",
703
+ selectedCount: "dipilih",
704
+ deleteSelected: "Padam pilihan",
705
+ tagsToApply: "Tag untuk digunakan",
706
+ applyTags: "Gunakan tag",
707
+ savedMessage: "Item disimpan.",
708
+ removedMessage: "Item dibuang.",
709
+ undo: "Buat asal",
710
+ undoAvailable: "Item dibuang. Buat asal?",
711
+ selectionScope: "Skop pilihan",
712
+ currentPage: "Halaman semasa",
713
+ searchResults: "Hasil carian semasa",
714
+ allItems: "Semua item yang disimpan",
715
+ statusAvailable: "Tersedia",
716
+ noteSavedMessage: "Nota disimpan.",
717
+ exportData: "Eksport JSON",
718
+ importData: "Import JSON",
719
+ importMode: "Mod import",
720
+ merge: "Gabung",
721
+ replace: "Ganti",
722
+ importedCount: "item diimport",
723
+ failedCount: "item gagal",
724
+ storageQuotaError: "Storan penuh. Kosongkan ruang dan cuba lagi.",
725
+ statusExpired: "Tamat tempoh",
726
+ statusRemoved: "Dibuang",
727
+ statusDeleted: "Dipadam",
728
+ statusPrivate: "Peribadi",
729
+ statusUnknown: "Tidak tersedia",
730
+ retry: "Cuba lagi",
731
+ removeFromList: "Buang daripada senarai",
732
+ pruneStale: "Buang item yang tidak tersedia",
733
+ retrySync: "Cuba penyegerakan lagi",
734
+ resolveSync: "Selesaikan konflik",
735
+ keepLocal: "Kekalkan versi setempat",
736
+ useServer: "Gunakan versi pelayan",
737
+ manualMerge: "Gabung secara manual",
738
+ close: "Tutup",
739
+ backupRecovery: "Pulihkan daripada sandaran",
740
+ backupRecoveryDescription: "Jika data penyegerakan setempat rosak, pulihkan sandaran JSON yang sah.",
741
+ syncPending: "Terdapat perubahan yang menunggu penyegerakan.",
742
+ syncSynced: "Semua perubahan telah disegerakkan.",
743
+ syncConflict: "Sesetengah perubahan memerlukan penyelesaian konflik."
744
+ };
745
+
746
+ // src/locales/pt-BR.ts
747
+ var PT_BR_LABELS = {
748
+ save: "Salvar",
749
+ saved: "Salvo",
750
+ remove: "Remover",
751
+ loading: "Carregando\u2026",
752
+ saving: "Salvando\u2026",
753
+ syncing: "Sincronizando\u2026",
754
+ error: "Ocorreu um erro.",
755
+ allTags: "Todos",
756
+ tags: "Tags",
757
+ filterTags: "Filtrar itens salvos por tag",
758
+ note: "Nota",
759
+ saveNote: "Salvar nota",
760
+ noItems: "Nenhum item salvo.",
761
+ loadingItems: "Carregando itens salvos\u2026",
762
+ errorItems: "N\xE3o foi poss\xEDvel carregar os itens salvos.",
763
+ search: "Pesquisar itens salvos",
764
+ sort: "Ordenar itens salvos",
765
+ newest: "Mais recentes primeiro",
766
+ oldest: "Mais antigos primeiro",
767
+ savedNewest: "Salvos mais recentemente primeiro",
768
+ savedOldest: "Salvos h\xE1 mais tempo primeiro",
769
+ updatedNewest: "Atualizados mais recentemente primeiro",
770
+ updatedOldest: "Atualizados h\xE1 mais tempo primeiro",
771
+ previousPage: "P\xE1gina anterior",
772
+ nextPage: "Pr\xF3xima p\xE1gina",
773
+ pagination: "Pagina\xE7\xE3o",
774
+ page: "P\xE1gina",
775
+ selectItems: "Selecionar itens salvos",
776
+ selectedCount: "selecionados",
777
+ deleteSelected: "Excluir selecionados",
778
+ tagsToApply: "Tags a aplicar",
779
+ applyTags: "Aplicar tags",
780
+ savedMessage: "Item salvo.",
781
+ removedMessage: "Item removido.",
782
+ undo: "Desfazer",
783
+ undoAvailable: "Item removido. Desfazer?",
784
+ selectionScope: "Escopo da sele\xE7\xE3o",
785
+ currentPage: "P\xE1gina atual",
786
+ searchResults: "Resultados da pesquisa atual",
787
+ allItems: "Todos os itens salvos",
788
+ statusAvailable: "Dispon\xEDvel",
789
+ noteSavedMessage: "Nota salva.",
790
+ exportData: "Exportar JSON",
791
+ importData: "Importar JSON",
792
+ importMode: "Modo de importa\xE7\xE3o",
793
+ merge: "Mesclar",
794
+ replace: "Substituir",
795
+ importedCount: "itens importados",
796
+ failedCount: "itens com falha",
797
+ storageQuotaError: "O armazenamento est\xE1 cheio. Libere espa\xE7o e tente novamente.",
798
+ statusExpired: "Expirado",
799
+ statusRemoved: "Removido",
800
+ statusDeleted: "Exclu\xEDdo",
801
+ statusPrivate: "Privado",
802
+ statusUnknown: "Indispon\xEDvel",
803
+ retry: "Tentar novamente",
804
+ removeFromList: "Remover da lista",
805
+ pruneStale: "Remover itens indispon\xEDveis",
806
+ retrySync: "Tentar sincronizar novamente",
807
+ resolveSync: "Resolver conflitos",
808
+ keepLocal: "Manter vers\xE3o local",
809
+ useServer: "Usar vers\xE3o do servidor",
810
+ manualMerge: "Mesclagem manual",
811
+ close: "Fechar",
812
+ backupRecovery: "Restaurar do backup",
813
+ backupRecoveryDescription: "Se os dados locais estiverem corrompidos, restaure um backup JSON v\xE1lido.",
814
+ syncPending: "H\xE1 altera\xE7\xF5es aguardando sincroniza\xE7\xE3o.",
815
+ syncSynced: "Todas as altera\xE7\xF5es foram sincronizadas.",
816
+ syncConflict: "Algumas altera\xE7\xF5es precisam de resolu\xE7\xE3o de conflito."
817
+ };
818
+
819
+ // src/locales/ru.ts
820
+ var RU_LABELS = {
821
+ save: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C",
822
+ saved: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E",
823
+ remove: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
824
+ loading: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\u2026",
825
+ saving: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435\u2026",
826
+ syncing: "\u0421\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u044F\u2026",
827
+ error: "\u041F\u0440\u043E\u0438\u0437\u043E\u0448\u043B\u0430 \u043E\u0448\u0438\u0431\u043A\u0430.",
828
+ allTags: "\u0412\u0441\u0435",
829
+ tags: "\u0422\u0435\u0433\u0438",
830
+ filterTags: "\u0424\u0438\u043B\u044C\u0442\u0440\u043E\u0432\u0430\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B \u043F\u043E \u0442\u0435\u0433\u0443",
831
+ note: "\u0417\u0430\u043C\u0435\u0442\u043A\u0430",
832
+ saveNote: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0437\u0430\u043C\u0435\u0442\u043A\u0443",
833
+ noItems: "\u041D\u0435\u0442 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0445 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432.",
834
+ loadingItems: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0445 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432\u2026",
835
+ errorItems: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B.",
836
+ search: "\u041F\u043E\u0438\u0441\u043A \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0445 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432",
837
+ sort: "\u0421\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0445 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432",
838
+ newest: "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u043D\u043E\u0432\u044B\u0435",
839
+ oldest: "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0441\u0442\u0430\u0440\u044B\u0435",
840
+ savedNewest: "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u043D\u0435\u0434\u0430\u0432\u043D\u043E \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435",
841
+ savedOldest: "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0434\u0430\u0432\u043D\u043E \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435",
842
+ updatedNewest: "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u043D\u0435\u0434\u0430\u0432\u043D\u043E \u043E\u0431\u043D\u043E\u0432\u043B\u0451\u043D\u043D\u044B\u0435",
843
+ updatedOldest: "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0434\u0430\u0432\u043D\u043E \u043E\u0431\u043D\u043E\u0432\u043B\u0451\u043D\u043D\u044B\u0435",
844
+ previousPage: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
845
+ nextPage: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
846
+ pagination: "\u041F\u0430\u0433\u0438\u043D\u0430\u0446\u0438\u044F",
847
+ page: "\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
848
+ selectItems: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B",
849
+ selectedCount: "\u0432\u044B\u0431\u0440\u0430\u043D\u043E",
850
+ deleteSelected: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0435",
851
+ tagsToApply: "\u0422\u0435\u0433\u0438 \u0434\u043B\u044F \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u0438\u044F",
852
+ applyTags: "\u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0435\u0433\u0438",
853
+ savedMessage: "\u042D\u043B\u0435\u043C\u0435\u043D\u0442 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D.",
854
+ removedMessage: "\u042D\u043B\u0435\u043C\u0435\u043D\u0442 \u0443\u0434\u0430\u043B\u0451\u043D.",
855
+ undo: "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C",
856
+ undoAvailable: "\u042D\u043B\u0435\u043C\u0435\u043D\u0442 \u0443\u0434\u0430\u043B\u0451\u043D. \u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C?",
857
+ selectionScope: "\u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0432\u044B\u0431\u043E\u0440\u0430",
858
+ currentPage: "\u0422\u0435\u043A\u0443\u0449\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
859
+ searchResults: "\u0422\u0435\u043A\u0443\u0449\u0438\u0435 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E\u0438\u0441\u043A\u0430",
860
+ allItems: "\u0412\u0441\u0435 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B",
861
+ statusAvailable: "\u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D",
862
+ noteSavedMessage: "\u0417\u0430\u043C\u0435\u0442\u043A\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430.",
863
+ exportData: "\u042D\u043A\u0441\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C JSON",
864
+ importData: "\u0418\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C JSON",
865
+ importMode: "\u0420\u0435\u0436\u0438\u043C \u0438\u043C\u043F\u043E\u0440\u0442\u0430",
866
+ merge: "\u041E\u0431\u044A\u0435\u0434\u0438\u043D\u0438\u0442\u044C",
867
+ replace: "\u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C",
868
+ importedCount: "\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432 \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043E",
869
+ failedCount: "\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432 \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
870
+ storageQuotaError: "\u0425\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u0437\u0430\u043F\u043E\u043B\u043D\u0435\u043D\u043E. \u041E\u0441\u0432\u043E\u0431\u043E\u0434\u0438\u0442\u0435 \u043C\u0435\u0441\u0442\u043E \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u043F\u044B\u0442\u043A\u0443.",
871
+ statusExpired: "\u0418\u0441\u0442\u0451\u043A \u0441\u0440\u043E\u043A",
872
+ statusRemoved: "\u0423\u0434\u0430\u043B\u0451\u043D",
873
+ statusDeleted: "\u0423\u0434\u0430\u043B\u0451\u043D \u043D\u0430\u0432\u0441\u0435\u0433\u0434\u0430",
874
+ statusPrivate: "\u041F\u0440\u0438\u0432\u0430\u0442\u043D\u044B\u0439",
875
+ statusUnknown: "\u041D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D",
876
+ retry: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C",
877
+ removeFromList: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437 \u0441\u043F\u0438\u0441\u043A\u0430",
878
+ pruneStale: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B",
879
+ retrySync: "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u044E",
880
+ resolveSync: "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044C \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u044B",
881
+ keepLocal: "\u041E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u0443\u044E \u0432\u0435\u0440\u0441\u0438\u044E",
882
+ useServer: "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0432\u0435\u0440\u0441\u0438\u044E \u0441\u0435\u0440\u0432\u0435\u0440\u0430",
883
+ manualMerge: "\u041E\u0431\u044A\u0435\u0434\u0438\u043D\u0438\u0442\u044C \u0432\u0440\u0443\u0447\u043D\u0443\u044E",
884
+ close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C",
885
+ backupRecovery: "\u0412\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0438\u0437 \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u043E\u0439 \u043A\u043E\u043F\u0438\u0438",
886
+ backupRecoveryDescription: "\u0415\u0441\u043B\u0438 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0438 \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u044B, \u0432\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0440\u0430\u0431\u043E\u0447\u0443\u044E JSON-\u043A\u043E\u043F\u0438\u044E.",
887
+ syncPending: "\u0415\u0441\u0442\u044C \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F, \u043E\u0436\u0438\u0434\u0430\u044E\u0449\u0438\u0435 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0438.",
888
+ syncSynced: "\u0412\u0441\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u044B.",
889
+ syncConflict: "\u041D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0442\u0440\u0435\u0431\u0443\u044E\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u0430."
890
+ };
891
+
892
+ // src/locales/th.ts
893
+ var TH_LABELS = {
894
+ save: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
895
+ saved: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E41\u0E25\u0E49\u0E27",
896
+ remove: "\u0E25\u0E1A",
897
+ loading: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14\u2026",
898
+ saving: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u2026",
899
+ syncing: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E0B\u0E34\u0E07\u0E04\u0E4C\u2026",
900
+ error: "\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14",
901
+ allTags: "\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14",
902
+ tags: "\u0E41\u0E17\u0E47\u0E01",
903
+ filterTags: "\u0E01\u0E23\u0E2D\u0E07\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E14\u0E49\u0E27\u0E22\u0E41\u0E17\u0E47\u0E01",
904
+ note: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E22\u0E48\u0E2D",
905
+ saveNote: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E22\u0E48\u0E2D",
906
+ noItems: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E44\u0E27\u0E49",
907
+ loadingItems: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u2026",
908
+ errorItems: "\u0E42\u0E2B\u0E25\u0E14\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49",
909
+ search: "\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
910
+ sort: "\u0E40\u0E23\u0E35\u0E22\u0E07\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
911
+ newest: "\u0E43\u0E2B\u0E21\u0E48\u0E2A\u0E38\u0E14\u0E01\u0E48\u0E2D\u0E19",
912
+ oldest: "\u0E40\u0E01\u0E48\u0E32\u0E2A\u0E38\u0E14\u0E01\u0E48\u0E2D\u0E19",
913
+ savedNewest: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E43\u0E2B\u0E21\u0E48\u0E2A\u0E38\u0E14\u0E01\u0E48\u0E2D\u0E19",
914
+ savedOldest: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E40\u0E01\u0E48\u0E32\u0E2A\u0E38\u0E14\u0E01\u0E48\u0E2D\u0E19",
915
+ updatedNewest: "\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15\u0E43\u0E2B\u0E21\u0E48\u0E2A\u0E38\u0E14\u0E01\u0E48\u0E2D\u0E19",
916
+ updatedOldest: "\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15\u0E40\u0E01\u0E48\u0E32\u0E2A\u0E38\u0E14\u0E01\u0E48\u0E2D\u0E19",
917
+ previousPage: "\u0E2B\u0E19\u0E49\u0E32\u0E01\u0E48\u0E2D\u0E19\u0E2B\u0E19\u0E49\u0E32",
918
+ nextPage: "\u0E2B\u0E19\u0E49\u0E32\u0E16\u0E31\u0E14\u0E44\u0E1B",
919
+ pagination: "\u0E01\u0E32\u0E23\u0E41\u0E1A\u0E48\u0E07\u0E2B\u0E19\u0E49\u0E32",
920
+ page: "\u0E2B\u0E19\u0E49\u0E32",
921
+ selectItems: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01",
922
+ selectedCount: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E40\u0E25\u0E37\u0E2D\u0E01",
923
+ deleteSelected: "\u0E25\u0E1A\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E40\u0E25\u0E37\u0E2D\u0E01",
924
+ tagsToApply: "\u0E41\u0E17\u0E47\u0E01\u0E17\u0E35\u0E48\u0E08\u0E30\u0E43\u0E0A\u0E49",
925
+ applyTags: "\u0E43\u0E0A\u0E49\u0E41\u0E17\u0E47\u0E01",
926
+ savedMessage: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E41\u0E25\u0E49\u0E27",
927
+ removedMessage: "\u0E25\u0E1A\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E41\u0E25\u0E49\u0E27",
928
+ undo: "\u0E40\u0E25\u0E34\u0E01\u0E17\u0E33",
929
+ undoAvailable: "\u0E25\u0E1A\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E41\u0E25\u0E49\u0E27 \u0E15\u0E49\u0E2D\u0E07\u0E01\u0E32\u0E23\u0E40\u0E25\u0E34\u0E01\u0E17\u0E33\u0E2B\u0E23\u0E37\u0E2D\u0E44\u0E21\u0E48",
930
+ selectionScope: "\u0E02\u0E2D\u0E1A\u0E40\u0E02\u0E15\u0E01\u0E32\u0E23\u0E40\u0E25\u0E37\u0E2D\u0E01",
931
+ currentPage: "\u0E2B\u0E19\u0E49\u0E32\u0E1B\u0E31\u0E08\u0E08\u0E38\u0E1A\u0E31\u0E19",
932
+ searchResults: "\u0E1C\u0E25\u0E01\u0E32\u0E23\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E1B\u0E31\u0E08\u0E08\u0E38\u0E1A\u0E31\u0E19",
933
+ allItems: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14",
934
+ statusAvailable: "\u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19",
935
+ noteSavedMessage: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E22\u0E48\u0E2D\u0E41\u0E25\u0E49\u0E27",
936
+ exportData: "\u0E2A\u0E48\u0E07\u0E2D\u0E2D\u0E01 JSON",
937
+ importData: "\u0E19\u0E33\u0E40\u0E02\u0E49\u0E32 JSON",
938
+ importMode: "\u0E42\u0E2B\u0E21\u0E14\u0E19\u0E33\u0E40\u0E02\u0E49\u0E32",
939
+ merge: "\u0E23\u0E27\u0E21",
940
+ replace: "\u0E41\u0E17\u0E19\u0E17\u0E35\u0E48",
941
+ importedCount: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E19\u0E33\u0E40\u0E02\u0E49\u0E32\u0E41\u0E25\u0E49\u0E27",
942
+ failedCount: "\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27",
943
+ storageQuotaError: "\u0E1E\u0E37\u0E49\u0E19\u0E17\u0E35\u0E48\u0E08\u0E31\u0E14\u0E40\u0E01\u0E47\u0E1A\u0E40\u0E15\u0E47\u0E21 \u0E42\u0E1B\u0E23\u0E14\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E1E\u0E37\u0E49\u0E19\u0E17\u0E35\u0E48\u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07",
944
+ statusExpired: "\u0E2B\u0E21\u0E14\u0E2D\u0E32\u0E22\u0E38",
945
+ statusRemoved: "\u0E19\u0E33\u0E2D\u0E2D\u0E01\u0E41\u0E25\u0E49\u0E27",
946
+ statusDeleted: "\u0E25\u0E1A\u0E41\u0E25\u0E49\u0E27",
947
+ statusPrivate: "\u0E40\u0E1B\u0E47\u0E19\u0E2A\u0E48\u0E27\u0E19\u0E15\u0E31\u0E27",
948
+ statusUnknown: "\u0E44\u0E21\u0E48\u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19",
949
+ retry: "\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48",
950
+ removeFromList: "\u0E25\u0E1A\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23",
951
+ pruneStale: "\u0E25\u0E1A\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49",
952
+ retrySync: "\u0E25\u0E2D\u0E07\u0E0B\u0E34\u0E07\u0E04\u0E4C\u0E43\u0E2B\u0E21\u0E48",
953
+ resolveSync: "\u0E41\u0E01\u0E49\u0E44\u0E02\u0E02\u0E49\u0E2D\u0E02\u0E31\u0E14\u0E41\u0E22\u0E49\u0E07",
954
+ keepLocal: "\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E43\u0E19\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07",
955
+ useServer: "\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E40\u0E0B\u0E34\u0E23\u0E4C\u0E1F\u0E40\u0E27\u0E2D\u0E23\u0E4C",
956
+ manualMerge: "\u0E23\u0E27\u0E21\u0E14\u0E49\u0E27\u0E22\u0E15\u0E19\u0E40\u0E2D\u0E07",
957
+ close: "\u0E1B\u0E34\u0E14",
958
+ backupRecovery: "\u0E01\u0E39\u0E49\u0E04\u0E37\u0E19\u0E08\u0E32\u0E01\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E33\u0E23\u0E2D\u0E07",
959
+ backupRecoveryDescription: "\u0E2B\u0E32\u0E01\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E0B\u0E34\u0E07\u0E04\u0E4C\u0E43\u0E19\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E40\u0E2A\u0E35\u0E22\u0E2B\u0E32\u0E22 \u0E43\u0E2B\u0E49\u0E01\u0E39\u0E49\u0E04\u0E37\u0E19\u0E08\u0E32\u0E01\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E33\u0E23\u0E2D\u0E07 JSON \u0E17\u0E35\u0E48\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E44\u0E14\u0E49",
960
+ syncPending: "\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E35\u0E48\u0E23\u0E2D\u0E01\u0E32\u0E23\u0E0B\u0E34\u0E07\u0E04\u0E4C",
961
+ syncSynced: "\u0E0B\u0E34\u0E07\u0E04\u0E4C\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14\u0E41\u0E25\u0E49\u0E27",
962
+ syncConflict: "\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E17\u0E35\u0E48\u0E15\u0E49\u0E2D\u0E07\u0E41\u0E01\u0E49\u0E44\u0E02\u0E02\u0E49\u0E2D\u0E02\u0E31\u0E14\u0E41\u0E22\u0E49\u0E07"
963
+ };
964
+
965
+ // src/locales/vi.ts
966
+ var VI_LABELS = {
967
+ save: "L\u01B0u",
968
+ saved: "\u0110\xE3 l\u01B0u",
969
+ remove: "X\xF3a",
970
+ loading: "\u0110ang t\u1EA3i\u2026",
971
+ saving: "\u0110ang l\u01B0u\u2026",
972
+ syncing: "\u0110ang \u0111\u1ED3ng b\u1ED9\u2026",
973
+ error: "\u0110\xE3 x\u1EA3y ra l\u1ED7i.",
974
+ allTags: "T\u1EA5t c\u1EA3",
975
+ tags: "Th\u1EBB",
976
+ filterTags: "L\u1ECDc m\u1EE5c \u0111\xE3 l\u01B0u theo th\u1EBB",
977
+ note: "Ghi ch\xFA",
978
+ saveNote: "L\u01B0u ghi ch\xFA",
979
+ noItems: "Ch\u01B0a c\xF3 m\u1EE5c n\xE0o \u0111\u01B0\u1EE3c l\u01B0u.",
980
+ loadingItems: "\u0110ang t\u1EA3i c\xE1c m\u1EE5c \u0111\xE3 l\u01B0u\u2026",
981
+ errorItems: "Kh\xF4ng th\u1EC3 t\u1EA3i c\xE1c m\u1EE5c \u0111\xE3 l\u01B0u.",
982
+ search: "T\xECm ki\u1EBFm m\u1EE5c \u0111\xE3 l\u01B0u",
983
+ sort: "S\u1EAFp x\u1EBFp m\u1EE5c \u0111\xE3 l\u01B0u",
984
+ newest: "M\u1EDBi nh\u1EA5t tr\u01B0\u1EDBc",
985
+ oldest: "C\u0169 nh\u1EA5t tr\u01B0\u1EDBc",
986
+ savedNewest: "L\u01B0u g\u1EA7n \u0111\xE2y nh\u1EA5t tr\u01B0\u1EDBc",
987
+ savedOldest: "L\u01B0u l\xE2u nh\u1EA5t tr\u01B0\u1EDBc",
988
+ updatedNewest: "C\u1EADp nh\u1EADt g\u1EA7n \u0111\xE2y nh\u1EA5t tr\u01B0\u1EDBc",
989
+ updatedOldest: "C\u1EADp nh\u1EADt l\xE2u nh\u1EA5t tr\u01B0\u1EDBc",
990
+ previousPage: "Trang tr\u01B0\u1EDBc",
991
+ nextPage: "Trang sau",
992
+ pagination: "Ph\xE2n trang",
993
+ page: "Trang",
994
+ selectItems: "Ch\u1ECDn m\u1EE5c \u0111\xE3 l\u01B0u",
995
+ selectedCount: "\u0111\xE3 ch\u1ECDn",
996
+ deleteSelected: "X\xF3a m\u1EE5c \u0111\xE3 ch\u1ECDn",
997
+ tagsToApply: "Th\u1EBB c\u1EA7n \xE1p d\u1EE5ng",
998
+ applyTags: "\xC1p d\u1EE5ng th\u1EBB",
999
+ savedMessage: "\u0110\xE3 l\u01B0u m\u1EE5c.",
1000
+ removedMessage: "\u0110\xE3 x\xF3a m\u1EE5c.",
1001
+ undo: "Ho\xE0n t\xE1c",
1002
+ undoAvailable: "\u0110\xE3 x\xF3a m\u1EE5c. Ho\xE0n t\xE1c?",
1003
+ selectionScope: "Ph\u1EA1m vi l\u1EF1a ch\u1ECDn",
1004
+ currentPage: "Trang hi\u1EC7n t\u1EA1i",
1005
+ searchResults: "K\u1EBFt qu\u1EA3 t\xECm ki\u1EBFm hi\u1EC7n t\u1EA1i",
1006
+ allItems: "T\u1EA5t c\u1EA3 m\u1EE5c \u0111\xE3 l\u01B0u",
1007
+ statusAvailable: "Kh\u1EA3 d\u1EE5ng",
1008
+ noteSavedMessage: "\u0110\xE3 l\u01B0u ghi ch\xFA.",
1009
+ exportData: "Xu\u1EA5t JSON",
1010
+ importData: "Nh\u1EADp JSON",
1011
+ importMode: "Ch\u1EBF \u0111\u1ED9 nh\u1EADp",
1012
+ merge: "H\u1EE3p nh\u1EA5t",
1013
+ replace: "Thay th\u1EBF",
1014
+ importedCount: "m\u1EE5c \u0111\xE3 nh\u1EADp",
1015
+ failedCount: "m\u1EE5c b\u1ECB l\u1ED7i",
1016
+ storageQuotaError: "B\u1ED9 nh\u1EDB \u0111\xE3 \u0111\u1EA7y. H\xE3y gi\u1EA3i ph\xF3ng dung l\u01B0\u1EE3ng r\u1ED3i th\u1EED l\u1EA1i.",
1017
+ statusExpired: "\u0110\xE3 h\u1EBFt h\u1EA1n",
1018
+ statusRemoved: "\u0110\xE3 g\u1EE1",
1019
+ statusDeleted: "\u0110\xE3 x\xF3a",
1020
+ statusPrivate: "Ri\xEAng t\u01B0",
1021
+ statusUnknown: "Kh\xF4ng kh\u1EA3 d\u1EE5ng",
1022
+ retry: "Th\u1EED l\u1EA1i",
1023
+ removeFromList: "X\xF3a kh\u1ECFi danh s\xE1ch",
1024
+ pruneStale: "X\xF3a c\xE1c m\u1EE5c kh\xF4ng kh\u1EA3 d\u1EE5ng",
1025
+ retrySync: "Th\u1EED \u0111\u1ED3ng b\u1ED9 l\u1EA1i",
1026
+ resolveSync: "Gi\u1EA3i quy\u1EBFt xung \u0111\u1ED9t",
1027
+ keepLocal: "Gi\u1EEF b\u1EA3n c\u1EE5c b\u1ED9",
1028
+ useServer: "D\xF9ng b\u1EA3n m\xE1y ch\u1EE7",
1029
+ manualMerge: "G\u1ED9p th\u1EE7 c\xF4ng",
1030
+ close: "\u0110\xF3ng",
1031
+ backupRecovery: "Kh\xF4i ph\u1EE5c t\u1EEB b\u1EA3n sao l\u01B0u",
1032
+ backupRecoveryDescription: "N\u1EBFu d\u1EEF li\u1EC7u \u0111\u1ED3ng b\u1ED9 c\u1EE5c b\u1ED9 b\u1ECB h\u1ECFng, h\xE3y kh\xF4i ph\u1EE5c b\u1EA3n sao l\u01B0u JSON h\u1EE3p l\u1EC7.",
1033
+ syncPending: "C\xF3 thay \u0111\u1ED5i \u0111ang ch\u1EDD \u0111\u1ED3ng b\u1ED9.",
1034
+ syncSynced: "T\u1EA5t c\u1EA3 thay \u0111\u1ED5i \u0111\xE3 \u0111\u01B0\u1EE3c \u0111\u1ED3ng b\u1ED9.",
1035
+ syncConflict: "M\u1ED9t s\u1ED1 thay \u0111\u1ED5i c\u1EA7n gi\u1EA3i quy\u1EBFt xung \u0111\u1ED9t."
1036
+ };
1037
+
1038
+ // src/locales/zh-Hans.ts
1039
+ var ZH_HANS_LABELS = {
1040
+ save: "\u4FDD\u5B58",
1041
+ saved: "\u5DF2\u4FDD\u5B58",
1042
+ remove: "\u5220\u9664",
1043
+ loading: "\u52A0\u8F7D\u4E2D\u2026",
1044
+ saving: "\u4FDD\u5B58\u4E2D\u2026",
1045
+ syncing: "\u540C\u6B65\u4E2D\u2026",
1046
+ error: "\u53D1\u751F\u9519\u8BEF\u3002",
1047
+ allTags: "\u5168\u90E8",
1048
+ tags: "\u6807\u7B7E",
1049
+ filterTags: "\u6309\u6807\u7B7E\u7B5B\u9009\u5DF2\u4FDD\u5B58\u9879\u76EE",
1050
+ note: "\u5907\u6CE8",
1051
+ saveNote: "\u4FDD\u5B58\u5907\u6CE8",
1052
+ noItems: "\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u9879\u76EE\u3002",
1053
+ loadingItems: "\u6B63\u5728\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u9879\u76EE\u2026",
1054
+ errorItems: "\u65E0\u6CD5\u52A0\u8F7D\u5DF2\u4FDD\u5B58\u9879\u76EE\u3002",
1055
+ search: "\u641C\u7D22\u5DF2\u4FDD\u5B58\u9879\u76EE",
1056
+ sort: "\u6392\u5E8F\u5DF2\u4FDD\u5B58\u9879\u76EE",
1057
+ newest: "\u6700\u65B0\u4F18\u5148",
1058
+ oldest: "\u6700\u65E9\u4F18\u5148",
1059
+ savedNewest: "\u4FDD\u5B58\u65F6\u95F4\u6700\u65B0\u4F18\u5148",
1060
+ savedOldest: "\u4FDD\u5B58\u65F6\u95F4\u6700\u65E9\u4F18\u5148",
1061
+ updatedNewest: "\u66F4\u65B0\u65F6\u95F4\u6700\u65B0\u4F18\u5148",
1062
+ updatedOldest: "\u66F4\u65B0\u65F6\u95F4\u6700\u65E9\u4F18\u5148",
1063
+ previousPage: "\u4E0A\u4E00\u9875",
1064
+ nextPage: "\u4E0B\u4E00\u9875",
1065
+ pagination: "\u5206\u9875",
1066
+ page: "\u9875",
1067
+ selectItems: "\u9009\u62E9\u5DF2\u4FDD\u5B58\u9879\u76EE",
1068
+ selectedCount: "\u9879\u5DF2\u9009\u62E9",
1069
+ deleteSelected: "\u5220\u9664\u6240\u9009\u9879\u76EE",
1070
+ tagsToApply: "\u8981\u5E94\u7528\u7684\u6807\u7B7E",
1071
+ applyTags: "\u5E94\u7528\u6807\u7B7E",
1072
+ savedMessage: "\u9879\u76EE\u5DF2\u4FDD\u5B58\u3002",
1073
+ removedMessage: "\u9879\u76EE\u5DF2\u5220\u9664\u3002",
1074
+ undo: "\u64A4\u9500",
1075
+ undoAvailable: "\u9879\u76EE\u5DF2\u5220\u9664\u3002\u8981\u64A4\u9500\u5417\uFF1F",
1076
+ selectionScope: "\u9009\u62E9\u8303\u56F4",
1077
+ currentPage: "\u5F53\u524D\u9875",
1078
+ searchResults: "\u5F53\u524D\u5168\u90E8\u641C\u7D22\u7ED3\u679C",
1079
+ allItems: "\u5168\u90E8\u5DF2\u4FDD\u5B58\u9879\u76EE",
1080
+ statusAvailable: "\u53EF\u7528",
1081
+ noteSavedMessage: "\u5907\u6CE8\u5DF2\u4FDD\u5B58\u3002",
1082
+ exportData: "\u5BFC\u51FAJSON",
1083
+ importData: "\u5BFC\u5165JSON",
1084
+ importMode: "\u5BFC\u5165\u65B9\u5F0F",
1085
+ merge: "\u5408\u5E76",
1086
+ replace: "\u66FF\u6362",
1087
+ importedCount: "\u9879\u5DF2\u5BFC\u5165",
1088
+ failedCount: "\u9879\u5931\u8D25",
1089
+ storageQuotaError: "\u5B58\u50A8\u7A7A\u95F4\u5DF2\u6EE1\u3002\u8BF7\u91CA\u653E\u7A7A\u95F4\u540E\u91CD\u8BD5\u3002",
1090
+ statusExpired: "\u5DF2\u8FC7\u671F",
1091
+ statusRemoved: "\u5DF2\u79FB\u9664",
1092
+ statusDeleted: "\u5DF2\u5220\u9664",
1093
+ statusPrivate: "\u4E0D\u516C\u5F00",
1094
+ statusUnknown: "\u4E0D\u53EF\u7528",
1095
+ retry: "\u91CD\u8BD5",
1096
+ removeFromList: "\u4ECE\u5217\u8868\u4E2D\u5220\u9664",
1097
+ pruneStale: "\u5220\u9664\u4E0D\u53EF\u7528\u9879\u76EE",
1098
+ retrySync: "\u91CD\u8BD5\u540C\u6B65",
1099
+ resolveSync: "\u89E3\u51B3\u51B2\u7A81",
1100
+ keepLocal: "\u4FDD\u7559\u672C\u5730\u7248\u672C",
1101
+ useServer: "\u4F7F\u7528\u670D\u52A1\u5668\u7248\u672C",
1102
+ manualMerge: "\u624B\u52A8\u5408\u5E76",
1103
+ close: "\u5173\u95ED",
1104
+ backupRecovery: "\u4ECE\u5907\u4EFD\u6062\u590D",
1105
+ backupRecoveryDescription: "\u5982\u679C\u672C\u5730\u540C\u6B65\u6570\u636E\u635F\u574F\uFF0C\u8BF7\u6062\u590D\u53EF\u7528\u7684 JSON \u5907\u4EFD\u3002",
1106
+ syncPending: "\u6709\u66F4\u6539\u7B49\u5F85\u540C\u6B65\u3002",
1107
+ syncSynced: "\u6240\u6709\u66F4\u6539\u5747\u5DF2\u540C\u6B65\u3002",
1108
+ syncConflict: "\u6709\u4E9B\u66F4\u6539\u9700\u8981\u89E3\u51B3\u51B2\u7A81\u3002"
1109
+ };
1110
+
1111
+ // src/locales/zh-Hant.ts
1112
+ var ZH_HANT_LABELS = {
1113
+ save: "\u5132\u5B58",
1114
+ saved: "\u5DF2\u5132\u5B58",
1115
+ remove: "\u522A\u9664",
1116
+ loading: "\u8F09\u5165\u4E2D\u2026",
1117
+ saving: "\u5132\u5B58\u4E2D\u2026",
1118
+ syncing: "\u540C\u6B65\u4E2D\u2026",
1119
+ error: "\u767C\u751F\u932F\u8AA4\u3002",
1120
+ allTags: "\u5168\u90E8",
1121
+ tags: "\u6A19\u7C64",
1122
+ filterTags: "\u4F9D\u6A19\u7C64\u7BE9\u9078\u5DF2\u5132\u5B58\u9805\u76EE",
1123
+ note: "\u5099\u8A3B",
1124
+ saveNote: "\u5132\u5B58\u5099\u8A3B",
1125
+ noItems: "\u6C92\u6709\u5DF2\u5132\u5B58\u7684\u9805\u76EE\u3002",
1126
+ loadingItems: "\u6B63\u5728\u8F09\u5165\u5DF2\u5132\u5B58\u9805\u76EE\u2026",
1127
+ errorItems: "\u7121\u6CD5\u8F09\u5165\u5DF2\u5132\u5B58\u9805\u76EE\u3002",
1128
+ search: "\u641C\u5C0B\u5DF2\u5132\u5B58\u9805\u76EE",
1129
+ sort: "\u6392\u5E8F\u5DF2\u5132\u5B58\u9805\u76EE",
1130
+ newest: "\u6700\u65B0\u512A\u5148",
1131
+ oldest: "\u6700\u65E9\u512A\u5148",
1132
+ savedNewest: "\u5132\u5B58\u6642\u9593\u6700\u65B0\u512A\u5148",
1133
+ savedOldest: "\u5132\u5B58\u6642\u9593\u6700\u65E9\u512A\u5148",
1134
+ updatedNewest: "\u66F4\u65B0\u6642\u9593\u6700\u65B0\u512A\u5148",
1135
+ updatedOldest: "\u66F4\u65B0\u6642\u9593\u6700\u65E9\u512A\u5148",
1136
+ previousPage: "\u4E0A\u4E00\u9801",
1137
+ nextPage: "\u4E0B\u4E00\u9801",
1138
+ pagination: "\u5206\u9801",
1139
+ page: "\u9801",
1140
+ selectItems: "\u9078\u53D6\u5DF2\u5132\u5B58\u9805\u76EE",
1141
+ selectedCount: "\u9805\u5DF2\u9078\u53D6",
1142
+ deleteSelected: "\u522A\u9664\u6240\u9078\u9805\u76EE",
1143
+ tagsToApply: "\u8981\u5957\u7528\u7684\u6A19\u7C64",
1144
+ applyTags: "\u5957\u7528\u6A19\u7C64",
1145
+ savedMessage: "\u9805\u76EE\u5DF2\u5132\u5B58\u3002",
1146
+ removedMessage: "\u9805\u76EE\u5DF2\u522A\u9664\u3002",
1147
+ undo: "\u5FA9\u539F",
1148
+ undoAvailable: "\u9805\u76EE\u5DF2\u522A\u9664\u3002\u8981\u5FA9\u539F\u55CE\uFF1F",
1149
+ selectionScope: "\u9078\u53D6\u7BC4\u570D",
1150
+ currentPage: "\u76EE\u524D\u9801\u9762",
1151
+ searchResults: "\u76EE\u524D\u5168\u90E8\u641C\u5C0B\u7D50\u679C",
1152
+ allItems: "\u6240\u6709\u5DF2\u5132\u5B58\u9805\u76EE",
1153
+ statusAvailable: "\u53EF\u7528",
1154
+ noteSavedMessage: "\u5099\u8A3B\u5DF2\u5132\u5B58\u3002",
1155
+ exportData: "\u532F\u51FAJSON",
1156
+ importData: "\u532F\u5165JSON",
1157
+ importMode: "\u532F\u5165\u65B9\u5F0F",
1158
+ merge: "\u5408\u4F75",
1159
+ replace: "\u53D6\u4EE3",
1160
+ importedCount: "\u9805\u5DF2\u532F\u5165",
1161
+ failedCount: "\u9805\u5931\u6557",
1162
+ storageQuotaError: "\u5132\u5B58\u7A7A\u9593\u5DF2\u6EFF\u3002\u8ACB\u91CB\u653E\u7A7A\u9593\u5F8C\u91CD\u8A66\u3002",
1163
+ statusExpired: "\u5DF2\u904E\u671F",
1164
+ statusRemoved: "\u5DF2\u79FB\u9664",
1165
+ statusDeleted: "\u5DF2\u522A\u9664",
1166
+ statusPrivate: "\u4E0D\u516C\u958B",
1167
+ statusUnknown: "\u7121\u6CD5\u4F7F\u7528",
1168
+ retry: "\u91CD\u8A66",
1169
+ removeFromList: "\u5F9E\u6E05\u55AE\u4E2D\u522A\u9664",
1170
+ pruneStale: "\u522A\u9664\u7121\u6CD5\u4F7F\u7528\u7684\u9805\u76EE",
1171
+ retrySync: "\u91CD\u8A66\u540C\u6B65",
1172
+ resolveSync: "\u89E3\u6C7A\u885D\u7A81",
1173
+ keepLocal: "\u4FDD\u7559\u672C\u6A5F\u7248\u672C",
1174
+ useServer: "\u4F7F\u7528\u4F3A\u670D\u5668\u7248\u672C",
1175
+ manualMerge: "\u624B\u52D5\u5408\u4F75",
1176
+ close: "\u95DC\u9589",
1177
+ backupRecovery: "\u5F9E\u5099\u4EFD\u9084\u539F",
1178
+ backupRecoveryDescription: "\u5982\u679C\u672C\u6A5F\u540C\u6B65\u8CC7\u6599\u640D\u6BC0\uFF0C\u8ACB\u9084\u539F\u53EF\u7528\u7684 JSON \u5099\u4EFD\u3002",
1179
+ syncPending: "\u6709\u8B8A\u66F4\u7B49\u5F85\u540C\u6B65\u3002",
1180
+ syncSynced: "\u6240\u6709\u8B8A\u66F4\u90FD\u5DF2\u540C\u6B65\u3002",
1181
+ syncConflict: "\u6709\u4E9B\u8B8A\u66F4\u9700\u8981\u89E3\u6C7A\u885D\u7A81\u3002"
1182
+ };
1183
+
1184
+ // src/locales/index.ts
1185
+ var KEEP_BUILT_IN_LOCALES = [
1186
+ "en",
1187
+ "ja",
1188
+ "ko",
1189
+ "zh-Hans",
1190
+ "zh-Hant",
1191
+ "th",
1192
+ "fr",
1193
+ "es",
1194
+ "pt-BR",
1195
+ "it",
1196
+ "de",
1197
+ "ru",
1198
+ "fil",
1199
+ "vi",
1200
+ "id",
1201
+ "ms"
1202
+ ];
73
1203
  var KEEP_LOCALE_LABELS = {
74
- ja: {
75
- save: "\u4FDD\u5B58",
76
- saved: "\u4FDD\u5B58\u6E08\u307F",
77
- remove: "\u524A\u9664",
78
- loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026",
79
- saving: "\u4FDD\u5B58\u4E2D\u2026",
80
- syncing: "\u540C\u671F\u4E2D\u2026",
81
- allTags: "\u3059\u3079\u3066",
82
- filterTags: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u30BF\u30B0\u3067\u7D5E\u308A\u8FBC\u3080",
83
- note: "\u30E1\u30E2",
84
- saveNote: "\u30E1\u30E2\u3092\u4FDD\u5B58",
85
- loadingItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026",
86
- errorItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
87
- noItems: "\u4FDD\u5B58\u3055\u308C\u305F\u30A2\u30A4\u30C6\u30E0\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
88
- search: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u691C\u7D22",
89
- sort: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u4E26\u3079\u66FF\u3048",
90
- newest: "\u65B0\u3057\u3044\u9806",
91
- oldest: "\u53E4\u3044\u9806",
92
- savedNewest: "\u4FDD\u5B58\u65E5\u6642\u306E\u65B0\u3057\u3044\u9806",
93
- savedOldest: "\u4FDD\u5B58\u65E5\u6642\u306E\u53E4\u3044\u9806",
94
- updatedNewest: "\u66F4\u65B0\u65E5\u6642\u306E\u65B0\u3057\u3044\u9806",
95
- updatedOldest: "\u66F4\u65B0\u65E5\u6642\u306E\u53E4\u3044\u9806",
96
- previousPage: "\u524D\u306E\u30DA\u30FC\u30B8",
97
- nextPage: "\u6B21\u306E\u30DA\u30FC\u30B8",
98
- pagination: "\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3",
99
- page: "\u30DA\u30FC\u30B8",
100
- selectItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u9078\u629E",
101
- selectedCount: "\u4EF6\u3092\u9078\u629E\u4E2D",
102
- deleteSelected: "\u9078\u629E\u9805\u76EE\u3092\u524A\u9664",
103
- undo: "\u5143\u306B\u623B\u3059",
104
- undoAvailable: "\u30A2\u30A4\u30C6\u30E0\u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002\u5143\u306B\u623B\u3057\u307E\u3059\u304B\uFF1F",
105
- selectionScope: "\u9078\u629E\u7BC4\u56F2",
106
- currentPage: "\u8868\u793A\u4E2D\u306E\u30DA\u30FC\u30B8",
107
- searchResults: "\u73FE\u5728\u306E\u691C\u7D22\u7D50\u679C\u5168\u4F53",
108
- allItems: "\u3059\u3079\u3066\u306E\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0",
109
- tags: "\u30BF\u30B0",
110
- statusAvailable: "\u5229\u7528\u53EF\u80FD",
111
- tagsToApply: "\u9069\u7528\u3059\u308B\u30BF\u30B0",
112
- applyTags: "\u30BF\u30B0\u3092\u9069\u7528"
113
- },
114
- ko: {
115
- save: "\uC800\uC7A5",
116
- saved: "\uC800\uC7A5\uB428",
117
- remove: "\uC0AD\uC81C",
118
- loading: "\uB85C\uB4DC \uC911\u2026",
119
- saving: "\uC800\uC7A5 \uC911\u2026",
120
- syncing: "\uB3D9\uAE30\uD654 \uC911\u2026",
121
- noItems: "\uC800\uC7A5\uB41C \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
122
- search: "\uC800\uC7A5\uB41C \uD56D\uBAA9 \uAC80\uC0C9",
123
- sort: "\uC800\uC7A5\uB41C \uD56D\uBAA9 \uC815\uB82C",
124
- previousPage: "\uC774\uC804 \uD398\uC774\uC9C0",
125
- nextPage: "\uB2E4\uC74C \uD398\uC774\uC9C0",
126
- pagination: "\uD398\uC774\uC9C0 \uB9E4\uAE40",
127
- page: "\uD398\uC774\uC9C0",
128
- undo: "\uC2E4\uD589 \uCDE8\uC18C",
129
- undoAvailable: "\uD56D\uBAA9\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4. \uC2E4\uD589 \uCDE8\uC18C\uD560\uAE4C\uC694?",
130
- selectionScope: "\uC120\uD0DD \uBC94\uC704",
131
- currentPage: "\uD604\uC7AC \uD398\uC774\uC9C0",
132
- searchResults: "\uD604\uC7AC \uAC80\uC0C9 \uACB0\uACFC \uC804\uCCB4",
133
- allItems: "\uBAA8\uB4E0 \uC800\uC7A5 \uD56D\uBAA9",
134
- tags: "\uD0DC\uADF8"
135
- },
136
- "zh-CN": {
137
- save: "\u4FDD\u5B58",
138
- saved: "\u5DF2\u4FDD\u5B58",
139
- remove: "\u5220\u9664",
140
- loading: "\u52A0\u8F7D\u4E2D\u2026",
141
- saving: "\u4FDD\u5B58\u4E2D\u2026",
142
- syncing: "\u540C\u6B65\u4E2D\u2026",
143
- noItems: "\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u9879\u76EE\u3002",
144
- search: "\u641C\u7D22\u5DF2\u4FDD\u5B58\u9879\u76EE",
145
- sort: "\u6392\u5E8F\u5DF2\u4FDD\u5B58\u9879\u76EE",
146
- previousPage: "\u4E0A\u4E00\u9875",
147
- nextPage: "\u4E0B\u4E00\u9875",
148
- pagination: "\u5206\u9875",
149
- page: "\u9875",
150
- undo: "\u64A4\u9500",
151
- undoAvailable: "\u9879\u76EE\u5DF2\u5220\u9664\u3002\u8981\u64A4\u9500\u5417\uFF1F",
152
- selectionScope: "\u9009\u62E9\u8303\u56F4",
153
- currentPage: "\u5F53\u524D\u9875",
154
- searchResults: "\u5F53\u524D\u641C\u7D22\u7ED3\u679C",
155
- allItems: "\u5168\u90E8\u5DF2\u4FDD\u5B58\u9879\u76EE",
156
- tags: "\u6807\u7B7E"
157
- },
158
- "zh-TW": {
159
- save: "\u5132\u5B58",
160
- saved: "\u5DF2\u5132\u5B58",
161
- remove: "\u522A\u9664",
162
- loading: "\u8F09\u5165\u4E2D\u2026",
163
- saving: "\u5132\u5B58\u4E2D\u2026",
164
- syncing: "\u540C\u6B65\u4E2D\u2026",
165
- noItems: "\u6C92\u6709\u5DF2\u5132\u5B58\u7684\u9805\u76EE\u3002",
166
- search: "\u641C\u5C0B\u5DF2\u5132\u5B58\u9805\u76EE",
167
- sort: "\u6392\u5E8F\u5DF2\u5132\u5B58\u9805\u76EE",
168
- previousPage: "\u4E0A\u4E00\u9801",
169
- nextPage: "\u4E0B\u4E00\u9801",
170
- undo: "\u5FA9\u539F",
171
- undoAvailable: "\u9805\u76EE\u5DF2\u522A\u9664\u3002\u8981\u5FA9\u539F\u55CE\uFF1F",
172
- selectionScope: "\u9078\u53D6\u7BC4\u570D",
173
- currentPage: "\u76EE\u524D\u9801\u9762",
174
- searchResults: "\u76EE\u524D\u641C\u5C0B\u7D50\u679C",
175
- allItems: "\u6240\u6709\u5DF2\u5132\u5B58\u9805\u76EE",
176
- tags: "\u6A19\u7C64"
177
- }
1204
+ en: EN_LABELS,
1205
+ ja: JA_LABELS,
1206
+ ko: KO_LABELS,
1207
+ "zh-Hans": ZH_HANS_LABELS,
1208
+ "zh-Hant": ZH_HANT_LABELS,
1209
+ th: TH_LABELS,
1210
+ fr: FR_LABELS,
1211
+ es: ES_LABELS,
1212
+ "pt-BR": PT_BR_LABELS,
1213
+ it: IT_LABELS,
1214
+ de: DE_LABELS,
1215
+ ru: RU_LABELS,
1216
+ fil: FIL_LABELS,
1217
+ vi: VI_LABELS,
1218
+ id: ID_LABELS,
1219
+ ms: MS_LABELS
1220
+ };
1221
+ var LOCALE_ALIASES = {
1222
+ "zh-cn": "zh-Hans",
1223
+ "zh-sg": "zh-Hans",
1224
+ zh: "zh-Hans",
1225
+ "zh-tw": "zh-Hant",
1226
+ "zh-hk": "zh-Hant",
1227
+ "zh-mo": "zh-Hant",
1228
+ "pt-pt": "pt-BR"
178
1229
  };
179
- KEEP_LOCALE_LABELS.zh = KEEP_LOCALE_LABELS["zh-CN"];
1230
+ function normalizeKeepLocale(locale) {
1231
+ const normalized = locale?.trim().replace(/_/g, "-").toLowerCase() ?? "en";
1232
+ const exact = KEEP_BUILT_IN_LOCALES.find((candidate) => candidate.toLowerCase() === normalized);
1233
+ if (exact) return exact;
1234
+ if (LOCALE_ALIASES[normalized]) return LOCALE_ALIASES[normalized];
1235
+ const language = normalized.split("-")[0];
1236
+ const languageMatch = KEEP_BUILT_IN_LOCALES.find((candidate) => candidate.toLowerCase() === language);
1237
+ return languageMatch ?? "en";
1238
+ }
1239
+ function getKeepLocaleLabels(locale) {
1240
+ return { ...KEEP_LOCALE_LABELS[normalizeKeepLocale(locale)] };
1241
+ }
1242
+
1243
+ // src/ui-context.tsx
1244
+ import { jsx } from "react/jsx-runtime";
1245
+ var DEFAULT_LABELS = KEEP_LOCALE_LABELS.en;
180
1246
  var KeepUiLabelsContext = createContext({ labels: DEFAULT_LABELS });
181
1247
  function KeepUiProvider({ labels, locale, labelResolver, children }) {
182
1248
  const value = useMemo(() => {
183
- const localeKey = locale?.toLowerCase() ?? "en";
184
- const dictionary = KEEP_LOCALE_LABELS[localeKey] ?? KEEP_LOCALE_LABELS[localeKey.split("-")[0]] ?? {};
1249
+ const resolvedLocale = normalizeKeepLocale(locale);
1250
+ const dictionary = getKeepLocaleLabels(resolvedLocale);
185
1251
  const resolved = { ...DEFAULT_LABELS, ...dictionary, ...labels };
186
- return { locale, labels: resolved, customLabels: labels, labelResolver };
1252
+ return { locale: locale ?? resolvedLocale, labels: resolved, customLabels: labels, labelResolver };
187
1253
  }, [labelResolver, labels, locale]);
188
1254
  return /* @__PURE__ */ jsx(KeepUiLabelsContext.Provider, { value, children });
189
1255
  }
@@ -194,10 +1260,6 @@ function useUiLabel(key, override) {
194
1260
  const context = useKeepUiLabels();
195
1261
  return override ?? context.customLabels?.[key] ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
196
1262
  }
197
- function getKeepLocaleLabels(locale) {
198
- const key = locale?.toLowerCase() ?? "en";
199
- return { ...KEEP_LOCALE_LABELS[key] ?? KEEP_LOCALE_LABELS[key.split("-")[0]] ?? {} };
200
- }
201
1263
 
202
1264
  // src/KeepBackup.tsx
203
1265
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
@@ -250,37 +1312,46 @@ function KeepBackup({
250
1312
  setError(cause);
251
1313
  }
252
1314
  }
253
- return /* @__PURE__ */ jsxs("section", { ...props, "data-state": error ? "error" : result ? "complete" : "idle", children: [
254
- /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => void handleExport(), disabled: context.isMutating, children: exportLabel }),
255
- /* @__PURE__ */ jsxs("label", { children: [
256
- importModeLabel,
257
- /* @__PURE__ */ jsxs("select", { value: mode, onChange: (event) => setMode(event.currentTarget.value), children: [
258
- /* @__PURE__ */ jsx2("option", { value: "merge", children: mergeLabel }),
259
- /* @__PURE__ */ jsx2("option", { value: "replace", children: replaceLabel })
260
- ] })
261
- ] }),
262
- /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => inputRef.current?.click(), disabled: context.isMutating, children: importLabel }),
263
- /* @__PURE__ */ jsx2(
264
- "input",
265
- {
266
- ref: inputRef,
267
- type: "file",
268
- accept: "application/json,.json",
269
- "aria-label": importLabel,
270
- onChange: (event) => void handleImport(event)
271
- }
272
- ),
273
- result ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
274
- result.imported,
275
- " ",
276
- importedCountLabel,
277
- "; ",
278
- result.failed,
279
- " ",
280
- failedCountLabel
281
- ] }) : null,
282
- error ? /* @__PURE__ */ jsx2("p", { role: "alert", children: isQuotaError(error) ? quotaErrorLabel : getErrorMessage(error) }) : null
283
- ] });
1315
+ return /* @__PURE__ */ jsxs(
1316
+ "section",
1317
+ {
1318
+ ...props,
1319
+ "data-keepkit": "backup",
1320
+ "data-state": error ? "error" : result ? "complete" : "idle",
1321
+ "data-loading": context.isMutating ? "true" : void 0,
1322
+ children: [
1323
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => void handleExport(), disabled: context.isMutating, children: exportLabel }),
1324
+ /* @__PURE__ */ jsxs("label", { children: [
1325
+ importModeLabel,
1326
+ /* @__PURE__ */ jsxs("select", { value: mode, onChange: (event) => setMode(event.currentTarget.value), children: [
1327
+ /* @__PURE__ */ jsx2("option", { value: "merge", children: mergeLabel }),
1328
+ /* @__PURE__ */ jsx2("option", { value: "replace", children: replaceLabel })
1329
+ ] })
1330
+ ] }),
1331
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => inputRef.current?.click(), disabled: context.isMutating, children: importLabel }),
1332
+ /* @__PURE__ */ jsx2(
1333
+ "input",
1334
+ {
1335
+ ref: inputRef,
1336
+ type: "file",
1337
+ accept: "application/json,.json",
1338
+ "aria-label": importLabel,
1339
+ onChange: (event) => void handleImport(event)
1340
+ }
1341
+ ),
1342
+ result ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
1343
+ result.imported,
1344
+ " ",
1345
+ importedCountLabel,
1346
+ "; ",
1347
+ result.failed,
1348
+ " ",
1349
+ failedCountLabel
1350
+ ] }) : null,
1351
+ error ? /* @__PURE__ */ jsx2("p", { role: "alert", children: isQuotaError(error) ? quotaErrorLabel : getErrorMessage(error) }) : null
1352
+ ]
1353
+ }
1354
+ );
284
1355
  }
285
1356
  function isQuotaError(error) {
286
1357
  if (error instanceof Error && error.name === "KeepStorageQuotaError") return true;
@@ -313,6 +1384,7 @@ function KeepItemCheckbox({
313
1384
  ...props,
314
1385
  type: "checkbox",
315
1386
  checked,
1387
+ "data-keepkit": "item-checkbox",
316
1388
  "data-state": checked ? "checked" : "unchecked",
317
1389
  "data-disabled": props.disabled ? "true" : void 0,
318
1390
  "aria-label": accessibleLabel,
@@ -506,6 +1578,7 @@ function KeepBulkActions({
506
1578
  "section",
507
1579
  {
508
1580
  ...props,
1581
+ "data-keepkit": "bulk-actions",
509
1582
  "aria-busy": list.isMutating || props["aria-busy"],
510
1583
  "data-state": selectedIds.length > 0 ? "selected" : "idle",
511
1584
  "data-loading": list.isLoading || list.isMutating ? "true" : void 0,
@@ -519,23 +1592,37 @@ import {
519
1592
  KeepButton as CoreKeepButton,
520
1593
  useKeepItem
521
1594
  } from "@keepkit/core/react";
522
- import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
523
- function KeepButton({ labels, ...props }) {
1595
+ import { createElement } from "react";
1596
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
1597
+ function KeepButton({
1598
+ labels,
1599
+ icons,
1600
+ iconOnly = false,
1601
+ showLabel = true,
1602
+ iconClassName,
1603
+ ...props
1604
+ }) {
524
1605
  const saveLabel = useUiLabel("save", typeof labels?.unsaved === "string" ? labels.unsaved : void 0);
525
1606
  const savedLabel = useUiLabel("saved", typeof labels?.saved === "string" ? labels.saved : void 0);
526
1607
  const loadingLabel = useUiLabel("loading", typeof labels?.loading === "string" ? labels.loading : void 0);
527
1608
  const errorLabel = useUiLabel("error", typeof labels?.error === "string" ? labels.error : void 0);
528
1609
  const buttonState = useKeepItem(props.item);
529
- const customStateLabel = labels?.loading !== void 0 || labels?.error !== void 0;
1610
+ const customStateLabel = labels?.loading !== void 0 || labels?.error !== void 0 || icons !== void 0 && props.children === void 0;
530
1611
  const getStateContent = (state) => {
531
- if (state.error) return labels?.error ?? errorLabel;
532
- if (state.isMutating) return labels?.loading ?? loadingLabel;
533
1612
  if (typeof props.children === "function") return props.children(state);
534
1613
  if (props.children !== void 0) return props.children;
535
- return state.isSaved ? labels?.saved ?? savedLabel : labels?.unsaved ?? saveLabel;
1614
+ const label = state.error ? labels?.error ?? errorLabel : state.isMutating ? labels?.loading ?? loadingLabel : state.isSaved ? labels?.saved ?? savedLabel : labels?.unsaved ?? saveLabel;
1615
+ if (!icons) return label;
1616
+ const icon = state.error ? icons.error : state.isMutating ? icons.loading : state.isSaved ? icons.remove ?? icons.saved : icons.save;
1617
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
1618
+ renderIcon(icon, iconClassName),
1619
+ showLabel && !iconOnly ? label : null
1620
+ ] });
536
1621
  };
537
1622
  const sharedProps = {
538
1623
  ...props,
1624
+ "data-keepkit": "button",
1625
+ "data-icon-only": iconOnly ? "true" : void 0,
539
1626
  "aria-busy": props["aria-busy"] ?? (buttonState.isLoading || buttonState.isMutating),
540
1627
  savedLabel: labels?.saved ?? props.savedLabel ?? savedLabel,
541
1628
  unsavedLabel: labels?.unsaved ?? props.unsavedLabel ?? saveLabel,
@@ -545,10 +1632,14 @@ function KeepButton({ labels, ...props }) {
545
1632
  if (!customStateLabel) return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps });
546
1633
  return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx6(Fragment2, { children: getStateContent(state) }) });
547
1634
  }
1635
+ function renderIcon(icon, className) {
1636
+ if (typeof icon === "function") return createElement(icon, { "aria-hidden": true, className });
1637
+ return icon ?? null;
1638
+ }
548
1639
 
549
1640
  // src/KeepCollection.tsx
550
1641
  import { KeepErrorBoundary as KeepErrorBoundary2, useKeepList as useKeepList4 } from "@keepkit/core/react";
551
- import { useMemo as useMemo3, useState as useState5 } from "react";
1642
+ import { useMemo as useMemo3, useState as useState6 } from "react";
552
1643
 
553
1644
  // src/KeepList.tsx
554
1645
  import {
@@ -562,7 +1653,116 @@ import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
562
1653
  import {
563
1654
  isValidElement as isValidElement2
564
1655
  } from "react";
565
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
1656
+
1657
+ // src/KeepStaleNotice.tsx
1658
+ import { useKeepContext as useKeepContext2 } from "@keepkit/core/react";
1659
+ import { useState as useState3 } from "react";
1660
+
1661
+ // src/KeepItemStatusBadge.tsx
1662
+ import { jsx as jsx7 } from "react/jsx-runtime";
1663
+ function KeepItemStatusBadge({ status = "available", label, className, ...props }) {
1664
+ const resolvedStatus = status === "available" ? "available" : status;
1665
+ const statusLabel = useUiLabel(getStatusLabelKey(resolvedStatus));
1666
+ return /* @__PURE__ */ jsx7("span", { ...props, className, "data-keepkit": "status-badge", "data-status": resolvedStatus, children: label ?? statusLabel });
1667
+ }
1668
+ function getStatusLabelKey(status) {
1669
+ switch (status) {
1670
+ case "available":
1671
+ return "statusAvailable";
1672
+ case "expired":
1673
+ return "statusExpired";
1674
+ case "removed":
1675
+ return "statusRemoved";
1676
+ case "deleted":
1677
+ return "statusDeleted";
1678
+ case "private":
1679
+ case "unknown":
1680
+ return status === "private" ? "statusPrivate" : "statusUnknown";
1681
+ }
1682
+ }
1683
+
1684
+ // src/KeepStaleNotice.tsx
1685
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1686
+ function KeepStaleNotice({
1687
+ item,
1688
+ onRetry,
1689
+ onRemoved,
1690
+ retryLabel,
1691
+ removeLabel,
1692
+ children,
1693
+ className,
1694
+ ...props
1695
+ }) {
1696
+ const context = useKeepContext2();
1697
+ const retryText = useUiLabel("retry");
1698
+ const removeText = useUiLabel("removeFromList");
1699
+ const errorText = useUiLabel("error");
1700
+ const [isRetrying, setIsRetrying] = useState3(false);
1701
+ const [error, setError] = useState3(null);
1702
+ const status = item.status && item.status !== "available" ? item.status : "unknown";
1703
+ async function handleRetry() {
1704
+ setError(null);
1705
+ setIsRetrying(true);
1706
+ try {
1707
+ if (onRetry) await onRetry(item);
1708
+ else await context.revalidateItems();
1709
+ } catch (cause) {
1710
+ setError(cause);
1711
+ } finally {
1712
+ setIsRetrying(false);
1713
+ }
1714
+ }
1715
+ async function handleRemove() {
1716
+ try {
1717
+ await context.removeItemWithUndo(item.id);
1718
+ onRemoved?.(item);
1719
+ } catch (cause) {
1720
+ setError(cause);
1721
+ }
1722
+ }
1723
+ return /* @__PURE__ */ jsxs4("aside", { ...props, className, "data-keepkit": "stale-notice", "data-state": error ? "error" : "stale", children: [
1724
+ /* @__PURE__ */ jsx8(KeepItemStatusBadge, { status }),
1725
+ children ?? (item.statusReason ? /* @__PURE__ */ jsx8("p", { children: item.statusReason }) : null),
1726
+ /* @__PURE__ */ jsxs4("div", { children: [
1727
+ /* @__PURE__ */ jsx8("button", { type: "button", onClick: () => void handleRetry(), disabled: isRetrying || context.isMutating, children: retryLabel ?? retryText }),
1728
+ /* @__PURE__ */ jsx8("button", { type: "button", onClick: () => void handleRemove(), disabled: context.isMutating, children: removeLabel ?? removeText })
1729
+ ] }),
1730
+ error ? /* @__PURE__ */ jsx8("p", { role: "alert", children: error instanceof Error ? error.message : errorText }) : null
1731
+ ] });
1732
+ }
1733
+ function KeepPruneStaleButton({
1734
+ statuses = ["expired", "removed", "deleted", "private", "unknown"],
1735
+ label,
1736
+ onPruned,
1737
+ children,
1738
+ disabled,
1739
+ ...props
1740
+ }) {
1741
+ const context = useKeepContext2();
1742
+ const defaultLabel = useUiLabel("pruneStale");
1743
+ const staleIds = context.items.filter((item) => item.status && statuses.includes(item.status)).map((item) => item.id);
1744
+ async function handlePrune() {
1745
+ const ids = [...staleIds];
1746
+ await context.removeItemsWithUndo(ids);
1747
+ onPruned?.(ids);
1748
+ }
1749
+ return /* @__PURE__ */ jsx8(
1750
+ "button",
1751
+ {
1752
+ ...props,
1753
+ type: "button",
1754
+ className: props.className,
1755
+ "data-keepkit": "prune-stale",
1756
+ "data-state": staleIds.length > 0 ? "available" : "empty",
1757
+ disabled: staleIds.length === 0 || context.isMutating || disabled,
1758
+ onClick: () => void handlePrune(),
1759
+ children: children ?? label ?? `${defaultLabel} (${staleIds.length})`
1760
+ }
1761
+ );
1762
+ }
1763
+
1764
+ // src/KeepItemCard.tsx
1765
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
566
1766
  function KeepItemCard({
567
1767
  item,
568
1768
  title,
@@ -572,12 +1772,14 @@ function KeepItemCard({
572
1772
  renderImage,
573
1773
  renderTags,
574
1774
  showTags = true,
1775
+ showSavedAt = true,
575
1776
  imageAlt,
576
1777
  render,
577
1778
  children,
578
1779
  removeLabel,
579
1780
  onRemoveError,
580
1781
  onRemoved,
1782
+ onRetry,
581
1783
  showSaveButton = true,
582
1784
  saveButtonLabels,
583
1785
  asChild = false,
@@ -591,6 +1793,8 @@ function KeepItemCard({
591
1793
  ...rootProps
592
1794
  }) {
593
1795
  const saveActionLabel = useUiLabel("save");
1796
+ const savedAtLabel = useUiLabel("saved");
1797
+ const errorLabel = useUiLabel("error");
594
1798
  const removeActionLabel = useUiLabel("remove");
595
1799
  const itemState = useKeepItem2(item);
596
1800
  const contentChildren = asChild && isValidElement2(children) ? void 0 : children;
@@ -606,7 +1810,7 @@ function KeepItemCard({
606
1810
  const imageProps = getImageProps?.(item, resolvedTitle);
607
1811
  const href = typeof hrefOption === "function" ? hrefOption(item) : hrefOption;
608
1812
  const isAvailable = item.status === void 0 || item.status === "available";
609
- const statusLabelKey = item.status && item.status !== "available" ? getStatusLabelKey(item.status) : "statusUnknown";
1813
+ const statusLabelKey = item.status && item.status !== "available" ? getStatusLabelKey2(item.status) : "statusUnknown";
610
1814
  const unavailableLabel = useUiLabel(statusLabelKey);
611
1815
  const tagsLabel = useUiLabel("tags");
612
1816
  const statusLabel = item.status && item.status !== "available" ? unavailableLabel : void 0;
@@ -619,7 +1823,7 @@ function KeepItemCard({
619
1823
  onClick: (event) => onOpen?.(item, event),
620
1824
  children: content
621
1825
  };
622
- return LinkComponent ? /* @__PURE__ */ jsx7(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx7("a", { ...linkProps });
1826
+ return LinkComponent ? /* @__PURE__ */ jsx9(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx9("a", { ...linkProps });
623
1827
  }
624
1828
  async function handleRemove() {
625
1829
  try {
@@ -629,12 +1833,21 @@ function KeepItemCard({
629
1833
  onRemoveError?.(error);
630
1834
  }
631
1835
  }
632
- const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs3(Fragment3, { children: [
633
- imageProps ? renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ?? (ImageComponent ? /* @__PURE__ */ jsx7(ImageComponent, { ...imageProps, alt: imageAlt ?? imageProps.alt }) : /* @__PURE__ */ jsx7("img", { ...imageProps, alt: imageAlt ?? imageProps.alt })) : null,
634
- /* @__PURE__ */ jsx7("h3", { children: linkTarget === "title" ? renderLink(resolvedTitle) : resolvedTitle }),
635
- showTags && (item.tags?.length ?? 0) > 0 ? renderTags ? renderTags(item.tags ?? [], item) : /* @__PURE__ */ jsx7("ul", { "aria-label": tagsLabel, children: item.tags?.map((tag) => /* @__PURE__ */ jsx7("li", { children: tag }, tag)) }) : null,
636
- statusLabel ? /* @__PURE__ */ jsx7("p", { "data-status": item.status, children: statusLabel }) : null,
637
- showSaveButton ? /* @__PURE__ */ jsx7(
1836
+ const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs5(Fragment3, { children: [
1837
+ imageProps ? renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ?? (ImageComponent ? /* @__PURE__ */ jsx9(ImageComponent, { ...imageProps, alt: imageAlt ?? imageProps.alt }) : /* @__PURE__ */ jsx9("img", { ...imageProps, alt: imageAlt ?? imageProps.alt })) : null,
1838
+ /* @__PURE__ */ jsx9("h3", { children: linkTarget === "title" ? renderLink(resolvedTitle) : resolvedTitle }),
1839
+ showSavedAt ? /* @__PURE__ */ jsxs5("div", { "data-card-meta": true, children: [
1840
+ /* @__PURE__ */ jsxs5("span", { children: [
1841
+ savedAtLabel,
1842
+ ":"
1843
+ ] }),
1844
+ " ",
1845
+ /* @__PURE__ */ jsx9("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
1846
+ ] }) : null,
1847
+ showTags && (item.tags?.length ?? 0) > 0 ? renderTags ? renderTags(item.tags ?? [], item) : /* @__PURE__ */ jsx9("ul", { "aria-label": tagsLabel, children: item.tags?.map((tag) => /* @__PURE__ */ jsx9("li", { children: tag }, tag)) }) : null,
1848
+ itemState.error ? /* @__PURE__ */ jsx9("p", { role: "alert", children: getErrorMessage2(itemState.error, errorLabel) }) : null,
1849
+ statusLabel ? /* @__PURE__ */ jsx9(KeepStaleNotice, { item, onRetry, onRemoved }) : null,
1850
+ showSaveButton && !statusLabel ? /* @__PURE__ */ jsx9(
638
1851
  KeepButton,
639
1852
  {
640
1853
  item: toKeepButtonItem(item),
@@ -642,7 +1855,7 @@ function KeepItemCard({
642
1855
  getAriaLabel: (buttonState) => `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`
643
1856
  }
644
1857
  ) : null,
645
- /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel })
1858
+ !statusLabel ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel }) : null
646
1859
  ] });
647
1860
  const linkedBody = linkTarget === "card" ? renderLink(body) : body;
648
1861
  return renderRoot(
@@ -651,8 +1864,9 @@ function KeepItemCard({
651
1864
  {
652
1865
  ...rootProps,
653
1866
  className,
1867
+ "data-keepkit": "card",
654
1868
  "aria-busy": itemState.isMutating || rootProps["aria-busy"],
655
- "data-state": itemState.isSaved ? "saved" : "unsaved",
1869
+ "data-state": itemState.error ? "error" : itemState.isSaved ? "saved" : "unsaved",
656
1870
  "data-status": item.status ?? "available",
657
1871
  "data-loading": itemState.isMutating ? "true" : void 0
658
1872
  },
@@ -660,7 +1874,7 @@ function KeepItemCard({
660
1874
  "KeepItemCard"
661
1875
  );
662
1876
  }
663
- function getStatusLabelKey(status) {
1877
+ function getStatusLabelKey2(status) {
664
1878
  switch (status) {
665
1879
  case "expired":
666
1880
  return "statusExpired";
@@ -674,14 +1888,20 @@ function getStatusLabelKey(status) {
674
1888
  return "statusUnknown";
675
1889
  }
676
1890
  }
1891
+ function formatSavedAt(timestamp) {
1892
+ return new Date(timestamp).toISOString().slice(0, 10);
1893
+ }
1894
+ function getErrorMessage2(error, fallback) {
1895
+ return error instanceof Error ? error.message : fallback;
1896
+ }
677
1897
 
678
1898
  // src/KeepList.tsx
679
- import { jsx as jsx8 } from "react/jsx-runtime";
1899
+ import { jsx as jsx10 } from "react/jsx-runtime";
680
1900
  function KeepList(props) {
681
1901
  const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
682
- const content = /* @__PURE__ */ jsx8(KeepListContent, { ...listProps });
1902
+ const content = /* @__PURE__ */ jsx10(KeepListContent, { ...listProps });
683
1903
  if (fallback === void 0 && onBoundaryError === void 0) return content;
684
- return /* @__PURE__ */ jsx8(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
1904
+ return /* @__PURE__ */ jsx10(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
685
1905
  }
686
1906
  function KeepListContent({
687
1907
  query,
@@ -715,6 +1935,7 @@ function KeepListContent({
715
1935
  {
716
1936
  ...rootProps,
717
1937
  className,
1938
+ "data-keepkit": "list",
718
1939
  "aria-busy": state.isLoading || rootProps["aria-busy"],
719
1940
  "data-state": getListState(state),
720
1941
  "data-loading": state.isLoading ? "true" : void 0
@@ -735,13 +1956,13 @@ function getListBody(state, options) {
735
1956
  if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);
736
1957
  if (typeof options.children === "function") return options.children(state);
737
1958
  if (options.children !== void 0 && !isValidElement3(options.children)) return options.children;
738
- return /* @__PURE__ */ jsx8(
1959
+ return /* @__PURE__ */ jsx10(
739
1960
  "ul",
740
1961
  {
741
1962
  "data-layout": options.layout,
742
1963
  style: options.layout === "grid" ? { display: "grid", gap: "1rem", gridTemplateColumns: "repeat(auto-fit, minmax(16rem, 1fr))" } : options.layout === "compact" ? { display: "grid", gap: "0.5rem", gridTemplateColumns: "repeat(auto-fit, minmax(12rem, 1fr))" } : { display: "flex", flexDirection: "column", gap: "1rem" },
743
1964
  children: state.items.map(
744
- (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
1965
+ (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx10("li", { children: /* @__PURE__ */ jsx10(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
745
1966
  )
746
1967
  }
747
1968
  );
@@ -749,8 +1970,8 @@ function getListBody(state, options) {
749
1970
 
750
1971
  // src/KeepTagFilter.tsx
751
1972
  import { useKeepList as useKeepList3 } from "@keepkit/core/react";
752
- import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState3 } from "react";
753
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1973
+ import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState4 } from "react";
1974
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
754
1975
  function KeepTagFilter({
755
1976
  query,
756
1977
  value: controlledValue,
@@ -768,7 +1989,7 @@ function KeepTagFilter({
768
1989
  }) {
769
1990
  const uiAllLabel = useUiLabel("allTags");
770
1991
  const uiAriaLabel = useUiLabel("filterTags");
771
- const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
1992
+ const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
772
1993
  const resolvedValue = controlledValue ?? uncontrolledValue;
773
1994
  const list = useKeepList3({
774
1995
  ...query,
@@ -787,12 +2008,12 @@ function KeepTagFilter({
787
2008
  [list.tagCounts, list.tags, resolvedValue, select]
788
2009
  );
789
2010
  const contentChildren = asChild && isValidElement4(children) ? void 0 : children;
790
- const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs4("fieldset", { children: [
791
- /* @__PURE__ */ jsx9("legend", { children: ariaLabel ?? uiAriaLabel }),
792
- /* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
793
- list.tags.map((tag) => /* @__PURE__ */ jsxs4("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
2011
+ const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs6("fieldset", { children: [
2012
+ /* @__PURE__ */ jsx11("legend", { children: ariaLabel ?? uiAriaLabel }),
2013
+ /* @__PURE__ */ jsx11("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
2014
+ list.tags.map((tag) => /* @__PURE__ */ jsxs6("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
794
2015
  renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag,
795
- /* @__PURE__ */ jsxs4("span", { children: [
2016
+ /* @__PURE__ */ jsxs6("span", { children: [
796
2017
  " (",
797
2018
  list.tagCounts[tag] ?? 0,
798
2019
  ")"
@@ -805,6 +2026,7 @@ function KeepTagFilter({
805
2026
  {
806
2027
  ...rootProps,
807
2028
  className,
2029
+ "data-keepkit": "tag-filter",
808
2030
  "data-state": resolvedValue === void 0 ? "all" : "filtered",
809
2031
  "data-loading": list.isLoading ? "true" : void 0
810
2032
  },
@@ -814,8 +2036,8 @@ function KeepTagFilter({
814
2036
  }
815
2037
 
816
2038
  // src/query-controls.tsx
817
- import { useEffect, useState as useState4 } from "react";
818
- import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
2039
+ import { useEffect, useState as useState5 } from "react";
2040
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
819
2041
  function KeepSearchInput({
820
2042
  value: controlledValue,
821
2043
  defaultValue = "",
@@ -826,7 +2048,7 @@ function KeepSearchInput({
826
2048
  ...props
827
2049
  }) {
828
2050
  const label = useUiLabel("search");
829
- const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
2051
+ const [uncontrolledValue, setUncontrolledValue] = useState5(defaultValue);
830
2052
  const value = controlledValue ?? uncontrolledValue;
831
2053
  useEffect(() => {
832
2054
  if (!onValueChange) return;
@@ -837,10 +2059,11 @@ function KeepSearchInput({
837
2059
  const timer = window.setTimeout(() => onValueChange(value), debounceMs);
838
2060
  return () => window.clearTimeout(timer);
839
2061
  }, [debounceMs, onValueChange, value]);
840
- return /* @__PURE__ */ jsx10(
2062
+ return /* @__PURE__ */ jsx12(
841
2063
  "input",
842
2064
  {
843
2065
  ...props,
2066
+ "data-keepkit": "search-input",
844
2067
  type: "search",
845
2068
  value,
846
2069
  "data-state": value ? "active" : "idle",
@@ -867,18 +2090,19 @@ function KeepSortSelect({
867
2090
  const updatedOldestLabel = useUiLabel("updatedOldest");
868
2091
  const savedNewestLabel = useUiLabel("savedNewest");
869
2092
  const savedOldestLabel = useUiLabel("savedOldest");
870
- const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
2093
+ const [uncontrolledValue, setUncontrolledValue] = useState5(defaultValue);
871
2094
  const value = controlledValue ?? uncontrolledValue;
872
- const options = children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
873
- /* @__PURE__ */ jsx10("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
874
- /* @__PURE__ */ jsx10("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
875
- /* @__PURE__ */ jsx10("option", { value: "savedAt:desc", children: savedNewestLabel }),
876
- /* @__PURE__ */ jsx10("option", { value: "savedAt:asc", children: savedOldestLabel })
2095
+ const options = children ?? /* @__PURE__ */ jsxs7(Fragment4, { children: [
2096
+ /* @__PURE__ */ jsx12("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
2097
+ /* @__PURE__ */ jsx12("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
2098
+ /* @__PURE__ */ jsx12("option", { value: "savedAt:desc", children: savedNewestLabel }),
2099
+ /* @__PURE__ */ jsx12("option", { value: "savedAt:asc", children: savedOldestLabel })
877
2100
  ] });
878
- return /* @__PURE__ */ jsx10(
2101
+ return /* @__PURE__ */ jsx12(
879
2102
  "select",
880
2103
  {
881
2104
  ...props,
2105
+ "data-keepkit": "sort-select",
882
2106
  value,
883
2107
  "data-state": "selected",
884
2108
  "data-disabled": props.disabled ? "true" : void 0,
@@ -914,14 +2138,15 @@ function KeepPagination({
914
2138
  };
915
2139
  const navProps = {
916
2140
  ...props,
2141
+ "data-keepkit": "pagination",
917
2142
  "aria-label": props["aria-label"] ?? paginationLabel,
918
2143
  "data-state": pageCount > 1 ? "active" : "idle"
919
2144
  };
920
- if (render) return /* @__PURE__ */ jsx10("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
2145
+ if (render) return /* @__PURE__ */ jsx12("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
921
2146
  const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));
922
- return /* @__PURE__ */ jsxs5("nav", { ...navProps, children: [
923
- /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
924
- visiblePages.map((nextPage) => /* @__PURE__ */ jsx10(
2147
+ return /* @__PURE__ */ jsxs7("nav", { ...navProps, children: [
2148
+ /* @__PURE__ */ jsx12("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
2149
+ visiblePages.map((nextPage) => /* @__PURE__ */ jsx12(
925
2150
  "button",
926
2151
  {
927
2152
  type: "button",
@@ -932,7 +2157,7 @@ function KeepPagination({
932
2157
  },
933
2158
  nextPage
934
2159
  )),
935
- /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
2160
+ /* @__PURE__ */ jsx12("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
936
2161
  ] });
937
2162
  }
938
2163
  function getVisiblePages(currentPage, pageCount, maxPageButtons) {
@@ -1025,12 +2250,12 @@ function getBrowserAdapter() {
1025
2250
  }
1026
2251
 
1027
2252
  // src/KeepCollection.tsx
1028
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
2253
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1029
2254
  function KeepCollection(props) {
1030
2255
  const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
1031
- const content = /* @__PURE__ */ jsx11(KeepCollectionContent, { ...collectionProps });
2256
+ const content = /* @__PURE__ */ jsx13(KeepCollectionContent, { ...collectionProps });
1032
2257
  if (fallback === void 0 && onBoundaryError === void 0) return content;
1033
- return /* @__PURE__ */ jsx11(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
2258
+ return /* @__PURE__ */ jsx13(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
1034
2259
  }
1035
2260
  function KeepCollectionContent({
1036
2261
  query = {},
@@ -1055,10 +2280,10 @@ function KeepCollectionContent({
1055
2280
  bulkActions: false,
1056
2281
  ...features
1057
2282
  };
1058
- const [searchValue, setSearchValue] = useState5(query.search?.query ?? "");
1059
- const [sort, setSort] = useState5(query.sort ?? { by: "updatedAt", direction: "desc" });
1060
- const [tag, setTag] = useState5(query.tags?.[0]);
1061
- const [page, setPage] = useState5(query.pagination?.page ?? 1);
2283
+ const [searchValue, setSearchValue] = useState6(query.search?.query ?? "");
2284
+ const [sort, setSort] = useState6(query.sort ?? { by: "updatedAt", direction: "desc" });
2285
+ const [tag, setTag] = useState6(query.tags?.[0]);
2286
+ const [page, setPage] = useState6(query.pagination?.page ?? 1);
1062
2287
  const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
1063
2288
  const resolvedQuery = useMemo3(
1064
2289
  () => ({
@@ -1084,17 +2309,18 @@ function KeepCollectionContent({
1084
2309
  adapter: urlAdapter
1085
2310
  });
1086
2311
  const list = useKeepList4(resolvedQuery);
1087
- return /* @__PURE__ */ jsxs6(
2312
+ return /* @__PURE__ */ jsxs8(
1088
2313
  "section",
1089
2314
  {
1090
2315
  ...rootProps,
1091
2316
  className,
2317
+ "data-keepkit": "collection",
1092
2318
  "aria-busy": list.isLoading || list.isMutating || rootProps["aria-busy"],
1093
2319
  "data-state": getCollectionState(list),
1094
2320
  "data-loading": list.isLoading || list.isMutating ? "true" : void 0,
1095
2321
  children: [
1096
- /* @__PURE__ */ jsxs6("div", { children: [
1097
- enabled.search ? /* @__PURE__ */ jsx11(
2322
+ /* @__PURE__ */ jsxs8("div", { children: [
2323
+ enabled.search ? /* @__PURE__ */ jsx13(
1098
2324
  KeepSearchInput,
1099
2325
  {
1100
2326
  value: searchValue,
@@ -1104,7 +2330,7 @@ function KeepCollectionContent({
1104
2330
  }
1105
2331
  }
1106
2332
  ) : null,
1107
- enabled.sort ? /* @__PURE__ */ jsx11(
2333
+ enabled.sort ? /* @__PURE__ */ jsx13(
1108
2334
  KeepSortSelect,
1109
2335
  {
1110
2336
  value: sortToValue(sort),
@@ -1114,7 +2340,7 @@ function KeepCollectionContent({
1114
2340
  }
1115
2341
  }
1116
2342
  ) : null,
1117
- enabled.tagFilter ? /* @__PURE__ */ jsx11(
2343
+ enabled.tagFilter ? /* @__PURE__ */ jsx13(
1118
2344
  KeepTagFilter,
1119
2345
  {
1120
2346
  query,
@@ -1126,7 +2352,7 @@ function KeepCollectionContent({
1126
2352
  }
1127
2353
  ) : null
1128
2354
  ] }),
1129
- /* @__PURE__ */ jsx11(
2355
+ /* @__PURE__ */ jsx13(
1130
2356
  KeepList,
1131
2357
  {
1132
2358
  query: resolvedQuery,
@@ -1138,7 +2364,7 @@ function KeepCollectionContent({
1138
2364
  error
1139
2365
  }
1140
2366
  ),
1141
- enabled.pagination ? /* @__PURE__ */ jsx11(
2367
+ enabled.pagination ? /* @__PURE__ */ jsx13(
1142
2368
  KeepPagination,
1143
2369
  {
1144
2370
  totalCount: list.totalCount,
@@ -1147,7 +2373,7 @@ function KeepCollectionContent({
1147
2373
  onPageChange: (nextPage) => setPage(nextPage)
1148
2374
  }
1149
2375
  ) : null,
1150
- enabled.bulkActions ? /* @__PURE__ */ jsx11(KeepBulkActions, { query: resolvedQuery }) : null
2376
+ enabled.bulkActions ? /* @__PURE__ */ jsx13(KeepBulkActions, { query: resolvedQuery }) : null
1151
2377
  ]
1152
2378
  }
1153
2379
  );
@@ -1160,10 +2386,10 @@ function getCollectionState(list) {
1160
2386
  }
1161
2387
 
1162
2388
  // src/KeepLayout.tsx
1163
- import { jsx as jsx12 } from "react/jsx-runtime";
2389
+ import { jsx as jsx14 } from "react/jsx-runtime";
1164
2390
  function KeepLayout({ layout = "list", children, style, ...props }) {
1165
2391
  const layoutStyle = layout === "grid" ? { display: "grid", gap: "1rem", gridTemplateColumns: "repeat(auto-fit, minmax(16rem, 1fr))" } : layout === "compact" ? { display: "grid", gap: "0.5rem", gridTemplateColumns: "repeat(auto-fit, minmax(12rem, 1fr))" } : { display: "flex", flexDirection: "column", gap: "1rem" };
1166
- return /* @__PURE__ */ jsx12("div", { ...props, style: { ...layoutStyle, ...style }, "data-layout": layout, children });
2392
+ return /* @__PURE__ */ jsx14("div", { ...props, style: { ...layoutStyle, ...style }, "data-keepkit": "layout", "data-layout": layout, children });
1167
2393
  }
1168
2394
 
1169
2395
  // src/KeepNoteEditor.tsx
@@ -1173,9 +2399,9 @@ import {
1173
2399
  useCallback as useCallback2,
1174
2400
  useEffect as useEffect3,
1175
2401
  useRef as useRef3,
1176
- useState as useState6
2402
+ useState as useState7
1177
2403
  } from "react";
1178
- import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
2404
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1179
2405
  function KeepNoteEditor({
1180
2406
  item,
1181
2407
  label,
@@ -1192,10 +2418,11 @@ function KeepNoteEditor({
1192
2418
  }) {
1193
2419
  const defaultLabel = useUiLabel("note");
1194
2420
  const defaultSaveLabel = useUiLabel("saveNote");
2421
+ const errorLabel = useUiLabel("error");
1195
2422
  const itemState = useKeepItem3(item);
1196
2423
  const { error, isMutating, item: savedItem, updateNote } = itemState;
1197
2424
  const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
1198
- const [note, setNote] = useState6(item.note ?? "");
2425
+ const [note, setNote] = useState7(item.note ?? "");
1199
2426
  const baselineNote = savedItem?.note ?? item.note ?? "";
1200
2427
  const isDirty = note !== baselineNote;
1201
2428
  const lastSavedNoteRef = useRef3(void 0);
@@ -1225,10 +2452,10 @@ function KeepNoteEditor({
1225
2452
  error,
1226
2453
  save
1227
2454
  };
1228
- const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs7(Fragment5, { children: [
1229
- /* @__PURE__ */ jsxs7("label", { children: [
2455
+ const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs9(Fragment5, { children: [
2456
+ /* @__PURE__ */ jsxs9("label", { children: [
1230
2457
  label ?? defaultLabel,
1231
- /* @__PURE__ */ jsx13(
2458
+ /* @__PURE__ */ jsx15(
1232
2459
  "textarea",
1233
2460
  {
1234
2461
  value: note,
@@ -1244,24 +2471,28 @@ function KeepNoteEditor({
1244
2471
  }
1245
2472
  )
1246
2473
  ] }),
1247
- /* @__PURE__ */ jsx13("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
2474
+ /* @__PURE__ */ jsx15("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
1248
2475
  ] });
1249
2476
  const handleSubmit = (event) => {
1250
2477
  event.preventDefault();
1251
2478
  void save().catch(() => void 0);
1252
2479
  };
1253
2480
  if (!asChild) {
1254
- return /* @__PURE__ */ jsx13(
2481
+ return /* @__PURE__ */ jsxs9(
1255
2482
  "form",
1256
2483
  {
1257
2484
  ...formProps,
1258
2485
  className,
2486
+ "data-keepkit": "note-editor",
1259
2487
  onSubmit: handleSubmit,
1260
2488
  "aria-busy": isMutating || formProps["aria-busy"],
1261
- "data-state": isDirty ? "dirty" : "clean",
2489
+ "data-state": error ? "error" : isDirty ? "dirty" : "clean",
1262
2490
  "data-loading": isMutating ? "true" : void 0,
1263
2491
  "data-disabled": isMutating ? "true" : void 0,
1264
- children: body
2492
+ children: [
2493
+ body,
2494
+ error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: getErrorMessage3(error, errorLabel) }) : null
2495
+ ]
1265
2496
  }
1266
2497
  );
1267
2498
  }
@@ -1271,9 +2502,10 @@ function KeepNoteEditor({
1271
2502
  {
1272
2503
  ...formProps,
1273
2504
  className,
2505
+ "data-keepkit": "note-editor",
1274
2506
  onSubmit: handleSubmit,
1275
2507
  "aria-busy": isMutating || formProps["aria-busy"],
1276
- "data-state": isDirty ? "dirty" : "clean",
2508
+ "data-state": error ? "error" : isDirty ? "dirty" : "clean",
1277
2509
  "data-loading": isMutating ? "true" : void 0,
1278
2510
  "data-disabled": isMutating ? "true" : void 0
1279
2511
  },
@@ -1281,11 +2513,164 @@ function KeepNoteEditor({
1281
2513
  "KeepNoteEditor"
1282
2514
  );
1283
2515
  }
2516
+ function getErrorMessage3(error, fallback) {
2517
+ return error instanceof Error ? error.message : fallback;
2518
+ }
2519
+
2520
+ // src/KeepSyncRecoveryDialog.tsx
2521
+ import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
2522
+ import { useEffect as useEffect4, useState as useState8 } from "react";
2523
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2524
+ function KeepSyncRecoveryDialog({
2525
+ open,
2526
+ onOpenChange,
2527
+ conflicts,
2528
+ onManualMerge,
2529
+ backup,
2530
+ showBackupControls = true,
2531
+ title,
2532
+ children,
2533
+ className,
2534
+ ...props
2535
+ }) {
2536
+ const context = useKeepContext3();
2537
+ const closeLabel = useUiLabel("close");
2538
+ const defaultDialogTitle = useUiLabel("resolveSync");
2539
+ const dialogTitle = title ?? defaultDialogTitle;
2540
+ const conflictLabel = useUiLabel("syncConflict");
2541
+ const keepLocalLabel = useUiLabel("keepLocal");
2542
+ const useServerLabel = useUiLabel("useServer");
2543
+ const manualMergeLabel = useUiLabel("manualMerge");
2544
+ const backupRecoveryLabel = useUiLabel("backupRecovery");
2545
+ const backupRecoveryDescription = useUiLabel("backupRecoveryDescription");
2546
+ const errorLabel = useUiLabel("error");
2547
+ const conflictList = conflicts ?? context.syncState.conflicts ?? [];
2548
+ const hasRecovery = conflictList.length > 0 || context.syncState.status === "error" || Boolean(context.error);
2549
+ const [dismissed, setDismissed] = useState8(false);
2550
+ const [busyId, setBusyId] = useState8();
2551
+ const [error, setError] = useState8();
2552
+ useEffect4(() => {
2553
+ if (hasRecovery) setDismissed(false);
2554
+ }, [hasRecovery]);
2555
+ const isOpen = open ?? (hasRecovery && !dismissed);
2556
+ if (!isOpen) return null;
2557
+ const close = () => {
2558
+ setDismissed(true);
2559
+ onOpenChange?.(false);
2560
+ };
2561
+ async function resolve(conflict, resolution) {
2562
+ setError(void 0);
2563
+ setBusyId(conflict.id);
2564
+ try {
2565
+ const merged = resolution === "manual" ? await onManualMerge?.(conflict) : void 0;
2566
+ if (resolution === "manual" && !merged) throw new Error("A manual merge result is required.");
2567
+ await context.resolveSyncConflict(conflict.id, resolution, merged);
2568
+ } catch (cause) {
2569
+ setError(cause);
2570
+ } finally {
2571
+ setBusyId(void 0);
2572
+ }
2573
+ }
2574
+ return /* @__PURE__ */ jsxs10(
2575
+ "section",
2576
+ {
2577
+ ...props,
2578
+ className,
2579
+ role: "dialog",
2580
+ "aria-modal": "true",
2581
+ "aria-labelledby": "keepkit-sync-recovery-title",
2582
+ "data-keepkit": "sync-recovery",
2583
+ "data-state": conflictList.length > 0 ? "conflict" : "error",
2584
+ "data-loading": busyId !== void 0 ? "true" : void 0,
2585
+ children: [
2586
+ /* @__PURE__ */ jsxs10("header", { children: [
2587
+ /* @__PURE__ */ jsx16("h2", { id: "keepkit-sync-recovery-title", children: dialogTitle }),
2588
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: close, "aria-label": closeLabel, children: closeLabel })
2589
+ ] }),
2590
+ children,
2591
+ conflictList.length > 0 ? /* @__PURE__ */ jsxs10("div", { children: [
2592
+ /* @__PURE__ */ jsx16("p", { children: conflictLabel }),
2593
+ conflictList.map((conflict) => /* @__PURE__ */ jsxs10("article", { "data-conflict-id": conflict.id, children: [
2594
+ /* @__PURE__ */ jsx16("h3", { children: getMetaTitle(conflict.operation.item?.meta) ?? conflict.id }),
2595
+ /* @__PURE__ */ jsxs10("div", { children: [
2596
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => void resolve(conflict, "local"), disabled: busyId !== void 0, children: keepLocalLabel }),
2597
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => void resolve(conflict, "remote"), disabled: busyId !== void 0, children: useServerLabel }),
2598
+ /* @__PURE__ */ jsx16(
2599
+ "button",
2600
+ {
2601
+ type: "button",
2602
+ onClick: () => void resolve(conflict, "manual"),
2603
+ disabled: busyId !== void 0 || !onManualMerge,
2604
+ children: manualMergeLabel
2605
+ }
2606
+ )
2607
+ ] })
2608
+ ] }, conflict.id))
2609
+ ] }) : null,
2610
+ context.syncState.status === "error" || context.error ? /* @__PURE__ */ jsxs10("section", { "data-recovery": "backup", children: [
2611
+ /* @__PURE__ */ jsx16("h3", { children: backupRecoveryLabel }),
2612
+ /* @__PURE__ */ jsx16("p", { children: backupRecoveryDescription }),
2613
+ backup ?? (showBackupControls ? /* @__PURE__ */ jsx16(KeepBackup, {}) : null)
2614
+ ] }) : null,
2615
+ error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: error instanceof Error ? error.message : errorLabel }) : null
2616
+ ]
2617
+ }
2618
+ );
2619
+ }
2620
+
2621
+ // src/KeepSyncStatusBanner.tsx
2622
+ import { useKeepContext as useKeepContext4 } from "@keepkit/core/react";
2623
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2624
+ function KeepSyncStatusBanner({
2625
+ onRetry,
2626
+ onResolveConflicts,
2627
+ children,
2628
+ className,
2629
+ ...props
2630
+ }) {
2631
+ const context = useKeepContext4();
2632
+ const retryLabel = useUiLabel("retrySync");
2633
+ const resolveLabel = useUiLabel("resolveSync");
2634
+ const conflictLabel = useUiLabel("syncConflict");
2635
+ const pendingLabel = useUiLabel("syncPending");
2636
+ const syncedLabel = useUiLabel("syncSynced");
2637
+ const status = context.syncState.status;
2638
+ const hasConflicts = (context.syncState.conflicts?.length ?? 0) > 0 || context.syncState.conflictIds.length > 0;
2639
+ if (status === "idle" && !hasConflicts) return null;
2640
+ const message = children ?? (status === "error" ? getErrorMessage4(context.syncState.error) : status === "conflict" || hasConflicts ? conflictLabel : status === "pending" || status === "syncing" ? pendingLabel : syncedLabel);
2641
+ const role = status === "error" || status === "conflict" || hasConflicts ? "alert" : "status";
2642
+ const retry = async () => {
2643
+ if (onRetry) {
2644
+ await onRetry();
2645
+ return;
2646
+ }
2647
+ await context.flushSync();
2648
+ };
2649
+ return /* @__PURE__ */ jsxs11(
2650
+ "aside",
2651
+ {
2652
+ ...props,
2653
+ className,
2654
+ role: props.role ?? role,
2655
+ "aria-live": props["aria-live"] ?? "polite",
2656
+ "data-keepkit": "sync-status",
2657
+ "data-state": status,
2658
+ children: [
2659
+ /* @__PURE__ */ jsx17("p", { children: message }),
2660
+ status === "error" || status === "pending" || status === "syncing" ? /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void retry(), disabled: context.isMutating, children: retryLabel }) : null,
2661
+ hasConflicts ? /* @__PURE__ */ jsx17("button", { type: "button", onClick: onResolveConflicts, disabled: !onResolveConflicts, children: resolveLabel }) : null
2662
+ ]
2663
+ }
2664
+ );
2665
+ }
2666
+ function getErrorMessage4(error) {
2667
+ return error instanceof Error ? error.message : "Sync failed.";
2668
+ }
1284
2669
 
1285
2670
  // src/KeepTagEditor.tsx
1286
2671
  import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
1287
- import { useCallback as useCallback3, useEffect as useEffect4, useState as useState7 } from "react";
1288
- import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
2672
+ import { useCallback as useCallback3, useEffect as useEffect5, useState as useState9 } from "react";
2673
+ import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1289
2674
  function KeepTagEditor({
1290
2675
  item,
1291
2676
  availableTags = [],
@@ -1297,10 +2682,11 @@ function KeepTagEditor({
1297
2682
  const tagsLabel = useUiLabel("tagsToApply");
1298
2683
  const removeLabel = useUiLabel("remove");
1299
2684
  const applyTagsLabel = useUiLabel("applyTags");
2685
+ const errorLabel = useUiLabel("error");
1300
2686
  const itemState = useKeepItem4(item);
1301
- const [tags, setTags] = useState7(item.tags ?? []);
1302
- const [input, setInput] = useState7("");
1303
- useEffect4(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
2687
+ const [tags, setTags] = useState9(item.tags ?? []);
2688
+ const [input, setInput] = useState9("");
2689
+ useEffect5(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
1304
2690
  const save = useCallback3(async () => {
1305
2691
  const nextTags = normalizeUiTags(tags);
1306
2692
  try {
@@ -1316,10 +2702,10 @@ function KeepTagEditor({
1316
2702
  setTags(normalizeUiTags([...tags, tag]));
1317
2703
  setInput("");
1318
2704
  };
1319
- const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs8(Fragment6, { children: [
1320
- /* @__PURE__ */ jsxs8("label", { children: [
2705
+ const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs12(Fragment6, { children: [
2706
+ /* @__PURE__ */ jsxs12("label", { children: [
1321
2707
  tagsLabel,
1322
- /* @__PURE__ */ jsx14(
2708
+ /* @__PURE__ */ jsx18(
1323
2709
  "input",
1324
2710
  {
1325
2711
  value: input,
@@ -1338,14 +2724,14 @@ function KeepTagEditor({
1338
2724
  }
1339
2725
  )
1340
2726
  ] }),
1341
- availableTags.length > 0 ? /* @__PURE__ */ jsx14("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx14("option", { value: tag }, tag)) }) : null,
1342
- /* @__PURE__ */ jsx14("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs8("li", { children: [
2727
+ availableTags.length > 0 ? /* @__PURE__ */ jsx18("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx18("option", { value: tag }, tag)) }) : null,
2728
+ /* @__PURE__ */ jsx18("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs12("li", { children: [
1343
2729
  tag,
1344
- /* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
2730
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
1345
2731
  ] }, tag)) }),
1346
- /* @__PURE__ */ jsx14("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
2732
+ /* @__PURE__ */ jsx18("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
1347
2733
  ] });
1348
- return /* @__PURE__ */ jsx14(
2734
+ return /* @__PURE__ */ jsxs12(
1349
2735
  "form",
1350
2736
  {
1351
2737
  ...props,
@@ -1354,32 +2740,39 @@ function KeepTagEditor({
1354
2740
  void save().catch(() => void 0);
1355
2741
  },
1356
2742
  "aria-busy": itemState.isMutating || props["aria-busy"],
1357
- "data-state": itemState.isMutating ? "saving" : "idle",
2743
+ "data-keepkit": "tag-editor",
2744
+ "data-state": itemState.error ? "error" : itemState.isMutating ? "saving" : "idle",
1358
2745
  "data-loading": itemState.isMutating ? "true" : void 0,
1359
2746
  "data-disabled": itemState.isMutating ? "true" : void 0,
1360
- children: body
2747
+ children: [
2748
+ body,
2749
+ itemState.error ? /* @__PURE__ */ jsx18("p", { role: "alert", children: getErrorMessage5(itemState.error, errorLabel) }) : null
2750
+ ]
1361
2751
  }
1362
2752
  );
1363
2753
  }
2754
+ function getErrorMessage5(error, fallback) {
2755
+ return error instanceof Error ? error.message : fallback;
2756
+ }
1364
2757
 
1365
2758
  // src/KeepUndo.tsx
1366
- import { useKeepContext as useKeepContext2 } from "@keepkit/core/react";
1367
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
2759
+ import { useKeepContext as useKeepContext5 } from "@keepkit/core/react";
2760
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1368
2761
  function KeepUndo({ children, label, ...props }) {
1369
- const context = useKeepContext2();
2762
+ const context = useKeepContext5();
1370
2763
  const message = useUiLabel("undoAvailable");
1371
2764
  const undoLabel = useUiLabel("undo");
1372
2765
  if (!context.undo.canUndo) return null;
1373
- return /* @__PURE__ */ jsxs9("div", { ...props, role: "status", "aria-live": "polite", "data-state": "available", children: [
2766
+ return /* @__PURE__ */ jsxs13("div", { ...props, role: "status", "aria-live": "polite", "data-keepkit": "undo", "data-state": "available", children: [
1374
2767
  children ?? message,
1375
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => void context.undoLastRemoval(), children: label ?? undoLabel })
2768
+ /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => void context.undoLastRemoval(), children: label ?? undoLabel })
1376
2769
  ] });
1377
2770
  }
1378
2771
 
1379
2772
  // src/status.tsx
1380
- import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
1381
- import { isValidElement as isValidElement6, useEffect as useEffect5, useRef as useRef4, useState as useState8 } from "react";
1382
- import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2773
+ import { useKeepContext as useKeepContext6 } from "@keepkit/core/react";
2774
+ import { isValidElement as isValidElement6, useEffect as useEffect6, useRef as useRef4, useState as useState10 } from "react";
2775
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1383
2776
  function KeepEmptyState({
1384
2777
  title,
1385
2778
  description,
@@ -1391,12 +2784,18 @@ function KeepEmptyState({
1391
2784
  }) {
1392
2785
  const defaultTitle = useUiLabel("noItems").replace(/\.$/, "");
1393
2786
  const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
1394
- const body = contentChildren ?? /* @__PURE__ */ jsxs10(Fragment7, { children: [
1395
- /* @__PURE__ */ jsx16("h2", { children: title ?? defaultTitle }),
1396
- description ? /* @__PURE__ */ jsx16("p", { children: description }) : null,
2787
+ const body = contentChildren ?? /* @__PURE__ */ jsxs14(Fragment7, { children: [
2788
+ /* @__PURE__ */ jsx20("h2", { children: title ?? defaultTitle }),
2789
+ description ? /* @__PURE__ */ jsx20("p", { children: description }) : null,
1397
2790
  action
1398
2791
  ] });
1399
- return renderRoot(asChild, children, { ...rootProps, className, "data-state": "empty" }, body, "KeepEmptyState");
2792
+ return renderRoot(
2793
+ asChild,
2794
+ children,
2795
+ { ...rootProps, className, "data-keepkit": "empty-state", "data-state": "empty" },
2796
+ body,
2797
+ "KeepEmptyState"
2798
+ );
1400
2799
  }
1401
2800
  function KeepStatus({
1402
2801
  status,
@@ -1407,10 +2806,10 @@ function KeepStatus({
1407
2806
  className,
1408
2807
  ...rootProps
1409
2808
  }) {
1410
- const context = useKeepContext3();
2809
+ const context = useKeepContext6();
1411
2810
  const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
1412
2811
  const resolvedStatus = status ?? getDerivedStatus(context);
1413
- const defaultLabel = useUiLabel(getStatusLabelKey2(resolvedStatus));
2812
+ const defaultLabel = useUiLabel(getStatusLabelKey3(resolvedStatus));
1414
2813
  const state = {
1415
2814
  status: resolvedStatus,
1416
2815
  error: context.error,
@@ -1425,6 +2824,7 @@ function KeepStatus({
1425
2824
  {
1426
2825
  ...rootProps,
1427
2826
  className,
2827
+ "data-keepkit": "status",
1428
2828
  role,
1429
2829
  "aria-live": rootProps["aria-live"] ?? "polite",
1430
2830
  "data-state": resolvedStatus,
@@ -1435,13 +2835,13 @@ function KeepStatus({
1435
2835
  );
1436
2836
  }
1437
2837
  function KeepAnnouncements({ messages, ...props }) {
1438
- const context = useKeepContext3();
2838
+ const context = useKeepContext6();
1439
2839
  const savedMessage = useUiLabel("savedMessage", messages?.save);
1440
2840
  const removedMessage = useUiLabel("removedMessage", messages?.remove);
1441
2841
  const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
1442
- const [message, setMessage] = useState8("");
2842
+ const [message, setMessage] = useState10("");
1443
2843
  const lastChangeRef = useRef4(void 0);
1444
- useEffect5(() => {
2844
+ useEffect6(() => {
1445
2845
  const change = context.lastChange;
1446
2846
  if (!change || change === lastChangeRef.current) return;
1447
2847
  lastChangeRef.current = change;
@@ -1449,13 +2849,14 @@ function KeepAnnouncements({ messages, ...props }) {
1449
2849
  else if (change.action === "remove" || change.action === "removeBatch") setMessage(removedMessage);
1450
2850
  else if (change.action === "updateNote") setMessage(noteSavedMessage);
1451
2851
  }, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);
1452
- return /* @__PURE__ */ jsx16(
2852
+ return /* @__PURE__ */ jsx20(
1453
2853
  "div",
1454
2854
  {
1455
2855
  ...props,
1456
2856
  role: props.role ?? "status",
1457
2857
  "aria-live": props["aria-live"] ?? "polite",
1458
2858
  "aria-atomic": "true",
2859
+ "data-keepkit": "announcements",
1459
2860
  "data-state": "announcing",
1460
2861
  children: message
1461
2862
  }
@@ -1470,7 +2871,7 @@ function getDerivedStatus(context) {
1470
2871
  if (context.isHydrated && context.items.length === 0) return "empty";
1471
2872
  return "idle";
1472
2873
  }
1473
- function getStatusLabelKey2(status) {
2874
+ function getStatusLabelKey3(status) {
1474
2875
  if (status === "empty") return "noItems";
1475
2876
  if (status === "loading") return "loadingItems";
1476
2877
  if (status === "error") return "error";
@@ -1479,11 +2880,64 @@ function getStatusLabelKey2(status) {
1479
2880
  return "saved";
1480
2881
  }
1481
2882
 
2883
+ // src/theme.tsx
2884
+ import { cloneElement as cloneElement2, isValidElement as isValidElement7 } from "react";
2885
+ import { jsx as jsx21 } from "react/jsx-runtime";
2886
+ function KeepThemeProvider({
2887
+ children,
2888
+ theme = "default",
2889
+ mode = "system",
2890
+ density = "comfortable",
2891
+ radius = "medium",
2892
+ accentColor,
2893
+ highContrast = false,
2894
+ reducedMotion = false,
2895
+ variables,
2896
+ style,
2897
+ className,
2898
+ asChild = false,
2899
+ ...props
2900
+ }) {
2901
+ const themeClassName = [
2902
+ "keep-theme",
2903
+ `keep-theme--${theme}`,
2904
+ `keep-theme--${mode}`,
2905
+ `keep-theme--density-${density}`,
2906
+ `keep-theme--radius-${radius}`,
2907
+ className
2908
+ ].filter(Boolean).join(" ");
2909
+ const themeStyle = {
2910
+ ...style,
2911
+ ...accentColor && !highContrast ? { "--keep-accent": accentColor, "--keep-primary": accentColor } : {},
2912
+ ...variables
2913
+ };
2914
+ const rootProps = {
2915
+ ...props,
2916
+ className: themeClassName,
2917
+ style: themeStyle,
2918
+ "data-keep-theme": theme,
2919
+ "data-theme": theme,
2920
+ "data-mode": mode,
2921
+ "data-density": density,
2922
+ "data-radius": radius,
2923
+ "data-accent-color": accentColor,
2924
+ "data-high-contrast": highContrast ? "true" : void 0,
2925
+ "data-reduced-motion": reducedMotion ? "true" : void 0
2926
+ };
2927
+ if (asChild) {
2928
+ if (!isValidElement7(children))
2929
+ throw new Error("KeepThemeProvider with asChild requires a single React element child.");
2930
+ return cloneElement2(children, rootProps);
2931
+ }
2932
+ return /* @__PURE__ */ jsx21("div", { ...rootProps, children });
2933
+ }
2934
+
1482
2935
  // src/index.tsx
2936
+ import { createAuthenticatedSyncKit } from "@keepkit/core/core";
1483
2937
  import {
1484
2938
  KeepErrorBoundary as KeepErrorBoundary3,
1485
2939
  KeepProvider,
1486
- useKeepContext as useKeepContext4,
2940
+ useKeepContext as useKeepContext7,
1487
2941
  useKeepItem as useKeepItem5,
1488
2942
  useKeepList as useKeepList5,
1489
2943
  useKeepShortcut
@@ -1498,36 +2952,90 @@ import {
1498
2952
  LocalStorageSyncQueueAdapter,
1499
2953
  SyncStorageAdapter
1500
2954
  } from "@keepkit/core/storage";
1501
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2955
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1502
2956
  function KeepKitProvider({
1503
2957
  labels,
1504
2958
  locale,
1505
2959
  labelResolver,
2960
+ theme,
2961
+ mode,
2962
+ density,
2963
+ radius,
2964
+ accentColor,
2965
+ highContrast,
2966
+ reducedMotion,
2967
+ variables,
2968
+ className: themeClassName,
2969
+ style: themeStyle,
2970
+ asChild: themeAsChild,
1506
2971
  children,
1507
2972
  ...providerProps
1508
2973
  }) {
1509
- return /* @__PURE__ */ jsx17(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsxs11(CoreKeepProvider, { ...providerProps, children: [
1510
- children,
1511
- /* @__PURE__ */ jsx17(KeepAnnouncements, {})
1512
- ] }) });
2974
+ return /* @__PURE__ */ jsx22(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsx22(
2975
+ KeepThemeProvider,
2976
+ {
2977
+ theme,
2978
+ mode,
2979
+ density,
2980
+ radius,
2981
+ accentColor,
2982
+ highContrast,
2983
+ reducedMotion,
2984
+ variables,
2985
+ className: themeClassName,
2986
+ style: themeStyle,
2987
+ asChild: themeAsChild,
2988
+ children: /* @__PURE__ */ jsxs15(CoreKeepProvider, { ...providerProps, children: [
2989
+ children,
2990
+ /* @__PURE__ */ jsx22(KeepAnnouncements, {})
2991
+ ] })
2992
+ }
2993
+ ) });
1513
2994
  }
1514
2995
  function createKeepKit(options = {}) {
1515
- const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;
2996
+ const {
2997
+ labels,
2998
+ locale,
2999
+ labelResolver,
3000
+ theme,
3001
+ mode,
3002
+ density,
3003
+ radius,
3004
+ accentColor,
3005
+ highContrast,
3006
+ reducedMotion,
3007
+ variables,
3008
+ themeClassName,
3009
+ themeStyle,
3010
+ getTitle,
3011
+ getImageProps,
3012
+ ...coreOptions
3013
+ } = options;
1516
3014
  const coreKit = createCoreKeepKit(coreOptions);
1517
3015
  return {
1518
- Provider: (props) => /* @__PURE__ */ jsx17(
3016
+ Provider: (props) => /* @__PURE__ */ jsx22(
1519
3017
  KeepKitProvider,
1520
3018
  {
1521
3019
  ...coreOptions,
1522
3020
  labels,
1523
3021
  locale,
1524
3022
  labelResolver,
3023
+ theme,
3024
+ mode,
3025
+ density,
3026
+ radius,
3027
+ accentColor,
3028
+ highContrast,
3029
+ reducedMotion,
3030
+ variables,
3031
+ className: themeClassName,
3032
+ style: themeStyle,
1525
3033
  ...props
1526
3034
  }
1527
3035
  ),
1528
- Button: (props) => /* @__PURE__ */ jsx17(KeepButton, { ...props }),
1529
- Backup: (props) => /* @__PURE__ */ jsx17(KeepBackup, { ...props }),
1530
- Collection: (props) => /* @__PURE__ */ jsx17(
3036
+ Button: (props) => /* @__PURE__ */ jsx22(KeepButton, { ...props }),
3037
+ Backup: (props) => /* @__PURE__ */ jsx22(KeepBackup, { ...props }),
3038
+ Collection: (props) => /* @__PURE__ */ jsx22(
1531
3039
  KeepCollection,
1532
3040
  {
1533
3041
  ...props,
@@ -1558,22 +3066,29 @@ export {
1558
3066
  KeepErrorBoundary3 as KeepErrorBoundary,
1559
3067
  KeepItemCard,
1560
3068
  KeepItemCheckbox,
3069
+ KeepItemStatusBadge,
1561
3070
  KeepKitProvider,
1562
3071
  KeepLayout,
1563
3072
  KeepList,
1564
3073
  KeepNoteEditor,
1565
3074
  KeepPagination,
1566
3075
  KeepProvider,
3076
+ KeepPruneStaleButton,
1567
3077
  KeepSearchInput,
1568
3078
  KeepSortSelect,
3079
+ KeepStaleNotice,
1569
3080
  KeepStatus,
3081
+ KeepSyncRecoveryDialog,
3082
+ KeepSyncStatusBanner,
1570
3083
  KeepTagEditor,
1571
3084
  KeepTagFilter,
3085
+ KeepThemeProvider,
1572
3086
  KeepUiProvider,
1573
3087
  KeepUndo,
1574
3088
  LocalStorageAdapter,
1575
3089
  LocalStorageSyncQueueAdapter,
1576
3090
  SyncStorageAdapter,
3091
+ createAuthenticatedSyncKit,
1577
3092
  createBrowserStorageAdapter,
1578
3093
  createKeepKit,
1579
3094
  createNextPagesRouterAdapter,
@@ -1581,7 +3096,7 @@ export {
1581
3096
  getKeepLocaleLabels,
1582
3097
  isAllSelected,
1583
3098
  toggleSelectAll,
1584
- useKeepContext4 as useKeepContext,
3099
+ useKeepContext7 as useKeepContext,
1585
3100
  useKeepItem5 as useKeepItem,
1586
3101
  useKeepList5 as useKeepList,
1587
3102
  useKeepShortcut,