@proveanything/smartlinks-utils-ui 0.10.8 → 0.10.9

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.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ComponentType, ReactNode } from 'react';
3
- import { FacetRule, MatchedAt, RecordTarget, AppRecord, MatchResult, ResolveAllEntry } from '@proveanything/smartlinks/dist/types/appObjects';
2
+ import { FacetRule, MatchedAt, AppRecord, RecordTarget, MatchResult, ResolveAllEntry } from '@proveanything/smartlinks/dist/types/appObjects';
3
+ import { ReactNode, ComponentType } from 'react';
4
4
  import { LucideIcon } from 'lucide-react';
5
5
  import * as _tanstack_query_core from '@tanstack/query-core';
6
6
  import * as _proveanything_smartlinks from '@proveanything/smartlinks';
@@ -93,6 +93,21 @@ interface RecordSummary<TData = unknown> {
93
93
  * browser uses this to render a friendly rule summary as the row subtitle.
94
94
  */
95
95
  facetRule?: FacetRule | null;
96
+ /**
97
+ * Optional visual hint for the leading status icon on the default row
98
+ * renderer. When set, takes precedence over the status-derived icon
99
+ * (configured / inherited / empty). Used by lifecycle rail buckets
100
+ * (success/warning/etc) and any host that wants per-row iconography
101
+ * without supplying a full `renderListRow`.
102
+ */
103
+ iconHint?: ReactNode;
104
+ /**
105
+ * Optional semantic tone for the leading status icon. Drives the icon
106
+ * colour via `ra-status-icon--<tone>` CSS classes. Has no effect unless
107
+ * `iconHint` is also set (or the tone is one that maps to a built-in
108
+ * default icon).
109
+ */
110
+ toneHint?: 'success' | 'warning' | 'danger' | 'muted' | 'info' | 'default';
96
111
  }
