@proveanything/smartlinks-utils-ui 0.1.13 → 0.3.0

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 CHANGED
@@ -1,146 +1,182 @@
1
- # @proveanything/smartlinks-ui
1
+ # @proveanything/smartlinks-utils-ui
2
2
 
3
- Reusable React components for [SmartLinks](https://smartlinks.app) microapps.
3
+ Reusable React components for [SmartLinks](https://smartlinks.app) microapps
4
+ the headline module is **RecordsAdminShell**, a complete admin UI for the
5
+ `app.records` pattern (per-product / per-variant / per-batch / per-facet data
6
+ with scope inheritance). Also ships an Asset Picker, Icon Picker, Font Picker,
7
+ and Conditions Editor.
8
+
9
+ - Package: `@proveanything/smartlinks-utils-ui`
10
+ - Tracks: `@proveanything/smartlinks ≥ 1.9`
11
+ - See also: SDK docs [`ui-utils.md`](https://github.com/proveanything/smartlinks-sdk/blob/main/docs/ui-utils.md) and [`records-admin-pattern.md`](https://github.com/proveanything/smartlinks-sdk/blob/main/docs/records-admin-pattern.md)
4
12
 
5
13
  ## Installation
6
14
 
7
15
  ```bash
8
- npm install @proveanything/smartlinks-ui
16
+ npm install @proveanything/smartlinks-utils-ui
9
17
  ```
10
18
 
11
- ### Peer Dependencies
12
-
13
- This package requires the following peer dependencies in your app:
19
+ ### Peer dependencies
14
20
 
15
21
  ```bash
16
- npm install react react-dom @proveanything/smartlinks
22
+ npm install react react-dom @proveanything/smartlinks @tanstack/react-query
17
23
  ```
18
24
 
25
+ `@tanstack/react-query` is required by `RecordsAdminShell` (caching, pagination,
26
+ optimistic save). Wrap your app in a `<QueryClientProvider>` somewhere up the
27
+ tree.
28
+
19
29
  ## Setup
20
30
 
21
- Import the pre-compiled styles in your app's entry point:
31
+ Import the pre-compiled styles **once** in your app entry (e.g. `main.tsx`):
22
32
 
23
33
  ```tsx
24
- import '@proveanything/smartlinks-ui/styles.css';
25
- // — OR, if you import the main barrel, CSS is included automatically:
26
- import { AssetPicker } from '@proveanything/smartlinks-ui';
34
+ import '@proveanything/smartlinks-utils-ui/styles.css';
27
35
  ```
28
36
 
29
- This provides all the Tailwind utility classes used by the components. Your app still needs to define the CSS variables (e.g., `--primary`, `--border`) — these come from your own design system (shadcn, custom theme, etc.).
37
+ Components inherit your shadcn-compatible CSS variables (`--primary`,
38
+ `--background`, `--border`, …) and pick up your theme automatically.
30
39
 
31
- **Note:** If you use sub-path imports (e.g., `@proveanything/smartlinks-ui/asset-picker`), you must also import the styles separately since sub-path entry points don't include the CSS.
40
+ ## Modules
32
41
 
33
- ## Components
42
+ | Subpath | Module | Use when |
43
+ |---------|--------|----------|
44
+ | `/records-admin` | **RecordsAdminShell** + hooks (`useResolvedRecord`, `useRecordEditor`, …) | Building any per-product / per-variant / per-batch / per-facet admin |
45
+ | `/asset-picker` | AssetPicker | Pick / upload / paste / URL-import media assets |
46
+ | `/icon-picker` | IconPicker | Searchable Font Awesome 7 Pro picker |
47
+ | `/font-picker` | FontPicker | Google Fonts + custom uploaded fonts |
48
+ | `/conditions-editor` | ConditionsEditor | Recursive AND/OR rule builder (12 condition types) |
34
49
 
35
- ### Asset Picker
50
+ ### Records Admin Shell
51
+
52
+ ```tsx
53
+ import {
54
+ RecordsAdminShell,
55
+ type EditorContext,
56
+ } from '@proveanything/smartlinks-utils-ui/records-admin';
57
+ import * as SL from '@proveanything/smartlinks';
58
+
59
+ <RecordsAdminShell<NutritionData>
60
+ SL={SL}
61
+ collectionId={collectionId}
62
+ appId={appId}
63
+ recordType="nutrition"
64
+ label="Nutrition info"
65
+ scopes={['facet', 'product', 'variant', 'batch']}
66
+ contextScope={{ productId, variantId, batchId }} // optional, from iframe URL
67
+ defaultData={() => ({})}
68
+ renderEditor={(ctx) => <NutritionForm ctx={ctx} />}
69
+ renderPreview={({ resolved }) => <pre>{JSON.stringify(resolved, null, 2)}</pre>}
70
+ />
71
+ ```
36
72
 
37
- Browse, upload, and select media assets scoped to a collection, product, or proof.
73
+ The shell renders the browser pane (scope tabs, search, status pills), the
74
+ editor pane (sticky save / discard / delete footer with optimistic save), and
75
+ the inheritance markers — you only provide the form for one record.
76
+
77
+ On the **public widget** side, read the resolved value with `useResolvedRecord`:
38
78
 
39
79
  ```tsx
40
- import { AssetPicker } from '@proveanything/smartlinks-ui/asset-picker';
80
+ import { useResolvedRecord } from '@proveanything/smartlinks-utils-ui/records-admin';
81
+
82
+ const { data, source, isLoading } = useResolvedRecord({
83
+ SL, appId, recordType: 'nutrition',
84
+ collectionId, productId, variantId, batchId,
85
+ });
86
+ // source: 'proof' | 'batch' | 'variant' | 'product' | 'facet' | 'universal' | null
87
+ ```
88
+
89
+ ### Asset Picker
90
+
91
+ ```tsx
92
+ import { AssetPicker } from '@proveanything/smartlinks-utils-ui/asset-picker';
41
93
 
42
94
  <AssetPicker
43
95
  scope={{ type: 'collection', collectionId: 'abc123' }}
44
96
  mode="dialog"
45
97
  allowUpload
46
- onSelect={(asset) => console.log('Selected:', asset)}
47
- trigger={<button>Choose Image</button>}
98
+ accept={['image/*']}
99
+ onSelect={(asset) => setHeroUrl(asset.url)}
100
+ trigger={<button>Choose image</button>}
48
101
  />
49
102
  ```
50
103
 
51
104
  ### Conditions Editor
52
105
 
53
- Visual editor for building condition rules with AND/OR logic groups.
54
-
55
106
  ```tsx
56
- import { ConditionsEditor } from '@proveanything/smartlinks-ui/conditions-editor';
107
+ import { ConditionsEditor } from '@proveanything/smartlinks-utils-ui/conditions-editor';
57
108
 
58
109
  <ConditionsEditor
59
- value={conditionGroup}
60
- onChange={setConditionGroup}
61
- // Optional: auto-loads facet definitions from SL.facets.publicList(collectionId)
62
- collectionId={collectionId}
63
- // …or pass them explicitly:
64
- // facets={[{ key: 'colour', name: 'Colour', cardinality: 'multi',
65
- // values: [{ key: 'red', name: 'Red' }] }]}
110
+ value={rules}
111
+ onChange={setRules}
112
+ collectionId={collectionId} // auto-loads facet definitions
66
113
  versions={[{ title: 'Default', value: '' }]}
67
114
  tags={['featured', 'new']}
68
115
  />
69
116
  ```
70
117
 
71
- Supported condition types include **facet** (match against product facet
72
- definitions), version, country, value, user, date, device, label, geofence,
73
- product id, item status and condition reference.
74
-
75
118
  ### Icon Picker
76
119
 
77
- Searchable Font Awesome icon picker with lazy-loaded icon index for tree shaking.
78
-
79
120
  ```tsx
80
- import { IconPicker } from '@proveanything/smartlinks-ui/icon-picker';
121
+ import { IconPicker } from '@proveanything/smartlinks-utils-ui/icon-picker';
81
122
 
82
123
  <IconPicker
83
124
  mode="dialog"
84
125
  value="fa-solid fa-heart"
85
- onSelect={(icon) => console.log(icon.name)}
86
- trigger={<button>Pick Icon</button>}
126
+ onSelect={(icon) => setIcon(icon.name)}
127
+ trigger={<button>Pick icon</button>}
87
128
  />
88
129
  ```
89
130
 
90
- ### Font Picker
131
+ Requires the Font Awesome 7 Pro kit script on the host page.
91
132
 
92
- Searchable font picker with Google Fonts catalog and support for custom uploaded fonts. Returns full loading metadata (CSS URLs, `@font-face` blocks, `cssFontFamily` strings) so the consumer knows exactly how to load the selected font.
133
+ ### Font Picker
93
134
 
94
135
  ```tsx
95
- import { FontPicker } from '@proveanything/smartlinks-ui/font-picker';
136
+ import { FontPicker } from '@proveanything/smartlinks-utils-ui/font-picker';
96
137
 
97
138
  <FontPicker
98
139
  mode="dialog"
99
140
  value="Inter"
100
141
  showPreview
101
142
  onSelect={(font) => {
102
- console.log(font.family); // "Inter"
103
- console.log(font.cssFontFamily); // "'Inter', ui-sans-serif, system-ui, sans-serif"
104
- console.log(font.loadSnippet); // <link href="..." rel="stylesheet">
143
+ console.log(font.cssFontFamily); // ready for `font-family:` CSS
144
+ console.log(font.loadSnippet); // <link> or @font-face block to inject
105
145
  }}
106
- trigger={<button>Pick Font</button>}
107
- />
108
-
109
- {/* With custom uploaded fonts from SmartLinks */}
110
- <FontPicker
111
- mode="dialog"
112
- showCustomFonts
113
- scope={{ collectionId: 'abc123' }}
114
- admin
115
- onSelect={(font) => console.log(font)}
116
146
  />
117
147
  ```
118
148
 
119
149
  ## Prerequisites
120
150
 
121
- All components assume `@proveanything/smartlinks` is already initialized in your app via `SL.initializeApi()`. Components that interact with the SmartLinks API (Asset Picker) will use the global SDK import directly.
151
+ All components assume `@proveanything/smartlinks` is initialised in your app
152
+ via `SL.initializeApi()`. Admin components (RecordsAdminShell, AssetPicker
153
+ upload, etc.) call the SDK with `admin: true` — do not render them in
154
+ public-facing views.
122
155
 
123
- ## Tree Shaking
156
+ ## Tree shaking
124
157
 
125
- Each component is a separate entry point. If you only import `AssetPicker`, the Icon Picker's Font Awesome index won't be bundled.
158
+ Each component has its own subpath export bundle only what you use:
126
159
 
127
160
  ```tsx
128
- // Only loads AssetPicker code
129
- import { AssetPicker } from '@proveanything/smartlinks-ui/asset-picker';
161
+ // Bundles only RecordsAdmin
162
+ import { RecordsAdminShell } from '@proveanything/smartlinks-utils-ui/records-admin';
130
163
 
131
- // Also works barrel import, bundler tree-shakes unused
132
- import { AssetPicker } from '@proveanything/smartlinks-ui';
164
+ // Barrel import — bundler tree-shakes the rest
165
+ import { RecordsAdminShell } from '@proveanything/smartlinks-utils-ui';
133
166
  ```
134
167
 
168
+ If you use subpath imports, import `styles.css` separately — subpaths do not
169
+ pull it in automatically.
170
+
135
171
  ## Development
136
172
 
137
173
  ```bash
138
174
  cd packages/smartlinks-ui
139
175
  npm install
140
- npm run build # Build with tsup
141
- npm run dev # Watch mode
176
+ npm run build # tsup
177
+ npm run dev # watch mode
142
178
  ```
143
179
 
144
180
  ## License
145
181
 
146
- MIT
182
+ MIT