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