@keepkit/core 0.8.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/react.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, ButtonHTMLAttributes, MouseEvent, HTMLAttributes, ReactElement, PropsWithChildren, ComponentType } from 'react';
3
- import { K as KeepItemMetadataRefresher, d as KeepItemRevalidator, R as RevalidateKeepItemsOptions, c as KeepItemRevalidationSummary, f as KeepListQuery, g as KeepStore, h as KeepStoreActions } from './store-CqNh-2DS.js';
4
- export { b as KeepItemRevalidationResult, e as KeepItemStatus, k as isKeepItemMetadataStale } from './store-CqNh-2DS.js';
5
- import { m as KeepItemInput, a as KeepItem, l as KeepEventHandlers, S as StorageAdapter, d as KeepPlugin, K as KeepSchema, b as KeepInvalidItemPolicy, f as KeepChangeContext, t as KeepSyncState } from './types-BCziYE6E.js';
2
+ import { ReactNode, ButtonHTMLAttributes, MouseEvent, HTMLAttributes, ReactElement, ErrorInfo, Component, PropsWithChildren, ComponentType } from 'react';
3
+ import { f as KeepItemMetadataRefresher, k as KeepItemRevalidator, R as RevalidateKeepItemsOptions, j as KeepItemRevalidationSummary, l as KeepListQuery, g as KeepItemResolver, I as ImportItemsOptions, a as ImportItemsResult, m as KeepStore, n as KeepStoreActions } from './store-Cgqx7_xd.js';
4
+ export { i as KeepItemRevalidationResult, s as isKeepItemMetadataStale } from './store-Cgqx7_xd.js';
5
+ import { m as KeepItemInput, a as KeepItem, k as KeepEventHandlers, S as StorageAdapter, c as KeepPlugin, K as KeepSchema, l as KeepInvalidItemPolicy, e as KeepChangeContext, u as KeepSyncState } from './types--YahIoEB.js';
6
+ export { n as KeepItemStatus } from './types--YahIoEB.js';
6
7
 