97
112
  interface ResolvedRecord<TData = unknown> {
98
113
  data: TData | null;
@@ -1048,6 +1063,20 @@ interface ItemsConfig<TData = unknown> {
1048
1063
  cardSize?: 'sm' | 'md' | 'lg';
1049
1064
  /** What the rail shows once an item is open. Default `'siblings'`. */
1050
1065
  railMode?: CollectionRailMode;
1066
+ /**
1067
+ * Optional projector that derives `label` / `subtitle` / `thumbnail`
1068
+ * (and any other `RecordSummary` fields) from a raw record. Runs for
1069
+ * every item in the collection-cardinality right-pane list. The
1070
+ * shell's default tries common keys (`title`, `name`, `label`,
1071
+ * `question`, …) — supply this when your record shape doesn't match
1072
+ * those, or when you want the global / all-items list to read from a
1073
+ * different field.
1074
+ *
1075
+ * `base` already carries the framework-derived fields (id, scope,
1076
+ * status, etc.); return a merged `RecordSummary` (e.g.
1077
+ * `{ ...base, label: rec.data?.headline ?? base.label }`).
1078
+ */
1079
+ toSummary?: (rec: AppRecord, base: RecordSummary<TData>) => RecordSummary<TData>;
1051
1080
  }
1052
1081
  interface UnsavedConfig<TData = unknown> {
1053
1082
  /**
@@ -1163,6 +1192,8 @@ interface Props$f {
1163
1192
  declare const StatusDot: ({ source, status, className }: Props$f) => react_jsx_runtime.JSX.Element;
1164
1193
 
1165
1194
  type StatusTone = 'own' | 'shared' | 'missing';
1195
+ /** Semantic tones used by host-driven iconography (e.g. lifecycle buckets). */
1196
+ type SemanticTone = 'success' | 'warning' | 'danger' | 'muted' | 'info' | 'default';
1166
1197
  interface Props$e {
1167
1198
  source?: RecordSource;
1168
1199
  status?: RecordStatus;
@@ -1171,8 +1202,21 @@ interface Props$e {
1171
1202
  size?: string;
1172
1203
  /** Optional accessible label — defaults to the tone name. */
1173
1204
  label?: string;
1205
+ /**
1206
+ * Host-supplied icon override. Either a React element (rendered as-is)
1207
+ * or any ReactNode. When set, takes precedence over the status-derived
1208
+ * icon. Pair with `semanticTone` to drive colour.
1209
+ */
1210
+ iconHint?: ReactNode;
1211
+ /**
1212
+ * Host-supplied semantic tone (success/warning/danger/muted/info). When
1213
+ * set, drives the icon colour AND — if no `iconHint` is supplied —
1214
+ * picks a sensible default lucide icon per tone (CheckCircle2 / Alert /
1215
+ * XCircle / MinusCircle / Info).
1216
+ */
1217
+ semanticTone?: SemanticTone;
1174
1218
  }
1175
- declare const StatusIcon: ({ source, status, className, size, label }: Props$e) => react_jsx_runtime.JSX.Element;
1219
+ declare const StatusIcon: ({ source, status, className, size, label, iconHint, semanticTone, }: Props$e) => react_jsx_runtime.JSX.Element;
1176
1220
  /** Short label rendered next to / under the row title. */
1177
1221
  declare const statusToneLabel: (tone: StatusTone) => string;
1178
1222
 
@@ -6,8 +6,8 @@ import { useFacets } from '../../chunk-4LHF5JB7.js';
6
6
  import { cn } from '../../chunk-L7FQ52F5.js';
7
7
  import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
8
8
  export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
9
- import { createContext, useState, useEffect, useCallback, useMemo, useRef, useContext, useSyncExternalStore, useLayoutEffect, createElement } from 'react';
10
- import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, List, SlidersHorizontal, Globe, Tag, Boxes, Layers, Package, Target, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, CopyPlus, AlertCircle, Undo2, Save, Loader2, XCircle, ArrowRight, Globe2, Check, Settings2 } from 'lucide-react';
9
+ import { createContext, useState, useEffect, useCallback, useMemo, useRef, isValidElement, useContext, useSyncExternalStore, useLayoutEffect, createElement } from 'react';
10
+ import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, List, SlidersHorizontal, Globe, Tag, Boxes, Layers, Package, Target, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, MinusCircle, XCircle, CopyPlus, AlertCircle, Undo2, Save, Loader2, ArrowRight, Globe2, Check, Settings2 } from 'lucide-react';
11
11
  import { useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
12
12
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
13
13
  import { createPortal } from 'react-dom';
@@ -3250,7 +3250,43 @@ var resolveTone = (source, status) => {
3250
3250
  if (source === "inherited" || status === "partial") return "shared";
3251
3251
  return "missing";
3252
3252
  };
3253
- var StatusIcon = ({ source, status, className, size = "1.05rem", label }) => {
3253
+ var SEMANTIC_DEFAULT_ICONS = {
3254
+ success: CheckCircle2,
3255
+ warning: AlertTriangle,
3256
+ danger: XCircle,
3257
+ muted: MinusCircle,
3258
+ info: Info
3259
+ };
3260
+ var StatusIcon = ({
3261
+ source,
3262
+ status,
3263
+ className,
3264
+ size = "1.05rem",
3265
+ label,
3266
+ iconHint,
3267
+ semanticTone
3268
+ }) => {
3269
+ if (semanticTone || iconHint) {
3270
+ const toneClass = semanticTone && semanticTone !== "default" ? `ra-status-icon--${semanticTone}` : "ra-status-icon--muted";
3271
+ let content;
3272
+ if (iconHint) {
3273
+ content = isValidElement(iconHint) ? iconHint : /* @__PURE__ */ jsx(Fragment, { children: iconHint });
3274
+ } else {
3275
+ const Icon2 = semanticTone && semanticTone !== "default" ? SEMANTIC_DEFAULT_ICONS[semanticTone] : MinusCircle;
3276
+ content = /* @__PURE__ */ jsx(Icon2, { className: "w-full h-full" });
3277
+ }
3278
+ return /* @__PURE__ */ jsx(
3279
+ "span",
3280
+ {
3281
+ className: cn("ra-status-icon", toneClass, className),
3282
+ style: { width: size, height: size },
3283
+ role: label ? "img" : void 0,
3284
+ "aria-label": label,
3285
+ "aria-hidden": label ? void 0 : "true",
3286
+ children: content
3287
+ }
3288
+ );
3289
+ }
3254
3290
  const tone = resolveTone(source, status);
3255
3291
  const Icon = DEFAULT_ICONS.status[tone === "own" ? "own" : tone === "shared" ? "inherited" : "missing"];
3256
3292
  return /* @__PURE__ */ jsx(
@@ -3483,7 +3519,9 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
3483
3519
  StatusIcon,
3484
3520
  {
3485
3521
  status: record.status,
3486
- label: statusToneLabel(tone)
3522
+ label: statusToneLabel(tone),
3523
+ iconHint: record.iconHint,
3524
+ semanticTone: record.toneHint
3487
3525
  }
3488
3526
  ) }),
3489
3527
  /* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
@@ -7396,7 +7434,8 @@ function RecordsAdminShellInner(props) {
7396
7434
  renderCard: renderItemCard,
7397
7435
  renderEmpty: renderItemEmpty,
7398
7436
  cardSize: itemCardSize = "md",
7399
- railMode: collectionRailMode = "siblings"
7437
+ railMode: collectionRailMode = "siblings",
7438
+ toSummary: itemToSummary
7400
7439
  } = items ?? {};
7401
7440
  const {
7402
7441
  strategy: dirtyStrategy = "keep",
@@ -7618,7 +7657,8 @@ function RecordsAdminShellInner(props) {
7618
7657
  // record across the whole collection (anchored, ruled, global) so
7619
7658
  // host-supplied lifecycle grouping has the full picture.
7620
7659
  includeAll: isCollection && activeScope === "all",
7621
- enabled: isCollection
7660
+ enabled: isCollection,
7661
+ toSummary: itemToSummary
7622
7662
  });
7623
7663
  useEffect(() => {
7624
7664
  if (skipNextItemResetRef.current) {
@@ -8404,8 +8444,11 @@ function RecordsAdminShellInner(props) {
8404
8444
  status: b.items.length ? "configured" : "empty",
8405
8445
  label: b.label,
8406
8446
  subtitle: `${b.items.length} ${itemNoun}${b.items.length === 1 ? "" : "s"}`,
8407
- // Tone surfaces as a chip; we reuse `badges` for that.
8408
- badges: b.tone && b.tone !== "default" ? [{ label: b.tone, tone: b.tone === "success" ? "success" : b.tone === "warning" ? "warning" : b.tone === "danger" ? "danger" : "neutral" }] : void 0
8447
+ // Tone + icon drive the row's leading status icon (replacing the
8448
+ // generic green tick / dotted circle for these synthetic rows).
8449
+ // Hosts can override the icon entirely via `groupBy(...).icon`.
8450
+ iconHint: b.icon,
8451
+ toneHint: b.tone
8409
8452
  });
8410
8453
  }
8411
8454
  return rows;