@keepkit/ui 0.4.0 → 0.5.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
@@ -4,76 +4,85 @@
4
4
 
5
5
  ## 日本語
6
6
 
7
- `@keepkit/core` の保存状態を、アプリ固有のCSSやUIライブラリに接続するための、低依存・スタイルレスなReact UIパーツです。Tailwind CSS、shadcn/ui、その他のデザインシステムには依存しません。
7
+ Reactアプリケーション向けの標準利用パッケージです。`@keepkit/core`を内包し、Provider、保存ボタン、検索・ソート・ページング付きの一覧を少ないコードで構成できます。
8
8
 
9
9
  ```bash
10
- pnpm add @keepkit/core @keepkit/ui
10
+ pnpm add @keepkit/ui
11
11
  ```
12
12
 
13
13
  ```tsx
14
- import { KeepList, KeepProvider, KeepTagFilter } from "@keepkit/ui";
14
+ import { createBrowserStorageAdapter, createKeepKit } from "@keepkit/ui";
15
15
 
16
- function SavedItems() {
16
+ type ArticleMeta = { title: string; url: string };
17
+ const keep = createKeepKit<ArticleMeta>({
18
+ storage: createBrowserStorageAdapter({ key: "articles" }),
19
+ locale: "ja-JP",
20
+ labels: { save: "保存", remove: "削除" },
21
+ });
22
+
23
+ function SavedArticles() {
17
24
  return (
18
- <KeepProvider>
19
- <KeepTagFilter value={selectedTag} onValueChange={setSelectedTag} />
20
- <KeepList options={{ tag: selectedTag }} />
21
- </KeepProvider>
25
+ <keep.Provider>
26
+ <keep.Collection
27
+ query={{ targetType: "article" }}
28
+ renderItem={(item) => <keep.Button item={{ id: item.id, targetType: item.targetType, meta: item.meta }} />}
29
+ />
30
+ </keep.Provider>
22
31
  );
23
32
  }
24
33
  ```
25
34
 
26
- 提供するコンポーネントは次のとおりです。
35
+ `keep.Collection`は検索、ソート、ページング、loading / empty / error、ARIA live通知を標準で提供します。`features={{ tagFilter: true, bulkActions: true }}`でタグフィルターと一括操作も有効にできます。個別の`KeepList`、`KeepSearchInput`、`KeepSortSelect`、`KeepPagination`などは高度なレイアウト用に利用できます。
27
36
 
28
- - `KeepButton`: 保存済み状態、`aria-pressed`、ローディング・エラー状態、`asChild`、render props。`labels` または既存の `savedAriaLabel` / `unsavedAriaLabel` で翻訳できます。
29
- - `KeepList`: 保存一覧、読み込み中・空・エラー状態、標準カード、削除操作。`renderItem` で行単位を置き換えられます。
30
- - `KeepItemCard`: タイトル、画像、保存ボタン、削除ボタン。`getImageProps`、`imageComponent`、`renderImage` とrender propsで表示を差し替えられます。
31
- - `KeepTagFilter`: タグと件数を表示するキーボード操作可能なフィルター。`value` / `onValueChange` のcontrolled APIに対応します。
32
- - `KeepNoteEditor`: ノートの編集・保存フォーム。`render` で完全なカスタムUIにできます。
33
- - `KeepSearchInput` / `KeepSortSelect` / `KeepPagination`: `useKeepList` に渡す検索、ソート、offsetページング用のプリミティブ。
34
- - `KeepTagEditor` / `KeepBulkActions`: タグ編集、複数選択、一括削除、一括タグ更新。
35
- - `KeepUiProvider`: `labels`、`locale`、`labelResolver` をUI全体に適用するラベルコンテキスト。
36
- - `KeepAnnouncements`: 保存、削除、ノート保存の成功を `aria-live` で通知します。
37
- - `KeepEmptyState` / `KeepStatus`: 空、読み込み中、保存中、同期中、エラー状態の表示。
37
+ 一覧のqueryは次の形式に統一されています。
38
38
 
39
- すべてのルート要素で `className` を利用でき、対応コンポーネントでは `asChild` で既存要素をルートとして利用できます。コンポーネントの標準HTMLは意味的な要素、ネイティブボタン、フォーム、`aria-live` を利用します。
39
+ ```tsx
40
+ const query = {
41
+ targetType: "article",
42
+ tags: ["read"],
43
+ search: { query: "react", mode: "and" as const },
44
+ sort: { by: "updatedAt" as const, direction: "desc" as const },
45
+ pagination: { page: 1, pageSize: 20 },
46
+ };
47
+ ```
40
48
 
41
- ### カスタマイズ契約
49
+ 保存操作にはID付きの最小入力を渡します。保存・更新時刻はKeepKitが管理します。
42
50
 
43
- - `render` / render props はstateを受け取り、標準内部マークアップを置き換えます。`KeepList.renderItem` は各アイテムだけを置き換えます。
44
- - `KeepItemCard` の画像は `getImageProps` `src`、`alt`、`width`、`height`、`srcSet` を作り、`imageComponent` または `renderImage` で描画します。
45
- - `asChild` は単一のReact要素を必要とし、ルート要素だけを置き換えます。内部のアクセシビリティ属性とイベントは保持してください。
46
- - 標準構造は `KeepList` が `div > ul > li`、`KeepTagFilter` が `fieldset`、`KeepNoteEditor` が `form`、一括操作が `section > fieldset` です。
47
- - CSSはルートと渡された標準要素の `className` に適用します。コンポーネントはstyleを持ちません。
48
- - `onClick`、`onSubmit`、`onChange` は利用者のハンドラーを先に実行し、`preventDefault()` された場合は既定操作を実行しません。
51
+ ```tsx
52
+ const article = { id: "article-123", targetType: "article", meta: { title, url } };
53
+ const item = keep.useItem(article);
54
+ ```
49
55
 
50
- ラベルと画像の拡張ポイントは `KeepUiProvider` と `getImageProps`/`imageComponent`/`renderImage` に集約しています。既存の個別label propsも明示的な上書き用途として利用できます。
56
+ 高度なフレームワーク中立APIは`@keepkit/core/core`、低レベルのReact APIは`@keepkit/core/react`、ストレージ実装は`@keepkit/core/storage`から利用できます。
51
57
 
52
58
  ## English
53
59
 
54
- `@keepkit/ui` provides low-dependency, style-free React UI primitives that connect `@keepkit/core` state to an app's own CSS or design system. It has no direct dependency on Tailwind CSS, shadcn/ui, or another component library.
60
+ The standard React package for KeepKit. It includes `@keepkit/core` and provides a single typed provider, save button, and searchable/sortable/paginated collection workflow.
55
61
 
56
62
  ```bash
57
- pnpm add @keepkit/core @keepkit/ui
63
+ pnpm add @keepkit/ui
58
64
  ```
59
65
 
60
66
  ```tsx
61
- import { KeepList, KeepProvider, KeepTagFilter } from "@keepkit/ui";
67
+ import { createBrowserStorageAdapter, createKeepKit } from "@keepkit/ui";
68
+
69
+ type ArticleMeta = { title: string; url: string };
70
+ const keep = createKeepKit<ArticleMeta>({
71
+ storage: createBrowserStorageAdapter({ key: "articles" }),
72
+ labels: { save: "Save", remove: "Remove" },
73
+ });
62
74
 
63
- function SavedItems() {
75
+ function SavedArticles() {
64
76
  return (
65
- <KeepProvider>
66
- <KeepTagFilter value={selectedTag} onValueChange={setSelectedTag} />
67
- <KeepList options={{ tag: selectedTag }} />
68
- </KeepProvider>
77
+ <keep.Provider>
78
+ <keep.Collection query={{ targetType: "article" }} />
79
+ </keep.Provider>
69
80
  );
70
81
  }
71
82
  ```
72
83
 
