npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

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.md and records-admin-pattern.md

Installation

npm install @proveanything/smartlinks-utils-ui

Peer 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' | null

Asset 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 mode

License

MIT