@keepkit/ui 0.9.0 → 0.10.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
@@ -6,12 +6,176 @@ import {
6
6
  createKeepKit as createCoreKeepKit
7
7
  } from "@keepkit/core/react";
8
8
 
9
+ // src/KeepBackup.tsx
10
+ import { useKeepContext } from "@keepkit/core/react";
11
+ import { useRef, useState } from "react";
12
+
13
+ // src/ui-context.tsx
14
+ import { createContext, useContext, useMemo } from "react";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var DEFAULT_LABELS = {
17
+ save: "Save",
18
+ saved: "Saved",
19
+ remove: "Remove",
20
+ loading: "Loading\u2026",
21
+ saving: "Saving\u2026",
22
+ syncing: "Syncing\u2026",
23
+ error: "Something went wrong.",
24
+ allTags: "All",
25
+ filterTags: "Filter saved items by tag",
26
+ note: "Note",
27
+ saveNote: "Save note",
28
+ noItems: "No saved items.",
29
+ loadingItems: "Loading saved items\u2026",
30
+ errorItems: "Could not load saved items.",
31
+ search: "Search saved items",
32
+ sort: "Sort saved items",
33
+ newest: "Newest first",
34
+ oldest: "Oldest first",
35
+ savedNewest: "Saved newest first",
36
+ savedOldest: "Saved oldest first",
37
+ updatedNewest: "Updated newest first",
38
+ updatedOldest: "Updated oldest first",
39
+ previousPage: "Previous page",
40
+ nextPage: "Next page",
41
+ pagination: "Pagination",
42
+ page: "Page",
43
+ selectItems: "Select saved items",
44
+ selectedCount: "selected",
45
+ deleteSelected: "Delete selected",
46
+ tagsToApply: "Tags to apply",
47
+ applyTags: "Apply tags",
48
+ savedMessage: "Item saved.",
49
+ removedMessage: "Item removed.",
50
+ noteSavedMessage: "Note saved.",
51
+ exportData: "Export JSON",
52
+ importData: "Import JSON",
53
+ importMode: "Import mode",
54
+ merge: "Merge",
55
+ replace: "Replace",
56
+ importedCount: "items imported",
57
+ failedCount: "items failed",
58
+ storageQuotaError: "Storage is full. Free space and try again.",
59
+ statusExpired: "Expired",
60
+ statusRemoved: "Removed",
61
+ statusDeleted: "Deleted",
62
+ statusPrivate: "Private",
63
+ statusUnknown: "Unavailable"
64
+ };
65
+ var KeepUiLabelsContext = createContext({ labels: DEFAULT_LABELS });
66
+ function KeepUiProvider({ labels, locale, labelResolver, children }) {
67
+ const value = useMemo(() => {
68
+ const resolved = { ...DEFAULT_LABELS, ...labels };
69
+ return { locale, labels: resolved, labelResolver };
70
+ }, [labelResolver, labels, locale]);
71
+ return /* @__PURE__ */ jsx(KeepUiLabelsContext.Provider, { value, children });
72
+ }
73
+ function useKeepUiLabels() {
74
+ return useContext(KeepUiLabelsContext);
75
+ }
76
+ function useUiLabel(key, override) {
77
+ const context = useKeepUiLabels();
78
+ return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
79
+ }
80
+
81
+ // src/KeepBackup.tsx
82
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
83
+ function KeepBackup({
84
+ filename = "keepkit-backup.json",
85
+ onExport,
86
+ onImported,
87
+ ...props
88
+ }) {
89
+ const context = useKeepContext();
90
+ const exportLabel = useUiLabel("exportData");
91
+ const importLabel = useUiLabel("importData");
92
+ const importModeLabel = useUiLabel("importMode");
93
+ const mergeLabel = useUiLabel("merge");
94
+ const replaceLabel = useUiLabel("replace");
95
+ const importedCountLabel = useUiLabel("importedCount");
96
+ const failedCountLabel = useUiLabel("failedCount");
97
+ const quotaErrorLabel = useUiLabel("storageQuotaError");
98
+ const inputRef = useRef(null);
99
+ const [mode, setMode] = useState("merge");
100
+ const [result, setResult] = useState();
101
+ const [error, setError] = useState();
102
+ async function handleExport() {
103
+ setError(void 0);
104
+ try {
105
+ const data = await context.exportBackup();
106
+ onExport?.(data);
107
+ if (typeof document === "undefined") return;
108
+ const url = URL.createObjectURL(new Blob([data], { type: "application/json" }));
109
+ const anchor = document.createElement("a");
110
+ anchor.href = url;
111
+ anchor.download = filename;
112
+ anchor.click();
113
+ URL.revokeObjectURL(url);
114
+ } catch (cause) {
115
+ setError(cause);
116
+ }
117
+ }
118
+ async function handleImport(event) {
119
+ const file = event.currentTarget.files?.[0];
120
+ event.currentTarget.value = "";
121
+ if (!file) return;
122
+ setError(void 0);
123
+ setResult(void 0);
124
+ try {
125
+ const imported = await context.importBackup(await file.text(), { mode });
126
+ setResult(imported);
127
+ onImported?.(imported);
128
+ } catch (cause) {
129
+ setError(cause);
130
+ }
131
+ }
132
+ return /* @__PURE__ */ jsxs("section", { ...props, "data-state": error ? "error" : result ? "complete" : "idle", children: [
133
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => void handleExport(), disabled: context.isMutating, children: exportLabel }),
134
+ /* @__PURE__ */ jsxs("label", { children: [
135
+ importModeLabel,
136
+ /* @__PURE__ */ jsxs("select", { value: mode, onChange: (event) => setMode(event.currentTarget.value), children: [
137
+ /* @__PURE__ */ jsx2("option", { value: "merge", children: mergeLabel }),
138
+ /* @__PURE__ */ jsx2("option", { value: "replace", children: replaceLabel })
139
+ ] })
140
+ ] }),
141
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => inputRef.current?.click(), disabled: context.isMutating, children: importLabel }),
142
+ /* @__PURE__ */ jsx2(
143
+ "input",
144
+ {
145
+ ref: inputRef,
146
+ type: "file",
147
+ accept: "application/json,.json",
148
+ "aria-label": importLabel,
149
+ onChange: (event) => void handleImport(event)
150
+ }
151
+ ),
152
+ result ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
153
+ result.imported,
154
+ " ",
155
+ importedCountLabel,
156
+ "; ",
157
+ result.failed,
158
+ " ",
159
+ failedCountLabel
160
+ ] }) : null,
161
+ error ? /* @__PURE__ */ jsx2("p", { role: "alert", children: isQuotaError(error) ? quotaErrorLabel : getErrorMessage(error) }) : null
162
+ ] });
163
+ }
164
+ function isQuotaError(error) {
165
+ if (error instanceof Error && error.name === "KeepStorageQuotaError") return true;
166
+ if (error && typeof error === "object" && "cause" in error) return isQuotaError(error.cause);
167
+ return false;
168
+ }
169
+ function getErrorMessage(error) {
170
+ return error instanceof Error ? error.message : "Something went wrong.";
171
+ }
172
+
9
173
  // src/KeepBulkActions.tsx