73
- Components include `KeepButton`, `KeepList`, `KeepItemCard`, `KeepTagFilter`, `KeepNoteEditor`, `KeepEmptyState`, and `KeepStatus`. They support `className`, render props, localized labels, and `asChild` where a root element can be replaced. The defaults use semantic HTML, native keyboard behavior, `aria-pressed`, and live-region status announcements. `KeepList` includes loading, empty, error, and removal states, while `KeepTagFilter` exposes controlled `value` / `onValueChange` state.
74
-
75
- The package also exports `KeepSearchInput`, `KeepSortSelect`, `KeepPagination`, `KeepTagEditor`, `KeepBulkActions`, `KeepUiProvider`, and `KeepAnnouncements`. Configure labels once with `KeepUiProvider`, replace card images with `getImageProps` plus `imageComponent` or `renderImage`, and use `KeepAnnouncements` for success messages in a polite live region.
84
+ `keep.Collection` includes search, sorting, pagination, loading/empty/error states, and polite live announcements. Enable `features={{ tagFilter: true, bulkActions: true }}` for tag filtering and bulk operations. Use the individual `KeepList`, `KeepSearchInput`, `KeepSortSelect`, and `KeepPagination` primitives when you need a custom layout.
76
85
 
77
- Customization is explicit: render props replace component markup, `KeepList.renderItem` replaces one item, `asChild` replaces only a single root element, and standard HTML structure is stable (`div > ul > li`, `fieldset`, `form`, and `section > fieldset`). User handlers run before default behavior and `preventDefault()` cancels it. The old URL-only image entry point is replaced by the structured image API; app-wide labels belong in `KeepUiProvider`.
86
+ Collection queries use one canonical shape: `targetType`, `tags`, `search`, `sort`, `pagination`, `filter`, and `savedBetween`. Saved item inputs contain only `id`, `meta`, `targetType`, `note`, and `tags`; KeepKit owns persistence timestamps.
78
87
 
79
- The package re-exports `KeepProvider` and the core React hooks for convenient composition. The state and storage implementation remains in `@keepkit/core`; this package only adds the UI layer. Existing component label props remain available as explicit overrides, while app-wide defaults belong in `KeepUiProvider`.
88
+ Framework-neutral APIs remain available from `@keepkit/core/core`, low-level React bindings from `@keepkit/core/react`, and storage adapters from `@keepkit/core/storage`.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as react from 'react';
2
- import { HTMLAttributes, ReactNode, ReactElement, ImgHTMLAttributes, ComponentType, FormHTMLAttributes, InputHTMLAttributes, SelectHTMLAttributes } from 'react';
3
- import { KeepListOptions, KeepItem } from '@keepkit/core/core';
4
- export { KeepItem, KeepItemInput, KeepListOptions, KeepSyncStatus } from '@keepkit/core/core';
5
- import { KeepButtonProps as KeepButtonProps$1, UseKeepListResult } from '@keepkit/core/react';
6
- export { KeepContextValue, KeepProvider, KeepProviderProps, useKeepContext, useKeepItem, useKeepList } from '@keepkit/core/react';
2
+ import { ReactNode, ImgHTMLAttributes, HTMLAttributes, ComponentType, ReactElement, FormHTMLAttributes, InputHTMLAttributes, SelectHTMLAttributes } from 'react';
3
+ import { KeepItem, KeepListQuery, KeepItemInput } from '@keepkit/core/core';
4
+ export { KeepItem, KeepItemInput, KeepListQuery, KeepSyncStatus } from '@keepkit/core/core';
5
+ import { CreateKeepKitOptions as CreateKeepKitOptions$1, KeepButtonProps as KeepButtonProps$1, UseKeepListResult, KeepProviderProps, useKeepContext, useKeepItem, KeepShortcutOptions } from '@keepkit/core/react';
6
+ export { KeepContextValue, KeepProvider, KeepProviderProps, KeepShortcutOptions, useKeepContext, useKeepItem, useKeepList, useKeepShortcut } from '@keepkit/core/react';
7
+ export { FallbackStorageAdapter, IndexedDBAdapter, IndexedDBSyncQueueAdapter, LocalStorageAdapter, LocalStorageSyncQueueAdapter, SyncStorageAdapter, createBrowserStorageAdapter, createStorageAdapter } from '@keepkit/core/storage';
7
8
 
8
9
  type KeepUiLabelKey = "save" | "saved" | "remove" | "loading" | "saving" | "syncing" | "error" | "allTags" | "filterTags" | "note" | "saveNote" | "noItems" | "loadingItems" | "errorItems" | "search" | "sort" | "newest" | "oldest" | "previousPage" | "nextPage" | "pagination" | "page" | "selectItems" | "selectedCount" | "deleteSelected" | "tagsToApply" | "applyTags" | "savedMessage" | "removedMessage" | "noteSavedMessage";
9
10
  type KeepUiLabels = Partial<Record<KeepUiLabelKey, string>>;
@@ -22,8 +23,28 @@ type KeepUiProviderProps = {
22
23
  };
23
24
  /** Provides one locale-aware label source to every UI primitive. */
24
25
  declare function KeepUiProvider({ labels, locale, labelResolver, children }: KeepUiProviderProps): react.JSX.Element;
26
+ type KeepKitProviderProps<TMeta = Record<string, unknown>> = Omit<KeepProviderProps<TMeta>, "children"> & Omit<KeepUiProviderProps, "children"> & {
27
+ children?: ReactNode;
28
+ };
29
+ /** Combines the core store and UI labels into the default application provider. */
30
+ declare function KeepKitProvider<TMeta = Record<string, unknown>>({ labels, locale, labelResolver, children, ...providerProps }: KeepKitProviderProps<TMeta>): react.JSX.Element;
25
31
  declare function useKeepUiLabels(): KeepUiLabelContext;
26
32
 
33
+ type CreateKeepKitOptions<TMeta = Record<string, unknown>> = CreateKeepKitOptions$1<TMeta> & Omit<KeepUiProviderProps, "children"> & {
34
+ getTitle?: (item: KeepItem<TMeta>) => ReactNode;
35
+ getImageProps?: (item: KeepItem<TMeta>, title: ReactNode) => KeepImageProps | undefined;
36
+ };
37
+ type KeepKit<TMeta = Record<string, unknown>> = {
38
+ Provider: ComponentType<KeepKitProviderProps<TMeta>>;
39
+ Button: ComponentType<KeepButtonProps<TMeta>>;
40
+ Collection: ComponentType<KeepCollectionProps<TMeta>>;
41
+ useContext: () => ReturnType<typeof useKeepContext<TMeta>>;
42
+ useItem: (item?: KeepItemInput<TMeta>) => ReturnType<typeof useKeepItem<TMeta>>;
43
+ useList: (query?: KeepListQuery<TMeta>) => UseKeepListResult<TMeta>;
44
+ useShortcut: (options: KeepShortcutOptions<TMeta>) => void;
45
+ };
46
+ /** Create one typed application API for the core and the standard UI layer. */
47
+ declare function createKeepKit<TMeta = Record<string, unknown>>(options?: CreateKeepKitOptions<TMeta>): KeepKit<TMeta>;
27
48
  type RenderProp<TState> = (state: TState) => ReactNode;
