@keepkit/ui 0.17.0 → 0.18.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
@@ -58,8 +58,9 @@ function SavedArticles() {
58
58
 
59
59
  `keep.Collection`は検索、ソート、ページング、loading / empty / error、ARIA live通知を標準で提供します。検索は既定で300msデバウンスされます。`features={{ tagFilter: true, bulkActions: true }}`でタグフィルターと一括操作も有効にできます。個別の`KeepList`、`KeepSearchInput`、`KeepSortSelect`、`KeepPagination`、`KeepItemCheckbox`、`KeepTagEditor`などは高度なレイアウト用に利用できます。`KeepBulkActions`はrender propsで操作UIを差し替えられ、`isAllSelected` / `toggleSelectAll`で表示中アイテムを一括操作できます。`KeepNoteEditor`は既定300msのデバウンス保存に対応し、`debounceMs={0}`でフォーム送信のみへ戻せます。通知領域だけを明示的に置く場合は`KeepAnnouncer`(`KeepAnnouncements`のalias)を使えます。
60
60
  `KeepItemCard`は`href`、`onOpen`、`linkTarget`、`linkComponent`に対応し、保存アイテムから詳細ページへ遷移できます。非公開・期限切れ等の`status`を持つアイテムは自動的にリンクを無効化します。`KeepBackup`はJSONのエクスポート、merge / replaceインポート、結果件数、容量エラー表示を提供します。
61
- `KeepTourBar`(alias: `KeepNavigator`)は進行度、前へ・次へ、一覧へ戻る操作をURLまたはコールバックで提供します。`keyboardShortcuts`を指定するとJ/Kまたは]/[で巡回でき、`useKeepTourShortcuts`ではキーと動作を個別に差し替えられます。`KeepReorderableList`はドラッグ操作と矢印キーによる並び替えを提供します。
61
+ `KeepTourBar`(alias: `KeepNavigator`)は進行度、前へ・次へ、一覧へ戻る操作をURLまたはコールバックで提供します。前後ボタンには隣接アイテム名のプレビューが付き、`getItemTitle`で表示名を差し替えられます。`keyboardShortcuts`を指定するとJ/Kまたは]/[で巡回でき、`useKeepTourShortcuts`ではキーと動作を個別に差し替えられます。`KeepReorderableList`はドラッグ操作と矢印キーによる並び替えを提供し、ドラッグ中の挿入位置を表示します。
62
62
  `KeepList`や`KeepCollection`のカードは検索語を大文字小文字を区別せず`<mark class="keep-highlight" data-highlight="true">`で表示します。単体の`KeepItemCard`では`highlightQuery`、任意のテキストでは`KeepHighlight`を使えます。`KeepItemCard.Media`は読み込み状態を`data-media-status`で公開し、失敗時は`fallback`または標準SVGへ切り替わります。
63
+ テーマCSSではハイライト用の`--keep-highlight-bg` / `--keep-highlight-fg`(ライト/ダーク対応)、タイトル2行・メモプレビュー3行の制限、メディアの固定アスペクト比を適用します。`KeepItemStatusBadge`は状態ラベルに加えてチェック・時計・進入禁止・鍵のSVGアイコンを表示し、状態ごとの形状とトーンを組み合わせます。個別の状態スタイルは`@keepkit/ui/styles/status.css`からも読み込めます。
63
64
  外部URLの詳細リンクには`target="_blank"`と`rel="noreferrer"`が既定で補完され、利用できないカードには`aria-disabled="true"`と`data-item-status`が付与されます。同期競合ダイアログではローカルとリモートの更新日時・メモを並べて確認できます。
64
65
 
65
66
  `KeepList`は初回ロード中、`layout`に合う`KeepItemCardSkeleton`を既定で6枚表示します。`loadingCount`で枚数を変更でき、従来の`loading`または`renderLoading`で完全に差し替えられます。`layout="auto"`は画面幅ではなく配置コンテナ幅に追従し、サイドバーやモーダルでも1列から複数列へ切り替わります。スケルトンのパルスは`prefers-reduced-motion`で静止表示になります。
@@ -85,7 +86,7 @@ const onFeedback = useKeepToastFeedback(toast);
85
86
  <KeepKitProvider storage={storage} onFeedback={onFeedback}>{children}</KeepKitProvider>;
86
87
  ```
87
88
 
88
- v0.17.0では`KeepTourBar` / `KeepNavigator`、`KeepReorderableList`、`useKeepTourShortcuts`を利用できます。`KeepCollection urlSync layout="list" | "grid" | "compact"`、`KeepBulkActions selectionScope="page" | "query" | "all"`、`KeepUndo`も利用できます。`createNextPagesRouterAdapter`はNext.js Pages Router用の注入adapterです。`locale`は16言語に対応し、`labels`で上書きできます。認証付き同期は`createAuthenticatedSyncKit`から利用できます。
89
+ v0.18.0では`KeepTourBar` / `KeepNavigator`、`KeepReorderableList`、`useKeepTourShortcuts`を利用できます。`KeepCollection urlSync layout="list" | "grid" | "compact"`、`KeepBulkActions selectionScope="page" | "query" | "all"`、`KeepUndo`も利用できます。`createNextPagesRouterAdapter`はNext.js Pages Router用の注入adapterです。`locale`は16言語に対応し、`labels`で上書きできます。認証付き同期は`createAuthenticatedSyncKit`から利用できます。
89
90
  Phase 4の状態UIとして`KeepItemStatusBadge`、`KeepStaleNotice`、`KeepPruneStaleButton`、`KeepSyncStatusBanner`、`KeepSyncRecoveryDialog`を利用できます。`import "@keepkit/ui/theme.css"`でテーマCSSを有効にできます。
90
91
 
91
92
  ### Tailwind/shadcnテーマ
@@ -174,8 +175,9 @@ function SavedArticles() {
174
175
 
175
176
  The opt-in theme adds neutral borders, surfaces, shadows, focus treatment, and decorative action icons without changing accessible names. Target individual controls with `data-keep-action`, or override `--keep-icon-size`, `--keep-control-gap`, `--keep-shadow`, `--keep-success`, and `--keep-warning`. Consumers that omit the CSS keep the headless markup, and `KeepButton icons` continues to take precedence over the built-in icon.
176
177
  `KeepItemCard` accepts `href`, `onOpen`, `linkTarget`, and `linkComponent` for detail-page navigation. Links are disabled for unavailable `status` values such as private or expired. `KeepBackup` provides JSON export, merge/replace import, result counts, and quota-error messaging.
177
- `KeepTourBar` (aliased as `KeepNavigator`) provides progress, previous/next, and return-to-list actions through URLs or callbacks. Set `keyboardShortcuts` for J/K or ]/[ tour navigation, or use `useKeepTourShortcuts` for custom bindings. `KeepReorderableList` supports drag and keyboard reordering.
178
+ `KeepTourBar` (aliased as `KeepNavigator`) provides progress, previous/next, and return-to-list actions through URLs or callbacks. Adjacent item titles are previewed below the navigation labels; customize them with `getItemTitle`. Set `keyboardShortcuts` for J/K or ]/[ tour navigation, or use `useKeepTourShortcuts` for custom bindings. `KeepReorderableList` supports drag and keyboard reordering and shows the active insertion position.
178
179
  Cards rendered by `KeepList` and `KeepCollection` highlight case-insensitive search matches with `<mark class="keep-highlight" data-highlight="true">`. Use `highlightQuery` on a standalone `KeepItemCard` or `KeepHighlight` for arbitrary text. `KeepItemCard.Media` exposes its loading state through `data-media-status` and replaces failed images with `fallback` or the built-in SVG placeholder.
180
+ The theme defines WCAG-oriented `--keep-highlight-bg` / `--keep-highlight-fg` pairs for light and dark modes, clamps titles to two lines and memo previews to three, and reserves a stable media aspect ratio. `KeepItemStatusBadge` combines visible status text with check, clock, ban, or lock SVG icons; import `@keepkit/ui/styles/status.css` when using the status styles independently.
179
181
  External detail URLs receive `target="_blank"` and `rel="noreferrer"` defaults. Unavailable cards expose `aria-disabled="true"` and normalized `data-item-status` values, and the sync recovery dialog compares local and remote updated dates and notes side by side.
180
182
 
181
183
  During initial loading, `KeepList` renders six layout-matched `KeepItemCardSkeleton` placeholders by default. Change the count with `loadingCount`, or replace them with the existing `loading` prop or its `renderLoading` alias. `layout="auto"` responds to the available container width rather than viewport width, so embedded sidebars and dialogs collapse to one column. Skeleton pulses become static under `prefers-reduced-motion`.
@@ -201,7 +203,7 @@ const onFeedback = useKeepToastFeedback(toast);
201
203
  <KeepKitProvider storage={storage} onFeedback={onFeedback}>{children}</KeepKitProvider>;
202
204
  ```
203
205
 
204
- In v0.17.0, use `KeepTourBar` / `KeepNavigator`, `KeepReorderableList`, and `useKeepTourShortcuts` for continuous saved-item tours. `KeepCollection urlSync` with `layout="list" | "grid" | "compact"`, `KeepBulkActions selectionScope="page" | "query" | "all"`, and `KeepUndo` remain available. `createNextPagesRouterAdapter` is the injected adapter for Next.js Pages Router. `locale` includes 16 built-in dictionaries, and `labels` overrides individual entries. Authenticated sync is available through `createAuthenticatedSyncKit`.
206
+ In v0.18.0, use `KeepTourBar` / `KeepNavigator`, `KeepReorderableList`, and `useKeepTourShortcuts` for continuous saved-item tours. `KeepCollection urlSync` with `layout="list" | "grid" | "compact"`, `KeepBulkActions selectionScope="page" | "query" | "all"`, and `KeepUndo` remain available. `createNextPagesRouterAdapter` is the injected adapter for Next.js Pages Router. `locale` includes 16 built-in dictionaries, and `labels` overrides individual entries. Authenticated sync is available through `createAuthenticatedSyncKit`.
205
207
  Phase 4 adds `KeepItemStatusBadge`, `KeepStaleNotice`, `KeepPruneStaleButton`, `KeepSyncStatusBanner`, and `KeepSyncRecoveryDialog` for unavailable items, sync failures, conflict resolution, and backup recovery. Import `@keepkit/ui/theme.css` or `@keepkit/ui/tailwind.css` for the opt-in theme layer.
206
208
 
207
209
  ### Tailwind and shadcn theme
package/dist/index.d.ts CHANGED
@@ -1,69 +1,40 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, HTMLAttributes, ComponentType, ImgHTMLAttributes, MouseEvent, HTMLAttributeAnchorTarget, InputHTMLAttributes, FormHTMLAttributes, KeyboardEvent, ButtonHTMLAttributes, SelectHTMLAttributes, CSSProperties } from 'react';
3
- import { KeepItem, ImportItemsResult, KeepListQuery, KeepUrlSyncOptions, KeepItemStatus, KeepSyncConflict, KeepItemInput } from '@keepkit/core/core';
2
+ import { HTMLAttributes, ReactNode, ComponentType, InputHTMLAttributes, ImgHTMLAttributes, MouseEvent, HTMLAttributeAnchorTarget, KeyboardEvent, FormHTMLAttributes, SelectHTMLAttributes, ButtonHTMLAttributes, CSSProperties } from 'react';
3
+ import { KeepListQuery, KeepUrlSyncOptions, ImportItemsResult, KeepItem, KeepItemStatus, KeepSyncConflict, KeepItemInput } from '@keepkit/core/core';
4
4
  export { AuthenticatedSyncAuthContext, AuthenticatedSyncKit, AuthenticatedSyncKitOptions, AuthenticatedSyncRequestContext, AuthenticatedSyncTransport, KeepItem, KeepItemInput, KeepListQuery, KeepScope, KeepSyncConflict, KeepSyncResolution, KeepSyncState, KeepSyncStatus, KeepUndoState, KeepUrlSyncOptions, createAuthenticatedSyncKit } from '@keepkit/core/core';