10
174
  import { useKeepList } from "@keepkit/core/react";
11
- import { useState } from "react";
175
+ import { useState as useState2 } from "react";
12
176
 
13
177
  // src/KeepItemCheckbox.tsx
14
- import { jsx } from "react/jsx-runtime";
178
+ import { jsx as jsx3 } from "react/jsx-runtime";
15
179
  function KeepItemCheckbox({
16
180
  item,
17
181
  checked = false,
@@ -22,7 +186,7 @@ function KeepItemCheckbox({
22
186
  }) {
23
187
  const itemLabel = getItemLabel(item) ?? item.id;
24
188
  const accessibleLabel = ariaLabel ?? (typeof label === "string" ? label : itemLabel);
25
- return /* @__PURE__ */ jsx(
189
+ return /* @__PURE__ */ jsx3(
26
190
  "input",
27
191
  {
28
192
  ...props,
@@ -46,7 +210,7 @@ import {
46
210
  cloneElement,
47
211
  isValidElement
48
212
  } from "react";
49
- import { jsx as jsx2 } from "react/jsx-runtime";
213
+ import { jsx as jsx4 } from "react/jsx-runtime";
50
214
  function toKeepButtonItem(item) {
51
215
  return {
52
216
  id: item.id,
@@ -75,66 +239,11 @@ function renderRoot(asChild, child, props, body, componentName) {
75
239
  if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);
76
240
  return cloneElement(child, { ...props, children: body });
77
241
  }
78
- return /* @__PURE__ */ jsx2("div", { ...props, children: body });
79
- }
80
-
81
- // src/ui-context.tsx
82
- import { createContext, useContext, useMemo } from "react";
83
- import { jsx as jsx3 } from "react/jsx-runtime";
84
- var DEFAULT_LABELS = {
85
- save: "Save",
86
- saved: "Saved",
87
- remove: "Remove",
88
- loading: "Loading\u2026",
89
- saving: "Saving\u2026",
90
- syncing: "Syncing\u2026",
91
- error: "Something went wrong.",
92
- allTags: "All",
93
- filterTags: "Filter saved items by tag",
94
- note: "Note",
95
- saveNote: "Save note",
96
- noItems: "No saved items.",
97
- loadingItems: "Loading saved items\u2026",
98
- errorItems: "Could not load saved items.",
99
- search: "Search saved items",
100
- sort: "Sort saved items",
101
- newest: "Newest first",
102
- oldest: "Oldest first",
103
- savedNewest: "Saved newest first",
104
- savedOldest: "Saved oldest first",
105
- updatedNewest: "Updated newest first",
106
- updatedOldest: "Updated oldest first",
107
- previousPage: "Previous page",
108
- nextPage: "Next page",
109
- pagination: "Pagination",
110
- page: "Page",
111
- selectItems: "Select saved items",
112
- selectedCount: "selected",
113
- deleteSelected: "Delete selected",
114
- tagsToApply: "Tags to apply",
115
- applyTags: "Apply tags",
116
- savedMessage: "Item saved.",
117
- removedMessage: "Item removed.",
118
- noteSavedMessage: "Note saved."
119
- };
120
- var KeepUiLabelsContext = createContext({ labels: DEFAULT_LABELS });
121
- function KeepUiProvider({ labels, locale, labelResolver, children }) {
122
- const value = useMemo(() => {
123
- const resolved = { ...DEFAULT_LABELS, ...labels };
124
- return { locale, labels: resolved, labelResolver };
125
- }, [labelResolver, labels, locale]);
126
- return /* @__PURE__ */ jsx3(KeepUiLabelsContext.Provider, { value, children });
127
- }
128
- function useKeepUiLabels() {
129
- return useContext(KeepUiLabelsContext);
130
- }
131
- function useUiLabel(key, override) {
132
- const context = useKeepUiLabels();
133
- return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
242
+ return /* @__PURE__ */ jsx4("div", { ...props, children: body });
134
243
  }
135
244
 
136
245
  // src/KeepBulkActions.tsx
137
- import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
246
+ import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
138
247
  function isAllSelected(items, selectedIds) {
139
248
  if (items.length === 0) return false;
140
249
  const selected = new Set(selectedIds);
@@ -166,10 +275,10 @@ function KeepBulkActions({
166
275
  const tagsLabel = useUiLabel("tagsToApply");
167
276
  const applyTagsLabel = useUiLabel("applyTags");
168
277
  const list = useKeepList(query);
169
- const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);
278
+ const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState2(defaultSelectedIds);
170
279
  const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
171
280
  const selected = new Set(selectedIds);
172
- const [tagsInput, setTagsInput] = useState("");
281
+ const [tagsInput, setTagsInput] = useState2("");
173
282
  const setSelectedIds = (ids) => {
174
283
  if (controlledSelectedIds === void 0) setUncontrolledSelectedIds(ids);
175
284
  onSelectedIdsChange?.(ids);
@@ -204,17 +313,17 @@ function KeepBulkActions({
204
313
  updateTags,
205
314
  isMutating: list.isMutating
206
315
  };
207
- const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
208
- /* @__PURE__ */ jsxs("fieldset", { children: [
209
- /* @__PURE__ */ jsx4("legend", { children: selectItemsLabel }),
210
- /* @__PURE__ */ jsxs("label", { children: [
211
- /* @__PURE__ */ jsx4("input", { type: "checkbox", checked: allSelected, onChange: toggleAll, "aria-label": selectItemsLabel }),
316
+ const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs2(Fragment, { children: [
317
+ /* @__PURE__ */ jsxs2("fieldset", { children: [
318
+ /* @__PURE__ */ jsx5("legend", { children: selectItemsLabel }),
319
+ /* @__PURE__ */ jsxs2("label", { children: [
320
+ /* @__PURE__ */ jsx5("input", { type: "checkbox", checked: allSelected, onChange: toggleAll, "aria-label": selectItemsLabel }),
212
321
  selectedIds.length,
213
322
  " ",
214
323
  selectedCountLabel
215
324
  ] }),
216
- list.items.map((item) => /* @__PURE__ */ jsxs("span", { children: [
217
- /* @__PURE__ */ jsx4(
325
+ list.items.map((item) => /* @__PURE__ */ jsxs2("span", { children: [
326
+ /* @__PURE__ */ jsx5(
218
327
  KeepItemCheckbox,
219
328
  {
220
329
  item,
@@ -225,12 +334,12 @@ function KeepBulkActions({
225
334
  renderItem ? renderItem(item, selected.has(item.id)) : getMetaTitle(item.meta) ?? item.id
226
335
  ] }, item.id))
227
336
  ] }),
228
- /* @__PURE__ */ jsx4("button", { type: "button", onClick: () => void remove(), disabled: selectedIds.length === 0 || list.isMutating, children: deleteSelectedLabel }),
229
- /* @__PURE__ */ jsxs("label", { children: [
337
+ /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => void remove(), disabled: selectedIds.length === 0 || list.isMutating, children: deleteSelectedLabel }),
338
+ /* @__PURE__ */ jsxs2("label", { children: [
230
339
  tagsLabel,
231
- /* @__PURE__ */ jsx4("input", { value: tagsInput, onChange: (event) => setTagsInput(event.currentTarget.value) })
340
+ /* @__PURE__ */ jsx5("input", { value: tagsInput, onChange: (event) => setTagsInput(event.currentTarget.value) })
232
341
  ] }),
233
- /* @__PURE__ */ jsx4(
342
+ /* @__PURE__ */ jsx5(
234
343
  "button",
235
344
  {
236
345
  type: "button",
@@ -240,7 +349,7 @@ function KeepBulkActions({
240
349
  }
241
350
  )
242
351
  ] });
243
- return /* @__PURE__ */ jsx4(
352
+ return /* @__PURE__ */ jsx5(
244
353
  "section",
245
354
  {
246
355
  ...props,
@@ -257,7 +366,7 @@ import {
257
366
  KeepButton as CoreKeepButton,
258
367
  useKeepItem
259
368
  } from "@keepkit/core/react";
260
- import { Fragment as Fragment2, jsx as jsx5 } from "react/jsx-runtime";
369
+ import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
261
370
  function KeepButton({ labels, ...props }) {
262
371
  const saveLabel = useUiLabel("save", typeof labels?.unsaved === "string" ? labels.unsaved : void 0);
263
372
  const savedLabel = useUiLabel("saved", typeof labels?.saved === "string" ? labels.saved : void 0);
@@ -280,13 +389,13 @@ function KeepButton({ labels, ...props }) {
280
389
  savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
281
390
  unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
282
391
  };
283
- if (!customStateLabel) return /* @__PURE__ */ jsx5(CoreKeepButton, { ...sharedProps });
284
- return /* @__PURE__ */ jsx5(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx5(Fragment2, { children: getStateContent(state) }) });
392
+ if (!customStateLabel) return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps });
393
+ return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx6(Fragment2, { children: getStateContent(state) }) });
285
394
  }
286
395
 
287
396
  // src/KeepCollection.tsx
288
397
  import { KeepErrorBoundary as KeepErrorBoundary2, useKeepList as useKeepList4 } from "@keepkit/core/react";
289
- import { useMemo as useMemo3, useState as useState4 } from "react";
398
+ import { useMemo as useMemo3, useState as useState5 } from "react";
290
399
 
291
400
  // src/KeepList.tsx
292
401
  import {
@@ -297,8 +406,10 @@ import { isValidElement as isValidElement3 } from "react";
297
406
 
298
407
  // src/KeepItemCard.tsx
299
408
  import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
300
- import { isValidElement as isValidElement2 } from "react";
301
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
409
+ import {
410
+ isValidElement as isValidElement2
411
+ } from "react";
412
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
302
413
  function KeepItemCard({
303
414
  item,
304
415
  title,
@@ -315,6 +426,12 @@ function KeepItemCard({
315
426
  showSaveButton = true,
316
427
  saveButtonLabels,
317
428
  asChild = false,
429
+ href: hrefOption,
430
+ onOpen,
431
+ linkTarget = "title",
432
+ linkComponent: LinkComponent,
433
+ linkTargetAttribute,
434
+ linkRel,
318
435
  className,
319
436
  ...rootProps
320
437
  }) {
@@ -327,10 +444,27 @@ function KeepItemCard({
327
444
  isSaved: itemState.isSaved,
328
445
  isMutating: itemState.isMutating,
329
446
  error: itemState.error,
330
- remove: itemState.remove
447
+ remove: itemState.remove,
448
+ status: item.status
331
449
  };
332
450
  const resolvedTitle = typeof title === "function" ? title(item) : title ?? getTitle?.(item) ?? getMetaTitle(item.meta) ?? item.id;
333
451
  const imageProps = getImageProps?.(item, resolvedTitle);
452
+ const href = typeof hrefOption === "function" ? hrefOption(item) : hrefOption;
453
+ const isAvailable = item.status === void 0 || item.status === "available";
454
+ const statusLabelKey = item.status && item.status !== "available" ? getStatusLabelKey(item.status) : "statusUnknown";
455
+ const unavailableLabel = useUiLabel(statusLabelKey);
456
+ const statusLabel = item.status && item.status !== "available" ? unavailableLabel : void 0;
457
+ function renderLink(content) {
458
+ if (!href || !isAvailable) return content;
459
+ const linkProps = {
460
+ href,
461
+ target: linkTargetAttribute,
462
+ rel: linkRel,
463
+ onClick: (event) => onOpen?.(item, event),
464
+ children: content
465
+ };
466
+ return LinkComponent ? /* @__PURE__ */ jsx7(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx7("a", { ...linkProps });
467
+ }
334
468
  async function handleRemove() {
335
469
  try {
336
470
  await itemState.remove();
@@ -339,10 +473,11 @@ function KeepItemCard({
339
473
  onRemoveError?.(error);
340
474
  }
341
475
  }
342
- const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
343
- imageProps ? renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ?? (ImageComponent ? /* @__PURE__ */ jsx6(ImageComponent, { ...imageProps, alt: imageAlt ?? imageProps.alt }) : /* @__PURE__ */ jsx6("img", { ...imageProps, alt: imageAlt ?? imageProps.alt })) : null,
344
- /* @__PURE__ */ jsx6("h3", { children: resolvedTitle }),
345
- showSaveButton ? /* @__PURE__ */ jsx6(
476
+ const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs3(Fragment3, { children: [
477
+ 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,
478
+ /* @__PURE__ */ jsx7("h3", { children: linkTarget === "title" ? renderLink(resolvedTitle) : resolvedTitle }),
479
+ statusLabel ? /* @__PURE__ */ jsx7("p", { "data-status": item.status, children: statusLabel }) : null,
480
+ showSaveButton ? /* @__PURE__ */ jsx7(
346
481
  KeepButton,
347
482
  {
348
483
  item: toKeepButtonItem(item),
@@ -350,8 +485,9 @@ function KeepItemCard({
350
485
  getAriaLabel: (buttonState) => `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`
351
486
  }
352
487
  ) : null,
353
- /* @__PURE__ */ jsx6("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel })
488
+ /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel })
354
489
  ] });
490
+ const linkedBody = linkTarget === "card" ? renderLink(body) : body;
355
491
  return renderRoot(
356
492
  asChild,
357
493
  isValidElement2(children) ? children : void 0,
@@ -360,20 +496,35 @@ function KeepItemCard({
360
496
  className,
361
497
  "aria-busy": itemState.isMutating || rootProps["aria-busy"],
362
498
  "data-state": itemState.isSaved ? "saved" : "unsaved",
499
+ "data-status": item.status ?? "available",
363
500
  "data-loading": itemState.isMutating ? "true" : void 0
364
501
  },
365
- body,
502
+ linkedBody,
366
503
  "KeepItemCard"
367
504
  );
368
505
  }
506
+ function getStatusLabelKey(status) {
507
+ switch (status) {
508
+ case "expired":
509
+ return "statusExpired";
510
+ case "removed":
511
+ return "statusRemoved";
512
+ case "deleted":
513
+ return "statusDeleted";
514
+ case "private":
515
+ return "statusPrivate";
516
+ default:
517
+ return "statusUnknown";
518
+ }
519
+ }
369
520
 
370
521
  // src/KeepList.tsx
371
- import { jsx as jsx7 } from "react/jsx-runtime";
522
+ import { jsx as jsx8 } from "react/jsx-runtime";
372
523
  function KeepList(props) {
373
524
  const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
374
- const content = /* @__PURE__ */ jsx7(KeepListContent, { ...listProps });
525
+ const content = /* @__PURE__ */ jsx8(KeepListContent, { ...listProps });
375
526
  if (fallback === void 0 && onBoundaryError === void 0) return content;
376
- return /* @__PURE__ */ jsx7(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
527
+ return /* @__PURE__ */ jsx8(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
377
528
  }
378
529
  function KeepListContent({
379
530
  query,
@@ -425,15 +576,15 @@ function getListBody(state, options) {
425
576
  if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);
426
577
  if (typeof options.children === "function") return options.children(state);
427
578
  if (options.children !== void 0 && !isValidElement3(options.children)) return options.children;
428
- return /* @__PURE__ */ jsx7("ul", { children: state.items.map(
429
- (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsx7(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
579
+ return /* @__PURE__ */ jsx8("ul", { children: state.items.map(
580
+ (item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
430
581
  ) });
431
582
  }
432
583
 
433
584
  // src/KeepTagFilter.tsx
434
585
  import { useKeepList as useKeepList3 } from "@keepkit/core/react";
435
- import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState2 } from "react";
436
- import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
586
+ import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState3 } from "react";
587
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
437
588
  function KeepTagFilter({
438
589
  query,
439
590
  value: controlledValue,
@@ -451,7 +602,7 @@ function KeepTagFilter({
451
602
  }) {
452
603
  const uiAllLabel = useUiLabel("allTags");
453
604
  const uiAriaLabel = useUiLabel("filterTags");
454
- const [uncontrolledValue, setUncontrolledValue] = useState2(defaultValue);
605
+ const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
455
606
  const resolvedValue = controlledValue ?? uncontrolledValue;
456
607
  const list = useKeepList3({
457
608
  ...query,
@@ -470,12 +621,12 @@ function KeepTagFilter({
470
621
  [list.tagCounts, list.tags, resolvedValue, select]
471
622
  );
472
623
  const contentChildren = asChild && isValidElement4(children) ? void 0 : children;
473
- const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs3("fieldset", { children: [
474
- /* @__PURE__ */ jsx8("legend", { children: ariaLabel ?? uiAriaLabel }),
475
- /* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
476
- list.tags.map((tag) => /* @__PURE__ */ jsxs3("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
624
+ const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs4("fieldset", { children: [
625
+ /* @__PURE__ */ jsx9("legend", { children: ariaLabel ?? uiAriaLabel }),
626
+ /* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
627
+ list.tags.map((tag) => /* @__PURE__ */ jsxs4("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
477
628
  renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag,
478
- /* @__PURE__ */ jsxs3("span", { children: [
629
+ /* @__PURE__ */ jsxs4("span", { children: [
479
630
  " (",
480
631
  list.tagCounts[tag] ?? 0,
481
632
  ")"
@@ -497,8 +648,8 @@ function KeepTagFilter({
497
648
  }
498
649
 
499
650
  // src/query-controls.tsx
500
- import { useEffect, useState as useState3 } from "react";
501
- import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
651
+ import { useEffect, useState as useState4 } from "react";
652
+ import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
502
653
  function KeepSearchInput({
503
654
  value: controlledValue,
504
655
  defaultValue = "",
@@ -509,7 +660,7 @@ function KeepSearchInput({
509
660
  ...props
510
661
  }) {
511
662
  const label = useUiLabel("search");
512
- const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
663
+ const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
513
664
  const value = controlledValue ?? uncontrolledValue;
514
665
  useEffect(() => {
515
666
  if (!onValueChange) return;
@@ -520,7 +671,7 @@ function KeepSearchInput({
520
671
  const timer = window.setTimeout(() => onValueChange(value), debounceMs);
521
672
  return () => window.clearTimeout(timer);
522
673
  }, [debounceMs, onValueChange, value]);
523
- return /* @__PURE__ */ jsx9(
674
+ return /* @__PURE__ */ jsx10(
524
675
  "input",
525
676
  {
526
677
  ...props,
@@ -550,15 +701,15 @@ function KeepSortSelect({
550
701
  const updatedOldestLabel = useUiLabel("updatedOldest");
551
702
  const savedNewestLabel = useUiLabel("savedNewest");
552
703
  const savedOldestLabel = useUiLabel("savedOldest");
553
- const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
704
+ const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
554
705
  const value = controlledValue ?? uncontrolledValue;
555
- const options = children ?? /* @__PURE__ */ jsxs4(Fragment4, { children: [
556
- /* @__PURE__ */ jsx9("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
557
- /* @__PURE__ */ jsx9("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
558
- /* @__PURE__ */ jsx9("option", { value: "savedAt:desc", children: savedNewestLabel }),
559
- /* @__PURE__ */ jsx9("option", { value: "savedAt:asc", children: savedOldestLabel })
706
+ const options = children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
707
+ /* @__PURE__ */ jsx10("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
708
+ /* @__PURE__ */ jsx10("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
709
+ /* @__PURE__ */ jsx10("option", { value: "savedAt:desc", children: savedNewestLabel }),
710
+ /* @__PURE__ */ jsx10("option", { value: "savedAt:asc", children: savedOldestLabel })
560
711
  ] });
561
- return /* @__PURE__ */ jsx9(
712
+ return /* @__PURE__ */ jsx10(
562
713
  "select",
563
714
  {
564
715
  ...props,
@@ -600,11 +751,11 @@ function KeepPagination({
600
751
  "aria-label": props["aria-label"] ?? paginationLabel,
601
752
  "data-state": pageCount > 1 ? "active" : "idle"
602
753
  };
603
- if (render) return /* @__PURE__ */ jsx9("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
754
+ if (render) return /* @__PURE__ */ jsx10("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
604
755
  const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));
605
- return /* @__PURE__ */ jsxs4("nav", { ...navProps, children: [
606
- /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
607
- visiblePages.map((nextPage) => /* @__PURE__ */ jsx9(
756
+ return /* @__PURE__ */ jsxs5("nav", { ...navProps, children: [
757
+ /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
758
+ visiblePages.map((nextPage) => /* @__PURE__ */ jsx10(
608
759
  "button",
609
760
  {
610
761
  type: "button",
@@ -615,7 +766,7 @@ function KeepPagination({
615
766
  },
616
767
  nextPage
617
768
  )),
618
- /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
769
+ /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
619
770
  ] });
620
771
  }
621
772
  function getVisiblePages(currentPage, pageCount, maxPageButtons) {
@@ -626,12 +777,12 @@ function getVisiblePages(currentPage, pageCount, maxPageButtons) {
626
777
  }
627
778
 
628
779
  // src/KeepCollection.tsx
629
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
780
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
630
781
  function KeepCollection(props) {
631
782
  const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
632
- const content = /* @__PURE__ */ jsx10(KeepCollectionContent, { ...collectionProps });
783
+ const content = /* @__PURE__ */ jsx11(KeepCollectionContent, { ...collectionProps });
633
784
  if (fallback === void 0 && onBoundaryError === void 0) return content;
634
- return /* @__PURE__ */ jsx10(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
785
+ return /* @__PURE__ */ jsx11(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
635
786
  }
636
787
  function KeepCollectionContent({
637
788
  query = {},
@@ -653,10 +804,10 @@ function KeepCollectionContent({
653
804
  bulkActions: false,
654
805
  ...features
655
806
  };
656
- const [searchValue, setSearchValue] = useState4(query.search?.query ?? "");
657
- const [sort, setSort] = useState4(query.sort ?? { by: "updatedAt", direction: "desc" });
658
- const [tag, setTag] = useState4(query.tags?.[0]);
659
- const [page, setPage] = useState4(query.pagination?.page ?? 1);
807
+ const [searchValue, setSearchValue] = useState5(query.search?.query ?? "");
808
+ const [sort, setSort] = useState5(query.sort ?? { by: "updatedAt", direction: "desc" });
809
+ const [tag, setTag] = useState5(query.tags?.[0]);
810
+ const [page, setPage] = useState5(query.pagination?.page ?? 1);
660
811
  const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
661
812
  const resolvedQuery = useMemo3(
662
813
  () => ({
@@ -669,7 +820,7 @@ function KeepCollectionContent({
669
820
  [enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag]
670
821
  );
671
822
  const list = useKeepList4(resolvedQuery);
672
- return /* @__PURE__ */ jsxs5(
823
+ return /* @__PURE__ */ jsxs6(
673
824
  "section",
674
825
  {
675
826
  ...rootProps,
@@ -678,8 +829,8 @@ function KeepCollectionContent({
678
829
  "data-state": getCollectionState(list),
679
830
  "data-loading": list.isLoading || list.isMutating ? "true" : void 0,
680
831
  children: [
681
- /* @__PURE__ */ jsxs5("div", { children: [
682
- enabled.search ? /* @__PURE__ */ jsx10(
832
+ /* @__PURE__ */ jsxs6("div", { children: [
833
+ enabled.search ? /* @__PURE__ */ jsx11(
683
834
  KeepSearchInput,
684
835
  {
685
836
  value: searchValue,
@@ -689,7 +840,7 @@ function KeepCollectionContent({
689
840
  }
690
841
  }
691
842
  ) : null,
692
- enabled.sort ? /* @__PURE__ */ jsx10(
843
+ enabled.sort ? /* @__PURE__ */ jsx11(
693
844
  KeepSortSelect,
694
845
  {
695
846
  value: sortToValue(sort),
@@ -699,7 +850,7 @@ function KeepCollectionContent({
699
850
  }
700
851
  }
701
852
  ) : null,
702
- enabled.tagFilter ? /* @__PURE__ */ jsx10(
853
+ enabled.tagFilter ? /* @__PURE__ */ jsx11(
703
854
  KeepTagFilter,
704
855
  {
705
856
  query,
@@ -711,7 +862,7 @@ function KeepCollectionContent({
711
862
  }
712
863
  ) : null
713
864
  ] }),
714
- /* @__PURE__ */ jsx10(
865
+ /* @__PURE__ */ jsx11(
715
866
  KeepList,
716
867
  {
717
868
  query: resolvedQuery,
@@ -722,7 +873,7 @@ function KeepCollectionContent({
722
873
  error
723
874
  }
724
875
  ),
725
- enabled.pagination ? /* @__PURE__ */ jsx10(
876
+ enabled.pagination ? /* @__PURE__ */ jsx11(
726
877
  KeepPagination,
727
878
  {
728
879
  totalCount: list.totalCount,
@@ -731,7 +882,7 @@ function KeepCollectionContent({
731
882
  onPageChange: (nextPage) => setPage(nextPage)
732
883
  }
733
884
  ) : null,
734
- enabled.bulkActions ? /* @__PURE__ */ jsx10(KeepBulkActions, { query: resolvedQuery }) : null
885
+ enabled.bulkActions ? /* @__PURE__ */ jsx11(KeepBulkActions, { query: resolvedQuery }) : null
735
886
  ]
736
887
  }
737
888
  );
@@ -749,10 +900,10 @@ import {
749
900
  isValidElement as isValidElement5,
750
901
  useCallback as useCallback2,
751
902
  useEffect as useEffect2,
752
- useRef,
753
- useState as useState5
903
+ useRef as useRef2,
904
+ useState as useState6
754
905
  } from "react";
755
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
906
+ import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
756
907
  function KeepNoteEditor({
757
908
  item,
758
909
  label,
@@ -772,10 +923,10 @@ function KeepNoteEditor({
772
923
  const itemState = useKeepItem3(item);
773
924
  const { error, isMutating, item: savedItem, updateNote } = itemState;
774
925
  const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
775
- const [note, setNote] = useState5(item.note ?? "");
926
+ const [note, setNote] = useState6(item.note ?? "");
776
927
  const baselineNote = savedItem?.note ?? item.note ?? "";
777
928
  const isDirty = note !== baselineNote;
778
- const lastSavedNoteRef = useRef(void 0);
929
+ const lastSavedNoteRef = useRef2(void 0);
779
930
  useEffect2(() => setNote(baselineNote), [baselineNote]);
780
931
  const save = useCallback2(async () => {
781
932
  const nextNote = note.trim() || void 0;
@@ -802,10 +953,10 @@ function KeepNoteEditor({
802
953
  error,
803
954
  save
804
955
  };
805
- const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs6(Fragment5, { children: [
806
- /* @__PURE__ */ jsxs6("label", { children: [
956
+ const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs7(Fragment5, { children: [
957
+ /* @__PURE__ */ jsxs7("label", { children: [
807
958
  label ?? defaultLabel,
808
- /* @__PURE__ */ jsx11(
959
+ /* @__PURE__ */ jsx12(
809
960
  "textarea",
810
961
  {
811
962
  value: note,
@@ -821,14 +972,14 @@ function KeepNoteEditor({
821
972
  }
822
973
  )
823
974
  ] }),
824
- /* @__PURE__ */ jsx11("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
975
+ /* @__PURE__ */ jsx12("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
825
976
  ] });
826
977
  const handleSubmit = (event) => {
827
978
  event.preventDefault();
828
979
  void save().catch(() => void 0);
829
980
  };
830
981
  if (!asChild) {
831
- return /* @__PURE__ */ jsx11(
982
+ return /* @__PURE__ */ jsx12(
832
983
  "form",
833
984
  {
834
985
  ...formProps,
@@ -861,8 +1012,8 @@ function KeepNoteEditor({
861
1012
 
862
1013
  // src/KeepTagEditor.tsx
863
1014
  import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
864
- import { useCallback as useCallback3, useEffect as useEffect3, useState as useState6 } from "react";
865
- import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1015
+ import { useCallback as useCallback3, useEffect as useEffect3, useState as useState7 } from "react";
1016
+ import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
866
1017
  function KeepTagEditor({
867
1018
  item,
868
1019
  availableTags = [],
@@ -875,8 +1026,8 @@ function KeepTagEditor({
875
1026
  const removeLabel = useUiLabel("remove");
876
1027
  const applyTagsLabel = useUiLabel("applyTags");
877
1028
  const itemState = useKeepItem4(item);
878
- const [tags, setTags] = useState6(item.tags ?? []);
879
- const [input, setInput] = useState6("");
1029
+ const [tags, setTags] = useState7(item.tags ?? []);
1030
+ const [input, setInput] = useState7("");
880
1031
  useEffect3(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
881
1032
  const save = useCallback3(async () => {
882
1033
  const nextTags = normalizeUiTags(tags);
@@ -893,10 +1044,10 @@ function KeepTagEditor({
893
1044
  setTags(normalizeUiTags([...tags, tag]));
894
1045
  setInput("");
895
1046
  };
896
- const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs7(Fragment6, { children: [
897
- /* @__PURE__ */ jsxs7("label", { children: [
1047
+ const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs8(Fragment6, { children: [
1048
+ /* @__PURE__ */ jsxs8("label", { children: [
898
1049
  tagsLabel,
899
- /* @__PURE__ */ jsx12(
1050
+ /* @__PURE__ */ jsx13(
900
1051
  "input",
901
1052
  {
902
1053
  value: input,
@@ -915,14 +1066,14 @@ function KeepTagEditor({
915
1066
  }
916
1067
  )
917
1068
  ] }),
918
- availableTags.length > 0 ? /* @__PURE__ */ jsx12("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx12("option", { value: tag }, tag)) }) : null,
919
- /* @__PURE__ */ jsx12("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs7("li", { children: [
1069
+ availableTags.length > 0 ? /* @__PURE__ */ jsx13("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx13("option", { value: tag }, tag)) }) : null,
1070
+ /* @__PURE__ */ jsx13("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs8("li", { children: [
920
1071
  tag,
921
- /* @__PURE__ */ jsx12("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
1072
+ /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
922
1073
  ] }, tag)) }),
923
- /* @__PURE__ */ jsx12("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
1074
+ /* @__PURE__ */ jsx13("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
924
1075
  ] });
925
- return /* @__PURE__ */ jsx12(
1076
+ return /* @__PURE__ */ jsx13(
926
1077
  "form",
927
1078
  {
928
1079
  ...props,
@@ -940,9 +1091,9 @@ function KeepTagEditor({
940
1091
  }
941
1092
 
942
1093
  // src/status.tsx
943
- import { useKeepContext } from "@keepkit/core/react";
944
- import { isValidElement as isValidElement6, useEffect as useEffect4, useRef as useRef2, useState as useState7 } from "react";
945
- import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1094
+ import { useKeepContext as useKeepContext2 } from "@keepkit/core/react";
1095
+ import { isValidElement as isValidElement6, useEffect as useEffect4, useRef as useRef3, useState as useState8 } from "react";
1096
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
946
1097
  function KeepEmptyState({
947
1098
  title,
948
1099
  description,
@@ -954,9 +1105,9 @@ function KeepEmptyState({
954
1105
  }) {
955
1106
  const defaultTitle = useUiLabel("noItems").replace(/\.$/, "");
956
1107
  const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
957
- const body = contentChildren ?? /* @__PURE__ */ jsxs8(Fragment7, { children: [
958
- /* @__PURE__ */ jsx13("h2", { children: title ?? defaultTitle }),
959
- description ? /* @__PURE__ */ jsx13("p", { children: description }) : null,
1108
+ const body = contentChildren ?? /* @__PURE__ */ jsxs9(Fragment7, { children: [
1109
+ /* @__PURE__ */ jsx14("h2", { children: title ?? defaultTitle }),
1110
+ description ? /* @__PURE__ */ jsx14("p", { children: description }) : null,
960
1111
  action
961
1112
  ] });
962
1113
  return renderRoot(asChild, children, { ...rootProps, className, "data-state": "empty" }, body, "KeepEmptyState");
@@ -970,10 +1121,10 @@ function KeepStatus({
970
1121
  className,
971
1122
  ...rootProps
972
1123
  }) {
973
- const context = useKeepContext();
1124
+ const context = useKeepContext2();
974
1125
  const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
975
1126
  const resolvedStatus = status ?? getDerivedStatus(context);
976
- const defaultLabel = useUiLabel(getStatusLabelKey(resolvedStatus));
1127
+ const defaultLabel = useUiLabel(getStatusLabelKey2(resolvedStatus));
977
1128
  const state = {
978
1129
  status: resolvedStatus,
979
1130
  error: context.error,
@@ -998,12 +1149,12 @@ function KeepStatus({
998
1149
  );
999
1150
  }
1000
1151
  function KeepAnnouncements({ messages, ...props }) {
1001
- const context = useKeepContext();
1152
+ const context = useKeepContext2();
1002
1153
  const savedMessage = useUiLabel("savedMessage", messages?.save);
1003
1154
  const removedMessage = useUiLabel("removedMessage", messages?.remove);
1004
1155
  const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
1005
- const [message, setMessage] = useState7("");
1006
- const lastChangeRef = useRef2(void 0);
1156
+ const [message, setMessage] = useState8("");
1157
+ const lastChangeRef = useRef3(void 0);
1007
1158
  useEffect4(() => {
1008
1159
  const change = context.lastChange;
1009
1160
  if (!change || change === lastChangeRef.current) return;
@@ -1012,7 +1163,7 @@ function KeepAnnouncements({ messages, ...props }) {
1012
1163
  else if (change.action === "remove" || change.action === "removeBatch") setMessage(removedMessage);
1013
1164
  else if (change.action === "updateNote") setMessage(noteSavedMessage);
1014
1165
  }, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);
1015
- return /* @__PURE__ */ jsx13(
1166
+ return /* @__PURE__ */ jsx14(
1016
1167
  "div",
1017
1168
  {
1018
1169
  ...props,
@@ -1033,7 +1184,7 @@ function getDerivedStatus(context) {
1033
1184
  if (context.isHydrated && context.items.length === 0) return "empty";
1034
1185
  return "idle";
1035
1186
  }
1036
- function getStatusLabelKey(status) {
1187
+ function getStatusLabelKey2(status) {
1037
1188
  if (status === "empty") return "noItems";
1038
1189
  if (status === "loading") return "loadingItems";
1039
1190
  if (status === "error") return "error";
@@ -1046,7 +1197,7 @@ function getStatusLabelKey(status) {
1046
1197
  import {
1047
1198
  KeepErrorBoundary as KeepErrorBoundary3,
1048
1199
  KeepProvider,
1049
- useKeepContext as useKeepContext2,
1200
+ useKeepContext as useKeepContext3,
1050
1201
  useKeepItem as useKeepItem5,
1051
1202
  useKeepList as useKeepList5,
1052
1203
  useKeepShortcut
@@ -1061,7 +1212,7 @@ import {
1061
1212
  LocalStorageSyncQueueAdapter,
1062
1213
  SyncStorageAdapter
1063
1214
  } from "@keepkit/core/storage";
1064
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1215
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1065
1216
  function KeepKitProvider({
1066
1217
  labels,
1067
1218
  locale,
@@ -1069,16 +1220,16 @@ function KeepKitProvider({
1069
1220
  children,
1070
1221
  ...providerProps
1071
1222
  }) {
1072
- return /* @__PURE__ */ jsx14(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsxs9(CoreKeepProvider, { ...providerProps, children: [
1223
+ return /* @__PURE__ */ jsx15(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsxs10(CoreKeepProvider, { ...providerProps, children: [
1073
1224
  children,
1074
- /* @__PURE__ */ jsx14(KeepAnnouncements, {})
1225
+ /* @__PURE__ */ jsx15(KeepAnnouncements, {})
1075
1226
  ] }) });
1076
1227
  }
1077
1228
  function createKeepKit(options = {}) {
1078
1229
  const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;
1079
1230
  const coreKit = createCoreKeepKit(coreOptions);
1080
1231
  return {
1081
- Provider: (props) => /* @__PURE__ */ jsx14(
1232
+ Provider: (props) => /* @__PURE__ */ jsx15(
1082
1233
  KeepKitProvider,
1083
1234
  {
1084
1235
  ...coreOptions,
@@ -1088,8 +1239,9 @@ function createKeepKit(options = {}) {
1088
1239
  ...props
1089
1240
  }
1090
1241
  ),
1091
- Button: (props) => /* @__PURE__ */ jsx14(KeepButton, { ...props }),
1092
- Collection: (props) => /* @__PURE__ */ jsx14(
1242
+ Button: (props) => /* @__PURE__ */ jsx15(KeepButton, { ...props }),
1243
+ Backup: (props) => /* @__PURE__ */ jsx15(KeepBackup, { ...props }),
1244
+ Collection: (props) => /* @__PURE__ */ jsx15(
1093
1245
  KeepCollection,
1094
1246
  {
1095
1247
  ...props,
@@ -1112,6 +1264,7 @@ export {
1112
1264
  IndexedDBSyncQueueAdapter,
1113
1265
  KeepAnnouncements,
1114
1266
  KeepAnnouncer,
1267
+ KeepBackup,
1115
1268
  KeepBulkActions,
1116
1269
  KeepButton,
1117
1270
  KeepCollection,
@@ -1138,7 +1291,7 @@ export {
1138
1291
  createStorageAdapter,
1139
1292
  isAllSelected,
1140
1293
  toggleSelectAll,
1141
- useKeepContext2 as useKeepContext,
1294
+ useKeepContext3 as useKeepContext,
1142
1295
  useKeepItem5 as useKeepItem,
1143
1296
  useKeepList5 as useKeepList,
1144
1297
  useKeepShortcut,