28
49
  type KeepButtonLabels = {
29
50
  saved?: ReactNode;
@@ -52,6 +73,7 @@ type KeepImageProps = ImgHTMLAttributes<HTMLImageElement> & {
52
73
  type KeepItemCardProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & {
53
74
  item: KeepItem<TMeta>;
54
75
  title?: ReactNode | ((item: KeepItem<TMeta>) => ReactNode);
76
+ getTitle?: (item: KeepItem<TMeta>) => ReactNode;
55
77
  getImageProps?: (item: KeepItem<TMeta>, title: ReactNode) => KeepImageProps | undefined;
56
78
  imageComponent?: ComponentType<KeepImageProps>;
57
79
  renderImage?: (props: KeepImageProps, item: KeepItem<TMeta>) => ReactNode;
@@ -66,10 +88,10 @@ type KeepItemCardProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HT
66
88
  asChild?: boolean;
67
89
  };
68
90
  /** A low-dependency item presentation primitive. The default markup can be replaced with render props. */
69
- declare function KeepItemCard<TMeta = Record<string, unknown>>({ item, title, getImageProps, imageComponent: ImageComponent, renderImage, imageAlt, render, children, removeLabel, onRemoveError, onRemoved, showSaveButton, saveButtonLabels, asChild, className, ...rootProps }: KeepItemCardProps<TMeta>): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
91
+ declare function KeepItemCard<TMeta = Record<string, unknown>>({ item, title, getTitle, getImageProps, imageComponent: ImageComponent, renderImage, imageAlt, render, children, removeLabel, onRemoveError, onRemoved, showSaveButton, saveButtonLabels, asChild, className, ...rootProps }: KeepItemCardProps<TMeta>): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
70
92
  type KeepListState<TMeta = Record<string, unknown>> = UseKeepListResult<TMeta>;
71
93
  type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
72
- options?: KeepListOptions<TMeta>;
94
+ query?: KeepListQuery<TMeta>;
73
95
  children?: ReactNode | RenderProp<KeepListState<TMeta>>;
74
96
  renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;
75
97
  loading?: ReactNode | RenderProp<KeepListState<TMeta>>;
@@ -79,7 +101,20 @@ type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLEl
79
101
  asChild?: boolean;
80
102
  };
81
103
  /** A list primitive with built-in loading, empty, error, and removal states. */
82
- declare function KeepList<TMeta = Record<string, unknown>>({ options, children, renderItem, loading, empty, error: errorContent, itemCardProps, asChild, className, ...rootProps }: KeepListProps<TMeta>): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
104
+ declare function KeepList<TMeta = Record<string, unknown>>({ query, children, renderItem, loading, empty, error: errorContent, itemCardProps, asChild, className, ...rootProps }: KeepListProps<TMeta>): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
105
+ type KeepCollectionFeature = "search" | "sort" | "pagination" | "tagFilter" | "bulkActions";
106
+ type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
107
+ query?: KeepListQuery<TMeta>;
108
+ pageSize?: number;
109
+ features?: Partial<Record<KeepCollectionFeature, boolean>>;
110
+ renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;
111
+ itemCardProps?: Omit<KeepItemCardProps<TMeta>, "item" | "children" | "render">;
112
+ loading?: ReactNode | RenderProp<KeepListState<TMeta>>;
113
+ empty?: ReactNode | RenderProp<KeepListState<TMeta>>;
114
+ error?: ReactNode | RenderProp<KeepListState<TMeta>>;
115
+ };
116
+ /** A batteries-included collection with query controls and accessible status feedback. */
117
+ declare function KeepCollection<TMeta = Record<string, unknown>>({ query, pageSize, features, renderItem, itemCardProps, loading, empty, error, className, ...rootProps }: KeepCollectionProps<TMeta>): react.JSX.Element;
83
118
  type KeepTagFilterState = {
84
119
  tags: string[];
85
120
  tagCounts: Record<string, number>;
@@ -87,7 +122,7 @@ type KeepTagFilterState = {
87
122
  select: (tag?: string) => void;
88
123
  };
89
124
  type KeepTagFilterProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "onChange"> & {
90
- listOptions?: KeepListOptions<TMeta>;
125
+ query?: KeepListQuery<TMeta>;
91
126
  value?: string;
92
127
  defaultValue?: string;
93
128
  onChange?: (tag?: string) => void;
@@ -99,8 +134,8 @@ type KeepTagFilterProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<H
99
134
  children?: ReactNode | RenderProp<KeepTagFilterState>;
100
135
  asChild?: boolean;
101
136
  };
102
- /** An ARIA button group for tag filtering; consumers can connect value to KeepList options. */
103
- declare function KeepTagFilter<TMeta = Record<string, unknown>>({ listOptions, value: controlledValue, defaultValue, onChange, onValueChange, allLabel, ariaLabel, renderTag, render, children, asChild, className, ...rootProps }: KeepTagFilterProps<TMeta>): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
137
+ /** An ARIA button group for tag filtering; consumers can connect value to a collection query. */
138
+ declare function KeepTagFilter<TMeta = Record<string, unknown>>({ query, value: controlledValue, defaultValue, onChange, onValueChange, allLabel, ariaLabel, renderTag, render, children, asChild, className, ...rootProps }: KeepTagFilterProps<TMeta>): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
104
139
  type KeepNoteEditorState<TMeta = Record<string, unknown>> = {
105
140
  item: KeepItem<TMeta>;
106
141
  note: string;
@@ -128,13 +163,13 @@ type KeepSearchInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "value"
128
163
  defaultValue?: string;
129
164
  onValueChange?: (value: string) => void;
130
165
  };
131
- /** A controlled/uncontrolled search field for wiring into useKeepList.searchQuery. */
166
+ /** A controlled/uncontrolled search field for wiring into KeepListQuery.search. */
132
167
  declare function KeepSearchInput({ value: controlledValue, defaultValue, onValueChange, "aria-label": ariaLabel, placeholder, ...props }: KeepSearchInputProps): react.JSX.Element;
133
168
  type KeepSortValue = "savedAt:desc" | "savedAt:asc" | "updatedAt:desc" | "updatedAt:asc";
134
169
  type KeepSortSelectProps = Omit<SelectHTMLAttributes<HTMLSelectElement>, "value" | "defaultValue" | "onChange"> & {
135
170
  value?: KeepSortValue;
136
171
  defaultValue?: KeepSortValue;
137
- onValueChange?: (value: KeepSortValue, sort: NonNullable<KeepListOptions["sort"]>) => void;
172
+ onValueChange?: (value: KeepSortValue, sort: NonNullable<KeepListQuery["sort"]>) => void;
138
173
  };
139
174
  /** Emits a normalized sort descriptor that can be passed directly to useKeepList. */
140
175
  declare function KeepSortSelect({ value: controlledValue, defaultValue, onValueChange, "aria-label": ariaLabel, children, ...props }: KeepSortSelectProps): react.JSX.Element;
@@ -166,7 +201,7 @@ type KeepTagEditorProps<TMeta = Record<string, unknown>> = Omit<FormHTMLAttribut
166
201
  /** Edits one item's normalized tag set and exposes a render-prop escape hatch. */
167
202
  declare function KeepTagEditor<TMeta = Record<string, unknown>>({ item, availableTags, onSaved, onSaveError, render, ...props }: KeepTagEditorProps<TMeta>): react.JSX.Element;
168
203
  type KeepBulkActionsProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
169
- listOptions?: KeepListOptions<TMeta>;
204
+ query?: KeepListQuery<TMeta>;
170
205
  selectedIds?: string[];
171
206
  defaultSelectedIds?: string[];
172
207
  onSelectedIdsChange?: (ids: string[]) => void;
@@ -174,7 +209,7 @@ type KeepBulkActionsProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes
174
209
  onCompleted?: (action: "remove" | "tags", ids: string[]) => void;
175
210
  };
176
211
  /** Selects visible items and performs one storage operation for the whole selection. */
