@keepkit/ui 0.8.0 → 0.9.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 CHANGED
@@ -10,6 +10,28 @@ Reactアプリケーション向けの標準利用パッケージです。`@keep
10
10
  pnpm add @keepkit/ui
11
11
  ```
12
12
 
13
+ ## Minimal Starter Recipe
14
+
15
+ ```tsx
16
+ import { createBrowserStorageAdapter, createKeepKit } from "@keepkit/ui";
17
+
18
+ type Meta = { title: string; url: string };
19
+ const keep = createKeepKit<Meta>({
20
+ storage: createBrowserStorageAdapter({ key: "demo:keeps" }),
21
+ });
22
+
23
+ export function SavedArticle({ article }: { article: Meta & { id: string } }) {
24
+ return (
25
+ <keep.Provider fallback={<p>Saved items are temporarily unavailable.</p>}>
26
+ <keep.Button item={{ id: article.id, targetType: "article", meta: article }} />
27
+ <keep.Collection query={{ targetType: "article" }} />
28
+ </keep.Provider>
29
+ );
30
+ }
31
+ ```
32
+
33
+ Every primitive exposes `data-state`; pending operations expose `data-loading="true"`, and disabled controls expose `data-disabled="true"`. Use these attributes from host CSS or Tailwind data variants. `KeepCollection` and `KeepList` accept `fallback`, `onBoundaryError`, and `boundaryResetKey` for local render-error isolation.
34
+
13
35
  ```tsx
14
36
  import { createBrowserStorageAdapter, createKeepKit } from "@keepkit/ui";
15
37
 
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as react from 'react';
2
2
  import { ReactNode, HTMLAttributes, ImgHTMLAttributes, ComponentType, InputHTMLAttributes, FormHTMLAttributes, SelectHTMLAttributes } from 'react';
3
3
  import { KeepListQuery, KeepItem, KeepItemInput } from '@keepkit/core/core';
4
4
  export { KeepItem, KeepItemInput, KeepListQuery, KeepSyncStatus } from '@keepkit/core/core';
5
- import { KeepButtonProps as KeepButtonProps$1, UseKeepListResult, CreateKeepKitOptions as CreateKeepKitOptions$1, KeepProviderProps, useKeepContext, useKeepItem, useKeepList, KeepShortcutOptions } from '@keepkit/core/react';
6
- export { KeepButtonState, KeepContextValue, KeepProvider, KeepProviderProps, KeepShortcutOptions, useKeepContext, useKeepItem, useKeepList, useKeepShortcut } from '@keepkit/core/react';
5
+ import { KeepButtonProps as KeepButtonProps$1, UseKeepListResult, KeepErrorBoundaryProps, CreateKeepKitOptions as CreateKeepKitOptions$1, KeepProviderProps, useKeepContext, useKeepItem, useKeepList, KeepShortcutOptions } from '@keepkit/core/react';
6
+ export { KeepButtonState, KeepContextValue, KeepErrorBoundary, KeepErrorBoundaryProps, KeepProvider, KeepProviderProps, KeepShortcutOptions, useKeepContext, useKeepItem, useKeepList, useKeepShortcut } from '@keepkit/core/react';
7
7
  export { FallbackStorageAdapter, IndexedDBAdapter, IndexedDBSyncQueueAdapter, LocalStorageAdapter, LocalStorageSyncQueueAdapter, SyncStorageAdapter, createBrowserStorageAdapter, createStorageAdapter } from '@keepkit/core/storage';
8
8
 
9
9
  type RenderProp<TState> = (state: TState) => ReactNode;
@@ -95,9 +95,12 @@ type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLEl
95
95
  error?: ReactNode | RenderProp<KeepListState<TMeta>>;
96
96
  itemCardProps?: Omit<KeepItemCardProps<TMeta>, "item" | "children" | "render">;
97
97
  asChild?: boolean;
98
+ fallback?: KeepErrorBoundaryProps["fallback"];
99
+ onBoundaryError?: KeepErrorBoundaryProps["onError"];
100
+ boundaryResetKey?: unknown;
98
101
  };
99
102
  /** A list primitive with built-in loading, empty, error, and removal states. */
100
- declare function KeepList<TMeta = Record<string, unknown>>({ query, children, renderItem, loading, empty, error: errorContent, itemCardProps, asChild, className, ...rootProps }: KeepListProps<TMeta>): react.ReactElement<unknown, string | react.JSXElementConstructor<any>>;
103
+ declare function KeepList<TMeta = Record<string, unknown>>(props: KeepListProps<TMeta>): react.JSX.Element;
101
104
 
102
105
  type KeepCollectionFeature = "search" | "sort" | "pagination" | "tagFilter" | "bulkActions";
103
106
  type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
@@ -109,9 +112,12 @@ type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<
109
112
  loading?: ReactNode | RenderProp<KeepListState<TMeta>>;
110
113
  empty?: ReactNode | RenderProp<KeepListState<TMeta>>;
111
114
  error?: ReactNode | RenderProp<KeepListState<TMeta>>;
115
+ fallback?: KeepErrorBoundaryProps["fallback"];
116
+ onBoundaryError?: KeepErrorBoundaryProps["onError"];
117
+ boundaryResetKey?: unknown;
112
118
  };
113
119
  /** A batteries-included collection with query controls and accessible status feedback. */
114
- declare function KeepCollection<TMeta = Record<string, unknown>>({ query, pageSize, features, renderItem, itemCardProps, loading, empty, error, className, ...rootProps }: KeepCollectionProps<TMeta>): react.JSX.Element;
120
+ declare function KeepCollection<TMeta = Record<string, unknown>>(props: KeepCollectionProps<TMeta>): react.JSX.Element;
115
121
 
116
122
  type KeepItemCheckboxProps<TMeta = Record<string, unknown>> = Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "checked" | "defaultChecked" | "onChange"> & {
117
123
  item: KeepItem<TMeta>;
package/dist/index.js CHANGED
@@ -28,6 +28,8 @@ function KeepItemCheckbox({
28
28
  ...props,
29
29
  type: "checkbox",
30
30
  checked,
31
+ "data-state": checked ? "checked" : "unchecked",
32
+ "data-disabled": props.disabled ? "true" : void 0,
31
33
  "aria-label": accessibleLabel,
32
34
  onChange: (event) => onCheckedChange?.(event.currentTarget.checked)
33
35
  }
@@ -238,7 +240,16 @@ function KeepBulkActions({
238
240
  }
239
241
  )
240
242
  ] });
241
- return /* @__PURE__ */ jsx4("section", { ...props, "aria-busy": list.isMutating || props["aria-busy"], children: body });
243
+ return /* @__PURE__ */ jsx4(
244
+ "section",
245
+ {
246
+ ...props,
247
+ "aria-busy": list.isMutating || props["aria-busy"],
248
+ "data-state": selectedIds.length > 0 ? "selected" : "idle",
249
+ "data-loading": list.isLoading || list.isMutating ? "true" : void 0,
250
+ children: body
251
+ }
252
+ );
242
253
  }
243
254
 
244
255
  // src/KeepButton.tsx
@@ -274,11 +285,14 @@ function KeepButton({ labels, ...props }) {
274
285
  }
275
286
 
276
287
  // src/KeepCollection.tsx
277
- import { useKeepList as useKeepList4 } from "@keepkit/core/react";
288
+ import { KeepErrorBoundary as KeepErrorBoundary2, useKeepList as useKeepList4 } from "@keepkit/core/react";
278
289
  import { useMemo as useMemo3, useState as useState4 } from "react";
279
290
 
280
291
  // src/KeepList.tsx
281
- import { useKeepList as useKeepList2 } from "@keepkit/core/react";
292
+ import {
293
+ KeepErrorBoundary,
294
+ useKeepList as useKeepList2
295
+ } from "@keepkit/core/react";
282
296
  import { isValidElement as isValidElement3 } from "react";
283
297
 
284
298
  // src/KeepItemCard.tsx
@@ -341,7 +355,13 @@ function KeepItemCard({
341
355
  return renderRoot(
342
356
  asChild,
343
357
  isValidElement2(children) ? children : void 0,
344
- { ...rootProps, className, "aria-busy": itemState.isMutating || rootProps["aria-busy"] },
358
+ {
359
+ ...rootProps,
360
+ className,
361
+ "aria-busy": itemState.isMutating || rootProps["aria-busy"],
362
+ "data-state": itemState.isSaved ? "saved" : "unsaved",
363
+ "data-loading": itemState.isMutating ? "true" : void 0
364
+ },
345
365
  body,
346
366
  "KeepItemCard"
347
367
  );
@@ -349,7 +369,13 @@ function KeepItemCard({
349
369
 
350
370
  // src/KeepList.tsx
351
371
  import { jsx as jsx7 } from "react/jsx-runtime";
352
- function KeepList({
372
+ function KeepList(props) {
373
+ const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
374
+ const content = /* @__PURE__ */ jsx7(KeepListContent, { ...listProps });
375
+ if (fallback === void 0 && onBoundaryError === void 0) return content;
376
+ return /* @__PURE__ */ jsx7(KeepErrorBoundary, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
377
+ }
378
+ function KeepListContent({
353
379
  query,
354
380
  children,
355
381
  renderItem,
@@ -376,11 +402,23 @@ function KeepList({
376
402
  return renderRoot(
377
403
  asChild,
378
404
  asChild && isValidElement3(children) ? children : void 0,
379
- { ...rootProps, className, "aria-busy": state.isLoading || rootProps["aria-busy"] },
405
+ {
406
+ ...rootProps,
407
+ className,
408
+ "aria-busy": state.isLoading || rootProps["aria-busy"],
409
+ "data-state": getListState(state),
410
+ "data-loading": state.isLoading ? "true" : void 0
411
+ },
380
412
  body,
381
413
  "KeepList"
382
414
  );
383
415
  }
416
+ function getListState(state) {
417
+ if (state.error && state.items.length === 0) return "error";
418
+ if (state.isLoading && !state.isHydrated) return "loading";
419
+ if (state.isHydrated && state.items.length === 0) return "empty";
420
+ return "ready";
421
+ }
384
422
  function getListBody(state, options) {
385
423
  if (state.error && state.items.length === 0) return resolveContent(options.error, state);
386
424
  if (state.isLoading && !state.isHydrated) return resolveContent(options.loading, state);
@@ -447,7 +485,12 @@ function KeepTagFilter({
447
485
  return renderRoot(
448
486
  asChild,
449
487
  isValidElement4(children) ? children : void 0,
450
- { ...rootProps, className },
488
+ {
489
+ ...rootProps,
490
+ className,
491
+ "data-state": resolvedValue === void 0 ? "all" : "filtered",
492
+ "data-loading": list.isLoading ? "true" : void 0
493
+ },
451
494
  body,
452
495
  "KeepTagFilter"
453
496
  );
@@ -483,6 +526,8 @@ function KeepSearchInput({
483
526
  ...props,
484
527
  type: "search",
485
528
  value,
529
+ "data-state": value ? "active" : "idle",
530
+ "data-disabled": props.disabled ? "true" : void 0,
486
531
  "aria-label": ariaLabel ?? label,
487
532
  placeholder: placeholder ?? label,
488
533
  onChange: (event) => {
@@ -518,6 +563,8 @@ function KeepSortSelect({
518
563
  {
519
564
  ...props,
520
565
  value,
566
+ "data-state": "selected",
567
+ "data-disabled": props.disabled ? "true" : void 0,
521
568
  "aria-label": ariaLabel ?? label,
522
569
  onChange: (event) => {
523
570
  const nextValue = event.currentTarget.value;
@@ -548,7 +595,11 @@ function KeepPagination({
548
595
  const next = Math.min(Math.max(1, nextPage), pageCount);
549
596
  onPageChange?.(next, (next - 1) * pageSize);
550
597
  };
551
- const navProps = { ...props, "aria-label": props["aria-label"] ?? paginationLabel };
598
+ const navProps = {
599
+ ...props,
600
+ "aria-label": props["aria-label"] ?? paginationLabel,
601
+ "data-state": pageCount > 1 ? "active" : "idle"
602
+ };
552
603
  if (render) return /* @__PURE__ */ jsx9("nav", { ...navProps, children: render({ page: currentPage, pageCount, goToPage }) });
553
604
  const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));
554
605
  return /* @__PURE__ */ jsxs4("nav", { ...navProps, children: [
@@ -576,7 +627,13 @@ function getVisiblePages(currentPage, pageCount, maxPageButtons) {
576
627
 
577
628
  // src/KeepCollection.tsx
578
629
  import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
579
- function KeepCollection({
630
+ function KeepCollection(props) {
631
+ const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
632
+ const content = /* @__PURE__ */ jsx10(KeepCollectionContent, { ...collectionProps });
633
+ if (fallback === void 0 && onBoundaryError === void 0) return content;
634
+ return /* @__PURE__ */ jsx10(KeepErrorBoundary2, { fallback, onError: onBoundaryError, resetKey: boundaryResetKey, children: content });
635
+ }
636
+ function KeepCollectionContent({
580
637
  query = {},
581
638
  pageSize = 20,
582
639
  features,
@@ -618,6 +675,8 @@ function KeepCollection({
618
675
  ...rootProps,
619
676
  className,
620
677
  "aria-busy": list.isLoading || list.isMutating || rootProps["aria-busy"],
678
+ "data-state": getCollectionState(list),
679
+ "data-loading": list.isLoading || list.isMutating ? "true" : void 0,
621
680
  children: [
622
681
  /* @__PURE__ */ jsxs5("div", { children: [
623
682
  enabled.search ? /* @__PURE__ */ jsx10(
@@ -677,6 +736,12 @@ function KeepCollection({
677
736
  }
678
737
  );
679
738
  }
739
+ function getCollectionState(list) {
740
+ if (list.error && list.items.length === 0) return "error";
741
+ if (list.isLoading && !list.isHydrated) return "loading";
742
+ if (list.isHydrated && list.items.length === 0) return "empty";
743
+ return "ready";
744
+ }
680
745
 
681
746
  // src/KeepNoteEditor.tsx
682
747
  import { useKeepItem as useKeepItem3 } from "@keepkit/core/react";
@@ -770,6 +835,9 @@ function KeepNoteEditor({
770
835
  className,
771
836
  onSubmit: handleSubmit,
772
837
  "aria-busy": isMutating || formProps["aria-busy"],
838
+ "data-state": isDirty ? "dirty" : "clean",
839
+ "data-loading": isMutating ? "true" : void 0,
840
+ "data-disabled": isMutating ? "true" : void 0,
773
841
  children: body
774
842
  }
775
843
  );
@@ -777,7 +845,15 @@ function KeepNoteEditor({
777
845
  return renderRoot(
778
846
  true,
779
847
  isValidElement5(children) ? children : void 0,
780
- { ...formProps, className, onSubmit: handleSubmit, "aria-busy": isMutating || formProps["aria-busy"] },
848
+ {
849
+ ...formProps,
850
+ className,
851
+ onSubmit: handleSubmit,
852
+ "aria-busy": isMutating || formProps["aria-busy"],
853
+ "data-state": isDirty ? "dirty" : "clean",
854
+ "data-loading": isMutating ? "true" : void 0,
855
+ "data-disabled": isMutating ? "true" : void 0
856
+ },
781
857
  body,
782
858
  "KeepNoteEditor"
783
859
  );
@@ -855,6 +931,9 @@ function KeepTagEditor({
855
931
  void save().catch(() => void 0);
856
932
  },
857
933
  "aria-busy": itemState.isMutating || props["aria-busy"],
934
+ "data-state": itemState.isMutating ? "saving" : "idle",
935
+ "data-loading": itemState.isMutating ? "true" : void 0,
936
+ "data-disabled": itemState.isMutating ? "true" : void 0,
858
937
  children: body
859
938
  }
860
939
  );
@@ -880,7 +959,7 @@ function KeepEmptyState({
880
959
  description ? /* @__PURE__ */ jsx13("p", { children: description }) : null,
881
960
  action
882
961
  ] });
883
- return renderRoot(asChild, children, { ...rootProps, className }, body, "KeepEmptyState");
962
+ return renderRoot(asChild, children, { ...rootProps, className, "data-state": "empty" }, body, "KeepEmptyState");
884
963
  }
885
964
  function KeepStatus({
886
965
  status,
@@ -906,7 +985,14 @@ function KeepStatus({
906
985
  return renderRoot(
907
986
  asChild,
908
987
  isValidElement6(children) ? children : void 0,
909
- { ...rootProps, className, role, "aria-live": rootProps["aria-live"] ?? "polite" },
988
+ {
989
+ ...rootProps,
990
+ className,
991
+ role,
992
+ "aria-live": rootProps["aria-live"] ?? "polite",
993
+ "data-state": resolvedStatus,
994
+ "data-loading": resolvedStatus === "loading" || resolvedStatus === "saving" || resolvedStatus === "syncing" ? "true" : void 0
995
+ },
910
996
  body,
911
997
  "KeepStatus"
912
998
  );
@@ -926,7 +1012,17 @@ function KeepAnnouncements({ messages, ...props }) {
926
1012
  else if (change.action === "remove" || change.action === "removeBatch") setMessage(removedMessage);
927
1013
  else if (change.action === "updateNote") setMessage(noteSavedMessage);
928
1014
  }, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);
929
- return /* @__PURE__ */ jsx13("div", { ...props, role: props.role ?? "status", "aria-live": props["aria-live"] ?? "polite", "aria-atomic": "true", children: message });
1015
+ return /* @__PURE__ */ jsx13(
1016
+ "div",
1017
+ {
1018
+ ...props,
1019
+ role: props.role ?? "status",
1020
+ "aria-live": props["aria-live"] ?? "polite",
1021
+ "aria-atomic": "true",
1022
+ "data-state": "announcing",
1023
+ children: message
1024
+ }
1025
+ );
930
1026
  }
931
1027
  var KeepAnnouncer = KeepAnnouncements;
932
1028
  function getDerivedStatus(context) {
@@ -947,7 +1043,14 @@ function getStatusLabelKey(status) {
947
1043
  }
948
1044
 
949
1045
  // src/index.tsx
950
- import { KeepProvider, useKeepContext as useKeepContext2, useKeepItem as useKeepItem5, useKeepList as useKeepList5, useKeepShortcut } from "@keepkit/core/react";
1046
+ import {
1047
+ KeepErrorBoundary as KeepErrorBoundary3,
1048
+ KeepProvider,
1049
+ useKeepContext as useKeepContext2,
1050
+ useKeepItem as useKeepItem5,
1051
+ useKeepList as useKeepList5,
1052
+ useKeepShortcut
1053
+ } from "@keepkit/core/react";
951
1054
  import {
952
1055
  createBrowserStorageAdapter,
953
1056
  createStorageAdapter,
@@ -1013,6 +1116,7 @@ export {
1013
1116
  KeepButton,
1014
1117
  KeepCollection,
1015
1118
  KeepEmptyState,
1119
+ KeepErrorBoundary3 as KeepErrorBoundary,
1016
1120
  KeepItemCard,
1017
1121
  KeepItemCheckbox,
1018
1122
  KeepKitProvider,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/KeepBulkActions.tsx","../src/KeepItemCheckbox.tsx","../src/shared.tsx","../src/ui-context.tsx","../src/KeepButton.tsx","../src/KeepCollection.tsx","../src/KeepList.tsx","../src/KeepItemCard.tsx","../src/KeepTagFilter.tsx","../src/query-controls.tsx","../src/KeepNoteEditor.tsx","../src/KeepTagEditor.tsx","../src/status.tsx"],"sourcesContent":["\"use client\";\n\nimport type { KeepItem, KeepItemInput, KeepListQuery } from \"@keepkit/core/core\";\nimport {\n type CreateKeepKitOptions as CoreCreateKeepKitOptions,\n KeepProvider as CoreKeepProvider,\n createKeepKit as createCoreKeepKit,\n type KeepProviderProps,\n type KeepShortcutOptions,\n type useKeepContext,\n type useKeepItem,\n type useKeepList,\n} from \"@keepkit/core/react\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { KeepBulkActions, type KeepBulkActionsProps, type KeepBulkActionsState } from \"./KeepBulkActions\";\nimport { KeepButton, type KeepButtonLabels, type KeepButtonProps } from \"./KeepButton\";\nimport { KeepCollection, type KeepCollectionFeature, type KeepCollectionProps } from \"./KeepCollection\";\nimport { type KeepImageProps, KeepItemCard, type KeepItemCardProps, type KeepItemCardState } from \"./KeepItemCard\";\nimport { KeepItemCheckbox, type KeepItemCheckboxProps } from \"./KeepItemCheckbox\";\nimport { KeepList, type KeepListProps, type KeepListState } from \"./KeepList\";\nimport { KeepNoteEditor, type KeepNoteEditorProps, type KeepNoteEditorState } from \"./KeepNoteEditor\";\nimport { KeepTagEditor, type KeepTagEditorProps, type KeepTagEditorState } from \"./KeepTagEditor\";\nimport { KeepTagFilter, type KeepTagFilterProps, type KeepTagFilterState } from \"./KeepTagFilter\";\nimport {\n KeepPagination,\n type KeepPaginationProps,\n type KeepPaginationState,\n KeepSearchInput,\n type KeepSearchInputProps,\n KeepSortSelect,\n type KeepSortSelectProps,\n type KeepSortValue,\n} from \"./query-controls\";\nimport {\n KeepAnnouncements,\n type KeepAnnouncementsProps,\n KeepAnnouncer,\n KeepEmptyState,\n type KeepEmptyStateProps,\n KeepStatus,\n type KeepStatusLabels,\n type KeepStatusProps,\n type KeepStatusState,\n type KeepStatusValue,\n} from \"./status\";\nimport {\n type KeepUiLabelContext,\n type KeepUiLabelKey,\n type KeepUiLabels,\n KeepUiProvider,\n type KeepUiProviderProps,\n useKeepUiLabels,\n} from \"./ui-context\";\n\nexport type KeepKitProviderProps<TMeta = Record<string, unknown>> = Omit<KeepProviderProps<TMeta>, \"children\"> &\n Omit<KeepUiProviderProps, \"children\"> & { children?: ReactNode };\n\n/** Combines the core store, UI labels, and the global live announcer. */\nexport function KeepKitProvider<TMeta = Record<string, unknown>>({\n labels,\n locale,\n labelResolver,\n children,\n ...providerProps\n}: KeepKitProviderProps<TMeta>) {\n return (\n <KeepUiProvider labels={labels} locale={locale} labelResolver={labelResolver}>\n <CoreKeepProvider<TMeta> {...providerProps}>\n {children}\n <KeepAnnouncements />\n </CoreKeepProvider>\n </KeepUiProvider>\n );\n}\n\nexport type { KeepItem, KeepItemInput, KeepListQuery, KeepSyncStatus } from \"@keepkit/core/core\";\nexport type { KeepButtonState, KeepContextValue, KeepProviderProps, KeepShortcutOptions } from \"@keepkit/core/react\";\nexport { KeepProvider, useKeepContext, useKeepItem, useKeepList, useKeepShortcut } from \"@keepkit/core/react\";\nexport {\n createBrowserStorageAdapter,\n createStorageAdapter,\n FallbackStorageAdapter,\n IndexedDBAdapter,\n IndexedDBSyncQueueAdapter,\n LocalStorageAdapter,\n LocalStorageSyncQueueAdapter,\n SyncStorageAdapter,\n} from \"@keepkit/core/storage\";\nexport { isAllSelected, toggleSelectAll } from \"./KeepBulkActions\";\nexport type { RenderProp } from \"./shared\";\nexport type {\n KeepAnnouncementsProps,\n KeepBulkActionsProps,\n KeepBulkActionsState,\n KeepButtonLabels,\n KeepButtonProps,\n KeepCollectionFeature,\n KeepCollectionProps,\n KeepEmptyStateProps,\n KeepImageProps,\n KeepItemCardProps,\n KeepItemCardState,\n KeepItemCheckboxProps,\n KeepListProps,\n KeepListState,\n KeepNoteEditorProps,\n KeepNoteEditorState,\n KeepPaginationProps,\n KeepPaginationState,\n KeepSearchInputProps,\n KeepSortSelectProps,\n KeepSortValue,\n KeepStatusLabels,\n KeepStatusProps,\n KeepStatusState,\n KeepStatusValue,\n KeepTagEditorProps,\n KeepTagEditorState,\n KeepTagFilterProps,\n KeepTagFilterState,\n KeepUiLabelContext,\n KeepUiLabelKey,\n KeepUiLabels,\n KeepUiProviderProps,\n};\nexport {\n KeepAnnouncements,\n KeepAnnouncer,\n KeepBulkActions,\n KeepButton,\n KeepCollection,\n KeepEmptyState,\n KeepItemCard,\n KeepItemCheckbox,\n KeepList,\n KeepNoteEditor,\n KeepPagination,\n KeepSearchInput,\n KeepSortSelect,\n KeepStatus,\n KeepTagEditor,\n KeepTagFilter,\n KeepUiProvider,\n useKeepUiLabels,\n};\n\nexport type CreateKeepKitOptions<TMeta = Record<string, unknown>> = CoreCreateKeepKitOptions<TMeta> &\n Omit<KeepUiProviderProps, \"children\"> & {\n getTitle?: (item: KeepItem<TMeta>) => ReactNode;\n getImageProps?: (item: KeepItem<TMeta>, title: ReactNode) => KeepImageProps | undefined;\n };\n\nexport type KeepKit<TMeta = Record<string, unknown>> = {\n Provider: ComponentType<KeepKitProviderProps<TMeta>>;\n Button: ComponentType<KeepButtonProps<TMeta>>;\n Collection: ComponentType<KeepCollectionProps<TMeta>>;\n useContext: () => ReturnType<typeof useKeepContext<TMeta>>;\n useItem: (item?: KeepItemInput<TMeta>) => ReturnType<typeof useKeepItem<TMeta>>;\n useList: (query?: KeepListQuery<TMeta>) => ReturnType<typeof useKeepList<TMeta>>;\n useShortcut: (options: KeepShortcutOptions<TMeta>) => void;\n};\n\n/** Create one typed application API for the core and standard UI layer. */\nexport function createKeepKit<TMeta = Record<string, unknown>>(\n options: CreateKeepKitOptions<TMeta> = {},\n): KeepKit<TMeta> {\n const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;\n const coreKit = createCoreKeepKit<TMeta>(coreOptions);\n return {\n Provider: (props) => (\n <KeepKitProvider<TMeta>\n {...coreOptions}\n labels={labels}\n locale={locale}\n labelResolver={labelResolver}\n {...props}\n />\n ),\n Button: (props) => <KeepButton<TMeta> {...props} />,\n Collection: (props) => (\n <KeepCollection<TMeta>\n {...props}\n itemCardProps={{\n ...(getTitle ? { getTitle } : {}),\n ...(getImageProps ? { getImageProps } : {}),\n ...props.itemCardProps,\n }}\n />\n ),\n useContext: () => coreKit.useContext(),\n useItem: (item) => coreKit.useItem(item),\n useList: (query) => coreKit.useList(query),\n useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions),\n };\n}\n","\"use client\";\n\nimport type { KeepItem, KeepListQuery } from \"@keepkit/core/core\";\nimport { useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, type ReactNode, useState } from \"react\";\nimport { KeepItemCheckbox } from \"./KeepItemCheckbox\";\nimport { getMetaTitle, normalizeUiTags, type RenderProp } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepBulkActionsState<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n selectedIds: string[];\n selectedCount: number;\n isAllSelected: boolean;\n allSelected: boolean;\n tagsInput: string;\n setTagsInput: (value: string) => void;\n toggle: (id: string) => void;\n toggleSelectAll: () => void;\n toggleAll: () => void;\n remove: () => Promise<void>;\n updateTags: () => Promise<void>;\n isMutating: boolean;\n};\n\n/** Returns whether every visible item is selected. Empty lists are never all selected. */\nexport function isAllSelected<TMeta>(\n items: readonly Pick<KeepItem<TMeta>, \"id\">[],\n selectedIds: readonly string[],\n): boolean {\n if (items.length === 0) return false;\n const selected = new Set(selectedIds);\n return items.every((item) => selected.has(item.id));\n}\n\n/** Toggles only the visible items, preserving selections outside the current query or page. */\nexport function toggleSelectAll<TMeta>(\n items: readonly Pick<KeepItem<TMeta>, \"id\">[],\n selectedIds: readonly string[],\n): string[] {\n const visibleIds = new Set(items.map((item) => item.id));\n if (isAllSelected(items, selectedIds)) return selectedIds.filter((id) => !visibleIds.has(id));\n const nextIds = [...selectedIds];\n for (const item of items) {\n if (!nextIds.includes(item.id)) nextIds.push(item.id);\n }\n return nextIds;\n}\n\nexport type KeepBulkActionsProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n query?: KeepListQuery<TMeta>;\n selectedIds?: string[];\n defaultSelectedIds?: string[];\n onSelectedIdsChange?: (ids: string[]) => void;\n renderItem?: (item: KeepItem<TMeta>, selected: boolean) => ReactNode;\n onCompleted?: (action: \"remove\" | \"tags\", ids: string[]) => void;\n render?: RenderProp<KeepBulkActionsState<TMeta>>;\n children?: ReactNode | RenderProp<KeepBulkActionsState<TMeta>>;\n};\n\n/** Selects visible items and performs one storage operation for the whole selection. */\nexport function KeepBulkActions<TMeta = Record<string, unknown>>({\n query,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n onSelectedIdsChange,\n renderItem,\n onCompleted,\n render,\n children,\n ...props\n}: KeepBulkActionsProps<TMeta>) {\n const selectItemsLabel = useUiLabel(\"selectItems\");\n const selectedCountLabel = useUiLabel(\"selectedCount\");\n const deleteSelectedLabel = useUiLabel(\"deleteSelected\");\n const tagsLabel = useUiLabel(\"tagsToApply\");\n const applyTagsLabel = useUiLabel(\"applyTags\");\n const list = useKeepList<TMeta>(query);\n const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);\n const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;\n const selected = new Set(selectedIds);\n const [tagsInput, setTagsInput] = useState(\"\");\n const setSelectedIds = (ids: string[]) => {\n if (controlledSelectedIds === undefined) setUncontrolledSelectedIds(ids);\n onSelectedIdsChange?.(ids);\n };\n const toggle = (id: string) =>\n setSelectedIds(selected.has(id) ? selectedIds.filter((current) => current !== id) : [...selectedIds, id]);\n const allSelected = isAllSelected(list.items, selectedIds);\n const toggleAll = () => setSelectedIds(toggleSelectAll(list.items, selectedIds));\n const remove = async () => {\n const ids = [...selectedIds];\n await list.removeBatch(ids);\n onCompleted?.(\"remove\", ids);\n setSelectedIds([]);\n };\n const updateTags = async () => {\n const ids = [...selectedIds];\n await list.updateTagsBatch(ids, normalizeUiTags(tagsInput.split(\",\")));\n onCompleted?.(\"tags\", ids);\n setSelectedIds([]);\n };\n const state: KeepBulkActionsState<TMeta> = {\n items: list.items,\n selectedIds,\n selectedCount: selectedIds.length,\n isAllSelected: allSelected,\n allSelected,\n tagsInput,\n setTagsInput,\n toggle,\n toggleSelectAll: toggleAll,\n toggleAll,\n remove,\n updateTags,\n isMutating: list.isMutating,\n };\n const body = render\n ? render(state)\n : typeof children === \"function\"\n ? children(state)\n : (children ?? (\n <>\n <fieldset>\n <legend>{selectItemsLabel}</legend>\n <label>\n <input type=\"checkbox\" checked={allSelected} onChange={toggleAll} aria-label={selectItemsLabel} />\n {selectedIds.length} {selectedCountLabel}\n </label>\n {list.items.map((item) => (\n <span key={item.id}>\n <KeepItemCheckbox\n item={item}\n checked={selected.has(item.id)}\n onCheckedChange={() => toggle(item.id)}\n />\n {renderItem ? renderItem(item, selected.has(item.id)) : (getMetaTitle(item.meta) ?? item.id)}\n </span>\n ))}\n </fieldset>\n <button type=\"button\" onClick={() => void remove()} disabled={selectedIds.length === 0 || list.isMutating}>\n {deleteSelectedLabel}\n </button>\n <label>\n {tagsLabel}\n <input value={tagsInput} onChange={(event) => setTagsInput(event.currentTarget.value)} />\n </label>\n <button\n type=\"button\"\n onClick={() => void updateTags()}\n disabled={selectedIds.length === 0 || list.isMutating}\n >\n {applyTagsLabel}\n </button>\n </>\n ));\n return (\n <section {...props} aria-busy={list.isMutating || props[\"aria-busy\"]}>\n {body}\n </section>\n );\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\n\nexport type KeepItemCheckboxProps<TMeta = Record<string, unknown>> = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"checked\" | \"defaultChecked\" | \"onChange\"\n> & {\n item: KeepItem<TMeta>;\n checked?: boolean;\n label?: ReactNode;\n onCheckedChange?: (checked: boolean) => void;\n};\n\n/** A reusable accessible selection checkbox for a saved item. */\nexport function KeepItemCheckbox<TMeta = Record<string, unknown>>({\n item,\n checked = false,\n label,\n onCheckedChange,\n \"aria-label\": ariaLabel,\n ...props\n}: KeepItemCheckboxProps<TMeta>) {\n const itemLabel = getItemLabel(item) ?? item.id;\n const accessibleLabel = ariaLabel ?? (typeof label === \"string\" ? label : itemLabel);\n return (\n <input\n {...props}\n type=\"checkbox\"\n checked={checked}\n aria-label={accessibleLabel}\n onChange={(event) => onCheckedChange?.(event.currentTarget.checked)}\n />\n );\n}\n\nfunction getItemLabel<TMeta>(item: KeepItem<TMeta>): string | undefined {\n if (typeof item.meta !== \"object\" || item.meta === null || !(\"title\" in item.meta)) return undefined;\n const title = (item.meta as { title?: unknown }).title;\n return typeof title === \"string\" && title.trim() ? title.trim() : undefined;\n}\n","\"use client\";\n\nimport type { KeepItem, KeepItemInput, KeepListQuery } from \"@keepkit/core/core\";\nimport {\n cloneElement,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n isValidElement,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nexport type RenderProp<TState> = (state: TState) => ReactNode;\n\nexport type KeepButtonLabels = {\n saved?: ReactNode;\n unsaved?: ReactNode;\n loading?: ReactNode;\n error?: ReactNode;\n savedAriaLabel?: string;\n unsavedAriaLabel?: string;\n};\n\nexport type KeepImageProps = ImgHTMLAttributes<HTMLImageElement> & {\n src: string;\n alt: string;\n};\n\nexport function toKeepButtonItem<TMeta>(item: KeepItem<TMeta>): KeepItemInput<TMeta> {\n return {\n id: item.id,\n meta: item.meta,\n targetType: item.targetType,\n note: item.note,\n tags: item.tags,\n };\n}\n\nexport function getMetaTitle<TMeta>(meta: TMeta): string | undefined {\n if (typeof meta !== \"object\" || meta === null || !(\"title\" in meta)) return undefined;\n const title = (meta as { title?: unknown }).title;\n return typeof title === \"string\" && title.trim() ? title.trim() : undefined;\n}\n\nexport function normalizeUiTags(tags: string[]): string[] {\n return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nexport function sortToValue(sort: KeepListQuery[\"sort\"]): `${\"savedAt\" | \"updatedAt\"}:${\"asc\" | \"desc\"}` {\n return `${sort?.by ?? \"updatedAt\"}:${sort?.direction ?? \"desc\"}`;\n}\n\nexport function resolveContent<TState>(content: ReactNode | RenderProp<TState>, state: TState): ReactNode {\n return typeof content === \"function\" ? content(state) : content;\n}\n\nexport function renderRoot(\n asChild: boolean,\n child: ReactNode,\n props: HTMLAttributes<HTMLElement> & Record<string, unknown>,\n body: ReactNode,\n componentName: string,\n): ReactElement {\n if (asChild) {\n if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);\n return cloneElement(child as ReactElement<Record<string, unknown>>, { ...props, children: body });\n }\n return <div {...props}>{body}</div>;\n}\n","\"use client\";\n\nimport { createContext, type ReactNode, useContext, useMemo } from \"react\";\n\nexport type KeepUiLabelKey =\n | \"save\"\n | \"saved\"\n | \"remove\"\n | \"loading\"\n | \"saving\"\n | \"syncing\"\n | \"error\"\n | \"allTags\"\n | \"filterTags\"\n | \"note\"\n | \"saveNote\"\n | \"noItems\"\n | \"loadingItems\"\n | \"errorItems\"\n | \"search\"\n | \"sort\"\n | \"newest\"\n | \"oldest\"\n | \"savedNewest\"\n | \"savedOldest\"\n | \"updatedNewest\"\n | \"updatedOldest\"\n | \"previousPage\"\n | \"nextPage\"\n | \"pagination\"\n | \"page\"\n | \"selectItems\"\n | \"selectedCount\"\n | \"deleteSelected\"\n | \"tagsToApply\"\n | \"applyTags\"\n | \"savedMessage\"\n | \"removedMessage\"\n | \"noteSavedMessage\";\n\nexport type KeepUiLabels = Partial<Record<KeepUiLabelKey, string>>;\n\nexport type KeepUiLabelContext = {\n locale?: string;\n labels: Readonly<Record<KeepUiLabelKey, string>>;\n labelResolver?: (key: KeepUiLabelKey, context: { locale?: string }) => string | undefined;\n};\n\nexport const DEFAULT_LABELS: Record<KeepUiLabelKey, string> = {\n save: \"Save\",\n saved: \"Saved\",\n remove: \"Remove\",\n loading: \"Loading…\",\n saving: \"Saving…\",\n syncing: \"Syncing…\",\n error: \"Something went wrong.\",\n allTags: \"All\",\n filterTags: \"Filter saved items by tag\",\n note: \"Note\",\n saveNote: \"Save note\",\n noItems: \"No saved items.\",\n loadingItems: \"Loading saved items…\",\n errorItems: \"Could not load saved items.\",\n search: \"Search saved items\",\n sort: \"Sort saved items\",\n newest: \"Newest first\",\n oldest: \"Oldest first\",\n savedNewest: \"Saved newest first\",\n savedOldest: \"Saved oldest first\",\n updatedNewest: \"Updated newest first\",\n updatedOldest: \"Updated oldest first\",\n previousPage: \"Previous page\",\n nextPage: \"Next page\",\n pagination: \"Pagination\",\n page: \"Page\",\n selectItems: \"Select saved items\",\n selectedCount: \"selected\",\n deleteSelected: \"Delete selected\",\n tagsToApply: \"Tags to apply\",\n applyTags: \"Apply tags\",\n savedMessage: \"Item saved.\",\n removedMessage: \"Item removed.\",\n noteSavedMessage: \"Note saved.\",\n};\n\nconst KeepUiLabelsContext = createContext<KeepUiLabelContext>({ labels: DEFAULT_LABELS });\n\nexport type KeepUiProviderProps = {\n labels?: KeepUiLabels;\n locale?: string;\n labelResolver?: KeepUiLabelContext[\"labelResolver\"];\n children?: ReactNode;\n};\n\n/** Provides one locale-aware label source to every UI primitive. */\nexport function KeepUiProvider({ labels, locale, labelResolver, children }: KeepUiProviderProps) {\n const value = useMemo<KeepUiLabelContext>(() => {\n const resolved = { ...DEFAULT_LABELS, ...labels };\n return { locale, labels: resolved, labelResolver };\n }, [labelResolver, labels, locale]);\n return <KeepUiLabelsContext.Provider value={value}>{children}</KeepUiLabelsContext.Provider>;\n}\n\nexport function useKeepUiLabels(): KeepUiLabelContext {\n return useContext(KeepUiLabelsContext);\n}\n\nexport function useUiLabel(key: KeepUiLabelKey, override?: string): string {\n const context = useKeepUiLabels();\n return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];\n}\n","\"use client\";\n\nimport {\n KeepButton as CoreKeepButton,\n type KeepButtonProps as CoreKeepButtonProps,\n type KeepButtonState,\n useKeepItem,\n} from \"@keepkit/core/react\";\nimport type { ReactNode } from \"react\";\nimport type { KeepButtonLabels } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type { KeepButtonLabels } from \"./shared\";\n\nexport type KeepButtonProps<TMeta = Record<string, unknown>> = CoreKeepButtonProps<TMeta> & {\n labels?: KeepButtonLabels;\n};\n\n/** A style-free save toggle with localized labels and the core button's ARIA/asChild behavior. */\nexport function KeepButton<TMeta = Record<string, unknown>>({ labels, ...props }: KeepButtonProps<TMeta>) {\n const saveLabel = useUiLabel(\"save\", typeof labels?.unsaved === \"string\" ? labels.unsaved : undefined);\n const savedLabel = useUiLabel(\"saved\", typeof labels?.saved === \"string\" ? labels.saved : undefined);\n const loadingLabel = useUiLabel(\"loading\", typeof labels?.loading === \"string\" ? labels.loading : undefined);\n const errorLabel = useUiLabel(\"error\", typeof labels?.error === \"string\" ? labels.error : undefined);\n const buttonState = useKeepItem<TMeta>(props.item);\n const customStateLabel = labels?.loading !== undefined || labels?.error !== undefined;\n const getStateContent = (state: KeepButtonState<TMeta>): ReactNode => {\n if (state.error) return labels?.error ?? errorLabel;\n if (state.isMutating) return labels?.loading ?? loadingLabel;\n if (typeof props.children === \"function\") return props.children(state);\n if (props.children !== undefined) return props.children;\n return state.isSaved ? (labels?.saved ?? savedLabel) : (labels?.unsaved ?? saveLabel);\n };\n const sharedProps = {\n ...props,\n \"aria-busy\": props[\"aria-busy\"] ?? (buttonState.isLoading || buttonState.isMutating),\n savedLabel: labels?.saved ?? props.savedLabel ?? savedLabel,\n unsavedLabel: labels?.unsaved ?? props.unsavedLabel ?? saveLabel,\n savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,\n unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel,\n };\n if (!customStateLabel) return <CoreKeepButton<TMeta> {...sharedProps} />;\n return (\n <CoreKeepButton<TMeta> {...sharedProps}>\n {(state: KeepButtonState<TMeta>) => <>{getStateContent(state)}</>}\n </CoreKeepButton>\n );\n}\n","\"use client\";\n\nimport type { KeepItem, KeepListQuery } from \"@keepkit/core/core\";\nimport { useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, type ReactNode, useMemo, useState } from \"react\";\nimport { KeepBulkActions } from \"./KeepBulkActions\";\nimport type { KeepItemCardProps } from \"./KeepItemCard\";\nimport { KeepList, type KeepListState } from \"./KeepList\";\nimport { KeepTagFilter } from \"./KeepTagFilter\";\nimport { KeepPagination, KeepSearchInput, KeepSortSelect } from \"./query-controls\";\nimport { type RenderProp, sortToValue } from \"./shared\";\n\nexport type KeepCollectionFeature = \"search\" | \"sort\" | \"pagination\" | \"tagFilter\" | \"bulkActions\";\n\nexport type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n query?: KeepListQuery<TMeta>;\n pageSize?: number;\n features?: Partial<Record<KeepCollectionFeature, boolean>>;\n renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;\n itemCardProps?: Omit<KeepItemCardProps<TMeta>, \"item\" | \"children\" | \"render\">;\n loading?: ReactNode | RenderProp<KeepListState<TMeta>>;\n empty?: ReactNode | RenderProp<KeepListState<TMeta>>;\n error?: ReactNode | RenderProp<KeepListState<TMeta>>;\n};\n\n/** A batteries-included collection with query controls and accessible status feedback. */\nexport function KeepCollection<TMeta = Record<string, unknown>>({\n query = {},\n pageSize = 20,\n features,\n renderItem,\n itemCardProps,\n loading,\n empty,\n error,\n className,\n ...rootProps\n}: KeepCollectionProps<TMeta>) {\n const enabled = {\n search: true,\n sort: true,\n pagination: true,\n tagFilter: false,\n bulkActions: false,\n ...features,\n };\n const [searchValue, setSearchValue] = useState(query.search?.query ?? \"\");\n const [sort, setSort] = useState(query.sort ?? { by: \"updatedAt\" as const, direction: \"desc\" as const });\n const [tag, setTag] = useState<string | undefined>(query.tags?.[0]);\n const [page, setPage] = useState(query.pagination?.page ?? 1);\n const resolvedPageSize = query.pagination?.pageSize ?? pageSize;\n const resolvedQuery = useMemo<KeepListQuery<TMeta>>(\n () => ({\n ...query,\n search: enabled.search ? { ...query.search, query: searchValue } : query.search,\n sort: enabled.sort ? sort : query.sort,\n tags: tag ? [...new Set([...(query.tags ?? []), tag])] : query.tags,\n pagination: enabled.pagination ? { ...query.pagination, page, pageSize: resolvedPageSize } : query.pagination,\n }),\n [enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag],\n );\n const list = useKeepList<TMeta>(resolvedQuery);\n\n return (\n <section\n {...rootProps}\n className={className}\n aria-busy={list.isLoading || list.isMutating || rootProps[\"aria-busy\"]}\n >\n <div>\n {enabled.search ? (\n <KeepSearchInput\n value={searchValue}\n onValueChange={(value) => {\n setSearchValue(value);\n setPage(1);\n }}\n />\n ) : null}\n {enabled.sort ? (\n <KeepSortSelect\n value={sortToValue(sort)}\n onValueChange={(_value, nextSort) => {\n setSort(nextSort);\n setPage(1);\n }}\n />\n ) : null}\n {enabled.tagFilter ? (\n <KeepTagFilter<TMeta>\n query={query}\n value={tag}\n onValueChange={(value) => {\n setTag(value);\n setPage(1);\n }}\n />\n ) : null}\n </div>\n <KeepList<TMeta>\n query={resolvedQuery}\n renderItem={renderItem}\n itemCardProps={itemCardProps}\n loading={loading}\n empty={empty}\n error={error}\n />\n {enabled.pagination ? (\n <KeepPagination\n totalCount={list.totalCount}\n pageSize={resolvedPageSize}\n page={list.page}\n onPageChange={(nextPage) => setPage(nextPage)}\n />\n ) : null}\n {enabled.bulkActions ? <KeepBulkActions<TMeta> query={resolvedQuery} /> : null}\n </section>\n );\n}\n","\"use client\";\n\nimport type { KeepItem, KeepListQuery } from \"@keepkit/core/core\";\nimport type { UseKeepListResult } from \"@keepkit/core/react\";\nimport { useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, isValidElement, type ReactNode } from \"react\";\nimport { KeepItemCard, type KeepItemCardProps } from \"./KeepItemCard\";\nimport { type RenderProp, renderRoot, resolveContent } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepListState<TMeta = Record<string, unknown>> = UseKeepListResult<TMeta>;\n\nexport type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n query?: KeepListQuery<TMeta>;\n children?: ReactNode | RenderProp<KeepListState<TMeta>>;\n renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;\n loading?: ReactNode | RenderProp<KeepListState<TMeta>>;\n empty?: ReactNode | RenderProp<KeepListState<TMeta>>;\n error?: ReactNode | RenderProp<KeepListState<TMeta>>;\n itemCardProps?: Omit<KeepItemCardProps<TMeta>, \"item\" | \"children\" | \"render\">;\n asChild?: boolean;\n};\n\n/** A list primitive with built-in loading, empty, error, and removal states. */\nexport function KeepList<TMeta = Record<string, unknown>>({\n query,\n children,\n renderItem,\n loading,\n empty,\n error: errorContent,\n itemCardProps,\n asChild = false,\n className,\n ...rootProps\n}: KeepListProps<TMeta>) {\n const defaultLoading = useUiLabel(\"loadingItems\");\n const defaultEmpty = useUiLabel(\"noItems\");\n const defaultError = useUiLabel(\"errorItems\");\n const state = useKeepList<TMeta>(query);\n const body = getListBody(state, {\n children,\n renderItem,\n loading: loading ?? defaultLoading,\n empty: empty ?? defaultEmpty,\n error: errorContent ?? defaultError,\n itemCardProps,\n });\n return renderRoot(\n asChild,\n asChild && isValidElement(children) ? children : undefined,\n { ...rootProps, className, \"aria-busy\": state.isLoading || rootProps[\"aria-busy\"] },\n body,\n \"KeepList\",\n );\n}\n\nfunction getListBody<TMeta>(\n state: KeepListState<TMeta>,\n options: {\n children?: ReactNode | RenderProp<KeepListState<TMeta>>;\n renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;\n loading: ReactNode | RenderProp<KeepListState<TMeta>>;\n empty: ReactNode | RenderProp<KeepListState<TMeta>>;\n error: ReactNode | RenderProp<KeepListState<TMeta>>;\n itemCardProps?: Omit<KeepItemCardProps<TMeta>, \"item\" | \"children\" | \"render\">;\n },\n): ReactNode {\n if (state.error && state.items.length === 0) return resolveContent(options.error, state);\n if (state.isLoading && !state.isHydrated) return resolveContent(options.loading, state);\n if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);\n if (typeof options.children === \"function\") return options.children(state);\n if (options.children !== undefined && !isValidElement(options.children)) return options.children;\n return (\n <ul>\n {state.items.map((item) =>\n options.renderItem ? (\n options.renderItem(item, state)\n ) : (\n <li key={item.id}>\n <KeepItemCard item={item} {...options.itemCardProps} />\n </li>\n ),\n )}\n </ul>\n );\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport { useKeepItem } from \"@keepkit/core/react\";\nimport { type ComponentType, type HTMLAttributes, type ImgHTMLAttributes, isValidElement, type ReactNode } from \"react\";\nimport { KeepButton, type KeepButtonLabels } from \"./KeepButton\";\nimport { getMetaTitle, type RenderProp, renderRoot, toKeepButtonItem } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepItemCardState<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta>;\n isSaved: boolean;\n isMutating: boolean;\n error: unknown | null;\n remove: () => Promise<void>;\n};\n\nexport type KeepImageProps = ImgHTMLAttributes<HTMLImageElement> & {\n src: string;\n alt: string;\n};\n\nexport type KeepItemCardProps<TMeta = Record<string, unknown>> = Omit<\n HTMLAttributes<HTMLElement>,\n \"children\" | \"title\"\n> & {\n item: KeepItem<TMeta>;\n title?: ReactNode | ((item: KeepItem<TMeta>) => ReactNode);\n getTitle?: (item: KeepItem<TMeta>) => ReactNode;\n getImageProps?: (item: KeepItem<TMeta>, title: ReactNode) => KeepImageProps | undefined;\n imageComponent?: ComponentType<KeepImageProps>;\n renderImage?: (props: KeepImageProps, item: KeepItem<TMeta>) => ReactNode;\n imageAlt?: string;\n render?: RenderProp<KeepItemCardState<TMeta>>;\n children?: ReactNode | RenderProp<KeepItemCardState<TMeta>>;\n removeLabel?: string;\n onRemoveError?: (error: unknown) => void;\n onRemoved?: (item: KeepItem<TMeta>) => void;\n showSaveButton?: boolean;\n saveButtonLabels?: KeepButtonLabels;\n asChild?: boolean;\n};\n\n/** A low-dependency item presentation primitive. The default markup can be replaced with render props. */\nexport function KeepItemCard<TMeta = Record<string, unknown>>({\n item,\n title,\n getTitle,\n getImageProps,\n imageComponent: ImageComponent,\n renderImage,\n imageAlt,\n render,\n children,\n removeLabel,\n onRemoveError,\n onRemoved,\n showSaveButton = true,\n saveButtonLabels,\n asChild = false,\n className,\n ...rootProps\n}: KeepItemCardProps<TMeta>) {\n const saveActionLabel = useUiLabel(\"save\");\n const removeActionLabel = useUiLabel(\"remove\");\n const itemState = useKeepItem<TMeta>(item);\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const state: KeepItemCardState<TMeta> = {\n item,\n isSaved: itemState.isSaved,\n isMutating: itemState.isMutating,\n error: itemState.error,\n remove: itemState.remove,\n };\n const resolvedTitle =\n typeof title === \"function\" ? title(item) : (title ?? getTitle?.(item) ?? getMetaTitle(item.meta) ?? item.id);\n const imageProps = getImageProps?.(item, resolvedTitle);\n\n async function handleRemove() {\n try {\n await itemState.remove();\n onRemoved?.(item);\n } catch (error) {\n onRemoveError?.(error);\n }\n }\n\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <>\n {imageProps\n ? (renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ??\n (ImageComponent ? (\n <ImageComponent {...imageProps} alt={imageAlt ?? imageProps.alt} />\n ) : (\n <img {...imageProps} alt={imageAlt ?? imageProps.alt} />\n )))\n : null}\n <h3>{resolvedTitle}</h3>\n {showSaveButton ? (\n <KeepButton\n item={toKeepButtonItem(item)}\n labels={saveButtonLabels}\n getAriaLabel={(buttonState) =>\n `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`\n }\n />\n ) : null}\n <button type=\"button\" onClick={() => void handleRemove()} disabled={itemState.isMutating}>\n {removeLabel ?? removeActionLabel}\n </button>\n </>\n ));\n\n return renderRoot(\n asChild,\n isValidElement(children) ? children : undefined,\n { ...rootProps, className, \"aria-busy\": itemState.isMutating || rootProps[\"aria-busy\"] },\n body,\n \"KeepItemCard\",\n );\n}\n","\"use client\";\n\nimport type { KeepListQuery } from \"@keepkit/core/core\";\nimport { useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, isValidElement, type ReactNode, useCallback, useMemo, useState } from \"react\";\nimport { type RenderProp, renderRoot } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepTagFilterState = {\n tags: string[];\n tagCounts: Record<string, number>;\n value?: string;\n select: (tag?: string) => void;\n};\n\nexport type KeepTagFilterProps<TMeta = Record<string, unknown>> = Omit<\n HTMLAttributes<HTMLElement>,\n \"children\" | \"onChange\"\n> & {\n query?: KeepListQuery<TMeta>;\n value?: string;\n defaultValue?: string;\n onChange?: (tag?: string) => void;\n onValueChange?: (tag?: string) => void;\n allLabel?: ReactNode;\n ariaLabel?: string;\n renderTag?: (tag: string, count: number, selected: boolean) => ReactNode;\n render?: RenderProp<KeepTagFilterState>;\n children?: ReactNode | RenderProp<KeepTagFilterState>;\n asChild?: boolean;\n};\n\n/** An ARIA button group for tag filtering; consumers can connect value to a collection query. */\nexport function KeepTagFilter<TMeta = Record<string, unknown>>({\n query,\n value: controlledValue,\n defaultValue,\n onChange,\n onValueChange,\n allLabel,\n ariaLabel,\n renderTag,\n render,\n children,\n asChild = false,\n className,\n ...rootProps\n}: KeepTagFilterProps<TMeta>) {\n const uiAllLabel = useUiLabel(\"allTags\");\n const uiAriaLabel = useUiLabel(\"filterTags\");\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const resolvedValue = controlledValue ?? uncontrolledValue;\n const list = useKeepList<TMeta>({\n ...query,\n tags: resolvedValue ? [...(query?.tags ?? []), resolvedValue] : query?.tags,\n });\n const select = useCallback(\n (tag?: string) => {\n if (controlledValue === undefined) setUncontrolledValue(tag);\n onChange?.(tag);\n onValueChange?.(tag);\n },\n [controlledValue, onChange, onValueChange],\n );\n const state = useMemo<KeepTagFilterState>(\n () => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),\n [list.tagCounts, list.tags, resolvedValue, select],\n );\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <fieldset>\n <legend>{ariaLabel ?? uiAriaLabel}</legend>\n <button type=\"button\" aria-pressed={resolvedValue === undefined} onClick={() => select()}>\n {allLabel ?? uiAllLabel}\n </button>\n {list.tags.map((tag) => (\n <button key={tag} type=\"button\" aria-pressed={resolvedValue === tag} onClick={() => select(tag)}>\n {renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag}\n <span> ({list.tagCounts[tag] ?? 0})</span>\n </button>\n ))}\n </fieldset>\n ));\n return renderRoot(\n asChild,\n isValidElement(children) ? children : undefined,\n { ...rootProps, className },\n body,\n \"KeepTagFilter\",\n );\n}\n","\"use client\";\n\nimport type { KeepListQuery } from \"@keepkit/core/core\";\nimport { type InputHTMLAttributes, type ReactNode, type SelectHTMLAttributes, useEffect, useState } from \"react\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepSearchInputProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n value?: string;\n defaultValue?: string;\n /** Delay before notifying consumers; set to 0 to disable debouncing. */\n debounceMs?: number;\n onValueChange?: (value: string) => void;\n};\n\n/** A controlled/uncontrolled search field with a small built-in debounce. */\nexport function KeepSearchInput({\n value: controlledValue,\n defaultValue = \"\",\n debounceMs = 300,\n onValueChange,\n \"aria-label\": ariaLabel,\n placeholder,\n ...props\n}: KeepSearchInputProps) {\n const label = useUiLabel(\"search\");\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n\n useEffect(() => {\n if (!onValueChange) return;\n if (debounceMs <= 0) {\n onValueChange(value);\n return;\n }\n const timer = window.setTimeout(() => onValueChange(value), debounceMs);\n return () => window.clearTimeout(timer);\n }, [debounceMs, onValueChange, value]);\n\n return (\n <input\n {...props}\n type=\"search\"\n value={value}\n aria-label={ariaLabel ?? label}\n placeholder={placeholder ?? label}\n onChange={(event) => {\n const nextValue = event.currentTarget.value;\n if (controlledValue === undefined) setUncontrolledValue(nextValue);\n }}\n />\n );\n}\n\nexport type KeepSortValue = \"savedAt:desc\" | \"savedAt:asc\" | \"updatedAt:desc\" | \"updatedAt:asc\";\n\nexport type KeepSortSelectProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n value?: KeepSortValue;\n defaultValue?: KeepSortValue;\n onValueChange?: (value: KeepSortValue, sort: NonNullable<KeepListQuery[\"sort\"]>) => void;\n};\n\n/** Emits a normalized sort descriptor that can be passed directly to useKeepList. */\nexport function KeepSortSelect({\n value: controlledValue,\n defaultValue = \"updatedAt:desc\",\n onValueChange,\n \"aria-label\": ariaLabel,\n children,\n ...props\n}: KeepSortSelectProps) {\n const label = useUiLabel(\"sort\");\n const updatedNewestLabel = useUiLabel(\"updatedNewest\");\n const updatedOldestLabel = useUiLabel(\"updatedOldest\");\n const savedNewestLabel = useUiLabel(\"savedNewest\");\n const savedOldestLabel = useUiLabel(\"savedOldest\");\n const [uncontrolledValue, setUncontrolledValue] = useState<KeepSortValue>(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n const options = children ?? (\n <>\n <option value=\"updatedAt:desc\">{updatedNewestLabel}</option>\n <option value=\"updatedAt:asc\">{updatedOldestLabel}</option>\n <option value=\"savedAt:desc\">{savedNewestLabel}</option>\n <option value=\"savedAt:asc\">{savedOldestLabel}</option>\n </>\n );\n return (\n <select\n {...props}\n value={value}\n aria-label={ariaLabel ?? label}\n onChange={(event) => {\n const nextValue = event.currentTarget.value as KeepSortValue;\n if (controlledValue === undefined) setUncontrolledValue(nextValue);\n const [by, direction] = nextValue.split(\":\") as [\"savedAt\" | \"updatedAt\", \"asc\" | \"desc\"];\n onValueChange?.(nextValue, { by, direction });\n }}\n >\n {options}\n </select>\n );\n}\n\nexport type KeepPaginationState = { page: number; pageCount: number; goToPage: (page: number) => void };\n\nexport type KeepPaginationProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n totalCount: number;\n pageSize: number;\n page?: number;\n maxPageButtons?: number;\n onPageChange?: (page: number, offset: number) => void;\n render?: (state: KeepPaginationState) => ReactNode;\n};\n\n/** Accessible pagination with previous/next controls and numbered page buttons. */\nexport function KeepPagination({\n totalCount,\n pageSize,\n page = 1,\n maxPageButtons = 7,\n onPageChange,\n render,\n ...props\n}: KeepPaginationProps) {\n const previousPageLabel = useUiLabel(\"previousPage\");\n const nextPageLabel = useUiLabel(\"nextPage\");\n const pageLabel = useUiLabel(\"page\");\n const paginationLabel = useUiLabel(\"pagination\");\n const pageCount = Math.max(1, Math.ceil(totalCount / Math.max(1, pageSize)));\n const currentPage = Math.min(Math.max(1, page), pageCount);\n const goToPage = (nextPage: number) => {\n const next = Math.min(Math.max(1, nextPage), pageCount);\n onPageChange?.(next, (next - 1) * pageSize);\n };\n const navProps = { ...props, \"aria-label\": props[\"aria-label\"] ?? paginationLabel };\n if (render) return <nav {...navProps}>{render({ page: currentPage, pageCount, goToPage })}</nav>;\n const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));\n return (\n <nav {...navProps}>\n <button type=\"button\" onClick={() => goToPage(currentPage - 1)} disabled={currentPage <= 1}>\n {previousPageLabel}\n </button>\n {visiblePages.map((nextPage) => (\n <button\n key={nextPage}\n type=\"button\"\n aria-current={nextPage === currentPage ? \"page\" : undefined}\n aria-label={`${pageLabel} ${nextPage}`}\n onClick={() => goToPage(nextPage)}\n >\n {nextPage}\n </button>\n ))}\n <button type=\"button\" onClick={() => goToPage(currentPage + 1)} disabled={currentPage >= pageCount}>\n {nextPageLabel}\n </button>\n </nav>\n );\n}\n\nfunction getVisiblePages(currentPage: number, pageCount: number, maxPageButtons: number): number[] {\n if (pageCount <= maxPageButtons) return Array.from({ length: pageCount }, (_, index) => index + 1);\n const half = Math.floor(maxPageButtons / 2);\n const start = Math.min(Math.max(1, currentPage - half), pageCount - maxPageButtons + 1);\n return Array.from({ length: maxPageButtons }, (_, index) => start + index);\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport { useKeepItem } from \"@keepkit/core/react\";\nimport {\n type FormHTMLAttributes,\n isValidElement,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { type RenderProp, renderRoot } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepNoteEditorState<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta>;\n note: string;\n setNote: (note: string) => void;\n isDirty: boolean;\n isSaving: boolean;\n error: unknown | null;\n save: () => Promise<void>;\n};\n\nexport type KeepNoteEditorProps<TMeta = Record<string, unknown>> = Omit<\n FormHTMLAttributes<HTMLFormElement>,\n \"children\" | \"onSubmit\"\n> & {\n item: KeepItem<TMeta>;\n label?: ReactNode;\n saveLabel?: ReactNode;\n placeholder?: string;\n /** Automatically save dirty notes after this delay; set to 0 to disable auto-save. */\n debounceMs?: number;\n onSaved?: (note?: string) => void;\n onSaveError?: (error: unknown) => void;\n render?: RenderProp<KeepNoteEditorState<TMeta>>;\n children?: ReactNode | RenderProp<KeepNoteEditorState<TMeta>>;\n asChild?: boolean;\n};\n\n/** A controlled-by-default note editor that persists through useKeepItem. */\nexport function KeepNoteEditor<TMeta = Record<string, unknown>>({\n item,\n label,\n saveLabel,\n placeholder,\n debounceMs = 300,\n onSaved,\n onSaveError,\n render,\n children,\n asChild = false,\n className,\n ...formProps\n}: KeepNoteEditorProps<TMeta>) {\n const defaultLabel = useUiLabel(\"note\");\n const defaultSaveLabel = useUiLabel(\"saveNote\");\n const itemState = useKeepItem<TMeta>(item);\n const { error, isMutating, item: savedItem, updateNote } = itemState;\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const [note, setNote] = useState(item.note ?? \"\");\n const baselineNote = savedItem?.note ?? item.note ?? \"\";\n const isDirty = note !== baselineNote;\n const lastSavedNoteRef = useRef<string | undefined>(undefined);\n useEffect(() => setNote(baselineNote), [baselineNote]);\n const save = useCallback(async () => {\n const nextNote = note.trim() || undefined;\n try {\n await updateNote(nextNote);\n lastSavedNoteRef.current = note;\n onSaved?.(nextNote);\n } catch (error) {\n onSaveError?.(error);\n throw error;\n }\n }, [note, onSaveError, onSaved, updateNote]);\n useEffect(() => {\n if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;\n const timer = window.setTimeout(() => void save().catch(() => undefined), debounceMs);\n return () => window.clearTimeout(timer);\n }, [debounceMs, isDirty, note, save]);\n const state: KeepNoteEditorState<TMeta> = {\n item,\n note,\n setNote,\n isDirty,\n isSaving: isMutating,\n error,\n save,\n };\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <>\n <label>\n {label ?? defaultLabel}\n <textarea\n value={note}\n onChange={(event) => setNote(event.currentTarget.value)}\n placeholder={placeholder}\n disabled={isMutating}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && (event.ctrlKey || event.metaKey)) {\n event.preventDefault();\n void save().catch(() => undefined);\n }\n }}\n />\n </label>\n <button type=\"submit\" disabled={isMutating} aria-busy={isMutating}>\n {saveLabel ?? defaultSaveLabel}\n </button>\n </>\n ));\n const handleSubmit: FormHTMLAttributes<HTMLFormElement>[\"onSubmit\"] = (event) => {\n event.preventDefault();\n void save().catch(() => undefined);\n };\n if (!asChild) {\n return (\n <form\n {...formProps}\n className={className}\n onSubmit={handleSubmit}\n aria-busy={isMutating || formProps[\"aria-busy\"]}\n >\n {body}\n </form>\n );\n }\n return renderRoot(\n true,\n isValidElement(children) ? children : undefined,\n { ...formProps, className, onSubmit: handleSubmit, \"aria-busy\": isMutating || formProps[\"aria-busy\"] },\n body,\n \"KeepNoteEditor\",\n );\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport { useKeepItem } from \"@keepkit/core/react\";\nimport { type FormHTMLAttributes, useCallback, useEffect, useState } from \"react\";\nimport { normalizeUiTags, type RenderProp } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepTagEditorState = {\n tags: string[];\n setTags: (tags: string[]) => void;\n save: () => Promise<void>;\n isSaving: boolean;\n};\n\nexport type KeepTagEditorProps<TMeta = Record<string, unknown>> = Omit<\n FormHTMLAttributes<HTMLFormElement>,\n \"children\" | \"onSubmit\"\n> & {\n item: KeepItem<TMeta>;\n availableTags?: string[];\n onSaved?: (tags?: string[]) => void;\n onSaveError?: (error: unknown) => void;\n render?: RenderProp<KeepTagEditorState>;\n};\n\n/** Edits one item's normalized tag set; Enter adds and Backspace removes the last tag. */\nexport function KeepTagEditor<TMeta = Record<string, unknown>>({\n item,\n availableTags = [],\n onSaved,\n onSaveError,\n render,\n ...props\n}: KeepTagEditorProps<TMeta>) {\n const tagsLabel = useUiLabel(\"tagsToApply\");\n const removeLabel = useUiLabel(\"remove\");\n const applyTagsLabel = useUiLabel(\"applyTags\");\n const itemState = useKeepItem<TMeta>(item);\n const [tags, setTags] = useState(item.tags ?? []);\n const [input, setInput] = useState(\"\");\n useEffect(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);\n const save = useCallback(async () => {\n const nextTags = normalizeUiTags(tags);\n try {\n await itemState.updateTags(nextTags);\n setTags(nextTags);\n onSaved?.(nextTags);\n } catch (error) {\n onSaveError?.(error);\n throw error;\n }\n }, [itemState, onSaveError, onSaved, tags]);\n const addTag = (tag: string) => {\n setTags(normalizeUiTags([...tags, tag]));\n setInput(\"\");\n };\n const body = render ? (\n render({ tags, setTags, save, isSaving: itemState.isMutating })\n ) : (\n <>\n <label>\n {tagsLabel}\n <input\n value={input}\n list={availableTags.length > 0 ? `keep-tags-${item.id}` : undefined}\n onChange={(event) => setInput(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n if (event.nativeEvent.isComposing) return;\n event.preventDefault();\n if (input.trim()) addTag(input);\n } else if (event.key === \"Backspace\" && input.length === 0 && tags.length > 0) {\n event.preventDefault();\n setTags(tags.slice(0, -1));\n }\n }}\n />\n </label>\n {availableTags.length > 0 ? (\n <datalist id={`keep-tags-${item.id}`}>\n {availableTags.map((tag) => (\n <option key={tag} value={tag} />\n ))}\n </datalist>\n ) : null}\n <ul aria-label={tagsLabel}>\n {tags.map((tag) => (\n <li key={tag}>\n {tag}\n <button type=\"button\" onClick={() => setTags(tags.filter((current) => current !== tag))}>\n {removeLabel}\n </button>\n </li>\n ))}\n </ul>\n <button type=\"submit\" disabled={itemState.isMutating} aria-busy={itemState.isMutating}>\n {applyTagsLabel}\n </button>\n </>\n );\n return (\n <form\n {...props}\n onSubmit={(event) => {\n event.preventDefault();\n void save().catch(() => undefined);\n }}\n aria-busy={itemState.isMutating || props[\"aria-busy\"]}\n >\n {body}\n </form>\n );\n}\n","\"use client\";\n\nimport type { KeepChangeContext, KeepItem } from \"@keepkit/core/core\";\nimport { useKeepContext } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, isValidElement, type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { type RenderProp, renderRoot } from \"./shared\";\nimport { type KeepUiLabelKey, useUiLabel } from \"./ui-context\";\n\nexport type KeepEmptyStateProps = Omit<HTMLAttributes<HTMLElement>, \"children\" | \"title\"> & {\n title?: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n children?: ReactNode;\n asChild?: boolean;\n};\n\n/** A style-free, reusable empty collection state. */\nexport function KeepEmptyState({\n title,\n description,\n action,\n children,\n asChild = false,\n className,\n ...rootProps\n}: KeepEmptyStateProps) {\n const defaultTitle = useUiLabel(\"noItems\").replace(/\\.$/, \"\");\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const body = contentChildren ?? (\n <>\n <h2>{title ?? defaultTitle}</h2>\n {description ? <p>{description}</p> : null}\n {action}\n </>\n );\n return renderRoot(asChild, children, { ...rootProps, className }, body, \"KeepEmptyState\");\n}\n\nexport type KeepStatusValue = \"idle\" | \"empty\" | \"loading\" | \"saving\" | \"syncing\" | \"error\";\nexport type KeepStatusLabels = Partial<Record<KeepStatusValue, ReactNode>>;\n\nexport type KeepStatusState<TMeta = Record<string, unknown>> = {\n status: KeepStatusValue;\n error: unknown | null;\n pendingCount: number;\n items: KeepItem<TMeta>[];\n};\n\nexport type KeepStatusProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n status?: KeepStatusValue;\n labels?: KeepStatusLabels;\n children?: ReactNode | RenderProp<KeepStatusState<TMeta>>;\n render?: RenderProp<KeepStatusState<TMeta>>;\n asChild?: boolean;\n};\n\n/** Presents provider loading, mutation, synchronization, empty, and error states accessibly. */\nexport function KeepStatus<TMeta = Record<string, unknown>>({\n status,\n labels,\n children,\n render,\n asChild = false,\n className,\n ...rootProps\n}: KeepStatusProps<TMeta>) {\n const context = useKeepContext<TMeta>();\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const resolvedStatus = status ?? getDerivedStatus(context);\n const defaultLabel = useUiLabel(getStatusLabelKey(resolvedStatus));\n const state: KeepStatusState<TMeta> = {\n status: resolvedStatus,\n error: context.error,\n pendingCount: context.syncState.pendingCount,\n items: context.items,\n };\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? labels?.[resolvedStatus] ?? defaultLabel);\n const role = rootProps.role ?? (resolvedStatus === \"error\" ? \"alert\" : \"status\");\n return renderRoot(\n asChild,\n isValidElement(children) ? children : undefined,\n { ...rootProps, className, role, \"aria-live\": rootProps[\"aria-live\"] ?? \"polite\" },\n body,\n \"KeepStatus\",\n );\n}\n\nexport type KeepAnnouncementsProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n messages?: Partial<Record<\"save\" | \"remove\" | \"note\", string>>;\n};\n\n/** Announces successful save, remove, and note operations in a polite live region. */\nexport function KeepAnnouncements<TMeta = Record<string, unknown>>({ messages, ...props }: KeepAnnouncementsProps) {\n const context = useKeepContext<TMeta>();\n const savedMessage = useUiLabel(\"savedMessage\", messages?.save);\n const removedMessage = useUiLabel(\"removedMessage\", messages?.remove);\n const noteSavedMessage = useUiLabel(\"noteSavedMessage\", messages?.note);\n const [message, setMessage] = useState(\"\");\n const lastChangeRef = useRef<KeepChangeContext<TMeta> | undefined>(undefined);\n useEffect(() => {\n const change = context.lastChange;\n if (!change || change === lastChangeRef.current) return;\n lastChangeRef.current = change;\n if (change.action === \"save\") setMessage(savedMessage);\n else if (change.action === \"remove\" || change.action === \"removeBatch\") setMessage(removedMessage);\n else if (change.action === \"updateNote\") setMessage(noteSavedMessage);\n }, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);\n return (\n <div {...props} role={props.role ?? \"status\"} aria-live={props[\"aria-live\"] ?? \"polite\"} aria-atomic=\"true\">\n {message}\n </div>\n );\n}\n\n/** Singular alias for applications that mount one announcer explicitly. */\nexport const KeepAnnouncer = KeepAnnouncements;\n\nfunction getDerivedStatus<TMeta>(context: ReturnType<typeof useKeepContext<TMeta>>): KeepStatusValue {\n if (context.error) return \"error\";\n if (context.syncState.status === \"pending\" || context.syncState.status === \"syncing\") return \"syncing\";\n if (context.isMutating) return \"saving\";\n if (context.isLoading && !context.isHydrated) return \"loading\";\n if (context.isHydrated && context.items.length === 0) return \"empty\";\n return \"idle\";\n}\n\nfunction getStatusLabelKey(status: KeepStatusValue): KeepUiLabelKey {\n if (status === \"empty\") return \"noItems\";\n if (status === \"loading\") return \"loadingItems\";\n if (status === \"error\") return \"error\";\n if (status === \"saving\") return \"saving\";\n if (status === \"syncing\") return \"syncing\";\n return \"saved\";\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","Fragment","jsx","useKeepList","useMemo","useState","useKeepList","isValidElement","useKeepItem","isValidElement","Fragment","jsx","jsxs","useKeepItem","isValidElement","jsx","useKeepList","isValidElement","useKeepList","isValidElement","useMemo","useState","jsx","jsxs","useState","useKeepList","useMemo","isValidElement","useState","Fragment","jsx","jsxs","useState","jsx","jsxs","useState","useMemo","useKeepList","useKeepItem","isValidElement","useCallback","useEffect","useState","Fragment","jsx","jsxs","useKeepItem","isValidElement","useState","useEffect","useCallback","error","useKeepItem","useCallback","useEffect","useState","Fragment","jsx","jsxs","useKeepItem","useState","useEffect","useCallback","isValidElement","useEffect","useRef","useState","Fragment","jsx","jsxs","isValidElement","useState","useRef","useEffect","useKeepContext","useKeepItem","useKeepList","jsx","jsxs","jsx"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/KeepBulkActions.tsx","../src/KeepItemCheckbox.tsx","../src/shared.tsx","../src/ui-context.tsx","../src/KeepButton.tsx","../src/KeepCollection.tsx","../src/KeepList.tsx","../src/KeepItemCard.tsx","../src/KeepTagFilter.tsx","../src/query-controls.tsx","../src/KeepNoteEditor.tsx","../src/KeepTagEditor.tsx","../src/status.tsx"],"sourcesContent":["\"use client\";\n\nimport type { KeepItem, KeepItemInput, KeepListQuery } from \"@keepkit/core/core\";\nimport {\n type CreateKeepKitOptions as CoreCreateKeepKitOptions,\n KeepProvider as CoreKeepProvider,\n createKeepKit as createCoreKeepKit,\n type KeepProviderProps,\n type KeepShortcutOptions,\n type useKeepContext,\n type useKeepItem,\n type useKeepList,\n} from \"@keepkit/core/react\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { KeepBulkActions, type KeepBulkActionsProps, type KeepBulkActionsState } from \"./KeepBulkActions\";\nimport { KeepButton, type KeepButtonLabels, type KeepButtonProps } from \"./KeepButton\";\nimport { KeepCollection, type KeepCollectionFeature, type KeepCollectionProps } from \"./KeepCollection\";\nimport { type KeepImageProps, KeepItemCard, type KeepItemCardProps, type KeepItemCardState } from \"./KeepItemCard\";\nimport { KeepItemCheckbox, type KeepItemCheckboxProps } from \"./KeepItemCheckbox\";\nimport { KeepList, type KeepListProps, type KeepListState } from \"./KeepList\";\nimport { KeepNoteEditor, type KeepNoteEditorProps, type KeepNoteEditorState } from \"./KeepNoteEditor\";\nimport { KeepTagEditor, type KeepTagEditorProps, type KeepTagEditorState } from \"./KeepTagEditor\";\nimport { KeepTagFilter, type KeepTagFilterProps, type KeepTagFilterState } from \"./KeepTagFilter\";\nimport {\n KeepPagination,\n type KeepPaginationProps,\n type KeepPaginationState,\n KeepSearchInput,\n type KeepSearchInputProps,\n KeepSortSelect,\n type KeepSortSelectProps,\n type KeepSortValue,\n} from \"./query-controls\";\nimport {\n KeepAnnouncements,\n type KeepAnnouncementsProps,\n KeepAnnouncer,\n KeepEmptyState,\n type KeepEmptyStateProps,\n KeepStatus,\n type KeepStatusLabels,\n type KeepStatusProps,\n type KeepStatusState,\n type KeepStatusValue,\n} from \"./status\";\nimport {\n type KeepUiLabelContext,\n type KeepUiLabelKey,\n type KeepUiLabels,\n KeepUiProvider,\n type KeepUiProviderProps,\n useKeepUiLabels,\n} from \"./ui-context\";\n\nexport type KeepKitProviderProps<TMeta = Record<string, unknown>> = Omit<KeepProviderProps<TMeta>, \"children\"> &\n Omit<KeepUiProviderProps, \"children\"> & { children?: ReactNode };\n\n/** Combines the core store, UI labels, and the global live announcer. */\nexport function KeepKitProvider<TMeta = Record<string, unknown>>({\n labels,\n locale,\n labelResolver,\n children,\n ...providerProps\n}: KeepKitProviderProps<TMeta>) {\n return (\n <KeepUiProvider labels={labels} locale={locale} labelResolver={labelResolver}>\n <CoreKeepProvider<TMeta> {...providerProps}>\n {children}\n <KeepAnnouncements />\n </CoreKeepProvider>\n </KeepUiProvider>\n );\n}\n\nexport type { KeepItem, KeepItemInput, KeepListQuery, KeepSyncStatus } from \"@keepkit/core/core\";\nexport type {\n KeepButtonState,\n KeepContextValue,\n KeepErrorBoundaryProps,\n KeepProviderProps,\n KeepShortcutOptions,\n} from \"@keepkit/core/react\";\nexport {\n KeepErrorBoundary,\n KeepProvider,\n useKeepContext,\n useKeepItem,\n useKeepList,\n useKeepShortcut,\n} from \"@keepkit/core/react\";\nexport {\n createBrowserStorageAdapter,\n createStorageAdapter,\n FallbackStorageAdapter,\n IndexedDBAdapter,\n IndexedDBSyncQueueAdapter,\n LocalStorageAdapter,\n LocalStorageSyncQueueAdapter,\n SyncStorageAdapter,\n} from \"@keepkit/core/storage\";\nexport { isAllSelected, toggleSelectAll } from \"./KeepBulkActions\";\nexport type { RenderProp } from \"./shared\";\nexport type {\n KeepAnnouncementsProps,\n KeepBulkActionsProps,\n KeepBulkActionsState,\n KeepButtonLabels,\n KeepButtonProps,\n KeepCollectionFeature,\n KeepCollectionProps,\n KeepEmptyStateProps,\n KeepImageProps,\n KeepItemCardProps,\n KeepItemCardState,\n KeepItemCheckboxProps,\n KeepListProps,\n KeepListState,\n KeepNoteEditorProps,\n KeepNoteEditorState,\n KeepPaginationProps,\n KeepPaginationState,\n KeepSearchInputProps,\n KeepSortSelectProps,\n KeepSortValue,\n KeepStatusLabels,\n KeepStatusProps,\n KeepStatusState,\n KeepStatusValue,\n KeepTagEditorProps,\n KeepTagEditorState,\n KeepTagFilterProps,\n KeepTagFilterState,\n KeepUiLabelContext,\n KeepUiLabelKey,\n KeepUiLabels,\n KeepUiProviderProps,\n};\nexport {\n KeepAnnouncements,\n KeepAnnouncer,\n KeepBulkActions,\n KeepButton,\n KeepCollection,\n KeepEmptyState,\n KeepItemCard,\n KeepItemCheckbox,\n KeepList,\n KeepNoteEditor,\n KeepPagination,\n KeepSearchInput,\n KeepSortSelect,\n KeepStatus,\n KeepTagEditor,\n KeepTagFilter,\n KeepUiProvider,\n useKeepUiLabels,\n};\n\nexport type CreateKeepKitOptions<TMeta = Record<string, unknown>> = CoreCreateKeepKitOptions<TMeta> &\n Omit<KeepUiProviderProps, \"children\"> & {\n getTitle?: (item: KeepItem<TMeta>) => ReactNode;\n getImageProps?: (item: KeepItem<TMeta>, title: ReactNode) => KeepImageProps | undefined;\n };\n\nexport type KeepKit<TMeta = Record<string, unknown>> = {\n Provider: ComponentType<KeepKitProviderProps<TMeta>>;\n Button: ComponentType<KeepButtonProps<TMeta>>;\n Collection: ComponentType<KeepCollectionProps<TMeta>>;\n useContext: () => ReturnType<typeof useKeepContext<TMeta>>;\n useItem: (item?: KeepItemInput<TMeta>) => ReturnType<typeof useKeepItem<TMeta>>;\n useList: (query?: KeepListQuery<TMeta>) => ReturnType<typeof useKeepList<TMeta>>;\n useShortcut: (options: KeepShortcutOptions<TMeta>) => void;\n};\n\n/** Create one typed application API for the core and standard UI layer. */\nexport function createKeepKit<TMeta = Record<string, unknown>>(\n options: CreateKeepKitOptions<TMeta> = {},\n): KeepKit<TMeta> {\n const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;\n const coreKit = createCoreKeepKit<TMeta>(coreOptions);\n return {\n Provider: (props) => (\n <KeepKitProvider<TMeta>\n {...coreOptions}\n labels={labels}\n locale={locale}\n labelResolver={labelResolver}\n {...props}\n />\n ),\n Button: (props) => <KeepButton<TMeta> {...props} />,\n Collection: (props) => (\n <KeepCollection<TMeta>\n {...props}\n itemCardProps={{\n ...(getTitle ? { getTitle } : {}),\n ...(getImageProps ? { getImageProps } : {}),\n ...props.itemCardProps,\n }}\n />\n ),\n useContext: () => coreKit.useContext(),\n useItem: (item) => coreKit.useItem(item),\n useList: (query) => coreKit.useList(query),\n useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions),\n };\n}\n","\"use client\";\n\nimport type { KeepItem, KeepListQuery } from \"@keepkit/core/core\";\nimport { useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, type ReactNode, useState } from \"react\";\nimport { KeepItemCheckbox } from \"./KeepItemCheckbox\";\nimport { getMetaTitle, normalizeUiTags, type RenderProp } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepBulkActionsState<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n selectedIds: string[];\n selectedCount: number;\n isAllSelected: boolean;\n allSelected: boolean;\n tagsInput: string;\n setTagsInput: (value: string) => void;\n toggle: (id: string) => void;\n toggleSelectAll: () => void;\n toggleAll: () => void;\n remove: () => Promise<void>;\n updateTags: () => Promise<void>;\n isMutating: boolean;\n};\n\n/** Returns whether every visible item is selected. Empty lists are never all selected. */\nexport function isAllSelected<TMeta>(\n items: readonly Pick<KeepItem<TMeta>, \"id\">[],\n selectedIds: readonly string[],\n): boolean {\n if (items.length === 0) return false;\n const selected = new Set(selectedIds);\n return items.every((item) => selected.has(item.id));\n}\n\n/** Toggles only the visible items, preserving selections outside the current query or page. */\nexport function toggleSelectAll<TMeta>(\n items: readonly Pick<KeepItem<TMeta>, \"id\">[],\n selectedIds: readonly string[],\n): string[] {\n const visibleIds = new Set(items.map((item) => item.id));\n if (isAllSelected(items, selectedIds)) return selectedIds.filter((id) => !visibleIds.has(id));\n const nextIds = [...selectedIds];\n for (const item of items) {\n if (!nextIds.includes(item.id)) nextIds.push(item.id);\n }\n return nextIds;\n}\n\nexport type KeepBulkActionsProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n query?: KeepListQuery<TMeta>;\n selectedIds?: string[];\n defaultSelectedIds?: string[];\n onSelectedIdsChange?: (ids: string[]) => void;\n renderItem?: (item: KeepItem<TMeta>, selected: boolean) => ReactNode;\n onCompleted?: (action: \"remove\" | \"tags\", ids: string[]) => void;\n render?: RenderProp<KeepBulkActionsState<TMeta>>;\n children?: ReactNode | RenderProp<KeepBulkActionsState<TMeta>>;\n};\n\n/** Selects visible items and performs one storage operation for the whole selection. */\nexport function KeepBulkActions<TMeta = Record<string, unknown>>({\n query,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n onSelectedIdsChange,\n renderItem,\n onCompleted,\n render,\n children,\n ...props\n}: KeepBulkActionsProps<TMeta>) {\n const selectItemsLabel = useUiLabel(\"selectItems\");\n const selectedCountLabel = useUiLabel(\"selectedCount\");\n const deleteSelectedLabel = useUiLabel(\"deleteSelected\");\n const tagsLabel = useUiLabel(\"tagsToApply\");\n const applyTagsLabel = useUiLabel(\"applyTags\");\n const list = useKeepList<TMeta>(query);\n const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);\n const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;\n const selected = new Set(selectedIds);\n const [tagsInput, setTagsInput] = useState(\"\");\n const setSelectedIds = (ids: string[]) => {\n if (controlledSelectedIds === undefined) setUncontrolledSelectedIds(ids);\n onSelectedIdsChange?.(ids);\n };\n const toggle = (id: string) =>\n setSelectedIds(selected.has(id) ? selectedIds.filter((current) => current !== id) : [...selectedIds, id]);\n const allSelected = isAllSelected(list.items, selectedIds);\n const toggleAll = () => setSelectedIds(toggleSelectAll(list.items, selectedIds));\n const remove = async () => {\n const ids = [...selectedIds];\n await list.removeBatch(ids);\n onCompleted?.(\"remove\", ids);\n setSelectedIds([]);\n };\n const updateTags = async () => {\n const ids = [...selectedIds];\n await list.updateTagsBatch(ids, normalizeUiTags(tagsInput.split(\",\")));\n onCompleted?.(\"tags\", ids);\n setSelectedIds([]);\n };\n const state: KeepBulkActionsState<TMeta> = {\n items: list.items,\n selectedIds,\n selectedCount: selectedIds.length,\n isAllSelected: allSelected,\n allSelected,\n tagsInput,\n setTagsInput,\n toggle,\n toggleSelectAll: toggleAll,\n toggleAll,\n remove,\n updateTags,\n isMutating: list.isMutating,\n };\n const body = render\n ? render(state)\n : typeof children === \"function\"\n ? children(state)\n : (children ?? (\n <>\n <fieldset>\n <legend>{selectItemsLabel}</legend>\n <label>\n <input type=\"checkbox\" checked={allSelected} onChange={toggleAll} aria-label={selectItemsLabel} />\n {selectedIds.length} {selectedCountLabel}\n </label>\n {list.items.map((item) => (\n <span key={item.id}>\n <KeepItemCheckbox\n item={item}\n checked={selected.has(item.id)}\n onCheckedChange={() => toggle(item.id)}\n />\n {renderItem ? renderItem(item, selected.has(item.id)) : (getMetaTitle(item.meta) ?? item.id)}\n </span>\n ))}\n </fieldset>\n <button type=\"button\" onClick={() => void remove()} disabled={selectedIds.length === 0 || list.isMutating}>\n {deleteSelectedLabel}\n </button>\n <label>\n {tagsLabel}\n <input value={tagsInput} onChange={(event) => setTagsInput(event.currentTarget.value)} />\n </label>\n <button\n type=\"button\"\n onClick={() => void updateTags()}\n disabled={selectedIds.length === 0 || list.isMutating}\n >\n {applyTagsLabel}\n </button>\n </>\n ));\n return (\n <section\n {...props}\n aria-busy={list.isMutating || props[\"aria-busy\"]}\n data-state={selectedIds.length > 0 ? \"selected\" : \"idle\"}\n data-loading={list.isLoading || list.isMutating ? \"true\" : undefined}\n >\n {body}\n </section>\n );\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\n\nexport type KeepItemCheckboxProps<TMeta = Record<string, unknown>> = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"checked\" | \"defaultChecked\" | \"onChange\"\n> & {\n item: KeepItem<TMeta>;\n checked?: boolean;\n label?: ReactNode;\n onCheckedChange?: (checked: boolean) => void;\n};\n\n/** A reusable accessible selection checkbox for a saved item. */\nexport function KeepItemCheckbox<TMeta = Record<string, unknown>>({\n item,\n checked = false,\n label,\n onCheckedChange,\n \"aria-label\": ariaLabel,\n ...props\n}: KeepItemCheckboxProps<TMeta>) {\n const itemLabel = getItemLabel(item) ?? item.id;\n const accessibleLabel = ariaLabel ?? (typeof label === \"string\" ? label : itemLabel);\n return (\n <input\n {...props}\n type=\"checkbox\"\n checked={checked}\n data-state={checked ? \"checked\" : \"unchecked\"}\n data-disabled={props.disabled ? \"true\" : undefined}\n aria-label={accessibleLabel}\n onChange={(event) => onCheckedChange?.(event.currentTarget.checked)}\n />\n );\n}\n\nfunction getItemLabel<TMeta>(item: KeepItem<TMeta>): string | undefined {\n if (typeof item.meta !== \"object\" || item.meta === null || !(\"title\" in item.meta)) return undefined;\n const title = (item.meta as { title?: unknown }).title;\n return typeof title === \"string\" && title.trim() ? title.trim() : undefined;\n}\n","\"use client\";\n\nimport type { KeepItem, KeepItemInput, KeepListQuery } from \"@keepkit/core/core\";\nimport {\n cloneElement,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n isValidElement,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nexport type RenderProp<TState> = (state: TState) => ReactNode;\n\nexport type KeepButtonLabels = {\n saved?: ReactNode;\n unsaved?: ReactNode;\n loading?: ReactNode;\n error?: ReactNode;\n savedAriaLabel?: string;\n unsavedAriaLabel?: string;\n};\n\nexport type KeepImageProps = ImgHTMLAttributes<HTMLImageElement> & {\n src: string;\n alt: string;\n};\n\nexport function toKeepButtonItem<TMeta>(item: KeepItem<TMeta>): KeepItemInput<TMeta> {\n return {\n id: item.id,\n meta: item.meta,\n targetType: item.targetType,\n note: item.note,\n tags: item.tags,\n };\n}\n\nexport function getMetaTitle<TMeta>(meta: TMeta): string | undefined {\n if (typeof meta !== \"object\" || meta === null || !(\"title\" in meta)) return undefined;\n const title = (meta as { title?: unknown }).title;\n return typeof title === \"string\" && title.trim() ? title.trim() : undefined;\n}\n\nexport function normalizeUiTags(tags: string[]): string[] {\n return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nexport function sortToValue(sort: KeepListQuery[\"sort\"]): `${\"savedAt\" | \"updatedAt\"}:${\"asc\" | \"desc\"}` {\n return `${sort?.by ?? \"updatedAt\"}:${sort?.direction ?? \"desc\"}`;\n}\n\nexport function resolveContent<TState>(content: ReactNode | RenderProp<TState>, state: TState): ReactNode {\n return typeof content === \"function\" ? content(state) : content;\n}\n\nexport function renderRoot(\n asChild: boolean,\n child: ReactNode,\n props: HTMLAttributes<HTMLElement> & Record<string, unknown>,\n body: ReactNode,\n componentName: string,\n): ReactElement {\n if (asChild) {\n if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);\n return cloneElement(child as ReactElement<Record<string, unknown>>, { ...props, children: body });\n }\n return <div {...props}>{body}</div>;\n}\n","\"use client\";\n\nimport { createContext, type ReactNode, useContext, useMemo } from \"react\";\n\nexport type KeepUiLabelKey =\n | \"save\"\n | \"saved\"\n | \"remove\"\n | \"loading\"\n | \"saving\"\n | \"syncing\"\n | \"error\"\n | \"allTags\"\n | \"filterTags\"\n | \"note\"\n | \"saveNote\"\n | \"noItems\"\n | \"loadingItems\"\n | \"errorItems\"\n | \"search\"\n | \"sort\"\n | \"newest\"\n | \"oldest\"\n | \"savedNewest\"\n | \"savedOldest\"\n | \"updatedNewest\"\n | \"updatedOldest\"\n | \"previousPage\"\n | \"nextPage\"\n | \"pagination\"\n | \"page\"\n | \"selectItems\"\n | \"selectedCount\"\n | \"deleteSelected\"\n | \"tagsToApply\"\n | \"applyTags\"\n | \"savedMessage\"\n | \"removedMessage\"\n | \"noteSavedMessage\";\n\nexport type KeepUiLabels = Partial<Record<KeepUiLabelKey, string>>;\n\nexport type KeepUiLabelContext = {\n locale?: string;\n labels: Readonly<Record<KeepUiLabelKey, string>>;\n labelResolver?: (key: KeepUiLabelKey, context: { locale?: string }) => string | undefined;\n};\n\nexport const DEFAULT_LABELS: Record<KeepUiLabelKey, string> = {\n save: \"Save\",\n saved: \"Saved\",\n remove: \"Remove\",\n loading: \"Loading…\",\n saving: \"Saving…\",\n syncing: \"Syncing…\",\n error: \"Something went wrong.\",\n allTags: \"All\",\n filterTags: \"Filter saved items by tag\",\n note: \"Note\",\n saveNote: \"Save note\",\n noItems: \"No saved items.\",\n loadingItems: \"Loading saved items…\",\n errorItems: \"Could not load saved items.\",\n search: \"Search saved items\",\n sort: \"Sort saved items\",\n newest: \"Newest first\",\n oldest: \"Oldest first\",\n savedNewest: \"Saved newest first\",\n savedOldest: \"Saved oldest first\",\n updatedNewest: \"Updated newest first\",\n updatedOldest: \"Updated oldest first\",\n previousPage: \"Previous page\",\n nextPage: \"Next page\",\n pagination: \"Pagination\",\n page: \"Page\",\n selectItems: \"Select saved items\",\n selectedCount: \"selected\",\n deleteSelected: \"Delete selected\",\n tagsToApply: \"Tags to apply\",\n applyTags: \"Apply tags\",\n savedMessage: \"Item saved.\",\n removedMessage: \"Item removed.\",\n noteSavedMessage: \"Note saved.\",\n};\n\nconst KeepUiLabelsContext = createContext<KeepUiLabelContext>({ labels: DEFAULT_LABELS });\n\nexport type KeepUiProviderProps = {\n labels?: KeepUiLabels;\n locale?: string;\n labelResolver?: KeepUiLabelContext[\"labelResolver\"];\n children?: ReactNode;\n};\n\n/** Provides one locale-aware label source to every UI primitive. */\nexport function KeepUiProvider({ labels, locale, labelResolver, children }: KeepUiProviderProps) {\n const value = useMemo<KeepUiLabelContext>(() => {\n const resolved = { ...DEFAULT_LABELS, ...labels };\n return { locale, labels: resolved, labelResolver };\n }, [labelResolver, labels, locale]);\n return <KeepUiLabelsContext.Provider value={value}>{children}</KeepUiLabelsContext.Provider>;\n}\n\nexport function useKeepUiLabels(): KeepUiLabelContext {\n return useContext(KeepUiLabelsContext);\n}\n\nexport function useUiLabel(key: KeepUiLabelKey, override?: string): string {\n const context = useKeepUiLabels();\n return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];\n}\n","\"use client\";\n\nimport {\n KeepButton as CoreKeepButton,\n type KeepButtonProps as CoreKeepButtonProps,\n type KeepButtonState,\n useKeepItem,\n} from \"@keepkit/core/react\";\nimport type { ReactNode } from \"react\";\nimport type { KeepButtonLabels } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type { KeepButtonLabels } from \"./shared\";\n\nexport type KeepButtonProps<TMeta = Record<string, unknown>> = CoreKeepButtonProps<TMeta> & {\n labels?: KeepButtonLabels;\n};\n\n/** A style-free save toggle with localized labels and the core button's ARIA/asChild behavior. */\nexport function KeepButton<TMeta = Record<string, unknown>>({ labels, ...props }: KeepButtonProps<TMeta>) {\n const saveLabel = useUiLabel(\"save\", typeof labels?.unsaved === \"string\" ? labels.unsaved : undefined);\n const savedLabel = useUiLabel(\"saved\", typeof labels?.saved === \"string\" ? labels.saved : undefined);\n const loadingLabel = useUiLabel(\"loading\", typeof labels?.loading === \"string\" ? labels.loading : undefined);\n const errorLabel = useUiLabel(\"error\", typeof labels?.error === \"string\" ? labels.error : undefined);\n const buttonState = useKeepItem<TMeta>(props.item);\n const customStateLabel = labels?.loading !== undefined || labels?.error !== undefined;\n const getStateContent = (state: KeepButtonState<TMeta>): ReactNode => {\n if (state.error) return labels?.error ?? errorLabel;\n if (state.isMutating) return labels?.loading ?? loadingLabel;\n if (typeof props.children === \"function\") return props.children(state);\n if (props.children !== undefined) return props.children;\n return state.isSaved ? (labels?.saved ?? savedLabel) : (labels?.unsaved ?? saveLabel);\n };\n const sharedProps = {\n ...props,\n \"aria-busy\": props[\"aria-busy\"] ?? (buttonState.isLoading || buttonState.isMutating),\n savedLabel: labels?.saved ?? props.savedLabel ?? savedLabel,\n unsavedLabel: labels?.unsaved ?? props.unsavedLabel ?? saveLabel,\n savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,\n unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel,\n };\n if (!customStateLabel) return <CoreKeepButton<TMeta> {...sharedProps} />;\n return (\n <CoreKeepButton<TMeta> {...sharedProps}>\n {(state: KeepButtonState<TMeta>) => <>{getStateContent(state)}</>}\n </CoreKeepButton>\n );\n}\n","\"use client\";\n\nimport type { KeepItem, KeepListQuery } from \"@keepkit/core/core\";\nimport { KeepErrorBoundary, type KeepErrorBoundaryProps, useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, type ReactNode, useMemo, useState } from \"react\";\nimport { KeepBulkActions } from \"./KeepBulkActions\";\nimport type { KeepItemCardProps } from \"./KeepItemCard\";\nimport { KeepList, type KeepListState } from \"./KeepList\";\nimport { KeepTagFilter } from \"./KeepTagFilter\";\nimport { KeepPagination, KeepSearchInput, KeepSortSelect } from \"./query-controls\";\nimport { type RenderProp, sortToValue } from \"./shared\";\n\nexport type KeepCollectionFeature = \"search\" | \"sort\" | \"pagination\" | \"tagFilter\" | \"bulkActions\";\n\nexport type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n query?: KeepListQuery<TMeta>;\n pageSize?: number;\n features?: Partial<Record<KeepCollectionFeature, boolean>>;\n renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;\n itemCardProps?: Omit<KeepItemCardProps<TMeta>, \"item\" | \"children\" | \"render\">;\n loading?: ReactNode | RenderProp<KeepListState<TMeta>>;\n empty?: ReactNode | RenderProp<KeepListState<TMeta>>;\n error?: ReactNode | RenderProp<KeepListState<TMeta>>;\n fallback?: KeepErrorBoundaryProps[\"fallback\"];\n onBoundaryError?: KeepErrorBoundaryProps[\"onError\"];\n boundaryResetKey?: unknown;\n};\n\n/** A batteries-included collection with query controls and accessible status feedback. */\nexport function KeepCollection<TMeta = Record<string, unknown>>(props: KeepCollectionProps<TMeta>) {\n const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;\n const content = <KeepCollectionContent<TMeta> {...collectionProps} />;\n if (fallback === undefined && onBoundaryError === undefined) return content;\n return (\n <KeepErrorBoundary fallback={fallback} onError={onBoundaryError} resetKey={boundaryResetKey}>\n {content}\n </KeepErrorBoundary>\n );\n}\n\nfunction KeepCollectionContent<TMeta = Record<string, unknown>>({\n query = {},\n pageSize = 20,\n features,\n renderItem,\n itemCardProps,\n loading,\n empty,\n error,\n className,\n ...rootProps\n}: Omit<KeepCollectionProps<TMeta>, \"fallback\" | \"onBoundaryError\" | \"boundaryResetKey\">) {\n const enabled = {\n search: true,\n sort: true,\n pagination: true,\n tagFilter: false,\n bulkActions: false,\n ...features,\n };\n const [searchValue, setSearchValue] = useState(query.search?.query ?? \"\");\n const [sort, setSort] = useState(query.sort ?? { by: \"updatedAt\" as const, direction: \"desc\" as const });\n const [tag, setTag] = useState<string | undefined>(query.tags?.[0]);\n const [page, setPage] = useState(query.pagination?.page ?? 1);\n const resolvedPageSize = query.pagination?.pageSize ?? pageSize;\n const resolvedQuery = useMemo<KeepListQuery<TMeta>>(\n () => ({\n ...query,\n search: enabled.search ? { ...query.search, query: searchValue } : query.search,\n sort: enabled.sort ? sort : query.sort,\n tags: tag ? [...new Set([...(query.tags ?? []), tag])] : query.tags,\n pagination: enabled.pagination ? { ...query.pagination, page, pageSize: resolvedPageSize } : query.pagination,\n }),\n [enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag],\n );\n const list = useKeepList<TMeta>(resolvedQuery);\n\n return (\n <section\n {...rootProps}\n className={className}\n aria-busy={list.isLoading || list.isMutating || rootProps[\"aria-busy\"]}\n data-state={getCollectionState(list)}\n data-loading={list.isLoading || list.isMutating ? \"true\" : undefined}\n >\n <div>\n {enabled.search ? (\n <KeepSearchInput\n value={searchValue}\n onValueChange={(value) => {\n setSearchValue(value);\n setPage(1);\n }}\n />\n ) : null}\n {enabled.sort ? (\n <KeepSortSelect\n value={sortToValue(sort)}\n onValueChange={(_value, nextSort) => {\n setSort(nextSort);\n setPage(1);\n }}\n />\n ) : null}\n {enabled.tagFilter ? (\n <KeepTagFilter<TMeta>\n query={query}\n value={tag}\n onValueChange={(value) => {\n setTag(value);\n setPage(1);\n }}\n />\n ) : null}\n </div>\n <KeepList<TMeta>\n query={resolvedQuery}\n renderItem={renderItem}\n itemCardProps={itemCardProps}\n loading={loading}\n empty={empty}\n error={error}\n />\n {enabled.pagination ? (\n <KeepPagination\n totalCount={list.totalCount}\n pageSize={resolvedPageSize}\n page={list.page}\n onPageChange={(nextPage) => setPage(nextPage)}\n />\n ) : null}\n {enabled.bulkActions ? <KeepBulkActions<TMeta> query={resolvedQuery} /> : null}\n </section>\n );\n}\n\nfunction getCollectionState<TMeta>(list: KeepListState<TMeta>): \"loading\" | \"error\" | \"empty\" | \"ready\" {\n if (list.error && list.items.length === 0) return \"error\";\n if (list.isLoading && !list.isHydrated) return \"loading\";\n if (list.isHydrated && list.items.length === 0) return \"empty\";\n return \"ready\";\n}\n","\"use client\";\n\nimport type { KeepItem, KeepListQuery } from \"@keepkit/core/core\";\nimport {\n KeepErrorBoundary,\n type KeepErrorBoundaryProps,\n type UseKeepListResult,\n useKeepList,\n} from \"@keepkit/core/react\";\nimport { type HTMLAttributes, isValidElement, type ReactNode } from \"react\";\nimport { KeepItemCard, type KeepItemCardProps } from \"./KeepItemCard\";\nimport { type RenderProp, renderRoot, resolveContent } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepListState<TMeta = Record<string, unknown>> = UseKeepListResult<TMeta>;\n\nexport type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n query?: KeepListQuery<TMeta>;\n children?: ReactNode | RenderProp<KeepListState<TMeta>>;\n renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;\n loading?: ReactNode | RenderProp<KeepListState<TMeta>>;\n empty?: ReactNode | RenderProp<KeepListState<TMeta>>;\n error?: ReactNode | RenderProp<KeepListState<TMeta>>;\n itemCardProps?: Omit<KeepItemCardProps<TMeta>, \"item\" | \"children\" | \"render\">;\n asChild?: boolean;\n fallback?: KeepErrorBoundaryProps[\"fallback\"];\n onBoundaryError?: KeepErrorBoundaryProps[\"onError\"];\n boundaryResetKey?: unknown;\n};\n\n/** A list primitive with built-in loading, empty, error, and removal states. */\nexport function KeepList<TMeta = Record<string, unknown>>(props: KeepListProps<TMeta>) {\n const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;\n const content = <KeepListContent<TMeta> {...listProps} />;\n if (fallback === undefined && onBoundaryError === undefined) return content;\n return (\n <KeepErrorBoundary fallback={fallback} onError={onBoundaryError} resetKey={boundaryResetKey}>\n {content}\n </KeepErrorBoundary>\n );\n}\n\nfunction KeepListContent<TMeta = Record<string, unknown>>({\n query,\n children,\n renderItem,\n loading,\n empty,\n error: errorContent,\n itemCardProps,\n asChild = false,\n className,\n ...rootProps\n}: KeepListProps<TMeta>) {\n const defaultLoading = useUiLabel(\"loadingItems\");\n const defaultEmpty = useUiLabel(\"noItems\");\n const defaultError = useUiLabel(\"errorItems\");\n const state = useKeepList<TMeta>(query);\n const body = getListBody(state, {\n children,\n renderItem,\n loading: loading ?? defaultLoading,\n empty: empty ?? defaultEmpty,\n error: errorContent ?? defaultError,\n itemCardProps,\n });\n return renderRoot(\n asChild,\n asChild && isValidElement(children) ? children : undefined,\n {\n ...rootProps,\n className,\n \"aria-busy\": state.isLoading || rootProps[\"aria-busy\"],\n \"data-state\": getListState(state),\n \"data-loading\": state.isLoading ? \"true\" : undefined,\n },\n body,\n \"KeepList\",\n );\n}\n\nfunction getListState<TMeta>(state: KeepListState<TMeta>): \"loading\" | \"error\" | \"empty\" | \"ready\" {\n if (state.error && state.items.length === 0) return \"error\";\n if (state.isLoading && !state.isHydrated) return \"loading\";\n if (state.isHydrated && state.items.length === 0) return \"empty\";\n return \"ready\";\n}\n\nfunction getListBody<TMeta>(\n state: KeepListState<TMeta>,\n options: {\n children?: ReactNode | RenderProp<KeepListState<TMeta>>;\n renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;\n loading: ReactNode | RenderProp<KeepListState<TMeta>>;\n empty: ReactNode | RenderProp<KeepListState<TMeta>>;\n error: ReactNode | RenderProp<KeepListState<TMeta>>;\n itemCardProps?: Omit<KeepItemCardProps<TMeta>, \"item\" | \"children\" | \"render\">;\n },\n): ReactNode {\n if (state.error && state.items.length === 0) return resolveContent(options.error, state);\n if (state.isLoading && !state.isHydrated) return resolveContent(options.loading, state);\n if (state.isHydrated && state.items.length === 0) return resolveContent(options.empty, state);\n if (typeof options.children === \"function\") return options.children(state);\n if (options.children !== undefined && !isValidElement(options.children)) return options.children;\n return (\n <ul>\n {state.items.map((item) =>\n options.renderItem ? (\n options.renderItem(item, state)\n ) : (\n <li key={item.id}>\n <KeepItemCard item={item} {...options.itemCardProps} />\n </li>\n ),\n )}\n </ul>\n );\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport { useKeepItem } from \"@keepkit/core/react\";\nimport { type ComponentType, type HTMLAttributes, type ImgHTMLAttributes, isValidElement, type ReactNode } from \"react\";\nimport { KeepButton, type KeepButtonLabels } from \"./KeepButton\";\nimport { getMetaTitle, type RenderProp, renderRoot, toKeepButtonItem } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepItemCardState<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta>;\n isSaved: boolean;\n isMutating: boolean;\n error: unknown | null;\n remove: () => Promise<void>;\n};\n\nexport type KeepImageProps = ImgHTMLAttributes<HTMLImageElement> & {\n src: string;\n alt: string;\n};\n\nexport type KeepItemCardProps<TMeta = Record<string, unknown>> = Omit<\n HTMLAttributes<HTMLElement>,\n \"children\" | \"title\"\n> & {\n item: KeepItem<TMeta>;\n title?: ReactNode | ((item: KeepItem<TMeta>) => ReactNode);\n getTitle?: (item: KeepItem<TMeta>) => ReactNode;\n getImageProps?: (item: KeepItem<TMeta>, title: ReactNode) => KeepImageProps | undefined;\n imageComponent?: ComponentType<KeepImageProps>;\n renderImage?: (props: KeepImageProps, item: KeepItem<TMeta>) => ReactNode;\n imageAlt?: string;\n render?: RenderProp<KeepItemCardState<TMeta>>;\n children?: ReactNode | RenderProp<KeepItemCardState<TMeta>>;\n removeLabel?: string;\n onRemoveError?: (error: unknown) => void;\n onRemoved?: (item: KeepItem<TMeta>) => void;\n showSaveButton?: boolean;\n saveButtonLabels?: KeepButtonLabels;\n asChild?: boolean;\n};\n\n/** A low-dependency item presentation primitive. The default markup can be replaced with render props. */\nexport function KeepItemCard<TMeta = Record<string, unknown>>({\n item,\n title,\n getTitle,\n getImageProps,\n imageComponent: ImageComponent,\n renderImage,\n imageAlt,\n render,\n children,\n removeLabel,\n onRemoveError,\n onRemoved,\n showSaveButton = true,\n saveButtonLabels,\n asChild = false,\n className,\n ...rootProps\n}: KeepItemCardProps<TMeta>) {\n const saveActionLabel = useUiLabel(\"save\");\n const removeActionLabel = useUiLabel(\"remove\");\n const itemState = useKeepItem<TMeta>(item);\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const state: KeepItemCardState<TMeta> = {\n item,\n isSaved: itemState.isSaved,\n isMutating: itemState.isMutating,\n error: itemState.error,\n remove: itemState.remove,\n };\n const resolvedTitle =\n typeof title === \"function\" ? title(item) : (title ?? getTitle?.(item) ?? getMetaTitle(item.meta) ?? item.id);\n const imageProps = getImageProps?.(item, resolvedTitle);\n\n async function handleRemove() {\n try {\n await itemState.remove();\n onRemoved?.(item);\n } catch (error) {\n onRemoveError?.(error);\n }\n }\n\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <>\n {imageProps\n ? (renderImage?.({ ...imageProps, alt: imageAlt ?? imageProps.alt }, item) ??\n (ImageComponent ? (\n <ImageComponent {...imageProps} alt={imageAlt ?? imageProps.alt} />\n ) : (\n <img {...imageProps} alt={imageAlt ?? imageProps.alt} />\n )))\n : null}\n <h3>{resolvedTitle}</h3>\n {showSaveButton ? (\n <KeepButton\n item={toKeepButtonItem(item)}\n labels={saveButtonLabels}\n getAriaLabel={(buttonState) =>\n `${buttonState.isSaved ? removeActionLabel : saveActionLabel} ${String(resolvedTitle)}`\n }\n />\n ) : null}\n <button type=\"button\" onClick={() => void handleRemove()} disabled={itemState.isMutating}>\n {removeLabel ?? removeActionLabel}\n </button>\n </>\n ));\n\n return renderRoot(\n asChild,\n isValidElement(children) ? children : undefined,\n {\n ...rootProps,\n className,\n \"aria-busy\": itemState.isMutating || rootProps[\"aria-busy\"],\n \"data-state\": itemState.isSaved ? \"saved\" : \"unsaved\",\n \"data-loading\": itemState.isMutating ? \"true\" : undefined,\n },\n body,\n \"KeepItemCard\",\n );\n}\n","\"use client\";\n\nimport type { KeepListQuery } from \"@keepkit/core/core\";\nimport { useKeepList } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, isValidElement, type ReactNode, useCallback, useMemo, useState } from \"react\";\nimport { type RenderProp, renderRoot } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepTagFilterState = {\n tags: string[];\n tagCounts: Record<string, number>;\n value?: string;\n select: (tag?: string) => void;\n};\n\nexport type KeepTagFilterProps<TMeta = Record<string, unknown>> = Omit<\n HTMLAttributes<HTMLElement>,\n \"children\" | \"onChange\"\n> & {\n query?: KeepListQuery<TMeta>;\n value?: string;\n defaultValue?: string;\n onChange?: (tag?: string) => void;\n onValueChange?: (tag?: string) => void;\n allLabel?: ReactNode;\n ariaLabel?: string;\n renderTag?: (tag: string, count: number, selected: boolean) => ReactNode;\n render?: RenderProp<KeepTagFilterState>;\n children?: ReactNode | RenderProp<KeepTagFilterState>;\n asChild?: boolean;\n};\n\n/** An ARIA button group for tag filtering; consumers can connect value to a collection query. */\nexport function KeepTagFilter<TMeta = Record<string, unknown>>({\n query,\n value: controlledValue,\n defaultValue,\n onChange,\n onValueChange,\n allLabel,\n ariaLabel,\n renderTag,\n render,\n children,\n asChild = false,\n className,\n ...rootProps\n}: KeepTagFilterProps<TMeta>) {\n const uiAllLabel = useUiLabel(\"allTags\");\n const uiAriaLabel = useUiLabel(\"filterTags\");\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const resolvedValue = controlledValue ?? uncontrolledValue;\n const list = useKeepList<TMeta>({\n ...query,\n tags: resolvedValue ? [...(query?.tags ?? []), resolvedValue] : query?.tags,\n });\n const select = useCallback(\n (tag?: string) => {\n if (controlledValue === undefined) setUncontrolledValue(tag);\n onChange?.(tag);\n onValueChange?.(tag);\n },\n [controlledValue, onChange, onValueChange],\n );\n const state = useMemo<KeepTagFilterState>(\n () => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),\n [list.tagCounts, list.tags, resolvedValue, select],\n );\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <fieldset>\n <legend>{ariaLabel ?? uiAriaLabel}</legend>\n <button type=\"button\" aria-pressed={resolvedValue === undefined} onClick={() => select()}>\n {allLabel ?? uiAllLabel}\n </button>\n {list.tags.map((tag) => (\n <button key={tag} type=\"button\" aria-pressed={resolvedValue === tag} onClick={() => select(tag)}>\n {renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, resolvedValue === tag) : tag}\n <span> ({list.tagCounts[tag] ?? 0})</span>\n </button>\n ))}\n </fieldset>\n ));\n return renderRoot(\n asChild,\n isValidElement(children) ? children : undefined,\n {\n ...rootProps,\n className,\n \"data-state\": resolvedValue === undefined ? \"all\" : \"filtered\",\n \"data-loading\": list.isLoading ? \"true\" : undefined,\n },\n body,\n \"KeepTagFilter\",\n );\n}\n","\"use client\";\n\nimport type { KeepListQuery } from \"@keepkit/core/core\";\nimport { type InputHTMLAttributes, type ReactNode, type SelectHTMLAttributes, useEffect, useState } from \"react\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepSearchInputProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n value?: string;\n defaultValue?: string;\n /** Delay before notifying consumers; set to 0 to disable debouncing. */\n debounceMs?: number;\n onValueChange?: (value: string) => void;\n};\n\n/** A controlled/uncontrolled search field with a small built-in debounce. */\nexport function KeepSearchInput({\n value: controlledValue,\n defaultValue = \"\",\n debounceMs = 300,\n onValueChange,\n \"aria-label\": ariaLabel,\n placeholder,\n ...props\n}: KeepSearchInputProps) {\n const label = useUiLabel(\"search\");\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n\n useEffect(() => {\n if (!onValueChange) return;\n if (debounceMs <= 0) {\n onValueChange(value);\n return;\n }\n const timer = window.setTimeout(() => onValueChange(value), debounceMs);\n return () => window.clearTimeout(timer);\n }, [debounceMs, onValueChange, value]);\n\n return (\n <input\n {...props}\n type=\"search\"\n value={value}\n data-state={value ? \"active\" : \"idle\"}\n data-disabled={props.disabled ? \"true\" : undefined}\n aria-label={ariaLabel ?? label}\n placeholder={placeholder ?? label}\n onChange={(event) => {\n const nextValue = event.currentTarget.value;\n if (controlledValue === undefined) setUncontrolledValue(nextValue);\n }}\n />\n );\n}\n\nexport type KeepSortValue = \"savedAt:desc\" | \"savedAt:asc\" | \"updatedAt:desc\" | \"updatedAt:asc\";\n\nexport type KeepSortSelectProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n value?: KeepSortValue;\n defaultValue?: KeepSortValue;\n onValueChange?: (value: KeepSortValue, sort: NonNullable<KeepListQuery[\"sort\"]>) => void;\n};\n\n/** Emits a normalized sort descriptor that can be passed directly to useKeepList. */\nexport function KeepSortSelect({\n value: controlledValue,\n defaultValue = \"updatedAt:desc\",\n onValueChange,\n \"aria-label\": ariaLabel,\n children,\n ...props\n}: KeepSortSelectProps) {\n const label = useUiLabel(\"sort\");\n const updatedNewestLabel = useUiLabel(\"updatedNewest\");\n const updatedOldestLabel = useUiLabel(\"updatedOldest\");\n const savedNewestLabel = useUiLabel(\"savedNewest\");\n const savedOldestLabel = useUiLabel(\"savedOldest\");\n const [uncontrolledValue, setUncontrolledValue] = useState<KeepSortValue>(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n const options = children ?? (\n <>\n <option value=\"updatedAt:desc\">{updatedNewestLabel}</option>\n <option value=\"updatedAt:asc\">{updatedOldestLabel}</option>\n <option value=\"savedAt:desc\">{savedNewestLabel}</option>\n <option value=\"savedAt:asc\">{savedOldestLabel}</option>\n </>\n );\n return (\n <select\n {...props}\n value={value}\n data-state=\"selected\"\n data-disabled={props.disabled ? \"true\" : undefined}\n aria-label={ariaLabel ?? label}\n onChange={(event) => {\n const nextValue = event.currentTarget.value as KeepSortValue;\n if (controlledValue === undefined) setUncontrolledValue(nextValue);\n const [by, direction] = nextValue.split(\":\") as [\"savedAt\" | \"updatedAt\", \"asc\" | \"desc\"];\n onValueChange?.(nextValue, { by, direction });\n }}\n >\n {options}\n </select>\n );\n}\n\nexport type KeepPaginationState = { page: number; pageCount: number; goToPage: (page: number) => void };\n\nexport type KeepPaginationProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n totalCount: number;\n pageSize: number;\n page?: number;\n maxPageButtons?: number;\n onPageChange?: (page: number, offset: number) => void;\n render?: (state: KeepPaginationState) => ReactNode;\n};\n\n/** Accessible pagination with previous/next controls and numbered page buttons. */\nexport function KeepPagination({\n totalCount,\n pageSize,\n page = 1,\n maxPageButtons = 7,\n onPageChange,\n render,\n ...props\n}: KeepPaginationProps) {\n const previousPageLabel = useUiLabel(\"previousPage\");\n const nextPageLabel = useUiLabel(\"nextPage\");\n const pageLabel = useUiLabel(\"page\");\n const paginationLabel = useUiLabel(\"pagination\");\n const pageCount = Math.max(1, Math.ceil(totalCount / Math.max(1, pageSize)));\n const currentPage = Math.min(Math.max(1, page), pageCount);\n const goToPage = (nextPage: number) => {\n const next = Math.min(Math.max(1, nextPage), pageCount);\n onPageChange?.(next, (next - 1) * pageSize);\n };\n const navProps = {\n ...props,\n \"aria-label\": props[\"aria-label\"] ?? paginationLabel,\n \"data-state\": pageCount > 1 ? \"active\" : \"idle\",\n };\n if (render) return <nav {...navProps}>{render({ page: currentPage, pageCount, goToPage })}</nav>;\n const visiblePages = getVisiblePages(currentPage, pageCount, Math.max(1, maxPageButtons));\n return (\n <nav {...navProps}>\n <button type=\"button\" onClick={() => goToPage(currentPage - 1)} disabled={currentPage <= 1}>\n {previousPageLabel}\n </button>\n {visiblePages.map((nextPage) => (\n <button\n key={nextPage}\n type=\"button\"\n aria-current={nextPage === currentPage ? \"page\" : undefined}\n aria-label={`${pageLabel} ${nextPage}`}\n onClick={() => goToPage(nextPage)}\n >\n {nextPage}\n </button>\n ))}\n <button type=\"button\" onClick={() => goToPage(currentPage + 1)} disabled={currentPage >= pageCount}>\n {nextPageLabel}\n </button>\n </nav>\n );\n}\n\nfunction getVisiblePages(currentPage: number, pageCount: number, maxPageButtons: number): number[] {\n if (pageCount <= maxPageButtons) return Array.from({ length: pageCount }, (_, index) => index + 1);\n const half = Math.floor(maxPageButtons / 2);\n const start = Math.min(Math.max(1, currentPage - half), pageCount - maxPageButtons + 1);\n return Array.from({ length: maxPageButtons }, (_, index) => start + index);\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport { useKeepItem } from \"@keepkit/core/react\";\nimport {\n type FormHTMLAttributes,\n isValidElement,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { type RenderProp, renderRoot } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepNoteEditorState<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta>;\n note: string;\n setNote: (note: string) => void;\n isDirty: boolean;\n isSaving: boolean;\n error: unknown | null;\n save: () => Promise<void>;\n};\n\nexport type KeepNoteEditorProps<TMeta = Record<string, unknown>> = Omit<\n FormHTMLAttributes<HTMLFormElement>,\n \"children\" | \"onSubmit\"\n> & {\n item: KeepItem<TMeta>;\n label?: ReactNode;\n saveLabel?: ReactNode;\n placeholder?: string;\n /** Automatically save dirty notes after this delay; set to 0 to disable auto-save. */\n debounceMs?: number;\n onSaved?: (note?: string) => void;\n onSaveError?: (error: unknown) => void;\n render?: RenderProp<KeepNoteEditorState<TMeta>>;\n children?: ReactNode | RenderProp<KeepNoteEditorState<TMeta>>;\n asChild?: boolean;\n};\n\n/** A controlled-by-default note editor that persists through useKeepItem. */\nexport function KeepNoteEditor<TMeta = Record<string, unknown>>({\n item,\n label,\n saveLabel,\n placeholder,\n debounceMs = 300,\n onSaved,\n onSaveError,\n render,\n children,\n asChild = false,\n className,\n ...formProps\n}: KeepNoteEditorProps<TMeta>) {\n const defaultLabel = useUiLabel(\"note\");\n const defaultSaveLabel = useUiLabel(\"saveNote\");\n const itemState = useKeepItem<TMeta>(item);\n const { error, isMutating, item: savedItem, updateNote } = itemState;\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const [note, setNote] = useState(item.note ?? \"\");\n const baselineNote = savedItem?.note ?? item.note ?? \"\";\n const isDirty = note !== baselineNote;\n const lastSavedNoteRef = useRef<string | undefined>(undefined);\n useEffect(() => setNote(baselineNote), [baselineNote]);\n const save = useCallback(async () => {\n const nextNote = note.trim() || undefined;\n try {\n await updateNote(nextNote);\n lastSavedNoteRef.current = note;\n onSaved?.(nextNote);\n } catch (error) {\n onSaveError?.(error);\n throw error;\n }\n }, [note, onSaveError, onSaved, updateNote]);\n useEffect(() => {\n if (!isDirty || debounceMs <= 0 || lastSavedNoteRef.current === note) return;\n const timer = window.setTimeout(() => void save().catch(() => undefined), debounceMs);\n return () => window.clearTimeout(timer);\n }, [debounceMs, isDirty, note, save]);\n const state: KeepNoteEditorState<TMeta> = {\n item,\n note,\n setNote,\n isDirty,\n isSaving: isMutating,\n error,\n save,\n };\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <>\n <label>\n {label ?? defaultLabel}\n <textarea\n value={note}\n onChange={(event) => setNote(event.currentTarget.value)}\n placeholder={placeholder}\n disabled={isMutating}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && (event.ctrlKey || event.metaKey)) {\n event.preventDefault();\n void save().catch(() => undefined);\n }\n }}\n />\n </label>\n <button type=\"submit\" disabled={isMutating} aria-busy={isMutating}>\n {saveLabel ?? defaultSaveLabel}\n </button>\n </>\n ));\n const handleSubmit: FormHTMLAttributes<HTMLFormElement>[\"onSubmit\"] = (event) => {\n event.preventDefault();\n void save().catch(() => undefined);\n };\n if (!asChild) {\n return (\n <form\n {...formProps}\n className={className}\n onSubmit={handleSubmit}\n aria-busy={isMutating || formProps[\"aria-busy\"]}\n data-state={isDirty ? \"dirty\" : \"clean\"}\n data-loading={isMutating ? \"true\" : undefined}\n data-disabled={isMutating ? \"true\" : undefined}\n >\n {body}\n </form>\n );\n }\n return renderRoot(\n true,\n isValidElement(children) ? children : undefined,\n {\n ...formProps,\n className,\n onSubmit: handleSubmit,\n \"aria-busy\": isMutating || formProps[\"aria-busy\"],\n \"data-state\": isDirty ? \"dirty\" : \"clean\",\n \"data-loading\": isMutating ? \"true\" : undefined,\n \"data-disabled\": isMutating ? \"true\" : undefined,\n },\n body,\n \"KeepNoteEditor\",\n );\n}\n","\"use client\";\n\nimport type { KeepItem } from \"@keepkit/core/core\";\nimport { useKeepItem } from \"@keepkit/core/react\";\nimport { type FormHTMLAttributes, useCallback, useEffect, useState } from \"react\";\nimport { normalizeUiTags, type RenderProp } from \"./shared\";\nimport { useUiLabel } from \"./ui-context\";\n\nexport type KeepTagEditorState = {\n tags: string[];\n setTags: (tags: string[]) => void;\n save: () => Promise<void>;\n isSaving: boolean;\n};\n\nexport type KeepTagEditorProps<TMeta = Record<string, unknown>> = Omit<\n FormHTMLAttributes<HTMLFormElement>,\n \"children\" | \"onSubmit\"\n> & {\n item: KeepItem<TMeta>;\n availableTags?: string[];\n onSaved?: (tags?: string[]) => void;\n onSaveError?: (error: unknown) => void;\n render?: RenderProp<KeepTagEditorState>;\n};\n\n/** Edits one item's normalized tag set; Enter adds and Backspace removes the last tag. */\nexport function KeepTagEditor<TMeta = Record<string, unknown>>({\n item,\n availableTags = [],\n onSaved,\n onSaveError,\n render,\n ...props\n}: KeepTagEditorProps<TMeta>) {\n const tagsLabel = useUiLabel(\"tagsToApply\");\n const removeLabel = useUiLabel(\"remove\");\n const applyTagsLabel = useUiLabel(\"applyTags\");\n const itemState = useKeepItem<TMeta>(item);\n const [tags, setTags] = useState(item.tags ?? []);\n const [input, setInput] = useState(\"\");\n useEffect(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);\n const save = useCallback(async () => {\n const nextTags = normalizeUiTags(tags);\n try {\n await itemState.updateTags(nextTags);\n setTags(nextTags);\n onSaved?.(nextTags);\n } catch (error) {\n onSaveError?.(error);\n throw error;\n }\n }, [itemState, onSaveError, onSaved, tags]);\n const addTag = (tag: string) => {\n setTags(normalizeUiTags([...tags, tag]));\n setInput(\"\");\n };\n const body = render ? (\n render({ tags, setTags, save, isSaving: itemState.isMutating })\n ) : (\n <>\n <label>\n {tagsLabel}\n <input\n value={input}\n list={availableTags.length > 0 ? `keep-tags-${item.id}` : undefined}\n onChange={(event) => setInput(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n if (event.nativeEvent.isComposing) return;\n event.preventDefault();\n if (input.trim()) addTag(input);\n } else if (event.key === \"Backspace\" && input.length === 0 && tags.length > 0) {\n event.preventDefault();\n setTags(tags.slice(0, -1));\n }\n }}\n />\n </label>\n {availableTags.length > 0 ? (\n <datalist id={`keep-tags-${item.id}`}>\n {availableTags.map((tag) => (\n <option key={tag} value={tag} />\n ))}\n </datalist>\n ) : null}\n <ul aria-label={tagsLabel}>\n {tags.map((tag) => (\n <li key={tag}>\n {tag}\n <button type=\"button\" onClick={() => setTags(tags.filter((current) => current !== tag))}>\n {removeLabel}\n </button>\n </li>\n ))}\n </ul>\n <button type=\"submit\" disabled={itemState.isMutating} aria-busy={itemState.isMutating}>\n {applyTagsLabel}\n </button>\n </>\n );\n return (\n <form\n {...props}\n onSubmit={(event) => {\n event.preventDefault();\n void save().catch(() => undefined);\n }}\n aria-busy={itemState.isMutating || props[\"aria-busy\"]}\n data-state={itemState.isMutating ? \"saving\" : \"idle\"}\n data-loading={itemState.isMutating ? \"true\" : undefined}\n data-disabled={itemState.isMutating ? \"true\" : undefined}\n >\n {body}\n </form>\n );\n}\n","\"use client\";\n\nimport type { KeepChangeContext, KeepItem } from \"@keepkit/core/core\";\nimport { useKeepContext } from \"@keepkit/core/react\";\nimport { type HTMLAttributes, isValidElement, type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { type RenderProp, renderRoot } from \"./shared\";\nimport { type KeepUiLabelKey, useUiLabel } from \"./ui-context\";\n\nexport type KeepEmptyStateProps = Omit<HTMLAttributes<HTMLElement>, \"children\" | \"title\"> & {\n title?: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n children?: ReactNode;\n asChild?: boolean;\n};\n\n/** A style-free, reusable empty collection state. */\nexport function KeepEmptyState({\n title,\n description,\n action,\n children,\n asChild = false,\n className,\n ...rootProps\n}: KeepEmptyStateProps) {\n const defaultTitle = useUiLabel(\"noItems\").replace(/\\.$/, \"\");\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const body = contentChildren ?? (\n <>\n <h2>{title ?? defaultTitle}</h2>\n {description ? <p>{description}</p> : null}\n {action}\n </>\n );\n return renderRoot(asChild, children, { ...rootProps, className, \"data-state\": \"empty\" }, body, \"KeepEmptyState\");\n}\n\nexport type KeepStatusValue = \"idle\" | \"empty\" | \"loading\" | \"saving\" | \"syncing\" | \"error\";\nexport type KeepStatusLabels = Partial<Record<KeepStatusValue, ReactNode>>;\n\nexport type KeepStatusState<TMeta = Record<string, unknown>> = {\n status: KeepStatusValue;\n error: unknown | null;\n pendingCount: number;\n items: KeepItem<TMeta>[];\n};\n\nexport type KeepStatusProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n status?: KeepStatusValue;\n labels?: KeepStatusLabels;\n children?: ReactNode | RenderProp<KeepStatusState<TMeta>>;\n render?: RenderProp<KeepStatusState<TMeta>>;\n asChild?: boolean;\n};\n\n/** Presents provider loading, mutation, synchronization, empty, and error states accessibly. */\nexport function KeepStatus<TMeta = Record<string, unknown>>({\n status,\n labels,\n children,\n render,\n asChild = false,\n className,\n ...rootProps\n}: KeepStatusProps<TMeta>) {\n const context = useKeepContext<TMeta>();\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const resolvedStatus = status ?? getDerivedStatus(context);\n const defaultLabel = useUiLabel(getStatusLabelKey(resolvedStatus));\n const state: KeepStatusState<TMeta> = {\n status: resolvedStatus,\n error: context.error,\n pendingCount: context.syncState.pendingCount,\n items: context.items,\n };\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? labels?.[resolvedStatus] ?? defaultLabel);\n const role = rootProps.role ?? (resolvedStatus === \"error\" ? \"alert\" : \"status\");\n return renderRoot(\n asChild,\n isValidElement(children) ? children : undefined,\n {\n ...rootProps,\n className,\n role,\n \"aria-live\": rootProps[\"aria-live\"] ?? \"polite\",\n \"data-state\": resolvedStatus,\n \"data-loading\":\n resolvedStatus === \"loading\" || resolvedStatus === \"saving\" || resolvedStatus === \"syncing\"\n ? \"true\"\n : undefined,\n },\n body,\n \"KeepStatus\",\n );\n}\n\nexport type KeepAnnouncementsProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n messages?: Partial<Record<\"save\" | \"remove\" | \"note\", string>>;\n};\n\n/** Announces successful save, remove, and note operations in a polite live region. */\nexport function KeepAnnouncements<TMeta = Record<string, unknown>>({ messages, ...props }: KeepAnnouncementsProps) {\n const context = useKeepContext<TMeta>();\n const savedMessage = useUiLabel(\"savedMessage\", messages?.save);\n const removedMessage = useUiLabel(\"removedMessage\", messages?.remove);\n const noteSavedMessage = useUiLabel(\"noteSavedMessage\", messages?.note);\n const [message, setMessage] = useState(\"\");\n const lastChangeRef = useRef<KeepChangeContext<TMeta> | undefined>(undefined);\n useEffect(() => {\n const change = context.lastChange;\n if (!change || change === lastChangeRef.current) return;\n lastChangeRef.current = change;\n if (change.action === \"save\") setMessage(savedMessage);\n else if (change.action === \"remove\" || change.action === \"removeBatch\") setMessage(removedMessage);\n else if (change.action === \"updateNote\") setMessage(noteSavedMessage);\n }, [context.lastChange, noteSavedMessage, removedMessage, savedMessage]);\n return (\n <div\n {...props}\n role={props.role ?? \"status\"}\n aria-live={props[\"aria-live\"] ?? \"polite\"}\n aria-atomic=\"true\"\n data-state=\"announcing\"\n >\n {message}\n </div>\n );\n}\n\n/** Singular alias for applications that mount one announcer explicitly. */\nexport const KeepAnnouncer = KeepAnnouncements;\n\nfunction getDerivedStatus<TMeta>(context: ReturnType<typeof useKeepContext<TMeta>>): KeepStatusValue {\n if (context.error) return \"error\";\n if (context.syncState.status === \"pending\" || context.syncState.status === \"syncing\") return \"syncing\";\n if (context.isMutating) return \"saving\";\n if (context.isLoading && !context.isHydrated) return \"loading\";\n if (context.isHydrated && context.items.length === 0) return \"empty\";\n return \"idle\";\n}\n\nfunction getStatusLabelKey(status: KeepStatusValue): KeepUiLabelKey {\n if (status === \"empty\") return \"noItems\";\n if (status === \"loading\") return \"loadingItems\";\n if (status === \"error\") return \"error\";\n if (status === \"saving\") return \"saving\";\n if (status === \"syncing\") return \"syncing\";\n return \"saved\";\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","Fragment","jsx","KeepErrorBoundary","useKeepList","useMemo","useState","useKeepList","isValidElement","useKeepItem","isValidElement","Fragment","jsx","jsxs","useKeepItem","isValidElement","jsx","useKeepList","isValidElement","useKeepList","isValidElement","useMemo","useState","jsx","jsxs","useState","useKeepList","useMemo","isValidElement","useState","Fragment","jsx","jsxs","useState","jsx","jsxs","KeepErrorBoundary","useState","useMemo","useKeepList","useKeepItem","isValidElement","useCallback","useEffect","useState","Fragment","jsx","jsxs","useKeepItem","isValidElement","useState","useEffect","useCallback","error","useKeepItem","useCallback","useEffect","useState","Fragment","jsx","jsxs","useKeepItem","useState","useEffect","useCallback","isValidElement","useEffect","useRef","useState","Fragment","jsx","jsxs","isValidElement","useState","useRef","useEffect","KeepErrorBoundary","useKeepContext","useKeepItem","useKeepList","jsx","jsxs","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keepkit/ui",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Headless, accessible React UI components for KeepKit.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "react": ">=18"
31
31
  },
32
32
  "dependencies": {
33
- "@keepkit/core": "0.8.0"
33
+ "@keepkit/core": "0.9.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@testing-library/react": "^16.3.3",