@proveanything/smartlinks-utils-ui 1.13.8 → 1.13.13
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 +6 -6
- package/dist/ErrorBoundary-J9iKgF_H.d.ts +40 -0
- package/dist/{chunk-OTJV62XV.js → chunk-5ZQT2GGU.js} +5 -5
- package/dist/chunk-5ZQT2GGU.js.map +1 -0
- package/dist/{chunk-4LHF5JB7.js → chunk-DH5HG5DW.js} +15 -6
- package/dist/chunk-DH5HG5DW.js.map +1 -0
- package/dist/{chunk-E3GQ6LNZ.js → chunk-I3T36FSI.js} +528 -49
- package/dist/chunk-I3T36FSI.js.map +1 -0
- package/dist/{chunk-7UBXTFZQ.js → chunk-JNCRSL2H.js} +13 -12
- package/dist/chunk-JNCRSL2H.js.map +1 -0
- package/dist/{chunk-JMCV6FOW.js → chunk-WVCNIX7N.js} +3 -3
- package/dist/{chunk-JMCV6FOW.js.map → chunk-WVCNIX7N.js.map} +1 -1
- package/dist/{chunk-3RRHM4LP.js → chunk-XASZS7EA.js} +131 -4
- package/dist/chunk-XASZS7EA.js.map +1 -0
- package/dist/components/AssetPicker/index.css +34 -0
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/AssetPicker/index.js +1 -1
- package/dist/components/ConditionsEditor/index.css +34 -0
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.d.ts +2 -2
- package/dist/components/ConditionsEditor/index.js +2 -2
- package/dist/components/FacetRuleEditor/index.d.ts +1 -1
- package/dist/components/FacetRuleEditor/index.js +2 -2
- package/dist/components/FontPicker/index.css +34 -0
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/FontPicker/index.js +1 -1
- package/dist/components/IconPicker/index.css +34 -0
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/LinkPicker/index.css +34 -0
- package/dist/components/LinkPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +34 -0
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +1 -0
- package/dist/components/RecordsAdmin/index.js +15 -11
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +34 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/{types-a2DdgZ2H.d.ts → types-BLqki3Zy.d.ts} +11 -0
- package/package.json +3 -3
- package/dist/chunk-3RRHM4LP.js.map +0 -1
- package/dist/chunk-4LHF5JB7.js.map +0 -1
- package/dist/chunk-7UBXTFZQ.js.map +0 -1
- package/dist/chunk-E3GQ6LNZ.js.map +0 -1
- package/dist/chunk-OTJV62XV.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useId, useState, useRef, useEffect, useCallback } from 'react';
|
|
1
|
+
import { useId, useState, useRef, useEffect, useCallback, Component } from 'react';
|
|
2
2
|
import { BookOpen, HelpCircle, AlertTriangle, CheckCircle2, Lightbulb, Info, X } from 'lucide-react';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -179,7 +179,134 @@ function useIntroState({ SL, persistKey }) {
|
|
|
179
179
|
const dismissed = !showHints || browserDismissed;
|
|
180
180
|
return { dismissed, onDismiss, onReopen, isLoading };
|
|
181
181
|
}
|
|
182
|
+
var ErrorBoundary = class extends Component {
|
|
183
|
+
constructor() {
|
|
184
|
+
super(...arguments);
|
|
185
|
+
this.state = { error: null };
|
|
186
|
+
this.reset = () => {
|
|
187
|
+
this.setState({ error: null });
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
static getDerivedStateFromError(error) {
|
|
191
|
+
return { error };
|
|
192
|
+
}
|
|
193
|
+
componentDidCatch(error, info) {
|
|
194
|
+
console.error(
|
|
195
|
+
`[smartlinks-ui] ErrorBoundary${this.props.label ? ` (${this.props.label})` : ""} caught:`,
|
|
196
|
+
error,
|
|
197
|
+
info?.componentStack
|
|
198
|
+
);
|
|
199
|
+
this.props.onError?.(error, info);
|
|
200
|
+
}
|
|
201
|
+
componentDidUpdate(prev) {
|
|
202
|
+
if (!this.state.error) return;
|
|
203
|
+
const cur = this.props.resetKeys;
|
|
204
|
+
const old = prev.resetKeys;
|
|
205
|
+
if (!cur || !old) return;
|
|
206
|
+
if (cur.length !== old.length) {
|
|
207
|
+
this.reset();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
for (let i = 0; i < cur.length; i++) {
|
|
211
|
+
if (!Object.is(cur[i], old[i])) {
|
|
212
|
+
this.reset();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
render() {
|
|
218
|
+
const { error } = this.state;
|
|
219
|
+
if (!error) return this.props.children;
|
|
220
|
+
const { fallback, label } = this.props;
|
|
221
|
+
if (typeof fallback === "function") {
|
|
222
|
+
return fallback({ error, reset: this.reset });
|
|
223
|
+
}
|
|
224
|
+
if (fallback !== void 0) return fallback;
|
|
225
|
+
return /* @__PURE__ */ jsx(DefaultFallback, { error, reset: this.reset, label });
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
var DefaultFallback = ({ error, reset, label }) => {
|
|
229
|
+
const what = label ? `This ${label}` : "This view";
|
|
230
|
+
return /* @__PURE__ */ jsxs(
|
|
231
|
+
"div",
|
|
232
|
+
{
|
|
233
|
+
role: "alert",
|
|
234
|
+
className: "ra-empty",
|
|
235
|
+
style: {
|
|
236
|
+
margin: 12,
|
|
237
|
+
padding: 16,
|
|
238
|
+
border: "1px solid hsl(var(--ra-border, 0 0% 90%))",
|
|
239
|
+
borderRadius: 8,
|
|
240
|
+
background: "hsl(var(--ra-surface, 0 0% 100%))",
|
|
241
|
+
color: "hsl(var(--ra-text, 0 0% 10%))",
|
|
242
|
+
display: "flex",
|
|
243
|
+
flexDirection: "column",
|
|
244
|
+
alignItems: "center",
|
|
245
|
+
gap: 8,
|
|
246
|
+
textAlign: "center"
|
|
247
|
+
},
|
|
248
|
+
children: [
|
|
249
|
+
/* @__PURE__ */ jsx(
|
|
250
|
+
"div",
|
|
251
|
+
{
|
|
252
|
+
className: "ra-empty-icon",
|
|
253
|
+
style: {
|
|
254
|
+
width: 36,
|
|
255
|
+
height: 36,
|
|
256
|
+
borderRadius: 9999,
|
|
257
|
+
background: "hsl(var(--ra-danger, 0 70% 50%) / 0.10)",
|
|
258
|
+
color: "hsl(var(--ra-danger, 0 70% 50%))",
|
|
259
|
+
display: "inline-flex",
|
|
260
|
+
alignItems: "center",
|
|
261
|
+
justifyContent: "center",
|
|
262
|
+
fontWeight: 700,
|
|
263
|
+
fontSize: 18
|
|
264
|
+
},
|
|
265
|
+
"aria-hidden": "true",
|
|
266
|
+
children: "!"
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
/* @__PURE__ */ jsxs("h3", { className: "ra-empty-title", style: { margin: 0, fontSize: 14, fontWeight: 600 }, children: [
|
|
270
|
+
what,
|
|
271
|
+
" couldn't be rendered"
|
|
272
|
+
] }),
|
|
273
|
+
/* @__PURE__ */ jsx(
|
|
274
|
+
"p",
|
|
275
|
+
{
|
|
276
|
+
className: "ra-empty-body",
|
|
277
|
+
style: {
|
|
278
|
+
margin: 0,
|
|
279
|
+
fontSize: 12,
|
|
280
|
+
color: "hsl(var(--ra-muted-text, 0 0% 40%))",
|
|
281
|
+
maxWidth: 520,
|
|
282
|
+
wordBreak: "break-word"
|
|
283
|
+
},
|
|
284
|
+
children: error?.message || "An unexpected error occurred while rendering this view."
|
|
285
|
+
}
|
|
286
|
+
),
|
|
287
|
+
/* @__PURE__ */ jsx(
|
|
288
|
+
"button",
|
|
289
|
+
{
|
|
290
|
+
type: "button",
|
|
291
|
+
onClick: reset,
|
|
292
|
+
className: "ra-btn",
|
|
293
|
+
style: {
|
|
294
|
+
marginTop: 4,
|
|
295
|
+
padding: "4px 10px",
|
|
296
|
+
fontSize: 12,
|
|
297
|
+
borderRadius: 6,
|
|
298
|
+
border: "1px solid hsl(var(--ra-border, 0 0% 80%))",
|
|
299
|
+
background: "hsl(var(--ra-surface, 0 0% 100%))",
|
|
300
|
+
cursor: "pointer"
|
|
301
|
+
},
|
|
302
|
+
children: "Try again"
|
|
303
|
+
}
|
|
304
|
+
)
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
};
|
|
182
309
|
|
|
183
|
-
export { AdminPageHeader, HINTS_PREFS_APP_ID, HINTS_PREFS_KEY, useHintsPreference, useIntroState };
|
|
184
|
-
//# sourceMappingURL=chunk-
|
|
185
|
-
//# sourceMappingURL=chunk-
|
|
310
|
+
export { AdminPageHeader, ErrorBoundary, HINTS_PREFS_APP_ID, HINTS_PREFS_KEY, useHintsPreference, useIntroState };
|
|
311
|
+
//# sourceMappingURL=chunk-XASZS7EA.js.map
|
|
312
|
+
//# sourceMappingURL=chunk-XASZS7EA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AdminPageHeader/AdminPageHeader.tsx","../src/hints/useHintsPreference.ts","../src/hints/useIntroState.ts","../src/utils/ErrorBoundary.tsx"],"names":["useState","useEffect","useCallback","jsx","jsxs"],"mappings":"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","file":"chunk-XASZS7EA.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}","// =============================================================================\r\n// useHintsPreference\r\n//\r\n// Single source of truth for the user-level \"show inline hints?\" preference.\r\n// Reads from `SL.auth.getAccount().prefs` (the canonical account-level prefs\r\n// bag added in SmartLinks SDK 1.11.5+) so the same flag follows the user\r\n// across every SmartLinks admin app — flip it once, applies everywhere.\r\n// There is intentionally no per-app preference list; that's what\r\n// `useIntroState` (browser-level dismiss) is for.\r\n//\r\n// Writes still flow through `SL.userAppData('prefs')` because the SDK does\r\n// not yet expose a dedicated `auth.setPrefs(...)`. The server treats the\r\n// `prefs` userAppData document as the backing store for `account.prefs`,\r\n// so reads and writes stay in sync.\r\n//\r\n// Shape on `account.prefs`:\r\n// { showHints?: boolean, ...other future flags }\r\n//\r\n// Default when unset / unauthenticated / SDK missing → `true` (show hints).\r\n// =============================================================================\r\nimport { useCallback, useEffect, useRef, useState } from 'react';\r\n\r\nexport const HINTS_PREFS_APP_ID = 'prefs';\r\nexport const HINTS_PREFS_KEY = 'showHints';\r\n\r\n/** Optional cross-tab cache so multiple components share one fetch per session. */\r\nlet cachedShowHints: boolean | undefined;\r\nlet inflight: Promise<boolean> | null = null;\r\n\r\nasync function readShowHints(SL: any): Promise<boolean> {\r\n if (cachedShowHints !== undefined) return cachedShowHints;\r\n if (inflight) return inflight;\r\n inflight = (async () => {\r\n try {\r\n // Read from the authenticated account's prefs bag. `prefs` may be\r\n // absent (server returned no document) — that's fine, we fall back\r\n // to the default below.\r\n const account = await SL?.auth?.getAccount?.();\r\n const value = account?.prefs?.[HINTS_PREFS_KEY];\r\n const resolved = typeof value === 'boolean' ? value : true;\r\n cachedShowHints = resolved;\r\n return resolved;\r\n } catch {\r\n cachedShowHints = true;\r\n return true;\r\n } finally {\r\n inflight = null;\r\n }\r\n })();\r\n return inflight;\r\n}\r\n\r\nasync function writeShowHints(SL: any, next: boolean): Promise<void> {\r\n cachedShowHints = next;\r\n try {\r\n // No dedicated `auth.setPrefs` setter exists yet — write through\r\n // userAppData('prefs'), which the server uses as the backing store\r\n // for `account.prefs`.\r\n const cfg = await SL?.userAppData?.getConfig?.(HINTS_PREFS_APP_ID).catch(() => ({}));\r\n await SL?.userAppData?.setConfig?.(HINTS_PREFS_APP_ID, {\r\n ...(cfg ?? {}),\r\n [HINTS_PREFS_KEY]: next,\r\n });\r\n } catch { /* best-effort */ }\r\n}\r\n\r\nexport interface UseHintsPreferenceResult {\r\n /** Whether inline hints / intro cards should be shown by default. */\r\n showHints: boolean;\r\n /** True until the first read from `userAppData` resolves. */\r\n isLoading: boolean;\r\n /** Persist a new value on the user record. */\r\n setShowHints: (next: boolean) => Promise<void>;\r\n}\r\n\r\n/**\r\n * Subscribe to the user's global `showHints` preference. Optimistic; defaults\r\n * to `true` while loading so admins coming in fresh always see the help.\r\n */\r\nexport function useHintsPreference(SL: any): UseHintsPreferenceResult {\r\n // NB: do NOT lazy-init from a module-level cache — Vite HMR reloads this\r\n // module while React keeps the old hook queue, which trips\r\n // \"Should have a queue. This is likely a bug in React.\". Always init to\r\n // the same shape and rely on the effect below to hydrate.\r\n const [showHints, setShowHintsState] = useState<boolean>(true);\r\n const [isLoading, setIsLoading] = useState<boolean>(true);\r\n const mounted = useRef(true);\r\n\r\n useEffect(() => {\r\n mounted.current = true;\r\n if (cachedShowHints !== undefined) {\r\n setShowHintsState(cachedShowHints);\r\n setIsLoading(false);\r\n return () => { mounted.current = false; };\r\n }\r\n readShowHints(SL).then((value) => {\r\n if (!mounted.current) return;\r\n setShowHintsState(value);\r\n setIsLoading(false);\r\n });\r\n return () => { mounted.current = false; };\r\n }, [SL]);\r\n\r\n const setShowHints = useCallback(async (next: boolean) => {\r\n setShowHintsState(next);\r\n await writeShowHints(SL, next);\r\n }, [SL]);\r\n\r\n return { showHints, isLoading, setShowHints };\r\n}\r\n\r\n/** Test / sign-out helper — drop the in-memory cache. */\r\nexport function __resetHintsPreferenceCache() {\r\n cachedShowHints = undefined;\r\n inflight = null;\r\n}\r\n","// =============================================================================\r\n// useIntroState\r\n//\r\n// One hook that resolves the full intro-card state for an `<AdminPageHeader>`:\r\n//\r\n// 1. Global user preference (`prefs.showHints` on `userAppData`)\r\n// → if `false`, the intro stays collapsed by default. The `?` reopen\r\n// button is still rendered so the user can pop it open whenever.\r\n// 2. Per-browser, per-app temporary dismiss (`localStorage`)\r\n// → flipped by the dismiss `X`, so reloads on this browser keep it\r\n// collapsed until they click `?`.\r\n//\r\n// Apps just call:\r\n// const intro = useIntroState({ SL, persistKey: appId });\r\n// <AdminPageHeader intro={{ title, body, ...intro }} />\r\n// =============================================================================\r\nimport { useCallback, useEffect, useState } from 'react';\r\nimport { useHintsPreference } from './useHintsPreference';\r\n\r\nconst lsKey = (persistKey: string) => `sl:intro-dismissed:${persistKey}`;\r\n\r\nexport interface UseIntroStateArgs {\r\n /** SmartLinks SDK namespace (`* as SL from '@proveanything/smartlinks'`). */\r\n SL: any;\r\n /**\r\n * Stable per-app key used for the browser-level dismiss. Usually the\r\n * app's `appId`. Pass a more specific value (e.g. `${appId}:rules`) if\r\n * you have multiple intros within one app.\r\n */\r\n persistKey: string;\r\n}\r\n\r\nexport interface UseIntroStateResult {\r\n /** Whether the intro card is currently dismissed/collapsed. */\r\n dismissed: boolean;\r\n /** Wire to AdminPageHeader's `intro.onDismiss`. */\r\n onDismiss: () => void;\r\n /** Wire to AdminPageHeader's `intro.onReopen`. Always available. */\r\n onReopen: () => void;\r\n /** True until the user preference has finished loading. */\r\n isLoading: boolean;\r\n}\r\n\r\nfunction readBrowserDismissed(persistKey: string): boolean {\r\n try { return localStorage.getItem(lsKey(persistKey)) === '1'; }\r\n catch { return false; }\r\n}\r\n\r\n/** Resolve dismiss state from global pref + per-browser flag. */\r\nexport function useIntroState({ SL, persistKey }: UseIntroStateArgs): UseIntroStateResult {\r\n const { showHints, isLoading } = useHintsPreference(SL);\r\n const [browserDismissed, setBrowserDismissed] = useState<boolean>(() => readBrowserDismissed(persistKey));\r\n\r\n // Re-read browser flag if the key changes (rare, but cheap).\r\n useEffect(() => {\r\n setBrowserDismissed(readBrowserDismissed(persistKey));\r\n }, [persistKey]);\r\n\r\n const onDismiss = useCallback(() => {\r\n setBrowserDismissed(true);\r\n try { localStorage.setItem(lsKey(persistKey), '1'); } catch { /* ignore */ }\r\n }, [persistKey]);\r\n\r\n const onReopen = useCallback(() => {\r\n setBrowserDismissed(false);\r\n try { localStorage.removeItem(lsKey(persistKey)); } catch { /* ignore */ }\r\n }, [persistKey]);\r\n\r\n // Dismissed when either: user opted out of hints globally, or they X'd it\r\n // on this browser. Reopening always works (it just clears the browser flag\r\n // for this session — global pref stays as-is).\r\n const dismissed = !showHints || browserDismissed;\r\n\r\n return { dismissed, onDismiss, onReopen, isLoading };\r\n}\r\n","// =============================================================================\r\n// ErrorBoundary — generic render-time crash guard.\r\n//\r\n// Purpose\r\n// -------\r\n// Host apps wired into the records-admin shell render arbitrary editor,\r\n// card, row, and preview content. A bad record, a missing field, or a\r\n// thrown exception in any of those host-supplied renderers used to take\r\n// down the entire admin app with a white screen. This boundary contains\r\n// the blast radius to the affected slot and shows a friendly \"couldn't\r\n// render\" panel with a Retry button.\r\n//\r\n// Notes\r\n// -----\r\n// * Implemented as a class (the only API React exposes for error\r\n// boundaries). Functional components cannot replace this.\r\n// * `resetKeys` mirrors react-error-boundary's API — when any key in the\r\n// array changes between renders, the boundary clears its error and\r\n// re-renders children. Use it to auto-recover when the user navigates\r\n// to a different record.\r\n// * `fallback` may be a React node or a render function receiving the\r\n// error + a `reset` callback. Defaults to a small themed card that\r\n// matches the records-admin `.ra-empty` aesthetic but degrades\r\n// gracefully when those tokens aren't loaded.\r\n// =============================================================================\r\nimport { Component, type ErrorInfo, type ReactNode } from 'react';\r\n\r\nexport interface ErrorBoundaryProps {\r\n children: ReactNode;\r\n /**\r\n * Optional label used in the default fallback message — e.g.\r\n * `label=\"editor\"` renders \"This editor couldn't be rendered.\"\r\n */\r\n label?: string;\r\n /**\r\n * Custom fallback. Either a node or a render function. When using the\r\n * function form, call `reset()` to clear the error and remount children.\r\n */\r\n fallback?: ReactNode | ((info: { error: Error; reset: () => void }) => ReactNode);\r\n /**\r\n * Fires when the boundary catches. Use to forward to telemetry.\r\n */\r\n onError?: (error: Error, info: ErrorInfo) => void;\r\n /**\r\n * When any value in this array changes (shallow compare), the boundary\r\n * clears its error state. Use to auto-recover on navigation.\r\n */\r\n resetKeys?: ReadonlyArray<unknown>;\r\n}\r\n\r\ninterface State {\r\n error: Error | null;\r\n}\r\n\r\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, State> {\r\n state: State = { error: null };\r\n\r\n static getDerivedStateFromError(error: Error): State {\r\n return { error };\r\n }\r\n\r\n componentDidCatch(error: Error, info: ErrorInfo): void {\r\n // Always log — silent failures in admin tooling are worse than noisy\r\n // ones. Hosts can mute via `onError` if they want.\r\n // eslint-disable-next-line no-console\r\n console.error(\r\n `[smartlinks-ui] ErrorBoundary${this.props.label ? ` (${this.props.label})` : ''} caught:`,\r\n error,\r\n info?.componentStack,\r\n );\r\n this.props.onError?.(error, info);\r\n }\r\n\r\n componentDidUpdate(prev: ErrorBoundaryProps): void {\r\n if (!this.state.error) return;\r\n const cur = this.props.resetKeys;\r\n const old = prev.resetKeys;\r\n if (!cur || !old) return;\r\n if (cur.length !== old.length) {\r\n this.reset();\r\n return;\r\n }\r\n for (let i = 0; i < cur.length; i++) {\r\n if (!Object.is(cur[i], old[i])) {\r\n this.reset();\r\n return;\r\n }\r\n }\r\n }\r\n\r\n reset = (): void => {\r\n this.setState({ error: null });\r\n };\r\n\r\n render(): ReactNode {\r\n const { error } = this.state;\r\n if (!error) return this.props.children;\r\n const { fallback, label } = this.props;\r\n if (typeof fallback === 'function') {\r\n return fallback({ error, reset: this.reset });\r\n }\r\n if (fallback !== undefined) return fallback;\r\n return <DefaultFallback error={error} reset={this.reset} label={label} />;\r\n }\r\n}\r\n\r\ninterface DefaultFallbackProps {\r\n error: Error;\r\n reset: () => void;\r\n label?: string;\r\n}\r\n\r\nconst DefaultFallback = ({ error, reset, label }: DefaultFallbackProps) => {\r\n const what = label ? `This ${label}` : 'This view';\r\n return (\r\n <div\r\n role=\"alert\"\r\n className=\"ra-empty\"\r\n style={{\r\n margin: 12,\r\n padding: 16,\r\n border: '1px solid hsl(var(--ra-border, 0 0% 90%))',\r\n borderRadius: 8,\r\n background: 'hsl(var(--ra-surface, 0 0% 100%))',\r\n color: 'hsl(var(--ra-text, 0 0% 10%))',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n gap: 8,\r\n textAlign: 'center',\r\n }}\r\n >\r\n <div\r\n className=\"ra-empty-icon\"\r\n style={{\r\n width: 36, height: 36, borderRadius: 9999,\r\n background: 'hsl(var(--ra-danger, 0 70% 50%) / 0.10)',\r\n color: 'hsl(var(--ra-danger, 0 70% 50%))',\r\n display: 'inline-flex', alignItems: 'center', justifyContent: 'center',\r\n fontWeight: 700, fontSize: 18,\r\n }}\r\n aria-hidden=\"true\"\r\n >\r\n !\r\n </div>\r\n <h3 className=\"ra-empty-title\" style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>\r\n {what} couldn't be rendered\r\n </h3>\r\n <p\r\n className=\"ra-empty-body\"\r\n style={{\r\n margin: 0,\r\n fontSize: 12,\r\n color: 'hsl(var(--ra-muted-text, 0 0% 40%))',\r\n maxWidth: 520,\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {error?.message || 'An unexpected error occurred while rendering this view.'}\r\n </p>\r\n <button\r\n type=\"button\"\r\n onClick={reset}\r\n className=\"ra-btn\"\r\n style={{\r\n marginTop: 4,\r\n padding: '4px 10px',\r\n fontSize: 12,\r\n borderRadius: 6,\r\n border: '1px solid hsl(var(--ra-border, 0 0% 80%))',\r\n background: 'hsl(var(--ra-surface, 0 0% 100%))',\r\n cursor: 'pointer',\r\n }}\r\n >\r\n Try again\r\n </button>\r\n </div>\r\n );\r\n};"]}
|
|
@@ -2539,6 +2539,9 @@
|
|
|
2539
2539
|
.static {
|
|
2540
2540
|
position: static;
|
|
2541
2541
|
}
|
|
2542
|
+
.\!fixed {
|
|
2543
|
+
position: fixed !important;
|
|
2544
|
+
}
|
|
2542
2545
|
.fixed {
|
|
2543
2546
|
position: fixed;
|
|
2544
2547
|
}
|
|
@@ -2791,6 +2794,9 @@
|
|
|
2791
2794
|
.h-24 {
|
|
2792
2795
|
height: 6rem;
|
|
2793
2796
|
}
|
|
2797
|
+
.h-28 {
|
|
2798
|
+
height: 7rem;
|
|
2799
|
+
}
|
|
2794
2800
|
.h-3 {
|
|
2795
2801
|
height: 0.75rem;
|
|
2796
2802
|
}
|
|
@@ -2869,6 +2875,9 @@
|
|
|
2869
2875
|
.w-24 {
|
|
2870
2876
|
width: 6rem;
|
|
2871
2877
|
}
|
|
2878
|
+
.w-28 {
|
|
2879
|
+
width: 7rem;
|
|
2880
|
+
}
|
|
2872
2881
|
.w-3 {
|
|
2873
2882
|
width: 0.75rem;
|
|
2874
2883
|
}
|
|
@@ -3068,6 +3077,9 @@
|
|
|
3068
3077
|
.items-center {
|
|
3069
3078
|
align-items: center;
|
|
3070
3079
|
}
|
|
3080
|
+
.items-baseline {
|
|
3081
|
+
align-items: baseline;
|
|
3082
|
+
}
|
|
3071
3083
|
.justify-end {
|
|
3072
3084
|
justify-content: flex-end;
|
|
3073
3085
|
}
|
|
@@ -3135,6 +3147,9 @@
|
|
|
3135
3147
|
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
|
3136
3148
|
border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
|
|
3137
3149
|
}
|
|
3150
|
+
.divide-border > :not([hidden]) ~ :not([hidden]) {
|
|
3151
|
+
border-color: hsl(var(--border));
|
|
3152
|
+
}
|
|
3138
3153
|
.self-start {
|
|
3139
3154
|
align-self: flex-start;
|
|
3140
3155
|
}
|
|
@@ -3200,6 +3215,9 @@
|
|
|
3200
3215
|
.border-dashed {
|
|
3201
3216
|
border-style: dashed;
|
|
3202
3217
|
}
|
|
3218
|
+
.border-amber-500\/40 {
|
|
3219
|
+
border-color: rgb(245 158 11 / 0.4);
|
|
3220
|
+
}
|
|
3203
3221
|
.border-background {
|
|
3204
3222
|
border-color: hsl(var(--background));
|
|
3205
3223
|
}
|
|
@@ -3216,6 +3234,9 @@
|
|
|
3216
3234
|
.border-destructive {
|
|
3217
3235
|
border-color: hsl(var(--destructive));
|
|
3218
3236
|
}
|
|
3237
|
+
.border-destructive\/40 {
|
|
3238
|
+
border-color: hsl(var(--destructive) / 0.4);
|
|
3239
|
+
}
|
|
3219
3240
|
.border-destructive\/50 {
|
|
3220
3241
|
border-color: hsl(var(--destructive) / 0.5);
|
|
3221
3242
|
}
|
|
@@ -3253,6 +3274,9 @@
|
|
|
3253
3274
|
--tw-bg-opacity: 1;
|
|
3254
3275
|
background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));
|
|
3255
3276
|
}
|
|
3277
|
+
.bg-amber-500\/10 {
|
|
3278
|
+
background-color: rgb(245 158 11 / 0.1);
|
|
3279
|
+
}
|
|
3256
3280
|
.bg-background {
|
|
3257
3281
|
background-color: hsl(var(--background));
|
|
3258
3282
|
}
|
|
@@ -3524,6 +3548,9 @@
|
|
|
3524
3548
|
.text-center {
|
|
3525
3549
|
text-align: center;
|
|
3526
3550
|
}
|
|
3551
|
+
.text-right {
|
|
3552
|
+
text-align: right;
|
|
3553
|
+
}
|
|
3527
3554
|
.font-mono {
|
|
3528
3555
|
font-family:
|
|
3529
3556
|
ui-monospace,
|
|
@@ -3971,6 +3998,9 @@
|
|
|
3971
3998
|
.hover\:underline:hover {
|
|
3972
3999
|
text-decoration-line: underline;
|
|
3973
4000
|
}
|
|
4001
|
+
.hover\:no-underline:hover {
|
|
4002
|
+
text-decoration-line: none;
|
|
4003
|
+
}
|
|
3974
4004
|
.hover\:opacity-100:hover {
|
|
3975
4005
|
opacity: 1;
|
|
3976
4006
|
}
|
|
@@ -4146,6 +4176,10 @@
|
|
|
4146
4176
|
--tw-text-opacity: 1;
|
|
4147
4177
|
color: rgb(110 231 183 / var(--tw-text-opacity, 1));
|
|
4148
4178
|
}
|
|
4179
|
+
.dark\:text-emerald-400 {
|
|
4180
|
+
--tw-text-opacity: 1;
|
|
4181
|
+
color: rgb(52 211 153 / var(--tw-text-opacity, 1));
|
|
4182
|
+
}
|
|
4149
4183
|
.dark\:text-gray-100 {
|
|
4150
4184
|
--tw-text-opacity: 1;
|
|
4151
4185
|
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
|