@keepkit/ui 0.26.1 → 0.26.2

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
@@ -106,7 +106,7 @@ const onFeedback = useKeepToastFeedback(toast);
106
106
  <KeepKitProvider storage={storage} onFeedback={onFeedback}>{children}</KeepKitProvider>;
107
107
  ```
108
108
 
109
- v0.26.1では`KeepWorkspace`と型付きの`keep.Workspace`を追加しました。Tailwind CSS v4との統合、ホストテーマ変数との衝突回避、CSS cascade layer対応も引き続き利用できます。保存直後の`KeepSavePopover`自動編集、`KeepQuickEditorState.saveStatus`、`KeepItemCard.Save` / `KeepItemCard.Remove`、管理モード向け`KeepBulkActions`、通知からのコレクション再訪導線も引き続き利用できます。
109
+ v0.26.2では`KeepWorkspace`と型付きの`keep.Workspace`を追加しました。Tailwind CSS v4との統合、ホストテーマ変数との衝突回避、CSS cascade layer対応も引き続き利用できます。保存直後の`KeepSavePopover`自動編集、`KeepQuickEditorState.saveStatus`、`KeepItemCard.Save` / `KeepItemCard.Remove`、管理モード向け`KeepBulkActions`、通知からのコレクション再訪導線も引き続き利用できます。
110
110
  Phase 4の状態UIとして`KeepItemStatusBadge`、`KeepStaleNotice`、`KeepPruneStaleButton`、`KeepSyncStatusBanner`、`KeepSyncRecoveryDialog`を利用できます。`import "@keepkit/ui/theme.css"`でテーマCSSを有効にできます。
111
111
 
112
112
  ### Tailwind/shadcnテーマ
@@ -243,7 +243,7 @@ const onFeedback = useKeepToastFeedback(toast);
243
243
  <KeepKitProvider storage={storage} onFeedback={onFeedback}>{children}</KeepKitProvider>;
244
244
  ```
245
245
 
246
- v0.26.1 adds `KeepWorkspace` and the typed `keep.Workspace`. Tailwind CSS v4 integration, host-theme isolation, and cascade-layer support remain available. `KeepSavePopover` post-save editing, `KeepQuickEditorState.saveStatus`, `KeepItemCard.Save` / `KeepItemCard.Remove`, management-mode `KeepBulkActions`, and notification-driven return to the collection remain available.
246
+ v0.26.2 adds `KeepWorkspace` and the typed `keep.Workspace`. Tailwind CSS v4 integration, host-theme isolation, and cascade-layer support remain available. `KeepSavePopover` post-save editing, `KeepQuickEditorState.saveStatus`, `KeepItemCard.Save` / `KeepItemCard.Remove`, management-mode `KeepBulkActions`, and notification-driven return to the collection remain available.
247
247
  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.
248
248
 
249
249
  ### Tailwind and shadcn theme
