@keepkit/core 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{chunk-THZ3ACR2.js → chunk-5W4QSJHV.js} +2 -2
- package/dist/chunk-5W4QSJHV.js.map +1 -0
- package/dist/{chunk-XWZ6GRD4.js → chunk-62I2YZYI.js} +70 -70
- package/dist/chunk-62I2YZYI.js.map +1 -0
- package/dist/{chunk-XIBTMJ4R.js → chunk-PNP7OALR.js} +54 -54
- package/dist/chunk-PNP7OALR.js.map +1 -0
- package/dist/core.d.ts +20 -20
- package/dist/core.js +76 -76
- package/dist/core.js.map +1 -1
- package/dist/react.d.ts +62 -62
- package/dist/react.js +112 -109
- package/dist/react.js.map +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +1 -1
- package/dist/{scope-D52NbAWR.d.ts → scope-Dk5FTVz8.d.ts} +1 -1
- package/dist/storage.d.ts +3 -3
- package/dist/storage.js +1 -1
- package/dist/{url-Blx4SPKD.d.ts → store-Cm35R_ho.d.ts} +68 -68
- package/dist/{types-B3xc8-Pi.d.ts → types-Aoc0Eyvk.d.ts} +2 -1
- package/package.json +1 -1
- package/dist/chunk-THZ3ACR2.js.map +0 -1
- package/dist/chunk-XIBTMJ4R.js.map +0 -1
- package/dist/chunk-XWZ6GRD4.js.map +0 -1
package/dist/react.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { g as KeepItemMetadataRefresher, l as KeepItemRevalidator, h as KeepItemResolver, c as KeepAutoRevalidationOptions, R as RevalidateKeepItemsOptions, k as KeepItemRevalidationSummary, I as ImportItemsOptions, a as ImportItemsResult, o as KeepStore, p as KeepStoreActions, m as KeepListQuery, n as KeepNavigationState } from './store-Cm35R_ho.js';
|
|
2
|
+
export { j as KeepItemRevalidationResult, r as KeepUrlParamNames, s as KeepUrlState, t as KeepUrlSyncOptions, A as isKeepItemMetadataStale } from './store-Cm35R_ho.js';
|
|
3
|
+
import { r as KeepItemInput, K as KeepItem, p as KeepEventHandlers, a as StorageAdapter, e as KeepPlugin, t as KeepSchema, q as KeepInvalidItemPolicy, j as KeepChangeContext, D as KeepSyncState, F as KeepUndoState } from './types-Aoc0Eyvk.js';
|
|
4
|
+
export { s as KeepItemStatus } from './types-Aoc0Eyvk.js';
|
|
5
|
+
export { K as KeepScope, S as ScopedStorageAdapter } from './scope-Dk5FTVz8.js';
|
|
1
6
|
import * as react from 'react';
|
|
2
7
|
import { ReactNode, ButtonHTMLAttributes, MouseEvent, HTMLAttributes, ReactElement, ErrorInfo, Component, PropsWithChildren, ComponentType } from 'react';
|
|
3
|
-
import { g as KeepItemMetadataRefresher, l as KeepItemRevalidator, R as RevalidateKeepItemsOptions, k as KeepItemRevalidationSummary, m as KeepListQuery, n as KeepNavigationState, h as KeepItemResolver, c as KeepAutoRevalidationOptions, I as ImportItemsOptions, a as ImportItemsResult, o as KeepStore, p as KeepStoreActions } from './url-Blx4SPKD.js';
|
|
4
|
-
export { j as KeepItemRevalidationResult, r as KeepUrlParamNames, s as KeepUrlState, t as KeepUrlSyncOptions, A as isKeepItemMetadataStale } from './url-Blx4SPKD.js';
|
|
5
|
-
import { s as KeepItemInput, a as KeepItem, q as KeepEventHandlers, b as StorageAdapter, f as KeepPlugin, K as KeepSchema, r as KeepInvalidItemPolicy, k as KeepChangeContext, D as KeepSyncState, F as KeepUndoState } from './types-B3xc8-Pi.js';
|
|
6
|
-
export { t as KeepItemStatus } from './types-B3xc8-Pi.js';
|
|
7
|
-
export { K as KeepScope, S as ScopedStorageAdapter } from './scope-D52NbAWR.js';
|
|
8
8
|
|
|
9
9
|
type UseKeepItemResult<TMeta = Record<string, unknown>> = {
|
|
10
10
|
item: KeepItem<TMeta> | undefined;
|
|
@@ -24,63 +24,6 @@ type UseKeepItemResult<TMeta = Record<string, unknown>> = {
|
|
|
24
24
|
/** Read and mutate one saved item from its complete minimal input description. */
|
|
25
25
|
declare function useKeepItem<TMeta = Record<string, unknown>>(input?: KeepItemInput<TMeta>): UseKeepItemResult<TMeta>;
|
|
26
26
|
|
|
27
|
-
type UseKeepListResult<TMeta = Record<string, unknown>> = {
|
|
28
|
-
items: KeepItem<TMeta>[];
|
|
29
|
-
totalCount: number;
|
|
30
|
-
tags: string[];
|
|
31
|
-
tagCounts: Record<string, number>;
|
|
32
|
-
page: number;
|
|
33
|
-
pageCount: number;
|
|
34
|
-
hasNextPage: boolean;
|
|
35
|
-
hasPreviousPage: boolean;
|
|
36
|
-
isLoading: boolean;
|
|
37
|
-
isHydrated: boolean;
|
|
38
|
-
isMutating: boolean;
|
|
39
|
-
error: unknown | null;
|
|
40
|
-
remove: (id: string) => Promise<void>;
|
|
41
|
-
removeBatch: (ids: string[]) => Promise<void>;
|
|
42
|
-
removeWithUndo: (id: string) => Promise<void>;
|
|
43
|
-
removeBatchWithUndo: (ids: string[]) => Promise<void>;
|
|
44
|
-
updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;
|
|
45
|
-
addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;
|
|
46
|
-
removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;
|
|
47
|
-
reorder: (orderedIds: string[]) => Promise<void>;
|
|
48
|
-
move: (id: string, targetIndex: number) => Promise<void>;
|
|
49
|
-
clear: () => Promise<void>;
|
|
50
|
-
refresh: () => Promise<void>;
|
|
51
|
-
revalidate: (revalidator: KeepItemRevalidator<TMeta>, options?: RevalidateKeepItemsOptions<TMeta>) => Promise<KeepItemRevalidationSummary<TMeta>>;
|
|
52
|
-
};
|
|
53
|
-
declare function useKeepList<TMeta = Record<string, unknown>>(query?: KeepListQuery<TMeta>): UseKeepListResult<TMeta>;
|
|
54
|
-
|
|
55
|
-
type UseKeepNavigatorOptions<TMeta = Record<string, unknown>> = {
|
|
56
|
-
currentId?: string;
|
|
57
|
-
initialIndex?: number;
|
|
58
|
-
query?: Omit<KeepListQuery<TMeta>, "pagination">;
|
|
59
|
-
};
|
|
60
|
-
type UseKeepNavigatorResult<TMeta = Record<string, unknown>> = KeepNavigationState<TMeta> & {
|
|
61
|
-
goToNext: () => KeepItem<TMeta> | null;
|
|
62
|
-
goToPrev: () => KeepItem<TMeta> | null;
|
|
63
|
-
goToIndex: (index: number) => KeepItem<TMeta> | null;
|
|
64
|
-
goToItem: (id: string) => KeepItem<TMeta> | null;
|
|
65
|
-
};
|
|
66
|
-
/** Derive a stable previous/current/next view and pointer actions from the provider store. */
|
|
67
|
-
declare function useKeepNavigator<TMeta = Record<string, unknown>>(options?: UseKeepNavigatorOptions<TMeta>): UseKeepNavigatorResult<TMeta>;
|
|
68
|
-
|
|
69
|
-
type KeepShortcutModifier = "meta" | "ctrl" | "alt" | "shift";
|
|
70
|
-
type KeepShortcutOptions<TMeta = Record<string, unknown>> = {
|
|
71
|
-
key: string;
|
|
72
|
-
modifier?: KeepShortcutModifier;
|
|
73
|
-
item?: KeepItemInput<TMeta>;
|
|
74
|
-
action?: "toggle" | "save" | "remove";
|
|
75
|
-
enabled?: boolean;
|
|
76
|
-
preventDefault?: boolean;
|
|
77
|
-
allowInEditable?: boolean;
|
|
78
|
-
onTrigger?: (event: KeyboardEvent) => void | Promise<void>;
|
|
79
|
-
onError?: (error: unknown) => void;
|
|
80
|
-
};
|
|
81
|
-
/** Bind a keyboard shortcut to a Keep action or an arbitrary command. */
|
|
82
|
-
declare function useKeepShortcut<TMeta = Record<string, unknown>>(options: KeepShortcutOptions<TMeta>): void;
|
|
83
|
-
|
|
84
27
|
type KeepButtonItem<TMeta = Record<string, unknown>> = KeepItemInput<TMeta>;
|
|
85
28
|
type KeepButtonSharedProps<TMeta> = {
|
|
86
29
|
item: KeepButtonItem<TMeta>;
|
|
@@ -197,6 +140,63 @@ declare function KeepProvider<TMeta = Record<string, unknown>>({ storage, initia
|
|
|
197
140
|
declare function useKeepContext<TMeta = Record<string, unknown>>(): KeepContextValue<TMeta>;
|
|
198
141
|
declare function useKeepStore<TMeta = Record<string, unknown>>(): KeepStoreAccess<TMeta>;
|
|
199
142
|
|
|
143
|
+
type UseKeepListResult<TMeta = Record<string, unknown>> = {
|
|
144
|
+
items: KeepItem<TMeta>[];
|
|
145
|
+
totalCount: number;
|
|
146
|
+
tags: string[];
|
|
147
|
+
tagCounts: Record<string, number>;
|
|
148
|
+
page: number;
|
|
149
|
+
pageCount: number;
|
|
150
|
+
hasNextPage: boolean;
|
|
151
|
+
hasPreviousPage: boolean;
|
|
152
|
+
isLoading: boolean;
|
|
153
|
+
isHydrated: boolean;
|
|
154
|
+
isMutating: boolean;
|
|
155
|
+
error: unknown | null;
|
|
156
|
+
remove: (id: string) => Promise<void>;
|
|
157
|
+
removeBatch: (ids: string[]) => Promise<void>;
|
|
158
|
+
removeWithUndo: (id: string) => Promise<void>;
|
|
159
|
+
removeBatchWithUndo: (ids: string[]) => Promise<void>;
|
|
160
|
+
updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;
|
|
161
|
+
addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;
|
|
162
|
+
removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;
|
|
163
|
+
reorder: (orderedIds: string[]) => Promise<void>;
|
|
164
|
+
move: (id: string, targetIndex: number) => Promise<void>;
|
|
165
|
+
clear: () => Promise<void>;
|
|
166
|
+
refresh: () => Promise<void>;
|
|
167
|
+
revalidate: (revalidator: KeepItemRevalidator<TMeta>, options?: RevalidateKeepItemsOptions<TMeta>) => Promise<KeepItemRevalidationSummary<TMeta>>;
|
|
168
|
+
};
|
|
169
|
+
declare function useKeepList<TMeta = Record<string, unknown>>(query?: KeepListQuery<TMeta>): UseKeepListResult<TMeta>;
|
|
170
|
+
|
|
171
|
+
type UseKeepNavigatorOptions<TMeta = Record<string, unknown>> = {
|
|
172
|
+
currentId?: string;
|
|
173
|
+
initialIndex?: number;
|
|
174
|
+
query?: Omit<KeepListQuery<TMeta>, "pagination">;
|
|
175
|
+
};
|
|
176
|
+
type UseKeepNavigatorResult<TMeta = Record<string, unknown>> = KeepNavigationState<TMeta> & {
|
|
177
|
+
goToNext: () => KeepItem<TMeta> | null;
|
|
178
|
+
goToPrev: () => KeepItem<TMeta> | null;
|
|
179
|
+
goToIndex: (index: number) => KeepItem<TMeta> | null;
|
|
180
|
+
goToItem: (id: string) => KeepItem<TMeta> | null;
|
|
181
|
+
};
|
|
182
|
+
/** Derive a stable previous/current/next view and pointer actions from the provider store. */
|
|
183
|
+
declare function useKeepNavigator<TMeta = Record<string, unknown>>(options?: UseKeepNavigatorOptions<TMeta>): UseKeepNavigatorResult<TMeta>;
|
|
184
|
+
|
|
185
|
+
type KeepShortcutModifier = "meta" | "ctrl" | "alt" | "shift";
|
|
186
|
+
type KeepShortcutOptions<TMeta = Record<string, unknown>> = {
|
|
187
|
+
key: string;
|
|
188
|
+
modifier?: KeepShortcutModifier;
|
|
189
|
+
item?: KeepItemInput<TMeta>;
|
|
190
|
+
action?: "toggle" | "save" | "remove";
|
|
191
|
+
enabled?: boolean;
|
|
192
|
+
preventDefault?: boolean;
|
|
193
|
+
allowInEditable?: boolean;
|
|
194
|
+
onTrigger?: (event: KeyboardEvent) => void | Promise<void>;
|
|
195
|
+
onError?: (error: unknown) => void;
|
|
196
|
+
};
|
|
197
|
+
/** Bind a keyboard shortcut to a Keep action or an arbitrary command. */
|
|
198
|
+
declare function useKeepShortcut<TMeta = Record<string, unknown>>(options: KeepShortcutOptions<TMeta>): void;
|
|
199
|
+
|
|
200
200
|
type CreateKeepKitOptions<TMeta = Record<string, unknown>> = Omit<KeepProviderProps<TMeta>, "children">;
|
|
201
201
|
type KeepKit<TMeta> = {
|
|
202
202
|
Provider: ComponentType<KeepProviderProps<TMeta>>;
|
package/dist/react.js
CHANGED
|
@@ -10,19 +10,26 @@ import {
|
|
|
10
10
|
queryKeepItems,
|
|
11
11
|
reorderKeepItems,
|
|
12
12
|
revalidateKeepItems
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-62I2YZYI.js";
|
|
14
14
|
import {
|
|
15
15
|
parseKeepMeta
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-5W4QSJHV.js";
|
|
17
17
|
import {
|
|
18
18
|
createBrowserStorageAdapter,
|
|
19
19
|
normalizeKeepTags
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-PNP7OALR.js";
|
|
21
21
|
|
|
22
|
-
// src/
|
|
22
|
+
// src/react/components/KeepButton.tsx
|
|
23
|
+
import {
|
|
24
|
+
Children,
|
|
25
|
+
cloneElement,
|
|
26
|
+
isValidElement
|
|
27
|
+
} from "react";
|
|
28
|
+
|
|
29
|
+
// src/react/hooks/useKeepItem.ts
|
|
23
30
|
import { useCallback as useCallback3 } from "react";
|
|
24
31
|
|
|
25
|
-
// src/KeepProvider.tsx
|
|
32
|
+
// src/react/components/KeepProvider.tsx
|
|
26
33
|
import {
|
|
27
34
|
createContext,
|
|
28
35
|
useCallback,
|
|
@@ -33,7 +40,7 @@ import {
|
|
|
33
40
|
useSyncExternalStore
|
|
34
41
|
} from "react";
|
|
35
42
|
|
|
36
|
-
// src/KeepErrorBoundary.tsx
|
|
43
|
+
// src/react/components/KeepErrorBoundary.tsx
|
|
37
44
|
import { Component } from "react";
|
|
38
45
|
var KeepErrorBoundary = class extends Component {
|
|
39
46
|
constructor() {
|
|
@@ -59,7 +66,7 @@ var KeepErrorBoundary = class extends Component {
|
|
|
59
66
|
}
|
|
60
67
|
};
|
|
61
68
|
|
|
62
|
-
// src/KeepProvider.tsx
|
|
69
|
+
// src/react/components/KeepProvider.tsx
|
|
63
70
|
import { jsx } from "react/jsx-runtime";
|
|
64
71
|
var defaultStorage = createBrowserStorageAdapter();
|
|
65
72
|
var KeepContext = createContext(null);
|
|
@@ -565,7 +572,8 @@ function KeepProviderContent({
|
|
|
565
572
|
const rememberUndo = useCallback(
|
|
566
573
|
(removedItems) => {
|
|
567
574
|
undoRef.current?.timer && clearTimeout(undoRef.current.timer);
|
|
568
|
-
const
|
|
575
|
+
const startedAt = Date.now();
|
|
576
|
+
const expiresAt = startedAt + Math.max(0, undoTimeoutMs);
|
|
569
577
|
const timer = setTimeout(
|
|
570
578
|
() => {
|
|
571
579
|
undoRef.current = void 0;
|
|
@@ -574,7 +582,7 @@ function KeepProviderContent({
|
|
|
574
582
|
Math.max(0, undoTimeoutMs)
|
|
575
583
|
);
|
|
576
584
|
undoRef.current = { items: removedItems, expiresAt, timer };
|
|
577
|
-
store.setState({ undo: { canUndo: true, ids: removedItems.map((item) => item.id), expiresAt } });
|
|
585
|
+
store.setState({ undo: { canUndo: true, ids: removedItems.map((item) => item.id), startedAt, expiresAt } });
|
|
578
586
|
},
|
|
579
587
|
[store, undoTimeoutMs]
|
|
580
588
|
);
|
|
@@ -910,7 +918,7 @@ function useKeepStore() {
|
|
|
910
918
|
return context;
|
|
911
919
|
}
|
|
912
920
|
|
|
913
|
-
// src/hooks/useKeepStoreSelector.ts
|
|
921
|
+
// src/react/hooks/useKeepStoreSelector.ts
|
|
914
922
|
import { useCallback as useCallback2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
915
923
|
function useKeepStoreSelector(store, selector) {
|
|
916
924
|
const cacheRef = useRef2(null);
|
|
@@ -925,7 +933,7 @@ function useKeepStoreSelector(store, selector) {
|
|
|
925
933
|
return useSyncExternalStore2(store.subscribe, getSelectedSnapshot, getSelectedSnapshot);
|
|
926
934
|
}
|
|
927
935
|
|
|
928
|
-
// src/hooks/useKeepItem.ts
|
|
936
|
+
// src/react/hooks/useKeepItem.ts
|
|
929
937
|
function useKeepItem(input) {
|
|
930
938
|
const { store, actions } = useKeepStore();
|
|
931
939
|
const id = input?.id ?? "";
|
|
@@ -982,7 +990,96 @@ function useKeepItem(input) {
|
|
|
982
990
|
};
|
|
983
991
|
}
|
|
984
992
|
|
|
985
|
-
// src/
|
|
993
|
+
// src/react/components/KeepButton.tsx
|
|
994
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
995
|
+
function KeepButton({
|
|
996
|
+
item,
|
|
997
|
+
children,
|
|
998
|
+
savedLabel = "Saved",
|
|
999
|
+
unsavedLabel = "Save",
|
|
1000
|
+
savedAriaLabel,
|
|
1001
|
+
unsavedAriaLabel,
|
|
1002
|
+
getAriaLabel,
|
|
1003
|
+
asChild = false,
|
|
1004
|
+
onToggleError,
|
|
1005
|
+
onClick,
|
|
1006
|
+
disabled,
|
|
1007
|
+
...buttonProps
|
|
1008
|
+
}) {
|
|
1009
|
+
const state = useKeepItem(item);
|
|
1010
|
+
const { isSaved, toggle } = state;
|
|
1011
|
+
const isDisabled = disabled ?? state.isMutating;
|
|
1012
|
+
async function handleClick(event) {
|
|
1013
|
+
if (isDisabled) return;
|
|
1014
|
+
if (asChild) {
|
|
1015
|
+
onClick?.(event);
|
|
1016
|
+
} else {
|
|
1017
|
+
onClick?.(
|
|
1018
|
+
event
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
if (event.defaultPrevented) return;
|
|
1022
|
+
try {
|
|
1023
|
+
await toggle();
|
|
1024
|
+
} catch (error) {
|
|
1025
|
+
onToggleError?.(error);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
const content = typeof children === "function" ? children(state) : children ?? (isSaved ? savedLabel : unsavedLabel);
|
|
1029
|
+
function handleElementClick(event) {
|
|
1030
|
+
if (isDisabled) return;
|
|
1031
|
+
if (asChild && isValidElement(content)) {
|
|
1032
|
+
content.props.onClick?.(event);
|
|
1033
|
+
}
|
|
1034
|
+
if (!event.defaultPrevented) void handleClick(event);
|
|
1035
|
+
}
|
|
1036
|
+
function handleKeyDown(event) {
|
|
1037
|
+
if (asChild && isValidElement(content)) {
|
|
1038
|
+
content.props.onKeyDown?.(event);
|
|
1039
|
+
}
|
|
1040
|
+
buttonProps.onKeyDown?.(event);
|
|
1041
|
+
if (!event.defaultPrevented && !isDisabled && asChild && (event.key === "Enter" || event.key === " ")) {
|
|
1042
|
+
void handleClick(event);
|
|
1043
|
+
event.preventDefault();
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
const child = asChild ? Children.only(content) : void 0;
|
|
1047
|
+
if (asChild && !isValidElement(child)) {
|
|
1048
|
+
throw new Error("KeepButton with asChild requires a single React element child.");
|
|
1049
|
+
}
|
|
1050
|
+
const commonProps = {
|
|
1051
|
+
...buttonProps,
|
|
1052
|
+
"aria-pressed": isSaved,
|
|
1053
|
+
"data-state": state.error ? "error" : isSaved ? "saved" : "unsaved",
|
|
1054
|
+
"data-loading": state.isLoading || state.isMutating ? "true" : void 0,
|
|
1055
|
+
"data-disabled": isDisabled ? "true" : void 0,
|
|
1056
|
+
"aria-label": ("aria-label" in buttonProps ? buttonProps["aria-label"] : void 0) ?? getAriaLabel?.(state) ?? (isSaved ? savedAriaLabel : unsavedAriaLabel) ?? getAccessibleLabel(isSaved, item, asChild),
|
|
1057
|
+
...asChild ? {
|
|
1058
|
+
"aria-disabled": isDisabled,
|
|
1059
|
+
role: buttonProps.role ?? "button",
|
|
1060
|
+
tabIndex: isDisabled ? -1 : buttonProps.tabIndex ?? 0
|
|
1061
|
+
} : { disabled: isDisabled },
|
|
1062
|
+
onClick: handleElementClick,
|
|
1063
|
+
onKeyDown: handleKeyDown
|
|
1064
|
+
};
|
|
1065
|
+
if (asChild) {
|
|
1066
|
+
return cloneElement(child, commonProps);
|
|
1067
|
+
}
|
|
1068
|
+
return /* @__PURE__ */ jsx2("button", { ...commonProps, type: "type" in buttonProps ? buttonProps.type ?? "button" : "button", children: content });
|
|
1069
|
+
}
|
|
1070
|
+
function getAccessibleLabel(isSaved, item, asChild) {
|
|
1071
|
+
if (!asChild) return isSaved ? "Remove saved item" : "Save item";
|
|
1072
|
+
const title = getMetaTitle(item.meta);
|
|
1073
|
+
const subject = title ? `${item.targetType ?? "item"}: ${title}` : item.targetType ?? "item";
|
|
1074
|
+
return `${isSaved ? "Remove" : "Save"} ${subject}`;
|
|
1075
|
+
}
|
|
1076
|
+
function getMetaTitle(meta) {
|
|
1077
|
+
if (typeof meta !== "object" || meta === null || !("title" in meta)) return void 0;
|
|
1078
|
+
const title = meta.title;
|
|
1079
|
+
return typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
// src/react/hooks/useKeepList.ts
|
|
986
1083
|
import { useCallback as useCallback4, useMemo as useMemo2 } from "react";
|
|
987
1084
|
function useKeepList(query = {}) {
|
|
988
1085
|
const { store, actions } = useKeepStore();
|
|
@@ -1082,7 +1179,7 @@ function sameCounts(left, right) {
|
|
|
1082
1179
|
});
|
|
1083
1180
|
}
|
|
1084
1181
|
|
|
1085
|
-
// src/hooks/useKeepNavigator.ts
|
|
1182
|
+
// src/react/hooks/useKeepNavigator.ts
|
|
1086
1183
|
import { useCallback as useCallback5, useMemo as useMemo3, useState } from "react";
|
|
1087
1184
|
function useKeepNavigator(options = {}) {
|
|
1088
1185
|
const { store } = useKeepStore();
|
|
@@ -1138,7 +1235,7 @@ function useKeepNavigator(options = {}) {
|
|
|
1138
1235
|
return { ...navigation, goToNext, goToPrev, goToIndex, goToItem };
|
|
1139
1236
|
}
|
|
1140
1237
|
|
|
1141
|
-
// src/hooks/useKeepShortcut.ts
|
|
1238
|
+
// src/react/hooks/useKeepShortcut.ts
|
|
1142
1239
|
import { useEffect as useEffect2 } from "react";
|
|
1143
1240
|
function useKeepShortcut(options) {
|
|
1144
1241
|
const item = useKeepItem(options.item);
|
|
@@ -1194,101 +1291,7 @@ function isEditableTarget(target) {
|
|
|
1194
1291
|
return target.isContentEditable || target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT";
|
|
1195
1292
|
}
|
|
1196
1293
|
|
|
1197
|
-
// src/
|
|
1198
|
-
import {
|
|
1199
|
-
Children,
|
|
1200
|
-
cloneElement,
|
|
1201
|
-
isValidElement
|
|
1202
|
-
} from "react";
|
|
1203
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1204
|
-
function KeepButton({
|
|
1205
|
-
item,
|
|
1206
|
-
children,
|
|
1207
|
-
savedLabel = "Saved",
|
|
1208
|
-
unsavedLabel = "Save",
|
|
1209
|
-
savedAriaLabel,
|
|
1210
|
-
unsavedAriaLabel,
|
|
1211
|
-
getAriaLabel,
|
|
1212
|
-
asChild = false,
|
|
1213
|
-
onToggleError,
|
|
1214
|
-
onClick,
|
|
1215
|
-
disabled,
|
|
1216
|
-
...buttonProps
|
|
1217
|
-
}) {
|
|
1218
|
-
const state = useKeepItem(item);
|
|
1219
|
-
const { isSaved, toggle } = state;
|
|
1220
|
-
const isDisabled = disabled ?? state.isMutating;
|
|
1221
|
-
async function handleClick(event) {
|
|
1222
|
-
if (isDisabled) return;
|
|
1223
|
-
if (asChild) {
|
|
1224
|
-
onClick?.(event);
|
|
1225
|
-
} else {
|
|
1226
|
-
onClick?.(
|
|
1227
|
-
event
|
|
1228
|
-
);
|
|
1229
|
-
}
|
|
1230
|
-
if (event.defaultPrevented) return;
|
|
1231
|
-
try {
|
|
1232
|
-
await toggle();
|
|
1233
|
-
} catch (error) {
|
|
1234
|
-
onToggleError?.(error);
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
const content = typeof children === "function" ? children(state) : children ?? (isSaved ? savedLabel : unsavedLabel);
|
|
1238
|
-
function handleElementClick(event) {
|
|
1239
|
-
if (isDisabled) return;
|
|
1240
|
-
if (asChild && isValidElement(content)) {
|
|
1241
|
-
content.props.onClick?.(event);
|
|
1242
|
-
}
|
|
1243
|
-
if (!event.defaultPrevented) void handleClick(event);
|
|
1244
|
-
}
|
|
1245
|
-
function handleKeyDown(event) {
|
|
1246
|
-
if (asChild && isValidElement(content)) {
|
|
1247
|
-
content.props.onKeyDown?.(event);
|
|
1248
|
-
}
|
|
1249
|
-
buttonProps.onKeyDown?.(event);
|
|
1250
|
-
if (!event.defaultPrevented && !isDisabled && asChild && (event.key === "Enter" || event.key === " ")) {
|
|
1251
|
-
void handleClick(event);
|
|
1252
|
-
event.preventDefault();
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
const child = asChild ? Children.only(content) : void 0;
|
|
1256
|
-
if (asChild && !isValidElement(child)) {
|
|
1257
|
-
throw new Error("KeepButton with asChild requires a single React element child.");
|
|
1258
|
-
}
|
|
1259
|
-
const commonProps = {
|
|
1260
|
-
...buttonProps,
|
|
1261
|
-
"aria-pressed": isSaved,
|
|
1262
|
-
"data-state": state.error ? "error" : isSaved ? "saved" : "unsaved",
|
|
1263
|
-
"data-loading": state.isLoading || state.isMutating ? "true" : void 0,
|
|
1264
|
-
"data-disabled": isDisabled ? "true" : void 0,
|
|
1265
|
-
"aria-label": ("aria-label" in buttonProps ? buttonProps["aria-label"] : void 0) ?? getAriaLabel?.(state) ?? (isSaved ? savedAriaLabel : unsavedAriaLabel) ?? getAccessibleLabel(isSaved, item, asChild),
|
|
1266
|
-
...asChild ? {
|
|
1267
|
-
"aria-disabled": isDisabled,
|
|
1268
|
-
role: buttonProps.role ?? "button",
|
|
1269
|
-
tabIndex: isDisabled ? -1 : buttonProps.tabIndex ?? 0
|
|
1270
|
-
} : { disabled: isDisabled },
|
|
1271
|
-
onClick: handleElementClick,
|
|
1272
|
-
onKeyDown: handleKeyDown
|
|
1273
|
-
};
|
|
1274
|
-
if (asChild) {
|
|
1275
|
-
return cloneElement(child, commonProps);
|
|
1276
|
-
}
|
|
1277
|
-
return /* @__PURE__ */ jsx2("button", { ...commonProps, type: "type" in buttonProps ? buttonProps.type ?? "button" : "button", children: content });
|
|
1278
|
-
}
|
|
1279
|
-
function getAccessibleLabel(isSaved, item, asChild) {
|
|
1280
|
-
if (!asChild) return isSaved ? "Remove saved item" : "Save item";
|
|
1281
|
-
const title = getMetaTitle(item.meta);
|
|
1282
|
-
const subject = title ? `${item.targetType ?? "item"}: ${title}` : item.targetType ?? "item";
|
|
1283
|
-
return `${isSaved ? "Remove" : "Save"} ${subject}`;
|
|
1284
|
-
}
|
|
1285
|
-
function getMetaTitle(meta) {
|
|
1286
|
-
if (typeof meta !== "object" || meta === null || !("title" in meta)) return void 0;
|
|
1287
|
-
const title = meta.title;
|
|
1288
|
-
return typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
// src/createKeepKit.tsx
|
|
1294
|
+
// src/react/createKeepKit.tsx
|
|
1292
1295
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1293
1296
|
function createKeepKit(options = {}) {
|
|
1294
1297
|
return {
|