@proveanything/smartlinks-utils-ui 0.10.7 → 0.10.8
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/dist/{IconPicker-BMMQLR5I.d.ts → IconPicker-DKpL5Hcc.d.ts} +1 -1
- package/dist/chunk-2MW54ZVG.js +92 -0
- package/dist/chunk-2MW54ZVG.js.map +1 -0
- package/dist/components/AssetPicker/index.d.ts +1 -1
- package/dist/components/IconPicker/index.d.ts +2 -2
- package/dist/components/RecordsAdmin/index.d.ts +30 -2
- package/dist/components/RecordsAdmin/index.js +119 -105
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +182 -182
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +62 -4
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/{useAssets-BM1bzzkq.d.ts → useAssets-BAtXv6D5.d.ts} +1 -1
- package/package.json +1 -1
|
@@ -40,4 +40,4 @@ interface IconPickerProps {
|
|
|
40
40
|
|
|
41
41
|
declare const IconPicker: React$1.FC<IconPickerProps>;
|
|
42
42
|
|
|
43
|
-
export {
|
|
43
|
+
export { type IconFamily as I, type IconStyle as a, IconPicker as b, type IconPickerProps as c, type IconSelection as d };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useId } from 'react';
|
|
2
|
+
import { BookOpen, HelpCircle, AlertTriangle, CheckCircle2, Lightbulb, Info, X } from 'lucide-react';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/components/AdminPageHeader/AdminPageHeader.tsx
|
|
6
|
+
var TONE_ICON = {
|
|
7
|
+
info: Lightbulb,
|
|
8
|
+
success: CheckCircle2,
|
|
9
|
+
warning: AlertTriangle
|
|
10
|
+
};
|
|
11
|
+
function AdminPageHeader({
|
|
12
|
+
title,
|
|
13
|
+
subtitle,
|
|
14
|
+
icon,
|
|
15
|
+
helpUrl,
|
|
16
|
+
helpLabel,
|
|
17
|
+
actions,
|
|
18
|
+
aside,
|
|
19
|
+
intro,
|
|
20
|
+
className
|
|
21
|
+
}) {
|
|
22
|
+
const titleId = useId();
|
|
23
|
+
const resolvedHelpLabel = helpLabel ?? "Help & documentation";
|
|
24
|
+
const resolvedReopenLabel = intro?.reopenLabel ?? "How it works";
|
|
25
|
+
const showReopen = !!intro && intro.dismissed && !!intro.onReopen;
|
|
26
|
+
const showIntro = !!intro && !intro.dismissed;
|
|
27
|
+
return /* @__PURE__ */ jsxs("header", { className: `sl-aph${className ? ` ${className}` : ""}`, "aria-labelledby": titleId, children: [
|
|
28
|
+
/* @__PURE__ */ jsxs("div", { className: "sl-aph__row", children: [
|
|
29
|
+
/* @__PURE__ */ jsx("div", { className: "sl-aph__main", children: /* @__PURE__ */ jsxs("div", { className: "sl-aph__text", children: [
|
|
30
|
+
/* @__PURE__ */ jsxs("h1", { className: "sl-aph__title", id: titleId, children: [
|
|
31
|
+
icon ? /* @__PURE__ */ jsx("span", { className: "sl-aph__icon", "aria-hidden": "true", children: icon }) : null,
|
|
32
|
+
/* @__PURE__ */ jsx("span", { children: title })
|
|
33
|
+
] }),
|
|
34
|
+
subtitle ? /* @__PURE__ */ jsx("p", { className: "sl-aph__subtitle", children: subtitle }) : null
|
|
35
|
+
] }) }),
|
|
36
|
+
actions || aside || helpUrl || showReopen ? /* @__PURE__ */ jsxs("div", { className: "sl-aph__aside", children: [
|
|
37
|
+
actions,
|
|
38
|
+
aside,
|
|
39
|
+
helpUrl ? /* @__PURE__ */ jsx(
|
|
40
|
+
"a",
|
|
41
|
+
{
|
|
42
|
+
href: helpUrl,
|
|
43
|
+
target: "_blank",
|
|
44
|
+
rel: "noopener noreferrer",
|
|
45
|
+
className: "sl-aph__icon-btn",
|
|
46
|
+
"aria-label": resolvedHelpLabel,
|
|
47
|
+
title: resolvedHelpLabel,
|
|
48
|
+
children: /* @__PURE__ */ jsx(BookOpen, { "aria-hidden": "true" })
|
|
49
|
+
}
|
|
50
|
+
) : null,
|
|
51
|
+
showReopen ? /* @__PURE__ */ jsx(
|
|
52
|
+
"button",
|
|
53
|
+
{
|
|
54
|
+
type: "button",
|
|
55
|
+
onClick: intro.onReopen,
|
|
56
|
+
className: "sl-aph__icon-btn",
|
|
57
|
+
"aria-label": resolvedReopenLabel,
|
|
58
|
+
title: resolvedReopenLabel,
|
|
59
|
+
children: /* @__PURE__ */ jsx(HelpCircle, { "aria-hidden": "true" })
|
|
60
|
+
}
|
|
61
|
+
) : null
|
|
62
|
+
] }) : null
|
|
63
|
+
] }),
|
|
64
|
+
showIntro ? /* @__PURE__ */ jsx(AdminPageHeaderIntroCard, { intro }) : null
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
function AdminPageHeaderIntroCard({ intro }) {
|
|
68
|
+
const tone = intro.tone ?? "info";
|
|
69
|
+
const Icon = TONE_ICON[tone] ?? Info;
|
|
70
|
+
return /* @__PURE__ */ jsxs("div", { className: "sl-aph__intro", "data-tone": tone, role: "note", children: [
|
|
71
|
+
/* @__PURE__ */ jsx("div", { className: "sl-aph__intro-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true", style: { width: "0.95rem", height: "0.95rem" } }) }),
|
|
72
|
+
/* @__PURE__ */ jsxs("div", { className: "sl-aph__intro-body", children: [
|
|
73
|
+
/* @__PURE__ */ jsx("h4", { className: "sl-aph__intro-title", children: intro.title }),
|
|
74
|
+
/* @__PURE__ */ jsx("span", { className: "sl-aph__intro-text", children: intro.body }),
|
|
75
|
+
intro.action ? /* @__PURE__ */ jsx("span", { className: "sl-aph__intro-action", children: intro.action }) : null
|
|
76
|
+
] }),
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
"button",
|
|
79
|
+
{
|
|
80
|
+
type: "button",
|
|
81
|
+
onClick: intro.onDismiss,
|
|
82
|
+
"aria-label": "Dismiss",
|
|
83
|
+
className: "sl-aph__intro-dismiss",
|
|
84
|
+
children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true", style: { width: "0.875rem", height: "0.875rem" } })
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
] });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { AdminPageHeader };
|
|
91
|
+
//# sourceMappingURL=chunk-2MW54ZVG.js.map
|
|
92
|
+
//# sourceMappingURL=chunk-2MW54ZVG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AdminPageHeader/AdminPageHeader.tsx"],"names":[],"mappings":"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","file":"chunk-2MW54ZVG.js","sourcesContent":["// =============================================================================\r\n// AdminPageHeader\r\n//\r\n// A standardised page header for any SmartLinks admin surface. Designed to be\r\n// used standalone (lightweight apps that don't need the full RecordsAdminShell)\r\n// or composed inside other shells. Supports:\r\n//\r\n// • Inline icon + title + full-width subtitle\r\n// • Right-aligned slot for app-specific actions (e.g. \"+ New\" button)\r\n// • External help link (icon-button that opens docs in a new tab)\r\n// • Optional dismissible intro card with `?` reopen affordance\r\n// • Optional `aside` slot for extra header content (stats strips, etc.)\r\n//\r\n// Styling is self-contained under `.sl-aph` and reuses the shared `--ra-*`\r\n// design tokens with sensible fallbacks, so it themes correctly whether the\r\n// host has loaded the records-admin token sheet or not.\r\n// =============================================================================\r\nimport { type ReactNode, useId } from 'react';\r\nimport { BookOpen, HelpCircle, X, Lightbulb, CheckCircle2, AlertTriangle, Info } from 'lucide-react';\r\nimport './admin-page-header.css';\r\n\r\nexport type AdminPageHeaderIntroTone = 'info' | 'success' | 'warning';\r\n\r\nexport interface AdminPageHeaderIntro {\r\n /** Short headline shown in bold at the start of the intro card. */\r\n title: string;\r\n /** Body content — plain text or rich nodes. */\r\n body: ReactNode;\r\n /** Visual tone — controls icon and surface tint. Default `'info'`. */\r\n tone?: AdminPageHeaderIntroTone;\r\n /** Optional action node rendered inline after the body (e.g. a Learn-more link). */\r\n action?: ReactNode;\r\n /** Whether the intro is currently dismissed. Controlled. */\r\n dismissed: boolean;\r\n /** Called when the user clicks the dismiss `X`. */\r\n onDismiss: () => void;\r\n /**\r\n * Called when the user clicks the reopen `?` button (only rendered when\r\n * dismissed is true). Omit to hide the reopen affordance entirely.\r\n */\r\n onReopen?: () => void;\r\n /** Tooltip / aria-label for the reopen button. Default \"How it works\". */\r\n reopenLabel?: string;\r\n}\r\n\r\nexport interface AdminPageHeaderProps {\r\n /** Page title — required. */\r\n title: string;\r\n /** Single-line muted subtitle under the title. */\r\n subtitle?: string;\r\n /** Icon rendered inline before the title. Pass a Lucide element or any node. */\r\n icon?: ReactNode;\r\n /**\r\n * External help / documentation URL. When set, renders a small icon-button\r\n * that opens the URL in a new tab. Use this to point at app-specific docs.\r\n */\r\n helpUrl?: string;\r\n /** Tooltip / aria-label for the help link. Default \"Help & documentation\". */\r\n helpLabel?: string;\r\n /**\r\n * Right-aligned action slot — typically a primary \"+ New\" button and/or\r\n * secondary controls. Rendered before the help / intro-reopen icon-buttons.\r\n */\r\n actions?: ReactNode;\r\n /**\r\n * Extra header content rendered between `actions` and the trailing\r\n * help / reopen icon-buttons. Used by RecordsAdminShell for its stats strip;\r\n * standalone apps rarely need it.\r\n */\r\n aside?: ReactNode;\r\n /**\r\n * Optional dismissible intro card rendered below the header row.\r\n * See {@link AdminPageHeaderIntro}.\r\n */\r\n intro?: AdminPageHeaderIntro;\r\n /** Extra class on the root container for layout overrides. */\r\n className?: string;\r\n}\r\n\r\nconst TONE_ICON = {\r\n info: Lightbulb,\r\n success: CheckCircle2,\r\n warning: AlertTriangle,\r\n} as const;\r\n\r\nexport function AdminPageHeader({\r\n title, subtitle, icon, helpUrl, helpLabel,\r\n actions, aside, intro, className,\r\n}: AdminPageHeaderProps) {\r\n const titleId = useId();\r\n const resolvedHelpLabel = helpLabel ?? 'Help & documentation';\r\n const resolvedReopenLabel = intro?.reopenLabel ?? 'How it works';\r\n const showReopen = !!intro && intro.dismissed && !!intro.onReopen;\r\n const showIntro = !!intro && !intro.dismissed;\r\n\r\n return (\r\n <header className={`sl-aph${className ? ` ${className}` : ''}`} aria-labelledby={titleId}>\r\n <div className=\"sl-aph__row\">\r\n <div className=\"sl-aph__main\">\r\n <div className=\"sl-aph__text\">\r\n <h1 className=\"sl-aph__title\" id={titleId}>\r\n {icon ? (\r\n <span className=\"sl-aph__icon\" aria-hidden=\"true\">{icon}</span>\r\n ) : null}\r\n <span>{title}</span>\r\n </h1>\r\n {subtitle ? <p className=\"sl-aph__subtitle\">{subtitle}</p> : null}\r\n </div>\r\n </div>\r\n {(actions || aside || helpUrl || showReopen) ? (\r\n <div className=\"sl-aph__aside\">\r\n {actions}\r\n {aside}\r\n {helpUrl ? (\r\n <a\r\n href={helpUrl}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"sl-aph__icon-btn\"\r\n aria-label={resolvedHelpLabel}\r\n title={resolvedHelpLabel}\r\n >\r\n <BookOpen aria-hidden=\"true\" />\r\n </a>\r\n ) : null}\r\n {showReopen ? (\r\n <button\r\n type=\"button\"\r\n onClick={intro!.onReopen}\r\n className=\"sl-aph__icon-btn\"\r\n aria-label={resolvedReopenLabel}\r\n title={resolvedReopenLabel}\r\n >\r\n <HelpCircle aria-hidden=\"true\" />\r\n </button>\r\n ) : null}\r\n </div>\r\n ) : null}\r\n </div>\r\n {showIntro ? <AdminPageHeaderIntroCard intro={intro!} /> : null}\r\n </header>\r\n );\r\n}\r\n\r\nfunction AdminPageHeaderIntroCard({ intro }: { intro: AdminPageHeaderIntro }) {\r\n const tone = intro.tone ?? 'info';\r\n const Icon = TONE_ICON[tone] ?? Info;\r\n return (\r\n <div className=\"sl-aph__intro\" data-tone={tone} role=\"note\">\r\n <div className=\"sl-aph__intro-icon\">\r\n <Icon aria-hidden=\"true\" style={{ width: '0.95rem', height: '0.95rem' }} />\r\n </div>\r\n <div className=\"sl-aph__intro-body\">\r\n <h4 className=\"sl-aph__intro-title\">{intro.title}</h4>\r\n <span className=\"sl-aph__intro-text\">{intro.body}</span>\r\n {intro.action ? <span className=\"sl-aph__intro-action\">{intro.action}</span> : null}\r\n </div>\r\n <button\r\n type=\"button\"\r\n onClick={intro.onDismiss}\r\n aria-label=\"Dismiss\"\r\n className=\"sl-aph__intro-dismiss\"\r\n >\r\n <X aria-hidden=\"true\" style={{ width: '0.875rem', height: '0.875rem' }} />\r\n </button>\r\n </div>\r\n );\r\n}"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { A as AssetItem, a as AssetPicker, b as AssetPickerMode, c as AssetPickerProps, d as AssetPickerSelection, e as AssetScope, f as AssetViewMode, u as useAssets } from '../../useAssets-BAtXv6D5.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
|
|
4
4
|
interface AppRegistryEntry {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { I as IconFamily, a as IconStyle } from '../../IconPicker-DKpL5Hcc.js';
|
|
2
|
+
export { b as IconPicker, c as IconPickerProps, d as IconSelection } from '../../IconPicker-DKpL5Hcc.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
|
|
5
5
|
declare function toFaClass(id: string, family: IconFamily, style: IconStyle | null): string;
|
|
@@ -962,7 +962,35 @@ interface RailConfig<TData = unknown> {
|
|
|
962
962
|
key: string;
|
|
963
963
|
label: string;
|
|
964
964
|
icon?: ReactNode;
|
|
965
|
+
/**
|
|
966
|
+
* Whether this bucket should be expanded by default (records-driven
|
|
967
|
+
* accordion mode). Last-write-wins per key. Has no effect in the
|
|
968
|
+
* collection-cardinality lifecycle-rail mode where buckets are flat
|
|
969
|
+
* selectable rows rather than accordion sections.
|
|
970
|
+
*/
|
|
971
|
+
defaultOpen?: boolean;
|
|
972
|
+
/**
|
|
973
|
+
* Semantic tone for the bucket — drives a CSS data attribute on the
|
|
974
|
+
* lifecycle bucket row (`data-tone="success" | "warning" | "muted"`).
|
|
975
|
+
* Apps style via `[data-tone="…"]` selectors against existing
|
|
976
|
+
* semantic tokens.
|
|
977
|
+
*/
|
|
978
|
+
tone?: 'default' | 'success' | 'warning' | 'muted' | 'danger';
|
|
965
979
|
} | null;
|
|
980
|
+
/**
|
|
981
|
+
* Initial bucket key to select on first mount of the lifecycle rail
|
|
982
|
+
* (collection cardinality + `'all'` / `'global'` scope + `groupBy`).
|
|
983
|
+
* Ignored when a deep-link state restores a different selection. Pass
|
|
984
|
+
* the same key shape your `groupBy` returns (e.g. `"1-open"`).
|
|
985
|
+
*/
|
|
986
|
+
defaultGroupKey?: string;
|
|
987
|
+
/**
|
|
988
|
+
* EXPERIMENTAL — invoked the first time a lifecycle bucket is selected
|
|
989
|
+
* (collection-cardinality lifecycle rail). Hosts can use this to trigger
|
|
990
|
+
* supplemental fetches before the bucket-filtered table renders. May be
|
|
991
|
+
* called more than once per key. API may change before stabilising.
|
|
992
|
+
*/
|
|
993
|
+
onGroupExpanded?: (key: string) => void;
|
|
966
994
|
/** Visual density. Default `comfortable`. */
|
|
967
995
|
density?: 'comfortable' | 'compact';
|
|
968
996
|
}
|
|
@@ -1696,7 +1724,7 @@ declare const useRecordList: (args: UseRecordListArgs) => {
|
|
|
1696
1724
|
};
|
|
1697
1725
|
isLoading: boolean;
|
|
1698
1726
|
error: Error | null;
|
|
1699
|
-
refetch: () => void
|
|
1727
|
+
refetch: () => Promise<void>;
|
|
1700
1728
|
hasNextPage: boolean;
|
|
1701
1729
|
isFetchingNextPage: boolean;
|
|
1702
1730
|
fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<_tanstack_query_core.InfiniteData<{
|
|
@@ -1841,7 +1869,7 @@ declare function useCollectionItems<T = unknown>(args: UseCollectionItemsArgs):
|
|
|
1841
1869
|
hasMore: boolean;
|
|
1842
1870
|
nextOffset: number;
|
|
1843
1871
|
}, unknown>, Error>>;
|
|
1844
|
-
refetch: () => void
|
|
1872
|
+
refetch: () => Promise<void>;
|
|
1845
1873
|
};
|
|
1846
1874
|
|
|
1847
1875
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AdminPageHeader } from '../../chunk-2MW54ZVG.js';
|
|
1
2
|
import { assertComponentStylesLoaded } from '../../chunk-OLYC54YT.js';
|
|
2
3
|
import '../../chunk-5UQQYXCX.js';
|
|
3
4
|
import { FacetRuleEditor } from '../../chunk-JMCV6FOW.js';
|
|
@@ -5,8 +6,8 @@ import { useFacets } from '../../chunk-4LHF5JB7.js';
|
|
|
5
6
|
import { cn } from '../../chunk-L7FQ52F5.js';
|
|
6
7
|
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
|
|
7
8
|
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
|
|
8
|
-
import { createContext, useState, useEffect, useCallback, useMemo, useRef, useContext, useSyncExternalStore, useLayoutEffect, createElement
|
|
9
|
-
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,
|
|
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';
|
|
10
11
|
import { useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
11
12
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
12
13
|
import { createPortal } from 'react-dom';
|
|
@@ -690,9 +691,9 @@ var useRecordList = (args) => {
|
|
|
690
691
|
partial: items.filter((r) => r.status === "partial").length,
|
|
691
692
|
empty: items.filter((r) => r.status === "empty").length
|
|
692
693
|
}), [items]);
|
|
693
|
-
const refetch = useCallback(() => {
|
|
694
|
-
|
|
695
|
-
}, [queryClient, ctx.collectionId, ctx.appId, ctx.recordType]);
|
|
694
|
+
const refetch = useCallback(() => queryClient.refetchQueries({
|
|
695
|
+
queryKey: [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType]
|
|
696
|
+
}), [queryClient, ctx.collectionId, ctx.appId, ctx.recordType]);
|
|
696
697
|
const total = query.data?.pages[query.data.pages.length - 1]?.total ?? items.length;
|
|
697
698
|
return {
|
|
698
699
|
allItems: items,
|
|
@@ -3125,9 +3126,11 @@ var useShellSelection = (args) => {
|
|
|
3125
3126
|
}, [contextScope?.batchId]);
|
|
3126
3127
|
const [selectedItemId, setSelectedItemId] = useState(null);
|
|
3127
3128
|
const skipNextItemResetRef = useRef(false);
|
|
3129
|
+
const [selectedLifecycleKey, setSelectedLifecycleKey] = useState(null);
|
|
3128
3130
|
useEffect(() => {
|
|
3129
3131
|
setSelectedRecordId(null);
|
|
3130
3132
|
setDraftKind(null);
|
|
3133
|
+
setSelectedLifecycleKey(null);
|
|
3131
3134
|
}, [activeScope]);
|
|
3132
3135
|
return {
|
|
3133
3136
|
activeScope,
|
|
@@ -3150,6 +3153,8 @@ var useShellSelection = (args) => {
|
|
|
3150
3153
|
setSelectedBatchId,
|
|
3151
3154
|
selectedItemId,
|
|
3152
3155
|
setSelectedItemId,
|
|
3156
|
+
selectedLifecycleKey,
|
|
3157
|
+
setSelectedLifecycleKey,
|
|
3153
3158
|
skipNextItemResetRef
|
|
3154
3159
|
};
|
|
3155
3160
|
};
|
|
@@ -4086,9 +4091,7 @@ function useCollectionItems(args) {
|
|
|
4086
4091
|
return toSummary2(rec, base);
|
|
4087
4092
|
}).filter((x) => x !== null);
|
|
4088
4093
|
}, [query.data, toSummary2, scope, ruleSignature, includeAll]);
|
|
4089
|
-
const refetch = useCallback(() => {
|
|
4090
|
-
queryClient.invalidateQueries({ queryKey });
|
|
4091
|
-
}, [queryClient, queryKey]);
|
|
4094
|
+
const refetch = useCallback(() => queryClient.refetchQueries({ queryKey }), [queryClient, queryKey]);
|
|
4092
4095
|
return {
|
|
4093
4096
|
items,
|
|
4094
4097
|
total: query.data?.pages[query.data.pages.length - 1]?.total ?? items.length,
|
|
@@ -6193,89 +6196,6 @@ var UtilityRow = ({ label, customLabel, introHidden, onShowIntro }) => {
|
|
|
6193
6196
|
}
|
|
6194
6197
|
);
|
|
6195
6198
|
};
|
|
6196
|
-
var TONE_ICON2 = {
|
|
6197
|
-
info: Lightbulb,
|
|
6198
|
-
success: CheckCircle2,
|
|
6199
|
-
warning: AlertTriangle
|
|
6200
|
-
};
|
|
6201
|
-
function AdminPageHeader({
|
|
6202
|
-
title,
|
|
6203
|
-
subtitle,
|
|
6204
|
-
icon,
|
|
6205
|
-
helpUrl,
|
|
6206
|
-
helpLabel,
|
|
6207
|
-
actions,
|
|
6208
|
-
aside,
|
|
6209
|
-
intro,
|
|
6210
|
-
className
|
|
6211
|
-
}) {
|
|
6212
|
-
const titleId = useId();
|
|
6213
|
-
const resolvedHelpLabel = helpLabel ?? "Help & documentation";
|
|
6214
|
-
const resolvedReopenLabel = intro?.reopenLabel ?? "How it works";
|
|
6215
|
-
const showReopen = !!intro && intro.dismissed && !!intro.onReopen;
|
|
6216
|
-
const showIntro = !!intro && !intro.dismissed;
|
|
6217
|
-
return /* @__PURE__ */ jsxs("header", { className: `sl-aph${className ? ` ${className}` : ""}`, "aria-labelledby": titleId, children: [
|
|
6218
|
-
/* @__PURE__ */ jsxs("div", { className: "sl-aph__row", children: [
|
|
6219
|
-
/* @__PURE__ */ jsx("div", { className: "sl-aph__main", children: /* @__PURE__ */ jsxs("div", { className: "sl-aph__text", children: [
|
|
6220
|
-
/* @__PURE__ */ jsxs("h1", { className: "sl-aph__title", id: titleId, children: [
|
|
6221
|
-
icon ? /* @__PURE__ */ jsx("span", { className: "sl-aph__icon", "aria-hidden": "true", children: icon }) : null,
|
|
6222
|
-
/* @__PURE__ */ jsx("span", { children: title })
|
|
6223
|
-
] }),
|
|
6224
|
-
subtitle ? /* @__PURE__ */ jsx("p", { className: "sl-aph__subtitle", children: subtitle }) : null
|
|
6225
|
-
] }) }),
|
|
6226
|
-
actions || aside || helpUrl || showReopen ? /* @__PURE__ */ jsxs("div", { className: "sl-aph__aside", children: [
|
|
6227
|
-
actions,
|
|
6228
|
-
aside,
|
|
6229
|
-
helpUrl ? /* @__PURE__ */ jsx(
|
|
6230
|
-
"a",
|
|
6231
|
-
{
|
|
6232
|
-
href: helpUrl,
|
|
6233
|
-
target: "_blank",
|
|
6234
|
-
rel: "noopener noreferrer",
|
|
6235
|
-
className: "sl-aph__icon-btn",
|
|
6236
|
-
"aria-label": resolvedHelpLabel,
|
|
6237
|
-
title: resolvedHelpLabel,
|
|
6238
|
-
children: /* @__PURE__ */ jsx(BookOpen, { "aria-hidden": "true" })
|
|
6239
|
-
}
|
|
6240
|
-
) : null,
|
|
6241
|
-
showReopen ? /* @__PURE__ */ jsx(
|
|
6242
|
-
"button",
|
|
6243
|
-
{
|
|
6244
|
-
type: "button",
|
|
6245
|
-
onClick: intro.onReopen,
|
|
6246
|
-
className: "sl-aph__icon-btn",
|
|
6247
|
-
"aria-label": resolvedReopenLabel,
|
|
6248
|
-
title: resolvedReopenLabel,
|
|
6249
|
-
children: /* @__PURE__ */ jsx(HelpCircle, { "aria-hidden": "true" })
|
|
6250
|
-
}
|
|
6251
|
-
) : null
|
|
6252
|
-
] }) : null
|
|
6253
|
-
] }),
|
|
6254
|
-
showIntro ? /* @__PURE__ */ jsx(AdminPageHeaderIntroCard, { intro }) : null
|
|
6255
|
-
] });
|
|
6256
|
-
}
|
|
6257
|
-
function AdminPageHeaderIntroCard({ intro }) {
|
|
6258
|
-
const tone = intro.tone ?? "info";
|
|
6259
|
-
const Icon = TONE_ICON2[tone] ?? Info;
|
|
6260
|
-
return /* @__PURE__ */ jsxs("div", { className: "sl-aph__intro", "data-tone": tone, role: "note", children: [
|
|
6261
|
-
/* @__PURE__ */ jsx("div", { className: "sl-aph__intro-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true", style: { width: "0.95rem", height: "0.95rem" } }) }),
|
|
6262
|
-
/* @__PURE__ */ jsxs("div", { className: "sl-aph__intro-body", children: [
|
|
6263
|
-
/* @__PURE__ */ jsx("h4", { className: "sl-aph__intro-title", children: intro.title }),
|
|
6264
|
-
/* @__PURE__ */ jsx("span", { className: "sl-aph__intro-text", children: intro.body }),
|
|
6265
|
-
intro.action ? /* @__PURE__ */ jsx("span", { className: "sl-aph__intro-action", children: intro.action }) : null
|
|
6266
|
-
] }),
|
|
6267
|
-
/* @__PURE__ */ jsx(
|
|
6268
|
-
"button",
|
|
6269
|
-
{
|
|
6270
|
-
type: "button",
|
|
6271
|
-
onClick: intro.onDismiss,
|
|
6272
|
-
"aria-label": "Dismiss",
|
|
6273
|
-
className: "sl-aph__intro-dismiss",
|
|
6274
|
-
children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true", style: { width: "0.875rem", height: "0.875rem" } })
|
|
6275
|
-
}
|
|
6276
|
-
)
|
|
6277
|
-
] });
|
|
6278
|
-
}
|
|
6279
6199
|
function ShellHeader({
|
|
6280
6200
|
title,
|
|
6281
6201
|
subtitle,
|
|
@@ -7452,6 +7372,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7452
7372
|
renderListRow,
|
|
7453
7373
|
renderEmpty: renderEmptyState,
|
|
7454
7374
|
groupBy,
|
|
7375
|
+
defaultGroupKey,
|
|
7376
|
+
onGroupExpanded,
|
|
7455
7377
|
density = "comfortable"
|
|
7456
7378
|
} = rail ?? {};
|
|
7457
7379
|
const {
|
|
@@ -7592,8 +7514,11 @@ function RecordsAdminShellInner(props) {
|
|
|
7592
7514
|
setSelectedBatchId,
|
|
7593
7515
|
selectedItemId,
|
|
7594
7516
|
setSelectedItemId,
|
|
7517
|
+
selectedLifecycleKey,
|
|
7518
|
+
setSelectedLifecycleKey,
|
|
7595
7519
|
skipNextItemResetRef
|
|
7596
7520
|
} = selection;
|
|
7521
|
+
const [isReconcilingRecordSelection, setIsReconcilingRecordSelection] = useState(false);
|
|
7597
7522
|
const { dismissed, dismiss, undismiss } = useIntroDismissed(SL, collectionId, appId, recordType);
|
|
7598
7523
|
const headerWillRender = useMemo(() => {
|
|
7599
7524
|
const headerCustomised = !!title || !!subtitle || !!headerIcon || !!headerActions || showStats || !!statsItems || !!statsTitle || !!statsIcon || !!helpUrl;
|
|
@@ -7654,6 +7579,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7654
7579
|
useEffect(() => {
|
|
7655
7580
|
if (activeScope !== "rule" && activeScope !== "collection" && activeScope !== "all") return;
|
|
7656
7581
|
if (selectedRecordId !== null) return;
|
|
7582
|
+
if (isReconcilingRecordSelection) return;
|
|
7657
7583
|
if (ruleWizardStep !== null) return;
|
|
7658
7584
|
if (draftKind !== null) return;
|
|
7659
7585
|
if (activeScope === "collection" && cardinality === "collection") {
|
|
@@ -7664,7 +7590,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7664
7590
|
}
|
|
7665
7591
|
const first = recordList.items[0];
|
|
7666
7592
|
if (first?.id) setSelectedRecordId(first.id);
|
|
7667
|
-
}, [activeScope, selectedRecordId, recordList.items, cardinality, ruleWizardStep, draftKind]);
|
|
7593
|
+
}, [activeScope, selectedRecordId, recordList.items, cardinality, ruleWizardStep, draftKind, isReconcilingRecordSelection]);
|
|
7668
7594
|
const editingScopes = useEditingScope({
|
|
7669
7595
|
activeScope,
|
|
7670
7596
|
cardinality,
|
|
@@ -7761,10 +7687,15 @@ function RecordsAdminShellInner(props) {
|
|
|
7761
7687
|
supportedScopes: supportedForResolution,
|
|
7762
7688
|
enabled: !!editingTargetScope
|
|
7763
7689
|
});
|
|
7764
|
-
const refetchAll = useCallback(() => {
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7690
|
+
const refetchAll = useCallback(async () => {
|
|
7691
|
+
await Promise.all([
|
|
7692
|
+
recordList.refetch(),
|
|
7693
|
+
isCollection ? collectionItems.refetch() : Promise.resolve(),
|
|
7694
|
+
queryClient.refetchQueries({
|
|
7695
|
+
queryKey: scopeCountsQueryKey(ctx.collectionId, ctx.appId, ctx.recordType)
|
|
7696
|
+
})
|
|
7697
|
+
]);
|
|
7698
|
+
}, [recordList, isCollection, collectionItems, queryClient, ctx.collectionId, ctx.appId, ctx.recordType]);
|
|
7768
7699
|
const { editorCtx } = useShellEditorTarget({
|
|
7769
7700
|
editingTargetScope,
|
|
7770
7701
|
isCollection,
|
|
@@ -7783,7 +7714,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7783
7714
|
},
|
|
7784
7715
|
defaultData,
|
|
7785
7716
|
deriveDraftLabel,
|
|
7786
|
-
onSaved: (isCreate, savedRecordId) => {
|
|
7717
|
+
onSaved: async (isCreate, savedRecordId) => {
|
|
7787
7718
|
onTelemetry?.({ type: "record.save", recordType, ref: editingTargetScope?.raw ?? "", isCreate });
|
|
7788
7719
|
if (ruleWizardStep !== null) {
|
|
7789
7720
|
setRuleWizardStep(null);
|
|
@@ -7791,15 +7722,20 @@ function RecordsAdminShellInner(props) {
|
|
|
7791
7722
|
setDraftKind(null);
|
|
7792
7723
|
}
|
|
7793
7724
|
if (isCreate && selectedRecordId === DRAFT_ID3) {
|
|
7794
|
-
|
|
7725
|
+
setIsReconcilingRecordSelection(true);
|
|
7726
|
+
setSelectedRecordId(null);
|
|
7795
7727
|
setDraftKind(null);
|
|
7796
7728
|
}
|
|
7797
7729
|
if (isCreate && isCollection && savedRecordId && isDraftId3(selectedItemId)) {
|
|
7798
7730
|
setSelectedItemId(savedRecordId);
|
|
7799
7731
|
}
|
|
7800
|
-
refetchAll();
|
|
7732
|
+
await refetchAll();
|
|
7733
|
+
if (!isCollection && isCreate && activeScope === "collection") {
|
|
7734
|
+
setSelectedRecordId(savedRecordId ?? null);
|
|
7735
|
+
}
|
|
7736
|
+
setIsReconcilingRecordSelection(false);
|
|
7801
7737
|
},
|
|
7802
|
-
onDeleted: () => {
|
|
7738
|
+
onDeleted: async () => {
|
|
7803
7739
|
onTelemetry?.({ type: "record.delete", recordType, ref: editingTargetScope?.raw ?? "" });
|
|
7804
7740
|
if (isCollection && selectedItemId) {
|
|
7805
7741
|
setSelectedItemId(null);
|
|
@@ -7808,10 +7744,12 @@ function RecordsAdminShellInner(props) {
|
|
|
7808
7744
|
} else if (drillTab === "batch") {
|
|
7809
7745
|
setSelectedBatchId(void 0);
|
|
7810
7746
|
} else if (selectedRecordId) {
|
|
7747
|
+
setIsReconcilingRecordSelection(true);
|
|
7811
7748
|
setSelectedRecordId(null);
|
|
7812
7749
|
setDraftKind(null);
|
|
7813
7750
|
}
|
|
7814
|
-
refetchAll();
|
|
7751
|
+
await refetchAll();
|
|
7752
|
+
setIsReconcilingRecordSelection(false);
|
|
7815
7753
|
}
|
|
7816
7754
|
});
|
|
7817
7755
|
useUnsavedGuard({
|
|
@@ -8426,17 +8364,93 @@ function RecordsAdminShellInner(props) {
|
|
|
8426
8364
|
}),
|
|
8427
8365
|
[i18n.itemsAllLabel, collectionItems.items.length, itemNoun]
|
|
8428
8366
|
);
|
|
8367
|
+
const isLifecycleRail = (isAllTab || isGlobalTab) && isCollection && !!groupBy;
|
|
8368
|
+
const lifecycleBuckets = useMemo(() => {
|
|
8369
|
+
if (!isLifecycleRail || !groupBy) return [];
|
|
8370
|
+
const map = /* @__PURE__ */ new Map();
|
|
8371
|
+
const order = [];
|
|
8372
|
+
for (const item of collectionItems.items) {
|
|
8373
|
+
const g = groupBy(item) ?? { key: "__other", label: "Other" };
|
|
8374
|
+
let bucket = map.get(g.key);
|
|
8375
|
+
if (!bucket) {
|
|
8376
|
+
bucket = { key: g.key, label: g.label, icon: g.icon, tone: g.tone, items: [] };
|
|
8377
|
+
map.set(g.key, bucket);
|
|
8378
|
+
order.push(g.key);
|
|
8379
|
+
}
|
|
8380
|
+
bucket.items.push(item);
|
|
8381
|
+
}
|
|
8382
|
+
return order.sort().map((k) => map.get(k));
|
|
8383
|
+
}, [isLifecycleRail, groupBy, collectionItems.items]);
|
|
8384
|
+
const LIFECYCLE_PREFIX = "lifecycle:";
|
|
8385
|
+
const lifecycleRows = useMemo(() => {
|
|
8386
|
+
if (!isLifecycleRail) return [];
|
|
8387
|
+
const rows = [
|
|
8388
|
+
{
|
|
8389
|
+
id: `${LIFECYCLE_PREFIX}__all`,
|
|
8390
|
+
ref: "",
|
|
8391
|
+
scope: parseRef(""),
|
|
8392
|
+
data: null,
|
|
8393
|
+
status: collectionItems.items.length ? "configured" : "empty",
|
|
8394
|
+
label: i18n.itemsAllLabel,
|
|
8395
|
+
subtitle: collectionItems.items.length ? `${collectionItems.items.length} ${itemNoun}${collectionItems.items.length === 1 ? "" : "s"}` : void 0
|
|
8396
|
+
}
|
|
8397
|
+
];
|
|
8398
|
+
for (const b of lifecycleBuckets) {
|
|
8399
|
+
rows.push({
|
|
8400
|
+
id: `${LIFECYCLE_PREFIX}${b.key}`,
|
|
8401
|
+
ref: "",
|
|
8402
|
+
scope: parseRef(""),
|
|
8403
|
+
data: null,
|
|
8404
|
+
status: b.items.length ? "configured" : "empty",
|
|
8405
|
+
label: b.label,
|
|
8406
|
+
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
|
|
8409
|
+
});
|
|
8410
|
+
}
|
|
8411
|
+
return rows;
|
|
8412
|
+
}, [isLifecycleRail, lifecycleBuckets, collectionItems.items.length, i18n.itemsAllLabel, itemNoun]);
|
|
8413
|
+
const lifecycleSeededRef = useRef(false);
|
|
8414
|
+
useEffect(() => {
|
|
8415
|
+
if (!isLifecycleRail) {
|
|
8416
|
+
lifecycleSeededRef.current = false;
|
|
8417
|
+
return;
|
|
8418
|
+
}
|
|
8419
|
+
if (lifecycleSeededRef.current) return;
|
|
8420
|
+
if (selectedLifecycleKey !== null) {
|
|
8421
|
+
lifecycleSeededRef.current = true;
|
|
8422
|
+
return;
|
|
8423
|
+
}
|
|
8424
|
+
if (!defaultGroupKey) return;
|
|
8425
|
+
if (!lifecycleBuckets.some((b) => b.key === defaultGroupKey)) return;
|
|
8426
|
+
setSelectedLifecycleKey(defaultGroupKey);
|
|
8427
|
+
lifecycleSeededRef.current = true;
|
|
8428
|
+
}, [isLifecycleRail, defaultGroupKey, lifecycleBuckets, selectedLifecycleKey, setSelectedLifecycleKey]);
|
|
8429
|
+
const filteredCollectionItems = useMemo(() => {
|
|
8430
|
+
if (!isLifecycleRail || !selectedLifecycleKey || !groupBy) return collectionItems.items;
|
|
8431
|
+
return collectionItems.items.filter((it) => {
|
|
8432
|
+
const g = groupBy(it) ?? { key: "__other" };
|
|
8433
|
+
return g.key === selectedLifecycleKey;
|
|
8434
|
+
});
|
|
8435
|
+
}, [isLifecycleRail, selectedLifecycleKey, groupBy, collectionItems.items]);
|
|
8429
8436
|
const leftItems = isProductTab ? productListItems : isRuleTab ? applyFacetBrowseFilter(
|
|
8430
8437
|
isCollection ? collectionRuleRailItems : filteredRuleItems
|
|
8431
|
-
) : (isGlobalTab || isAllTab) && isCollection ? [collectionGlobalAllRow] : isRecordsTab ? applyFacetBrowseFilter(recordList.items) : [];
|
|
8438
|
+
) : isLifecycleRail ? lifecycleRows : (isGlobalTab || isAllTab) && isCollection ? [collectionGlobalAllRow] : isRecordsTab ? applyFacetBrowseFilter(recordList.items) : [];
|
|
8432
8439
|
const leftLoading = isProductTab ? !productPinned && productBrowse.isLoading : isRecordsTab ? recordList.isLoading || probe.isLoading : false;
|
|
8433
8440
|
const leftError = isProductTab ? productBrowse.error : isRecordsTab ? recordList.error : null;
|
|
8434
|
-
const leftSelectedId = isProductTab ? void 0 : selectedRecordId && selectedRecordId !== DRAFT_ID3 ? selectedRecordId : void 0;
|
|
8441
|
+
const leftSelectedId = isProductTab ? void 0 : isLifecycleRail ? `${LIFECYCLE_PREFIX}${selectedLifecycleKey ?? "__all"}` : selectedRecordId && selectedRecordId !== DRAFT_ID3 ? selectedRecordId : void 0;
|
|
8435
8442
|
const leftSelectedAnchorKey = isProductTab ? selectedProductId ? buildRef({ productId: selectedProductId }) : void 0 : void 0;
|
|
8436
8443
|
const dirtyId = !editorCtx.isDirty ? void 0 : selectedRecordId && selectedRecordId !== DRAFT_ID3 ? selectedRecordId : void 0;
|
|
8437
8444
|
const dirtyAnchorKey = !editorCtx.isDirty ? void 0 : isProductTab ? editingScope?.raw : void 0;
|
|
8438
8445
|
const onLeftSelect = (item) => {
|
|
8439
8446
|
void runWithGuard(() => {
|
|
8447
|
+
if (isLifecycleRail && typeof item.id === "string" && item.id.startsWith(LIFECYCLE_PREFIX)) {
|
|
8448
|
+
const key = item.id.slice(LIFECYCLE_PREFIX.length);
|
|
8449
|
+
const next = key === "__all" ? null : key;
|
|
8450
|
+
setSelectedLifecycleKey(next);
|
|
8451
|
+
if (next && onGroupExpanded) onGroupExpanded(next);
|
|
8452
|
+
return;
|
|
8453
|
+
}
|
|
8440
8454
|
if (isProductTab) {
|
|
8441
8455
|
setSelectedProductId(item.scope.productId);
|
|
8442
8456
|
setSelectedVariantId(void 0);
|
|
@@ -8794,7 +8808,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8794
8808
|
// navigational anchor, not a real record — applying the
|
|
8795
8809
|
// host's groupBy bucketed it under "Other" (its
|
|
8796
8810
|
// data is null). Skip grouping for that single-row rail.
|
|
8797
|
-
(isGlobalTab || isAllTab) && isCollection ? void 0 : effectiveGroupBy
|
|
8811
|
+
(isGlobalTab || isAllTab) && isCollection || isLifecycleRail ? void 0 : effectiveGroupBy
|
|
8798
8812
|
),
|
|
8799
8813
|
renderGroupActions: renderRuleGroupActions,
|
|
8800
8814
|
rowClipboard,
|
|
@@ -8883,7 +8897,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8883
8897
|
ruleWizardStep === null && isCollection && editingScope && !selectedItemId && /* @__PURE__ */ jsx(
|
|
8884
8898
|
ItemListView,
|
|
8885
8899
|
{
|
|
8886
|
-
items:
|
|
8900
|
+
items: filteredCollectionItems,
|
|
8887
8901
|
isLoading: collectionItems.isLoading,
|
|
8888
8902
|
error: collectionItems.error,
|
|
8889
8903
|
ctx: itemViewCtx,
|