@keepkit/ui 0.5.0 → 0.7.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/index.d.ts +148 -103
- package/dist/index.js +580 -402
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
package/dist/index.js
CHANGED
|
@@ -2,36 +2,83 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.tsx
|
|
4
4
|
import {
|
|
5
|
-
KeepButton as CoreKeepButton,
|
|
6
5
|
KeepProvider as CoreKeepProvider,
|
|
7
|
-
createKeepKit as createCoreKeepKit
|
|
8
|
-
useKeepContext,
|
|
9
|
-
useKeepItem,
|
|
10
|
-
useKeepList
|
|
6
|
+
createKeepKit as createCoreKeepKit
|
|
11
7
|
} from "@keepkit/core/react";
|
|
8
|
+
|
|
9
|
+
// src/KeepBulkActions.tsx
|
|
10
|
+
import { useKeepList } from "@keepkit/core/react";
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
|
|
13
|
+
// src/KeepItemCheckbox.tsx
|
|
14
|
+
import { jsx } from "react/jsx-runtime";
|
|
15
|
+
function KeepItemCheckbox({
|
|
16
|
+
item,
|
|
17
|
+
checked = false,
|
|
18
|
+
label,
|
|
19
|
+
onCheckedChange,
|
|
20
|
+
"aria-label": ariaLabel,
|
|
21
|
+
...props
|
|
22
|
+
}) {
|
|
23
|
+
const itemLabel = getItemLabel(item) ?? item.id;
|
|
24
|
+
const accessibleLabel = ariaLabel ?? (typeof label === "string" ? label : itemLabel);
|
|
25
|
+
return /* @__PURE__ */ jsx(
|
|
26
|
+
"input",
|
|
27
|
+
{
|
|
28
|
+
...props,
|
|
29
|
+
type: "checkbox",
|
|
30
|
+
checked,
|
|
31
|
+
"aria-label": accessibleLabel,
|
|
32
|
+
onChange: (event) => onCheckedChange?.(event.currentTarget.checked)
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
function getItemLabel(item) {
|
|
37
|
+
if (typeof item.meta !== "object" || item.meta === null || !("title" in item.meta)) return void 0;
|
|
38
|
+
const title = item.meta.title;
|
|
39
|
+
return typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/shared.tsx
|
|
12
43
|
import {
|
|
13
44
|
cloneElement,
|
|
14
|
-
|
|
15
|
-
isValidElement,
|
|
16
|
-
useCallback,
|
|
17
|
-
useContext,
|
|
18
|
-
useEffect,
|
|
19
|
-
useMemo,
|
|
20
|
-
useRef,
|
|
21
|
-
useState
|
|
45
|
+
isValidElement
|
|
22
46
|
} from "react";
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
48
|
+
function toKeepButtonItem(item) {
|
|
49
|
+
return {
|
|
50
|
+
id: item.id,
|
|
51
|
+
meta: item.meta,
|
|
52
|
+
targetType: item.targetType,
|
|
53
|
+
note: item.note,
|
|
54
|
+
tags: item.tags
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function getMetaTitle(meta) {
|
|
58
|
+
if (typeof meta !== "object" || meta === null || !("title" in meta)) return void 0;
|
|
59
|
+
const title = meta.title;
|
|
60
|
+
return typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
61
|
+
}
|
|
62
|
+
function normalizeUiTags(tags) {
|
|
63
|
+
return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];
|
|
64
|
+
}
|
|
65
|
+
function sortToValue(sort) {
|
|
66
|
+
return `${sort?.by ?? "updatedAt"}:${sort?.direction ?? "desc"}`;
|
|
67
|
+
}
|
|
68
|
+
function resolveContent(content, state) {
|
|
69
|
+
return typeof content === "function" ? content(state) : content;
|
|
70
|
+
}
|
|
71
|
+
function renderRoot(asChild, child, props, body, componentName) {
|
|
72
|
+
if (asChild) {
|
|
73
|
+
if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);
|
|
74
|
+
return cloneElement(child, { ...props, children: body });
|
|
75
|
+
}
|
|
76
|
+
return /* @__PURE__ */ jsx2("div", { ...props, children: body });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/ui-context.tsx
|
|
80
|
+
import { createContext, useContext, useMemo } from "react";
|
|
81
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
35
82
|
var DEFAULT_LABELS = {
|
|
36
83
|
save: "Save",
|
|
37
84
|
saved: "Saved",
|
|
@@ -51,6 +98,10 @@ var DEFAULT_LABELS = {
|
|
|
51
98
|
sort: "Sort saved items",
|
|
52
99
|
newest: "Newest first",
|
|
53
100
|
oldest: "Oldest first",
|
|
101
|
+
savedNewest: "Saved newest first",
|
|
102
|
+
savedOldest: "Saved oldest first",
|
|
103
|
+
updatedNewest: "Updated newest first",
|
|
104
|
+
updatedOldest: "Updated oldest first",
|
|
54
105
|
previousPage: "Previous page",
|
|
55
106
|
nextPage: "Next page",
|
|
56
107
|
pagination: "Pagination",
|
|
@@ -70,16 +121,7 @@ function KeepUiProvider({ labels, locale, labelResolver, children }) {
|
|
|
70
121
|
const resolved = { ...DEFAULT_LABELS, ...labels };
|
|
71
122
|
return { locale, labels: resolved, labelResolver };
|
|
72
123
|
}, [labelResolver, labels, locale]);
|
|
73
|
-
return /* @__PURE__ */
|
|
74
|
-
}
|
|
75
|
-
function KeepKitProvider({
|
|
76
|
-
labels,
|
|
77
|
-
locale,
|
|
78
|
-
labelResolver,
|
|
79
|
-
children,
|
|
80
|
-
...providerProps
|
|
81
|
-
}) {
|
|
82
|
-
return /* @__PURE__ */ jsx(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsx(CoreKeepProvider, { ...providerProps, children }) });
|
|
124
|
+
return /* @__PURE__ */ jsx3(KeepUiLabelsContext.Provider, { value, children });
|
|
83
125
|
}
|
|
84
126
|
function useKeepUiLabels() {
|
|
85
127
|
return useContext(KeepUiLabelsContext);
|
|
@@ -88,38 +130,107 @@ function useUiLabel(key, override) {
|
|
|
88
130
|
const context = useKeepUiLabels();
|
|
89
131
|
return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
|
|
90
132
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
133
|
+
|
|
134
|
+
// src/KeepBulkActions.tsx
|
|
135
|
+
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
136
|
+
function KeepBulkActions({
|
|
137
|
+
query,
|
|
138
|
+
selectedIds: controlledSelectedIds,
|
|
139
|
+
defaultSelectedIds = [],
|
|
140
|
+
onSelectedIdsChange,
|
|
141
|
+
renderItem,
|
|
142
|
+
onCompleted,
|
|
143
|
+
render,
|
|
144
|
+
children,
|
|
145
|
+
...props
|
|
146
|
+
}) {
|
|
147
|
+
const selectItemsLabel = useUiLabel("selectItems");
|
|
148
|
+
const selectedCountLabel = useUiLabel("selectedCount");
|
|
149
|
+
const deleteSelectedLabel = useUiLabel("deleteSelected");
|
|
150
|
+
const tagsLabel = useUiLabel("tagsToApply");
|
|
151
|
+
const applyTagsLabel = useUiLabel("applyTags");
|
|
152
|
+
const list = useKeepList(query);
|
|
153
|
+
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);
|
|
154
|
+
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
155
|
+
const selected = new Set(selectedIds);
|
|
156
|
+
const [tagsInput, setTagsInput] = useState("");
|
|
157
|
+
const setSelectedIds = (ids) => {
|
|
158
|
+
if (controlledSelectedIds === void 0) setUncontrolledSelectedIds(ids);
|
|
159
|
+
onSelectedIdsChange?.(ids);
|
|
160
|
+
};
|
|
161
|
+
const toggle = (id) => setSelectedIds(selected.has(id) ? selectedIds.filter((current) => current !== id) : [...selectedIds, id]);
|
|
162
|
+
const allSelected = list.items.length > 0 && list.items.every((item) => selected.has(item.id));
|
|
163
|
+
const toggleAll = () => setSelectedIds(allSelected ? [] : list.items.map((item) => item.id));
|
|
164
|
+
const remove = async () => {
|
|
165
|
+
const ids = [...selectedIds];
|
|
166
|
+
await list.removeBatch(ids);
|
|
167
|
+
onCompleted?.("remove", ids);
|
|
168
|
+
setSelectedIds([]);
|
|
169
|
+
};
|
|
170
|
+
const updateTags = async () => {
|
|
171
|
+
const ids = [...selectedIds];
|
|
172
|
+
await list.updateTagsBatch(ids, normalizeUiTags(tagsInput.split(",")));
|
|
173
|
+
onCompleted?.("tags", ids);
|
|
174
|
+
setSelectedIds([]);
|
|
175
|
+
};
|
|
176
|
+
const state = {
|
|
177
|
+
items: list.items,
|
|
178
|
+
selectedIds,
|
|
179
|
+
selectedCount: selectedIds.length,
|
|
180
|
+
allSelected,
|
|
181
|
+
tagsInput,
|
|
182
|
+
setTagsInput,
|
|
183
|
+
toggle,
|
|
184
|
+
toggleAll,
|
|
185
|
+
remove,
|
|
186
|
+
updateTags,
|
|
187
|
+
isMutating: list.isMutating
|
|
188
|
+
};
|
|
189
|
+
const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
190
|
+
/* @__PURE__ */ jsxs("fieldset", { children: [
|
|
191
|
+
/* @__PURE__ */ jsx4("legend", { children: selectItemsLabel }),
|
|
192
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
193
|
+
/* @__PURE__ */ jsx4("input", { type: "checkbox", checked: allSelected, onChange: toggleAll, "aria-label": selectItemsLabel }),
|
|
194
|
+
selectedIds.length,
|
|
195
|
+
" ",
|
|
196
|
+
selectedCountLabel
|
|
197
|
+
] }),
|
|
198
|
+
list.items.map((item) => /* @__PURE__ */ jsxs("span", { children: [
|
|
199
|
+
/* @__PURE__ */ jsx4(
|
|
200
|
+
KeepItemCheckbox,
|
|
201
|
+
{
|
|
202
|
+
item,
|
|
203
|
+
checked: selected.has(item.id),
|
|
204
|
+
onCheckedChange: () => toggle(item.id)
|
|
205
|
+
}
|
|
206
|
+
),
|
|
207
|
+
renderItem ? renderItem(item, selected.has(item.id)) : getMetaTitle(item.meta) ?? item.id
|
|
208
|
+
] }, item.id))
|
|
209
|
+
] }),
|
|
210
|
+
/* @__PURE__ */ jsx4("button", { type: "button", onClick: () => void remove(), disabled: selectedIds.length === 0 || list.isMutating, children: deleteSelectedLabel }),
|
|
211
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
212
|
+
tagsLabel,
|
|
213
|
+
/* @__PURE__ */ jsx4("input", { value: tagsInput, onChange: (event) => setTagsInput(event.currentTarget.value) })
|
|
214
|
+
] }),
|
|
215
|
+
/* @__PURE__ */ jsx4(
|
|
216
|
+
"button",
|
|
97
217
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
...props
|
|
218
|
+
type: "button",
|
|
219
|
+
onClick: () => void updateTags(),
|
|
220
|
+
disabled: selectedIds.length === 0 || list.isMutating,
|
|
221
|
+
children: applyTagsLabel
|
|
103
222
|
}
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
KeepCollection,
|
|
108
|
-
{
|
|
109
|
-
...props,
|
|
110
|
-
itemCardProps: {
|
|
111
|
-
...getTitle ? { getTitle } : {},
|
|
112
|
-
...getImageProps ? { getImageProps } : {},
|
|
113
|
-
...props.itemCardProps
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
),
|
|
117
|
-
useContext: () => coreKit.useContext(),
|
|
118
|
-
useItem: (item) => coreKit.useItem(item),
|
|
119
|
-
useList: (query) => coreKit.useList(query),
|
|
120
|
-
useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions)
|
|
121
|
-
};
|
|
223
|
+
)
|
|
224
|
+
] });
|
|
225
|
+
return /* @__PURE__ */ jsx4("section", { ...props, "aria-busy": list.isMutating || props["aria-busy"], children: body });
|
|
122
226
|
}
|
|
227
|
+
|
|
228
|
+
// src/KeepButton.tsx
|
|
229
|
+
import {
|
|
230
|
+
KeepButton as CoreKeepButton,
|
|
231
|
+
useKeepItem
|
|
232
|
+
} from "@keepkit/core/react";
|
|
233
|
+
import { Fragment as Fragment2, jsx as jsx5 } from "react/jsx-runtime";
|
|
123
234
|
function KeepButton({ labels, ...props }) {
|
|
124
235
|
const saveLabel = useUiLabel("save", typeof labels?.unsaved === "string" ? labels.unsaved : void 0);
|
|
125
236
|
const savedLabel = useUiLabel("saved", typeof labels?.saved === "string" ? labels.saved : void 0);
|
|
@@ -134,22 +245,6 @@ function KeepButton({ labels, ...props }) {
|
|
|
134
245
|
if (props.children !== void 0) return props.children;
|
|
135
246
|
return state.isSaved ? labels?.saved ?? savedLabel : labels?.unsaved ?? saveLabel;
|
|
136
247
|
};
|
|
137
|
-
if (props.asChild === true) {
|
|
138
|
-
const sharedProps2 = {
|
|
139
|
-
...props,
|
|
140
|
-
"aria-busy": props["aria-busy"] ?? (buttonState.isLoading || buttonState.isMutating),
|
|
141
|
-
savedLabel: labels?.saved ?? props.savedLabel ?? savedLabel,
|
|
142
|
-
unsavedLabel: labels?.unsaved ?? props.unsavedLabel ?? saveLabel,
|
|
143
|
-
savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
|
|
144
|
-
unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
|
|
145
|
-
};
|
|
146
|
-
if (!customStateLabel) return /* @__PURE__ */ jsx(CoreKeepButton, { ...sharedProps2 });
|
|
147
|
-
const statefulProps2 = {
|
|
148
|
-
...sharedProps2,
|
|
149
|
-
children: (state) => /* @__PURE__ */ jsx(Fragment, { children: getStateContent(state) })
|
|
150
|
-
};
|
|
151
|
-
return /* @__PURE__ */ jsx(CoreKeepButton, { ...statefulProps2 });
|
|
152
|
-
}
|
|
153
248
|
const sharedProps = {
|
|
154
249
|
...props,
|
|
155
250
|
"aria-busy": props["aria-busy"] ?? (buttonState.isLoading || buttonState.isMutating),
|
|
@@ -158,10 +253,22 @@ function KeepButton({ labels, ...props }) {
|
|
|
158
253
|
savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
|
|
159
254
|
unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
|
|
160
255
|
};
|
|
161
|
-
if (!customStateLabel) return /* @__PURE__ */
|
|
162
|
-
|
|
163
|
-
return /* @__PURE__ */ jsx(CoreKeepButton, { ...statefulProps });
|
|
256
|
+
if (!customStateLabel) return /* @__PURE__ */ jsx5(CoreKeepButton, { ...sharedProps });
|
|
257
|
+
return /* @__PURE__ */ jsx5(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx5(Fragment2, { children: getStateContent(state) }) });
|
|
164
258
|
}
|
|
259
|
+
|
|
260
|
+
// src/KeepCollection.tsx
|
|
261
|
+
import { useKeepList as useKeepList4 } from "@keepkit/core/react";
|
|
262
|
+
import { useMemo as useMemo3, useState as useState4 } from "react";
|
|
263
|
+
|
|
264
|
+
// src/KeepList.tsx
|
|
265
|
+
import { useKeepList as useKeepList2 } from "@keepkit/core/react";
|
|
266
|
+
import { isValidElement as isValidElement3 } from "react";
|
|
267
|
+
|
|
268
|
+
// src/KeepItemCard.tsx
|
|
269
|
+
import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
|
|
270
|
+
import { isValidElement as isValidElement2 } from "react";
|
|
271
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
165
272
|
function KeepItemCard({
|
|
166
273
|
item,
|
|
167
274
|
title,
|
|
@@ -183,8 +290,8 @@ function KeepItemCard({
|
|
|
183
290
|
}) {
|
|
184
291
|
const saveActionLabel = useUiLabel("save");
|
|
185
292
|
const removeActionLabel = useUiLabel("remove");
|
|
186
|
-
const itemState =
|
|
187
|
-
const contentChildren = asChild &&
|
|
293
|
+
const itemState = useKeepItem2(item);
|
|
294
|
+
const contentChildren = asChild && isValidElement2(children) ? void 0 : children;
|
|
188
295
|
const state = {
|
|
189
296
|
item,
|
|
190
297
|
isSaved: itemState.isSaved,
|
|
@@ -202,10 +309,10 @@ function KeepItemCard({
|
|
|
202
309
|
onRemoveError?.(error);
|
|
203
310
|
}
|
|
204
311
|
}
|
|
205
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */
|
|
206
|
-
imageProps ? renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ?? (ImageComponent ? /* @__PURE__ */
|
|
207
|
-
/* @__PURE__ */
|
|
208
|
-
showSaveButton ? /* @__PURE__ */
|
|
312
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
313
|
+
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,
|
|
314
|
+
/* @__PURE__ */ jsx6("h3", { children: resolvedTitle }),
|
|
315
|
+
showSaveButton ? /* @__PURE__ */ jsx6(
|
|
209
316
|
KeepButton,
|
|
210
317
|
{
|
|
211
318
|
item: toKeepButtonItem(item),
|
|
@@ -213,16 +320,19 @@ function KeepItemCard({
|
|
|
213
320
|
getAriaLabel: (buttonState) => `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`
|
|
214
321
|
}
|
|
215
322
|
) : null,
|
|
216
|
-
/* @__PURE__ */
|
|
323
|
+
/* @__PURE__ */ jsx6("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel })
|
|
217
324
|
] });
|
|
218
325
|
return renderRoot(
|
|
219
326
|
asChild,
|
|
220
|
-
|
|
327
|
+
isValidElement2(children) ? children : void 0,
|
|
221
328
|
{ ...rootProps, className, "aria-busy": itemState.isMutating || rootProps["aria-busy"] },
|
|
222
329
|
body,
|
|
223
330
|
"KeepItemCard"
|
|
224
331
|
);
|
|
225
332
|
}
|
|
333
|
+
|
|
334
|
+
// src/KeepList.tsx
|
|
335
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
226
336
|
function KeepList({
|
|
227
337
|
query,
|
|
228
338
|
children,
|
|
@@ -238,7 +348,7 @@ function KeepList({
|
|
|
238
348
|
const defaultLoading = useUiLabel("loadingItems");
|
|
239
349
|
const defaultEmpty = useUiLabel("noItems");
|
|
240
350
|
const defaultError = useUiLabel("errorItems");
|
|
241
|
-
const state =
|
|
351
|
+
const state = useKeepList2(query);
|
|
242
352
|
const body = getListBody(state, {
|
|
243
353
|
children,
|
|
244
354
|
renderItem,
|
|
@@ -247,10 +357,9 @@ function KeepList({
|
|
|
247
357
|
error: errorContent ?? defaultError,
|
|
248
358
|
itemCardProps
|
|
249
359
|
});
|
|
250
|
-
const root = asChild && isValidElement(children) ? children : void 0;
|
|
251
360
|
return renderRoot(
|
|
252
361
|
asChild,
|
|
253
|
-
|
|
362
|
+
asChild && isValidElement3(children) ? children : void 0,
|
|
254
363
|
{ ...rootProps, className, "aria-busy": state.isLoading || rootProps["aria-busy"] },
|
|
255
364
|
body,
|
|
256
365
|
"KeepList"
|
|
@@ -261,12 +370,196 @@ function getListBody(state, options) {
|
|
|
261
370
|
if (state.isLoading && !state.isHydrated) return resolveContent(options.loading, state);
|
|
262
371
|
if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);
|
|
263
372
|
if (typeof options.children === "function") return options.children(state);
|
|
264
|
-
if (options.children !== void 0 && !
|
|
265
|
-
|
|
266
|
-
(item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */
|
|
373
|
+
if (options.children !== void 0 && !isValidElement3(options.children)) return options.children;
|
|
374
|
+
return /* @__PURE__ */ jsx7("ul", { children: state.items.map(
|
|
375
|
+
(item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsx7(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
|
|
376
|
+
) });
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/KeepTagFilter.tsx
|
|
380
|
+
import { useKeepList as useKeepList3 } from "@keepkit/core/react";
|
|
381
|
+
import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState2 } from "react";
|
|
382
|
+
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
383
|
+
function KeepTagFilter({
|
|
384
|
+
query,
|
|
385
|
+
value: controlledValue,
|
|
386
|
+
defaultValue,
|
|
387
|
+
onChange,
|
|
388
|
+
onValueChange,
|
|
389
|
+
allLabel,
|
|
390
|
+
ariaLabel,
|
|
391
|
+
renderTag,
|
|
392
|
+
render,
|
|
393
|
+
children,
|
|
394
|
+
asChild = false,
|
|
395
|
+
className,
|
|
396
|
+
...rootProps
|
|
397
|
+
}) {
|
|
398
|
+
const uiAllLabel = useUiLabel("allTags");
|
|
399
|
+
const uiAriaLabel = useUiLabel("filterTags");
|
|
400
|
+
const [uncontrolledValue, setUncontrolledValue] = useState2(defaultValue);
|
|
401
|
+
const resolvedValue = controlledValue ?? uncontrolledValue;
|
|
402
|
+
const list = useKeepList3({
|
|
403
|
+
...query,
|
|
404
|
+
tags: resolvedValue ? [...query?.tags ?? [], resolvedValue] : query?.tags
|
|
405
|
+
});
|
|
406
|
+
const select = useCallback(
|
|
407
|
+
(tag) => {
|
|
408
|
+
if (controlledValue === void 0) setUncontrolledValue(tag);
|
|
409
|
+
onChange?.(tag);
|
|
410
|
+
onValueChange?.(tag);
|
|
411
|
+
},
|
|
412
|
+
[controlledValue, onChange, onValueChange]
|
|
413
|
+
);
|
|
414
|
+
const state = useMemo2(
|
|
415
|
+
() => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),
|
|
416
|
+
[list.tagCounts, list.tags, resolvedValue, select]
|
|
417
|
+
);
|
|
418
|
+
const contentChildren = asChild && isValidElement4(children) ? void 0 : children;
|
|
419
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs3("fieldset", { children: [
|
|
420
|
+
/* @__PURE__ */ jsx8("legend", { children: ariaLabel ?? uiAriaLabel }),
|
|
421
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
|
|
422
|
+
list.tags.map((tag) => /* @__PURE__ */ jsxs3("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
|
|
423
|
+
renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag,
|
|
424
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
425
|
+
" (",
|
|
426
|
+
list.tagCounts[tag] ?? 0,
|
|
427
|
+
")"
|
|
428
|
+
] })
|
|
429
|
+
] }, tag))
|
|
430
|
+
] });
|
|
431
|
+
return renderRoot(
|
|
432
|
+
asChild,
|
|
433
|
+
isValidElement4(children) ? children : void 0,
|
|
434
|
+
{ ...rootProps, className },
|
|
435
|
+
body,
|
|
436
|
+
"KeepTagFilter"
|
|
267
437
|
);
|
|
268
|
-
return /* @__PURE__ */ jsx("ul", { children: items });
|
|
269
438
|
}
|
|
439
|
+
|
|
440
|
+
// src/query-controls.tsx
|
|
441
|
+
import { useEffect, useState as useState3 } from "react";
|
|
442
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
443
|
+
function KeepSearchInput({
|
|
444
|
+
value: controlledValue,
|
|
445
|
+
defaultValue = "",
|
|
446
|
+
debounceMs = 300,
|
|
447
|
+
onValueChange,
|
|
448
|
+
"aria-label": ariaLabel,
|
|
449
|
+
placeholder,
|
|
450
|
+
...props
|
|
451
|
+
}) {
|
|
452
|
+
const label = useUiLabel("search");
|
|
453
|
+
const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
|
|
454
|
+
const value = controlledValue ?? uncontrolledValue;
|
|
455
|
+
useEffect(() => {
|
|
456
|
+
if (!onValueChange) return;
|
|
457
|
+
if (debounceMs <= 0) {
|
|
458
|
+
onValueChange(value);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
const timer = window.setTimeout(() => onValueChange(value), debounceMs);
|
|
462
|
+
return () => window.clearTimeout(timer);
|
|
463
|
+
}, [debounceMs, onValueChange, value]);
|
|
464
|
+
return /* @__PURE__ */ jsx9(
|
|
465
|
+
"input",
|
|
466
|
+
{
|
|
467
|
+
...props,
|
|
468
|
+
type: "search",
|
|
469
|
+
value,
|
|
470
|
+
"aria-label": ariaLabel ?? label,
|
|
471
|
+
placeholder: placeholder ?? label,
|
|
472
|
+
onChange: (event) => {
|
|
473
|
+
const nextValue = event.currentTarget.value;
|
|
474
|
+
if (controlledValue === void 0) setUncontrolledValue(nextValue);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
function KeepSortSelect({
|
|
480
|
+
value: controlledValue,
|
|
481
|
+
defaultValue = "updatedAt:desc",
|
|
482
|
+
onValueChange,
|
|
483
|
+
"aria-label": ariaLabel,
|
|
484
|
+
children,
|
|
485
|
+
...props
|
|
486
|
+
}) {
|
|
487
|
+
const label = useUiLabel("sort");
|
|
488
|
+
const updatedNewestLabel = useUiLabel("updatedNewest");
|
|
489
|
+
const updatedOldestLabel = useUiLabel("updatedOldest");
|
|
490
|
+
const savedNewestLabel = useUiLabel("savedNewest");
|
|
491
|
+
const savedOldestLabel = useUiLabel("savedOldest");
|
|
492
|
+
const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
|
|
493
|
+
const value = controlledValue ?? uncontrolledValue;
|
|
494
|
+
const options = children ?? /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
495
|
+
/* @__PURE__ */ jsx9("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
|
|
496
|
+
/* @__PURE__ */ jsx9("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
|
|
497
|
+
/* @__PURE__ */ jsx9("option", { value: "savedAt:desc", children: savedNewestLabel }),
|
|
498
|
+
/* @__PURE__ */ jsx9("option", { value: "savedAt:asc", children: savedOldestLabel })
|
|
499
|
+
] });
|
|
500
|
+
return /* @__PURE__ */ jsx9(
|
|
501
|
+
"select",
|
|
502
|
+
{
|
|
503
|
+
...props,
|
|
504
|
+
value,
|
|
505
|
+
"aria-label": ariaLabel ?? label,
|
|
506
|
+
onChange: (event) => {
|
|
507
|
+
const nextValue = event.currentTarget.value;
|
|
508
|
+
if (controlledValue === void 0) setUncontrolledValue(nextValue);
|
|
509
|
+
const [by, direction] = nextValue.split(":");
|
|
510
|
+
onValueChange?.(nextValue, { by, direction });
|
|
511
|
+
},
|
|
512
|
+
children: options
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
function KeepPagination({
|
|
517
|
+
totalCount,
|
|
518
|
+
pageSize,
|
|
519
|
+
page = 1,
|
|
520
|
+
maxPageButtons = 7,
|
|
521
|
+
onPageChange,
|
|
522
|
+
render,
|
|
523
|
+
...props
|
|
524
|
+
}) {
|
|
525
|
+
const previousPageLabel = useUiLabel("previousPage");
|
|
526
|
+
const nextPageLabel = useUiLabel("nextPage");
|
|
527
|
+
const pageLabel = useUiLabel("page");
|
|
528
|
+
const paginationLabel = useUiLabel("pagination");
|
|
529
|
+
const pageCount = Math.max(1, Math.ceil(totalCount / Math.max(1, pageSize)));
|
|
530
|
+
const currentPage = Math.min(Math.max(1, page), pageCount);
|
|
531
|
+
const goToPage = (nextPage) => {
|
|
532
|
+
const next = Math.min(Math.max(1, nextPage), pageCount);
|
|
533
|
+
onPageChange?.(next, (next - 1) * pageSize);
|
|
534
|
+
};
|
|
535
|
+
const navProps = { ...props, "aria-label": props["aria-label"] ?? paginationLabel };
|
|
536
|
+
if (render) return /* @__PURE__ */ jsx9("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
|
|
537
|
+
const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));
|
|
538
|
+
return /* @__PURE__ */ jsxs4("nav", { ...navProps, children: [
|
|
539
|
+
/* @__PURE__ */ jsx9("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
|
|
540
|
+
visiblePages.map((nextPage) => /* @__PURE__ */ jsx9(
|
|
541
|
+
"button",
|
|
542
|
+
{
|
|
543
|
+
type: "button",
|
|
544
|
+
"aria-current": nextPage === currentPage ? "page" : void 0,
|
|
545
|
+
"aria-label": `${pageLabel} ${nextPage}`,
|
|
546
|
+
onClick: () => goToPage(nextPage),
|
|
547
|
+
children: nextPage
|
|
548
|
+
},
|
|
549
|
+
nextPage
|
|
550
|
+
)),
|
|
551
|
+
/* @__PURE__ */ jsx9("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
|
|
552
|
+
] });
|
|
553
|
+
}
|
|
554
|
+
function getVisiblePages(currentPage, pageCount, maxPageButtons) {
|
|
555
|
+
if (pageCount <= maxPageButtons) return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
556
|
+
const half = Math.floor(maxPageButtons / 2);
|
|
557
|
+
const start = Math.min(Math.max(1, currentPage - half), pageCount - maxPageButtons + 1);
|
|
558
|
+
return Array.from({ length: maxPageButtons }, (_, index) => start + index);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/KeepCollection.tsx
|
|
562
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
270
563
|
function KeepCollection({
|
|
271
564
|
query = {},
|
|
272
565
|
pageSize = 20,
|
|
@@ -287,12 +580,12 @@ function KeepCollection({
|
|
|
287
580
|
bulkActions: false,
|
|
288
581
|
...features
|
|
289
582
|
};
|
|
290
|
-
const [searchValue, setSearchValue] =
|
|
291
|
-
const [sort, setSort] =
|
|
292
|
-
const [tag, setTag] =
|
|
293
|
-
const [page, setPage] =
|
|
583
|
+
const [searchValue, setSearchValue] = useState4(query.search?.query ?? "");
|
|
584
|
+
const [sort, setSort] = useState4(query.sort ?? { by: "updatedAt", direction: "desc" });
|
|
585
|
+
const [tag, setTag] = useState4(query.tags?.[0]);
|
|
586
|
+
const [page, setPage] = useState4(query.pagination?.page ?? 1);
|
|
294
587
|
const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
|
|
295
|
-
const resolvedQuery =
|
|
588
|
+
const resolvedQuery = useMemo3(
|
|
296
589
|
() => ({
|
|
297
590
|
...query,
|
|
298
591
|
search: enabled.search ? { ...query.search, query: searchValue } : query.search,
|
|
@@ -302,25 +595,48 @@ function KeepCollection({
|
|
|
302
595
|
}),
|
|
303
596
|
[enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag]
|
|
304
597
|
);
|
|
305
|
-
const list =
|
|
306
|
-
|
|
307
|
-
if (searchValue !== void 0 || sort.by !== void 0 || sort.direction !== void 0 || tag !== void 0) {
|
|
308
|
-
setPage(1);
|
|
309
|
-
}
|
|
310
|
-
}, [searchValue, sort.by, sort.direction, tag]);
|
|
311
|
-
return /* @__PURE__ */ jsxs(
|
|
598
|
+
const list = useKeepList4(resolvedQuery);
|
|
599
|
+
return /* @__PURE__ */ jsxs5(
|
|
312
600
|
"section",
|
|
313
601
|
{
|
|
314
602
|
...rootProps,
|
|
315
603
|
className,
|
|
316
604
|
"aria-busy": list.isLoading || list.isMutating || rootProps["aria-busy"],
|
|
317
605
|
children: [
|
|
318
|
-
/* @__PURE__ */
|
|
319
|
-
enabled.search ? /* @__PURE__ */
|
|
320
|
-
|
|
321
|
-
|
|
606
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
607
|
+
enabled.search ? /* @__PURE__ */ jsx10(
|
|
608
|
+
KeepSearchInput,
|
|
609
|
+
{
|
|
610
|
+
value: searchValue,
|
|
611
|
+
onValueChange: (value) => {
|
|
612
|
+
setSearchValue(value);
|
|
613
|
+
setPage(1);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
) : null,
|
|
617
|
+
enabled.sort ? /* @__PURE__ */ jsx10(
|
|
618
|
+
KeepSortSelect,
|
|
619
|
+
{
|
|
620
|
+
value: sortToValue(sort),
|
|
621
|
+
onValueChange: (_value, nextSort) => {
|
|
622
|
+
setSort(nextSort);
|
|
623
|
+
setPage(1);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
) : null,
|
|
627
|
+
enabled.tagFilter ? /* @__PURE__ */ jsx10(
|
|
628
|
+
KeepTagFilter,
|
|
629
|
+
{
|
|
630
|
+
query,
|
|
631
|
+
value: tag,
|
|
632
|
+
onValueChange: (value) => {
|
|
633
|
+
setTag(value);
|
|
634
|
+
setPage(1);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
) : null
|
|
322
638
|
] }),
|
|
323
|
-
/* @__PURE__ */
|
|
639
|
+
/* @__PURE__ */ jsx10(
|
|
324
640
|
KeepList,
|
|
325
641
|
{
|
|
326
642
|
query: resolvedQuery,
|
|
@@ -331,81 +647,37 @@ function KeepCollection({
|
|
|
331
647
|
error
|
|
332
648
|
}
|
|
333
649
|
),
|
|
334
|
-
enabled.pagination ? /* @__PURE__ */
|
|
650
|
+
enabled.pagination ? /* @__PURE__ */ jsx10(
|
|
335
651
|
KeepPagination,
|
|
336
652
|
{
|
|
337
653
|
totalCount: list.totalCount,
|
|
338
654
|
pageSize: resolvedPageSize,
|
|
339
655
|
page: list.page,
|
|
340
|
-
onPageChange: (
|
|
656
|
+
onPageChange: (nextPage) => setPage(nextPage)
|
|
341
657
|
}
|
|
342
658
|
) : null,
|
|
343
|
-
enabled.bulkActions ? /* @__PURE__ */
|
|
344
|
-
/* @__PURE__ */ jsx(KeepAnnouncements, {})
|
|
659
|
+
enabled.bulkActions ? /* @__PURE__ */ jsx10(KeepBulkActions, { query: resolvedQuery }) : null
|
|
345
660
|
]
|
|
346
661
|
}
|
|
347
662
|
);
|
|
348
663
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
asChild = false,
|
|
361
|
-
className,
|
|
362
|
-
...rootProps
|
|
363
|
-
}) {
|
|
364
|
-
const uiAllLabel = useUiLabel("allTags");
|
|
365
|
-
const uiAriaLabel = useUiLabel("filterTags");
|
|
366
|
-
const defaultAllLabel = allLabel ?? uiAllLabel;
|
|
367
|
-
const defaultAriaLabel = ariaLabel ?? uiAriaLabel;
|
|
368
|
-
const contentChildren = asChild && isValidElement(children) ? void 0 : children;
|
|
369
|
-
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
370
|
-
const value = controlledValue ?? uncontrolledValue;
|
|
371
|
-
const list = useKeepList({ ...query, tags: value ? [...query?.tags ?? [], value] : query?.tags });
|
|
372
|
-
const select = useCallback(
|
|
373
|
-
(tag) => {
|
|
374
|
-
if (controlledValue === void 0) setUncontrolledValue(tag);
|
|
375
|
-
onChange?.(tag);
|
|
376
|
-
onValueChange?.(tag);
|
|
377
|
-
},
|
|
378
|
-
[controlledValue, onChange, onValueChange]
|
|
379
|
-
);
|
|
380
|
-
const state = useMemo(
|
|
381
|
-
() => ({ tags: list.tags, tagCounts: list.tagCounts, value, select }),
|
|
382
|
-
[list.tagCounts, list.tags, select, value]
|
|
383
|
-
);
|
|
384
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
385
|
-
/* @__PURE__ */ jsx("legend", { children: defaultAriaLabel }),
|
|
386
|
-
/* @__PURE__ */ jsx("button", { type: "button", "aria-pressed": value === void 0, onClick: () => select(), children: defaultAllLabel }),
|
|
387
|
-
list.tags.map((tag) => /* @__PURE__ */ jsxs("button", { type: "button", "aria-pressed": value === tag, onClick: () => select(tag), children: [
|
|
388
|
-
renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, value === tag) : tag,
|
|
389
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
390
|
-
" (",
|
|
391
|
-
list.tagCounts[tag] ?? 0,
|
|
392
|
-
")"
|
|
393
|
-
] })
|
|
394
|
-
] }, tag))
|
|
395
|
-
] });
|
|
396
|
-
return renderRoot(
|
|
397
|
-
asChild,
|
|
398
|
-
isValidElement(children) ? children : void 0,
|
|
399
|
-
{ ...rootProps, className },
|
|
400
|
-
body,
|
|
401
|
-
"KeepTagFilter"
|
|
402
|
-
);
|
|
403
|
-
}
|
|
664
|
+
|
|
665
|
+
// src/KeepNoteEditor.tsx
|
|
666
|
+
import { useKeepItem as useKeepItem3 } from "@keepkit/core/react";
|
|
667
|
+
import {
|
|
668
|
+
isValidElement as isValidElement5,
|
|
669
|
+
useCallback as useCallback2,
|
|
670
|
+
useEffect as useEffect2,
|
|
671
|
+
useRef,
|
|
672
|
+
useState as useState5
|
|
673
|
+
} from "react";
|
|
674
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
404
675
|
function KeepNoteEditor({
|
|
405
676
|
item,
|
|
406
677
|
label,
|
|
407
678
|
saveLabel,
|
|
408
679
|
placeholder,
|
|
680
|
+
debounceMs = 300,
|
|
409
681
|
onSaved,
|
|
410
682
|
onSaveError,
|
|
411
683
|
render,
|
|
@@ -416,162 +688,89 @@ function KeepNoteEditor({
|
|
|
416
688
|
}) {
|
|
417
689
|
const defaultLabel = useUiLabel("note");
|
|
418
690
|
const defaultSaveLabel = useUiLabel("saveNote");
|
|
419
|
-
const itemState =
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
const
|
|
691
|
+
const itemState = useKeepItem3(item);
|
|
692
|
+
const { error, isMutating, item: savedItem, updateNote } = itemState;
|
|
693
|
+
const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
|
|
694
|
+
const [note, setNote] = useState5(item.note ?? "");
|
|
695
|
+
const baselineNote = savedItem?.note ?? item.note ?? "";
|
|
696
|
+
const isDirty = note !== baselineNote;
|
|
697
|
+
const lastSavedNoteRef = useRef(void 0);
|
|
698
|
+
useEffect2(() => setNote(baselineNote), [baselineNote]);
|
|
699
|
+
const save = useCallback2(async () => {
|
|
424
700
|
const nextNote = note.trim() || void 0;
|
|
425
701
|
try {
|
|
426
|
-
await
|
|
702
|
+
await updateNote(nextNote);
|
|
703
|
+
lastSavedNoteRef.current = note;
|
|
427
704
|
onSaved?.(nextNote);
|
|
428
|
-
} catch (
|
|
429
|
-
onSaveError?.(
|
|
430
|
-
throw
|
|
705
|
+
} catch (error2) {
|
|
706
|
+
onSaveError?.(error2);
|
|
707
|
+
throw error2;
|
|
431
708
|
}
|
|
432
|
-
}, [
|
|
709
|
+
}, [note, onSaveError, onSaved, updateNote]);
|
|
710
|
+
useEffect2(() => {
|
|
711
|
+
if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;
|
|
712
|
+
const timer = window.setTimeout(() => void save().catch(() => void 0), debounceMs);
|
|
713
|
+
return () => window.clearTimeout(timer);
|
|
714
|
+
}, [debounceMs, isDirty, note, save]);
|
|
433
715
|
const state = {
|
|
434
716
|
item,
|
|
435
717
|
note,
|
|
436
718
|
setNote,
|
|
437
|
-
isDirty
|
|
438
|
-
isSaving:
|
|
439
|
-
error
|
|
719
|
+
isDirty,
|
|
720
|
+
isSaving: isMutating,
|
|
721
|
+
error,
|
|
440
722
|
save
|
|
441
723
|
};
|
|
442
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */
|
|
443
|
-
/* @__PURE__ */
|
|
724
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs6(Fragment5, { children: [
|
|
725
|
+
/* @__PURE__ */ jsxs6("label", { children: [
|
|
444
726
|
label ?? defaultLabel,
|
|
445
|
-
/* @__PURE__ */
|
|
727
|
+
/* @__PURE__ */ jsx11(
|
|
446
728
|
"textarea",
|
|
447
729
|
{
|
|
448
730
|
value: note,
|
|
449
731
|
onChange: (event) => setNote(event.currentTarget.value),
|
|
450
732
|
placeholder,
|
|
451
|
-
disabled:
|
|
733
|
+
disabled: isMutating,
|
|
734
|
+
onKeyDown: (event) => {
|
|
735
|
+
if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
|
|
736
|
+
event.preventDefault();
|
|
737
|
+
void save().catch(() => void 0);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
452
740
|
}
|
|
453
741
|
)
|
|
454
742
|
] }),
|
|
455
|
-
/* @__PURE__ */
|
|
743
|
+
/* @__PURE__ */ jsx11("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
|
|
456
744
|
] });
|
|
457
745
|
const handleSubmit = (event) => {
|
|
458
746
|
event.preventDefault();
|
|
459
747
|
void save().catch(() => void 0);
|
|
460
748
|
};
|
|
461
749
|
if (!asChild) {
|
|
462
|
-
return /* @__PURE__ */
|
|
750
|
+
return /* @__PURE__ */ jsx11(
|
|
463
751
|
"form",
|
|
464
752
|
{
|
|
465
753
|
...formProps,
|
|
466
754
|
className,
|
|
467
755
|
onSubmit: handleSubmit,
|
|
468
|
-
"aria-busy":
|
|
756
|
+
"aria-busy": isMutating || formProps["aria-busy"],
|
|
469
757
|
children: body
|
|
470
758
|
}
|
|
471
759
|
);
|
|
472
760
|
}
|
|
473
761
|
return renderRoot(
|
|
474
762
|
true,
|
|
475
|
-
|
|
476
|
-
{ ...formProps, className, onSubmit: handleSubmit, "aria-busy":
|
|
763
|
+
isValidElement5(children) ? children : void 0,
|
|
764
|
+
{ ...formProps, className, onSubmit: handleSubmit, "aria-busy": isMutating || formProps["aria-busy"] },
|
|
477
765
|
body,
|
|
478
766
|
"KeepNoteEditor"
|
|
479
767
|
);
|
|
480
768
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
placeholder,
|
|
487
|
-
...props
|
|
488
|
-
}) {
|
|
489
|
-
const label = useUiLabel("search");
|
|
490
|
-
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
491
|
-
const value = controlledValue ?? uncontrolledValue;
|
|
492
|
-
return /* @__PURE__ */ jsx(
|
|
493
|
-
"input",
|
|
494
|
-
{
|
|
495
|
-
...props,
|
|
496
|
-
type: "search",
|
|
497
|
-
value,
|
|
498
|
-
"aria-label": ariaLabel ?? label,
|
|
499
|
-
placeholder: placeholder ?? label,
|
|
500
|
-
onChange: (event) => {
|
|
501
|
-
const nextValue = event.currentTarget.value;
|
|
502
|
-
if (controlledValue === void 0) setUncontrolledValue(nextValue);
|
|
503
|
-
onValueChange?.(nextValue);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
function KeepSortSelect({
|
|
509
|
-
value: controlledValue,
|
|
510
|
-
defaultValue = "updatedAt:desc",
|
|
511
|
-
onValueChange,
|
|
512
|
-
"aria-label": ariaLabel,
|
|
513
|
-
children,
|
|
514
|
-
...props
|
|
515
|
-
}) {
|
|
516
|
-
const label = useUiLabel("sort");
|
|
517
|
-
const newestLabel = useUiLabel("newest");
|
|
518
|
-
const savedLabel = useUiLabel("saved");
|
|
519
|
-
const oldestLabel = useUiLabel("oldest");
|
|
520
|
-
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
521
|
-
const value = controlledValue ?? uncontrolledValue;
|
|
522
|
-
const options = children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
523
|
-
/* @__PURE__ */ jsx("option", { value: "updatedAt:desc", children: newestLabel }),
|
|
524
|
-
/* @__PURE__ */ jsx("option", { value: "savedAt:desc", children: savedLabel }),
|
|
525
|
-
/* @__PURE__ */ jsx("option", { value: "updatedAt:asc", children: oldestLabel }),
|
|
526
|
-
/* @__PURE__ */ jsx("option", { value: "savedAt:asc", children: oldestLabel })
|
|
527
|
-
] });
|
|
528
|
-
return /* @__PURE__ */ jsx(
|
|
529
|
-
"select",
|
|
530
|
-
{
|
|
531
|
-
...props,
|
|
532
|
-
value,
|
|
533
|
-
"aria-label": ariaLabel ?? label,
|
|
534
|
-
onChange: (event) => {
|
|
535
|
-
const nextValue = event.currentTarget.value;
|
|
536
|
-
if (controlledValue === void 0) setUncontrolledValue(nextValue);
|
|
537
|
-
const [by, direction] = nextValue.split(":");
|
|
538
|
-
onValueChange?.(nextValue, { by, direction });
|
|
539
|
-
},
|
|
540
|
-
children: options
|
|
541
|
-
}
|
|
542
|
-
);
|
|
543
|
-
}
|
|
544
|
-
function KeepPagination({
|
|
545
|
-
totalCount,
|
|
546
|
-
pageSize,
|
|
547
|
-
page = 1,
|
|
548
|
-
onPageChange,
|
|
549
|
-
render,
|
|
550
|
-
...props
|
|
551
|
-
}) {
|
|
552
|
-
const previousPageLabel = useUiLabel("previousPage");
|
|
553
|
-
const nextPageLabel = useUiLabel("nextPage");
|
|
554
|
-
const pageLabel = useUiLabel("page");
|
|
555
|
-
const paginationLabel = useUiLabel("pagination");
|
|
556
|
-
const pageCount = Math.max(1, Math.ceil(totalCount / Math.max(1, pageSize)));
|
|
557
|
-
const currentPage = Math.min(Math.max(1, page), pageCount);
|
|
558
|
-
const goToPage = (nextPage) => {
|
|
559
|
-
const next = Math.min(Math.max(1, nextPage), pageCount);
|
|
560
|
-
onPageChange?.(next, (next - 1) * pageSize);
|
|
561
|
-
};
|
|
562
|
-
if (render) return /* @__PURE__ */ jsx("nav", { ...props, children: render({ page: currentPage, pageCount, goToPage }) });
|
|
563
|
-
return /* @__PURE__ */ jsxs("nav", { ...props, "aria-label": props["aria-label"] ?? paginationLabel, children: [
|
|
564
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
|
|
565
|
-
/* @__PURE__ */ jsxs("span", { "aria-current": "page", children: [
|
|
566
|
-
pageLabel,
|
|
567
|
-
" ",
|
|
568
|
-
currentPage,
|
|
569
|
-
" / ",
|
|
570
|
-
pageCount
|
|
571
|
-
] }),
|
|
572
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
|
|
573
|
-
] });
|
|
574
|
-
}
|
|
769
|
+
|
|
770
|
+
// src/KeepTagEditor.tsx
|
|
771
|
+
import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
|
|
772
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useState as useState6 } from "react";
|
|
773
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
575
774
|
function KeepTagEditor({
|
|
576
775
|
item,
|
|
577
776
|
availableTags = [],
|
|
@@ -583,11 +782,11 @@ function KeepTagEditor({
|
|
|
583
782
|
const tagsLabel = useUiLabel("tagsToApply");
|
|
584
783
|
const removeLabel = useUiLabel("remove");
|
|
585
784
|
const applyTagsLabel = useUiLabel("applyTags");
|
|
586
|
-
const itemState =
|
|
587
|
-
const [tags, setTags] =
|
|
588
|
-
const [input, setInput] =
|
|
589
|
-
|
|
590
|
-
const save =
|
|
785
|
+
const itemState = useKeepItem4(item);
|
|
786
|
+
const [tags, setTags] = useState6(item.tags ?? []);
|
|
787
|
+
const [input, setInput] = useState6("");
|
|
788
|
+
useEffect3(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
|
|
789
|
+
const save = useCallback3(async () => {
|
|
591
790
|
const nextTags = normalizeUiTags(tags);
|
|
592
791
|
try {
|
|
593
792
|
await itemState.updateTags(nextTags);
|
|
@@ -599,14 +798,13 @@ function KeepTagEditor({
|
|
|
599
798
|
}
|
|
600
799
|
}, [itemState, onSaveError, onSaved, tags]);
|
|
601
800
|
const addTag = (tag) => {
|
|
602
|
-
|
|
603
|
-
setTags(next);
|
|
801
|
+
setTags(normalizeUiTags([...tags, tag]));
|
|
604
802
|
setInput("");
|
|
605
803
|
};
|
|
606
|
-
const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */
|
|
607
|
-
/* @__PURE__ */
|
|
804
|
+
const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs7(Fragment6, { children: [
|
|
805
|
+
/* @__PURE__ */ jsxs7("label", { children: [
|
|
608
806
|
tagsLabel,
|
|
609
|
-
/* @__PURE__ */
|
|
807
|
+
/* @__PURE__ */ jsx12(
|
|
610
808
|
"input",
|
|
611
809
|
{
|
|
612
810
|
value: input,
|
|
@@ -616,19 +814,22 @@ function KeepTagEditor({
|
|
|
616
814
|
if (event.key === "Enter") {
|
|
617
815
|
event.preventDefault();
|
|
618
816
|
if (input.trim()) addTag(input);
|
|
817
|
+
} else if (event.key === "Backspace" && input.length === 0 && tags.length > 0) {
|
|
818
|
+
event.preventDefault();
|
|
819
|
+
setTags(tags.slice(0, -1));
|
|
619
820
|
}
|
|
620
821
|
}
|
|
621
822
|
}
|
|
622
823
|
)
|
|
623
824
|
] }),
|
|
624
|
-
availableTags.length > 0 ? /* @__PURE__ */
|
|
625
|
-
/* @__PURE__ */
|
|
825
|
+
availableTags.length > 0 ? /* @__PURE__ */ jsx12("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx12("option", { value: tag }, tag)) }) : null,
|
|
826
|
+
/* @__PURE__ */ jsx12("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs7("li", { children: [
|
|
626
827
|
tag,
|
|
627
|
-
/* @__PURE__ */
|
|
828
|
+
/* @__PURE__ */ jsx12("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
|
|
628
829
|
] }, tag)) }),
|
|
629
|
-
/* @__PURE__ */
|
|
830
|
+
/* @__PURE__ */ jsx12("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
|
|
630
831
|
] });
|
|
631
|
-
return /* @__PURE__ */
|
|
832
|
+
return /* @__PURE__ */ jsx12(
|
|
632
833
|
"form",
|
|
633
834
|
{
|
|
634
835
|
...props,
|
|
@@ -641,65 +842,11 @@ function KeepTagEditor({
|
|
|
641
842
|
}
|
|
642
843
|
);
|
|
643
844
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
renderItem,
|
|
650
|
-
onCompleted,
|
|
651
|
-
...props
|
|
652
|
-
}) {
|
|
653
|
-
const selectItemsLabel = useUiLabel("selectItems");
|
|
654
|
-
const selectedCountLabel = useUiLabel("selectedCount");
|
|
655
|
-
const deleteSelectedLabel = useUiLabel("deleteSelected");
|
|
656
|
-
const tagsLabel = useUiLabel("tagsToApply");
|
|
657
|
-
const applyTagsLabel = useUiLabel("applyTags");
|
|
658
|
-
const list = useKeepList(query);
|
|
659
|
-
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);
|
|
660
|
-
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
661
|
-
const selected = new Set(selectedIds);
|
|
662
|
-
const [tagsInput, setTagsInput] = useState("");
|
|
663
|
-
const setSelectedIds = (ids) => {
|
|
664
|
-
if (controlledSelectedIds === void 0) setUncontrolledSelectedIds(ids);
|
|
665
|
-
onSelectedIdsChange?.(ids);
|
|
666
|
-
};
|
|
667
|
-
const toggle = (id) => setSelectedIds(selected.has(id) ? selectedIds.filter((current) => current !== id) : [...selectedIds, id]);
|
|
668
|
-
const allSelected = list.items.length > 0 && list.items.every((item) => selected.has(item.id));
|
|
669
|
-
const toggleAll = () => setSelectedIds(allSelected ? [] : list.items.map((item) => item.id));
|
|
670
|
-
const remove = async () => {
|
|
671
|
-
await list.removeBatch(selectedIds);
|
|
672
|
-
onCompleted?.("remove", selectedIds);
|
|
673
|
-
setSelectedIds([]);
|
|
674
|
-
};
|
|
675
|
-
const updateTags = async () => {
|
|
676
|
-
const tags = normalizeUiTags(tagsInput.split(","));
|
|
677
|
-
await list.updateTagsBatch(selectedIds, tags);
|
|
678
|
-
onCompleted?.("tags", selectedIds);
|
|
679
|
-
setSelectedIds([]);
|
|
680
|
-
};
|
|
681
|
-
return /* @__PURE__ */ jsxs("section", { ...props, "aria-busy": list.isMutating || props["aria-busy"], children: [
|
|
682
|
-
/* @__PURE__ */ jsxs("fieldset", { children: [
|
|
683
|
-
/* @__PURE__ */ jsx("legend", { children: selectItemsLabel }),
|
|
684
|
-
/* @__PURE__ */ jsxs("label", { children: [
|
|
685
|
-
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: allSelected, onChange: toggleAll }),
|
|
686
|
-
selectedIds.length,
|
|
687
|
-
" ",
|
|
688
|
-
selectedCountLabel
|
|
689
|
-
] }),
|
|
690
|
-
list.items.map((item) => /* @__PURE__ */ jsxs("label", { children: [
|
|
691
|
-
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: selected.has(item.id), onChange: () => toggle(item.id) }),
|
|
692
|
-
renderItem ? renderItem(item, selected.has(item.id)) : getMetaTitle(item.meta) ?? item.id
|
|
693
|
-
] }, item.id))
|
|
694
|
-
] }),
|
|
695
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => void remove(), disabled: selectedIds.length === 0 || list.isMutating, children: deleteSelectedLabel }),
|
|
696
|
-
/* @__PURE__ */ jsxs("label", { children: [
|
|
697
|
-
tagsLabel,
|
|
698
|
-
/* @__PURE__ */ jsx("input", { value: tagsInput, onChange: (event) => setTagsInput(event.currentTarget.value) })
|
|
699
|
-
] }),
|
|
700
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => void updateTags(), disabled: selectedIds.length === 0 || list.isMutating, children: applyTagsLabel })
|
|
701
|
-
] });
|
|
702
|
-
}
|
|
845
|
+
|
|
846
|
+
// src/status.tsx
|
|
847
|
+
import { useKeepContext } from "@keepkit/core/react";
|
|
848
|
+
import { isValidElement as isValidElement6, useEffect as useEffect4, useRef as useRef2, useState as useState7 } from "react";
|
|
849
|
+
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
703
850
|
function KeepEmptyState({
|
|
704
851
|
title,
|
|
705
852
|
description,
|
|
@@ -710,10 +857,10 @@ function KeepEmptyState({
|
|
|
710
857
|
...rootProps
|
|
711
858
|
}) {
|
|
712
859
|
const defaultTitle = useUiLabel("noItems").replace(/\.$/, "");
|
|
713
|
-
const contentChildren = asChild &&
|
|
714
|
-
const body = contentChildren ?? /* @__PURE__ */
|
|
715
|
-
/* @__PURE__ */
|
|
716
|
-
description ? /* @__PURE__ */
|
|
860
|
+
const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
|
|
861
|
+
const body = contentChildren ?? /* @__PURE__ */ jsxs8(Fragment7, { children: [
|
|
862
|
+
/* @__PURE__ */ jsx13("h2", { children: title ?? defaultTitle }),
|
|
863
|
+
description ? /* @__PURE__ */ jsx13("p", { children: description }) : null,
|
|
717
864
|
action
|
|
718
865
|
] });
|
|
719
866
|
return renderRoot(asChild, children, { ...rootProps, className }, body, "KeepEmptyState");
|
|
@@ -728,7 +875,7 @@ function KeepStatus({
|
|
|
728
875
|
...rootProps
|
|
729
876
|
}) {
|
|
730
877
|
const context = useKeepContext();
|
|
731
|
-
const contentChildren = asChild &&
|
|
878
|
+
const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
|
|
732
879
|
const resolvedStatus = status ?? getDerivedStatus(context);
|
|
733
880
|
const defaultLabel = useUiLabel(getStatusLabelKey(resolvedStatus));
|
|
734
881
|
const state = {
|
|
@@ -741,7 +888,7 @@ function KeepStatus({
|
|
|
741
888
|
const role = rootProps.role ?? (resolvedStatus === "error" ? "alert" : "status");
|
|
742
889
|
return renderRoot(
|
|
743
890
|
asChild,
|
|
744
|
-
|
|
891
|
+
isValidElement6(children) ? children : void 0,
|
|
745
892
|
{ ...rootProps, className, role, "aria-live": rootProps["aria-live"] ?? "polite" },
|
|
746
893
|
body,
|
|
747
894
|
"KeepStatus"
|
|
@@ -752,9 +899,9 @@ function KeepAnnouncements({ messages, ...props }) {
|
|
|
752
899
|
const savedMessage = useUiLabel("savedMessage", messages?.save);
|
|
753
900
|
const removedMessage = useUiLabel("removedMessage", messages?.remove);
|
|
754
901
|
const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
|
|
755
|
-
const [message, setMessage] =
|
|
756
|
-
const lastChangeRef =
|
|
757
|
-
|
|
902
|
+
const [message, setMessage] = useState7("");
|
|
903
|
+
const lastChangeRef = useRef2(void 0);
|
|
904
|
+
useEffect4(() => {
|
|
758
905
|
const change = context.lastChange;
|
|
759
906
|
if (!change || change === lastChangeRef.current) return;
|
|
760
907
|
lastChangeRef.current = change;
|
|
@@ -762,8 +909,9 @@ function KeepAnnouncements({ messages, ...props }) {
|
|
|
762
909
|
else if (change.action === "remove" || change.action === "removeBatch") setMessage(removedMessage);
|
|
763
910
|
else if (change.action === "updateNote") setMessage(noteSavedMessage);
|
|
764
911
|
}, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);
|
|
765
|
-
return /* @__PURE__ */
|
|
912
|
+
return /* @__PURE__ */ jsx13("div", { ...props, role: props.role ?? "status", "aria-live": props["aria-live"] ?? "polite", "aria-atomic": "true", children: message });
|
|
766
913
|
}
|
|
914
|
+
var KeepAnnouncer = KeepAnnouncements;
|
|
767
915
|
function getDerivedStatus(context) {
|
|
768
916
|
if (context.error) return "error";
|
|
769
917
|
if (context.syncState.status === "pending" || context.syncState.status === "syncing") return "syncing";
|
|
@@ -780,46 +928,76 @@ function getStatusLabelKey(status) {
|
|
|
780
928
|
if (status === "syncing") return "syncing";
|
|
781
929
|
return "saved";
|
|
782
930
|
}
|
|
783
|
-
|
|
784
|
-
|
|
931
|
+
|
|
932
|
+
// src/index.tsx
|
|
933
|
+
import { KeepProvider, useKeepContext as useKeepContext2, useKeepItem as useKeepItem5, useKeepList as useKeepList5, useKeepShortcut } from "@keepkit/core/react";
|
|
934
|
+
import {
|
|
935
|
+
createBrowserStorageAdapter,
|
|
936
|
+
createStorageAdapter,
|
|
937
|
+
FallbackStorageAdapter,
|
|
938
|
+
IndexedDBAdapter,
|
|
939
|
+
IndexedDBSyncQueueAdapter,
|
|
940
|
+
LocalStorageAdapter,
|
|
941
|
+
LocalStorageSyncQueueAdapter,
|
|
942
|
+
SyncStorageAdapter
|
|
943
|
+
} from "@keepkit/core/storage";
|
|
944
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
945
|
+
function KeepKitProvider({
|
|
946
|
+
labels,
|
|
947
|
+
locale,
|
|
948
|
+
labelResolver,
|
|
949
|
+
children,
|
|
950
|
+
...providerProps
|
|
951
|
+
}) {
|
|
952
|
+
return /* @__PURE__ */ jsx14(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsxs9(CoreKeepProvider, { ...providerProps, children: [
|
|
953
|
+
children,
|
|
954
|
+
/* @__PURE__ */ jsx14(KeepAnnouncements, {})
|
|
955
|
+
] }) });
|
|
785
956
|
}
|
|
786
|
-
function
|
|
957
|
+
function createKeepKit(options = {}) {
|
|
958
|
+
const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;
|
|
959
|
+
const coreKit = createCoreKeepKit(coreOptions);
|
|
787
960
|
return {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
961
|
+
Provider: (props) => /* @__PURE__ */ jsx14(
|
|
962
|
+
KeepKitProvider,
|
|
963
|
+
{
|
|
964
|
+
...coreOptions,
|
|
965
|
+
labels,
|
|
966
|
+
locale,
|
|
967
|
+
labelResolver,
|
|
968
|
+
...props
|
|
969
|
+
}
|
|
970
|
+
),
|
|
971
|
+
Button: (props) => /* @__PURE__ */ jsx14(KeepButton, { ...props }),
|
|
972
|
+
Collection: (props) => /* @__PURE__ */ jsx14(
|
|
973
|
+
KeepCollection,
|
|
974
|
+
{
|
|
975
|
+
...props,
|
|
976
|
+
itemCardProps: {
|
|
977
|
+
...getTitle ? { getTitle } : {},
|
|
978
|
+
...getImageProps ? { getImageProps } : {},
|
|
979
|
+
...props.itemCardProps
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
),
|
|
983
|
+
useContext: () => coreKit.useContext(),
|
|
984
|
+
useItem: (item) => coreKit.useItem(item),
|
|
985
|
+
useList: (query) => coreKit.useList(query),
|
|
986
|
+
useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions)
|
|
793
987
|
};
|
|
794
988
|
}
|
|
795
|
-
function getMetaTitle(meta) {
|
|
796
|
-
if (typeof meta !== "object" || meta === null || !("title" in meta)) return void 0;
|
|
797
|
-
const title = meta.title;
|
|
798
|
-
return typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
799
|
-
}
|
|
800
|
-
function normalizeUiTags(tags) {
|
|
801
|
-
return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];
|
|
802
|
-
}
|
|
803
|
-
function sortToValue(sort) {
|
|
804
|
-
return `${sort?.by ?? "updatedAt"}:${sort?.direction ?? "desc"}`;
|
|
805
|
-
}
|
|
806
|
-
function renderRoot(asChild, child, props, body, componentName) {
|
|
807
|
-
if (asChild) {
|
|
808
|
-
if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);
|
|
809
|
-
return cloneElement(child, { ...props, children: body });
|
|
810
|
-
}
|
|
811
|
-
return /* @__PURE__ */ jsx("div", { ...props, children: body });
|
|
812
|
-
}
|
|
813
989
|
export {
|
|
814
990
|
FallbackStorageAdapter,
|
|
815
991
|
IndexedDBAdapter,
|
|
816
992
|
IndexedDBSyncQueueAdapter,
|
|
817
993
|
KeepAnnouncements,
|
|
994
|
+
KeepAnnouncer,
|
|
818
995
|
KeepBulkActions,
|
|
819
996
|
KeepButton,
|
|
820
997
|
KeepCollection,
|
|
821
998
|
KeepEmptyState,
|
|
822
999
|
KeepItemCard,
|
|
1000
|
+
KeepItemCheckbox,
|
|
823
1001
|
KeepKitProvider,
|
|
824
1002
|
KeepList,
|
|
825
1003
|
KeepNoteEditor,
|
|
@@ -838,8 +1016,8 @@ export {
|
|
|
838
1016
|
createKeepKit,
|
|
839
1017
|
createStorageAdapter,
|
|
840
1018
|
useKeepContext2 as useKeepContext,
|
|
841
|
-
|
|
842
|
-
|
|
1019
|
+
useKeepItem5 as useKeepItem,
|
|
1020
|
+
useKeepList5 as useKeepList,
|
|
843
1021
|
useKeepShortcut,
|
|
844
1022
|
useKeepUiLabels
|
|
845
1023
|
};
|