package/dist/index.js CHANGED
@@ -2140,11 +2140,12 @@ function getErrorMessage(error) {
2140
2140
  import {
2141
2141
  cloneElement,
2142
2142
  createContext as createContext2,
2143
+ Fragment,
2143
2144
  isValidElement,
2144
2145
  useContext as useContext2,
2145
2146
  useMemo as useMemo2
2146
2147
  } from "react";
2147
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
2148
+ import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
2148
2149
  var KeepSearchQueryContext = createContext2(void 0);
2149
2150
  function KeepSearchQueryProvider({ query, children }) {
2150
2151
  return /* @__PURE__ */ jsx3(KeepSearchQueryContext.Provider, { value: query, children });
@@ -2181,7 +2182,7 @@ function highlightText(text, query) {
2181
2182
  }
2182
2183
  if (lastIndex === 0) return text;
2183
2184
  if (lastIndex < text.length) parts.push(text.slice(lastIndex));
2184
- return /* @__PURE__ */ jsx3(Fragment, { children: parts });
2185
+ return /* @__PURE__ */ jsx3(Fragment2, { children: parts });
2185
2186
  }
2186
2187
  function escapeRegExp(value) {
2187
2188
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -2212,6 +2213,15 @@ function sortToValue(sort) {
2212
2213
  function resolveContent(content, state) {
2213
2214
  return typeof content === "function" ? content(state) : content;
2214
2215
  }
2216
+ function hasRenderableContent(content) {
2217
+ if (content === null || content === void 0 || typeof content === "boolean") return false;
2218
+ if (typeof content === "string") return content.length > 0;
2219
+ if (Array.isArray(content)) return content.some(hasRenderableContent);
2220
+ if (isValidElement(content) && content.type === Fragment) {
2221
+ return hasRenderableContent(content.props.children);
2222
+ }
2223
+ return true;
2224
+ }
2215
2225
  function composeRefs(...refs) {
2216
2226
  return (value) => {
2217
2227
  for (const ref of refs) {
@@ -2418,7 +2428,7 @@ function getItemLabel(item) {
2418
2428
  }
2419
2429
 
2420
2430
  // src/features/actions/KeepBulkActions.tsx
2421
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2431
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2422
2432
  function KeepBulkActions({
2423
2433
  query,
2424
2434
  selectedIds: controlledSelectedIds,
@@ -2441,7 +2451,7 @@ function KeepBulkActions({
2441
2451
  controlledScope,
2442
2452
  onSelectionScopeChange
2443
2453
  });
2444
- const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs3(Fragment2, { children: [
2454
+ const body = render ? render(state) : typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs3(Fragment3, { children: [
2445
2455
  /* @__PURE__ */ jsxs3("fieldset", { children: [
2446
2456
  /* @__PURE__ */ jsx5("legend", { children: labels.selectItems }),
2447
2457
  /* @__PURE__ */ jsxs3("label", { children: [
@@ -2559,7 +2569,7 @@ function useKeepButton({ item, labels, icons, children }) {
2559
2569
  }
2560
2570
 
2561
2571
  // src/features/actions/KeepButton.tsx
2562
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
2572
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
2563
2573
  function KeepButton({
2564
2574
  labels,
2565
2575
  icons,
@@ -2604,7 +2614,7 @@ function KeepButton({
2604
2614
  const label = state.error ? labels?.error ?? view.labels.error : state.isMutating ? labels?.loading ?? view.labels.loading : state.isSaved ? labels?.saved ?? view.labels.saved : labels?.unsaved ?? view.labels.save;
2605
2615
  if (!icons) return label;
2606
2616
  const icon = state.error ? icons.error : state.isMutating ? icons.loading : state.isSaved ? icons.remove ?? icons.saved : icons.save;
2607
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
2617
+ return /* @__PURE__ */ jsxs4(Fragment4, { children: [
2608
2618
  renderIcon(icon, iconClassName),
2609
2619
  showLabel && !iconOnly ? label : null
2610
2620
  ] });
@@ -2632,7 +2642,7 @@ function KeepButton({
2632
2642
  unsavedAriaLabel: labels?.unsavedAriaLabel ?? props.unsavedAriaLabel
2633
2643
  };
2634
2644
  if (!view.customStateLabel) return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps });
2635
- return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx6(Fragment3, { children: getStateContent(state) }) });
2645
+ return /* @__PURE__ */ jsx6(CoreKeepButton, { ...sharedProps, children: (state) => /* @__PURE__ */ jsx6(Fragment4, { children: getStateContent(state) }) });
2636
2646
  }
2637
2647
  function renderIcon(icon, className) {
2638
2648
  if (typeof icon === "function") return createElement(icon, { "aria-hidden": true, className });
@@ -2657,7 +2667,7 @@ import {
2657
2667
  useRef as useRef4,
2658
2668
  useState as useState3
2659
2669
  } from "react";
2660
- import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2670
+ import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2661
2671
  function useKeepQuickEditor(item, options = {}) {
2662
2672
  const { debounceMs = 300, onSaved, onSaveError } = options;
2663
2673
  const itemState = useKeepItem3(item);
@@ -2814,7 +2824,7 @@ function KeepQuickEditorView({
2814
2824
  if (event.key === "Tab") trapFocus(event, focusScopeRef?.current ?? rootRef.current);
2815
2825
  };
2816
2826
  const statusMessage = state.saveStatus === "dirty" ? unsavedChangesLabel : state.saveStatus === "saving" ? savingLabel : state.saveStatus === "saved" ? savedLabel : state.saveStatus === "error" ? getErrorMessage2(state.error, errorLabel) : null;
2817
- const body = typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
2827
+ const body = typeof children === "function" ? children(state) : children ?? /* @__PURE__ */ jsxs5(Fragment5, { children: [
2818
2828
  /* @__PURE__ */ jsxs5("label", { children: [
2819
2829
  noteLabel,
2820
2830
  /* @__PURE__ */ jsx7("textarea", { value: state.note, onChange: (event) => state.setNote(event.currentTarget.value) })
@@ -3132,7 +3142,7 @@ import {
3132
3142
  isValidElement as isValidElement2,
3133
3143
  useRef as useRef6
3134
3144
  } from "react";
3135
- import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
3145
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
3136
3146
  function KeepActiveFiltersSummary({
3137
3147
  query,
3138
3148
  search: providedSearch,
@@ -3193,7 +3203,7 @@ function KeepActiveFiltersSummary({
3193
3203
  removeTag: (tag) => onTagChange?.(tag)
3194
3204
  };
3195
3205
  const contentChildren = asChild && isElement(children) ? void 0 : children;
3196
- const body = typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? (hasFilters ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
3206
+ const body = typeof contentChildren === "function" ? contentChildren(state) : contentChildren ?? (hasFilters ? /* @__PURE__ */ jsxs8(Fragment6, { children: [
3197
3207
  /* @__PURE__ */ jsx10("span", { "data-active-filters-label": "true", children: activeFiltersLabel }),
3198
3208
  /* @__PURE__ */ jsxs8("ul", { "data-active-filters-list": "true", children: [
3199
3209
  search ? /* @__PURE__ */ jsxs8("li", { "data-filter-kind": "search", children: [
@@ -3576,7 +3586,7 @@ function getVisiblePages(currentPage, pageCount, maxPageButtons) {
3576
3586
  }
3577
3587
 
3578
3588
  // src/features/query/query-controls.tsx
3579
- import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3589
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3580
3590
  function KeepSearchInput({
3581
3591
  value: controlledValue,
3582
3592
  defaultValue = "",
@@ -3612,7 +3622,7 @@ function KeepSortSelect({
3612
3622
  ...props
3613
3623
  }) {
3614
3624
  const view = useKeepSortSelect({ controlledValue, defaultValue, onValueChange });
3615
- const options = children ?? /* @__PURE__ */ jsxs12(Fragment6, { children: [
3625
+ const options = children ?? /* @__PURE__ */ jsxs12(Fragment7, { children: [
3616
3626
  /* @__PURE__ */ jsx14("option", { value: "updatedAt:desc", children: view.labels.updatedNewest }),
3617
3627
  /* @__PURE__ */ jsx14("option", { value: "updatedAt:asc", children: view.labels.updatedOldest }),
3618
3628
  /* @__PURE__ */ jsx14("option", { value: "savedAt:desc", children: view.labels.savedNewest }),
@@ -3869,7 +3879,7 @@ function getDisplayStatus(status) {
3869
3879
  }
3870
3880
 
3871
3881
  // src/features/item/KeepItemStatusBadge.tsx
3872
- import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3882
+ import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3873
3883
  function KeepItemStatusBadge({ status = "available", label, className, ...props }) {
3874
3884
  const view = useKeepItemStatusBadge(status);
3875
3885
  return /* @__PURE__ */ jsxs13(
@@ -3906,15 +3916,15 @@ function StatusIcon({ name }) {
3906
3916
  focusable: "false",
3907
3917
  children: [
3908
3918
  name === "check" ? /* @__PURE__ */ jsx15("path", { d: "m5 12 4 4L19 6" }) : null,
3909
- name === "clock" ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
3919
+ name === "clock" ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
3910
3920
  /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "8" }),
3911
3921
  /* @__PURE__ */ jsx15("path", { d: "M12 7v5l3 2" })
3912
3922
  ] }) : null,
3913
- name === "ban" ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
3923
+ name === "ban" ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
3914
3924
  /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "8" }),
3915
3925
  /* @__PURE__ */ jsx15("path", { d: "m6.5 6.5 11 11" })
3916
3926
  ] }) : null,
3917
- name === "lock" ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
3927
+ name === "lock" ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
3918
3928
  /* @__PURE__ */ jsx15("rect", { x: "5", y: "10", width: "14", height: "10", rx: "2" }),
3919
3929
  /* @__PURE__ */ jsx15("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
3920
3930
  ] }) : null
@@ -4175,7 +4185,7 @@ function getDisplayStatus2(status) {
4175
4185
  }
4176
4186
 
4177
4187
  // src/features/item/KeepItemCard.tsx
4178
- import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4188
+ import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4179
4189
  var KeepItemCardContext = createContext3(null);
4180
4190
  function useKeepItemCardCompound(part) {
4181
4191
  const context = useContext3(KeepItemCardContext);
@@ -4291,8 +4301,8 @@ function KeepItemCardRoot({
4291
4301
  /* @__PURE__ */ jsx17("time", { dateTime: new Date(item.savedAt).toISOString(), children: formatSavedAt(item.savedAt) })
4292
4302
  ] }) : null;
4293
4303
  const error = view.itemState.error ? /* @__PURE__ */ jsx17("p", { role: "alert", children: getErrorMessage3(view.itemState.error, view.labels.error) }) : null;
4294
- const actions = view.statusLabel ? /* @__PURE__ */ jsx17(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs15(Fragment8, { children: [
4295
- showEditButton ? /* @__PURE__ */ jsxs15(Fragment8, { children: [
4304
+ const actions = view.statusLabel ? /* @__PURE__ */ jsx17(KeepStaleNotice, { item, onRetry, onRemoved }) : /* @__PURE__ */ jsxs15(Fragment9, { children: [
4305
+ showEditButton ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
4296
4306
  /* @__PURE__ */ jsx17(
4297
4307
  "button",
4298
4308
  {
@@ -4338,7 +4348,7 @@ function KeepItemCardRoot({
4338
4348
  saveAriaLabel: `${view.labels.remove} ${String(view.resolvedTitle)}`,
4339
4349
  renderText: (content) => /* @__PURE__ */ jsx17(KeepHighlight, { query: searchQuery, children: content })
4340
4350
  };
4341
- const defaultBody = /* @__PURE__ */ jsxs15(Fragment8, { children: [
4351
+ const defaultBody = /* @__PURE__ */ jsxs15(Fragment9, { children: [
4342
4352
  /* @__PURE__ */ jsx17(KeepItemCardMedia, {}),
4343
4353
  /* @__PURE__ */ jsx17(KeepItemCardContent, {}),
4344
4354
  /* @__PURE__ */ jsx17(KeepItemCardActions, {})
@@ -4371,7 +4381,7 @@ function KeepItemCardMedia({ children, fallback, ...props }) {
4371
4381
  }
4372
4382
  function KeepItemCardContent({ children, ...props }) {
4373
4383
  const context = useKeepItemCardCompound("Content");
4374
- return /* @__PURE__ */ jsx17("div", { ...props, "data-keep-card-part": "content", children: children === void 0 ? /* @__PURE__ */ jsxs15(Fragment8, { children: [
4384
+ return /* @__PURE__ */ jsx17("div", { ...props, "data-keep-card-part": "content", children: children === void 0 ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
4375
4385
  /* @__PURE__ */ jsx17(KeepItemCardTitle, {}),
4376
4386
  context.meta,
4377
4387
  /* @__PURE__ */ jsx17(KeepItemCardTags, {}),
@@ -4486,7 +4496,7 @@ function getErrorMessage3(error, fallback) {
4486
4496
 
4487
4497
  // src/features/status/KeepEmptyState.tsx
4488
4498
  import { isValidElement as isValidElement5 } from "react";
4489
- import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4499
+ import { Fragment as Fragment10, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4490
4500
  function KeepEmptyState({
4491
4501
  title,
4492
4502
  description,
@@ -4505,7 +4515,7 @@ function KeepEmptyState({
4505
4515
  );
4506
4516
  const clearLabel = useUiLabel("clearFilters");
4507
4517
  const contentChildren = asChild && isValidElement5(children) ? void 0 : children;
4508
- const body = contentChildren ?? /* @__PURE__ */ jsxs16(Fragment9, { children: [
4518
+ const body = contentChildren ?? /* @__PURE__ */ jsxs16(Fragment10, { children: [
4509
4519
  /* @__PURE__ */ jsx18("h2", { children: title ?? defaultTitle }),
4510
4520
  description ?? /* @__PURE__ */ jsx18("p", { children: defaultDescription }),
4511
4521
  action ?? (resolvedVariant === "empty-filtered" && onClearFilters ? /* @__PURE__ */ jsx18("button", { type: "button", "data-keep-action": "clear-filters", onClick: onClearFilters, children: clearLabel }) : null)
@@ -4710,7 +4720,7 @@ function KeepReorderableList({
4710
4720
  }
4711
4721
 
4712
4722
  // src/features/collection/KeepList.tsx
4713
- import { Fragment as Fragment10, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
4723
+ import { Fragment as Fragment11, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
4714
4724
  function KeepList(props) {
4715
4725
  const { fallback, onBoundaryError, boundaryResetKey, ...listProps } = props;
4716
4726
  const content = /* @__PURE__ */ jsx20(KeepListContent, { ...listProps });
@@ -4795,7 +4805,7 @@ function getListBody(state, options) {
4795
4805
  if (state.isLoading && !state.isHydrated) {
4796
4806
  if (options.loading !== void 0) return resolveContent(options.loading, state);
4797
4807
  const count = Number.isFinite(options.loadingCount) ? Math.max(0, Math.floor(options.loadingCount)) : 6;
4798
- return /* @__PURE__ */ jsxs17(Fragment10, { children: [
4808
+ return /* @__PURE__ */ jsxs17(Fragment11, { children: [
4799
4809
  /* @__PURE__ */ jsx20("span", { role: "status", "data-keepkit": "loading-label", children: options.loadingLabel }),
4800
4810
  /* @__PURE__ */ jsx20("ul", { "data-keepkit": "skeleton-list", "data-layout": options.layout, children: Array.from({ length: count }, (_, index) => (
4801
4811
  // biome-ignore lint/suspicious/noArrayIndexKey: Static loading placeholders never reorder.
@@ -4824,7 +4834,7 @@ function getListBody(state, options) {
4824
4834
  await options.reorder(orderedIds);
4825
4835
  await options.onReorder?.(orderedIds);
4826
4836
  },
4827
- renderItem: (item, reorderState) => /* @__PURE__ */ jsxs17(Fragment10, { children: [
4837
+ renderItem: (item, reorderState) => /* @__PURE__ */ jsxs17(Fragment11, { children: [
4828
4838
  /* @__PURE__ */ jsx20("button", { type: "button", ...reorderState.dragHandleProps, children: "\u2195" }),
4829
4839
  options.renderItem ? options.renderItem(item, state) : /* @__PURE__ */ jsx20(KeepItemCard, { item, ...options.itemCardProps })
4830
4840
  ] }),
@@ -4844,7 +4854,7 @@ function hasActiveQueryFilters(query) {
4844
4854
  }
4845
4855
 
4846
4856
  // src/features/collection/KeepCollection.tsx
4847
- import { Fragment as Fragment11, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
4857
+ import { Fragment as Fragment12, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
4848
4858
  function KeepCollection(props) {
4849
4859
  const { fallback, onBoundaryError, boundaryResetKey, ...collectionProps } = props;
4850
4860
  const content = /* @__PURE__ */ jsx21(KeepCollectionContent, { ...collectionProps });
@@ -4912,11 +4922,11 @@ function KeepCollectionContent({
4912
4922
  const structuredToolbar = toolbarLayout === "grouped" || toolbarVariant === "panel" || slots?.toolbarStart !== void 0 || slots?.toolbarEnd !== void 0;
4913
4923
  const hasQueryControls = view.enabled.search || view.enabled.sort;
4914
4924
  const hasFilterControls = view.enabled.tagFilter || view.enabled.collectionFilter || archiveScope !== void 0;
4915
- const queryControls = hasQueryControls ? /* @__PURE__ */ jsxs18(Fragment11, { children: [
4925
+ const queryControls = hasQueryControls ? /* @__PURE__ */ jsxs18(Fragment12, { children: [
4916
4926
  view.enabled.search ? /* @__PURE__ */ jsx21(KeepSearchInput, { value: view.searchValue, onValueChange: view.setSearchValue }) : null,
4917
4927
  view.enabled.sort ? /* @__PURE__ */ jsx21(KeepSortSelect, { value: view.sortValue, onValueChange: view.setSortValue }) : null
4918
4928
  ] }) : null;
4919
- const filterControls = hasFilterControls ? /* @__PURE__ */ jsxs18(Fragment11, { children: [
4929
+ const filterControls = hasFilterControls ? /* @__PURE__ */ jsxs18(Fragment12, { children: [
4920
4930
  view.enabled.tagFilter ? /* @__PURE__ */ jsx21(KeepTagFilter, { query, value: view.activeTags[0], onValueChange: view.setTag }) : null,
4921
4931
  view.enabled.collectionFilter ? /* @__PURE__ */ jsx21(
4922
4932
  KeepCollectionFilter,
@@ -4947,10 +4957,19 @@ function KeepCollectionContent({
4947
4957
  const renderToolbarGroup = (group, content, label) => {
4948
4958
  if (!hasRenderableContent(content)) return null;
4949
4959
  const labelId = `${toolbarId}-${group}`;
4950
- return /* @__PURE__ */ jsxs18("fieldset", { "data-keepkit": "collection-toolbar-group", "data-group": group, "aria-labelledby": labelId, children: [
4951
- /* @__PURE__ */ jsx21("legend", { id: labelId, "data-keepkit": "collection-toolbar-label", children: label }),
4952
- /* @__PURE__ */ jsx21("div", { "data-keepkit": "collection-toolbar-content", children: content })
4953
- ] });
4960
+ return /* @__PURE__ */ jsxs18(
4961
+ "fieldset",
4962
+ {
4963
+ "data-keepkit": "collection-toolbar-group",
4964
+ "data-group": group,
4965
+ role: "group",
4966
+ "aria-labelledby": labelId,
4967
+ children: [
4968
+ /* @__PURE__ */ jsx21("legend", { id: labelId, "data-keepkit": "collection-toolbar-label", children: label }),
4969
+ /* @__PURE__ */ jsx21("div", { "data-keepkit": "collection-toolbar-content", children: content })
4970
+ ]
4971
+ }
4972
+ );
4954
4973
  };
4955
4974
  const toolbar = !structuredToolbar ? /* @__PURE__ */ jsxs18("div", { children: [
4956
4975
  queryControls,
@@ -5023,9 +5042,6 @@ function getCollectionState(list) {
5023
5042
  if (list.isHydrated && list.items.length === 0) return "empty";
5024
5043
  return "ready";
5025
5044
  }
5026
- function hasRenderableContent(content) {
5027
- return content !== null && content !== void 0 && content !== false && content !== true && content !== "";
5028
- }
5029
5045
 
5030
5046
  // src/features/collection/KeepLayout.tsx
5031
5047
  import { jsx as jsx22 } from "react/jsx-runtime";
@@ -5132,7 +5148,7 @@ function useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError }) {
5132
5148
  }
5133
5149
 
5134
5150
  // src/features/editor/KeepNoteEditor.tsx
5135
- import { Fragment as Fragment12, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5151
+ import { Fragment as Fragment13, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5136
5152
  function KeepNoteEditor({
5137
5153
  item,
5138
5154
  label,
@@ -5151,7 +5167,7 @@ function KeepNoteEditor({
5151
5167
  const view = useKeepNoteEditor({ item, debounceMs, onSaved, onSaveError });
5152
5168
  const { error, isDirty, isSaving, note, setNote } = view.state;
5153
5169
  const contentChildren = asChild && isValidElement7(children) ? void 0 : children;
5154
- const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs20(Fragment12, { children: [
5170
+ const body = render ? render(view.state) : typeof contentChildren === "function" ? contentChildren(view.state) : contentChildren ?? /* @__PURE__ */ jsxs20(Fragment13, { children: [
5155
5171
  /* @__PURE__ */ jsxs20("label", { children: [
5156
5172
  label ?? view.labels.note,
5157
5173
  /* @__PURE__ */ jsx24(
@@ -5265,7 +5281,7 @@ function useKeepTagEditor({ item, onSaved, onSaveError }) {
5265
5281
  }
5266
5282
 
5267
5283
  // src/features/editor/KeepTagEditor.tsx
5268
- import { Fragment as Fragment13, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
5284
+ import { Fragment as Fragment14, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
5269
5285
  function KeepTagEditor({
5270
5286
  item,
5271
5287
  availableTags = [],
@@ -5276,7 +5292,7 @@ function KeepTagEditor({
5276
5292
  }) {
5277
5293
  const view = useKeepTagEditor({ item, onSaved, onSaveError });
5278
5294
  const { isSaving, tags } = view.state;
5279
- const body = render ? render(view.state) : /* @__PURE__ */ jsxs21(Fragment13, { children: [
5295
+ const body = render ? render(view.state) : /* @__PURE__ */ jsxs21(Fragment14, { children: [
5280
5296
  /* @__PURE__ */ jsxs21("label", { children: [
5281
5297
  view.labels.tags,
5282
5298
  /* @__PURE__ */ jsx25(
@@ -5375,7 +5391,7 @@ function isEditableTarget(target) {
5375
5391
  }
5376
5392
 
5377
5393
  // src/features/navigation/KeepTourBar.tsx
5378
- import { Fragment as Fragment14, jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
5394
+ import { Fragment as Fragment15, jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
5379
5395
  function KeepTourBar({
5380
5396
  navigation: providedNavigation,
5381
5397
  currentId,
@@ -5445,7 +5461,7 @@ function KeepTourBar({
5445
5461
  return resolvedPrev();
5446
5462
  }
5447
5463
  });
5448
- const body = /* @__PURE__ */ jsxs22(Fragment14, { children: [
5464
+ const body = /* @__PURE__ */ jsxs22(Fragment15, { children: [
5449
5465
  showProgress ? /* @__PURE__ */ jsx26("span", { "data-keepkit": "tour-progress", "aria-live": "polite", children: progress ?? `${navigation.currentPosition ?? 0} / ${navigation.items.length}` }) : null,
5450
5466
  /* @__PURE__ */ jsx26(
5451
5467
  TourAction,
@@ -5455,7 +5471,7 @@ function KeepTourBar({
5455
5471
  onClick: resolvedPrevHref ? notifyPrevNavigation : resolvedPrev,
5456
5472
  "data-keep-action": "tour-prev",
5457
5473
  shortcut: showShortcutHint ? shortcutOptions?.prevKeys?.[0] ?? "K" : void 0,
5458
- preview: navigation.prevItem ? /* @__PURE__ */ jsxs22(Fragment14, { children: [
5474
+ preview: navigation.prevItem ? /* @__PURE__ */ jsxs22(Fragment15, { children: [
5459
5475
  previousLabel,
5460
5476
  ": ",
5461
5477
  getItemTitle(navigation.prevItem)
@@ -5471,7 +5487,7 @@ function KeepTourBar({
5471
5487
  onClick: resolvedNextHref ? notifyNextNavigation : resolvedNext,
5472
5488
  "data-keep-action": "tour-next",
5473
5489
  shortcut: showShortcutHint ? shortcutOptions?.nextKeys?.[0] ?? "J" : void 0,
5474
- preview: navigation.nextItem ? /* @__PURE__ */ jsxs22(Fragment14, { children: [
5490
+ preview: navigation.nextItem ? /* @__PURE__ */ jsxs22(Fragment15, { children: [
5475
5491
  nextItemLabel,
5476
5492
  ": ",
5477
5493
  getItemTitle(navigation.nextItem)
@@ -5491,7 +5507,7 @@ function KeepTourBar({
5491
5507
  }
5492
5508
  function TourAction({ href, disabled = false, onClick, children, preview, shortcut, ...props }) {
5493
5509
  const previewId = useId4();
5494
- const content = /* @__PURE__ */ jsxs22(Fragment14, { children: [
5510
+ const content = /* @__PURE__ */ jsxs22(Fragment15, { children: [
5495
5511
  /* @__PURE__ */ jsx26("span", { "data-tour-label": "true", children }),
5496
5512
  shortcut ? /* @__PURE__ */ jsx26(KeepShortcutHint, { shortcut }) : null,
5497
5513
  preview ? /* @__PURE__ */ jsx26("small", { id: previewId, "data-tour-preview": "true", children: preview }) : null
@@ -6003,7 +6019,7 @@ function KeepWorkspace({
6003
6019
  const structuredRegions = surface !== void 0 && surface !== "plain";
6004
6020
  const region = (name, content) => {
6005
6021
  if (!structuredRegions) return content;
6006
- if (content === null || content === void 0 || content === false) return null;
6022
+ if (!hasRenderableContent(content)) return null;
6007
6023
  const resolvedSurface = typeof surface === "string" ? surface : surface[name] ?? "plain";
6008
6024
  return /* @__PURE__ */ jsx30("div", { "data-keepkit": "workspace-region", "data-region": name, "data-surface": resolvedSurface, children: content });
6009
6025
  };