@proveanything/smartlinks-utils-ui
v1.13.14
Published
Reusable React components for SmartLinks microapps — Asset Picker, Conditions Editor, Icon Picker, and more.
Downloads
14,476
Maintainers
Readme
@proveanything/smartlinks-utils-ui
Reusable React components for SmartLinks microapps —
the headline module is RecordsAdminShell, a complete admin UI for the
app.records pattern (global / rule-targeted / per-product data with
automatic variant & batch drill-down where the collection supports them).
Also ships an Asset Picker, Icon Picker, Font Picker, and Conditions Editor.
- Package:
@proveanything/smartlinks-utils-ui - Tracks:
@proveanything/smartlinks ≥ 1.9 - Per-component reference docs:
docs/— props, slots, behaviour, examples - Conceptual SDK docs:
ui-utils.mdandrecords-admin-pattern.md
Installation
npm install @proveanything/smartlinks-utils-uiPeer dependencies
npm install react react-dom @proveanything/smartlinks @tanstack/react-query@tanstack/react-query is required by RecordsAdminShell (caching, pagination,
optimistic save). Wrap your app in a <QueryClientProvider> somewhere up the
tree.
Setup
Import the pre-compiled styles once in your app entry (e.g. main.tsx):
import '@proveanything/smartlinks-utils-ui/styles.css';Components inherit your shadcn-compatible CSS variables (--primary,
--background, --border, …) and pick up your theme automatically.
Modules
| Subpath | Module | Use when |
|---------|--------|----------|
| /records-admin | RecordsAdminShell + hooks (useResolvedRecord, useRecordEditor, …) | Building any global / rule-targeted / per-product admin (variant & batch drill-down is automatic) |
| /asset-picker | AssetPicker | Pick / upload / paste / URL-import media assets |
| /icon-picker | IconPicker | Searchable Font Awesome 7 Pro picker |
| /font-picker | FontPicker | Google Fonts + custom uploaded fonts |
| /conditions-editor | ConditionsEditor | Recursive AND/OR rule builder (12 condition types) |
Each module has a full reference doc under docs/:
Records Admin Shell
⚠️ Before you mount the shell, decide cardinality. If your app is a list of things (auction items, FAQs, image gallery, perks) you want
items.cardinality: 'list'. If it's one winning record per scope (warranty, nutrition, care instructions) keep the default'singleton'. The default is'singleton', so multi-item apps must opt in — see Choosing cardinality. ('collection'is still accepted as a deprecated alias for'list'.)
import {
RecordsAdminShell,
type EditorContext,
} from '@proveanything/smartlinks-utils-ui/records-admin';
import * as SL from '@proveanything/smartlinks';
<RecordsAdminShell<NutritionData>
SL={SL}
collectionId={collectionId}
appId={appId}
recordType="nutrition"
label="Nutrition info"
scopes={['collection', 'rule', 'product']}
contextScope={{ productId, variantId, batchId }} // optional, from iframe URL
defaultData={() => ({})}
renderEditor={(ctx) => <NutritionForm ctx={ctx} />}
renderPreview={({ resolved }) => <pre>{JSON.stringify(resolved, null, 2)}</pre>}
/>The shell renders the browser pane (scope tabs, search, status pills), the editor pane (sticky save / discard / delete footer with optimistic save), and the inheritance markers — you only provide the form for one record.
On the public widget side, read the resolved value with useResolvedRecord:
import { useResolvedRecord } from '@proveanything/smartlinks-utils-ui/records-admin';
const { data, source, isLoading } = useResolvedRecord({
SL, appId, recordType: 'nutrition',
collectionId, productId, variantId, batchId,
});
// source: 'proof' | 'batch' | 'variant' | 'product' | 'rule' | 'collection' | nullAsset Picker
import { AssetPicker } from '@proveanything/smartlinks-utils-ui/asset-picker';
<AssetPicker
scope={{ type: 'collection', collectionId: 'abc123' }}
mode="dialog"
allowUpload
accept={['image/*']}
onSelect={(asset) => setHeroUrl(asset.url)}
trigger={<button>Choose image</button>}
/>Conditions Editor
import { ConditionsEditor } from '@proveanything/smartlinks-utils-ui/conditions-editor';
<ConditionsEditor
value={rules}
onChange={setRules}
collectionId={collectionId} // auto-loads facet definitions
versions={[{ title: 'Default', value: '' }]}
tags={['featured', 'new']}
/>Icon Picker
import { IconPicker } from '@proveanything/smartlinks-utils-ui/icon-picker';
<IconPicker
mode="dialog"
value="fa-solid fa-heart"
onSelect={(icon) => setIcon(icon.name)}
trigger={<button>Pick icon</button>}
/>Requires the Font Awesome 7 Pro kit script on the host page.
Font Picker
import { FontPicker } from '@proveanything/smartlinks-utils-ui/font-picker';
<FontPicker
mode="dialog"
value="Inter"
showPreview
onSelect={(font) => {
console.log(font.cssFontFamily); // ready for `font-family:` CSS
console.log(font.loadSnippet); // <link> or @font-face block to inject
}}
/>Prerequisites
All components assume @proveanything/smartlinks is initialised in your app
via SL.initializeApi(). Admin components (RecordsAdminShell, AssetPicker
upload, etc.) call the SDK with admin: true — do not render them in
public-facing views.
Tree shaking
Each component has its own subpath export — bundle only what you use:
// Bundles only RecordsAdmin
import { RecordsAdminShell } from '@proveanything/smartlinks-utils-ui/records-admin';
// Barrel import — bundler tree-shakes the rest
import { RecordsAdminShell } from '@proveanything/smartlinks-utils-ui';If you use subpath imports, import styles.css separately — subpaths do not
pull it in automatically.
Development
cd packages/smartlinks-ui
npm install
npm run build # tsup
npm run dev # watch modeLicense
MIT
