@proveanything/smartlinks-utils-ui 1.13.11 → 1.13.14

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/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { AppLinkTarget, DeepLinkTarget, DiscoveredApp, ExternalLinkTarget, LinkK
8
8
  export { b as IconPicker, c as IconPickerProps, d as IconSelection } from './IconPicker-nhY3wWlB.js';
9
9
  export { CATEGORY_FALLBACKS, CATEGORY_LABELS, FontCategory, FontEntry, FontPicker, FontPickerProps, FontScope, FontSelection, FontSource, FontWeight, GOOGLE_FONTS_CATALOG, getGoogleFontUrl } from './components/FontPicker/index.js';
10
10
  import { ClassValue } from 'clsx';
11
+ export { E as ErrorBoundary, a as ErrorBoundaryProps } from './ErrorBoundary-J9iKgF_H.js';
11
12
  export { FacetRule, FacetRuleClause } from '@proveanything/smartlinks/dist/types/appObjects';
12
13
 
13
14
  type AdminPageHeaderIntroTone = 'info' | 'success' | 'warning';
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- export { ASSET_MIME_FILTERS, AssetPicker, useAssets } from './chunk-7RWLFKHC.js';
2
- export { ConditionsEditor } from './chunk-A4YZYKWT.js';
1
+ export { ASSET_MIME_FILTERS, AssetPicker, useAssets } from './chunk-I3T36FSI.js';
2
+ export { ConditionsEditor } from './chunk-JNCRSL2H.js';
3
3
  export { IconPicker } from './chunk-JQPS5XPJ.js';
4
4
  export { CATEGORY_FALLBACKS, CATEGORY_LABELS, FontPicker, GOOGLE_FONTS_CATALOG, getGoogleFontUrl } from './chunk-5ZQT2GGU.js';
5
- import { useHintsPreference } from './chunk-3RRHM4LP.js';
6
- export { AdminPageHeader, HINTS_PREFS_APP_ID, HINTS_PREFS_KEY, useHintsPreference, useIntroState } from './chunk-3RRHM4LP.js';
5
+ import { useHintsPreference } from './chunk-XASZS7EA.js';
6
+ export { AdminPageHeader, ErrorBoundary, HINTS_PREFS_APP_ID, HINTS_PREFS_KEY, useHintsPreference, useIntroState } from './chunk-XASZS7EA.js';
7
7
  import './chunk-S27GIYV7.js';
8
8
  export { FacetRuleEditor } from './chunk-WVCNIX7N.js';
9
9
  import './chunk-DH5HG5DW.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hints/HintsPreferenceToggle.tsx","../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAmBO,SAAS,qBAAA,CAAsB;AAAA,EACpC,EAAA;AAAA,EAAI,KAAA,GAAQ,kBAAA;AAAA,EAAoB,WAAA;AAAA,EAAa;AAC/C,CAAA,EAA+B;AAC7B,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,SAAA,EAAU,GAAI,mBAAmB,EAAE,CAAA;AACpE,EAAA,uBACE,IAAA,CAAC,OAAA,EAAA,EAAM,SAAA,EAAsB,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAY,YAAA,EAAc,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,WAAU,EAChH,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,UAAA;AAAA,QACL,OAAA,EAAS,SAAA;AAAA,QACT,QAAA,EAAU,SAAA;AAAA,QACV,QAAA,EAAU,CAAC,CAAA,KAAM;AAAE,UAAA,KAAK,YAAA,CAAa,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA;AAAA,QAAG,CAAA;AAAA,QACxD,KAAA,EAAO,EAAE,SAAA,EAAW,QAAA;AAAS;AAAA,KAC/B;AAAA,yBACC,MAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAK,KAAA,EAAO,EAAE,UAAA,EAAY,GAAA,IAAQ,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MACxC,WAAA,mBACC,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,OAAA,EAAS,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,OAAA,EAAS,GAAA,EAAI,EAAI,uBAAY,CAAA,GAChF;AAAA,KAAA,EACN;AAAA,GAAA,EACF,CAAA;AAEJ;;;ACjCA,kBAAA,EAAmB","file":"index.js","sourcesContent":["// =============================================================================\r\n// HintsPreferenceToggle\r\n//\r\n// Tiny opt-in component that flips the global `prefs.showHints` flag on the\r\n// user record. Drop into any settings/account surface — the value affects\r\n// every SmartLinks admin app the user opens, no per-app wiring required.\r\n// =============================================================================\r\nimport { useHintsPreference } from './useHintsPreference';\r\n\r\nexport interface HintsPreferenceToggleProps {\r\n /** SmartLinks SDK namespace (`* as SL from '@proveanything/smartlinks'`). */\r\n SL: any;\r\n /** Visible label. Default: \"Show inline help\". */\r\n label?: string;\r\n /** Optional helper line under the label. */\r\n description?: string;\r\n className?: string;\r\n}\r\n\r\nexport function HintsPreferenceToggle({\r\n SL, label = 'Show inline help', description, className,\r\n}: HintsPreferenceToggleProps) {\r\n const { showHints, setShowHints, isLoading } = useHintsPreference(SL);\r\n return (\r\n <label className={className} style={{ display: 'flex', alignItems: 'flex-start', gap: '0.5rem', cursor: 'pointer' }}>\r\n <input\r\n type=\"checkbox\"\r\n checked={showHints}\r\n disabled={isLoading}\r\n onChange={(e) => { void setShowHints(e.target.checked); }}\r\n style={{ marginTop: '0.2rem' }}\r\n />\r\n <span>\r\n <span style={{ fontWeight: 500 }}>{label}</span>\r\n {description ? (\r\n <span style={{ display: 'block', fontSize: '0.85em', opacity: 0.7 }}>{description}</span>\r\n ) : null}\r\n </span>\r\n </label>\r\n );\r\n}\r\n","// =============================================================================\r\n// @proveanything/smartlinks-ui\r\n// =============================================================================\r\n\r\n// Pre-compiled Tailwind utilities — tsup processes this through PostCSS\r\nimport './styles.css';\r\nimport { assertStylesLoaded } from './utils/assertStylesLoaded';\r\nassertStylesLoaded();\r\n\r\n// --- Asset Picker ---\r\nexport { AssetPicker, useAssets } from './components/AssetPicker';\r\nexport type {\r\n AssetPickerProps,\r\n AssetPickerMode,\r\n AssetScope,\r\n AssetPickerSelection,\r\n AssetItem,\r\n AssetViewMode,\r\n AssetMimeFilter,\r\n} from './components/AssetPicker/types';\r\nexport { ASSET_MIME_FILTERS } from './components/AssetPicker/types';\r\n\r\n// --- Admin Page Header ---\r\nexport { AdminPageHeader } from './components/AdminPageHeader';\r\nexport type {\r\n AdminPageHeaderProps,\r\n AdminPageHeaderIntro,\r\n AdminPageHeaderIntroTone,\r\n} from './components/AdminPageHeader';\r\n\r\n// --- Hints (global user preference + per-browser dismiss) ---\r\nexport {\r\n useHintsPreference, useIntroState, HintsPreferenceToggle,\r\n HINTS_PREFS_APP_ID, HINTS_PREFS_KEY,\r\n} from './hints';\r\nexport type {\r\n UseHintsPreferenceResult, UseIntroStateArgs, UseIntroStateResult,\r\n HintsPreferenceToggleProps,\r\n} from './hints';\r\n\r\n// --- Conditions Editor ---\r\nexport { ConditionsEditor } from './components/ConditionsEditor';\r\nexport type {\r\n ConditionsEditorProps,\r\n Condition,\r\n ConditionGroup,\r\n ConditionType,\r\n ConditionTypeMeta,\r\n SelectOption,\r\n VersionOption,\r\n} from './components/ConditionsEditor/types';\r\n\r\n// --- Facet Rule Editor (records targeting) ---\r\nexport { FacetRuleEditor } from './components/FacetRuleEditor';\r\nexport type {\r\n FacetRuleEditorProps,\r\n FacetRule,\r\n FacetRuleClause,\r\n} from './components/FacetRuleEditor/types';\r\n\r\n// --- Link Picker (universal link/app/deep-link) ---\r\nexport { LinkPicker, useLinkTargets, resolveLink } from './components/LinkPicker';\r\nexport type {\r\n LinkPickerProps,\r\n LinkTarget,\r\n LinkKind,\r\n LinkOpenTarget,\r\n ExternalLinkTarget,\r\n AppLinkTarget,\r\n DeepLinkTarget,\r\n LinkableEntry,\r\n DiscoveredApp,\r\n UseLinkTargetsOptions,\r\n UseLinkTargetsReturn,\r\n ResolveLinkContext,\r\n ResolvedLink,\r\n} from './components/LinkPicker';\r\n\r\n// --- Icon Picker ---\r\nexport { IconPicker } from './components/IconPicker';\r\nexport type {\r\n IconPickerProps,\r\n IconSelection,\r\n} from './components/IconPicker/types';\r\n\r\n// --- Font Picker ---\r\nexport { FontPicker } from './components/FontPicker';\r\nexport type {\r\n FontPickerProps,\r\n FontSelection,\r\n FontSource,\r\n FontCategory,\r\n FontWeight,\r\n FontEntry,\r\n FontScope,\r\n} from './components/FontPicker/types';\r\nexport { GOOGLE_FONTS_CATALOG, getGoogleFontUrl, CATEGORY_LABELS, CATEGORY_FALLBACKS } from './components/FontPicker/google-fonts';\r\n\r\n// --- Shared utilities ---\r\nexport { cn } from './utils/cn';\r\n"]}
1
+ {"version":3,"sources":["../src/hints/HintsPreferenceToggle.tsx","../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAmBO,SAAS,qBAAA,CAAsB;AAAA,EACpC,EAAA;AAAA,EAAI,KAAA,GAAQ,kBAAA;AAAA,EAAoB,WAAA;AAAA,EAAa;AAC/C,CAAA,EAA+B;AAC7B,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,SAAA,EAAU,GAAI,mBAAmB,EAAE,CAAA;AACpE,EAAA,uBACE,IAAA,CAAC,OAAA,EAAA,EAAM,SAAA,EAAsB,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAY,YAAA,EAAc,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,WAAU,EAChH,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,UAAA;AAAA,QACL,OAAA,EAAS,SAAA;AAAA,QACT,QAAA,EAAU,SAAA;AAAA,QACV,QAAA,EAAU,CAAC,CAAA,KAAM;AAAE,UAAA,KAAK,YAAA,CAAa,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA;AAAA,QAAG,CAAA;AAAA,QACxD,KAAA,EAAO,EAAE,SAAA,EAAW,QAAA;AAAS;AAAA,KAC/B;AAAA,yBACC,MAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAK,KAAA,EAAO,EAAE,UAAA,EAAY,GAAA,IAAQ,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MACxC,WAAA,mBACC,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,OAAA,EAAS,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,OAAA,EAAS,GAAA,EAAI,EAAI,uBAAY,CAAA,GAChF;AAAA,KAAA,EACN;AAAA,GAAA,EACF,CAAA;AAEJ;;;ACjCA,kBAAA,EAAmB","file":"index.js","sourcesContent":["// =============================================================================\r\n// HintsPreferenceToggle\r\n//\r\n// Tiny opt-in component that flips the global `prefs.showHints` flag on the\r\n// user record. Drop into any settings/account surface — the value affects\r\n// every SmartLinks admin app the user opens, no per-app wiring required.\r\n// =============================================================================\r\nimport { useHintsPreference } from './useHintsPreference';\r\n\r\nexport interface HintsPreferenceToggleProps {\r\n /** SmartLinks SDK namespace (`* as SL from '@proveanything/smartlinks'`). */\r\n SL: any;\r\n /** Visible label. Default: \"Show inline help\". */\r\n label?: string;\r\n /** Optional helper line under the label. */\r\n description?: string;\r\n className?: string;\r\n}\r\n\r\nexport function HintsPreferenceToggle({\r\n SL, label = 'Show inline help', description, className,\r\n}: HintsPreferenceToggleProps) {\r\n const { showHints, setShowHints, isLoading } = useHintsPreference(SL);\r\n return (\r\n <label className={className} style={{ display: 'flex', alignItems: 'flex-start', gap: '0.5rem', cursor: 'pointer' }}>\r\n <input\r\n type=\"checkbox\"\r\n checked={showHints}\r\n disabled={isLoading}\r\n onChange={(e) => { void setShowHints(e.target.checked); }}\r\n style={{ marginTop: '0.2rem' }}\r\n />\r\n <span>\r\n <span style={{ fontWeight: 500 }}>{label}</span>\r\n {description ? (\r\n <span style={{ display: 'block', fontSize: '0.85em', opacity: 0.7 }}>{description}</span>\r\n ) : null}\r\n </span>\r\n </label>\r\n );\r\n}\r\n","// =============================================================================\r\n// @proveanything/smartlinks-ui\r\n// =============================================================================\r\n\r\n// Pre-compiled Tailwind utilities — tsup processes this through PostCSS\r\nimport './styles.css';\r\nimport { assertStylesLoaded } from './utils/assertStylesLoaded';\r\nassertStylesLoaded();\r\n\r\n// --- Asset Picker ---\r\nexport { AssetPicker, useAssets } from './components/AssetPicker';\r\nexport type {\r\n AssetPickerProps,\r\n AssetPickerMode,\r\n AssetScope,\r\n AssetPickerSelection,\r\n AssetItem,\r\n AssetViewMode,\r\n AssetMimeFilter,\r\n} from './components/AssetPicker/types';\r\nexport { ASSET_MIME_FILTERS } from './components/AssetPicker/types';\r\n\r\n// --- Admin Page Header ---\r\nexport { AdminPageHeader } from './components/AdminPageHeader';\r\nexport type {\r\n AdminPageHeaderProps,\r\n AdminPageHeaderIntro,\r\n AdminPageHeaderIntroTone,\r\n} from './components/AdminPageHeader';\r\n\r\n// --- Hints (global user preference + per-browser dismiss) ---\r\nexport {\r\n useHintsPreference, useIntroState, HintsPreferenceToggle,\r\n HINTS_PREFS_APP_ID, HINTS_PREFS_KEY,\r\n} from './hints';\r\nexport type {\r\n UseHintsPreferenceResult, UseIntroStateArgs, UseIntroStateResult,\r\n HintsPreferenceToggleProps,\r\n} from './hints';\r\n\r\n// --- Conditions Editor ---\r\nexport { ConditionsEditor } from './components/ConditionsEditor';\r\nexport type {\r\n ConditionsEditorProps,\r\n Condition,\r\n ConditionGroup,\r\n ConditionType,\r\n ConditionTypeMeta,\r\n SelectOption,\r\n VersionOption,\r\n} from './components/ConditionsEditor/types';\r\n\r\n// --- Facet Rule Editor (records targeting) ---\r\nexport { FacetRuleEditor } from './components/FacetRuleEditor';\r\nexport type {\r\n FacetRuleEditorProps,\r\n FacetRule,\r\n FacetRuleClause,\r\n} from './components/FacetRuleEditor/types';\r\n\r\n// --- Link Picker (universal link/app/deep-link) ---\r\nexport { LinkPicker, useLinkTargets, resolveLink } from './components/LinkPicker';\r\nexport type {\r\n LinkPickerProps,\r\n LinkTarget,\r\n LinkKind,\r\n LinkOpenTarget,\r\n ExternalLinkTarget,\r\n AppLinkTarget,\r\n DeepLinkTarget,\r\n LinkableEntry,\r\n DiscoveredApp,\r\n UseLinkTargetsOptions,\r\n UseLinkTargetsReturn,\r\n ResolveLinkContext,\r\n ResolvedLink,\r\n} from './components/LinkPicker';\r\n\r\n// --- Icon Picker ---\r\nexport { IconPicker } from './components/IconPicker';\r\nexport type {\r\n IconPickerProps,\r\n IconSelection,\r\n} from './components/IconPicker/types';\r\n\r\n// --- Font Picker ---\r\nexport { FontPicker } from './components/FontPicker';\r\nexport type {\r\n FontPickerProps,\r\n FontSelection,\r\n FontSource,\r\n FontCategory,\r\n FontWeight,\r\n FontEntry,\r\n FontScope,\r\n} from './components/FontPicker/types';\r\nexport { GOOGLE_FONTS_CATALOG, getGoogleFontUrl, CATEGORY_LABELS, CATEGORY_FALLBACKS } from './components/FontPicker/google-fonts';\r\n\r\n// --- Shared utilities ---\r\nexport { cn } from './utils/cn';\r\nexport { ErrorBoundary } from './utils/ErrorBoundary';\r\nexport type { ErrorBoundaryProps } from './utils/ErrorBoundary';\r\n"]}
@@ -0,0 +1,3 @@
1
+ export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, removeRecord, restoreRecord, updateRecord, upsertRecord, upsertRecordForScope } from './chunk-W5ZEH3RT.js';
2
+ //# sourceMappingURL=records-GPSKUNST.js.map
3
+ //# sourceMappingURL=records-GPSKUNST.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"records-4NN757SG.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"records-GPSKUNST.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks-utils-ui",
3
- "version": "1.13.11",
3
+ "version": "1.13.14",
4
4
  "description": "Reusable React components for SmartLinks microapps — Asset Picker, Conditions Editor, Icon Picker, and more.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/AdminPageHeader/AdminPageHeader.tsx","../src/hints/useHintsPreference.ts","../src/hints/useIntroState.ts"],"names":["useState","useEffect","useCallback"],"mappings":"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","file":"chunk-3RRHM4LP.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"]}