7
8
  type UseKeepItemResult<TMeta = Record<string, unknown>> = {
8
9
  item: KeepItem<TMeta> | undefined;
@@ -40,7 +41,7 @@ type UseKeepListResult<TMeta = Record<string, unknown>> = {
40
41
  removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;
41
42
  clear: () => Promise<void>;
42
43
  refresh: () => Promise<void>;
43
- revalidate: (revalidator: KeepItemRevalidator<TMeta>, options?: RevalidateKeepItemsOptions) => Promise<KeepItemRevalidationSummary<TMeta>>;
44
+ revalidate: (revalidator: KeepItemRevalidator<TMeta>, options?: RevalidateKeepItemsOptions<TMeta>) => Promise<KeepItemRevalidationSummary<TMeta>>;
44
45
  };
45
46
  declare function useKeepList<TMeta = Record<string, unknown>>(query?: KeepListQuery<TMeta>): UseKeepListResult<TMeta>;
46
47
 
@@ -94,6 +95,25 @@ type KeepButtonState<TMeta = Record<string, unknown>> = {
94
95
  /** A style-free accessible save toggle. Consumers provide all visual styling. */
95
96
  declare function KeepButton<TMeta = Record<string, unknown>>({ item, children, savedLabel, unsavedLabel, savedAriaLabel, unsavedAriaLabel, getAriaLabel, asChild, onToggleError, onClick, disabled, ...buttonProps }: KeepButtonProps<TMeta>): react.JSX.Element;
96
97
 
98
+ type KeepErrorBoundaryProps = {
99
+ children?: ReactNode;
100
+ fallback?: ReactNode | ((error: unknown) => ReactNode);
101
+ onError?: (error: unknown, info: ErrorInfo) => void;
102
+ /** Change this value to retry rendering after an error has been handled. */
103
+ resetKey?: unknown;
104
+ };
105
+ type KeepErrorBoundaryState = {
106
+ error: unknown | null;
107
+ };
108
+ /** Prevents an unexpected render error from taking down the host application. */
109
+ declare class KeepErrorBoundary extends Component<KeepErrorBoundaryProps, KeepErrorBoundaryState> {
110
+ state: KeepErrorBoundaryState;
111
+ static getDerivedStateFromError(error: unknown): KeepErrorBoundaryState;
112
+ componentDidCatch(error: unknown, info: ErrorInfo): void;
113
+ componentDidUpdate(previousProps: KeepErrorBoundaryProps): void;
114
+ render(): ReactNode;
115
+ }
116
+
97
117
  type KeepContextValue<TMeta = Record<string, unknown>> = {
98
118
  items: KeepItem<TMeta>[];
99
119
  isLoading: boolean;
@@ -114,7 +134,9 @@ type KeepContextValue<TMeta = Record<string, unknown>> = {
114
134
  refresh: () => Promise<void>;
115
135
  flushSync: () => Promise<void>;
116
136
  refreshItemMetadata: (id: string, refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;
117
- revalidateItems: (revalidator: KeepItemRevalidator<TMeta>, options?: RevalidateKeepItemsOptions) => Promise<KeepItemRevalidationSummary<TMeta>>;
137
+ revalidateItems: (revalidator?: KeepItemRevalidator<TMeta>, options?: RevalidateKeepItemsOptions<TMeta>) => Promise<KeepItemRevalidationSummary<TMeta>>;
138
+ exportBackup: () => Promise<string>;
139
+ importBackup: (data: string, options?: Pick<ImportItemsOptions<TMeta>, "mode" | "invalidItemPolicy" | "onInvalidItem">) => Promise<ImportItemsResult<TMeta>>;
118
140
  };
119
141
  type KeepProviderProps<TMeta = Record<string, unknown>> = PropsWithChildren<KeepEventHandlers<TMeta> & {
120
142
  storage?: StorageAdapter<TMeta>;
@@ -130,12 +152,18 @@ type KeepProviderProps<TMeta = Record<string, unknown>> = PropsWithChildren<Keep
130
152
  invalidItemPolicy?: KeepInvalidItemPolicy;
131
153
  onInvalidItem?: (error: unknown, item: KeepItem<unknown>) => void;
132
154
  migrateMeta?: (meta: unknown, fromVersion: number, toVersion: number, item: KeepItem<TMeta>) => TMeta | Promise<TMeta>;
155
+ /** Render this content when a descendant or provider render unexpectedly throws. */
156
+ fallback?: KeepErrorBoundaryProps["fallback"];
157
+ onBoundaryError?: KeepErrorBoundaryProps["onError"];
158
+ boundaryResetKey?: unknown;
159
+ validateItem?: KeepItemRevalidator<TMeta>;
160
+ resolveItem?: KeepItemResolver<TMeta>;
133
161
  }>;
134
162
  type KeepStoreAccess<TMeta> = {
135
163
  store: KeepStore<TMeta>;
136
164
  actions: KeepStoreActions<TMeta>;
137
165
  };
138
- declare function KeepProvider<TMeta = Record<string, unknown>>({ storage, initialItems, onSave, onRemove, onNoteUpdate, onTagsUpdate, onChange, onError, plugins, schemaVersion, schema, invalidItemPolicy, onInvalidItem, migrateMeta, children, }: KeepProviderProps<TMeta>): react.JSX.Element;
166
+ declare function KeepProvider<TMeta = Record<string, unknown>>({ storage, initialItems, onSave, onRemove, onNoteUpdate, onTagsUpdate, onChange, onError, plugins, schemaVersion, schema, invalidItemPolicy, onInvalidItem, migrateMeta, fallback, onBoundaryError, boundaryResetKey, validateItem, resolveItem, children, }: KeepProviderProps<TMeta>): react.JSX.Element;
139
167
  declare function useKeepContext<TMeta = Record<string, unknown>>(): KeepContextValue<TMeta>;
140
168
  declare function useKeepStore<TMeta = Record<string, unknown>>(): KeepStoreAccess<TMeta>;
141
169
 
@@ -151,4 +179,4 @@ type KeepKit<TMeta> = {
151
179
  /** Create an app-specific, fully typed set of KeepKit components and hooks. */
152
180
  declare function createKeepKit<TMeta = Record<string, unknown>>(options?: CreateKeepKitOptions<TMeta>): KeepKit<TMeta>;
153
181
 
154
- export { type CreateKeepKitOptions, KeepButton, type KeepButtonItem, type KeepButtonProps, type KeepButtonState, type KeepContextValue, KeepItemMetadataRefresher, KeepItemRevalidationSummary, KeepItemRevalidator, type KeepKit, KeepListQuery, KeepProvider, type KeepProviderProps, type KeepShortcutModifier, type KeepShortcutOptions, RevalidateKeepItemsOptions, type UseKeepItemResult, type UseKeepListResult, createKeepKit, useKeepContext, useKeepItem, useKeepList, useKeepShortcut, useKeepStore };
182
+ export { type CreateKeepKitOptions, KeepButton, type KeepButtonItem, type KeepButtonProps, type KeepButtonState, type KeepContextValue, KeepErrorBoundary, type KeepErrorBoundaryProps, KeepItemMetadataRefresher, KeepItemResolver, KeepItemRevalidationSummary, KeepItemRevalidator, type KeepKit, KeepListQuery, KeepProvider, type KeepProviderProps, type KeepShortcutModifier, type KeepShortcutOptions, RevalidateKeepItemsOptions, type UseKeepItemResult, type UseKeepListResult, createKeepKit, useKeepContext, useKeepItem, useKeepList, useKeepShortcut, useKeepStore };
package/dist/react.js CHANGED
@@ -1,10 +1,12 @@
1
1
  "use client";
2
2
  import {
3
3
  KeepStore,
4
+ exportItems,
5
+ importItems,
4
6
  isKeepItemMetadataStale,
5
7
  queryKeepItems,
6
8
  revalidateKeepItems
7
- } from "./chunk-AWQWKK4V.js";
9
+ } from "./chunk-XF5VI6O5.js";
8
10
  import {
9
11
  parseKeepMeta
10
12
  } from "./chunk-THZ3ACR2.js";
@@ -12,7 +14,7 @@ import "./chunk-5QSZP6MT.js";
12
14
  import {
13
15
  createBrowserStorageAdapter,
14
16
  normalizeKeepTags
15
- } from "./chunk-DBRHZ6XU.js";
17
+ } from "./chunk-EXE4E3GA.js";
16
18
 
17
19
  // src/hooks/useKeepItem.ts
18
20
  import { useCallback as useCallback3 } from "react";
@@ -27,6 +29,34 @@ import {
27
29
  useRef,
28
30
  useSyncExternalStore
29
31
  } from "react";
32
+
33
+ // src/KeepErrorBoundary.tsx
34
+ import { Component } from "react";
35
+ var KeepErrorBoundary = class extends Component {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.state = { error: null };
39
+ }
40
+ static getDerivedStateFromError(error) {
41
+ return { error };
42
+ }
43
+ componentDidCatch(error, info) {
44
+ this.props.onError?.(error, info);
45
+ }
46
+ componentDidUpdate(previousProps) {
47
+ if (this.state.error !== null && previousProps.resetKey !== this.props.resetKey) {
48
+ this.setState({ error: null });
49
+ }
50
+ }
51
+ render() {
52
+ if (this.state.error !== null) {
53
+ return typeof this.props.fallback === "function" ? this.props.fallback(this.state.error) : this.props.fallback ?? null;
54
+ }
55
+ return this.props.children;
56
+ }
57
+ };
58
+
59
+ // src/KeepProvider.tsx
30
60
  import { jsx } from "react/jsx-runtime";
31
61
  var defaultStorage = createBrowserStorageAdapter();
32
62
  var KeepContext = createContext(null);
@@ -46,6 +76,55 @@ function KeepProvider({
46
76
  invalidItemPolicy = "error",
47
77
  onInvalidItem,
48
78
  migrateMeta,
79
+ fallback,
80
+ onBoundaryError,
81
+ boundaryResetKey,
82
+ validateItem,
83
+ resolveItem,
84
+ children
85
+ }) {
86
+ const content = /* @__PURE__ */ jsx(
87
+ KeepProviderContent,
88
+ {
89
+ storage,
90
+ initialItems,
91
+ onSave,
92
+ onRemove,
93
+ onNoteUpdate,
94
+ onTagsUpdate,
95
+ onChange,
96
+ onError,
97
+ plugins,
98
+ schemaVersion,
99
+ schema,
100
+ invalidItemPolicy,
101
+ onInvalidItem,
102
+ migrateMeta,
103
+ validateItem,
104
+ resolveItem,
105
+ children
106
+ }
107
+ );
108
+ if (fallback === void 0 && onBoundaryError === void 0) return content;
109
+ return /* @__PURE__ */ jsx(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
110
+ }
111
+ function KeepProviderContent({
112
+ storage = defaultStorage,
113
+ initialItems,
114
+ onSave,
115
+ onRemove,
116
+ onNoteUpdate,
117
+ onTagsUpdate,
118
+ onChange,
119
+ onError,
120
+ plugins = [],
121
+ schemaVersion,
122
+ schema,
123
+ invalidItemPolicy = "error",
124
+ onInvalidItem,
125
+ migrateMeta,
126
+ validateItem,
127
+ resolveItem,
49
128
  children
50
129
  }) {
51
130
  const storeRef = useRef(null);
@@ -411,7 +490,13 @@ function KeepProvider({
411
490
  const previous = itemsRef.current;
412
491
  let persistenceStarted = false;
413
492
  try {
414
- const summary = await revalidateKeepItems(previous, revalidator, options);
493
+ const activeRevalidator = revalidator ?? validateItem;
494
+ if (!activeRevalidator)
495
+ throw new Error("KeepProvider.revalidateItems requires a revalidator or validateItem.");
496
+ const summary = await revalidateKeepItems(previous, activeRevalidator, {
497
+ ...options,
498
+ resolveItem: options.resolveItem ?? resolveItem
499
+ });
415
500
  const pluginContext = { action: "revalidate", items: summary.updatedItems };
416
501
  await runBeforePlugins(pluginContext);
417
502
  if (summary.updatedItems.length > 0) {
@@ -447,7 +532,17 @@ function KeepProvider({
447
532
  if (pendingMutationsRef.current === 0) store.setState({ isMutating: false });
448
533
  });
449
534
  },
450
- [enqueueOperation, reportError, runAfterPlugins, runBeforePlugins, setItems, storage, store]
535
+ [
536
+ enqueueOperation,
537
+ reportError,
538
+ resolveItem,
539
+ runAfterPlugins,
540
+ runBeforePlugins,
541
+ setItems,
542
+ storage,
543
+ store,
544
+ validateItem
545
+ ]
451
546
  );
452
547
  const refreshItemMetadata = useCallback(
453
548
  async (id, refresh2) => {
@@ -462,6 +557,34 @@ function KeepProvider({
462
557
  [revalidateItems]
463
558
  );
464
559
  const flushSync = useCallback(() => syncStorage ? syncStorage.flushSync() : Promise.resolve(), [syncStorage]);
560
+ const exportBackup = useCallback(() => exportItems(storage), [storage]);
561
+ const importBackup = useCallback(
562
+ async (data, options = {}) => {
563
+ pendingMutationsRef.current += 1;
564
+ store.setState({ isMutating: true });
565
+ const run = enqueueOperation(async () => {
566
+ try {
567
+ const result = await importItems(storage, data, {
568
+ ...options,
569
+ schema: migrationRef.current.schema,
570
+ invalidItemPolicy: options.invalidItemPolicy ?? migrationRef.current.invalidItemPolicy,
571
+ onInvalidItem: options.onInvalidItem ?? migrationRef.current.onInvalidItem
572
+ });
573
+ setItems(result.items);
574
+ store.setState({ error: null });
575
+ return result;
576
+ } catch (cause) {
577
+ reportError(cause, { action: "import" });
578
+ throw cause;
579
+ }
580
+ });
581
+ return run.finally(() => {
582
+ pendingMutationsRef.current -= 1;
583
+ if (pendingMutationsRef.current === 0) store.setState({ isMutating: false });
584
+ });
585
+ },
586
+ [enqueueOperation, reportError, setItems, storage, store]
587
+ );
465
588
  const value = useMemo(
466
589
  () => ({
467
590
  items,
@@ -483,7 +606,9 @@ function KeepProvider({
483
606
  refresh,
484
607
  flushSync,
485
608
  refreshItemMetadata,
486
- revalidateItems
609
+ revalidateItems,
610
+ exportBackup,
611
+ importBackup
487
612
  }),
488
613
  [
489
614
  clear,
@@ -505,7 +630,9 @@ function KeepProvider({
505
630
  removeTagsBatch,
506
631
  removeItems,
507
632
  refreshItemMetadata,
508
- revalidateItems
633
+ revalidateItems,
634
+ exportBackup,
635
+ importBackup
509
636
  ]
510
637
  );
511
638
  const actions = useMemo(
@@ -855,6 +982,9 @@ function KeepButton({
855
982
  const commonProps = {
856
983
  ...buttonProps,
857
984
  "aria-pressed": isSaved,
985
+ "data-state": isSaved ? "saved" : "unsaved",
986
+ "data-loading": state.isLoading || state.isMutating ? "true" : void 0,
987
+ "data-disabled": isDisabled ? "true" : void 0,
858
988
  "aria-label": ("aria-label" in buttonProps ? buttonProps["aria-label"] : void 0) ?? getAriaLabel?.(state) ?? (isSaved ? savedAriaLabel : unsavedAriaLabel) ?? getAccessibleLabel(isSaved, item, asChild),
859
989
  ...asChild ? {
860
990
  "aria-disabled": isDisabled,
@@ -895,6 +1025,7 @@ function createKeepKit(options = {}) {
895
1025
  }
896
1026
  export {
897
1027
  KeepButton,
1028
+ KeepErrorBoundary,
898
1029
  KeepProvider,
899
1030
  createKeepKit,
900
1031
  isKeepItemMetadataStale,