5
5
  import { KeepButtonProps as KeepButtonProps$1, UseKeepListResult, KeepErrorBoundaryProps, UseKeepNavigatorResult, CreateKeepKitOptions as CreateKeepKitOptions$1, KeepProviderProps, useKeepContext, useKeepItem, useKeepList, UseKeepNavigatorOptions, KeepShortcutOptions } from '@keepkit/core/react';
6
6
  export { KeepButtonState, KeepContextValue, KeepErrorBoundary, KeepErrorBoundaryProps, KeepProvider, KeepProviderProps, KeepShortcutOptions, useKeepContext, useKeepItem, useKeepList, useKeepNavigator, useKeepShortcut } from '@keepkit/core/react';
7
7
  export { FallbackStorageAdapter, IndexedDBAdapter, IndexedDBSyncQueueAdapter, LocalStorageAdapter, LocalStorageSyncQueueAdapter, SyncStorageAdapter, createBrowserStorageAdapter, createStorageAdapter } from '@keepkit/core/storage';
8
8
 
9
- type KeepUiLabelKey = "save" | "saved" | "remove" | "loading" | "saving" | "syncing" | "error" | "allTags" | "tags" | "filterTags" | "note" | "saveNote" | "noItems" | "loadingItems" | "errorItems" | "search" | "sort" | "newest" | "oldest" | "savedNewest" | "savedOldest" | "updatedNewest" | "updatedOldest" | "previousPage" | "nextPage" | "pagination" | "page" | "selectItems" | "selectedCount" | "deleteSelected" | "tagsToApply" | "applyTags" | "savedMessage" | "removedMessage" | "restoredMessage" | "syncFailedMessage" | "stalePrunedMessage" | "undo" | "undoAvailable" | "selectionScope" | "currentPage" | "searchResults" | "allItems" | "localVersion" | "remoteVersion" | "updatedAt" | "statusAvailable" | "noteSavedMessage" | "exportData" | "importData" | "importMode" | "merge" | "replace" | "importedCount" | "failedCount" | "storageQuotaError" | "statusExpired" | "statusRemoved" | "statusDeleted" | "statusPrivate" | "statusUnknown" | "retry" | "removeFromList" | "pruneStale" | "retrySync" | "resolveSync" | "keepLocal" | "useServer" | "manualMerge" | "close" | "backupRecovery" | "backupRecoveryDescription" | "syncPending" | "syncSynced" | "syncConflict";
10
- type KeepUiLabels = Partial<Record<KeepUiLabelKey, string>>;
11
- type KeepUiLocaleLabels = Record<KeepUiLabelKey, string>;
12
-
13
- declare const KEEP_BUILT_IN_LOCALES: readonly ["en", "ja", "ko", "zh-Hans", "zh-Hant", "th", "fr", "es", "pt-BR", "it", "de", "ru", "fil", "vi", "id", "ms"];
14
- type KeepUiLocale = (typeof KEEP_BUILT_IN_LOCALES)[number];
15
- declare function getKeepLocaleLabels(locale?: string): KeepUiLocaleLabels;
16
-
17
- type KeepUiLabelContext = {
18
- locale?: string;
19
- labels: Readonly<Record<KeepUiLabelKey, string>>;
20
- customLabels?: KeepUiLabels;
21
- labelResolver?: (key: KeepUiLabelKey, context: {
22
- locale?: string;
23
- }) => string | undefined;
24
- emitFeedback: <TMeta>(event: KeepUiFeedbackEvent<TMeta>) => void;
25
- };
26
- type KeepUiFeedbackBase<TType extends string> = {
27
- type: TType;
28
- message: string;
29
- };
30
- type KeepUiFeedbackEvent<TMeta = Record<string, unknown>> = (KeepUiFeedbackBase<"item-saved"> & {
31
- item: KeepItem<TMeta>;
32
- }) | (KeepUiFeedbackBase<"item-removed"> & {
33
- item: KeepItem<TMeta>;
34
- undo: () => void | Promise<void>;
35
- undoLabel: string;
36
- }) | (KeepUiFeedbackBase<"item-restored"> & {
37
- item?: KeepItem<TMeta>;
38
- items: KeepItem<TMeta>[];
39
- }) | KeepUiFeedbackBase<"sync-completed"> | (KeepUiFeedbackBase<"sync-failed"> & {
40
- error: unknown;
41
- }) | (KeepUiFeedbackBase<"stale-pruned"> & {
42
- item?: KeepItem<TMeta>;
43
- items: KeepItem<TMeta>[];
44
- undo: () => void | Promise<void>;
45
- undoLabel: string;
46
- });
47
- type KeepUiProviderProps<TMeta = Record<string, unknown>> = {
48
- labels?: KeepUiLabels;
49
- locale?: string;
50
- labelResolver?: KeepUiLabelContext["labelResolver"];
51
- onFeedback?: (event: KeepUiFeedbackEvent<TMeta>) => void;
52
- children?: ReactNode;
9
+ type KeepUrlAdapter = {
10
+ getUrl: () => string;
11
+ subscribe?: (listener: () => void) => () => void;
12
+ navigate: (url: string, mode: "replace" | "push") => void;
53
13
  };
54
- /** Provides one complete locale-aware label source to every UI primitive. */
55
- declare function KeepUiProvider<TMeta = Record<string, unknown>>({ labels, locale, labelResolver, onFeedback, children, }: KeepUiProviderProps<TMeta>): react.JSX.Element;
56
- declare function useKeepUiLabels(): KeepUiLabelContext;
57
-
58
- type KeepToastFeedbackOptions = {
59
- action?: {
60
- label: string;
61
- onClick: () => void;
14
+ type KeepPagesRouterLike = {
15
+ asPath?: string;
16
+ push: (url: string, as?: string, options?: {
17
+ shallow?: boolean;
18
+ }) => Promise<boolean> | boolean;
19
+ replace: (url: string, as?: string, options?: {
20
+ shallow?: boolean;
21
+ }) => Promise<boolean> | boolean;
22
+ events?: {
23
+ on: (event: string, listener: () => void) => void;
24
+ off: (event: string, listener: () => void) => void;
62
25
  };
63
26
  };
64
- type KeepToastHandler = (message: string, options?: KeepToastFeedbackOptions) => unknown;
65
- /** Adapts KeepKit feedback to Sonner-like toast functions without adding a toast dependency. */
66
- declare function useKeepToastFeedback<TMeta = Record<string, unknown>>(showToast: KeepToastHandler): (event: KeepUiFeedbackEvent<TMeta>) => void;
27
+ type KeepUrlSyncProps<TMeta = Record<string, unknown>> = {
28
+ enabled?: boolean;
29
+ query: KeepListQuery<TMeta>;
30
+ onQueryChange: (query: KeepListQuery<TMeta> | ((previous: KeepListQuery<TMeta>) => KeepListQuery<TMeta>)) => void;
31
+ options?: KeepUrlSyncOptions;
32
+ adapter?: KeepUrlAdapter;
33
+ };
34
+ /** Adapter for Next.js Pages Router. It intentionally uses structural typing and has no Next dependency. */
35
+ declare function createNextPagesRouterAdapter(router: KeepPagesRouterLike): KeepUrlAdapter;
36
+ /** Synchronizes collection filters with browser history and supports back/forward restoration. */
37
+ declare function useKeepUrlSync<TMeta = Record<string, unknown>>({ enabled, query, onQueryChange, options, adapter: providedAdapter, }: KeepUrlSyncProps<TMeta>): void;
67
38
 
68
39
  type KeepBackupProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
69
40
  filename?: string;
@@ -150,6 +121,22 @@ type KeepButtonProps<TMeta = Record<string, unknown>> = KeepButtonProps$1<TMeta>
150
121
  /** A style-free save toggle with localized labels and the core button's ARIA/asChild behavior. */
151
122
  declare function KeepButton<TMeta = Record<string, unknown>>({ labels, icons, iconOnly, showLabel, iconClassName, onClick, onToggleError, ...props }: KeepButtonProps<TMeta>): react.JSX.Element;
152
123
 
124
+ type KeepItemCheckboxProps<TMeta = Record<string, unknown>> = Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "checked" | "defaultChecked" | "onChange"> & {
125
+ item: KeepItem<TMeta>;
126
+ checked?: boolean;
127
+ label?: ReactNode;
128
+ onCheckedChange?: (checked: boolean) => void;
129
+ };
130
+ /** A reusable accessible selection checkbox for a saved item. */
131
+ declare function KeepItemCheckbox<TMeta = Record<string, unknown>>({ item, checked, label, onCheckedChange, "aria-label": ariaLabel, ...props }: KeepItemCheckboxProps<TMeta>): react.JSX.Element;
132
+
133
+ type KeepUndoProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
134
+ children?: ReactNode;
135
+ label?: ReactNode;
136
+ };
137
+ /** Presents the short-lived undo action created by removeWithUndo/removeBatchWithUndo. */
138
+ declare function KeepUndo({ children, label, ...props }: KeepUndoProps): react.JSX.Element | null;
139
+
153
140
  type KeepItemCardState<TMeta = Record<string, unknown>> = {
154
141
  item: KeepItem<TMeta>;
155
142
  isSaved: boolean;
@@ -216,6 +203,7 @@ declare function KeepItemCardMedia({ children, fallback, ...props }: KeepItemCar
216
203
  declare function KeepItemCardContent({ children, ...props }: KeepItemCardContentProps): react.JSX.Element;
217
204
  declare function KeepItemCardTitle({ as, children, ...props }: KeepItemCardTitleProps): react.DetailedReactHTMLElement<{
218
205
  "data-keep-card-part": string;
206
+ "data-line-clamp": string;
219
207
  onChange?: react.ChangeEventHandler<HTMLHeadingElement, Element> | undefined;
220
208
  onError?: react.ReactEventHandler<HTMLHeadingElement> | undefined;
221
209
  className?: string | undefined | undefined;
@@ -528,36 +516,6 @@ type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLEl
528
516
  /** A list primitive with built-in loading, empty, error, and removal states. */
529
517
  declare function KeepList<TMeta = Record<string, unknown>>(props: KeepListProps<TMeta>): react.JSX.Element;
530
518
 
531
- type KeepUrlAdapter = {
532
- getUrl: () => string;
533
- subscribe?: (listener: () => void) => () => void;
534
- navigate: (url: string, mode: "replace" | "push") => void;
535
- };
536
- type KeepPagesRouterLike = {
537
- asPath?: string;
538
- push: (url: string, as?: string, options?: {
539
- shallow?: boolean;
540
- }) => Promise<boolean> | boolean;
541
- replace: (url: string, as?: string, options?: {
542
- shallow?: boolean;
543
- }) => Promise<boolean> | boolean;
544
- events?: {
545
- on: (event: string, listener: () => void) => void;
546
- off: (event: string, listener: () => void) => void;
547
- };
548
- };
549
- type KeepUrlSyncProps<TMeta = Record<string, unknown>> = {
550
- enabled?: boolean;
551
- query: KeepListQuery<TMeta>;
552
- onQueryChange: (query: KeepListQuery<TMeta> | ((previous: KeepListQuery<TMeta>) => KeepListQuery<TMeta>)) => void;
553
- options?: KeepUrlSyncOptions;
554
- adapter?: KeepUrlAdapter;
555
- };
556
- /** Adapter for Next.js Pages Router. It intentionally uses structural typing and has no Next dependency. */
557
- declare function createNextPagesRouterAdapter(router: KeepPagesRouterLike): KeepUrlAdapter;
558
- /** Synchronizes collection filters with browser history and supports back/forward restoration. */
559
- declare function useKeepUrlSync<TMeta = Record<string, unknown>>({ enabled, query, onQueryChange, options, adapter: providedAdapter, }: KeepUrlSyncProps<TMeta>): void;
560
-
561
519
  type KeepCollectionFeature = "search" | "sort" | "pagination" | "tagFilter" | "bulkActions";
562
520
  type KeepLayoutPreset = "list" | "grid" | "compact" | "auto";
563
521
  type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
@@ -582,23 +540,6 @@ type KeepCollectionProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<
582
540
  /** A batteries-included collection with query controls and accessible status feedback. */
583
541
  declare function KeepCollection<TMeta = Record<string, unknown>>(props: KeepCollectionProps<TMeta>): react.JSX.Element;
584
542
 
585
- type KeepItemCheckboxProps<TMeta = Record<string, unknown>> = Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "checked" | "defaultChecked" | "onChange"> & {
586
- item: KeepItem<TMeta>;
587
- checked?: boolean;
588
- label?: ReactNode;
589
- onCheckedChange?: (checked: boolean) => void;
590
- };
591
- /** A reusable accessible selection checkbox for a saved item. */
592
- declare function KeepItemCheckbox<TMeta = Record<string, unknown>>({ item, checked, label, onCheckedChange, "aria-label": ariaLabel, ...props }: KeepItemCheckboxProps<TMeta>): react.JSX.Element;
593
-
594
- type KeepItemStatusBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
595
- status?: KeepItemStatus | "restricted";
596
- label?: ReactNode;
597
- };
598
- type KeepDisplayStatus = "available" | "expired" | "removed" | "restricted";
599
- /** Displays the normalized availability state of a saved item. */
600
- declare function KeepItemStatusBadge({ status, label, className, ...props }: KeepItemStatusBadgeProps): react.JSX.Element;
601
-
602
543
  type KeepLayoutProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
603
544
  layout?: KeepLayoutPreset;
604
545
  children?: ReactNode;
@@ -606,31 +547,6 @@ type KeepLayoutProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
606
547
  /** A container-aware layout wrapper with a stable preset attribute for host or theme CSS. */
607
548
  declare function KeepLayout({ layout, children, onKeyDown, onFocusCapture, ...props }: KeepLayoutProps): react.JSX.Element;
608
549
 
609
- type KeepNoteEditorState<TMeta = Record<string, unknown>> = {
610
- item: KeepItem<TMeta>;
611
- note: string;
612
- setNote: (note: string) => void;
613
- isDirty: boolean;
614
- isSaving: boolean;
615
- error: unknown | null;
616
- save: () => Promise<void>;
617
- };
618
- type KeepNoteEditorProps<TMeta = Record<string, unknown>> = Omit<FormHTMLAttributes<HTMLFormElement>, "children" | "onSubmit"> & {
619
- item: KeepItem<TMeta>;
620
- label?: ReactNode;
621
- saveLabel?: ReactNode;
622
- placeholder?: string;
623
- /** Automatically save dirty notes after this delay; set to 0 to disable auto-save. */
624
- debounceMs?: number;
625
- onSaved?: (note?: string) => void;
626
- onSaveError?: (error: unknown) => void;
627
- render?: RenderProp<KeepNoteEditorState<TMeta>>;
628
- children?: ReactNode | RenderProp<KeepNoteEditorState<TMeta>>;
629
- asChild?: boolean;
630
- };
631
- /** A controlled-by-default note editor that persists through useKeepItem. */
632
- declare function KeepNoteEditor<TMeta = Record<string, unknown>>({ item, label, saveLabel, placeholder, debounceMs, onSaved, onSaveError, render, children, asChild, className, ...formProps }: KeepNoteEditorProps<TMeta>): react.JSX.Element;
633
-
634
550
  type KeepReorderableItemState = {
635
551
  index: number;
636
552
  isDragging: boolean;
@@ -638,6 +554,7 @@ type KeepReorderableItemState = {
638
554
  role: "button";
639
555
  tabIndex: 0;
640
556
  draggable: true;
557
+ "data-drag-handle": "true";
641
558
  "aria-label": string;
642
559
  "aria-grabbed": boolean;
643
560
  onDragStart: () => void;
@@ -660,45 +577,30 @@ declare function KeepReorderableList<TItem extends {
660
577
  id: string;
661
578
  } = KeepItem>({ items, onReorder, renderItem, itemLabel, ...props }: KeepReorderableListProps<TItem>): react.JSX.Element;
662
579
 
663
- type KeepStaleNoticeProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
580
+ type KeepNoteEditorState<TMeta = Record<string, unknown>> = {
664
581
  item: KeepItem<TMeta>;
665
- onRetry?: (item: KeepItem<TMeta>) => void | Promise<void>;
666
- onRemoved?: (item: KeepItem<TMeta>) => void;
667
- retryLabel?: ReactNode;
668
- removeLabel?: ReactNode;
669
- children?: ReactNode;
582
+ note: string;
583
+ setNote: (note: string) => void;
584
+ isDirty: boolean;
585
+ isSaving: boolean;
586
+ error: unknown | null;
587
+ save: () => Promise<void>;
670
588
  };
671
- /** Provides retry and remove actions for an item whose source is no longer available. */
672
- declare function KeepStaleNotice<TMeta = Record<string, unknown>>({ item, onRetry, onRemoved, retryLabel, removeLabel, children, className, ...props }: KeepStaleNoticeProps<TMeta>): react.JSX.Element;
673
- type KeepPruneStaleButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
674
- statuses?: KeepItemStatus[];
589
+ type KeepNoteEditorProps<TMeta = Record<string, unknown>> = Omit<FormHTMLAttributes<HTMLFormElement>, "children" | "onSubmit"> & {
590
+ item: KeepItem<TMeta>;
675
591
  label?: ReactNode;
676
- onPruned?: (ids: string[]) => void;
677
- children?: ReactNode;
678
- };
679
- /** Removes all unavailable items through the provider's undo-capable batch action. */
680
- declare function KeepPruneStaleButton<TMeta = Record<string, unknown>>({ statuses, label, onPruned, children, disabled, ...props }: KeepPruneStaleButtonProps): react.JSX.Element;
681
-
682
- type KeepSyncRecoveryDialogProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & {
683
- open?: boolean;
684
- onOpenChange?: (open: boolean) => void;
685
- conflicts?: KeepSyncConflict<TMeta>[];
686
- onManualMerge?: (conflict: KeepSyncConflict<TMeta>) => KeepItem<TMeta> | Promise<KeepItem<TMeta>>;
687
- backup?: ReactNode;
688
- showBackupControls?: boolean;
689
- title?: ReactNode;
690
- children?: ReactNode;
691
- };
692
- /** Resolves queued sync conflicts and guides users to restore a backup after data corruption. */
693
- declare function KeepSyncRecoveryDialog<TMeta = Record<string, unknown>>({ open, onOpenChange, conflicts, onManualMerge, backup, showBackupControls, title, children, className, ...props }: KeepSyncRecoveryDialogProps<TMeta>): react.JSX.Element | null;
694
-
695
- type KeepSyncStatusBannerProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
696
- onRetry?: () => void | Promise<void>;
697
- onResolveConflicts?: () => void;
698
- children?: ReactNode;
592
+ saveLabel?: ReactNode;
593
+ placeholder?: string;
594
+ /** Automatically save dirty notes after this delay; set to 0 to disable auto-save. */
595
+ debounceMs?: number;
596
+ onSaved?: (note?: string) => void;
597
+ onSaveError?: (error: unknown) => void;
598
+ render?: RenderProp<KeepNoteEditorState<TMeta>>;
599
+ children?: ReactNode | RenderProp<KeepNoteEditorState<TMeta>>;
600
+ asChild?: boolean;
699
601
  };
700
- /** Announces synchronization failures and exposes retry or conflict-recovery entry points. */
701
- declare function KeepSyncStatusBanner({ onRetry, onResolveConflicts, children, className, ...props }: KeepSyncStatusBannerProps): react.JSX.Element | null;
602
+ /** A controlled-by-default note editor that persists through useKeepItem. */
603
+ declare function KeepNoteEditor<TMeta = Record<string, unknown>>({ item, label, saveLabel, placeholder, debounceMs, onSaved, onSaveError, render, children, asChild, className, ...formProps }: KeepNoteEditorProps<TMeta>): react.JSX.Element;
702
604
 
703
605
  type KeepTagEditorState = {
704
606
  tags: string[];
@@ -716,27 +618,72 @@ type KeepTagEditorProps<TMeta = Record<string, unknown>> = Omit<FormHTMLAttribut
716
618
  /** Edits one item's normalized tag set; Enter adds and Backspace removes the last tag. */
717
619
  declare function KeepTagEditor<TMeta = Record<string, unknown>>({ item, availableTags, onSaved, onSaveError, render, ...props }: KeepTagEditorProps<TMeta>): react.JSX.Element;
718
620
 
719
- type KeepTagFilterState = {
720
- tags: string[];
721
- tagCounts: Record<string, number>;
722
- value?: string;
723
- select: (tag?: string) => void;
621
+ type KeepUiLabelKey = "save" | "saved" | "remove" | "loading" | "saving" | "syncing" | "error" | "allTags" | "tags" | "filterTags" | "note" | "saveNote" | "noItems" | "loadingItems" | "errorItems" | "search" | "sort" | "newest" | "oldest" | "savedNewest" | "savedOldest" | "updatedNewest" | "updatedOldest" | "previousPage" | "nextPage" | "pagination" | "page" | "selectItems" | "selectedCount" | "deleteSelected" | "tagsToApply" | "applyTags" | "savedMessage" | "removedMessage" | "restoredMessage" | "syncFailedMessage" | "stalePrunedMessage" | "undo" | "undoAvailable" | "selectionScope" | "currentPage" | "searchResults" | "allItems" | "localVersion" | "remoteVersion" | "updatedAt" | "statusAvailable" | "noteSavedMessage" | "exportData" | "importData" | "importMode" | "merge" | "replace" | "importedCount" | "failedCount" | "storageQuotaError" | "statusExpired" | "statusRemoved" | "statusDeleted" | "statusPrivate" | "statusUnknown" | "retry" | "removeFromList" | "pruneStale" | "retrySync" | "resolveSync" | "keepLocal" | "useServer" | "manualMerge" | "close" | "backupRecovery" | "backupRecoveryDescription" | "syncPending" | "syncSynced" | "syncConflict";
622
+ type KeepUiLabels = Partial<Record<KeepUiLabelKey, string>>;
623
+ type KeepUiLocaleLabels = Record<KeepUiLabelKey, string>;
624
+
625
+ declare const KEEP_BUILT_IN_LOCALES: readonly ["en", "ja", "ko", "zh-Hans", "zh-Hant", "th", "fr", "es", "pt-BR", "it", "de", "ru", "fil", "vi", "id", "ms"];
626
+ type KeepUiLocale = (typeof KEEP_BUILT_IN_LOCALES)[number];
627
+ declare function getKeepLocaleLabels(locale?: string): KeepUiLocaleLabels;
628
+
629
+ type KeepUiLabelContext = {
630
+ locale?: string;
631
+ labels: Readonly<Record<KeepUiLabelKey, string>>;
632
+ customLabels?: KeepUiLabels;
633
+ labelResolver?: (key: KeepUiLabelKey, context: {
634
+ locale?: string;
635
+ }) => string | undefined;
636
+ emitFeedback: <TMeta>(event: KeepUiFeedbackEvent<TMeta>) => void;
724
637
  };
725
- type KeepTagFilterProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "onChange"> & {
726
- query?: KeepListQuery<TMeta>;
727
- value?: string;
728
- defaultValue?: string;
729
- onChange?: (tag?: string) => void;
730
- onValueChange?: (tag?: string) => void;
731
- allLabel?: ReactNode;
732
- ariaLabel?: string;
733
- renderTag?: (tag: string, count: number, selected: boolean) => ReactNode;
734
- render?: RenderProp<KeepTagFilterState>;
735
- children?: ReactNode | RenderProp<KeepTagFilterState>;
736
- asChild?: boolean;
638
+ type KeepUiFeedbackBase<TType extends string> = {
639
+ type: TType;
640
+ message: string;
737
641
  };
738
- /** An ARIA button group for tag filtering; consumers can connect value to a collection query. */
739
- declare function KeepTagFilter<TMeta = Record<string, unknown>>({ query, value: controlledValue, defaultValue, onChange, onValueChange, allLabel, ariaLabel, renderTag, render, children, asChild, className, ...rootProps }: KeepTagFilterProps<TMeta>): react.ReactElement<unknown, string | react.JSXElementConstructor<any>>;
642
+ type KeepUiFeedbackEvent<TMeta = Record<string, unknown>> = (KeepUiFeedbackBase<"item-saved"> & {
643
+ item: KeepItem<TMeta>;
644
+ }) | (KeepUiFeedbackBase<"item-removed"> & {
645
+ item: KeepItem<TMeta>;
646
+ undo: () => void | Promise<void>;
647
+ undoLabel: string;
648
+ }) | (KeepUiFeedbackBase<"item-restored"> & {
649
+ item?: KeepItem<TMeta>;
650
+ items: KeepItem<TMeta>[];
651
+ }) | KeepUiFeedbackBase<"sync-completed"> | (KeepUiFeedbackBase<"sync-failed"> & {
652
+ error: unknown;
653
+ }) | (KeepUiFeedbackBase<"stale-pruned"> & {
654
+ item?: KeepItem<TMeta>;
655
+ items: KeepItem<TMeta>[];
656
+ undo: () => void | Promise<void>;
657
+ undoLabel: string;
658
+ });
659
+ type KeepUiProviderProps<TMeta = Record<string, unknown>> = {
660
+ labels?: KeepUiLabels;
661
+ locale?: string;
662
+ labelResolver?: KeepUiLabelContext["labelResolver"];
663
+ onFeedback?: (event: KeepUiFeedbackEvent<TMeta>) => void;
664
+ children?: ReactNode;
665
+ };
666
+ /** Provides one complete locale-aware label source to every UI primitive. */
667
+ declare function KeepUiProvider<TMeta = Record<string, unknown>>({ labels, locale, labelResolver, onFeedback, children, }: KeepUiProviderProps<TMeta>): react.JSX.Element;
668
+ declare function useKeepUiLabels(): KeepUiLabelContext;
669
+
670
+ type KeepToastFeedbackOptions = {
671
+ action?: {
672
+ label: string;
673
+ onClick: () => void;
674
+ };
675
+ };
676
+ type KeepToastHandler = (message: string, options?: KeepToastFeedbackOptions) => unknown;
677
+ /** Adapts KeepKit feedback to Sonner-like toast functions without adding a toast dependency. */
678
+ declare function useKeepToastFeedback<TMeta = Record<string, unknown>>(showToast: KeepToastHandler): (event: KeepUiFeedbackEvent<TMeta>) => void;
679
+
680
+ type KeepItemStatusBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
681
+ status?: KeepItemStatus | "restricted";
682
+ label?: ReactNode;
683
+ };
684
+ type KeepDisplayStatus = "available" | "expired" | "removed" | "restricted";
685
+ /** Displays the normalized availability state of a saved item. */
686
+ declare function KeepItemStatusBadge({ status, label, className, ...props }: KeepItemStatusBadgeProps): react.JSX.Element;
740
687
 
741
688
  type KeepTourShortcutsOptions = {
742
689
  onNext: () => void | Promise<void>;
@@ -768,17 +715,33 @@ type KeepTourBarProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTM
768
715
  keyboardShortcuts?: boolean;
769
716
  shortcutOptions?: Omit<KeepTourShortcutsOptions, "onNext" | "onPrev">;
770
717
  progress?: ReactNode;
718
+ getItemTitle?: (item: KeepItem<TMeta>) => ReactNode;
771
719
  };
772
720
  /** Headless previous/current/next navigation with optional URL links and keyboard shortcuts. */
773
- declare function KeepTourBar<TMeta = Record<string, unknown>>({ navigation: providedNavigation, currentId, initialIndex, showProgress, prevHref, nextHref, backHref, onPrev, onNext, onBack, prevLabel, nextLabel, backLabel, keyboardShortcuts, shortcutOptions, progress, ...props }: KeepTourBarProps<TMeta>): react.JSX.Element;
721
+ declare function KeepTourBar<TMeta = Record<string, unknown>>({ navigation: providedNavigation, currentId, initialIndex, showProgress, prevHref, nextHref, backHref, onPrev, onNext, onBack, prevLabel, nextLabel, backLabel, keyboardShortcuts, shortcutOptions, progress, getItemTitle, ...props }: KeepTourBarProps<TMeta>): react.JSX.Element;
774
722
  declare const KeepNavigator: typeof KeepTourBar;
775
723
 
776
- type KeepUndoProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
777
- children?: ReactNode;
778
- label?: ReactNode;
724
+ type KeepTagFilterState = {
725
+ tags: string[];
726
+ tagCounts: Record<string, number>;
727
+ value?: string;
728
+ select: (tag?: string) => void;
779
729
  };
780
- /** Presents the short-lived undo action created by removeWithUndo/removeBatchWithUndo. */
781
- declare function KeepUndo({ children, label, ...props }: KeepUndoProps): react.JSX.Element | null;
730
+ type KeepTagFilterProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "onChange"> & {
731
+ query?: KeepListQuery<TMeta>;
732
+ value?: string;
733
+ defaultValue?: string;
734
+ onChange?: (tag?: string) => void;
735
+ onValueChange?: (tag?: string) => void;
736
+ allLabel?: ReactNode;
737
+ ariaLabel?: string;
738
+ renderTag?: (tag: string, count: number, selected: boolean) => ReactNode;
739
+ render?: RenderProp<KeepTagFilterState>;
740
+ children?: ReactNode | RenderProp<KeepTagFilterState>;
741
+ asChild?: boolean;
742
+ };
743
+ /** An ARIA button group for tag filtering; consumers can connect value to a collection query. */
744
+ declare function KeepTagFilter<TMeta = Record<string, unknown>>({ query, value: controlledValue, defaultValue, onChange, onValueChange, allLabel, ariaLabel, renderTag, render, children, asChild, className, ...rootProps }: KeepTagFilterProps<TMeta>): react.ReactElement<unknown, string | react.JSXElementConstructor<any>>;
782
745
 
783
746
  type KeepSearchInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "defaultValue" | "onChange"> & {
784
747
  value?: string;
@@ -813,6 +776,25 @@ type KeepPaginationProps = Omit<React.HTMLAttributes<HTMLElement>, "children"> &
813
776
  /** Accessible pagination with previous/next controls and numbered page buttons. */
814
777
  declare function KeepPagination({ totalCount, pageSize, page, maxPageButtons, onPageChange, render, ...props }: KeepPaginationProps): react.JSX.Element;
815
778
 
779
+ type KeepStaleNoticeProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
780
+ item: KeepItem<TMeta>;
781
+ onRetry?: (item: KeepItem<TMeta>) => void | Promise<void>;
782
+ onRemoved?: (item: KeepItem<TMeta>) => void;
783
+ retryLabel?: ReactNode;
784
+ removeLabel?: ReactNode;
785
+ children?: ReactNode;
786
+ };
787
+ /** Provides retry and remove actions for an item whose source is no longer available. */
788
+ declare function KeepStaleNotice<TMeta = Record<string, unknown>>({ item, onRetry, onRemoved, retryLabel, removeLabel, children, className, ...props }: KeepStaleNoticeProps<TMeta>): react.JSX.Element;
789
+ type KeepPruneStaleButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
790
+ statuses?: KeepItemStatus[];
791
+ label?: ReactNode;
792
+ onPruned?: (ids: string[]) => void;
793
+ children?: ReactNode;
794
+ };
795
+ /** Removes all unavailable items through the provider's undo-capable batch action. */
796
+ declare function KeepPruneStaleButton<TMeta = Record<string, unknown>>({ statuses, label, onPruned, children, disabled, ...props }: KeepPruneStaleButtonProps): react.JSX.Element;
797
+
816
798
  type KeepEmptyStateProps = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & {
817
799
  title?: ReactNode;
818
800
  description?: ReactNode;
@@ -847,6 +829,27 @@ declare function KeepAnnouncements<TMeta = Record<string, unknown>>({ messages,
847
829
  /** Singular alias for applications that mount one announcer explicitly. */
848
830
  declare const KeepAnnouncer: typeof KeepAnnouncements;
849
831
 
832
+ type KeepSyncRecoveryDialogProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & {
833
+ open?: boolean;
834
+ onOpenChange?: (open: boolean) => void;
835
+ conflicts?: KeepSyncConflict<TMeta>[];
836
+ onManualMerge?: (conflict: KeepSyncConflict<TMeta>) => KeepItem<TMeta> | Promise<KeepItem<TMeta>>;
837
+ backup?: ReactNode;
838
+ showBackupControls?: boolean;
839
+ title?: ReactNode;
840
+ children?: ReactNode;
841
+ };
842
+ /** Resolves queued sync conflicts and guides users to restore a backup after data corruption. */
843
+ declare function KeepSyncRecoveryDialog<TMeta = Record<string, unknown>>({ open, onOpenChange, conflicts, onManualMerge, backup, showBackupControls, title, children, className, ...props }: KeepSyncRecoveryDialogProps<TMeta>): react.JSX.Element | null;
844
+
845
+ type KeepSyncStatusBannerProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
846
+ onRetry?: () => void | Promise<void>;
847
+ onResolveConflicts?: () => void;
848
+ children?: ReactNode;
849
+ };
850
+ /** Announces synchronization failures and exposes retry or conflict-recovery entry points. */
851
+ declare function KeepSyncStatusBanner({ onRetry, onResolveConflicts, children, className, ...props }: KeepSyncStatusBannerProps): react.JSX.Element | null;
852
+
850
853
  declare const keepThemeNames: readonly ["default", "ocean", "forest", "sunset", "lavender", "compact", "minimal", "rounded", "high-contrast", "dark"];
851
854
  type KeepThemeName = (typeof keepThemeNames)[number];
852
855
  type KeepThemeMode = "light" | "dark" | "system";