@keepkit/ui 0.6.0 → 0.8.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 +162 -141
- package/dist/index.js +550 -456
- 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,122 @@ 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
|
-
onValueChange,
|
|
116
|
-
"aria-label": ariaLabel,
|
|
117
|
-
placeholder,
|
|
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
|
-
);
|
|
134
|
+
// src/KeepBulkActions.tsx
|
|
135
|
+
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
136
|
+
function isAllSelected(items, selectedIds) {
|
|
137
|
+
if (items.length === 0) return false;
|
|
138
|
+
const selected = new Set(selectedIds);
|
|
139
|
+
return items.every((item) => selected.has(item.id));
|
|
146
140
|
}
|
|
147
|
-
function
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
);
|
|
141
|
+
function toggleSelectAll(items, selectedIds) {
|
|
142
|
+
const visibleIds = new Set(items.map((item) => item.id));
|
|
143
|
+
if (isAllSelected(items, selectedIds)) return selectedIds.filter((id) => !visibleIds.has(id));
|
|
144
|
+
const nextIds = [...selectedIds];
|
|
145
|
+
for (const item of items) {
|
|
146
|
+
if (!nextIds.includes(item.id)) nextIds.push(item.id);
|
|
147
|
+
}
|
|
148
|
+
return nextIds;
|
|
183
149
|
}
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
150
|
+
function KeepBulkActions({
|
|
151
|
+
query,
|
|
152
|
+
selectedIds: controlledSelectedIds,
|
|
153
|
+
defaultSelectedIds = [],
|
|
154
|
+
onSelectedIdsChange,
|
|
155
|
+
renderItem,
|
|
156
|
+
onCompleted,
|
|
190
157
|
render,
|
|
158
|
+
children,
|
|
191
159
|
...props
|
|
192
160
|
}) {
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
161
|
+
const selectItemsLabel = useUiLabel("selectItems");
|
|
162
|
+
const selectedCountLabel = useUiLabel("selectedCount");
|
|
163
|
+
const deleteSelectedLabel = useUiLabel("deleteSelected");
|
|
164
|
+
const tagsLabel = useUiLabel("tagsToApply");
|
|
165
|
+
const applyTagsLabel = useUiLabel("applyTags");
|
|
166
|
+
const list = useKeepList(query);
|
|
167
|
+
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);
|
|
168
|
+
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
169
|
+
const selected = new Set(selectedIds);
|
|
170
|
+
const [tagsInput, setTagsInput] = useState("");
|
|
171
|
+
const setSelectedIds = (ids) => {
|
|
172
|
+
if (controlledSelectedIds === void 0) setUncontrolledSelectedIds(ids);
|
|
173
|
+
onSelectedIdsChange?.(ids);
|
|
202
174
|
};
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
175
|
+
const toggle = (id) => setSelectedIds(selected.has(id) ? selectedIds.filter((current) => current !== id) : [...selectedIds, id]);
|
|
176
|
+
const allSelected = isAllSelected(list.items, selectedIds);
|
|
177
|
+
const toggleAll = () => setSelectedIds(toggleSelectAll(list.items, selectedIds));
|
|
178
|
+
const remove = async () => {
|
|
179
|
+
const ids = [...selectedIds];
|
|
180
|
+
await list.removeBatch(ids);
|
|
181
|
+
onCompleted?.("remove", ids);
|
|
182
|
+
setSelectedIds([]);
|
|
183
|
+
};
|
|
184
|
+
const updateTags = async () => {
|
|
185
|
+
const ids = [...selectedIds];
|
|
186
|
+
await list.updateTagsBatch(ids, normalizeUiTags(tagsInput.split(",")));
|
|
187
|
+
onCompleted?.("tags", ids);
|
|
188
|
+
setSelectedIds([]);
|
|
189
|
+
};
|
|
190
|
+
const state = {
|
|
191
|
+
items: list.items,
|
|
192
|
+
selectedIds,
|
|
193
|
+
selectedCount: selectedIds.length,
|
|
194
|
+
isAllSelected: allSelected,
|
|
195
|
+
allSelected,
|
|
196
|
+
tagsInput,
|
|
197
|
+
setTagsInput,
|
|
198
|
+
toggle,
|
|
199
|
+
toggleSelectAll: toggleAll,
|
|
200
|
+
toggleAll,
|
|
201
|
+
remove,
|
|
202
|
+
updateTags,
|
|
203
|
+
isMutating: list.isMutating
|
|
204
|
+
};
|
|
205
|
+
const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
206
|
+
/* @__PURE__ */ jsxs("fieldset", { children: [
|
|
207
|
+
/* @__PURE__ */ jsx4("legend", { children: selectItemsLabel }),
|
|
208
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
209
|
+
/* @__PURE__ */ jsx4("input", { type: "checkbox", checked: allSelected, onChange: toggleAll, "aria-label": selectItemsLabel }),
|
|
210
|
+
selectedIds.length,
|
|
211
|
+
" ",
|
|
212
|
+
selectedCountLabel
|
|
213
|
+
] }),
|
|
214
|
+
list.items.map((item) => /* @__PURE__ */ jsxs("span", { children: [
|
|
215
|
+
/* @__PURE__ */ jsx4(
|
|
216
|
+
KeepItemCheckbox,
|
|
217
|
+
{
|
|
218
|
+
item,
|
|
219
|
+
checked: selected.has(item.id),
|
|
220
|
+
onCheckedChange: () => toggle(item.id)
|
|
221
|
+
}
|
|
222
|
+
),
|
|
223
|
+
renderItem ? renderItem(item, selected.has(item.id)) : getMetaTitle(item.meta) ?? item.id
|
|
224
|
+
] }, item.id))
|
|
225
|
+
] }),
|
|
226
|
+
/* @__PURE__ */ jsx4("button", { type: "button", onClick: () => void remove(), disabled: selectedIds.length === 0 || list.isMutating, children: deleteSelectedLabel }),
|
|
227
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
228
|
+
tagsLabel,
|
|
229
|
+
/* @__PURE__ */ jsx4("input", { value: tagsInput, onChange: (event) => setTagsInput(event.currentTarget.value) })
|
|
230
|
+
] }),
|
|
231
|
+
/* @__PURE__ */ jsx4(
|
|
209
232
|
"button",
|
|
210
233
|
{
|
|
211
234
|
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 })
|
|
235
|
+
onClick: () => void updateTags(),
|
|
236
|
+
disabled: selectedIds.length === 0 || list.isMutating,
|
|
237
|
+
children: applyTagsLabel
|
|
238
|
+
}
|
|
239
|
+
)
|
|
220
240
|
] });
|
|
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);
|
|
241
|
+
return /* @__PURE__ */ jsx4("section", { ...props, "aria-busy": list.isMutating || props["aria-busy"], children: body });
|
|
227
242
|
}
|
|
228
243
|
|
|
229
|
-
// src/
|
|
230
|
-
import { KeepProvider, useKeepContext as useKeepContext2, useKeepItem as useKeepItem2, useKeepList as useKeepList2, useKeepShortcut } from "@keepkit/core/react";
|
|
244
|
+
// src/KeepButton.tsx
|
|
231
245
|
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
|
-
}
|
|
246
|
+
KeepButton as CoreKeepButton,
|
|
247
|
+
useKeepItem
|
|
248
|
+
} from "@keepkit/core/react";
|
|
249
|
+
import { Fragment as Fragment2, jsx as jsx5 } from "react/jsx-runtime";
|
|
286
250
|
function KeepButton({ labels, ...props }) {
|
|
287
251
|
const saveLabel = useUiLabel("save", typeof labels?.unsaved === "string" ? labels.unsaved : void 0);
|
|
288
252
|
const savedLabel = useUiLabel("saved", typeof labels?.saved === "string" ? labels.saved : void 0);
|
|
@@ -297,22 +261,6 @@ function KeepButton({ labels, ...props }) {
|
|
|
297
261
|
if (props.children !== void 0) return props.children;
|
|
298
262
|
return state.isSaved ? labels?.saved ?? savedLabel : labels?.unsaved ?? saveLabel;
|
|
299
263
|
};
|
|
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
264
|
const sharedProps = {
|
|
317
265
|
...props,
|
|
318
266
|
"aria-busy": props["aria-busy"] ?? (buttonState.isLoading || buttonState.isMutating),
|
|
@@ -321,10 +269,22 @@ function KeepButton({ labels, ...props }) {
|
|
|
321
269
|
savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
|
|
322
270
|
unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
|
|
323
271
|
};
|
|
324
|
-
if (!customStateLabel) return /* @__PURE__ */
|
|
325
|
-
|
|
326
|
-
return /* @__PURE__ */ jsx4(CoreKeepButton, { ...statefulProps });
|
|
272
|
+
if (!customStateLabel) return /* @__PURE__ */ jsx5(CoreKeepButton, { ...sharedProps });
|
|
273
|
+
return /* @__PURE__ */ jsx5(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx5(Fragment2, { children: getStateContent(state) }) });
|
|
327
274
|
}
|
|
275
|
+
|
|
276
|
+
// src/KeepCollection.tsx
|
|
277
|
+
import { useKeepList as useKeepList4 } from "@keepkit/core/react";
|
|
278
|
+
import { useMemo as useMemo3, useState as useState4 } from "react";
|
|
279
|
+
|
|
280
|
+
// src/KeepList.tsx
|
|
281
|
+
import { useKeepList as useKeepList2 } from "@keepkit/core/react";
|
|
282
|
+
import { isValidElement as isValidElement3 } from "react";
|
|
283
|
+
|
|
284
|
+
// src/KeepItemCard.tsx
|
|
285
|
+
import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
|
|
286
|
+
import { isValidElement as isValidElement2 } from "react";
|
|
287
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
328
288
|
function KeepItemCard({
|
|
329
289
|
item,
|
|
330
290
|
title,
|
|
@@ -346,8 +306,8 @@ function KeepItemCard({
|
|
|
346
306
|
}) {
|
|
347
307
|
const saveActionLabel = useUiLabel("save");
|
|
348
308
|
const removeActionLabel = useUiLabel("remove");
|
|
349
|
-
const itemState =
|
|
350
|
-
const contentChildren = asChild &&
|
|
309
|
+
const itemState = useKeepItem2(item);
|
|
310
|
+
const contentChildren = asChild && isValidElement2(children) ? void 0 : children;
|
|
351
311
|
const state = {
|
|
352
312
|
item,
|
|
353
313
|
isSaved: itemState.isSaved,
|
|
@@ -365,10 +325,10 @@ function KeepItemCard({
|
|
|
365
325
|
onRemoveError?.(error);
|
|
366
326
|
}
|
|
367
327
|
}
|
|
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__ */
|
|
328
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
329
|
+
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,
|
|
330
|
+
/* @__PURE__ */ jsx6("h3", { children: resolvedTitle }),
|
|
331
|
+
showSaveButton ? /* @__PURE__ */ jsx6(
|
|
372
332
|
KeepButton,
|
|
373
333
|
{
|
|
374
334
|
item: toKeepButtonItem(item),
|
|
@@ -376,16 +336,19 @@ function KeepItemCard({
|
|
|
376
336
|
getAriaLabel: (buttonState) => `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`
|
|
377
337
|
}
|
|
378
338
|
) : null,
|
|
379
|
-
/* @__PURE__ */
|
|
339
|
+
/* @__PURE__ */ jsx6("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel })
|
|
380
340
|
] });
|
|
381
341
|
return renderRoot(
|
|
382
342
|
asChild,
|
|
383
|
-
|
|
343
|
+
isValidElement2(children) ? children : void 0,
|
|
384
344
|
{ ...rootProps, className, "aria-busy": itemState.isMutating || rootProps["aria-busy"] },
|
|
385
345
|
body,
|
|
386
346
|
"KeepItemCard"
|
|
387
347
|
);
|
|
388
348
|
}
|
|
349
|
+
|
|
350
|
+
// src/KeepList.tsx
|
|
351
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
389
352
|
function KeepList({
|
|
390
353
|
query,
|
|
391
354
|
children,
|
|
@@ -401,7 +364,7 @@ function KeepList({
|
|
|
401
364
|
const defaultLoading = useUiLabel("loadingItems");
|
|
402
365
|
const defaultEmpty = useUiLabel("noItems");
|
|
403
366
|
const defaultError = useUiLabel("errorItems");
|
|
404
|
-
const state =
|
|
367
|
+
const state = useKeepList2(query);
|
|
405
368
|
const body = getListBody(state, {
|
|
406
369
|
children,
|
|
407
370
|
renderItem,
|
|
@@ -410,10 +373,9 @@ function KeepList({
|
|
|
410
373
|
error: errorContent ?? defaultError,
|
|
411
374
|
itemCardProps
|
|
412
375
|
});
|
|
413
|
-
const root = asChild && isValidElement(children) ? children : void 0;
|
|
414
376
|
return renderRoot(
|
|
415
377
|
asChild,
|
|
416
|
-
|
|
378
|
+
asChild && isValidElement3(children) ? children : void 0,
|
|
417
379
|
{ ...rootProps, className, "aria-busy": state.isLoading || rootProps["aria-busy"] },
|
|
418
380
|
body,
|
|
419
381
|
"KeepList"
|
|
@@ -424,12 +386,196 @@ function getListBody(state, options) {
|
|
|
424
386
|
if (state.isLoading && !state.isHydrated) return resolveContent(options.loading, state);
|
|
425
387
|
if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);
|
|
426
388
|
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__ */
|
|
389
|
+
if (options.children !== void 0 && !isValidElement3(options.children)) return options.children;
|
|
390
|
+
return /* @__PURE__ */ jsx7("ul", { children: state.items.map(
|
|
391
|
+
(item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsx7(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
|
|
392
|
+
) });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/KeepTagFilter.tsx
|
|
396
|
+
import { useKeepList as useKeepList3 } from "@keepkit/core/react";
|
|
397
|
+
import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState2 } from "react";
|
|
398
|
+
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
399
|
+
function KeepTagFilter({
|
|
400
|
+
query,
|
|
401
|
+
value: controlledValue,
|
|
402
|
+
defaultValue,
|
|
403
|
+
onChange,
|
|
404
|
+
onValueChange,
|
|
405
|
+
allLabel,
|
|
406
|
+
ariaLabel,
|
|
407
|
+
renderTag,
|
|
408
|
+
render,
|
|
409
|
+
children,
|
|
410
|
+
asChild = false,
|
|
411
|
+
className,
|
|
412
|
+
...rootProps
|
|
413
|
+
}) {
|
|
414
|
+
const uiAllLabel = useUiLabel("allTags");
|
|
415
|
+
const uiAriaLabel = useUiLabel("filterTags");
|
|
416
|
+
const [uncontrolledValue, setUncontrolledValue] = useState2(defaultValue);
|
|
417
|
+
const resolvedValue = controlledValue ?? uncontrolledValue;
|
|
418
|
+
const list = useKeepList3({
|
|
419
|
+
...query,
|
|
420
|
+
tags: resolvedValue ? [...query?.tags ?? [], resolvedValue] : query?.tags
|
|
421
|
+
});
|
|
422
|
+
const select = useCallback(
|
|
423
|
+
(tag) => {
|
|
424
|
+
if (controlledValue === void 0) setUncontrolledValue(tag);
|
|
425
|
+
onChange?.(tag);
|
|
426
|
+
onValueChange?.(tag);
|
|
427
|
+
},
|
|
428
|
+
[controlledValue, onChange, onValueChange]
|
|
429
|
+
);
|
|
430
|
+
const state = useMemo2(
|
|
431
|
+
() => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),
|
|
432
|
+
[list.tagCounts, list.tags, resolvedValue, select]
|
|
433
|
+
);
|
|
434
|
+
const contentChildren = asChild && isValidElement4(children) ? void 0 : children;
|
|
435
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs3("fieldset", { children: [
|
|
436
|
+
/* @__PURE__ */ jsx8("legend", { children: ariaLabel ?? uiAriaLabel }),
|
|
437
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
|
|
438
|
+
list.tags.map((tag) => /* @__PURE__ */ jsxs3("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
|
|
439
|
+
renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag,
|
|
440
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
441
|
+
" (",
|
|
442
|
+
list.tagCounts[tag] ?? 0,
|
|
443
|
+
")"
|
|
444
|
+
] })
|
|
445
|
+
] }, tag))
|
|
446
|
+
] });
|
|
447
|
+
return renderRoot(
|
|
448
|
+
asChild,
|
|
449
|
+
isValidElement4(children) ? children : void 0,
|
|
450
|
+
{ ...rootProps, className },
|
|
451
|
+
body,
|
|
452
|
+
"KeepTagFilter"
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// src/query-controls.tsx
|
|
457
|
+
import { useEffect, useState as useState3 } from "react";
|
|
458
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
459
|
+
function KeepSearchInput({
|
|
460
|
+
value: controlledValue,
|
|
461
|
+
defaultValue = "",
|
|
462
|
+
debounceMs = 300,
|
|
463
|
+
onValueChange,
|
|
464
|
+
"aria-label": ariaLabel,
|
|
465
|
+
placeholder,
|
|
466
|
+
...props
|
|
467
|
+
}) {
|
|
468
|
+
const label = useUiLabel("search");
|
|
469
|
+
const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
|
|
470
|
+
const value = controlledValue ?? uncontrolledValue;
|
|
471
|
+
useEffect(() => {
|
|
472
|
+
if (!onValueChange) return;
|
|
473
|
+
if (debounceMs <= 0) {
|
|
474
|
+
onValueChange(value);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const timer = window.setTimeout(() => onValueChange(value), debounceMs);
|
|
478
|
+
return () => window.clearTimeout(timer);
|
|
479
|
+
}, [debounceMs, onValueChange, value]);
|
|
480
|
+
return /* @__PURE__ */ jsx9(
|
|
481
|
+
"input",
|
|
482
|
+
{
|
|
483
|
+
...props,
|
|
484
|
+
type: "search",
|
|
485
|
+
value,
|
|
486
|
+
"aria-label": ariaLabel ?? label,
|
|
487
|
+
placeholder: placeholder ?? label,
|
|
488
|
+
onChange: (event) => {
|
|
489
|
+
const nextValue = event.currentTarget.value;
|
|
490
|
+
if (controlledValue === void 0) setUncontrolledValue(nextValue);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
function KeepSortSelect({
|
|
496
|
+
value: controlledValue,
|
|
497
|
+
defaultValue = "updatedAt:desc",
|
|
498
|
+
onValueChange,
|
|
499
|
+
"aria-label": ariaLabel,
|
|
500
|
+
children,
|
|
501
|
+
...props
|
|
502
|
+
}) {
|
|
503
|
+
const label = useUiLabel("sort");
|
|
504
|
+
const updatedNewestLabel = useUiLabel("updatedNewest");
|
|
505
|
+
const updatedOldestLabel = useUiLabel("updatedOldest");
|
|
506
|
+
const savedNewestLabel = useUiLabel("savedNewest");
|
|
507
|
+
const savedOldestLabel = useUiLabel("savedOldest");
|
|
508
|
+
const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
|
|
509
|
+
const value = controlledValue ?? uncontrolledValue;
|
|
510
|
+
const options = children ?? /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
511
|
+
/* @__PURE__ */ jsx9("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
|
|
512
|
+
/* @__PURE__ */ jsx9("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
|
|
513
|
+
/* @__PURE__ */ jsx9("option", { value: "savedAt:desc", children: savedNewestLabel }),
|
|
514
|
+
/* @__PURE__ */ jsx9("option", { value: "savedAt:asc", children: savedOldestLabel })
|
|
515
|
+
] });
|
|
516
|
+
return /* @__PURE__ */ jsx9(
|
|
517
|
+
"select",
|
|
518
|
+
{
|
|
519
|
+
...props,
|
|
520
|
+
value,
|
|
521
|
+
"aria-label": ariaLabel ?? label,
|
|
522
|
+
onChange: (event) => {
|
|
523
|
+
const nextValue = event.currentTarget.value;
|
|
524
|
+
if (controlledValue === void 0) setUncontrolledValue(nextValue);
|
|
525
|
+
const [by, direction] = nextValue.split(":");
|
|
526
|
+
onValueChange?.(nextValue, { by, direction });
|
|
527
|
+
},
|
|
528
|
+
children: options
|
|
529
|
+
}
|
|
430
530
|
);
|
|
431
|
-
return /* @__PURE__ */ jsx4("ul", { children: items });
|
|
432
531
|
}
|
|
532
|
+
function KeepPagination({
|
|
533
|
+
totalCount,
|
|
534
|
+
pageSize,
|
|
535
|
+
page = 1,
|
|
536
|
+
maxPageButtons = 7,
|
|
537
|
+
onPageChange,
|
|
538
|
+
render,
|
|
539
|
+
...props
|
|
540
|
+
}) {
|
|
541
|
+
const previousPageLabel = useUiLabel("previousPage");
|
|
542
|
+
const nextPageLabel = useUiLabel("nextPage");
|
|
543
|
+
const pageLabel = useUiLabel("page");
|
|
544
|
+
const paginationLabel = useUiLabel("pagination");
|
|
545
|
+
const pageCount = Math.max(1, Math.ceil(totalCount / Math.max(1, pageSize)));
|
|
546
|
+
const currentPage = Math.min(Math.max(1, page), pageCount);
|
|
547
|
+
const goToPage = (nextPage) => {
|
|
548
|
+
const next = Math.min(Math.max(1, nextPage), pageCount);
|
|
549
|
+
onPageChange?.(next, (next - 1) * pageSize);
|
|
550
|
+
};
|
|
551
|
+
const navProps = { ...props, "aria-label": props["aria-label"] ?? paginationLabel };
|
|
552
|
+
if (render) return /* @__PURE__ */ jsx9("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
|
|
553
|
+
const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));
|
|
554
|
+
return /* @__PURE__ */ jsxs4("nav", { ...navProps, children: [
|
|
555
|
+
/* @__PURE__ */ jsx9("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
|
|
556
|
+
visiblePages.map((nextPage) => /* @__PURE__ */ jsx9(
|
|
557
|
+
"button",
|
|
558
|
+
{
|
|
559
|
+
type: "button",
|
|
560
|
+
"aria-current": nextPage === currentPage ? "page" : void 0,
|
|
561
|
+
"aria-label": `${pageLabel} ${nextPage}`,
|
|
562
|
+
onClick: () => goToPage(nextPage),
|
|
563
|
+
children: nextPage
|
|
564
|
+
},
|
|
565
|
+
nextPage
|
|
566
|
+
)),
|
|
567
|
+
/* @__PURE__ */ jsx9("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
|
|
568
|
+
] });
|
|
569
|
+
}
|
|
570
|
+
function getVisiblePages(currentPage, pageCount, maxPageButtons) {
|
|
571
|
+
if (pageCount <= maxPageButtons) return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
572
|
+
const half = Math.floor(maxPageButtons / 2);
|
|
573
|
+
const start = Math.min(Math.max(1, currentPage - half), pageCount - maxPageButtons + 1);
|
|
574
|
+
return Array.from({ length: maxPageButtons }, (_, index) => start + index);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// src/KeepCollection.tsx
|
|
578
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
433
579
|
function KeepCollection({
|
|
434
580
|
query = {},
|
|
435
581
|
pageSize = 20,
|
|
@@ -450,12 +596,12 @@ function KeepCollection({
|
|
|
450
596
|
bulkActions: false,
|
|
451
597
|
...features
|
|
452
598
|
};
|
|
453
|
-
const [searchValue, setSearchValue] =
|
|
454
|
-
const [sort, setSort] =
|
|
455
|
-
const [tag, setTag] =
|
|
456
|
-
const [page, setPage] =
|
|
599
|
+
const [searchValue, setSearchValue] = useState4(query.search?.query ?? "");
|
|
600
|
+
const [sort, setSort] = useState4(query.sort ?? { by: "updatedAt", direction: "desc" });
|
|
601
|
+
const [tag, setTag] = useState4(query.tags?.[0]);
|
|
602
|
+
const [page, setPage] = useState4(query.pagination?.page ?? 1);
|
|
457
603
|
const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
|
|
458
|
-
const resolvedQuery =
|
|
604
|
+
const resolvedQuery = useMemo3(
|
|
459
605
|
() => ({
|
|
460
606
|
...query,
|
|
461
607
|
search: enabled.search ? { ...query.search, query: searchValue } : query.search,
|
|
@@ -465,25 +611,48 @@ function KeepCollection({
|
|
|
465
611
|
}),
|
|
466
612
|
[enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag]
|
|
467
613
|
);
|
|
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(
|
|
614
|
+
const list = useKeepList4(resolvedQuery);
|
|
615
|
+
return /* @__PURE__ */ jsxs5(
|
|
475
616
|
"section",
|
|
476
617
|
{
|
|
477
618
|
...rootProps,
|
|
478
619
|
className,
|
|
479
620
|
"aria-busy": list.isLoading || list.isMutating || rootProps["aria-busy"],
|
|
480
621
|
children: [
|
|
481
|
-
/* @__PURE__ */
|
|
482
|
-
enabled.search ? /* @__PURE__ */
|
|
483
|
-
|
|
484
|
-
|
|
622
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
623
|
+
enabled.search ? /* @__PURE__ */ jsx10(
|
|
624
|
+
KeepSearchInput,
|
|
625
|
+
{
|
|
626
|
+
value: searchValue,
|
|
627
|
+
onValueChange: (value) => {
|
|
628
|
+
setSearchValue(value);
|
|
629
|
+
setPage(1);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
) : null,
|
|
633
|
+
enabled.sort ? /* @__PURE__ */ jsx10(
|
|
634
|
+
KeepSortSelect,
|
|
635
|
+
{
|
|
636
|
+
value: sortToValue(sort),
|
|
637
|
+
onValueChange: (_value, nextSort) => {
|
|
638
|
+
setSort(nextSort);
|
|
639
|
+
setPage(1);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
) : null,
|
|
643
|
+
enabled.tagFilter ? /* @__PURE__ */ jsx10(
|
|
644
|
+
KeepTagFilter,
|
|
645
|
+
{
|
|
646
|
+
query,
|
|
647
|
+
value: tag,
|
|
648
|
+
onValueChange: (value) => {
|
|
649
|
+
setTag(value);
|
|
650
|
+
setPage(1);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
) : null
|
|
485
654
|
] }),
|
|
486
|
-
/* @__PURE__ */
|
|
655
|
+
/* @__PURE__ */ jsx10(
|
|
487
656
|
KeepList,
|
|
488
657
|
{
|
|
489
658
|
query: resolvedQuery,
|
|
@@ -494,80 +663,37 @@ function KeepCollection({
|
|
|
494
663
|
error
|
|
495
664
|
}
|
|
496
665
|
),
|
|
497
|
-
enabled.pagination ? /* @__PURE__ */
|
|
666
|
+
enabled.pagination ? /* @__PURE__ */ jsx10(
|
|
498
667
|
KeepPagination,
|
|
499
668
|
{
|
|
500
669
|
totalCount: list.totalCount,
|
|
501
670
|
pageSize: resolvedPageSize,
|
|
502
671
|
page: list.page,
|
|
503
|
-
onPageChange: (
|
|
672
|
+
onPageChange: (nextPage) => setPage(nextPage)
|
|
504
673
|
}
|
|
505
674
|
) : null,
|
|
506
|
-
enabled.bulkActions ? /* @__PURE__ */
|
|
675
|
+
enabled.bulkActions ? /* @__PURE__ */ jsx10(KeepBulkActions, { query: resolvedQuery }) : null
|
|
507
676
|
]
|
|
508
677
|
}
|
|
509
678
|
);
|
|
510
679
|
}
|
|
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
|
-
}
|
|
680
|
+
|
|
681
|
+
// src/KeepNoteEditor.tsx
|
|
682
|
+
import { useKeepItem as useKeepItem3 } from "@keepkit/core/react";
|
|
683
|
+
import {
|
|
684
|
+
isValidElement as isValidElement5,
|
|
685
|
+
useCallback as useCallback2,
|
|
686
|
+
useEffect as useEffect2,
|
|
687
|
+
useRef,
|
|
688
|
+
useState as useState5
|
|
689
|
+
} from "react";
|
|
690
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
566
691
|
function KeepNoteEditor({
|
|
567
692
|
item,
|
|
568
693
|
label,
|
|
569
694
|
saveLabel,
|
|
570
695
|
placeholder,
|
|
696
|
+
debounceMs = 300,
|
|
571
697
|
onSaved,
|
|
572
698
|
onSaveError,
|
|
573
699
|
render,
|
|
@@ -578,68 +704,89 @@ function KeepNoteEditor({
|
|
|
578
704
|
}) {
|
|
579
705
|
const defaultLabel = useUiLabel("note");
|
|
580
706
|
const defaultSaveLabel = useUiLabel("saveNote");
|
|
581
|
-
const itemState =
|
|
582
|
-
const
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
const
|
|
707
|
+
const itemState = useKeepItem3(item);
|
|
708
|
+
const { error, isMutating, item: savedItem, updateNote } = itemState;
|
|
709
|
+
const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
|
|
710
|
+
const [note, setNote] = useState5(item.note ?? "");
|
|
711
|
+
const baselineNote = savedItem?.note ?? item.note ?? "";
|
|
712
|
+
const isDirty = note !== baselineNote;
|
|
713
|
+
const lastSavedNoteRef = useRef(void 0);
|
|
714
|
+
useEffect2(() => setNote(baselineNote), [baselineNote]);
|
|
715
|
+
const save = useCallback2(async () => {
|
|
586
716
|
const nextNote = note.trim() || void 0;
|
|
587
717
|
try {
|
|
588
|
-
await
|
|
718
|
+
await updateNote(nextNote);
|
|
719
|
+
lastSavedNoteRef.current = note;
|
|
589
720
|
onSaved?.(nextNote);
|
|
590
|
-
} catch (
|
|
591
|
-
onSaveError?.(
|
|
592
|
-
throw
|
|
721
|
+
} catch (error2) {
|
|
722
|
+
onSaveError?.(error2);
|
|
723
|
+
throw error2;
|
|
593
724
|
}
|
|
594
|
-
}, [
|
|
725
|
+
}, [note, onSaveError, onSaved, updateNote]);
|
|
726
|
+
useEffect2(() => {
|
|
727
|
+
if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;
|
|
728
|
+
const timer = window.setTimeout(() => void save().catch(() => void 0), debounceMs);
|
|
729
|
+
return () => window.clearTimeout(timer);
|
|
730
|
+
}, [debounceMs, isDirty, note, save]);
|
|
595
731
|
const state = {
|
|
596
732
|
item,
|
|
597
733
|
note,
|
|
598
734
|
setNote,
|
|
599
|
-
isDirty
|
|
600
|
-
isSaving:
|
|
601
|
-
error
|
|
735
|
+
isDirty,
|
|
736
|
+
isSaving: isMutating,
|
|
737
|
+
error,
|
|
602
738
|
save
|
|
603
739
|
};
|
|
604
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
740
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs6(Fragment5, { children: [
|
|
741
|
+
/* @__PURE__ */ jsxs6("label", { children: [
|
|
606
742
|
label ?? defaultLabel,
|
|
607
|
-
/* @__PURE__ */
|
|
743
|
+
/* @__PURE__ */ jsx11(
|
|
608
744
|
"textarea",
|
|
609
745
|
{
|
|
610
746
|
value: note,
|
|
611
747
|
onChange: (event) => setNote(event.currentTarget.value),
|
|
612
748
|
placeholder,
|
|
613
|
-
disabled:
|
|
749
|
+
disabled: isMutating,
|
|
750
|
+
onKeyDown: (event) => {
|
|
751
|
+
if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
|
|
752
|
+
event.preventDefault();
|
|
753
|
+
void save().catch(() => void 0);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
614
756
|
}
|
|
615
757
|
)
|
|
616
758
|
] }),
|
|
617
|
-
/* @__PURE__ */
|
|
759
|
+
/* @__PURE__ */ jsx11("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
|
|
618
760
|
] });
|
|
619
761
|
const handleSubmit = (event) => {
|
|
620
762
|
event.preventDefault();
|
|
621
763
|
void save().catch(() => void 0);
|
|
622
764
|
};
|
|
623
765
|
if (!asChild) {
|
|
624
|
-
return /* @__PURE__ */
|
|
766
|
+
return /* @__PURE__ */ jsx11(
|
|
625
767
|
"form",
|
|
626
768
|
{
|
|
627
769
|
...formProps,
|
|
628
770
|
className,
|
|
629
771
|
onSubmit: handleSubmit,
|
|
630
|
-
"aria-busy":
|
|
772
|
+
"aria-busy": isMutating || formProps["aria-busy"],
|
|
631
773
|
children: body
|
|
632
774
|
}
|
|
633
775
|
);
|
|
634
776
|
}
|
|
635
777
|
return renderRoot(
|
|
636
778
|
true,
|
|
637
|
-
|
|
638
|
-
{ ...formProps, className, onSubmit: handleSubmit, "aria-busy":
|
|
779
|
+
isValidElement5(children) ? children : void 0,
|
|
780
|
+
{ ...formProps, className, onSubmit: handleSubmit, "aria-busy": isMutating || formProps["aria-busy"] },
|
|
639
781
|
body,
|
|
640
782
|
"KeepNoteEditor"
|
|
641
783
|
);
|
|
642
784
|
}
|
|
785
|
+
|
|
786
|
+
// src/KeepTagEditor.tsx
|
|
787
|
+
import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
|
|
788
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useState as useState6 } from "react";
|
|
789
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
643
790
|
function KeepTagEditor({
|
|
644
791
|
item,
|
|
645
792
|
availableTags = [],
|
|
@@ -651,11 +798,11 @@ function KeepTagEditor({
|
|
|
651
798
|
const tagsLabel = useUiLabel("tagsToApply");
|
|
652
799
|
const removeLabel = useUiLabel("remove");
|
|
653
800
|
const applyTagsLabel = useUiLabel("applyTags");
|
|
654
|
-
const itemState =
|
|
655
|
-
const [tags, setTags] =
|
|
656
|
-
const [input, setInput] =
|
|
657
|
-
|
|
658
|
-
const save =
|
|
801
|
+
const itemState = useKeepItem4(item);
|
|
802
|
+
const [tags, setTags] = useState6(item.tags ?? []);
|
|
803
|
+
const [input, setInput] = useState6("");
|
|
804
|
+
useEffect3(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
|
|
805
|
+
const save = useCallback3(async () => {
|
|
659
806
|
const nextTags = normalizeUiTags(tags);
|
|
660
807
|
try {
|
|
661
808
|
await itemState.updateTags(nextTags);
|
|
@@ -667,14 +814,13 @@ function KeepTagEditor({
|
|
|
667
814
|
}
|
|
668
815
|
}, [itemState, onSaveError, onSaved, tags]);
|
|
669
816
|
const addTag = (tag) => {
|
|
670
|
-
|
|
671
|
-
setTags(next);
|
|
817
|
+
setTags(normalizeUiTags([...tags, tag]));
|
|
672
818
|
setInput("");
|
|
673
819
|
};
|
|
674
|
-
const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */
|
|
675
|
-
/* @__PURE__ */
|
|
820
|
+
const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs7(Fragment6, { children: [
|
|
821
|
+
/* @__PURE__ */ jsxs7("label", { children: [
|
|
676
822
|
tagsLabel,
|
|
677
|
-
/* @__PURE__ */
|
|
823
|
+
/* @__PURE__ */ jsx12(
|
|
678
824
|
"input",
|
|
679
825
|
{
|
|
680
826
|
value: input,
|
|
@@ -682,6 +828,7 @@ function KeepTagEditor({
|
|
|
682
828
|
onChange: (event) => setInput(event.currentTarget.value),
|
|
683
829
|
onKeyDown: (event) => {
|
|
684
830
|
if (event.key === "Enter") {
|
|
831
|
+
if (event.nativeEvent.isComposing) return;
|
|
685
832
|
event.preventDefault();
|
|
686
833
|
if (input.trim()) addTag(input);
|
|
687
834
|
} else if (event.key === "Backspace" && input.length === 0 && tags.length > 0) {
|
|
@@ -692,14 +839,14 @@ function KeepTagEditor({
|
|
|
692
839
|
}
|
|
693
840
|
)
|
|
694
841
|
] }),
|
|
695
|
-
availableTags.length > 0 ? /* @__PURE__ */
|
|
696
|
-
/* @__PURE__ */
|
|
842
|
+
availableTags.length > 0 ? /* @__PURE__ */ jsx12("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx12("option", { value: tag }, tag)) }) : null,
|
|
843
|
+
/* @__PURE__ */ jsx12("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs7("li", { children: [
|
|
697
844
|
tag,
|
|
698
|
-
/* @__PURE__ */
|
|
845
|
+
/* @__PURE__ */ jsx12("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
|
|
699
846
|
] }, tag)) }),
|
|
700
|
-
/* @__PURE__ */
|
|
847
|
+
/* @__PURE__ */ jsx12("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
|
|
701
848
|
] });
|
|
702
|
-
return /* @__PURE__ */
|
|
849
|
+
return /* @__PURE__ */ jsx12(
|
|
703
850
|
"form",
|
|
704
851
|
{
|
|
705
852
|
...props,
|
|
@@ -712,96 +859,11 @@ function KeepTagEditor({
|
|
|
712
859
|
}
|
|
713
860
|
);
|
|
714
861
|
}
|
|
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
|
-
}
|
|
862
|
+
|
|
863
|
+
// src/status.tsx
|
|
864
|
+
import { useKeepContext } from "@keepkit/core/react";
|
|
865
|
+
import { isValidElement as isValidElement6, useEffect as useEffect4, useRef as useRef2, useState as useState7 } from "react";
|
|
866
|
+
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
805
867
|
function KeepEmptyState({
|
|
806
868
|
title,
|
|
807
869
|
description,
|
|
@@ -812,10 +874,10 @@ function KeepEmptyState({
|
|
|
812
874
|
...rootProps
|
|
813
875
|
}) {
|
|
814
876
|
const defaultTitle = useUiLabel("noItems").replace(/\.$/, "");
|
|
815
|
-
const contentChildren = asChild &&
|
|
816
|
-
const body = contentChildren ?? /* @__PURE__ */
|
|
817
|
-
/* @__PURE__ */
|
|
818
|
-
description ? /* @__PURE__ */
|
|
877
|
+
const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
|
|
878
|
+
const body = contentChildren ?? /* @__PURE__ */ jsxs8(Fragment7, { children: [
|
|
879
|
+
/* @__PURE__ */ jsx13("h2", { children: title ?? defaultTitle }),
|
|
880
|
+
description ? /* @__PURE__ */ jsx13("p", { children: description }) : null,
|
|
819
881
|
action
|
|
820
882
|
] });
|
|
821
883
|
return renderRoot(asChild, children, { ...rootProps, className }, body, "KeepEmptyState");
|
|
@@ -830,7 +892,7 @@ function KeepStatus({
|
|
|
830
892
|
...rootProps
|
|
831
893
|
}) {
|
|
832
894
|
const context = useKeepContext();
|
|
833
|
-
const contentChildren = asChild &&
|
|
895
|
+
const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
|
|
834
896
|
const resolvedStatus = status ?? getDerivedStatus(context);
|
|
835
897
|
const defaultLabel = useUiLabel(getStatusLabelKey(resolvedStatus));
|
|
836
898
|
const state = {
|
|
@@ -843,7 +905,7 @@ function KeepStatus({
|
|
|
843
905
|
const role = rootProps.role ?? (resolvedStatus === "error" ? "alert" : "status");
|
|
844
906
|
return renderRoot(
|
|
845
907
|
asChild,
|
|
846
|
-
|
|
908
|
+
isValidElement6(children) ? children : void 0,
|
|
847
909
|
{ ...rootProps, className, role, "aria-live": rootProps["aria-live"] ?? "polite" },
|
|
848
910
|
body,
|
|
849
911
|
"KeepStatus"
|
|
@@ -854,9 +916,9 @@ function KeepAnnouncements({ messages, ...props }) {
|
|
|
854
916
|
const savedMessage = useUiLabel("savedMessage", messages?.save);
|
|
855
917
|
const removedMessage = useUiLabel("removedMessage", messages?.remove);
|
|
856
918
|
const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
|
|
857
|
-
const [message, setMessage] =
|
|
858
|
-
const lastChangeRef =
|
|
859
|
-
|
|
919
|
+
const [message, setMessage] = useState7("");
|
|
920
|
+
const lastChangeRef = useRef2(void 0);
|
|
921
|
+
useEffect4(() => {
|
|
860
922
|
const change = context.lastChange;
|
|
861
923
|
if (!change || change === lastChangeRef.current) return;
|
|
862
924
|
lastChangeRef.current = change;
|
|
@@ -864,8 +926,9 @@ function KeepAnnouncements({ messages, ...props }) {
|
|
|
864
926
|
else if (change.action === "remove" || change.action === "removeBatch") setMessage(removedMessage);
|
|
865
927
|
else if (change.action === "updateNote") setMessage(noteSavedMessage);
|
|
866
928
|
}, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);
|
|
867
|
-
return /* @__PURE__ */
|
|
929
|
+
return /* @__PURE__ */ jsx13("div", { ...props, role: props.role ?? "status", "aria-live": props["aria-live"] ?? "polite", "aria-atomic": "true", children: message });
|
|
868
930
|
}
|
|
931
|
+
var KeepAnnouncer = KeepAnnouncements;
|
|
869
932
|
function getDerivedStatus(context) {
|
|
870
933
|
if (context.error) return "error";
|
|
871
934
|
if (context.syncState.status === "pending" || context.syncState.status === "syncing") return "syncing";
|
|
@@ -882,41 +945,70 @@ function getStatusLabelKey(status) {
|
|
|
882
945
|
if (status === "syncing") return "syncing";
|
|
883
946
|
return "saved";
|
|
884
947
|
}
|
|
885
|
-
|
|
886
|
-
|
|
948
|
+
|
|
949
|
+
// src/index.tsx
|
|
950
|
+
import { KeepProvider, useKeepContext as useKeepContext2, useKeepItem as useKeepItem5, useKeepList as useKeepList5, useKeepShortcut } from "@keepkit/core/react";
|
|
951
|
+
import {
|
|
952
|
+
createBrowserStorageAdapter,
|
|
953
|
+
createStorageAdapter,
|
|
954
|
+
FallbackStorageAdapter,
|
|
955
|
+
IndexedDBAdapter,
|
|
956
|
+
IndexedDBSyncQueueAdapter,
|
|
957
|
+
LocalStorageAdapter,
|
|
958
|
+
LocalStorageSyncQueueAdapter,
|
|
959
|
+
SyncStorageAdapter
|
|
960
|
+
} from "@keepkit/core/storage";
|
|
961
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
962
|
+
function KeepKitProvider({
|
|
963
|
+
labels,
|
|
964
|
+
locale,
|
|
965
|
+
labelResolver,
|
|
966
|
+
children,
|
|
967
|
+
...providerProps
|
|
968
|
+
}) {
|
|
969
|
+
return /* @__PURE__ */ jsx14(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsxs9(CoreKeepProvider, { ...providerProps, children: [
|
|
970
|
+
children,
|
|
971
|
+
/* @__PURE__ */ jsx14(KeepAnnouncements, {})
|
|
972
|
+
] }) });
|
|
887
973
|
}
|
|
888
|
-
function
|
|
974
|
+
function createKeepKit(options = {}) {
|
|
975
|
+
const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;
|
|
976
|
+
const coreKit = createCoreKeepKit(coreOptions);
|
|
889
977
|
return {
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
978
|
+
Provider: (props) => /* @__PURE__ */ jsx14(
|
|
979
|
+
KeepKitProvider,
|
|
980
|
+
{
|
|
981
|
+
...coreOptions,
|
|
982
|
+
labels,
|
|
983
|
+
locale,
|
|
984
|
+
labelResolver,
|
|
985
|
+
...props
|
|
986
|
+
}
|
|
987
|
+
),
|
|
988
|
+
Button: (props) => /* @__PURE__ */ jsx14(KeepButton, { ...props }),
|
|
989
|
+
Collection: (props) => /* @__PURE__ */ jsx14(
|
|
990
|
+
KeepCollection,
|
|
991
|
+
{
|
|
992
|
+
...props,
|
|
993
|
+
itemCardProps: {
|
|
994
|
+
...getTitle ? { getTitle } : {},
|
|
995
|
+
...getImageProps ? { getImageProps } : {},
|
|
996
|
+
...props.itemCardProps
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
),
|
|
1000
|
+
useContext: () => coreKit.useContext(),
|
|
1001
|
+
useItem: (item) => coreKit.useItem(item),
|
|
1002
|
+
useList: (query) => coreKit.useList(query),
|
|
1003
|
+
useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions)
|
|
895
1004
|
};
|
|
896
1005
|
}
|
|
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
1006
|
export {
|
|
916
1007
|
FallbackStorageAdapter,
|
|
917
1008
|
IndexedDBAdapter,
|
|
918
1009
|
IndexedDBSyncQueueAdapter,
|
|
919
1010
|
KeepAnnouncements,
|
|
1011
|
+
KeepAnnouncer,
|
|
920
1012
|
KeepBulkActions,
|
|
921
1013
|
KeepButton,
|
|
922
1014
|
KeepCollection,
|
|
@@ -940,9 +1032,11 @@ export {
|
|
|
940
1032
|
createBrowserStorageAdapter,
|
|
941
1033
|
createKeepKit,
|
|
942
1034
|
createStorageAdapter,
|
|
1035
|
+
isAllSelected,
|
|
1036
|
+
toggleSelectAll,
|
|
943
1037
|
useKeepContext2 as useKeepContext,
|
|
944
|
-
|
|
945
|
-
|
|
1038
|
+
useKeepItem5 as useKeepItem,
|
|
1039
|
+
useKeepList5 as useKeepList,
|
|
946
1040
|
useKeepShortcut,
|
|
947
1041
|
useKeepUiLabels
|
|
948
1042
|
};
|