177
- declare function KeepBulkActions<TMeta = Record<string, unknown>>({ listOptions, selectedIds: controlledSelectedIds, defaultSelectedIds, onSelectedIdsChange, renderItem, onCompleted, ...props }: KeepBulkActionsProps<TMeta>): react.JSX.Element;
212
+ declare function KeepBulkActions<TMeta = Record<string, unknown>>({ query, selectedIds: controlledSelectedIds, defaultSelectedIds, onSelectedIdsChange, renderItem, onCompleted, ...props }: KeepBulkActionsProps<TMeta>): react.JSX.Element;
178
213
  type KeepEmptyStateProps = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & {
179
214
  title?: ReactNode;
180
215
  description?: ReactNode;
@@ -207,4 +242,4 @@ type KeepAnnouncementsProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
207
242
  /** Announces successful save, remove, and note operations in a polite live region. */
208
243
  declare function KeepAnnouncements<TMeta = Record<string, unknown>>({ messages, ...props }: KeepAnnouncementsProps): react.JSX.Element;
209
244
 
210
- export { KeepAnnouncements, type KeepAnnouncementsProps, KeepBulkActions, type KeepBulkActionsProps, KeepButton, type KeepButtonLabels, type KeepButtonProps, KeepEmptyState, type KeepEmptyStateProps, type KeepImageProps, KeepItemCard, type KeepItemCardProps, type KeepItemCardState, KeepList, type KeepListProps, type KeepListState, KeepNoteEditor, type KeepNoteEditorProps, type KeepNoteEditorState, KeepPagination, type KeepPaginationProps, KeepSearchInput, type KeepSearchInputProps, KeepSortSelect, type KeepSortSelectProps, type KeepSortValue, KeepStatus, type KeepStatusLabels, type KeepStatusProps, type KeepStatusState, type KeepStatusValue, KeepTagEditor, type KeepTagEditorProps, KeepTagFilter, type KeepTagFilterProps, type KeepTagFilterState, type KeepUiLabelContext, type KeepUiLabelKey, type KeepUiLabels, KeepUiProvider, type KeepUiProviderProps, type RenderProp, useKeepUiLabels };
245
+ export { type CreateKeepKitOptions, KeepAnnouncements, type KeepAnnouncementsProps, KeepBulkActions, type KeepBulkActionsProps, KeepButton, type KeepButtonLabels, type KeepButtonProps, KeepCollection, type KeepCollectionFeature, type KeepCollectionProps, KeepEmptyState, type KeepEmptyStateProps, type KeepImageProps, KeepItemCard, type KeepItemCardProps, type KeepItemCardState, type KeepKit, KeepKitProvider, type KeepKitProviderProps, KeepList, type KeepListProps, type KeepListState, KeepNoteEditor, type KeepNoteEditorProps, type KeepNoteEditorState, KeepPagination, type KeepPaginationProps, KeepSearchInput, type KeepSearchInputProps, KeepSortSelect, type KeepSortSelectProps, type KeepSortValue, KeepStatus, type KeepStatusLabels, type KeepStatusProps, type KeepStatusState, type KeepStatusValue, KeepTagEditor, type KeepTagEditorProps, KeepTagFilter, type KeepTagFilterProps, type KeepTagFilterState, type KeepUiLabelContext, type KeepUiLabelKey, type KeepUiLabels, KeepUiProvider, type KeepUiProviderProps, type RenderProp, createKeepKit, useKeepUiLabels };
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@
3
3
  // src/index.tsx
4
4
  import {
5
5
  KeepButton as CoreKeepButton,
6
+ KeepProvider as CoreKeepProvider,
7
+ createKeepKit as createCoreKeepKit,
6
8
  useKeepContext,
7
9
  useKeepItem,
8
10
  useKeepList
@@ -18,7 +20,17 @@ import {
18
20
  useRef,
19
21
  useState
20
22
  } from "react";
21
- import { KeepProvider, useKeepContext as useKeepContext2, useKeepItem as useKeepItem2, useKeepList as useKeepList2 } from "@keepkit/core/react";
23
+ import { KeepProvider, useKeepContext as useKeepContext2, useKeepItem as useKeepItem2, useKeepList as useKeepList2, useKeepShortcut } from "@keepkit/core/react";
24
+ import {
25
+ createBrowserStorageAdapter,
26
+ createStorageAdapter,
27
+ FallbackStorageAdapter,
28
+ IndexedDBAdapter,
29
+ IndexedDBSyncQueueAdapter,
30
+ LocalStorageAdapter,
31
+ LocalStorageSyncQueueAdapter,
32
+ SyncStorageAdapter
33
+ } from "@keepkit/core/storage";
22
34
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
23
35
  var DEFAULT_LABELS = {
24
36
  save: "Save",
@@ -60,6 +72,15 @@ function KeepUiProvider({ labels, locale, labelResolver, children }) {
60
72
  }, [labelResolver, labels, locale]);
61
73
  return /* @__PURE__ */ jsx(KeepUiLabelsContext.Provider, { value, children });
62
74
  }
75
+ function KeepKitProvider({
76
+ labels,
77
+ locale,
78
+ labelResolver,
79
+ children,
80
+ ...providerProps
81
+ }) {
82
+ return /* @__PURE__ */ jsx(KeepUiProvider, { labels, locale, labelResolver, children: /* @__PURE__ */ jsx(CoreKeepProvider, { ...providerProps, children }) });
83
+ }
63
84
  function useKeepUiLabels() {
64
85
  return useContext(KeepUiLabelsContext);
65
86
  }
@@ -67,17 +88,44 @@ function useUiLabel(key, override) {
67
88
  const context = useKeepUiLabels();
68
89
  return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];
69
90
  }
