@keepkit/ui 0.9.0 → 0.11.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 +6 -0
- package/dist/index.d.ts +88 -7
- package/dist/index.js +632 -188
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6,12 +6,297 @@ import {
|
|
|
6
6
|
createKeepKit as createCoreKeepKit
|
|
7
7
|
} from "@keepkit/core/react";
|
|
8
8
|
|
|
9
|
+
// src/KeepBackup.tsx
|
|
10
|
+
import { useKeepContext } from "@keepkit/core/react";
|
|
11
|
+
import { useRef, useState } from "react";
|
|
12
|
+
|
|
13
|
+
// src/ui-context.tsx
|
|
14
|
+
import { createContext, useContext, useMemo } from "react";
|
|
15
|
+
import { jsx } from "react/jsx-runtime";
|
|
16
|
+
var DEFAULT_LABELS = {
|
|
17
|
+
save: "Save",
|
|
18
|
+
saved: "Saved",
|
|
19
|
+
remove: "Remove",
|
|
20
|
+
loading: "Loading\u2026",
|
|
21
|
+
saving: "Saving\u2026",
|
|
22
|
+
syncing: "Syncing\u2026",
|
|
23
|
+
error: "Something went wrong.",
|
|
24
|
+
allTags: "All",
|
|
25
|
+
tags: "Tags",
|
|
26
|
+
filterTags: "Filter saved items by tag",
|
|
27
|
+
note: "Note",
|
|
28
|
+
saveNote: "Save note",
|
|
29
|
+
noItems: "No saved items.",
|
|
30
|
+
loadingItems: "Loading saved items\u2026",
|
|
31
|
+
errorItems: "Could not load saved items.",
|
|
32
|
+
search: "Search saved items",
|
|
33
|
+
sort: "Sort saved items",
|
|
34
|
+
newest: "Newest first",
|
|
35
|
+
oldest: "Oldest first",
|
|
36
|
+
savedNewest: "Saved newest first",
|
|
37
|
+
savedOldest: "Saved oldest first",
|
|
38
|
+
updatedNewest: "Updated newest first",
|
|
39
|
+
updatedOldest: "Updated oldest first",
|
|
40
|
+
previousPage: "Previous page",
|
|
41
|
+
nextPage: "Next page",
|
|
42
|
+
pagination: "Pagination",
|
|
43
|
+
page: "Page",
|
|
44
|
+
selectItems: "Select saved items",
|
|
45
|
+
selectedCount: "selected",
|
|
46
|
+
deleteSelected: "Delete selected",
|
|
47
|
+
tagsToApply: "Tags to apply",
|
|
48
|
+
applyTags: "Apply tags",
|
|
49
|
+
savedMessage: "Item saved.",
|
|
50
|
+
removedMessage: "Item removed.",
|
|
51
|
+
undo: "Undo",
|
|
52
|
+
undoAvailable: "Item removed. Undo?",
|
|
53
|
+
selectionScope: "Selection scope",
|
|
54
|
+
currentPage: "Current page",
|
|
55
|
+
searchResults: "Current search results",
|
|
56
|
+
allItems: "All saved items",
|
|
57
|
+
statusAvailable: "Available",
|
|
58
|
+
noteSavedMessage: "Note saved.",
|
|
59
|
+
exportData: "Export JSON",
|
|
60
|
+
importData: "Import JSON",
|
|
61
|
+
importMode: "Import mode",
|
|
62
|
+
merge: "Merge",
|
|
63
|
+
replace: "Replace",
|
|
64
|
+
importedCount: "items imported",
|
|
65
|
+
failedCount: "items failed",
|
|
66
|
+
storageQuotaError: "Storage is full. Free space and try again.",
|
|
67
|
+
statusExpired: "Expired",
|
|
68
|
+
statusRemoved: "Removed",
|
|
69
|
+
statusDeleted: "Deleted",
|
|
70
|
+
statusPrivate: "Private",
|
|
71
|
+
statusUnknown: "Unavailable"
|
|
72
|
+
};
|
|
73
|
+
var KEEP_LOCALE_LABELS = {
|
|
74
|
+
ja: {
|
|
75
|
+
save: "\u4FDD\u5B58",
|
|
76
|
+
saved: "\u4FDD\u5B58\u6E08\u307F",
|
|
77
|
+
remove: "\u524A\u9664",
|
|
78
|
+
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026",
|
|
79
|
+
saving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
80
|
+
syncing: "\u540C\u671F\u4E2D\u2026",
|
|
81
|
+
allTags: "\u3059\u3079\u3066",
|
|
82
|
+
filterTags: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u30BF\u30B0\u3067\u7D5E\u308A\u8FBC\u3080",
|
|
83
|
+
note: "\u30E1\u30E2",
|
|
84
|
+
saveNote: "\u30E1\u30E2\u3092\u4FDD\u5B58",
|
|
85
|
+
loadingItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026",
|
|
86
|
+
errorItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
|
|
87
|
+
noItems: "\u4FDD\u5B58\u3055\u308C\u305F\u30A2\u30A4\u30C6\u30E0\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
88
|
+
search: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u691C\u7D22",
|
|
89
|
+
sort: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u4E26\u3079\u66FF\u3048",
|
|
90
|
+
newest: "\u65B0\u3057\u3044\u9806",
|
|
91
|
+
oldest: "\u53E4\u3044\u9806",
|
|
92
|
+
savedNewest: "\u4FDD\u5B58\u65E5\u6642\u306E\u65B0\u3057\u3044\u9806",
|
|
93
|
+
savedOldest: "\u4FDD\u5B58\u65E5\u6642\u306E\u53E4\u3044\u9806",
|
|
94
|
+
updatedNewest: "\u66F4\u65B0\u65E5\u6642\u306E\u65B0\u3057\u3044\u9806",
|
|
95
|
+
updatedOldest: "\u66F4\u65B0\u65E5\u6642\u306E\u53E4\u3044\u9806",
|
|
96
|
+
previousPage: "\u524D\u306E\u30DA\u30FC\u30B8",
|
|
97
|
+
nextPage: "\u6B21\u306E\u30DA\u30FC\u30B8",
|
|
98
|
+
pagination: "\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3",
|
|
99
|
+
page: "\u30DA\u30FC\u30B8",
|
|
100
|
+
selectItems: "\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0\u3092\u9078\u629E",
|
|
101
|
+
selectedCount: "\u4EF6\u3092\u9078\u629E\u4E2D",
|
|
102
|
+
deleteSelected: "\u9078\u629E\u9805\u76EE\u3092\u524A\u9664",
|
|
103
|
+
undo: "\u5143\u306B\u623B\u3059",
|
|
104
|
+
undoAvailable: "\u30A2\u30A4\u30C6\u30E0\u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002\u5143\u306B\u623B\u3057\u307E\u3059\u304B\uFF1F",
|
|
105
|
+
selectionScope: "\u9078\u629E\u7BC4\u56F2",
|
|
106
|
+
currentPage: "\u8868\u793A\u4E2D\u306E\u30DA\u30FC\u30B8",
|
|
107
|
+
searchResults: "\u73FE\u5728\u306E\u691C\u7D22\u7D50\u679C\u5168\u4F53",
|
|
108
|
+
allItems: "\u3059\u3079\u3066\u306E\u4FDD\u5B58\u30A2\u30A4\u30C6\u30E0",
|
|
109
|
+
tags: "\u30BF\u30B0",
|
|
110
|
+
statusAvailable: "\u5229\u7528\u53EF\u80FD",
|
|
111
|
+
tagsToApply: "\u9069\u7528\u3059\u308B\u30BF\u30B0",
|
|
112
|
+
applyTags: "\u30BF\u30B0\u3092\u9069\u7528"
|
|
113
|
+
},
|
|
114
|
+
ko: {
|
|
115
|
+
save: "\uC800\uC7A5",
|
|
116
|
+
saved: "\uC800\uC7A5\uB428",
|
|
117
|
+
remove: "\uC0AD\uC81C",
|
|
118
|
+
loading: "\uB85C\uB4DC \uC911\u2026",
|
|
119
|
+
saving: "\uC800\uC7A5 \uC911\u2026",
|
|
120
|
+
syncing: "\uB3D9\uAE30\uD654 \uC911\u2026",
|
|
121
|
+
noItems: "\uC800\uC7A5\uB41C \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
122
|
+
search: "\uC800\uC7A5\uB41C \uD56D\uBAA9 \uAC80\uC0C9",
|
|
123
|
+
sort: "\uC800\uC7A5\uB41C \uD56D\uBAA9 \uC815\uB82C",
|
|
124
|
+
previousPage: "\uC774\uC804 \uD398\uC774\uC9C0",
|
|
125
|
+
nextPage: "\uB2E4\uC74C \uD398\uC774\uC9C0",
|
|
126
|
+
pagination: "\uD398\uC774\uC9C0 \uB9E4\uAE40",
|
|
127
|
+
page: "\uD398\uC774\uC9C0",
|
|
128
|
+
undo: "\uC2E4\uD589 \uCDE8\uC18C",
|
|
129
|
+
undoAvailable: "\uD56D\uBAA9\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4. \uC2E4\uD589 \uCDE8\uC18C\uD560\uAE4C\uC694?",
|
|
130
|
+
selectionScope: "\uC120\uD0DD \uBC94\uC704",
|
|
131
|
+
currentPage: "\uD604\uC7AC \uD398\uC774\uC9C0",
|
|
132
|
+
searchResults: "\uD604\uC7AC \uAC80\uC0C9 \uACB0\uACFC \uC804\uCCB4",
|
|
133
|
+
allItems: "\uBAA8\uB4E0 \uC800\uC7A5 \uD56D\uBAA9",
|
|
134
|
+
tags: "\uD0DC\uADF8"
|
|
135
|
+
},
|
|
136
|
+
"zh-CN": {
|
|
137
|
+
save: "\u4FDD\u5B58",
|
|
138
|
+
saved: "\u5DF2\u4FDD\u5B58",
|
|
139
|
+
remove: "\u5220\u9664",
|
|
140
|
+
loading: "\u52A0\u8F7D\u4E2D\u2026",
|
|
141
|
+
saving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
142
|
+
syncing: "\u540C\u6B65\u4E2D\u2026",
|
|
143
|
+
noItems: "\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u9879\u76EE\u3002",
|
|
144
|
+
search: "\u641C\u7D22\u5DF2\u4FDD\u5B58\u9879\u76EE",
|
|
145
|
+
sort: "\u6392\u5E8F\u5DF2\u4FDD\u5B58\u9879\u76EE",
|
|
146
|
+
previousPage: "\u4E0A\u4E00\u9875",
|
|
147
|
+
nextPage: "\u4E0B\u4E00\u9875",
|
|
148
|
+
pagination: "\u5206\u9875",
|
|
149
|
+
page: "\u9875",
|
|
150
|
+
undo: "\u64A4\u9500",
|
|
151
|
+
undoAvailable: "\u9879\u76EE\u5DF2\u5220\u9664\u3002\u8981\u64A4\u9500\u5417\uFF1F",
|
|
152
|
+
selectionScope: "\u9009\u62E9\u8303\u56F4",
|
|
153
|
+
currentPage: "\u5F53\u524D\u9875",
|
|
154
|
+
searchResults: "\u5F53\u524D\u641C\u7D22\u7ED3\u679C",
|
|
155
|
+
allItems: "\u5168\u90E8\u5DF2\u4FDD\u5B58\u9879\u76EE",
|
|
156
|
+
tags: "\u6807\u7B7E"
|
|
157
|
+
},
|
|
158
|
+
"zh-TW": {
|
|
159
|
+
save: "\u5132\u5B58",
|
|
160
|
+
saved: "\u5DF2\u5132\u5B58",
|
|
161
|
+
remove: "\u522A\u9664",
|
|
162
|
+
loading: "\u8F09\u5165\u4E2D\u2026",
|
|
163
|
+
saving: "\u5132\u5B58\u4E2D\u2026",
|
|
164
|
+
syncing: "\u540C\u6B65\u4E2D\u2026",
|
|
165
|
+
noItems: "\u6C92\u6709\u5DF2\u5132\u5B58\u7684\u9805\u76EE\u3002",
|
|
166
|
+
search: "\u641C\u5C0B\u5DF2\u5132\u5B58\u9805\u76EE",
|
|
167
|
+
sort: "\u6392\u5E8F\u5DF2\u5132\u5B58\u9805\u76EE",
|
|
168
|
+
previousPage: "\u4E0A\u4E00\u9801",
|
|
169
|
+
nextPage: "\u4E0B\u4E00\u9801",
|
|
170
|
+
undo: "\u5FA9\u539F",
|
|
171
|
+
undoAvailable: "\u9805\u76EE\u5DF2\u522A\u9664\u3002\u8981\u5FA9\u539F\u55CE\uFF1F",
|
|
172
|
+
selectionScope: "\u9078\u53D6\u7BC4\u570D",
|
|
173
|
+
currentPage: "\u76EE\u524D\u9801\u9762",
|
|
174
|
+
searchResults: "\u76EE\u524D\u641C\u5C0B\u7D50\u679C",
|
|
175
|
+
allItems: "\u6240\u6709\u5DF2\u5132\u5B58\u9805\u76EE",
|
|
176
|
+
tags: "\u6A19\u7C64"
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
KEEP_LOCALE_LABELS.zh = KEEP_LOCALE_LABELS["zh-CN"];
|
|
180
|
+
var KeepUiLabelsContext = createContext({ labels: DEFAULT_LABELS });
|
|
181
|
+
function KeepUiProvider({ labels, locale, labelResolver, children }) {
|
|
182
|
+
const value = useMemo(() => {
|
|
183
|
+
const localeKey = locale?.toLowerCase() ?? "en";
|
|
184
|
+
const dictionary = KEEP_LOCALE_LABELS[localeKey] ?? KEEP_LOCALE_LABELS[localeKey.split("-")[0]] ?? {};
|
|
185
|
+
const resolved = { ...DEFAULT_LABELS, ...dictionary, ...labels };
|
|
186
|
+
return { locale, labels: resolved, customLabels: labels, labelResolver };
|
|
187
|
+
}, [labelResolver, labels, locale]);
|
|
188
|
+
return /* @__PURE__ */ jsx(KeepUiLabelsContext.Provider, { value, children });
|
|
189
|
+
}
|
|
190
|
+
function useKeepUiLabels() {
|
|
191
|
+
return useContext(KeepUiLabelsContext);
|
|
192
|
+
}
|
|
193
|
+
function useUiLabel(key, override) {
|
|
194
|
+
const context = useKeepUiLabels();
|
|
195
|
+
return override ?? context.customLabels?.[key] ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
|
|
196
|
+
}
|
|
197
|
+
function getKeepLocaleLabels(locale) {
|
|
198
|
+
const key = locale?.toLowerCase() ?? "en";
|
|
199
|
+
return { ...KEEP_LOCALE_LABELS[key] ?? KEEP_LOCALE_LABELS[key.split("-")[0]] ?? {} };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/KeepBackup.tsx
|
|
203
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
204
|
+
function KeepBackup({
|
|
205
|
+
filename = "keepkit-backup.json",
|
|
206
|
+
onExport,
|
|
207
|
+
onImported,
|
|
208
|
+
...props
|
|
209
|
+
}) {
|
|
210
|
+
const context = useKeepContext();
|
|
211
|
+
const exportLabel = useUiLabel("exportData");
|
|
212
|
+
const importLabel = useUiLabel("importData");
|
|
213
|
+
const importModeLabel = useUiLabel("importMode");
|
|
214
|
+
const mergeLabel = useUiLabel("merge");
|
|
215
|
+
const replaceLabel = useUiLabel("replace");
|
|
216
|
+
const importedCountLabel = useUiLabel("importedCount");
|
|
217
|
+
const failedCountLabel = useUiLabel("failedCount");
|
|
218
|
+
const quotaErrorLabel = useUiLabel("storageQuotaError");
|
|
219
|
+
const inputRef = useRef(null);
|
|
220
|
+
const [mode, setMode] = useState("merge");
|
|
221
|
+
const [result, setResult] = useState();
|
|
222
|
+
const [error, setError] = useState();
|
|
223
|
+
async function handleExport() {
|
|
224
|
+
setError(void 0);
|
|
225
|
+
try {
|
|
226
|
+
const data = await context.exportBackup();
|
|
227
|
+
onExport?.(data);
|
|
228
|
+
if (typeof document === "undefined") return;
|
|
229
|
+
const url = URL.createObjectURL(new Blob([data], { type: "application/json" }));
|
|
230
|
+
const anchor = document.createElement("a");
|
|
231
|
+
anchor.href = url;
|
|
232
|
+
anchor.download = filename;
|
|
233
|
+
anchor.click();
|
|
234
|
+
URL.revokeObjectURL(url);
|
|
235
|
+
} catch (cause) {
|
|
236
|
+
setError(cause);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function handleImport(event) {
|
|
240
|
+
const file = event.currentTarget.files?.[0];
|
|
241
|
+
event.currentTarget.value = "";
|
|
242
|
+
if (!file) return;
|
|
243
|
+
setError(void 0);
|
|
244
|
+
setResult(void 0);
|
|
245
|
+
try {
|
|
246
|
+
const imported = await context.importBackup(await file.text(), { mode });
|
|
247
|
+
setResult(imported);
|
|
248
|
+
onImported?.(imported);
|
|
249
|
+
} catch (cause) {
|
|
250
|
+
setError(cause);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return /* @__PURE__ */ jsxs("section", { ...props, "data-state": error ? "error" : result ? "complete" : "idle", children: [
|
|
254
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => void handleExport(), disabled: context.isMutating, children: exportLabel }),
|
|
255
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
256
|
+
importModeLabel,
|
|
257
|
+
/* @__PURE__ */ jsxs("select", { value: mode, onChange: (event) => setMode(event.currentTarget.value), children: [
|
|
258
|
+
/* @__PURE__ */ jsx2("option", { value: "merge", children: mergeLabel }),
|
|
259
|
+
/* @__PURE__ */ jsx2("option", { value: "replace", children: replaceLabel })
|
|
260
|
+
] })
|
|
261
|
+
] }),
|
|
262
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => inputRef.current?.click(), disabled: context.isMutating, children: importLabel }),
|
|
263
|
+
/* @__PURE__ */ jsx2(
|
|
264
|
+
"input",
|
|
265
|
+
{
|
|
266
|
+
ref: inputRef,
|
|
267
|
+
type: "file",
|
|
268
|
+
accept: "application/json,.json",
|
|
269
|
+
"aria-label": importLabel,
|
|
270
|
+
onChange: (event) => void handleImport(event)
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
result ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
|
|
274
|
+
result.imported,
|
|
275
|
+
" ",
|
|
276
|
+
importedCountLabel,
|
|
277
|
+
"; ",
|
|
278
|
+
result.failed,
|
|
279
|
+
" ",
|
|
280
|
+
failedCountLabel
|
|
281
|
+
] }) : null,
|
|
282
|
+
error ? /* @__PURE__ */ jsx2("p", { role: "alert", children: isQuotaError(error) ? quotaErrorLabel : getErrorMessage(error) }) : null
|
|
283
|
+
] });
|
|
284
|
+
}
|
|
285
|
+
function isQuotaError(error) {
|
|
286
|
+
if (error instanceof Error && error.name === "KeepStorageQuotaError") return true;
|
|
287
|
+
if (error && typeof error === "object" && "cause" in error) return isQuotaError(error.cause);
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
function getErrorMessage(error) {
|
|
291
|
+
return error instanceof Error ? error.message : "Something went wrong.";
|
|
292
|
+
}
|
|
293
|
+
|
|
9
294
|
// src/KeepBulkActions.tsx
|
|
10
295
|
import { useKeepList } from "@keepkit/core/react";
|
|
11
|
-
import { useState } from "react";
|
|
296
|
+
import { useState as useState2 } from "react";
|
|
12
297
|
|
|
13
298
|
// src/KeepItemCheckbox.tsx
|
|
14
|
-
import { jsx } from "react/jsx-runtime";
|
|
299
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
15
300
|
function KeepItemCheckbox({
|
|
16
301
|
item,
|
|
17
302
|
checked = false,
|
|
@@ -22,7 +307,7 @@ function KeepItemCheckbox({
|
|
|
22
307
|
}) {
|
|
23
308
|
const itemLabel = getItemLabel(item) ?? item.id;
|
|
24
309
|
const accessibleLabel = ariaLabel ?? (typeof label === "string" ? label : itemLabel);
|
|
25
|
-
return /* @__PURE__ */
|
|
310
|
+
return /* @__PURE__ */ jsx3(
|
|
26
311
|
"input",
|
|
27
312
|
{
|
|
28
313
|
...props,
|
|
@@ -46,7 +331,7 @@ import {
|
|
|
46
331
|
cloneElement,
|
|
47
332
|
isValidElement
|
|
48
333
|
} from "react";
|
|
49
|
-
import { jsx as
|
|
334
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
50
335
|
function toKeepButtonItem(item) {
|
|
51
336
|
return {
|
|
52
337
|
id: item.id,
|
|
@@ -75,66 +360,11 @@ function renderRoot(asChild, child, props, body, componentName) {
|
|
|
75
360
|
if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);
|
|
76
361
|
return cloneElement(child, { ...props, children: body });
|
|
77
362
|
}
|
|
78
|
-
return /* @__PURE__ */
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// src/ui-context.tsx
|
|
82
|
-
import { createContext, useContext, useMemo } from "react";
|
|
83
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
84
|
-
var DEFAULT_LABELS = {
|
|
85
|
-
save: "Save",
|
|
86
|
-
saved: "Saved",
|
|
87
|
-
remove: "Remove",
|
|
88
|
-
loading: "Loading\u2026",
|
|
89
|
-
saving: "Saving\u2026",
|
|
90
|
-
syncing: "Syncing\u2026",
|
|
91
|
-
error: "Something went wrong.",
|
|
92
|
-
allTags: "All",
|
|
93
|
-
filterTags: "Filter saved items by tag",
|
|
94
|
-
note: "Note",
|
|
95
|
-
saveNote: "Save note",
|
|
96
|
-
noItems: "No saved items.",
|
|
97
|
-
loadingItems: "Loading saved items\u2026",
|
|
98
|
-
errorItems: "Could not load saved items.",
|
|
99
|
-
search: "Search saved items",
|
|
100
|
-
sort: "Sort saved items",
|
|
101
|
-
newest: "Newest first",
|
|
102
|
-
oldest: "Oldest first",
|
|
103
|
-
savedNewest: "Saved newest first",
|
|
104
|
-
savedOldest: "Saved oldest first",
|
|
105
|
-
updatedNewest: "Updated newest first",
|
|
106
|
-
updatedOldest: "Updated oldest first",
|
|
107
|
-
previousPage: "Previous page",
|
|
108
|
-
nextPage: "Next page",
|
|
109
|
-
pagination: "Pagination",
|
|
110
|
-
page: "Page",
|
|
111
|
-
selectItems: "Select saved items",
|
|
112
|
-
selectedCount: "selected",
|
|
113
|
-
deleteSelected: "Delete selected",
|
|
114
|
-
tagsToApply: "Tags to apply",
|
|
115
|
-
applyTags: "Apply tags",
|
|
116
|
-
savedMessage: "Item saved.",
|
|
117
|
-
removedMessage: "Item removed.",
|
|
118
|
-
noteSavedMessage: "Note saved."
|
|
119
|
-
};
|
|
120
|
-
var KeepUiLabelsContext = createContext({ labels: DEFAULT_LABELS });
|
|
121
|
-
function KeepUiProvider({ labels, locale, labelResolver, children }) {
|
|
122
|
-
const value = useMemo(() => {
|
|
123
|
-
const resolved = { ...DEFAULT_LABELS, ...labels };
|
|
124
|
-
return { locale, labels: resolved, labelResolver };
|
|
125
|
-
}, [labelResolver, labels, locale]);
|
|
126
|
-
return /* @__PURE__ */ jsx3(KeepUiLabelsContext.Provider, { value, children });
|
|
127
|
-
}
|
|
128
|
-
function useKeepUiLabels() {
|
|
129
|
-
return useContext(KeepUiLabelsContext);
|
|
130
|
-
}
|
|
131
|
-
function useUiLabel(key, override) {
|
|
132
|
-
const context = useKeepUiLabels();
|
|
133
|
-
return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
|
|
363
|
+
return /* @__PURE__ */ jsx4("div", { ...props, children: body });
|
|
134
364
|
}
|
|
135
365
|
|
|
136
366
|
// src/KeepBulkActions.tsx
|
|
137
|
-
import { Fragment, jsx as
|
|
367
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
138
368
|
function isAllSelected(items, selectedIds) {
|
|
139
369
|
if (items.length === 0) return false;
|
|
140
370
|
const selected = new Set(selectedIds);
|
|
@@ -156,6 +386,8 @@ function KeepBulkActions({
|
|
|
156
386
|
onSelectedIdsChange,
|
|
157
387
|
renderItem,
|
|
158
388
|
onCompleted,
|
|
389
|
+
selectionScope: controlledScope,
|
|
390
|
+
onSelectionScopeChange,
|
|
159
391
|
render,
|
|
160
392
|
children,
|
|
161
393
|
...props
|
|
@@ -165,21 +397,34 @@ function KeepBulkActions({
|
|
|
165
397
|
const deleteSelectedLabel = useUiLabel("deleteSelected");
|
|
166
398
|
const tagsLabel = useUiLabel("tagsToApply");
|
|
167
399
|
const applyTagsLabel = useUiLabel("applyTags");
|
|
400
|
+
const selectionScopeLabel = useUiLabel("selectionScope");
|
|
401
|
+
const currentPageLabel = useUiLabel("currentPage");
|
|
402
|
+
const searchResultsLabel = useUiLabel("searchResults");
|
|
403
|
+
const allItemsLabel = useUiLabel("allItems");
|
|
168
404
|
const list = useKeepList(query);
|
|
169
|
-
const
|
|
405
|
+
const queryList = useKeepList(query ? { ...query, pagination: void 0 } : { pagination: void 0 });
|
|
406
|
+
const allList = useKeepList({ pagination: void 0 });
|
|
407
|
+
const [uncontrolledScope, setUncontrolledScope] = useState2(controlledScope ?? "page");
|
|
408
|
+
const selectionScope = controlledScope ?? uncontrolledScope;
|
|
409
|
+
const setSelectionScope = (scope) => {
|
|
410
|
+
if (controlledScope === void 0) setUncontrolledScope(scope);
|
|
411
|
+
onSelectionScopeChange?.(scope);
|
|
412
|
+
};
|
|
413
|
+
const targetItems = selectionScope === "page" ? list.items : selectionScope === "query" ? queryList.items : allList.items;
|
|
414
|
+
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState2(defaultSelectedIds);
|
|
170
415
|
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
171
416
|
const selected = new Set(selectedIds);
|
|
172
|
-
const [tagsInput, setTagsInput] =
|
|
417
|
+
const [tagsInput, setTagsInput] = useState2("");
|
|
173
418
|
const setSelectedIds = (ids) => {
|
|
174
419
|
if (controlledSelectedIds === void 0) setUncontrolledSelectedIds(ids);
|
|
175
420
|
onSelectedIdsChange?.(ids);
|
|
176
421
|
};
|
|
177
422
|
const toggle = (id) => setSelectedIds(selected.has(id) ? selectedIds.filter((current) => current !== id) : [...selectedIds, id]);
|
|
178
|
-
const allSelected = isAllSelected(
|
|
179
|
-
const toggleAll = () => setSelectedIds(toggleSelectAll(
|
|
423
|
+
const allSelected = isAllSelected(targetItems, selectedIds);
|
|
424
|
+
const toggleAll = () => setSelectedIds(toggleSelectAll(targetItems, selectedIds));
|
|
180
425
|
const remove = async () => {
|
|
181
426
|
const ids = [...selectedIds];
|
|
182
|
-
await list.
|
|
427
|
+
await list.removeBatchWithUndo(ids);
|
|
183
428
|
onCompleted?.("remove", ids);
|
|
184
429
|
setSelectedIds([]);
|
|
185
430
|
};
|
|
@@ -190,7 +435,7 @@ function KeepBulkActions({
|
|
|
190
435
|
setSelectedIds([]);
|
|
191
436
|
};
|
|
192
437
|
const state = {
|
|
193
|
-
items:
|
|
438
|
+
items: targetItems,
|
|
194
439
|
selectedIds,
|
|
195
440
|
selectedCount: selectedIds.length,
|
|
196
441
|
isAllSelected: allSelected,
|
|
@@ -202,19 +447,36 @@ function KeepBulkActions({
|
|
|
202
447
|
toggleAll,
|
|
203
448
|
remove,
|
|
204
449
|
updateTags,
|
|
205
|
-
isMutating: list.isMutating
|
|
450
|
+
isMutating: list.isMutating,
|
|
451
|
+
selectionScope,
|
|
452
|
+
setSelectionScope
|
|
206
453
|
};
|
|
207
|
-
const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */
|
|
208
|
-
/* @__PURE__ */
|
|
209
|
-
/* @__PURE__ */
|
|
210
|
-
/* @__PURE__ */
|
|
211
|
-
|
|
454
|
+
const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
455
|
+
/* @__PURE__ */ jsxs2("fieldset", { children: [
|
|
456
|
+
/* @__PURE__ */ jsx5("legend", { children: selectItemsLabel }),
|
|
457
|
+
/* @__PURE__ */ jsxs2("label", { children: [
|
|
458
|
+
selectionScopeLabel,
|
|
459
|
+
/* @__PURE__ */ jsxs2(
|
|
460
|
+
"select",
|
|
461
|
+
{
|
|
462
|
+
value: selectionScope,
|
|
463
|
+
onChange: (event) => setSelectionScope(event.currentTarget.value),
|
|
464
|
+
children: [
|
|
465
|
+
/* @__PURE__ */ jsx5("option", { value: "page", children: currentPageLabel }),
|
|
466
|
+
/* @__PURE__ */ jsx5("option", { value: "query", children: searchResultsLabel }),
|
|
467
|
+
/* @__PURE__ */ jsx5("option", { value: "all", children: allItemsLabel })
|
|
468
|
+
]
|
|
469
|
+
}
|
|
470
|
+
)
|
|
471
|
+
] }),
|
|
472
|
+
/* @__PURE__ */ jsxs2("label", { children: [
|
|
473
|
+
/* @__PURE__ */ jsx5("input", { type: "checkbox", checked: allSelected, onChange: toggleAll, "aria-label": selectItemsLabel }),
|
|
212
474
|
selectedIds.length,
|
|
213
475
|
" ",
|
|
214
476
|
selectedCountLabel
|
|
215
477
|
] }),
|
|
216
|
-
|
|
217
|
-
/* @__PURE__ */
|
|
478
|
+
targetItems.map((item) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
479
|
+
/* @__PURE__ */ jsx5(
|
|
218
480
|
KeepItemCheckbox,
|
|
219
481
|
{
|
|
220
482
|
item,
|
|
@@ -225,12 +487,12 @@ function KeepBulkActions({
|
|
|
225
487
|
renderItem ? renderItem(item, selected.has(item.id)) : getMetaTitle(item.meta) ?? item.id
|
|
226
488
|
] }, item.id))
|
|
227
489
|
] }),
|
|
228
|
-
/* @__PURE__ */
|
|
229
|
-
/* @__PURE__ */
|
|
490
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: () => void remove(), disabled: selectedIds.length === 0 || list.isMutating, children: deleteSelectedLabel }),
|
|
491
|
+
/* @__PURE__ */ jsxs2("label", { children: [
|
|
230
492
|
tagsLabel,
|
|
231
|
-
/* @__PURE__ */
|
|
493
|
+
/* @__PURE__ */ jsx5("input", { value: tagsInput, onChange: (event) => setTagsInput(event.currentTarget.value) })
|
|
232
494
|
] }),
|
|
233
|
-
/* @__PURE__ */
|
|
495
|
+
/* @__PURE__ */ jsx5(
|
|
234
496
|
"button",
|
|
235
497
|
{
|
|
236
498
|
type: "button",
|
|
@@ -240,7 +502,7 @@ function KeepBulkActions({
|
|
|
240
502
|
}
|
|
241
503
|
)
|
|
242
504
|
] });
|
|
243
|
-
return /* @__PURE__ */
|
|
505
|
+
return /* @__PURE__ */ jsx5(
|
|
244
506
|
"section",
|
|
245
507
|
{
|
|
246
508
|
...props,
|
|
@@ -257,7 +519,7 @@ import {
|
|
|
257
519
|
KeepButton as CoreKeepButton,
|
|
258
520
|
useKeepItem
|
|
259
521
|
} from "@keepkit/core/react";
|
|
260
|
-
import { Fragment as Fragment2, jsx as
|
|
522
|
+
import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
|
|
261
523
|
function KeepButton({ labels, ...props }) {
|
|
262
524
|
const saveLabel = useUiLabel("save", typeof labels?.unsaved === "string" ? labels.unsaved : void 0);
|
|
263
525
|
const savedLabel = useUiLabel("saved", typeof labels?.saved === "string" ? labels.saved : void 0);
|
|
@@ -280,13 +542,13 @@ function KeepButton({ labels, ...props }) {
|
|
|
280
542
|
savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
|
|
281
543
|
unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
|
|
282
544
|
};
|
|
283
|
-
if (!customStateLabel) return /* @__PURE__ */
|
|
284
|
-
return /* @__PURE__ */
|
|
545
|
+
if (!customStateLabel) return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps });
|
|
546
|
+
return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx6(Fragment2, { children: getStateContent(state) }) });
|
|
285
547
|
}
|
|
286
548
|
|
|
287
549
|
// src/KeepCollection.tsx
|
|
288
550
|
import { KeepErrorBoundary as KeepErrorBoundary2, useKeepList as useKeepList4 } from "@keepkit/core/react";
|
|
289
|
-
import { useMemo as useMemo3, useState as
|
|
551
|
+
import { useMemo as useMemo3, useState as useState5 } from "react";
|
|
290
552
|
|
|
291
553
|
// src/KeepList.tsx
|
|
292
554
|
import {
|
|
@@ -297,8 +559,10 @@ import { isValidElement as isValidElement3 } from "react";
|
|
|
297
559
|
|
|
298
560
|
// src/KeepItemCard.tsx
|
|
299
561
|
import { useKeepItem as useKeepItem2 } from "@keepkit/core/react";
|
|
300
|
-
import {
|
|
301
|
-
|
|
562
|
+
import {
|
|
563
|
+
isValidElement as isValidElement2
|
|
564
|
+
} from "react";
|
|
565
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
302
566
|
function KeepItemCard({
|
|
303
567
|
item,
|
|
304
568
|
title,
|
|
@@ -306,6 +570,8 @@ function KeepItemCard({
|
|
|
306
570
|
getImageProps,
|
|
307
571
|
imageComponent: ImageComponent,
|
|
308
572
|
renderImage,
|
|
573
|
+
renderTags,
|
|
574
|
+
showTags = true,
|
|
309
575
|
imageAlt,
|
|
310
576
|
render,
|
|
311
577
|
children,
|
|
@@ -315,6 +581,12 @@ function KeepItemCard({
|
|
|
315
581
|
showSaveButton = true,
|
|
316
582
|
saveButtonLabels,
|
|
317
583
|
asChild = false,
|
|
584
|
+
href: hrefOption,
|
|
585
|
+
onOpen,
|
|
586
|
+
linkTarget = "title",
|
|
587
|
+
linkComponent: LinkComponent,
|
|
588
|
+
linkTargetAttribute,
|
|
589
|
+
linkRel,
|
|
318
590
|
className,
|
|
319
591
|
...rootProps
|
|
320
592
|
}) {
|
|
@@ -327,10 +599,28 @@ function KeepItemCard({
|
|
|
327
599
|
isSaved: itemState.isSaved,
|
|
328
600
|
isMutating: itemState.isMutating,
|
|
329
601
|
error: itemState.error,
|
|
330
|
-
remove: itemState.remove
|
|
602
|
+
remove: itemState.remove,
|
|
603
|
+
status: item.status
|
|
331
604
|
};
|
|
332
605
|
const resolvedTitle = typeof title === "function" ? title(item) : title ?? getTitle?.(item) ?? getMetaTitle(item.meta) ?? item.id;
|
|
333
606
|
const imageProps = getImageProps?.(item, resolvedTitle);
|
|
607
|
+
const href = typeof hrefOption === "function" ? hrefOption(item) : hrefOption;
|
|
608
|
+
const isAvailable = item.status === void 0 || item.status === "available";
|
|
609
|
+
const statusLabelKey = item.status && item.status !== "available" ? getStatusLabelKey(item.status) : "statusUnknown";
|
|
610
|
+
const unavailableLabel = useUiLabel(statusLabelKey);
|
|
611
|
+
const tagsLabel = useUiLabel("tags");
|
|
612
|
+
const statusLabel = item.status && item.status !== "available" ? unavailableLabel : void 0;
|
|
613
|
+
function renderLink(content) {
|
|
614
|
+
if (!href || !isAvailable) return content;
|
|
615
|
+
const linkProps = {
|
|
616
|
+
href,
|
|
617
|
+
target: linkTargetAttribute,
|
|
618
|
+
rel: linkRel,
|
|
619
|
+
onClick: (event) => onOpen?.(item, event),
|
|
620
|
+
children: content
|
|
621
|
+
};
|
|
622
|
+
return LinkComponent ? /* @__PURE__ */ jsx7(LinkComponent, { ...linkProps }) : /* @__PURE__ */ jsx7("a", { ...linkProps });
|
|
623
|
+
}
|
|
334
624
|
async function handleRemove() {
|
|
335
625
|
try {
|
|
336
626
|
await itemState.remove();
|
|
@@ -339,10 +629,12 @@ function KeepItemCard({
|
|
|
339
629
|
onRemoveError?.(error);
|
|
340
630
|
}
|
|
341
631
|
}
|
|
342
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */
|
|
343
|
-
imageProps ? renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ?? (ImageComponent ? /* @__PURE__ */
|
|
344
|
-
/* @__PURE__ */
|
|
345
|
-
|
|
632
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
633
|
+
imageProps ? renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ?? (ImageComponent ? /* @__PURE__ */ jsx7(ImageComponent, { ...imageProps, alt: imageAlt ?? imageProps.alt }) : /* @__PURE__ */ jsx7("img", { ...imageProps, alt: imageAlt ?? imageProps.alt })) : null,
|
|
634
|
+
/* @__PURE__ */ jsx7("h3", { children: linkTarget === "title" ? renderLink(resolvedTitle) : resolvedTitle }),
|
|
635
|
+
showTags && (item.tags?.length ?? 0) > 0 ? renderTags ? renderTags(item.tags ?? [], item) : /* @__PURE__ */ jsx7("ul", { "aria-label": tagsLabel, children: item.tags?.map((tag) => /* @__PURE__ */ jsx7("li", { children: tag }, tag)) }) : null,
|
|
636
|
+
statusLabel ? /* @__PURE__ */ jsx7("p", { "data-status": item.status, children: statusLabel }) : null,
|
|
637
|
+
showSaveButton ? /* @__PURE__ */ jsx7(
|
|
346
638
|
KeepButton,
|
|
347
639
|
{
|
|
348
640
|
item: toKeepButtonItem(item),
|
|
@@ -350,8 +642,9 @@ function KeepItemCard({
|
|
|
350
642
|
getAriaLabel: (buttonState) => `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`
|
|
351
643
|
}
|
|
352
644
|
) : null,
|
|
353
|
-
/* @__PURE__ */
|
|
645
|
+
/* @__PURE__ */ jsx7("button", { type: "button", onClick: () => void handleRemove(), disabled: itemState.isMutating, children: removeLabel ?? removeActionLabel })
|
|
354
646
|
] });
|
|
647
|
+
const linkedBody = linkTarget === "card" ? renderLink(body) : body;
|
|
355
648
|
return renderRoot(
|
|
356
649
|
asChild,
|
|
357
650
|
isValidElement2(children) ? children : void 0,
|
|
@@ -360,20 +653,35 @@ function KeepItemCard({
|
|
|
360
653
|
className,
|
|
361
654
|
"aria-busy": itemState.isMutating || rootProps["aria-busy"],
|
|
362
655
|
"data-state": itemState.isSaved ? "saved" : "unsaved",
|
|
656
|
+
"data-status": item.status ?? "available",
|
|
363
657
|
"data-loading": itemState.isMutating ? "true" : void 0
|
|
364
658
|
},
|
|
365
|
-
|
|
659
|
+
linkedBody,
|
|
366
660
|
"KeepItemCard"
|
|
367
661
|
);
|
|
368
662
|
}
|
|
663
|
+
function getStatusLabelKey(status) {
|
|
664
|
+
switch (status) {
|
|
665
|
+
case "expired":
|
|
666
|
+
return "statusExpired";
|
|
667
|
+
case "removed":
|
|
668
|
+
return "statusRemoved";
|
|
669
|
+
case "deleted":
|
|
670
|
+
return "statusDeleted";
|
|
671
|
+
case "private":
|
|
672
|
+
return "statusPrivate";
|
|
673
|
+
default:
|
|
674
|
+
return "statusUnknown";
|
|
675
|
+
}
|
|
676
|
+
}
|
|
369
677
|
|
|
370
678
|
// src/KeepList.tsx
|
|
371
|
-
import { jsx as
|
|
679
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
372
680
|
function KeepList(props) {
|
|
373
681
|
const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
|
|
374
|
-
const content = /* @__PURE__ */
|
|
682
|
+
const content = /* @__PURE__ */ jsx8(KeepListContent, { ...listProps });
|
|
375
683
|
if (fallback === void 0 && onBoundaryError === void 0) return content;
|
|
376
|
-
return /* @__PURE__ */
|
|
684
|
+
return /* @__PURE__ */ jsx8(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
|
|
377
685
|
}
|
|
378
686
|
function KeepListContent({
|
|
379
687
|
query,
|
|
@@ -383,6 +691,7 @@ function KeepListContent({
|
|
|
383
691
|
empty,
|
|
384
692
|
error: errorContent,
|
|
385
693
|
itemCardProps,
|
|
694
|
+
layout = "list",
|
|
386
695
|
asChild = false,
|
|
387
696
|
className,
|
|
388
697
|
...rootProps
|
|
@@ -397,7 +706,8 @@ function KeepListContent({
|
|
|
397
706
|
loading: loading ?? defaultLoading,
|
|
398
707
|
empty: empty ?? defaultEmpty,
|
|
399
708
|
error: errorContent ?? defaultError,
|
|
400
|
-
itemCardProps
|
|
709
|
+
itemCardProps,
|
|
710
|
+
layout
|
|
401
711
|
});
|
|
402
712
|
return renderRoot(
|
|
403
713
|
asChild,
|
|
@@ -425,15 +735,22 @@ function getListBody(state, options) {
|
|
|
425
735
|
if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);
|
|
426
736
|
if (typeof options.children === "function") return options.children(state);
|
|
427
737
|
if (options.children !== void 0 && !isValidElement3(options.children)) return options.children;
|
|
428
|
-
return /* @__PURE__ */
|
|
429
|
-
|
|
430
|
-
|
|
738
|
+
return /* @__PURE__ */ jsx8(
|
|
739
|
+
"ul",
|
|
740
|
+
{
|
|
741
|
+
"data-layout": options.layout,
|
|
742
|
+
style: options.layout === "grid" ? { display: "grid", gap: "1rem", gridTemplateColumns: "repeat(auto-fit, minmax(16rem, 1fr))" } : options.layout === "compact" ? { display: "grid", gap: "0.5rem", gridTemplateColumns: "repeat(auto-fit, minmax(12rem, 1fr))" } : { display: "flex", flexDirection: "column", gap: "1rem" },
|
|
743
|
+
children: state.items.map(
|
|
744
|
+
(item) => options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8(KeepItemCard, { item, ...options.itemCardProps }) }, item.id)
|
|
745
|
+
)
|
|
746
|
+
}
|
|
747
|
+
);
|
|
431
748
|
}
|
|
432
749
|
|
|
433
750
|
// src/KeepTagFilter.tsx
|
|
434
751
|
import { useKeepList as useKeepList3 } from "@keepkit/core/react";
|
|
435
|
-
import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as
|
|
436
|
-
import { jsx as
|
|
752
|
+
import { isValidElement as isValidElement4, useCallback, useMemo as useMemo2, useState as useState3 } from "react";
|
|
753
|
+
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
437
754
|
function KeepTagFilter({
|
|
438
755
|
query,
|
|
439
756
|
value: controlledValue,
|
|
@@ -451,7 +768,7 @@ function KeepTagFilter({
|
|
|
451
768
|
}) {
|
|
452
769
|
const uiAllLabel = useUiLabel("allTags");
|
|
453
770
|
const uiAriaLabel = useUiLabel("filterTags");
|
|
454
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
771
|
+
const [uncontrolledValue, setUncontrolledValue] = useState3(defaultValue);
|
|
455
772
|
const resolvedValue = controlledValue ?? uncontrolledValue;
|
|
456
773
|
const list = useKeepList3({
|
|
457
774
|
...query,
|
|
@@ -470,12 +787,12 @@ function KeepTagFilter({
|
|
|
470
787
|
[list.tagCounts, list.tags, resolvedValue, select]
|
|
471
788
|
);
|
|
472
789
|
const contentChildren = asChild && isValidElement4(children) ? void 0 : children;
|
|
473
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */
|
|
474
|
-
/* @__PURE__ */
|
|
475
|
-
/* @__PURE__ */
|
|
476
|
-
list.tags.map((tag) => /* @__PURE__ */
|
|
790
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs4("fieldset", { children: [
|
|
791
|
+
/* @__PURE__ */ jsx9("legend", { children: ariaLabel ?? uiAriaLabel }),
|
|
792
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": resolvedValue === void 0, onClick: () => select(), children: allLabel ?? uiAllLabel }),
|
|
793
|
+
list.tags.map((tag) => /* @__PURE__ */ jsxs4("button", { type: "button", "aria-pressed": resolvedValue === tag, onClick: () => select(tag), children: [
|
|
477
794
|
renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag,
|
|
478
|
-
/* @__PURE__ */
|
|
795
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
479
796
|
" (",
|
|
480
797
|
list.tagCounts[tag] ?? 0,
|
|
481
798
|
")"
|
|
@@ -497,8 +814,8 @@ function KeepTagFilter({
|
|
|
497
814
|
}
|
|
498
815
|
|
|
499
816
|
// src/query-controls.tsx
|
|
500
|
-
import { useEffect, useState as
|
|
501
|
-
import { Fragment as Fragment4, jsx as
|
|
817
|
+
import { useEffect, useState as useState4 } from "react";
|
|
818
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
502
819
|
function KeepSearchInput({
|
|
503
820
|
value: controlledValue,
|
|
504
821
|
defaultValue = "",
|
|
@@ -509,7 +826,7 @@ function KeepSearchInput({
|
|
|
509
826
|
...props
|
|
510
827
|
}) {
|
|
511
828
|
const label = useUiLabel("search");
|
|
512
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
829
|
+
const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
|
|
513
830
|
const value = controlledValue ?? uncontrolledValue;
|
|
514
831
|
useEffect(() => {
|
|
515
832
|
if (!onValueChange) return;
|
|
@@ -520,7 +837,7 @@ function KeepSearchInput({
|
|
|
520
837
|
const timer = window.setTimeout(() => onValueChange(value), debounceMs);
|
|
521
838
|
return () => window.clearTimeout(timer);
|
|
522
839
|
}, [debounceMs, onValueChange, value]);
|
|
523
|
-
return /* @__PURE__ */
|
|
840
|
+
return /* @__PURE__ */ jsx10(
|
|
524
841
|
"input",
|
|
525
842
|
{
|
|
526
843
|
...props,
|
|
@@ -550,15 +867,15 @@ function KeepSortSelect({
|
|
|
550
867
|
const updatedOldestLabel = useUiLabel("updatedOldest");
|
|
551
868
|
const savedNewestLabel = useUiLabel("savedNewest");
|
|
552
869
|
const savedOldestLabel = useUiLabel("savedOldest");
|
|
553
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
870
|
+
const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
|
|
554
871
|
const value = controlledValue ?? uncontrolledValue;
|
|
555
|
-
const options = children ?? /* @__PURE__ */
|
|
556
|
-
/* @__PURE__ */
|
|
557
|
-
/* @__PURE__ */
|
|
558
|
-
/* @__PURE__ */
|
|
559
|
-
/* @__PURE__ */
|
|
872
|
+
const options = children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
873
|
+
/* @__PURE__ */ jsx10("option", { value: "updatedAt:desc", children: updatedNewestLabel }),
|
|
874
|
+
/* @__PURE__ */ jsx10("option", { value: "updatedAt:asc", children: updatedOldestLabel }),
|
|
875
|
+
/* @__PURE__ */ jsx10("option", { value: "savedAt:desc", children: savedNewestLabel }),
|
|
876
|
+
/* @__PURE__ */ jsx10("option", { value: "savedAt:asc", children: savedOldestLabel })
|
|
560
877
|
] });
|
|
561
|
-
return /* @__PURE__ */
|
|
878
|
+
return /* @__PURE__ */ jsx10(
|
|
562
879
|
"select",
|
|
563
880
|
{
|
|
564
881
|
...props,
|
|
@@ -600,11 +917,11 @@ function KeepPagination({
|
|
|
600
917
|
"aria-label": props["aria-label"] ?? paginationLabel,
|
|
601
918
|
"data-state": pageCount > 1 ? "active" : "idle"
|
|
602
919
|
};
|
|
603
|
-
if (render) return /* @__PURE__ */
|
|
920
|
+
if (render) return /* @__PURE__ */ jsx10("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
|
|
604
921
|
const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));
|
|
605
|
-
return /* @__PURE__ */
|
|
606
|
-
/* @__PURE__ */
|
|
607
|
-
visiblePages.map((nextPage) => /* @__PURE__ */
|
|
922
|
+
return /* @__PURE__ */ jsxs5("nav", { ...navProps, children: [
|
|
923
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => goToPage(currentPage - 1), disabled: currentPage <= 1, children: previousPageLabel }),
|
|
924
|
+
visiblePages.map((nextPage) => /* @__PURE__ */ jsx10(
|
|
608
925
|
"button",
|
|
609
926
|
{
|
|
610
927
|
type: "button",
|
|
@@ -615,7 +932,7 @@ function KeepPagination({
|
|
|
615
932
|
},
|
|
616
933
|
nextPage
|
|
617
934
|
)),
|
|
618
|
-
/* @__PURE__ */
|
|
935
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => goToPage(currentPage + 1), disabled: currentPage >= pageCount, children: nextPageLabel })
|
|
619
936
|
] });
|
|
620
937
|
}
|
|
621
938
|
function getVisiblePages(currentPage, pageCount, maxPageButtons) {
|
|
@@ -625,17 +942,102 @@ function getVisiblePages(currentPage, pageCount, maxPageButtons) {
|
|
|
625
942
|
return Array.from({ length: maxPageButtons }, (_, index) => start + index);
|
|
626
943
|
}
|
|
627
944
|
|
|
945
|
+
// src/url-sync.tsx
|
|
946
|
+
import {
|
|
947
|
+
DEFAULT_KEEP_URL_PARAMS,
|
|
948
|
+
decodeKeepListQuery,
|
|
949
|
+
encodeKeepListQuery
|
|
950
|
+
} from "@keepkit/core/core";
|
|
951
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
952
|
+
function createNextPagesRouterAdapter(router) {
|
|
953
|
+
const getUrl = () => router.asPath ?? (typeof window === "undefined" ? "/" : window.location.href);
|
|
954
|
+
return {
|
|
955
|
+
getUrl,
|
|
956
|
+
subscribe: router.events ? (listener) => {
|
|
957
|
+
router.events?.on("routeChangeComplete", listener);
|
|
958
|
+
return () => router.events?.off("routeChangeComplete", listener);
|
|
959
|
+
} : void 0,
|
|
960
|
+
navigate: (url, mode) => {
|
|
961
|
+
void router[mode](url, void 0, { shallow: true });
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
function useKeepUrlSync({
|
|
966
|
+
enabled = true,
|
|
967
|
+
query,
|
|
968
|
+
onQueryChange,
|
|
969
|
+
options = {},
|
|
970
|
+
adapter: providedAdapter
|
|
971
|
+
}) {
|
|
972
|
+
const browserAdapterRef = useRef2(getBrowserAdapter());
|
|
973
|
+
const adapter = providedAdapter ?? browserAdapterRef.current;
|
|
974
|
+
const onQueryChangeRef = useRef2(onQueryChange);
|
|
975
|
+
onQueryChangeRef.current = onQueryChange;
|
|
976
|
+
const skipWriteRef = useRef2(true);
|
|
977
|
+
const params = options.params;
|
|
978
|
+
useEffect2(() => {
|
|
979
|
+
if (!enabled) return;
|
|
980
|
+
const read = () => {
|
|
981
|
+
const url = adapter.getUrl();
|
|
982
|
+
const decoded = decodeKeepListQuery(url, { params });
|
|
983
|
+
skipWriteRef.current = true;
|
|
984
|
+
onQueryChangeRef.current((previousQuery) => ({
|
|
985
|
+
...previousQuery,
|
|
986
|
+
...decoded.search ? { search: decoded.search } : { search: void 0 },
|
|
987
|
+
...decoded.tags ? { tags: decoded.tags } : { tags: void 0 },
|
|
988
|
+
...decoded.sort ? { sort: decoded.sort } : {},
|
|
989
|
+
...decoded.pagination ? { pagination: { ...previousQuery.pagination, ...decoded.pagination } } : {}
|
|
990
|
+
}));
|
|
991
|
+
};
|
|
992
|
+
read();
|
|
993
|
+
return adapter.subscribe?.(read);
|
|
994
|
+
}, [adapter, enabled, params]);
|
|
995
|
+
useEffect2(() => {
|
|
996
|
+
if (!enabled) return;
|
|
997
|
+
if (skipWriteRef.current) {
|
|
998
|
+
skipWriteRef.current = false;
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
const currentUrl = new URL(adapter.getUrl(), "http://keepkit.invalid");
|
|
1002
|
+
const urlParams = { ...DEFAULT_KEEP_URL_PARAMS, ...params };
|
|
1003
|
+
for (const key of Object.values(urlParams)) currentUrl.searchParams.delete(key);
|
|
1004
|
+
const nextParams = encodeKeepListQuery(query, { params });
|
|
1005
|
+
nextParams.forEach((value, key) => {
|
|
1006
|
+
currentUrl.searchParams.append(key, value);
|
|
1007
|
+
});
|
|
1008
|
+
const nextUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;
|
|
1009
|
+
adapter.navigate(nextUrl, options.history ?? "push");
|
|
1010
|
+
}, [adapter, enabled, options.history, params, query]);
|
|
1011
|
+
}
|
|
1012
|
+
function getBrowserAdapter() {
|
|
1013
|
+
return {
|
|
1014
|
+
getUrl: () => typeof window === "undefined" ? "/" : window.location.href,
|
|
1015
|
+
subscribe: (listener) => {
|
|
1016
|
+
if (typeof window === "undefined") return () => void 0;
|
|
1017
|
+
window.addEventListener("popstate", listener);
|
|
1018
|
+
return () => window.removeEventListener("popstate", listener);
|
|
1019
|
+
},
|
|
1020
|
+
navigate: (url, mode) => {
|
|
1021
|
+
if (typeof window === "undefined") return;
|
|
1022
|
+
window.history[mode === "push" ? "pushState" : "replaceState"]({}, "", url);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
|
|
628
1027
|
// src/KeepCollection.tsx
|
|
629
|
-
import { jsx as
|
|
1028
|
+
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
630
1029
|
function KeepCollection(props) {
|
|
631
1030
|
const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
|
|
632
|
-
const content = /* @__PURE__ */
|
|
1031
|
+
const content = /* @__PURE__ */ jsx11(KeepCollectionContent, { ...collectionProps });
|
|
633
1032
|
if (fallback === void 0 && onBoundaryError === void 0) return content;
|
|
634
|
-
return /* @__PURE__ */
|
|
1033
|
+
return /* @__PURE__ */ jsx11(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
|
|
635
1034
|
}
|
|
636
1035
|
function KeepCollectionContent({
|
|
637
1036
|
query = {},
|
|
638
1037
|
pageSize = 20,
|
|
1038
|
+
layout = "list",
|
|
1039
|
+
urlSync = false,
|
|
1040
|
+
urlAdapter,
|
|
639
1041
|
features,
|
|
640
1042
|
renderItem,
|
|
641
1043
|
itemCardProps,
|
|
@@ -653,10 +1055,10 @@ function KeepCollectionContent({
|
|
|
653
1055
|
bulkActions: false,
|
|
654
1056
|
...features
|
|
655
1057
|
};
|
|
656
|
-
const [searchValue, setSearchValue] =
|
|
657
|
-
const [sort, setSort] =
|
|
658
|
-
const [tag, setTag] =
|
|
659
|
-
const [page, setPage] =
|
|
1058
|
+
const [searchValue, setSearchValue] = useState5(query.search?.query ?? "");
|
|
1059
|
+
const [sort, setSort] = useState5(query.sort ?? { by: "updatedAt", direction: "desc" });
|
|
1060
|
+
const [tag, setTag] = useState5(query.tags?.[0]);
|
|
1061
|
+
const [page, setPage] = useState5(query.pagination?.page ?? 1);
|
|
660
1062
|
const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
|
|
661
1063
|
const resolvedQuery = useMemo3(
|
|
662
1064
|
() => ({
|
|
@@ -668,8 +1070,21 @@ function KeepCollectionContent({
|
|
|
668
1070
|
}),
|
|
669
1071
|
[enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag]
|
|
670
1072
|
);
|
|
1073
|
+
useKeepUrlSync({
|
|
1074
|
+
enabled: Boolean(urlSync),
|
|
1075
|
+
query: resolvedQuery,
|
|
1076
|
+
onQueryChange: (nextOrUpdater) => {
|
|
1077
|
+
const next = typeof nextOrUpdater === "function" ? nextOrUpdater(resolvedQuery) : nextOrUpdater;
|
|
1078
|
+
setSearchValue(next.search?.query ?? "");
|
|
1079
|
+
setSort(next.sort ?? { by: "updatedAt", direction: "desc" });
|
|
1080
|
+
setTag(next.tags?.[0]);
|
|
1081
|
+
setPage(next.pagination?.page ?? 1);
|
|
1082
|
+
},
|
|
1083
|
+
options: typeof urlSync === "object" ? urlSync : {},
|
|
1084
|
+
adapter: urlAdapter
|
|
1085
|
+
});
|
|
671
1086
|
const list = useKeepList4(resolvedQuery);
|
|
672
|
-
return /* @__PURE__ */
|
|
1087
|
+
return /* @__PURE__ */ jsxs6(
|
|
673
1088
|
"section",
|
|
674
1089
|
{
|
|
675
1090
|
...rootProps,
|
|
@@ -678,8 +1093,8 @@ function KeepCollectionContent({
|
|
|
678
1093
|
"data-state": getCollectionState(list),
|
|
679
1094
|
"data-loading": list.isLoading || list.isMutating ? "true" : void 0,
|
|
680
1095
|
children: [
|
|
681
|
-
/* @__PURE__ */
|
|
682
|
-
enabled.search ? /* @__PURE__ */
|
|
1096
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
1097
|
+
enabled.search ? /* @__PURE__ */ jsx11(
|
|
683
1098
|
KeepSearchInput,
|
|
684
1099
|
{
|
|
685
1100
|
value: searchValue,
|
|
@@ -689,7 +1104,7 @@ function KeepCollectionContent({
|
|
|
689
1104
|
}
|
|
690
1105
|
}
|
|
691
1106
|
) : null,
|
|
692
|
-
enabled.sort ? /* @__PURE__ */
|
|
1107
|
+
enabled.sort ? /* @__PURE__ */ jsx11(
|
|
693
1108
|
KeepSortSelect,
|
|
694
1109
|
{
|
|
695
1110
|
value: sortToValue(sort),
|
|
@@ -699,7 +1114,7 @@ function KeepCollectionContent({
|
|
|
699
1114
|
}
|
|
700
1115
|
}
|
|
701
1116
|
) : null,
|
|
702
|
-
enabled.tagFilter ? /* @__PURE__ */
|
|
1117
|
+
enabled.tagFilter ? /* @__PURE__ */ jsx11(
|
|
703
1118
|
KeepTagFilter,
|
|
704
1119
|
{
|
|
705
1120
|
query,
|
|
@@ -711,18 +1126,19 @@ function KeepCollectionContent({
|
|
|
711
1126
|
}
|
|
712
1127
|
) : null
|
|
713
1128
|
] }),
|
|
714
|
-
/* @__PURE__ */
|
|
1129
|
+
/* @__PURE__ */ jsx11(
|
|
715
1130
|
KeepList,
|
|
716
1131
|
{
|
|
717
1132
|
query: resolvedQuery,
|
|
718
1133
|
renderItem,
|
|
719
1134
|
itemCardProps,
|
|
1135
|
+
layout,
|
|
720
1136
|
loading,
|
|
721
1137
|
empty,
|
|
722
1138
|
error
|
|
723
1139
|
}
|
|
724
1140
|
),
|
|
725
|
-
enabled.pagination ? /* @__PURE__ */
|
|
1141
|
+
enabled.pagination ? /* @__PURE__ */ jsx11(
|
|
726
1142
|
KeepPagination,
|
|
727
1143
|
{
|
|
728
1144
|
totalCount: list.totalCount,
|
|
@@ -731,7 +1147,7 @@ function KeepCollectionContent({
|
|
|
731
1147
|
onPageChange: (nextPage) => setPage(nextPage)
|
|
732
1148
|
}
|
|
733
1149
|
) : null,
|
|
734
|
-
enabled.bulkActions ? /* @__PURE__ */
|
|
1150
|
+
enabled.bulkActions ? /* @__PURE__ */ jsx11(KeepBulkActions, { query: resolvedQuery }) : null
|
|
735
1151
|
]
|
|
736
1152
|
}
|
|
737
1153
|
);
|
|
@@ -743,16 +1159,23 @@ function getCollectionState(list) {
|
|
|
743
1159
|
return "ready";
|
|
744
1160
|
}
|
|
745
1161
|
|
|
1162
|
+
// src/KeepLayout.tsx
|
|
1163
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1164
|
+
function KeepLayout({ layout = "list", children, style, ...props }) {
|
|
1165
|
+
const layoutStyle = layout === "grid" ? { display: "grid", gap: "1rem", gridTemplateColumns: "repeat(auto-fit, minmax(16rem, 1fr))" } : layout === "compact" ? { display: "grid", gap: "0.5rem", gridTemplateColumns: "repeat(auto-fit, minmax(12rem, 1fr))" } : { display: "flex", flexDirection: "column", gap: "1rem" };
|
|
1166
|
+
return /* @__PURE__ */ jsx12("div", { ...props, style: { ...layoutStyle, ...style }, "data-layout": layout, children });
|
|
1167
|
+
}
|
|
1168
|
+
|
|
746
1169
|
// src/KeepNoteEditor.tsx
|
|
747
1170
|
import { useKeepItem as useKeepItem3 } from "@keepkit/core/react";
|
|
748
1171
|
import {
|
|
749
1172
|
isValidElement as isValidElement5,
|
|
750
1173
|
useCallback as useCallback2,
|
|
751
|
-
useEffect as
|
|
752
|
-
useRef,
|
|
753
|
-
useState as
|
|
1174
|
+
useEffect as useEffect3,
|
|
1175
|
+
useRef as useRef3,
|
|
1176
|
+
useState as useState6
|
|
754
1177
|
} from "react";
|
|
755
|
-
import { Fragment as Fragment5, jsx as
|
|
1178
|
+
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
756
1179
|
function KeepNoteEditor({
|
|
757
1180
|
item,
|
|
758
1181
|
label,
|
|
@@ -772,11 +1195,11 @@ function KeepNoteEditor({
|
|
|
772
1195
|
const itemState = useKeepItem3(item);
|
|
773
1196
|
const { error, isMutating, item: savedItem, updateNote } = itemState;
|
|
774
1197
|
const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
|
|
775
|
-
const [note, setNote] =
|
|
1198
|
+
const [note, setNote] = useState6(item.note ?? "");
|
|
776
1199
|
const baselineNote = savedItem?.note ?? item.note ?? "";
|
|
777
1200
|
const isDirty = note !== baselineNote;
|
|
778
|
-
const lastSavedNoteRef =
|
|
779
|
-
|
|
1201
|
+
const lastSavedNoteRef = useRef3(void 0);
|
|
1202
|
+
useEffect3(() => setNote(baselineNote), [baselineNote]);
|
|
780
1203
|
const save = useCallback2(async () => {
|
|
781
1204
|
const nextNote = note.trim() || void 0;
|
|
782
1205
|
try {
|
|
@@ -788,7 +1211,7 @@ function KeepNoteEditor({
|
|
|
788
1211
|
throw error2;
|
|
789
1212
|
}
|
|
790
1213
|
}, [note, onSaveError, onSaved, updateNote]);
|
|
791
|
-
|
|
1214
|
+
useEffect3(() => {
|
|
792
1215
|
if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;
|
|
793
1216
|
const timer = window.setTimeout(() => void save().catch(() => void 0), debounceMs);
|
|
794
1217
|
return () => window.clearTimeout(timer);
|
|
@@ -802,10 +1225,10 @@ function KeepNoteEditor({
|
|
|
802
1225
|
error,
|
|
803
1226
|
save
|
|
804
1227
|
};
|
|
805
|
-
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */
|
|
806
|
-
/* @__PURE__ */
|
|
1228
|
+
const body = render ? render(state) : typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
1229
|
+
/* @__PURE__ */ jsxs7("label", { children: [
|
|
807
1230
|
label ?? defaultLabel,
|
|
808
|
-
/* @__PURE__ */
|
|
1231
|
+
/* @__PURE__ */ jsx13(
|
|
809
1232
|
"textarea",
|
|
810
1233
|
{
|
|
811
1234
|
value: note,
|
|
@@ -821,14 +1244,14 @@ function KeepNoteEditor({
|
|
|
821
1244
|
}
|
|
822
1245
|
)
|
|
823
1246
|
] }),
|
|
824
|
-
/* @__PURE__ */
|
|
1247
|
+
/* @__PURE__ */ jsx13("button", { type: "submit", disabled: isMutating, "aria-busy": isMutating, children: saveLabel ?? defaultSaveLabel })
|
|
825
1248
|
] });
|
|
826
1249
|
const handleSubmit = (event) => {
|
|
827
1250
|
event.preventDefault();
|
|
828
1251
|
void save().catch(() => void 0);
|
|
829
1252
|
};
|
|
830
1253
|
if (!asChild) {
|
|
831
|
-
return /* @__PURE__ */
|
|
1254
|
+
return /* @__PURE__ */ jsx13(
|
|
832
1255
|
"form",
|
|
833
1256
|
{
|
|
834
1257
|
...formProps,
|
|
@@ -861,8 +1284,8 @@ function KeepNoteEditor({
|
|
|
861
1284
|
|
|
862
1285
|
// src/KeepTagEditor.tsx
|
|
863
1286
|
import { useKeepItem as useKeepItem4 } from "@keepkit/core/react";
|
|
864
|
-
import { useCallback as useCallback3, useEffect as
|
|
865
|
-
import { Fragment as Fragment6, jsx as
|
|
1287
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useState as useState7 } from "react";
|
|
1288
|
+
import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
866
1289
|
function KeepTagEditor({
|
|
867
1290
|
item,
|
|
868
1291
|
availableTags = [],
|
|
@@ -875,9 +1298,9 @@ function KeepTagEditor({
|
|
|
875
1298
|
const removeLabel = useUiLabel("remove");
|
|
876
1299
|
const applyTagsLabel = useUiLabel("applyTags");
|
|
877
1300
|
const itemState = useKeepItem4(item);
|
|
878
|
-
const [tags, setTags] =
|
|
879
|
-
const [input, setInput] =
|
|
880
|
-
|
|
1301
|
+
const [tags, setTags] = useState7(item.tags ?? []);
|
|
1302
|
+
const [input, setInput] = useState7("");
|
|
1303
|
+
useEffect4(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
|
|
881
1304
|
const save = useCallback3(async () => {
|
|
882
1305
|
const nextTags = normalizeUiTags(tags);
|
|
883
1306
|
try {
|
|
@@ -893,10 +1316,10 @@ function KeepTagEditor({
|
|
|
893
1316
|
setTags(normalizeUiTags([...tags, tag]));
|
|
894
1317
|
setInput("");
|
|
895
1318
|
};
|
|
896
|
-
const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */
|
|
897
|
-
/* @__PURE__ */
|
|
1319
|
+
const body = render ? render({ tags, setTags, save, isSaving: itemState.isMutating }) : /* @__PURE__ */ jsxs8(Fragment6, { children: [
|
|
1320
|
+
/* @__PURE__ */ jsxs8("label", { children: [
|
|
898
1321
|
tagsLabel,
|
|
899
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsx14(
|
|
900
1323
|
"input",
|
|
901
1324
|
{
|
|
902
1325
|
value: input,
|
|
@@ -915,14 +1338,14 @@ function KeepTagEditor({
|
|
|
915
1338
|
}
|
|
916
1339
|
)
|
|
917
1340
|
] }),
|
|
918
|
-
availableTags.length > 0 ? /* @__PURE__ */
|
|
919
|
-
/* @__PURE__ */
|
|
1341
|
+
availableTags.length > 0 ? /* @__PURE__ */ jsx14("datalist", { id: `keep-tags-${item.id}`, children: availableTags.map((tag) => /* @__PURE__ */ jsx14("option", { value: tag }, tag)) }) : null,
|
|
1342
|
+
/* @__PURE__ */ jsx14("ul", { "aria-label": tagsLabel, children: tags.map((tag) => /* @__PURE__ */ jsxs8("li", { children: [
|
|
920
1343
|
tag,
|
|
921
|
-
/* @__PURE__ */
|
|
1344
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setTags(tags.filter((current) => current !== tag)), children: removeLabel })
|
|
922
1345
|
] }, tag)) }),
|
|
923
|
-
/* @__PURE__ */
|
|
1346
|
+
/* @__PURE__ */ jsx14("button", { type: "submit", disabled: itemState.isMutating, "aria-busy": itemState.isMutating, children: applyTagsLabel })
|
|
924
1347
|
] });
|
|
925
|
-
return /* @__PURE__ */
|
|
1348
|
+
return /* @__PURE__ */ jsx14(
|
|
926
1349
|
"form",
|
|
927
1350
|
{
|
|
928
1351
|
...props,
|
|
@@ -939,10 +1362,24 @@ function KeepTagEditor({
|
|
|
939
1362
|
);
|
|
940
1363
|
}
|
|
941
1364
|
|
|
1365
|
+
// src/KeepUndo.tsx
|
|
1366
|
+
import { useKeepContext as useKeepContext2 } from "@keepkit/core/react";
|
|
1367
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1368
|
+
function KeepUndo({ children, label, ...props }) {
|
|
1369
|
+
const context = useKeepContext2();
|
|
1370
|
+
const message = useUiLabel("undoAvailable");
|
|
1371
|
+
const undoLabel = useUiLabel("undo");
|
|
1372
|
+
if (!context.undo.canUndo) return null;
|
|
1373
|
+
return /* @__PURE__ */ jsxs9("div", { ...props, role: "status", "aria-live": "polite", "data-state": "available", children: [
|
|
1374
|
+
children ?? message,
|
|
1375
|
+
/* @__PURE__ */ jsx15("button", { type: "button", onClick: () => void context.undoLastRemoval(), children: label ?? undoLabel })
|
|
1376
|
+
] });
|
|
1377
|
+
}
|
|
1378
|
+
|
|
942
1379
|
// src/status.tsx
|
|
943
|
-
import { useKeepContext } from "@keepkit/core/react";
|
|
944
|
-
import { isValidElement as isValidElement6, useEffect as
|
|
945
|
-
import { Fragment as Fragment7, jsx as
|
|
1380
|
+
import { useKeepContext as useKeepContext3 } from "@keepkit/core/react";
|
|
1381
|
+
import { isValidElement as isValidElement6, useEffect as useEffect5, useRef as useRef4, useState as useState8 } from "react";
|
|
1382
|
+
import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
946
1383
|
function KeepEmptyState({
|
|
947
1384
|
title,
|
|
948
1385
|
description,
|
|
@@ -954,9 +1391,9 @@ function KeepEmptyState({
|
|
|
954
1391
|
}) {
|
|
955
1392
|
const defaultTitle = useUiLabel("noItems").replace(/\.$/, "");
|
|
956
1393
|
const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
|
|
957
|
-
const body = contentChildren ?? /* @__PURE__ */
|
|
958
|
-
/* @__PURE__ */
|
|
959
|
-
description ? /* @__PURE__ */
|
|
1394
|
+
const body = contentChildren ?? /* @__PURE__ */ jsxs10(Fragment7, { children: [
|
|
1395
|
+
/* @__PURE__ */ jsx16("h2", { children: title ?? defaultTitle }),
|
|
1396
|
+
description ? /* @__PURE__ */ jsx16("p", { children: description }) : null,
|
|
960
1397
|
action
|
|
961
1398
|
] });
|
|
962
1399
|
return renderRoot(asChild, children, { ...rootProps, className, "data-state": "empty" }, body, "KeepEmptyState");
|
|
@@ -970,10 +1407,10 @@ function KeepStatus({
|
|
|
970
1407
|
className,
|
|
971
1408
|
...rootProps
|
|
972
1409
|
}) {
|
|
973
|
-
const context =
|
|
1410
|
+
const context = useKeepContext3();
|
|
974
1411
|
const contentChildren = asChild && isValidElement6(children) ? void 0 : children;
|
|
975
1412
|
const resolvedStatus = status ?? getDerivedStatus(context);
|
|
976
|
-
const defaultLabel = useUiLabel(
|
|
1413
|
+
const defaultLabel = useUiLabel(getStatusLabelKey2(resolvedStatus));
|
|
977
1414
|
const state = {
|
|
978
1415
|
status: resolvedStatus,
|
|
979
1416
|
error: context.error,
|
|
@@ -998,13 +1435,13 @@ function KeepStatus({
|
|
|
998
1435
|
);
|
|
999
1436
|
}
|
|
1000
1437
|
function KeepAnnouncements({ messages, ...props }) {
|
|
1001
|
-
const context =
|
|
1438
|
+
const context = useKeepContext3();
|
|
1002
1439
|
const savedMessage = useUiLabel("savedMessage", messages?.save);
|
|
1003
1440
|
const removedMessage = useUiLabel("removedMessage", messages?.remove);
|
|
1004
1441
|
const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
|
|
1005
|
-
const [message, setMessage] =
|
|
1006
|
-
const lastChangeRef =
|
|
1007
|
-
|
|
1442
|
+
const [message, setMessage] = useState8("");
|
|
1443
|
+
const lastChangeRef = useRef4(void 0);
|
|
1444
|
+
useEffect5(() => {
|
|
1008
1445
|
const change = context.lastChange;
|
|
1009
1446
|
if (!change || change === lastChangeRef.current) return;
|
|
1010
1447
|
lastChangeRef.current = change;
|
|
@@ -1012,7 +1449,7 @@ function KeepAnnouncements({ messages, ...props }) {
|
|
|
1012
1449
|
else if (change.action === "remove" || change.action === "removeBatch") setMessage(removedMessage);
|
|
1013
1450
|
else if (change.action === "updateNote") setMessage(noteSavedMessage);
|
|
1014
1451
|
}, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);
|
|
1015
|
-
return /* @__PURE__ */
|
|
1452
|
+
return /* @__PURE__ */ jsx16(
|
|
1016
1453
|
"div",
|
|
1017
1454
|
{
|
|
1018
1455
|
...props,
|
|
@@ -1033,7 +1470,7 @@ function getDerivedStatus(context) {
|
|
|
1033
1470
|
if (context.isHydrated && context.items.length === 0) return "empty";
|
|
1034
1471
|
return "idle";
|
|
1035
1472
|
}
|
|
1036
|
-
function
|
|
1473
|
+
function getStatusLabelKey2(status) {
|
|
1037
1474
|
if (status === "empty") return "noItems";
|
|
1038
1475
|
if (status === "loading") return "loadingItems";
|
|
1039
1476
|
if (status === "error") return "error";
|
|
@@ -1046,7 +1483,7 @@ function getStatusLabelKey(status) {
|
|
|
1046
1483
|
import {
|
|
1047
1484
|
KeepErrorBoundary as KeepErrorBoundary3,
|
|
1048
1485
|
KeepProvider,
|
|
1049
|
-
useKeepContext as
|
|
1486
|
+
useKeepContext as useKeepContext4,
|
|
1050
1487
|
useKeepItem as useKeepItem5,
|
|
1051
1488
|
useKeepList as useKeepList5,
|
|
1052
1489
|
useKeepShortcut
|
|
@@ -1061,7 +1498,7 @@ import {
|
|
|
1061
1498
|
LocalStorageSyncQueueAdapter,
|
|
1062
1499
|
SyncStorageAdapter
|
|
1063
1500
|
} from "@keepkit/core/storage";
|
|
1064
|
-
import { jsx as
|
|
1501
|
+
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1065
1502
|
function KeepKitProvider({
|
|
1066
1503
|
labels,
|
|
1067
1504
|
locale,
|
|
@@ -1069,16 +1506,16 @@ function KeepKitProvider({
|
|
|
1069
1506
|
children,
|
|
1070
1507
|
...providerProps
|
|
1071
1508
|
}) {
|
|
1072
|
-
return /* @__PURE__ */
|
|
1509
|
+
return /* @__PURE__ */ jsx17(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsxs11(CoreKeepProvider, { ...providerProps, children: [
|
|
1073
1510
|
children,
|
|
1074
|
-
/* @__PURE__ */
|
|
1511
|
+
/* @__PURE__ */ jsx17(KeepAnnouncements, {})
|
|
1075
1512
|
] }) });
|
|
1076
1513
|
}
|
|
1077
1514
|
function createKeepKit(options = {}) {
|
|
1078
1515
|
const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;
|
|
1079
1516
|
const coreKit = createCoreKeepKit(coreOptions);
|
|
1080
1517
|
return {
|
|
1081
|
-
Provider: (props) => /* @__PURE__ */
|
|
1518
|
+
Provider: (props) => /* @__PURE__ */ jsx17(
|
|
1082
1519
|
KeepKitProvider,
|
|
1083
1520
|
{
|
|
1084
1521
|
...coreOptions,
|
|
@@ -1088,8 +1525,9 @@ function createKeepKit(options = {}) {
|
|
|
1088
1525
|
...props
|
|
1089
1526
|
}
|
|
1090
1527
|
),
|
|
1091
|
-
Button: (props) => /* @__PURE__ */
|
|
1092
|
-
|
|
1528
|
+
Button: (props) => /* @__PURE__ */ jsx17(KeepButton, { ...props }),
|
|
1529
|
+
Backup: (props) => /* @__PURE__ */ jsx17(KeepBackup, { ...props }),
|
|
1530
|
+
Collection: (props) => /* @__PURE__ */ jsx17(
|
|
1093
1531
|
KeepCollection,
|
|
1094
1532
|
{
|
|
1095
1533
|
...props,
|
|
@@ -1112,6 +1550,7 @@ export {
|
|
|
1112
1550
|
IndexedDBSyncQueueAdapter,
|
|
1113
1551
|
KeepAnnouncements,
|
|
1114
1552
|
KeepAnnouncer,
|
|
1553
|
+
KeepBackup,
|
|
1115
1554
|
KeepBulkActions,
|
|
1116
1555
|
KeepButton,
|
|
1117
1556
|
KeepCollection,
|
|
@@ -1120,6 +1559,7 @@ export {
|
|
|
1120
1559
|
KeepItemCard,
|
|
1121
1560
|
KeepItemCheckbox,
|
|
1122
1561
|
KeepKitProvider,
|
|
1562
|
+
KeepLayout,
|
|
1123
1563
|
KeepList,
|
|
1124
1564
|
KeepNoteEditor,
|
|
1125
1565
|
KeepPagination,
|
|
@@ -1130,18 +1570,22 @@ export {
|
|
|
1130
1570
|
KeepTagEditor,
|
|
1131
1571
|
KeepTagFilter,
|
|
1132
1572
|
KeepUiProvider,
|
|
1573
|
+
KeepUndo,
|
|
1133
1574
|
LocalStorageAdapter,
|
|
1134
1575
|
LocalStorageSyncQueueAdapter,
|
|
1135
1576
|
SyncStorageAdapter,
|
|
1136
1577
|
createBrowserStorageAdapter,
|
|
1137
1578
|
createKeepKit,
|
|
1579
|
+
createNextPagesRouterAdapter,
|
|
1138
1580
|
createStorageAdapter,
|
|
1581
|
+
getKeepLocaleLabels,
|
|
1139
1582
|
isAllSelected,
|
|
1140
1583
|
toggleSelectAll,
|
|
1141
|
-
|
|
1584
|
+
useKeepContext4 as useKeepContext,
|
|
1142
1585
|
useKeepItem5 as useKeepItem,
|
|
1143
1586
|
useKeepList5 as useKeepList,
|
|
1144
1587
|
useKeepShortcut,
|
|
1145
|
-
useKeepUiLabels
|
|
1588
|
+
useKeepUiLabels,
|
|
1589
|
+
useKeepUrlSync
|
|
1146
1590
|
};
|
|
1147
1591
|
//# sourceMappingURL=index.js.map
|