@keepkit/ui 0.19.0 → 0.20.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 +4 -4
- package/dist/index.d.ts +19 -2
- package/dist/index.js +102 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ function SavedArticles() {
|
|
|
60
60
|
`KeepCollection`は検索語と選択タグを`KeepActiveFiltersSummary`のチップとして表示し、個別解除と「すべての条件をクリア」を提供します。`activeFilters`でこの領域を差し替えられます。標準の`KeepList` / `KeepCollection`は、全件0件の`empty-storage`と絞り込み結果0件の`empty-filtered`を区別し、後者では`onClearFilters`付きの解除ボタンを表示します。
|
|
61
61
|
`KeepItemCard`は`href`、`onOpen`、`linkTarget`、`linkComponent`に対応し、保存アイテムから詳細ページへ遷移できます。非公開・期限切れ等の`status`を持つアイテムは自動的にリンクを無効化します。`KeepBackup`はJSONのエクスポート、merge / replaceインポート、結果件数、容量エラー表示を提供します。
|
|
62
62
|
`KeepTourBar`(alias: `KeepNavigator`)は進行度、前へ・次へ、一覧へ戻る操作をURLまたはコールバックで提供します。前後ボタンには隣接アイテム名のプレビューが付き、`getItemTitle`で表示名を差し替えられます。`keyboardShortcuts`を指定するとJ/Kまたは]/[で巡回でき、`useKeepTourShortcuts`ではキーと動作を個別に差し替えられます。`KeepReorderableList`はドラッグ操作と矢印キーによる並び替えを提供し、ドラッグ中の挿入位置を表示します。
|
|
63
|
-
`KeepShortcutHint`はセマンティックな`<kbd>`バッジを表示します。`KeepTourBar showShortcutHint`は前へ/次へのキーを、`KeepNoteEditor showShortcutHint`は`Ctrl+Enter`を標準ボタン内に表示します。`mergeProps` / `createSlot`は`asChild`でclassName、style、ARIA
|
|
63
|
+
`KeepShortcutHint`はセマンティックな`<kbd>`バッジを表示します。`KeepTourBar showShortcutHint`は前へ/次へのキーを、`KeepNoteEditor showShortcutHint`は`Ctrl+Enter`を標準ボタン内に表示します。`mergeProps` / `createSlot`は`asChild`でclassName、style、ARIA属性、イベント、子と親のrefを合成し、`composeRefs`はcallback refとobject refをまとめる共通基盤です。フィルターチップは削除後に隣接チップへ戻り、ArrowLeft / ArrowRightで移動できます。
|
|
64
64
|
`KeepList`や`KeepCollection`のカードは検索語を大文字小文字を区別せず`<mark class="keep-highlight" data-highlight="true">`で表示します。単体の`KeepItemCard`では`highlightQuery`、任意のテキストでは`KeepHighlight`を使えます。`KeepItemCard.Media`は読み込み状態を`data-media-status`で公開し、失敗時は`fallback`または標準SVGへ切り替わります。
|
|
65
65
|
テーマCSSではハイライト用の`--keep-highlight-bg` / `--keep-highlight-fg`(ライト/ダーク対応)、タイトル2行・メモプレビュー3行の制限、メディアの固定アスペクト比を適用します。`KeepItemStatusBadge`は状態ラベルに加えてチェック・時計・進入禁止・鍵のSVGアイコンを表示し、状態ごとの形状とトーンを組み合わせます。個別の状態スタイルは`@keepkit/ui/styles/status.css`からも読み込めます。
|
|
66
66
|
外部URLの詳細リンクには`target="_blank"`と`rel="noreferrer"`が既定で補完され、利用できないカードには`aria-disabled="true"`と`data-item-status`が付与されます。同期競合ダイアログではローカルとリモートの更新日時・メモを並べて確認できます。
|
|
@@ -88,7 +88,7 @@ const onFeedback = useKeepToastFeedback(toast);
|
|
|
88
88
|
<KeepKitProvider storage={storage} onFeedback={onFeedback}>{children}</KeepKitProvider>;
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
v0.
|
|
91
|
+
v0.20.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`から利用できます。
|
|
92
92
|
Phase 4の状態UIとして`KeepItemStatusBadge`、`KeepStaleNotice`、`KeepPruneStaleButton`、`KeepSyncStatusBanner`、`KeepSyncRecoveryDialog`を利用できます。`import "@keepkit/ui/theme.css"`でテーマCSSを有効にできます。
|
|
93
93
|
|
|
94
94
|
### Tailwind/shadcnテーマ
|
|
@@ -179,7 +179,7 @@ function SavedArticles() {
|
|
|
179
179
|
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.
|
|
180
180
|
`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.
|
|
181
181
|
`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.
|
|
182
|
-
`KeepShortcutHint` renders semantic `<kbd>` badges. `KeepTourBar showShortcutHint` displays the previous/next keys, while `KeepNoteEditor showShortcutHint` displays `Ctrl+Enter` in the save button. `mergeProps` / `createSlot`
|
|
182
|
+
`KeepShortcutHint` renders semantic `<kbd>` badges. `KeepTourBar showShortcutHint` displays the previous/next keys, while `KeepNoteEditor showShortcutHint` displays `Ctrl+Enter` in the save button. `mergeProps` / `createSlot` compose className, style, ARIA, events, and child/parent refs for `asChild` slots; `composeRefs` combines callback and object refs. Filter chips restore focus to an adjacent chip after removal and support ArrowLeft / ArrowRight navigation.
|
|
183
183
|
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.
|
|
184
184
|
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.
|
|
185
185
|
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.
|
|
@@ -207,7 +207,7 @@ const onFeedback = useKeepToastFeedback(toast);
|
|
|
207
207
|
<KeepKitProvider storage={storage} onFeedback={onFeedback}>{children}</KeepKitProvider>;
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
-
In v0.
|
|
210
|
+
In v0.20.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`.
|
|
211
211
|
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.
|
|
212
212
|
|
|
213
213
|
### Tailwind and shadcn theme
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { HTMLAttributes, ReactNode, ComponentType, ReactElement, InputHTMLAttributes, ImgHTMLAttributes, MouseEvent, HTMLAttributeAnchorTarget, KeyboardEvent, FormHTMLAttributes, SelectHTMLAttributes, ButtonHTMLAttributes, CSSProperties } from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode, ComponentType, Ref, RefCallback, ReactElement, InputHTMLAttributes, ImgHTMLAttributes, MouseEvent, HTMLAttributeAnchorTarget, KeyboardEvent, FormHTMLAttributes, SelectHTMLAttributes, ButtonHTMLAttributes, CSSProperties } from 'react';
|
|
3
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';
|
|
@@ -73,6 +73,8 @@ type KeepButtonIcons = {
|
|
|
73
73
|
error?: KeepButtonIcon;
|
|
74
74
|
};
|
|
75
75
|
type MergeableProps = Record<string, unknown>;
|
|
76
|
+
/** Combines callback and object refs while preserving every ref target. */
|
|
77
|
+
declare function composeRefs<T>(...refs: Array<Ref<T> | null | undefined>): RefCallback<T>;
|
|
76
78
|
/** Chains child and component event handlers while preserving both handlers' event order. */
|
|
77
79
|
declare function chainedFunction<T extends (...args: never[]) => unknown>(childHandler: T | undefined, parentHandler: T | undefined): T | undefined;
|
|
78
80
|
/** Merges slot props without dropping child classes, styles, ARIA attributes, or events. */
|
|
@@ -118,6 +120,9 @@ type KeepBulkActionsProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes
|
|
|
118
120
|
declare function KeepBulkActions<TMeta = Record<string, unknown>>({ query, selectedIds: controlledSelectedIds, defaultSelectedIds, onSelectedIdsChange, renderItem, onCompleted, selectionScope: controlledScope, onSelectionScopeChange, render, children, ...props }: KeepBulkActionsProps<TMeta>): react.JSX.Element;
|
|
119
121
|
|
|
120
122
|
type KeepButtonProps<TMeta = Record<string, unknown>> = KeepButtonProps$1<TMeta> & {
|
|
123
|
+
ref?: Ref<HTMLElement> | {
|
|
124
|
+
readonly current: unknown;
|
|
125
|
+
};
|
|
121
126
|
labels?: KeepButtonLabels;
|
|
122
127
|
icons?: KeepButtonIcons;
|
|
123
128
|
iconOnly?: boolean;
|
|
@@ -163,6 +168,9 @@ type KeepImageProps = ImgHTMLAttributes<HTMLImageElement> & {
|
|
|
163
168
|
alt: string;
|
|
164
169
|
};
|
|
165
170
|
type KeepItemCardProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & {
|
|
171
|
+
ref?: Ref<HTMLElement> | {
|
|
172
|
+
readonly current: unknown;
|
|
173
|
+
};
|
|
166
174
|
item: KeepItem<TMeta>;
|
|
167
175
|
title?: ReactNode | ((item: KeepItem<TMeta>) => ReactNode);
|
|
168
176
|
getTitle?: (item: KeepItem<TMeta>) => ReactNode;
|
|
@@ -503,6 +511,9 @@ declare function KeepItemCardSkeleton({ layout, ...props }: KeepItemCardSkeleton
|
|
|
503
511
|
|
|
504
512
|
type KeepListState<TMeta = Record<string, unknown>> = UseKeepListResult<TMeta>;
|
|
505
513
|
type KeepListProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
|
|
514
|
+
ref?: Ref<HTMLElement> | {
|
|
515
|
+
readonly current: unknown;
|
|
516
|
+
};
|
|
506
517
|
query?: KeepListQuery<TMeta>;
|
|
507
518
|
children?: ReactNode | RenderProp<KeepListState<TMeta>>;
|
|
508
519
|
renderItem?: (item: KeepItem<TMeta>, state: KeepListState<TMeta>) => ReactNode;
|
|
@@ -715,6 +726,9 @@ type KeepTourShortcutsOptions = {
|
|
|
715
726
|
declare function useKeepTourShortcuts({ onNext, onPrev, enabled, allowInEditable, preventDefault, nextKeys, prevKeys, onError, }: KeepTourShortcutsOptions): void;
|
|
716
727
|
|
|
717
728
|
type KeepTourBarProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
|
|
729
|
+
ref?: Ref<HTMLElement> | {
|
|
730
|
+
readonly current: unknown;
|
|
731
|
+
};
|
|
718
732
|
navigation?: UseKeepNavigatorResult<TMeta>;
|
|
719
733
|
currentId?: string;
|
|
720
734
|
initialIndex?: number;
|
|
@@ -741,6 +755,9 @@ declare function KeepTourBar<TMeta = Record<string, unknown>>({ navigation: prov
|
|
|
741
755
|
declare const KeepNavigator: typeof KeepTourBar;
|
|
742
756
|
|
|
743
757
|
type KeepActiveFiltersSummaryProps<TMeta = Record<string, unknown>> = Omit<HTMLAttributes<HTMLElement>, "children"> & {
|
|
758
|
+
ref?: Ref<HTMLElement> | {
|
|
759
|
+
readonly current: unknown;
|
|
760
|
+
};
|
|
744
761
|
query?: KeepListQuery<TMeta>;
|
|
745
762
|
search?: string;
|
|
746
763
|
tags?: readonly string[];
|
|
@@ -960,4 +977,4 @@ type KeepKit<TMeta = Record<string, unknown>> = {
|
|
|
960
977
|
/** Create one typed application API for the core and standard UI layer. */
|
|
961
978
|
declare function createKeepKit<TMeta = Record<string, unknown>>(options?: CreateKeepKitOptions<TMeta>): KeepKit<TMeta>;
|
|
962
979
|
|
|
963
|
-
export { type CreateKeepKitOptions, KeepActiveFiltersSummary, type KeepActiveFiltersSummaryProps, type KeepActiveFiltersSummaryState, KeepAnnouncements, type KeepAnnouncementsProps, KeepAnnouncer, KeepBackup, type KeepBackupProps, KeepBulkActions, type KeepBulkActionsProps, type KeepBulkActionsState, KeepButton, type KeepButtonIcon, type KeepButtonIconProps, type KeepButtonIcons, type KeepButtonLabels, type KeepButtonProps, KeepCollection, type KeepCollectionFeature, type KeepCollectionProps, type KeepDisplayStatus, KeepEmptyState, type KeepEmptyStateProps, type KeepEmptyStateVariant, KeepHighlight, type KeepHighlightProps, type KeepImageProps, KeepItemCard, type KeepItemCardActionsProps, type KeepItemCardContentProps, type KeepItemCardLinkProps, type KeepItemCardMediaProps, type KeepItemCardProps, KeepItemCardSkeleton, type KeepItemCardSkeletonProps, type KeepItemCardState, type KeepItemCardTagsProps, type KeepItemCardTitleProps, KeepItemCheckbox, type KeepItemCheckboxProps, KeepItemStatusBadge, type KeepItemStatusBadgeProps, type KeepKit, KeepKitProvider, type KeepKitProviderProps, KeepLayout, type KeepLayoutPreset, type KeepLayoutProps, KeepList, type KeepListProps, type KeepListState, KeepNavigator, KeepNoteEditor, type KeepNoteEditorProps, type KeepNoteEditorState, type KeepPagesRouterLike, KeepPagination, type KeepPaginationProps, type KeepPaginationState, KeepPruneStaleButton, type KeepPruneStaleButtonProps, type KeepReorderableItemState, KeepReorderableList, type KeepReorderableListProps, KeepSearchInput, type KeepSearchInputProps, type KeepSelectionScope, KeepShortcutHint, type KeepShortcutHintProps, KeepSortSelect, type KeepSortSelectProps, type KeepSortValue, KeepStaleNotice, type KeepStaleNoticeProps, KeepStatus, type KeepStatusLabels, type KeepStatusProps, type KeepStatusState, type KeepStatusValue, KeepSyncRecoveryDialog, type KeepSyncRecoveryDialogProps, KeepSyncStatusBanner, type KeepSyncStatusBannerProps, KeepTagEditor, type KeepTagEditorProps, type KeepTagEditorState, KeepTagFilter, type KeepTagFilterProps, type KeepTagFilterState, type KeepThemeDensity, type KeepThemeMode, type KeepThemeName, KeepThemeProvider, type KeepThemeProviderProps, type KeepThemeRadius, type KeepThemeVariables, type KeepToastFeedbackOptions, type KeepToastHandler, KeepTourBar, type KeepTourBarProps, type KeepTourShortcutsOptions, type KeepUiFeedbackEvent, type KeepUiLabelContext, type KeepUiLabelKey, type KeepUiLabels, type KeepUiLocale, type KeepUiLocaleLabels, KeepUiProvider, type KeepUiProviderProps, KeepUndo, type KeepUndoProps, type KeepUrlAdapter, type RenderProp, chainedFunction, createKeepKit, createNextPagesRouterAdapter, createSlot, getKeepLocaleLabels, highlightText, isAllSelected, keepThemeNames, mergeProps, toggleSelectAll, useKeepToastFeedback, useKeepTourShortcuts, useKeepUiLabels, useKeepUrlSync };
|
|
980
|
+
export { type CreateKeepKitOptions, KeepActiveFiltersSummary, type KeepActiveFiltersSummaryProps, type KeepActiveFiltersSummaryState, KeepAnnouncements, type KeepAnnouncementsProps, KeepAnnouncer, KeepBackup, type KeepBackupProps, KeepBulkActions, type KeepBulkActionsProps, type KeepBulkActionsState, KeepButton, type KeepButtonIcon, type KeepButtonIconProps, type KeepButtonIcons, type KeepButtonLabels, type KeepButtonProps, KeepCollection, type KeepCollectionFeature, type KeepCollectionProps, type KeepDisplayStatus, KeepEmptyState, type KeepEmptyStateProps, type KeepEmptyStateVariant, KeepHighlight, type KeepHighlightProps, type KeepImageProps, KeepItemCard, type KeepItemCardActionsProps, type KeepItemCardContentProps, type KeepItemCardLinkProps, type KeepItemCardMediaProps, type KeepItemCardProps, KeepItemCardSkeleton, type KeepItemCardSkeletonProps, type KeepItemCardState, type KeepItemCardTagsProps, type KeepItemCardTitleProps, KeepItemCheckbox, type KeepItemCheckboxProps, KeepItemStatusBadge, type KeepItemStatusBadgeProps, type KeepKit, KeepKitProvider, type KeepKitProviderProps, KeepLayout, type KeepLayoutPreset, type KeepLayoutProps, KeepList, type KeepListProps, type KeepListState, KeepNavigator, KeepNoteEditor, type KeepNoteEditorProps, type KeepNoteEditorState, type KeepPagesRouterLike, KeepPagination, type KeepPaginationProps, type KeepPaginationState, KeepPruneStaleButton, type KeepPruneStaleButtonProps, type KeepReorderableItemState, KeepReorderableList, type KeepReorderableListProps, KeepSearchInput, type KeepSearchInputProps, type KeepSelectionScope, KeepShortcutHint, type KeepShortcutHintProps, KeepSortSelect, type KeepSortSelectProps, type KeepSortValue, KeepStaleNotice, type KeepStaleNoticeProps, KeepStatus, type KeepStatusLabels, type KeepStatusProps, type KeepStatusState, type KeepStatusValue, KeepSyncRecoveryDialog, type KeepSyncRecoveryDialogProps, KeepSyncStatusBanner, type KeepSyncStatusBannerProps, KeepTagEditor, type KeepTagEditorProps, type KeepTagEditorState, KeepTagFilter, type KeepTagFilterProps, type KeepTagFilterState, type KeepThemeDensity, type KeepThemeMode, type KeepThemeName, KeepThemeProvider, type KeepThemeProviderProps, type KeepThemeRadius, type KeepThemeVariables, type KeepToastFeedbackOptions, type KeepToastHandler, KeepTourBar, type KeepTourBarProps, type KeepTourShortcutsOptions, type KeepUiFeedbackEvent, type KeepUiLabelContext, type KeepUiLabelKey, type KeepUiLabels, type KeepUiLocale, type KeepUiLocaleLabels, KeepUiProvider, type KeepUiProviderProps, KeepUndo, type KeepUndoProps, type KeepUrlAdapter, type RenderProp, chainedFunction, composeRefs, createKeepKit, createNextPagesRouterAdapter, createSlot, getKeepLocaleLabels, highlightText, isAllSelected, keepThemeNames, mergeProps, toggleSelectAll, useKeepToastFeedback, useKeepTourShortcuts, useKeepUiLabels, useKeepUrlSync };
|
package/dist/index.js
CHANGED
|
@@ -1712,7 +1712,8 @@ import {
|
|
|
1712
1712
|
cloneElement,
|
|
1713
1713
|
createContext as createContext2,
|
|
1714
1714
|
isValidElement,
|
|
1715
|
-
useContext as useContext2
|
|
1715
|
+
useContext as useContext2,
|
|
1716
|
+
useMemo as useMemo2
|
|
1716
1717
|
} from "react";
|
|
1717
1718
|
import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
|
|
1718
1719
|
var KeepSearchQueryContext = createContext2(void 0);
|
|
@@ -1725,8 +1726,11 @@ function useKeepSearchQuery() {
|
|
|
1725
1726
|
function KeepHighlight({ children, query }) {
|
|
1726
1727
|
const contextQuery = useKeepSearchQuery();
|
|
1727
1728
|
const resolvedQuery = query ?? contextQuery;
|
|
1728
|
-
|
|
1729
|
-
return
|
|
1729
|
+
const normalizedQuery = resolvedQuery?.trim() ?? "";
|
|
1730
|
+
return useMemo2(() => {
|
|
1731
|
+
if (typeof children !== "string" || !normalizedQuery) return children ?? null;
|
|
1732
|
+
return highlightText(children, normalizedQuery);
|
|
1733
|
+
}, [children, normalizedQuery]);
|
|
1730
1734
|
}
|
|
1731
1735
|
function highlightText(text, query) {
|
|
1732
1736
|
const normalizedQuery = query.trim();
|
|
@@ -1776,6 +1780,17 @@ function sortToValue(sort) {
|
|
|
1776
1780
|
function resolveContent(content, state) {
|
|
1777
1781
|
return typeof content === "function" ? content(state) : content;
|
|
1778
1782
|
}
|
|
1783
|
+
function composeRefs(...refs) {
|
|
1784
|
+
return (value) => {
|
|
1785
|
+
for (const ref of refs) {
|
|
1786
|
+
if (typeof ref === "function") {
|
|
1787
|
+
ref(value);
|
|
1788
|
+
} else if (ref !== null && ref !== void 0) {
|
|
1789
|
+
ref.current = value;
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1779
1794
|
function chainedFunction(childHandler, parentHandler) {
|
|
1780
1795
|
if (!childHandler) return parentHandler;
|
|
1781
1796
|
if (!parentHandler) return childHandler;
|
|
@@ -1786,6 +1801,12 @@ function chainedFunction(childHandler, parentHandler) {
|
|
|
1786
1801
|
}
|
|
1787
1802
|
function mergeProps(childProps, parentProps) {
|
|
1788
1803
|
const merged = { ...parentProps, ...childProps };
|
|
1804
|
+
if ("ref" in childProps || "ref" in parentProps) {
|
|
1805
|
+
merged.ref = composeRefs(
|
|
1806
|
+
childProps.ref,
|
|
1807
|
+
parentProps.ref
|
|
1808
|
+
);
|
|
1809
|
+
}
|
|
1789
1810
|
const className = mergeClassNames(childProps.className, parentProps.className);
|
|
1790
1811
|
if (className) merged.className = className;
|
|
1791
1812
|
const style = mergeStyles(childProps.style, parentProps.style);
|
|
@@ -2252,7 +2273,10 @@ function KeepUndo({ children, label, ...props }) {
|
|
|
2252
2273
|
import { KeepErrorBoundary as KeepErrorBoundary2 } from "@keepkit/core/react";
|
|
2253
2274
|
|
|
2254
2275
|
// src/features/query/KeepActiveFiltersSummary.tsx
|
|
2255
|
-
import {
|
|
2276
|
+
import {
|
|
2277
|
+
isValidElement as isValidElement2,
|
|
2278
|
+
useRef as useRef4
|
|
2279
|
+
} from "react";
|
|
2256
2280
|
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2257
2281
|
function KeepActiveFiltersSummary({
|
|
2258
2282
|
query,
|
|
@@ -2273,6 +2297,38 @@ function KeepActiveFiltersSummary({
|
|
|
2273
2297
|
const clearAllLabel = useUiLabel("clearAllFilters");
|
|
2274
2298
|
const clearLabel = useUiLabel("clearFilters");
|
|
2275
2299
|
const removeLabel = useUiLabel("removeFilter");
|
|
2300
|
+
const chipRefs = useRef4([]);
|
|
2301
|
+
const filterCount = Number(Boolean(search)) + tags.length;
|
|
2302
|
+
function focusChip(index) {
|
|
2303
|
+
chipRefs.current[index]?.focus();
|
|
2304
|
+
}
|
|
2305
|
+
function focusAfterRemoval(index, source) {
|
|
2306
|
+
const summaryRoot = source.closest('[data-keepkit="active-filters"]');
|
|
2307
|
+
const fallbackScope = source.closest('[data-keepkit="collection"]') ?? summaryRoot?.parentElement ?? source.parentElement;
|
|
2308
|
+
queueMicrotask(() => {
|
|
2309
|
+
const nextIndex = index < filterCount - 1 ? index : index - 1;
|
|
2310
|
+
const nextChip = nextIndex >= 0 ? chipRefs.current[nextIndex] : null;
|
|
2311
|
+
if (nextChip?.isConnected) {
|
|
2312
|
+
nextChip.focus();
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
focusFilterFallback(fallbackScope);
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
function handleChipKeyDown(event, index) {
|
|
2319
|
+
const nextIndex = event.key === "ArrowRight" ? index + 1 : event.key === "ArrowLeft" ? index - 1 : -1;
|
|
2320
|
+
if (nextIndex < 0 || nextIndex >= filterCount || !chipRefs.current[nextIndex]) return;
|
|
2321
|
+
event.preventDefault();
|
|
2322
|
+
focusChip(nextIndex);
|
|
2323
|
+
}
|
|
2324
|
+
function removeSearch(event) {
|
|
2325
|
+
focusAfterRemoval(0, event.currentTarget);
|
|
2326
|
+
onSearchChange?.("");
|
|
2327
|
+
}
|
|
2328
|
+
function removeTag(tag, index, event) {
|
|
2329
|
+
focusAfterRemoval(index, event.currentTarget);
|
|
2330
|
+
onTagChange?.(tag);
|
|
2331
|
+
}
|
|
2276
2332
|
const state = {
|
|
2277
2333
|
search,
|
|
2278
2334
|
tags,
|
|
@@ -2293,12 +2349,16 @@ function KeepActiveFiltersSummary({
|
|
|
2293
2349
|
type: "button",
|
|
2294
2350
|
"data-keep-action": "remove-search-filter",
|
|
2295
2351
|
"aria-label": `${search} ${removeLabel}`,
|
|
2296
|
-
|
|
2352
|
+
ref: (element) => {
|
|
2353
|
+
chipRefs.current[0] = element;
|
|
2354
|
+
},
|
|
2355
|
+
onKeyDown: (event) => handleChipKeyDown(event, 0),
|
|
2356
|
+
onClick: removeSearch,
|
|
2297
2357
|
children: "\xD7"
|
|
2298
2358
|
}
|
|
2299
2359
|
)
|
|
2300
2360
|
] }) : null,
|
|
2301
|
-
tags.map((tag) => /* @__PURE__ */ jsxs5("li", { "data-filter-kind": "tag", children: [
|
|
2361
|
+
tags.map((tag, tagIndex) => /* @__PURE__ */ jsxs5("li", { "data-filter-kind": "tag", children: [
|
|
2302
2362
|
/* @__PURE__ */ jsx8("span", { "data-filter-value": "true", children: tag }),
|
|
2303
2363
|
/* @__PURE__ */ jsx8(
|
|
2304
2364
|
"button",
|
|
@@ -2306,7 +2366,11 @@ function KeepActiveFiltersSummary({
|
|
|
2306
2366
|
type: "button",
|
|
2307
2367
|
"data-keep-action": "remove-tag-filter",
|
|
2308
2368
|
"aria-label": `${tag} ${removeLabel}`,
|
|
2309
|
-
|
|
2369
|
+
ref: (element) => {
|
|
2370
|
+
chipRefs.current[tagIndex + Number(Boolean(search))] = element;
|
|
2371
|
+
},
|
|
2372
|
+
onKeyDown: (event) => handleChipKeyDown(event, tagIndex + Number(Boolean(search))),
|
|
2373
|
+
onClick: (event) => removeTag(tag, tagIndex + Number(Boolean(search)), event),
|
|
2310
2374
|
children: "\xD7"
|
|
2311
2375
|
}
|
|
2312
2376
|
)
|
|
@@ -2335,13 +2399,30 @@ function normalizeTags(tags) {
|
|
|
2335
2399
|
function isElement(value) {
|
|
2336
2400
|
return isValidElement2(value);
|
|
2337
2401
|
}
|
|
2402
|
+
function focusFilterFallback(scope) {
|
|
2403
|
+
const searchInput = scope?.querySelector('[data-keep-action="search"]');
|
|
2404
|
+
if (searchInput) {
|
|
2405
|
+
searchInput.focus();
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
const listCard = scope?.querySelector('[data-keepkit="card"][tabindex="0"]');
|
|
2409
|
+
if (listCard) {
|
|
2410
|
+
listCard.focus();
|
|
2411
|
+
return;
|
|
2412
|
+
}
|
|
2413
|
+
const list = scope?.querySelector('[data-keepkit="list"]');
|
|
2414
|
+
if (list) {
|
|
2415
|
+
if (!list.hasAttribute("tabindex")) list.tabIndex = -1;
|
|
2416
|
+
list.focus();
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2338
2419
|
|
|
2339
2420
|
// src/features/query/KeepTagFilter.tsx
|
|
2340
2421
|
import { isValidElement as isValidElement3 } from "react";
|
|
2341
2422
|
|
|
2342
2423
|
// src/features/query/hooks/useKeepTagFilter.ts
|
|
2343
2424
|
import { useKeepList as useKeepList2 } from "@keepkit/core/react";
|
|
2344
|
-
import { useCallback as useCallback2, useMemo as
|
|
2425
|
+
import { useCallback as useCallback2, useMemo as useMemo3, useState as useState4 } from "react";
|
|
2345
2426
|
function useKeepTagFilter(options) {
|
|
2346
2427
|
const { query, controlledValue, defaultValue, onChange, onValueChange } = options;
|
|
2347
2428
|
const [uncontrolledValue, setUncontrolledValue] = useState4(defaultValue);
|
|
@@ -2358,7 +2439,7 @@ function useKeepTagFilter(options) {
|
|
|
2358
2439
|
},
|
|
2359
2440
|
[controlledValue, onChange, onValueChange]
|
|
2360
2441
|
);
|
|
2361
|
-
const state =
|
|
2442
|
+
const state = useMemo3(
|
|
2362
2443
|
() => ({ tags: list.tags, tagCounts: list.tagCounts, value: resolvedValue, select }),
|
|
2363
2444
|
[list.tagCounts, list.tags, resolvedValue, select]
|
|
2364
2445
|
);
|
|
@@ -2620,7 +2701,7 @@ function KeepPagination({
|
|
|
2620
2701
|
|
|
2621
2702
|
// src/features/collection/hooks/useKeepCollection.ts
|
|
2622
2703
|
import { useKeepList as useKeepList3 } from "@keepkit/core/react";
|
|
2623
|
-
import { useMemo as
|
|
2704
|
+
import { useMemo as useMemo4, useState as useState6 } from "react";
|
|
2624
2705
|
function useKeepCollection({
|
|
2625
2706
|
query,
|
|
2626
2707
|
pageSize,
|
|
@@ -2641,7 +2722,7 @@ function useKeepCollection({
|
|
|
2641
2722
|
const [activeTags, setActiveTags] = useState6(query.tags ?? []);
|
|
2642
2723
|
const [page, setPage] = useState6(query.pagination?.page ?? 1);
|
|
2643
2724
|
const resolvedPageSize = query.pagination?.pageSize ?? pageSize;
|
|
2644
|
-
const resolvedQuery =
|
|
2725
|
+
const resolvedQuery = useMemo4(
|
|
2645
2726
|
() => ({
|
|
2646
2727
|
...query,
|
|
2647
2728
|
search: enabled.search ? { ...query.search, query: searchValue } : query.search,
|
|
@@ -3339,9 +3420,9 @@ function useKeepListView(query) {
|
|
|
3339
3420
|
}
|
|
3340
3421
|
|
|
3341
3422
|
// src/features/collection/hooks/useRovingTabIndex.ts
|
|
3342
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useRef as
|
|
3423
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
3343
3424
|
function useRovingTabIndex() {
|
|
3344
|
-
const ref =
|
|
3425
|
+
const ref = useRef5(null);
|
|
3345
3426
|
const getItems = useCallback3(() => {
|
|
3346
3427
|
const root = ref.current;
|
|
3347
3428
|
if (!root) return [];
|
|
@@ -3459,7 +3540,7 @@ function KeepListContent({
|
|
|
3459
3540
|
"data-loading": state.isLoading ? "true" : void 0,
|
|
3460
3541
|
"data-roving-tabindex": "true",
|
|
3461
3542
|
role: rootProps.role ?? "group",
|
|
3462
|
-
ref: roving.ref,
|
|
3543
|
+
ref: composeRefs(roving.ref, rootProps.ref),
|
|
3463
3544
|
onKeyDown: (event) => {
|
|
3464
3545
|
onKeyDown?.(event);
|
|
3465
3546
|
if (!event.defaultPrevented) roving.onKeyDown(event);
|
|
@@ -3756,14 +3837,14 @@ function KeepShortcutHint({ shortcut, separator = "+", ...props }) {
|
|
|
3756
3837
|
|
|
3757
3838
|
// src/features/editor/hooks/useKeepNoteEditor.ts
|
|
3758
3839
|
import { useKeepItem as useKeepItem3 } from "@keepkit/core/react";
|
|
3759
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useRef as
|
|
3840
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef6, useState as useState10 } from "react";
|
|
3760
3841
|
function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
|
|
3761
3842
|
const itemState = useKeepItem3(item);
|
|
3762
3843
|
const { error, isMutating, item: savedItem, updateNote } = itemState;
|
|
3763
3844
|
const [note, setNote] = useState10(item.note ?? "");
|
|
3764
3845
|
const baselineNote = savedItem?.note ?? item.note ?? "";
|
|
3765
3846
|
const isDirty = note !== baselineNote;
|
|
3766
|
-
const lastSavedNoteRef =
|
|
3847
|
+
const lastSavedNoteRef = useRef6(void 0);
|
|
3767
3848
|
useEffect7(() => setNote(baselineNote), [baselineNote]);
|
|
3768
3849
|
const save = useCallback4(async () => {
|
|
3769
3850
|
const nextNote = note.trim() || void 0;
|
|
@@ -4184,7 +4265,7 @@ import { isValidElement as isValidElement8 } from "react";
|
|
|
4184
4265
|
|
|
4185
4266
|
// src/features/status/hooks/useStatusViews.ts
|
|
4186
4267
|
import { useKeepContext as useKeepContext4 } from "@keepkit/core/react";
|
|
4187
|
-
import { useEffect as useEffect10, useRef as
|
|
4268
|
+
import { useEffect as useEffect10, useRef as useRef7, useState as useState12 } from "react";
|
|
4188
4269
|
function useKeepStatus(status) {
|
|
4189
4270
|
const context = useKeepContext4();
|
|
4190
4271
|
const resolvedStatus = status ?? getDerivedStatus(context);
|
|
@@ -4202,7 +4283,7 @@ function useKeepAnnouncements(messages) {
|
|
|
4202
4283
|
const removedMessage = useUiLabel("removedMessage", messages?.remove);
|
|
4203
4284
|
const noteSavedMessage = useUiLabel("noteSavedMessage", messages?.note);
|
|
4204
4285
|
const [message, setMessage] = useState12("");
|
|
4205
|
-
const lastChangeRef =
|
|
4286
|
+
const lastChangeRef = useRef7(void 0);
|
|
4206
4287
|
useEffect10(() => {
|
|
4207
4288
|
const change = context.lastChange;
|
|
4208
4289
|
if (!change || change === lastChangeRef.current) return;
|
|
@@ -4280,13 +4361,13 @@ var KeepAnnouncer = KeepAnnouncements;
|
|
|
4280
4361
|
|
|
4281
4362
|
// src/features/sync/hooks/useKeepSyncFeedback.ts
|
|
4282
4363
|
import { useKeepContext as useKeepContext5 } from "@keepkit/core/react";
|
|
4283
|
-
import { useEffect as useEffect11, useRef as
|
|
4364
|
+
import { useEffect as useEffect11, useRef as useRef8 } from "react";
|
|
4284
4365
|
function useKeepSyncFeedback() {
|
|
4285
4366
|
const { syncState } = useKeepContext5();
|
|
4286
4367
|
const emitFeedback = useKeepUiFeedback();
|
|
4287
4368
|
const completedMessage = useUiLabel("syncSynced");
|
|
4288
4369
|
const failedMessage = useUiLabel("syncFailedMessage");
|
|
4289
|
-
const previousStatus =
|
|
4370
|
+
const previousStatus = useRef8("idle");
|
|
4290
4371
|
useEffect11(() => {
|
|
4291
4372
|
const previous = previousStatus.current;
|
|
4292
4373
|
previousStatus.current = syncState.status;
|
|
@@ -4806,6 +4887,7 @@ export {
|
|
|
4806
4887
|
LocalStorageSyncQueueAdapter,
|
|
4807
4888
|
SyncStorageAdapter,
|
|
4808
4889
|
chainedFunction,
|
|
4890
|
+
composeRefs,
|
|
4809
4891
|
createAuthenticatedSyncKit,
|
|
4810
4892
|
createBrowserStorageAdapter,
|
|
4811
4893
|
createKeepKit,
|