91
+ function createKeepKit(options = {}) {
92
+ const { labels, locale, labelResolver, getTitle, getImageProps, ...coreOptions } = options;
93
+ const coreKit = createCoreKeepKit(coreOptions);
94
+ return {
95
+ Provider: (props) => /* @__PURE__ */ jsx(
96
+ KeepKitProvider,
97
+ {
98
+ ...coreOptions,
99
+ labels,
100
+ locale,
101
+ labelResolver,
102
+ ...props
103
+ }
104
+ ),
105
+ Button: (props) => /* @__PURE__ */ jsx(KeepButton, { ...props }),
106
+ Collection: (props) => /* @__PURE__ */ jsx(
107
+ KeepCollection,
108
+ {
109
+ ...props,
110
+ itemCardProps: {
111
+ ...getTitle ? { getTitle } : {},
112
+ ...getImageProps ? { getImageProps } : {},
113
+ ...props.itemCardProps
114
+ }
115
+ }
116
+ ),
117
+ useContext: () => coreKit.useContext(),
118
+ useItem: (item) => coreKit.useItem(item),
119
+ useList: (query) => coreKit.useList(query),
120
+ useShortcut: (shortcutOptions) => coreKit.useShortcut(shortcutOptions)
121
+ };
122
+ }
70
123
  function KeepButton({ labels, ...props }) {
71
124
  const saveLabel = useUiLabel("save", typeof labels?.unsaved === "string" ? labels.unsaved : void 0);
72
125
  const savedLabel = useUiLabel("saved", typeof labels?.saved === "string" ? labels.saved : void 0);
73
126
  const loadingLabel = useUiLabel("loading", typeof labels?.loading === "string" ? labels.loading : void 0);
74
127
  const errorLabel = useUiLabel("error", typeof labels?.error === "string" ? labels.error : void 0);
75
- const buttonState = useKeepItem(props.item.id, {
76
- meta: props.item.meta,
77
- targetType: props.item.targetType,
78
- note: props.item.note,
79
- tags: props.item.tags
80
- });
128
+ const buttonState = useKeepItem(props.item);
81
129
  const customStateLabel = labels?.loading !== void 0 || labels?.error !== void 0;
82
130
  const getStateContent = (state) => {
83
131
  if (state.error) return labels?.error ?? errorLabel;
@@ -90,8 +138,8 @@ function KeepButton({ labels, ...props }) {
90
138
  const sharedProps2 = {
91
139
  ...props,
92
140
  "aria-busy": props["aria-busy"] ?? (buttonState.isLoading || buttonState.isMutating),
93
- savedLabel: labels?.saved ?? savedLabel,
94
- unsavedLabel: labels?.unsaved ?? saveLabel,
141
+ savedLabel: labels?.saved ?? props.savedLabel ?? savedLabel,
142
+ unsavedLabel: labels?.unsaved ?? props.unsavedLabel ?? saveLabel,
95
143
  savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
96
144
  unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
97
145
  };
@@ -105,8 +153,8 @@ function KeepButton({ labels, ...props }) {
105
153
  const sharedProps = {
106
154
  ...props,
107
155
  "aria-busy": props["aria-busy"] ?? (buttonState.isLoading || buttonState.isMutating),
108
- savedLabel: labels?.saved ?? savedLabel,
109
- unsavedLabel: labels?.unsaved ?? saveLabel,
156
+ savedLabel: labels?.saved ?? props.savedLabel ?? savedLabel,
157
+ unsavedLabel: labels?.unsaved ?? props.unsavedLabel ?? saveLabel,
110
158
  savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,
111
159
  unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
112
160
  };
@@ -117,6 +165,7 @@ function KeepButton({ labels, ...props }) {
117
165
  function KeepItemCard({
118
166
  item,
119
167
  title,
168
+ getTitle,
120
169
  getImageProps,
121
170
  imageComponent: ImageComponent,
122
171
  renderImage,
@@ -134,7 +183,7 @@ function KeepItemCard({
134
183
  }) {
135
184
  const saveActionLabel = useUiLabel("save");
136
185
  const removeActionLabel = useUiLabel("remove");
137
- const itemState = useKeepItem(item.id);
186
+ const itemState = useKeepItem(item);
138
187
  const contentChildren = asChild && isValidElement(children) ? void 0 : children;
139
188
  const state = {
140
189
  item,
@@ -143,7 +192,7 @@ function KeepItemCard({
143
192
  error: itemState.error,
144
193
  remove: itemState.remove
145
194
  };
146
- const resolvedTitle = typeof title === "function" ? title(item) : title ?? getMetaTitle(item.meta) ?? item.id;
195
+ const resolvedTitle = typeof title === "function" ? title(item) : title ?? getTitle?.(item) ?? getMetaTitle(item.meta) ?? item.id;
147
196
  const imageProps = getImageProps?.(item, resolvedTitle);
148
197
  async function handleRemove() {
149
198
  try {
@@ -175,7 +224,7 @@ function KeepItemCard({
175
224
  );
176
225
  }
177
226
  function KeepList({
178
- options,
227
+ query,
179
228
  children,
180
229
  renderItem,
181
230
  loading,
@@ -189,7 +238,7 @@ function KeepList({
189
238
  const defaultLoading = useUiLabel("loadingItems");
190
239
  const defaultEmpty = useUiLabel("noItems");
191
240
  const defaultError = useUiLabel("errorItems");
192
- const state = useKeepList(options);
241
+ const state = useKeepList(query);
193
242
  const body = getListBody(state, {
194
243
  children,
195
244
  renderItem,
@@ -218,8 +267,87 @@ function getListBody(state, options) {
218
267
  );
219
268
  return /* @__PURE__ */ jsx("ul", { children: items });
220
269
  }
270
+ function KeepCollection({
271
+ query = {},
272
+ pageSize = 20,
273
+ features,
274
+ renderItem,
275
+ itemCardProps,
276
+ loading,
277
+ empty,
278
+ error,
279
+ className,
280
+ ...rootProps
281
+ }) {
282
+ const enabled = {
283
+ search: true,
284
+ sort: true,
285
+ pagination: true,
286
+ tagFilter: false,
287
+ bulkActions: false,
288
+ ...features
289
+ };
290
+ const [searchValue, setSearchValue] = useState(query.search?.query ?? "");
291
+ const [sort, setSort] = useState(query.sort ?? { by: "updatedAt", direction: "desc" });
292
+ const [tag, setTag] = useState(query.tags?.[0]);
293
+ const [page, setPage] = useState(query.pagination?.page ?? 1);
294
+ const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
295
+ const resolvedQuery = useMemo(
296
+ () => ({
297
+ ...query,
298
+ search: enabled.search ? { ...query.search, query: searchValue } : query.search,
299
+ sort: enabled.sort ? sort : query.sort,
300
+ tags: tag ? [.../* @__PURE__ */ new Set([...query.tags ?? [], tag])] : query.tags,
301
+ pagination: enabled.pagination ? { ...query.pagination, page, pageSize: resolvedPageSize } : query.pagination
302
+ }),
303
+ [enabled.pagination, enabled.search, enabled.sort, page, query, resolvedPageSize, searchValue, sort, tag]
304
+ );
305
+ const list = useKeepList(resolvedQuery);
306
+ useEffect(() => {
307
+ if (searchValue !== void 0 || sort.by !== void 0 || sort.direction !== void 0 || tag !== void 0) {
308
+ setPage(1);
309
+ }
310
+ }, [searchValue, sort.by, sort.direction, tag]);
311
+ return /* @__PURE__ */ jsxs(
312
+ "section",
313
+ {
314
+ ...rootProps,
315
+ className,
316
+ "aria-busy": list.isLoading || list.isMutating || rootProps["aria-busy"],
317
+ children: [
318
+ /* @__PURE__ */ jsxs("div", { children: [
319
+ enabled.search ? /* @__PURE__ */ jsx(KeepSearchInput, { value: searchValue, onValueChange: setSearchValue }) : null,
320
+ enabled.sort ? /* @__PURE__ */ jsx(KeepSortSelect, { value: sortToValue(sort), onValueChange: (_value, nextSort) => setSort(nextSort) }) : null,
321
+ enabled.tagFilter ? /* @__PURE__ */ jsx(KeepTagFilter, { query, value: tag, onValueChange: setTag }) : null
322
+ ] }),
323
+ /* @__PURE__ */ jsx(
324
+ KeepList,
325
+ {
326
+ query: resolvedQuery,
327
+ renderItem,
328
+ itemCardProps,
329
+ loading,
330
+ empty,
331
+ error
332
+ }
333
+ ),
334
+ enabled.pagination ? /* @__PURE__ */ jsx(
335
+ KeepPagination,
336
+ {
337
+ totalCount: list.totalCount,
338
+ pageSize: resolvedPageSize,
339
+ page: list.page,
340
+ onPageChange: (_nextPage, nextPageOffset) => setPage(Math.floor(nextPageOffset / resolvedPageSize) + 1)
341
+ }
342
+ ) : null,
343
+ enabled.bulkActions ? /* @__PURE__ */ jsx(KeepBulkActions, { query: resolvedQuery }) : null,
344
+ /* @__PURE__ */ jsx(KeepAnnouncements, {})
345
+ ]
346
+ }
347
+ );
348
+ }
221
349
  function KeepTagFilter({
222
- listOptions,
350
+ query,
223
351
  value: controlledValue,
224
352
  defaultValue,
225
353
  onChange,
@@ -237,10 +365,10 @@ function KeepTagFilter({
237
365
  const uiAriaLabel = useUiLabel("filterTags");
238
366
  const defaultAllLabel = allLabel ?? uiAllLabel;
239
367
  const defaultAriaLabel = ariaLabel ?? uiAriaLabel;
240
- const list = useKeepList(listOptions);
241
368
  const contentChildren = asChild && isValidElement(children) ? void 0 : children;
242
369
  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
243
370
  const value = controlledValue ?? uncontrolledValue;
371
+ const list = useKeepList({ ...query, tags: value ? [...query?.tags ?? [], value] : query?.tags });
244
372
  const select = useCallback(
245
373
  (tag) => {
246
374
  if (controlledValue === void 0) setUncontrolledValue(tag);
@@ -288,7 +416,7 @@ function KeepNoteEditor({
288
416
  }) {
289
417
  const defaultLabel = useUiLabel("note");
290
418
  const defaultSaveLabel = useUiLabel("saveNote");
291
- const itemState = useKeepItem(item.id);
419
+ const itemState = useKeepItem(item);
292
420
  const contentChildren = asChild && isValidElement(children) ? void 0 : children;
293
421
  const [note, setNote] = useState(item.note ?? "");
294
422
  useEffect(() => setNote(itemState.item?.note ?? item.note ?? ""), [item.note, itemState.item?.note]);
@@ -455,7 +583,7 @@ function KeepTagEditor({
455
583
  const tagsLabel = useUiLabel("tagsToApply");
456
584
  const removeLabel = useUiLabel("remove");
457
585
  const applyTagsLabel = useUiLabel("applyTags");
458
- const itemState = useKeepItem(item.id);
586
+ const itemState = useKeepItem(item);
459
587
  const [tags, setTags] = useState(item.tags ?? []);
460
588
  const [input, setInput] = useState("");
461
589
  useEffect(() => setTags(itemState.item?.tags ?? item.tags ?? []), [item.tags, itemState.item?.tags]);
@@ -514,7 +642,7 @@ function KeepTagEditor({
514
642
  );
515
643
  }
516
644
  function KeepBulkActions({
517
- listOptions,
645
+ query,
518
646
  selectedIds: controlledSelectedIds,
519
647
  defaultSelectedIds = [],
520
648
  onSelectedIdsChange,
@@ -527,7 +655,7 @@ function KeepBulkActions({
527
655
  const deleteSelectedLabel = useUiLabel("deleteSelected");
528
656
  const tagsLabel = useUiLabel("tagsToApply");
529
657
  const applyTagsLabel = useUiLabel("applyTags");
530
- const list = useKeepList(listOptions);
658
+ const list = useKeepList(query);
531
659
  const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState(defaultSelectedIds);
532
660
  const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
533
661
  const selected = new Set(selectedIds);
@@ -672,6 +800,9 @@ function getMetaTitle(meta) {
672
800
  function normalizeUiTags(tags) {
673
801
  return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];
674
802
  }
803
+ function sortToValue(sort) {
804
+ return `${sort?.by ?? "updatedAt"}:${sort?.direction ?? "desc"}`;
805
+ }
675
806
  function renderRoot(asChild, child, props, body, componentName) {
676
807
  if (asChild) {
677
808
  if (!isValidElement(child)) throw new Error(`${componentName} with asChild requires a single React element child.`);
@@ -680,11 +811,16 @@ function renderRoot(asChild, child, props, body, componentName) {
680
811
  return /* @__PURE__ */ jsx("div", { ...props, children: body });
681
812
  }
682
813
  export {
814
+ FallbackStorageAdapter,
815
+ IndexedDBAdapter,
816
+ IndexedDBSyncQueueAdapter,
683
817
  KeepAnnouncements,
684
818
  KeepBulkActions,
685
819
  KeepButton,
820
+ KeepCollection,
686
821
  KeepEmptyState,
687
822
  KeepItemCard,
823
+ KeepKitProvider,
688
824
  KeepList,
689
825
  KeepNoteEditor,
690
826
  KeepPagination,
@@ -695,9 +831,16 @@ export {
695
831
  KeepTagEditor,
696
832
  KeepTagFilter,
697
833
  KeepUiProvider,
834
+ LocalStorageAdapter,
835
+ LocalStorageSyncQueueAdapter,
836
+ SyncStorageAdapter,
837
+ createBrowserStorageAdapter,
838
+ createKeepKit,
839
+ createStorageAdapter,
698
840
  useKeepContext2 as useKeepContext,
699
841
  useKeepItem2 as useKeepItem,
700
842
  useKeepList2 as useKeepList,
843
+ useKeepShortcut,
701
844
  useKeepUiLabels
702
845
  };
703
846
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport type { KeepChangeContext, KeepItem, KeepItemInput, KeepListOptions, KeepSyncStatus } from \"@keepkit/core/core\";\nimport type { UseKeepListResult } from \"@keepkit/core/react\";\nimport {\n KeepButton as CoreKeepButton,\n type KeepButtonProps as CoreKeepButtonProps,\n type KeepButtonState,\n useKeepContext,\n useKeepItem,\n useKeepList,\n} from \"@keepkit/core/react\";\nimport {\n type ComponentType,\n cloneElement,\n createContext,\n type FormHTMLAttributes,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n type InputHTMLAttributes,\n isValidElement,\n type ReactElement,\n type ReactNode,\n type SelectHTMLAttributes,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} 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 | \"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\nconst 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 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\nfunction useUiLabel(key: KeepUiLabelKey, override?: string): string {\n const context = useKeepUiLabels();\n return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];\n}\n\nexport type { KeepContextValue, KeepProviderProps } from \"@keepkit/core/react\";\nexport { KeepProvider, useKeepContext, useKeepItem, useKeepList } from \"@keepkit/core/react\";\nexport type { KeepItem, KeepItemInput, KeepListOptions, KeepSyncStatus };\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 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.id, {\n meta: props.item.meta,\n targetType: props.item.targetType,\n note: props.item.note,\n tags: props.item.tags,\n });\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 if (props.asChild === true) {\n const sharedProps = {\n ...props,\n \"aria-busy\": props[\"aria-busy\"] ?? (buttonState.isLoading || buttonState.isMutating),\n savedLabel: labels?.saved ?? savedLabel,\n unsavedLabel: labels?.unsaved ?? saveLabel,\n savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,\n unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel,\n };\n if (!customStateLabel) return <CoreKeepButton<TMeta> {...sharedProps} />;\n const statefulProps = {\n ...sharedProps,\n children: (state: KeepButtonState<TMeta>) => <>{getStateContent(state)}</>,\n };\n return <CoreKeepButton<TMeta> {...statefulProps} />;\n }\n const sharedProps = {\n ...props,\n \"aria-busy\": props[\"aria-busy\"] ?? (buttonState.isLoading || buttonState.isMutating),\n savedLabel: labels?.saved ?? savedLabel,\n unsavedLabel: labels?.unsaved ?? saveLabel,\n savedAriaLabel: labels?.savedAriaLabel ?? props.savedAriaLabel,\n unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel,\n };\n if (!customStateLabel) return <CoreKeepButton<TMeta> {...sharedProps} />;\n const statefulProps = { ...sharedProps, children: (state: KeepButtonState<TMeta>) => getStateContent(state) };\n return <CoreKeepButton<TMeta> {...statefulProps} />;\n}\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 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 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.id);\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 = typeof title === \"function\" ? title(item) : (title ?? 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\nexport type KeepListState<TMeta = Record<string, unknown>> = UseKeepListResult<TMeta>;\n\nexport type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n options?: KeepListOptions<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 options,\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>(options);\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 const root = asChild && isValidElement(children) ? children : undefined;\n return renderRoot(\n asChild,\n root,\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 const items = 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 return <ul>{items}</ul>;\n}\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 listOptions?: KeepListOptions<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 KeepList options. */\nexport function KeepTagFilter<TMeta = Record<string, unknown>>({\n listOptions,\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 defaultAllLabel = allLabel ?? uiAllLabel;\n const defaultAriaLabel = ariaLabel ?? uiAriaLabel;\n const list = useKeepList<TMeta>(listOptions);\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\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, select }),\n [list.tagCounts, list.tags, select, value],\n );\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <fieldset>\n <legend>{defaultAriaLabel}</legend>\n <button type=\"button\" aria-pressed={value === undefined} onClick={() => select()}>\n {defaultAllLabel}\n </button>\n {list.tags.map((tag) => (\n <button key={tag} type=\"button\" aria-pressed={value === tag} onClick={() => select(tag)}>\n {renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, value === 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\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 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 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.id);\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const [note, setNote] = useState(item.note ?? \"\");\n useEffect(() => setNote(itemState.item?.note ?? item.note ?? \"\"), [item.note, itemState.item?.note]);\n const save = useCallback(async () => {\n const nextNote = note.trim() || undefined;\n try {\n await itemState.updateNote(nextNote);\n onSaved?.(nextNote);\n } catch (error) {\n onSaveError?.(error);\n throw error;\n }\n }, [itemState, note, onSaveError, onSaved]);\n const state: KeepNoteEditorState<TMeta> = {\n item,\n note,\n setNote,\n isDirty: note !== (itemState.item?.note ?? item.note ?? \"\"),\n isSaving: itemState.isMutating,\n error: itemState.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={itemState.isMutating}\n />\n </label>\n <button type=\"submit\" disabled={itemState.isMutating} aria-busy={itemState.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={itemState.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\": itemState.isMutating || formProps[\"aria-busy\"] },\n body,\n \"KeepNoteEditor\",\n );\n}\n\nexport type KeepSearchInputProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n};\n\n/** A controlled/uncontrolled search field for wiring into useKeepList.searchQuery. */\nexport function KeepSearchInput({\n value: controlledValue,\n defaultValue = \"\",\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 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 onValueChange?.(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<KeepListOptions[\"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 newestLabel = useUiLabel(\"newest\");\n const savedLabel = useUiLabel(\"saved\");\n const oldestLabel = useUiLabel(\"oldest\");\n const [uncontrolledValue, setUncontrolledValue] = useState<KeepSortValue>(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n const options = children ?? (\n <>\n <option value=\"updatedAt:desc\">{newestLabel}</option>\n <option value=\"savedAt:desc\">{savedLabel}</option>\n <option value=\"updatedAt:asc\">{oldestLabel}</option>\n <option value=\"savedAt:asc\">{oldestLabel}</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 KeepPaginationProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n totalCount: number;\n pageSize: number;\n page?: number;\n onPageChange?: (page: number, offset: number) => void;\n render?: RenderProp<{ page: number; pageCount: number; goToPage: (page: number) => void }>;\n};\n\n/** A small accessible pagination control using one-based pages and zero-based offsets. */\nexport function KeepPagination({\n totalCount,\n pageSize,\n page = 1,\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 if (render) return <nav {...props}>{render({ page: currentPage, pageCount, goToPage })}</nav>;\n return (\n <nav {...props} aria-label={props[\"aria-label\"] ?? paginationLabel}>\n <button type=\"button\" onClick={() => goToPage(currentPage - 1)} disabled={currentPage <= 1}>\n {previousPageLabel}\n </button>\n <span aria-current=\"page\">\n {pageLabel} {currentPage} / {pageCount}\n </span>\n <button type=\"button\" onClick={() => goToPage(currentPage + 1)} disabled={currentPage >= pageCount}>\n {nextPageLabel}\n </button>\n </nav>\n );\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<{\n tags: string[];\n setTags: (tags: string[]) => void;\n save: () => Promise<void>;\n isSaving: boolean;\n }>;\n};\n\n/** Edits one item's normalized tag set and exposes a render-prop escape hatch. */\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.id);\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 const next = normalizeUiTags([...tags, tag]);\n setTags(next);\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 event.preventDefault();\n if (input.trim()) addTag(input);\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\nexport type KeepBulkActionsProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n listOptions?: KeepListOptions<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};\n\n/** Selects visible items and performs one storage operation for the whole selection. */\nexport function KeepBulkActions<TMeta = Record<string, unknown>>({\n listOptions,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n onSelectedIdsChange,\n renderItem,\n onCompleted,\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>(listOptions);\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 = list.items.length > 0 && list.items.every((item) => selected.has(item.id));\n const toggleAll = () => setSelectedIds(allSelected ? [] : list.items.map((item) => item.id));\n const remove = async () => {\n await list.removeBatch(selectedIds);\n onCompleted?.(\"remove\", selectedIds);\n setSelectedIds([]);\n };\n const updateTags = async () => {\n const tags = normalizeUiTags(tagsInput.split(\",\"));\n await list.updateTagsBatch(selectedIds, tags);\n onCompleted?.(\"tags\", selectedIds);\n setSelectedIds([]);\n };\n return (\n <section {...props} aria-busy={list.isMutating || props[\"aria-busy\"]}>\n <fieldset>\n <legend>{selectItemsLabel}</legend>\n <label>\n <input type=\"checkbox\" checked={allSelected} onChange={toggleAll} />\n {selectedIds.length} {selectedCountLabel}\n </label>\n {list.items.map((item) => (\n <label key={item.id}>\n <input type=\"checkbox\" checked={selected.has(item.id)} onChange={() => toggle(item.id)} />\n {renderItem ? renderItem(item, selected.has(item.id)) : (getMetaTitle(item.meta) ?? item.id)}\n </label>\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 type=\"button\" onClick={() => void updateTags()} disabled={selectedIds.length === 0 || list.isMutating}>\n {applyTagsLabel}\n </button>\n </section>\n );\n}\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\";\n\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\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\nfunction resolveContent<TState>(content: ReactNode | RenderProp<TState>, state: TState): ReactNode {\n return typeof content === \"function\" ? content(state) : content;\n}\n\nfunction toKeepButtonItem<TMeta>(item: KeepItem<TMeta>): KeepItemInput<TMeta> & { id: string } {\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\nfunction 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\nfunction normalizeUiTags(tags: string[]): string[] {\n return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nfunction 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"],"mappings":"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","names":["useKeepContext","useKeepItem","useKeepList","sharedProps","statefulProps"]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport type { KeepChangeContext, KeepItem, KeepItemInput, KeepListQuery, KeepSyncStatus } from \"@keepkit/core/core\";\nimport type { UseKeepListResult } from \"@keepkit/core/react\";\nimport {\n type CreateKeepKitOptions as CoreCreateKeepKitOptions,\n KeepButton as CoreKeepButton,\n type KeepButtonProps as CoreKeepButtonProps,\n KeepProvider as CoreKeepProvider,\n createKeepKit as createCoreKeepKit,\n type KeepButtonState,\n type KeepProviderProps,\n type KeepShortcutOptions,\n useKeepContext,\n useKeepItem,\n useKeepList,\n} from \"@keepkit/core/react\";\nimport {\n type ComponentType,\n cloneElement,\n createContext,\n type FormHTMLAttributes,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n type InputHTMLAttributes,\n isValidElement,\n type ReactElement,\n type ReactNode,\n type SelectHTMLAttributes,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} 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 | \"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\nconst 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 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 type KeepKitProviderProps<TMeta = Record<string, unknown>> = Omit<KeepProviderProps<TMeta>, \"children\"> &\n Omit<KeepUiProviderProps, \"children\"> & {\n children?: ReactNode;\n };\n\n/** Combines the core store and UI labels into the default application provider. */\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}>{children}</CoreKeepProvider>\n </KeepUiProvider>\n );\n}\n\nexport function useKeepUiLabels(): KeepUiLabelContext {\n return useContext(KeepUiLabelsContext);\n}\n\nfunction useUiLabel(key: KeepUiLabelKey, override?: string): string {\n const context = useKeepUiLabels();\n return override ?? context.labelResolver?.(key, { locale: context.locale }) ?? context.labels[key];\n}\n\nexport type { KeepContextValue, KeepProviderProps } 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 type { KeepItem, KeepItemInput, KeepListQuery, KeepShortcutOptions, KeepSyncStatus };\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>) => UseKeepListResult<TMeta>;\n useShortcut: (options: KeepShortcutOptions<TMeta>) => void;\n};\n\n/** Create one typed application API for the core and the 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\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 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 if (props.asChild === true) {\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 const statefulProps = {\n ...sharedProps,\n children: (state: KeepButtonState<TMeta>) => <>{getStateContent(state)}</>,\n };\n return <CoreKeepButton<TMeta> {...statefulProps} />;\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 const statefulProps = { ...sharedProps, children: (state: KeepButtonState<TMeta>) => getStateContent(state) };\n return <CoreKeepButton<TMeta> {...statefulProps} />;\n}\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\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 const root = asChild && isValidElement(children) ? children : undefined;\n return renderRoot(\n asChild,\n root,\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 const items = 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 return <ul>{items}</ul>;\n}\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 useEffect(() => {\n if (searchValue !== undefined || sort.by !== undefined || sort.direction !== undefined || tag !== undefined) {\n setPage(1);\n }\n }, [searchValue, sort.by, sort.direction, tag]);\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 ? <KeepSearchInput value={searchValue} onValueChange={setSearchValue} /> : null}\n {enabled.sort ? (\n <KeepSortSelect value={sortToValue(sort)} onValueChange={(_value, nextSort) => setSort(nextSort)} />\n ) : null}\n {enabled.tagFilter ? <KeepTagFilter<TMeta> query={query} value={tag} onValueChange={setTag} /> : 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, nextPageOffset) => setPage(Math.floor(nextPageOffset / resolvedPageSize) + 1)}\n />\n ) : null}\n {enabled.bulkActions ? <KeepBulkActions<TMeta> query={resolvedQuery} /> : null}\n <KeepAnnouncements />\n </section>\n );\n}\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 defaultAllLabel = allLabel ?? uiAllLabel;\n const defaultAriaLabel = ariaLabel ?? uiAriaLabel;\n const contentChildren = asChild && isValidElement(children) ? undefined : children;\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n const list = useKeepList<TMeta>({ ...query, tags: value ? [...(query?.tags ?? []), value] : query?.tags });\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, select }),\n [list.tagCounts, list.tags, select, value],\n );\n const body = render\n ? render(state)\n : typeof contentChildren === \"function\"\n ? contentChildren(state)\n : (contentChildren ?? (\n <fieldset>\n <legend>{defaultAriaLabel}</legend>\n <button type=\"button\" aria-pressed={value === undefined} onClick={() => select()}>\n {defaultAllLabel}\n </button>\n {list.tags.map((tag) => (\n <button key={tag} type=\"button\" aria-pressed={value === tag} onClick={() => select(tag)}>\n {renderTag ? renderTag(tag, list.tagCounts[tag] ?? 0, value === 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\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 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 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 contentChildren = asChild && isValidElement(children) ? undefined : children;\n const [note, setNote] = useState(item.note ?? \"\");\n useEffect(() => setNote(itemState.item?.note ?? item.note ?? \"\"), [item.note, itemState.item?.note]);\n const save = useCallback(async () => {\n const nextNote = note.trim() || undefined;\n try {\n await itemState.updateNote(nextNote);\n onSaved?.(nextNote);\n } catch (error) {\n onSaveError?.(error);\n throw error;\n }\n }, [itemState, note, onSaveError, onSaved]);\n const state: KeepNoteEditorState<TMeta> = {\n item,\n note,\n setNote,\n isDirty: note !== (itemState.item?.note ?? item.note ?? \"\"),\n isSaving: itemState.isMutating,\n error: itemState.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={itemState.isMutating}\n />\n </label>\n <button type=\"submit\" disabled={itemState.isMutating} aria-busy={itemState.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={itemState.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\": itemState.isMutating || formProps[\"aria-busy\"] },\n body,\n \"KeepNoteEditor\",\n );\n}\n\nexport type KeepSearchInputProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> & {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n};\n\n/** A controlled/uncontrolled search field for wiring into KeepListQuery.search. */\nexport function KeepSearchInput({\n value: controlledValue,\n defaultValue = \"\",\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 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 onValueChange?.(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 newestLabel = useUiLabel(\"newest\");\n const savedLabel = useUiLabel(\"saved\");\n const oldestLabel = useUiLabel(\"oldest\");\n const [uncontrolledValue, setUncontrolledValue] = useState<KeepSortValue>(defaultValue);\n const value = controlledValue ?? uncontrolledValue;\n const options = children ?? (\n <>\n <option value=\"updatedAt:desc\">{newestLabel}</option>\n <option value=\"savedAt:desc\">{savedLabel}</option>\n <option value=\"updatedAt:asc\">{oldestLabel}</option>\n <option value=\"savedAt:asc\">{oldestLabel}</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 KeepPaginationProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> & {\n totalCount: number;\n pageSize: number;\n page?: number;\n onPageChange?: (page: number, offset: number) => void;\n render?: RenderProp<{ page: number; pageCount: number; goToPage: (page: number) => void }>;\n};\n\n/** A small accessible pagination control using one-based pages and zero-based offsets. */\nexport function KeepPagination({\n totalCount,\n pageSize,\n page = 1,\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 if (render) return <nav {...props}>{render({ page: currentPage, pageCount, goToPage })}</nav>;\n return (\n <nav {...props} aria-label={props[\"aria-label\"] ?? paginationLabel}>\n <button type=\"button\" onClick={() => goToPage(currentPage - 1)} disabled={currentPage <= 1}>\n {previousPageLabel}\n </button>\n <span aria-current=\"page\">\n {pageLabel} {currentPage} / {pageCount}\n </span>\n <button type=\"button\" onClick={() => goToPage(currentPage + 1)} disabled={currentPage >= pageCount}>\n {nextPageLabel}\n </button>\n </nav>\n );\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<{\n tags: string[];\n setTags: (tags: string[]) => void;\n save: () => Promise<void>;\n isSaving: boolean;\n }>;\n};\n\n/** Edits one item's normalized tag set and exposes a render-prop escape hatch. */\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 const next = normalizeUiTags([...tags, tag]);\n setTags(next);\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 event.preventDefault();\n if (input.trim()) addTag(input);\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\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};\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 ...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 = list.items.length > 0 && list.items.every((item) => selected.has(item.id));\n const toggleAll = () => setSelectedIds(allSelected ? [] : list.items.map((item) => item.id));\n const remove = async () => {\n await list.removeBatch(selectedIds);\n onCompleted?.(\"remove\", selectedIds);\n setSelectedIds([]);\n };\n const updateTags = async () => {\n const tags = normalizeUiTags(tagsInput.split(\",\"));\n await list.updateTagsBatch(selectedIds, tags);\n onCompleted?.(\"tags\", selectedIds);\n setSelectedIds([]);\n };\n return (\n <section {...props} aria-busy={list.isMutating || props[\"aria-busy\"]}>\n <fieldset>\n <legend>{selectItemsLabel}</legend>\n <label>\n <input type=\"checkbox\" checked={allSelected} onChange={toggleAll} />\n {selectedIds.length} {selectedCountLabel}\n </label>\n {list.items.map((item) => (\n <label key={item.id}>\n <input type=\"checkbox\" checked={selected.has(item.id)} onChange={() => toggle(item.id)} />\n {renderItem ? renderItem(item, selected.has(item.id)) : (getMetaTitle(item.meta) ?? item.id)}\n </label>\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 type=\"button\" onClick={() => void updateTags()} disabled={selectedIds.length === 0 || list.isMutating}>\n {applyTagsLabel}\n </button>\n </section>\n );\n}\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\";\n\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\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\nfunction resolveContent<TState>(content: ReactNode | RenderProp<TState>, state: TState): ReactNode {\n return typeof content === \"function\" ? content(state) : content;\n}\n\nfunction 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\nfunction 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\nfunction normalizeUiTags(tags: string[]): string[] {\n return [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nfunction sortToValue(sort: KeepListQuery[\"sort\"]): KeepSortValue {\n return `${sort?.by ?? \"updatedAt\"}:${sort?.direction ?? \"desc\"}` as KeepSortValue;\n}\n\nfunction 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"],"mappings":"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","names":["useKeepContext","useKeepItem","useKeepList","sharedProps","statefulProps"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keepkit/ui",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Headless, accessible React UI components for KeepKit.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,11 +27,12 @@
27
27
  "access": "public"
28
28
  },
29
29
  "peerDependencies": {
30
- "@keepkit/core": ">=0.4.0",
31
30
  "react": ">=18"
32
31
  },
32
+ "dependencies": {
33
+ "@keepkit/core": "0.5.0"
34
+ },
33
35
  "devDependencies": {
34
- "@keepkit/core": "0.4.0",
35
36
  "@types/react": "^19.2.18",
36
37
  "react": "^19.2.8",
37
38
  "tsup": "^8.5.1",